npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gxui/components

v1.0.2

Published

Enterprise theme engine + UI components (MUI-based)

Downloads

242

Readme

@gx-ui/components

Enterprise-grade React UI library built on Material UI 7, Framer Motion, and a multi-theme engine. Drop it into any React 18+ / 19+ app to get a complete design system — themes, feedback components, user management forms, motion presets, and more — out of the box.


Table of Contents


Installation

# npm
npm install @gx-ui/components

# yarn
yarn add @gx-ui/components

# pnpm
pnpm add @gx-ui/components

Install peer dependencies (skip any you already have):

npm install @mui/material @mui/icons-material @emotion/react @emotion/styled framer-motion react react-dom

Note: framer-motion is optional. The library works without it, but GlassOverlay and motion-enhanced components require it.


Quick Start

Wrap your app root with GxThemeProvider. Everything else is then importable on demand.

// main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { GxThemeProvider } from '@gx-ui/components';
import App from './App';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <GxThemeProvider defaultTheme="glassmorphism" defaultMode="system">
      <App />
    </GxThemeProvider>
  </StrictMode>,
);

Theme System

GxThemeProvider

The root provider. Must wrap your entire app. Handles MUI theme injection, light/dark mode, and optional cloud sync.

import { GxThemeProvider } from '@gx-ui/components';

<GxThemeProvider
  defaultTheme="enterprise"   // Which theme to start with (default: 'default')
  defaultMode="system"        // 'light' | 'dark' | 'system' (default: 'system')
  syncUrl="https://api.example.com" // Optional: base URL for cloud theme sync
>
  <App />
</GxThemeProvider>

| Prop | Type | Default | Description | |---|---|---|---| | defaultTheme | GxThemeId | 'default' | Initial theme | | defaultMode | GxThemeMode | 'system' | Initial color mode | | syncUrl | string | 'https://api.gksvp.com' | Cloud sync base URL |

Available Themes

| ID | Style | Best For | |---|---|---| | default | Clean MUI blue, rounded surfaces | General-purpose apps | | glassmorphism | Frosted glass panels, backdrop blur | Dashboards, media apps | | liquid | Aurora radial gradients, fluid shapes | Creative tools, portfolios | | materialYou | MD3-inspired tonal surfaces | Consumer mobile-first apps | | minimalDark | Pure black, ultra-thin borders | Developer tools, IDEs | | enterprise | Conservative navy, B2B SaaS | Admin panels, internal tools | | natural | Forest greens, earthy tones | Wellness, sustainability apps | | product | Violet & amber, conversion-optimized | Landing pages, SaaS marketing | | skeuomorphism | Tactile neumorphic surfaces | Audio apps, knobs, sliders | | claymorphism | Puffy 3D clay-like surfaces | Consumer apps, games | | liquidGlass | Apple's spatial design language | Premium, spatial UIs |

Switching Themes at Runtime

Use the useGxTheme hook from anywhere inside GxThemeProvider.

import { useGxTheme } from '@gx-ui/components';

function ThemePicker() {
  const { currentTheme, mode, setTheme, setMode } = useGxTheme();

  return (
    <>
      <button onClick={() => setTheme('liquid')}>Liquid</button>
      <button onClick={() => setTheme('enterprise')}>Enterprise</button>
      <button onClick={() => setMode(mode === 'dark' ? 'light' : 'dark')}>
        Toggle {mode === 'dark' ? 'Light' : 'Dark'}
      </button>
    </>
  );
}

ThemeStudio

A full-featured, self-contained theme management page. Drop it on a route — no additional props required.

import { lazy, Suspense } from 'react';
import { PageSkeleton } from '@gx-ui/components';

// Lazy-load — it's a heavy editor, only load when the route is visited.
const ThemeStudio = lazy(() =>
  import('@gx-ui/components').then(m => ({ default: m.ThemeStudio }))
);

// In your router:
<Route path="/themes" element={
  <Suspense fallback={<PageSkeleton layout="dashboard" />}>
    <ThemeStudio />
  </Suspense>
} />

Features: theme grid/list view, search & sort, live light/dark preview, custom theme creation with color editor, WCAG contrast audit, and cloud sync.


Feedback & Loading

NavProgress

A fixed top-of-page progress bar (like YouTube/GitHub). Requires NavProgressProvider near your app root.

Step 1 — Add the provider and bar once (App or Layout root):

// App.tsx
import { NavProgressProvider, NavProgress } from '@gx-ui/components';

export default function App() {
  return (
    <NavProgressProvider>
      <NavProgress />          {/* renders the fixed bar — put this once */}
      <BrowserRouter>
        <AppRoutes />
      </BrowserRouter>
    </NavProgressProvider>
  );
}

Step 2 — Call start() / stop() around async operations anywhere in your app:

import { useNavProgress } from '@gx-ui/components';

function SaveButton() {
  const { start, stop } = useNavProgress();

  const handleSave = async () => {
    start();
    try {
      await api.saveData();
    } finally {
      stop();
    }
  };

  return <button onClick={handleSave}>Save</button>;
}

NavProgress props:

| Prop | Type | Default | Description | |---|---|---|---| | color | 'primary' \| 'secondary' \| 'inherit' | 'primary' | Bar color | | height | number | 3 | Height in px | | zIndex | number | 9999 | z-index override |

Behavior: start() sets progress to 8% and logarithmically increments toward 90%. stop() jumps to 100% then fades out after 450 ms.


LoadingButton

A MUI Button wrapper that shows a CircularProgress spinner while loading. Maintains button width so the layout never shifts.

import { LoadingButton } from '@gx-ui/components';

function SubmitForm() {
  const [saving, setSaving] = useState(false);

  return (
    // Spinner at the end (default)
    <LoadingButton
      loading={saving}
      variant="contained"
      onClick={handleSubmit}
    >
      Save Changes
    </LoadingButton>
  );
}

Spinner positions:

// Spinner replaces the startIcon
<LoadingButton loading={saving} loadingPosition="start" startIcon={<SaveIcon />}>
  Save
</LoadingButton>

// Spinner overlays the label — button width is preserved exactly
<LoadingButton loading={saving} loadingPosition="center" loadingText="Saving…">
  Save Changes
</LoadingButton>

// Spinner at the end (default)
<LoadingButton loading={saving} loadingPosition="end">
  Submit
</LoadingButton>

| Prop | Type | Default | Description | |---|---|---|---| | loading | boolean | false | Shows spinner and disables the button | | loadingPosition | 'start' \| 'end' \| 'center' | 'end' | Where the spinner appears | | loadingText | React.ReactNode | — | Label shown while loading (center mode) | | spinnerSize | number | 16 | Spinner diameter in px | | disabled | boolean | — | Disable independently of loading |

Accepts all standard MUI ButtonProps.


GlassOverlay

A blocking overlay with a frosted-glass card and spinner. Two variants: fullscreen (portal to document.body) and scoped (covers the nearest position: relative ancestor).

import { GlassOverlay } from '@gx-ui/components';

// Full-page — use for critical blocking operations (delete account, payment processing)
function DeleteAccountButton() {
  const [deleting, setDeleting] = useState(false);

  return (
    <>
      <GlassOverlay open={deleting} message="Deleting account…" />
      <button onClick={() => { setDeleting(true); deleteAccount(); }}>
        Delete Account
      </button>
    </>
  );
}

// Scoped — covers only a card while it saves
function ProfileCard() {
  const [saving, setSaving] = useState(false);

  return (
    <Box sx={{ position: 'relative' }}>
      <GlassOverlay open={saving} variant="scoped" message="Saving…" />
      <CardContent>…form fields…</CardContent>
    </Box>
  );
}

| Prop | Type | Default | Description | |---|---|---|---| | open | boolean | — | Required. Shows/hides the overlay | | message | string | — | Label shown below the spinner | | variant | 'fullscreen' \| 'scoped' | 'fullscreen' | Fullscreen uses a portal; scoped is inline | | blur | number | 12 | Backdrop blur in px | | spinnerSize | number | 40 | Spinner diameter in px | | zIndex | number | 1400 | z-index (default is above MUI Dialog) |

Accessibility: Renders with role="dialog", aria-modal, aria-busy, and aria-label automatically.


PageSkeleton

Full-page shimmer skeleton that mimics your page layout while data loads. Use as a Suspense fallback or an early if (loading) return guard.

import { PageSkeleton } from '@gx-ui/components';

// As a Suspense fallback (route-level lazy loading)
<Suspense fallback={<PageSkeleton layout="dashboard" />}>
  <DashboardPage />
</Suspense>

// As an early return guard
function ProfilePage() {
  const { loading } = useProfile();
  if (loading) return <PageSkeleton layout="profile" />;
  return <ActualProfilePage />;
}

// Table with custom row count
<PageSkeleton layout="table" rows={12} />

// Form with custom field count
<PageSkeleton layout="form" fields={8} />

| Prop | Type | Default | Description | |---|---|---|---| | layout | 'dashboard' \| 'profile' \| 'table' \| 'form' | 'dashboard' | Which page pattern to mimic | | rows | number | 8 | Row count for table layout | | fields | number | 6 | Field count for form layout |

Layout previews:

  • dashboard — top nav + 4 stat cards + chart area + list panel
  • profile — top nav + avatar header + 3 form sections
  • table — toolbar + filter chips + header row + data rows
  • form — page title + grouped input fields + action buttons

UI Components

GlassCard

A frosted-glass card with optional hover lift, glow, and shine effects. Adapts to the active theme automatically.

import { GlassCard } from '@gx-ui/components';

<GlassCard hover glow>
  <Typography variant="h6">Card Title</Typography>
  <Typography>Card content goes here.</Typography>
</GlassCard>

// Disable hover animation
<GlassCard hover={false}>
  <StaticContent />
</GlassCard>

| Prop | Type | Default | Description | |---|---|---|---| | hover | boolean | true | Lift + scale on hover | | glow | boolean | false | Ambient glow around card | | blur | number | 20 | Backdrop blur strength in px | | shine | boolean | false | Diagonal shine sweep on hover |

Accepts all MUI BoxProps.


GlassTextField

A MUI TextField with glass morphism styling and optional focus animation.

import { GlassTextField } from '@gx-ui/components';

<GlassTextField label="Email" type="email" fullWidth />

<GlassTextField
  label="Password"
  type="password"
  glassVariant="gradient"
  fullWidth
/>

<GlassTextField
  label="Notes"
  multiline
  rows={4}
  glassVariant="inset"
  disableMotion
/>

| Prop | Type | Default | Description | |---|---|---|---| | glassVariant | 'default' \| 'gradient' \| 'inset' | 'default' | Glass style variant | | disableMotion | boolean | false | Disables Framer Motion focus animation |

Accepts all MUI TextFieldProps except variant (always outlined).


GradientButton

A MUI Button with a gradient background, configurable angle, and optional glow effect.

import { GradientButton } from '@gx-ui/components';

<GradientButton>Get Started</GradientButton>

<GradientButton glow angle={90} toSecondary>
  Learn More
</GradientButton>

| Prop | Type | Default | Description | |---|---|---|---| | angle | number | 135 | Gradient angle in degrees | | glow | boolean | true | Adds ambient glow shadow | | toSecondary | boolean | false | Gradient goes from primary → secondary |

Accepts all MUI ButtonProps except component.


LoadingCard & ShimmerBlock

LoadingCard renders a themed skeleton for a single card. ShimmerBlock is the low-level primitive for building custom skeletons.

import { LoadingCard, ShimmerBlock } from '@gx-ui/components';

// Pre-built card skeletons
<LoadingCard variant="product" />
<LoadingCard variant="list" rows={5} />
<LoadingCard variant="profile" />
<LoadingCard variant="stat" shimmer={false} />

// Build a custom skeleton from primitives
function MyCustomSkeleton() {
  return (
    <Box sx={{ p: 2 }}>
      <ShimmerBlock width="60%" height={24} radius={4} />
      <Box sx={{ mt: 1 }}>
        <ShimmerBlock width="100%" height={14} />
      </Box>
      <Box sx={{ mt: 0.5 }}>
        <ShimmerBlock width="80%" height={14} />
      </Box>
    </Box>
  );
}

LoadingCard props:

| Prop | Type | Default | Description | |---|---|---|---| | variant | 'product' \| 'list' \| 'profile' \| 'stat' | 'product' | Card shape to mimic | | rows | number | 3 | Row count for list variant | | shimmer | boolean | true | Enables the sweep shimmer animation | | glass | boolean | false | Glass-style card background |

ShimmerBlock props:

| Prop | Type | Default | Description | |---|---|---|---| | width | string \| number | '100%' | Width (px or CSS string like '60%') | | height | string \| number | 16 | Height in px | | radius | number | 4 | Border radius in px |


ProductCard

A ready-to-use e-commerce / catalog card with image, badge, tags, price, and an action button.

import { ProductCard } from '@gx-ui/components';

<ProductCard
  image="/products/widget.png"
  title="Premium Widget"
  subtitle="By Acme Corp"
  price="$49.99"
  badge="New"
  tags={['TypeScript', 'React']}
  actionLabel="View Details"
  onAction={() => navigate('/products/1')}
/>

// Loading state
<ProductCard title="" loading />

// Glass style
<ProductCard title="Card Title" glass onAction={handleClick} />

| Prop | Type | Default | Description | |---|---|---|---| | title | string | — | Required | | image | string | — | Image URL | | subtitle | string | — | Secondary text below title | | price | string | — | Price string (formatted, e.g. '$49.99') | | badge | string | — | Badge label (top-right corner) | | tags | string[] | — | Chip tags below subtitle | | loading | boolean | false | Shows skeleton instead of content | | glass | boolean | false | Glass background variant | | onAction | () => void | — | Action button click handler | | actionLabel | string | 'View' | Action button label |


User Management

A complete set of forms and pages for managing a user's profile, contacts, addresses, KYC documents, social accounts, and preferences. Wire them to your own API.

UserManagementPage

All-in-one page with tabs for every user management section. The simplest integration path.

import { UserManagementPage } from '@gx-ui/components';

function ProfilePage() {
  const handleSave = async (data) => {
    // data contains: profile, phones, emails, addresses,
    //                documents, socialAccounts, uiPreferences,
    //                notificationPreferences, privacyPreferences
    await userApi.save(data);
  };

  return (
    <UserManagementPage
      initialProfile={{
        firstName: 'Jane',
        lastName:  'Doe',
        email:     '[email protected]',
      }}
      onSave={handleSave}
      isLoading={false}
    />
  );
}

| Prop | Type | Default | Description | |---|---|---|---| | initialProfile | Partial<UserProfile> | — | Pre-populate form fields | | onSave | (data) => Promise<void> | — | Called when user saves any section | | isLoading | boolean | false | Shows loading state | | onNavigate | (tab: string) => void | — | Notified when the user switches tabs |


UserProfileCard

A compact or full display card for a user's profile — avatar, name, status, role badge.

import { UserProfileCard } from '@gx-ui/components';

<UserProfileCard profile={userProfile} />

// Compact single-line variant
<UserProfileCard profile={userProfile} compact />

UserProfileForm

Controlled form for editing core profile fields.

import { UserProfileForm } from '@gx-ui/components';

const [profileData, setProfileData] = useState({ firstName: '', lastName: '', bio: '' });

<UserProfileForm
  value={profileData}
  onChange={(field, value) => setProfileData(p => ({ ...p, [field]: value }))}
  showAdminFields={isAdmin}
/>

AddressForm

Add, remove, and set-primary for a user's address list.

import { AddressForm } from '@gx-ui/components';

<AddressForm
  addresses={profile.addresses}
  onAdd={async (data) => { await api.addAddress(data); }}
  onRemove={async (id) => { await api.removeAddress(id); }}
  onSetPrimary={async (id) => { await api.setPrimaryAddress(id); }}
/>

ContactDetailForm

Manages a list of phone numbers and email addresses with country dial code selection and validation.

import { ContactDetailForm } from '@gx-ui/components';

<ContactDetailForm
  phoneEntries={phones}
  emailEntries={emails}
  onPhonesChange={setPhones}
  onEmailsChange={setEmails}
  showErrors
/>

KycDocumentForm

Upload and manage identity documents (passport, national ID, driving license, etc.) with verification status display.

import { KycDocumentForm } from '@gx-ui/components';

<KycDocumentForm
  documents={profile.kyc}
  onAdd={async (data) => { await api.addDocument(data); }}
  onRemove={async (id) => { await api.removeDocument(id); }}
  readOnly={!canEdit}
/>

SocialAccountsForm

Manage links to 20+ social platforms including LinkedIn, Twitter/X, GitHub, Instagram, YouTube, and regional platforms (WeChat, KakaoTalk, Zalo, VK, etc.).

import { SocialAccountsForm } from '@gx-ui/components';

<SocialAccountsForm
  accounts={profile.socialAccounts}
  onAdd={(data) => api.addSocial(data)}
  onUpdate={(id, data) => api.updateSocial(id, data)}
  onDelete={(id) => api.deleteSocial(id)}
/>

UserPreferencesPanel

Three preference sections in a single panel: UI preferences (theme, language, density), notification preferences (email, push, SMS toggles), and privacy preferences (profile visibility, data sharing).

import { UserPreferencesPanel } from '@gx-ui/components';

<UserPreferencesPanel
  ui={prefs.ui}
  notifications={prefs.notifications}
  privacy={prefs.privacy}
  onUiChange={(key, value) => updateUiPref(key, value)}
  onNotificationChange={(key, value) => updateNotifPref(key, value)}
  onPrivacyChange={(key, value) => updatePrivacyPref(key, value)}
/>

Motion Presets

Framer Motion animation presets for consistent motion across your app. Spread directly into motion component props.

import { motion } from 'framer-motion';
import { slideUp, staggerContainer, staggerItem, hoverLift, tapPress } from '@gx-ui/components';

// Entrance animation
<motion.div variants={slideUp} initial="hidden" animate="visible">
  <MyCard />
</motion.div>

// Stagger children
<motion.ul variants={staggerContainer} initial="hidden" animate="visible">
  {items.map(item => (
    <motion.li key={item.id} variants={staggerItem}>
      {item.label}
    </motion.li>
  ))}
</motion.ul>

// Interactive gestures
<motion.div whileHover={hoverLift} whileTap={tapPress}>
  <ClickableCard />
</motion.div>

Entrance variants (use with initial="hidden" animate="visible"):

| Export | Effect | |---|---| | fadeIn | Opacity fade | | slideUp | Fade + slide up 16 px | | slideDown | Fade + slide down 16 px | | slideIn | Fade + slide in from left 24 px | | scaleIn | Fade + scale from 0.92 |

Stagger (apply to container, staggerItem to children):

| Export | Effect | |---|---| | staggerContainer | Staggers children by 60 ms | | staggerItem | Fades + slides up 12 px |

Gestures (use with whileHover / whileTap):

| Export | Effect | |---|---| | hoverLift | Lifts up 6 px + scales 1.05× | | hoverScale | Scales 1.03× | | hoverGlow | Scales 1.02× | | tapPress | Scales down to 0.97× | | focusScale | Scales 1.02× |

Continuous (use with animate):

| Export | Effect | |---|---| | pulseAnimation | Breathing opacity pulse | | shimmerAnimation | Left-to-right sweep | | floatBob | Gentle up-down float | | spin | Continuous rotation |


Hooks

useNavProgress

Controls the NavProgress bar from anywhere in the tree.

import { useNavProgress } from '@gx-ui/components';

const { start, stop, isLoading, progress } = useNavProgress();

| Return | Type | Description | |---|---|---| | start | () => void | Begin progress animation | | stop | () => void | Complete and hide the bar | | isLoading | boolean | Whether the bar is currently active | | progress | number | Current progress value (0–100) |

Requires NavProgressProvider to be an ancestor in the tree.


useCountry

Look up country data by ISO code, or search the full country list.

import { useCountry, useCountrySearch } from '@gx-ui/components';

// Single lookup
const country = useCountry('IN');
// → { code: 'IN', name: 'India', dialCode: '+91' }

// Searchable list for autocomplete UI
const { query, setQuery, countries } = useCountrySearch();

usePhoneValidation

Parse and validate phone numbers using libphonenumber-js. Returns E.164, national, and international formats.

import { usePhoneInput, validatePhone } from '@gx-ui/components';

// Controlled input hook
function PhoneField() {
  const { rawValue, formatted, validation, handleChange, handleCountryChange } = usePhoneInput('IN');

  return (
    <>
      <select onChange={e => handleCountryChange(e.target.value)}>…</select>
      <input value={rawValue} onChange={e => handleChange(e.target.value)} />
      {!validation.isValid && <span>{validation.error}</span>}
      {validation.isValid && <span>E.164: {validation.e164}</span>}
    </>
  );
}

// One-shot validation
const result = validatePhone('+919876543210');
// → { isValid: true, e164: '+919876543210', national: '98765 43210', ... }

Constants

import { COUNTRIES, CURRENCY_MAP, TIMEZONE_MAP, getCountryByCode } from '@gx-ui/components';

// Countries (ISO 3166-1 alpha-2)
COUNTRIES.forEach(c => console.log(c.code, c.name, c.dialCode));
const india = getCountryByCode('IN'); // { code: 'IN', name: 'India', dialCode: '+91' }

// Currencies
const usd = CURRENCY_MAP['USD']; // { code, name, symbol, decimals }

// Timezones
const tz = TIMEZONE_MAP['Asia/Kolkata']; // { id, label, offset, region }

Types

All types are re-exported from the package root. Import them with import type for zero runtime cost.

import type {
  // User
  UserProfile, Gender, AccountStatus, AccountType,

  // Contact
  PhoneEntry, EmailEntry, PhoneContactType, EmailContactType,

  // Address
  Address, AddressFormData, AddressType,

  // KYC
  KycDocument, KycDocumentFormData, KycDocumentType, KycVerificationStatus,

  // Social
  SocialAccount, SocialAccountFormData, SocialPlatform,

  // Preferences
  UiPreferences, NotificationPreferences, PrivacyPreferences,

  // Theme
  GxThemeId, GxThemeMode, ThemeConfig, ThemePreset,
} from '@gx-ui/components';

Peer Dependencies

| Package | Required | Version | |---|---|---| | react | Yes | >=18 | | react-dom | Yes | >=18 | | @mui/material | Yes | >=6 | | @emotion/react | Yes | >=11 | | @emotion/styled | Yes | >=11 | | framer-motion | Optional | >=10 |

framer-motion is optional but required by GlassOverlay and any component that uses motion presets.


Bundle Info

The library ships as dual ESM + CJS with full TypeScript declarations.

dist/
├── index.js        # ESM — tree-shakeable
├── index.cjs       # CommonJS
├── index.d.ts      # TypeScript declarations (ESM)
└── index.d.cts     # TypeScript declarations (CJS)

Built with tsup targeting ES2022. All MUI, React, and Framer Motion imports are externalized — they are not bundled into the output, keeping the installed size minimal.

To rebuild after source changes:

# One-time build
npm run build

# Watch mode for development
npm run dev

# Type-check only (no emit)
npm run typecheck