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

@gnwebsoft/ui

v4.0.42

Published

A set of reusable wrappers for MUI v7

Downloads

2,430

Readme

@gnwebsoft/ui

A comprehensive TypeScript library providing reusable React components and wrappers for MUI v7. Built for modern React applications with full TypeScript support, form integration, and accessibility features.

npm version TypeScript MIT License

Features

  • 🎨 MUI v7 Integration - Built on top of Material-UI components
  • 📝 Form Controls - Comprehensive react-hook-form wrappers
  • 🔍 TypeScript First - Full type safety and IntelliSense support
  • 🌳 Tree Shakeable - Modular exports for optimal bundle size
  • Accessible - WCAG compliant components
  • 🎯 Modern React - Hooks, memo, forwardRef patterns
  • 📱 Responsive - Mobile-first design approach

Installation

npm install @gnwebsoft/ui
# or
yarn add @gnwebsoft/ui
# or
pnpm add @gnwebsoft/ui

Peer Dependencies

This library requires the following peer dependencies:

npm install react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled react-hook-form @hookform/resolvers zod
{
  "@emotion/cache": "^11.14.0",
  "@emotion/react": "^11.14.0",
  "@emotion/styled": "^11.14.0",
  "@hookform/resolvers": "^5.2.1",
  "@mui/icons-material": "^7.3.1",
  "@mui/lab": "^7.0.0-beta.16",
  "@mui/material": "^7.3.1",
  "@mui/x-data-grid": "^8.9.2",
  "@mui/x-date-pickers": "^8.9.2",
  "autosuggest-highlight": "^3.3.4",
  "axios": "^1.11.0",
  "dayjs": "^1.11.13",
  "es-toolkit": "^1.39.8",
  "lodash": "^4.17.21",
  "react": "^19.1.1",
  "react-dom": "^19.1.1",
  "react-hook-form": "^7.62.0",
  "typescript": "^5.9.2",
  "zod": "^4.0.15",
  "zustand": "^5.0.2"
}

Quick Start

import React from 'react';
import { SimpleButton, LabelText } from '@gnwebsoft/ui';
import { ThemeProvider, createTheme } from '@mui/material/styles';

const theme = createTheme();

function App() {
  return (
    <ThemeProvider theme={theme}>
      <div>
        <LabelText>Welcome to @gnwebsoft/ui</LabelText>
        <SimpleButton
          variant="contained"
          color="primary"
          onClick={() => alert('Hello World!')}
        >
          Click Me
        </SimpleButton>
      </div>
    </ThemeProvider>
  );
}

export default App;

Module Imports

For optimal bundle size, import from specific modules:

// 🎯 Preferred - Tree-shakeable imports
import { SimpleButton } from '@gnwebsoft/ui/components';
import { TextFieldElement } from '@gnwebsoft/ui/wrappers';
import { useTransform } from '@gnwebsoft/ui/hooks';
import type { ApiResponse } from '@gnwebsoft/ui/types';
import { handleServerErrors } from '@gnwebsoft/ui/utils';

// 📦 Alternative - Root import (larger bundle)
import { SimpleButton, TextFieldElement } from '@gnwebsoft/ui';

Available Modules

| Module | Description | Import Path | | -------------- | ---------------------- | -------------------------- | | Components | UI components | @gnwebsoft/ui/components | | Wrappers | Form element wrappers | @gnwebsoft/ui/wrappers | | Hooks | Custom React hooks | @gnwebsoft/ui/hooks | | Types | TypeScript definitions | @gnwebsoft/ui/types | | Utils | Utility functions | @gnwebsoft/ui/utils |

Components

Basic Components

SimpleButton

Enhanced MUI Button with loading states and conditional rendering.

import { SimpleButton } from '@gnwebsoft/ui/components';

<SimpleButton
  loading={isSubmitting}
  loadingText="Saving..."
  show={hasPermission}
  variant="contained"
  onClick={handleSubmit}
>
  Save Changes
</SimpleButton>;

Features:

  • Loading state with spinner
  • Conditional rendering
  • Automatic disabling during loading
  • Custom loading text support
  • Full TypeScript support

LabelText

Responsive label-value display component with grid layout and hover effects.

import { LabelText } from '@gnwebsoft/ui/components';

<LabelText
  label="Full Name"
  value="John Doe"
  gridSize={{
    labelSize: { xs: 12, sm: 4, md: 3 },
    valueSize: { xs: 12, sm: 8, md: 9 },
  }}
/>;

Features:

  • Responsive grid layout
  • Hover effects with background color change
  • Text overflow handling with ellipsis
  • Tooltip on hover showing full value
  • Customizable spacing and styling

AuthorizedView

Simple conditional rendering component based on a boolean show prop.

import { AuthorizedView } from '@gnwebsoft/ui/components';

<AuthorizedView show={user.hasAdminRole}>
  <AdminPanel />
</AuthorizedView>;

Features:

  • Minimal overhead conditional rendering
  • Returns empty fragment when hidden
  • TypeScript support

ClearButton, CancelButton, FilterButton

Standardized button components for common form actions.

import { ClearButton, CancelButton, FilterButton } from '@gnwebsoft/ui/components';

<ClearButton
  isSubmitting={isLoading}
  handleClear={() => reset()}
  storeKey="userFormData" // Optional localStorage cleanup
/>

<CancelButton
  isSubmitting={isLoading}
  handleCancel={() => navigate('/dashboard')}
/>

<FilterButton
  isSubmitting={isFiltering}
  show={hasFilters}
  title="Apply Filters"
  icon={<SearchIcon />}
/>

Layout Components

FormWrapper

Card-based container for forms with header, title, and action buttons.

import { FormWrapper } from '@gnwebsoft/ui/components';

<FormWrapper
  title="User Profile"
  icon={<PersonIcon />}
  actionButton={
    <SimpleButton variant="outlined" size="small">
      Reset
    </SimpleButton>
  }
>
  <TextFieldElement name="firstName" label="First Name" />
  <TextFieldElement name="lastName" label="Last Name" />
</FormWrapper>;

Features:

  • Card-based layout with header and content areas
  • Divider between header and content
  • Flexible action button placement
  • Grid container for content with spacing

FilterWrapper, ListWrapper, SimpleToolbar

Specialized container components for different UI patterns.

import { FilterWrapper, ListWrapper, SimpleToolbar } from '@gnwebsoft/ui/components';

<FilterWrapper>
  <TextField label="Search" />
  <SelectElement name="category" options={categories} />
</FilterWrapper>

<ListWrapper>
  <LabelText label="Name" value={user.name} />
  <LabelText label="Email" value={user.email} />
</ListWrapper>

<SimpleToolbar>
  <SimpleButton variant="contained">Add New</SimpleButton>
  <SimpleButton variant="outlined">Export</SimpleButton>
</SimpleToolbar>

Form Wrappers

All form wrappers integrate seamlessly with react-hook-form:

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import {
  TextFieldElement,
  SelectElement,
  DatePickerElement,
  CheckboxElement,
} from '@gnwebsoft/ui/wrappers';

const schema = z.object({
  name: z.string().min(1, 'Name is required'),
  email: z.string().email('Invalid email'),
  category: z.string(),
  birthDate: z.date(),
  subscribe: z.boolean(),
});

type FormData = z.infer<typeof schema>;

function ContactForm() {
  const { control, handleSubmit } = useForm<FormData>({
    resolver: zodResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <TextFieldElement
        control={control}
        name="name"
        label="Full Name"
        required
      />

      <TextFieldElement
        control={control}
        name="email"
        label="Email"
        type="email"
        required
      />

      <SelectElement
        control={control}
        name="category"
        label="Category"
        options={[
          { value: 'general', label: 'General Inquiry' },
          { value: 'support', label: 'Support' },
        ]}
      />

      <DatePickerElement
        control={control}
        name="birthDate"
        label="Birth Date"
      />

      <CheckboxElement
        control={control}
        name="subscribe"
        label="Subscribe to newsletter"
      />

      <SimpleButton type="submit" variant="contained">
        Submit
      </SimpleButton>
    </form>
  );
}

Available Form Wrappers

| Component | Description | Use Case | Features | | ---------------------- | ------------------------------------- | --------------------------------- | ----------------------------------------------------- | | TextFieldElement | Text input wrapper | Single-line text, email, password | Value transformation, grid layout, auto-validation | | PasswordElement | Password input with visibility toggle | Secure password entry | Eye icon toggle, all TextFieldElement features | | SelectElement | Single selection dropdown | Categories, statuses | Auto-select single option, custom label/value keys | | SelectMultiElement | Multiple selection dropdown | Tags, permissions | Chip display, select all/none functionality | | SelectCascadeElement | Dependent dropdown selections | Country → State → City | Hierarchical options, parent-child relationships | | AsyncSelect | Async searchable dropdown | User search, API data | Debounced search, loading states, no options handling | | AsyncMultiSelect | Async multiple selection | Multiple user selection | Async loading with multi-select capabilities | | DatePickerElement | Date selection | Birth dates, deadlines | MUI date picker integration, keyboard input | | TimePickerElement | Time selection | Appointments, schedules | MUI time picker integration, 12/24 hour format | | CheckboxElement | Single checkbox | Agreements, preferences | Boolean value handling, label integration | | CheckboxGroup | Multiple checkboxes | Multiple selections | Array value handling, group validation | | RadioButtonGroup | Radio button group | Exclusive selections | Single selection from multiple options |

Hooks

useTransform

Transform values with memoization and change handling for form components.

import { useTransform } from '@gnwebsoft/ui/hooks';

const { value, onChange } = useTransform({
  value: formValue,
  onChange: field.onChange,
  transform: {
    input: value => value?.toString() || '',
    output: event => parseInt(event.target.value) || null,
  },
});

Features:

  • Memoized transformations for performance
  • Input/output transformation support
  • Change event handling
  • TypeScript type safety
  • Integration with form components

Common Use Cases:

  • Number input formatting
  • Date formatting
  • Currency formatting
  • Array to string conversion

Types

Comprehensive TypeScript interfaces for API integration and form handling:

import type {
  ApiResponse,
  OperationResponse,
  ValidationErrors,
  OptionItem,
  PostModel,
  ListResponse,
} from '@gnwebsoft/ui/types';

// API response structure
const response: ApiResponse<User[]> = {
  status: 200,
  data: users,
  traceId: 'abc123',
};

// Form options
const options: OptionItem[] = [
  { Label: 'Option 1', Value: '1' },
  { Label: 'Option 2', Value: '2' },
];

// Paginated list response
const listResponse: ListResponse<User> = {
  Data: [
    /* users */
  ],
  Total: 150,
};

// Filter/search request
const filterRequest: PostModel<UserFilter> = {
  filterModel: { name: 'John' },
  pageOffset: 0,
  pageSize: 20,
  sortField: 'name',
  sortOrder: 'asc',
};

Available Types:

  • ApiResponse<T> - Standard API response structure
  • ValidationErrors - Form validation errors
  • OptionItem / OptionItem2 - Select options
  • PostModel<T> - Filter/pagination requests
  • ListResponse<T> - Paginated responses
  • AsyncSelectPayload - Async select data

Utilities

API Utilities

import { api, handleServerErrors } from '@gnwebsoft/ui/utils';

// API calls with automatic authentication
const users = await api.get<User[]>('/users');
const newUser = await api.post<User>('/users', userData);
const filteredUsers = await api.filter<User, UserFilter>(
  '/users/search',
  filterModel
);

// File upload
const uploadResult = await api.upload<UploadResponse>('/upload', formData);

// Form error handling
try {
  await api.post('/submit', formData);
} catch (error) {
  handleServerErrors({
    errors: error.response.data.errors,
    setError,
  });
}

Data Transformation

import {
  flattenObjectKeys,
  readValueAsDate,
  propertyExists,
  removeLeadingTrailingSlashes,
  getTimezone,
} from '@gnwebsoft/ui/utils';

// Flatten nested objects
const flatData = flattenObjectKeys({ user: { name: 'John', age: 30 } });
// Result: { 'user.name': 'John', 'user.age': 30, 'user': {...} }

// Date conversion
const date = readValueAsDate('2023-12-25');
// Result: Date object or null

// Property checking
if (propertyExists(obj, 'user.address.street')) {
  console.log(obj.user.address.street);
}

// URL cleaning
const cleanPath = removeLeadingTrailingSlashes('/api/users/');
// Result: 'api/users'

// Timezone info
const timezone = getTimezone();
// Result: 'America/New_York' or current timezone

Available Utilities:

  • api / api2 - HTTP clients with authentication
  • handleServerErrors - Form error mapping
  • flattenObjectKeys - Nested object flattening
  • readValueAsDate - Safe date conversion
  • propertyExists - Type-safe property checking
  • removeLeadingTrailingSlashes - URL path cleaning
  • getTimezone - Timezone information
  • schemaTools - Zod schema utilities

Styling and Theming

Components inherit MUI theme configuration:

import { createTheme, ThemeProvider } from '@mui/material/styles';

const theme = createTheme({
  palette: {
    primary: {
      main: '#1976d2',
    },
    secondary: {
      main: '#dc004e',
    },
  },
  typography: {
    fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
  },
});

function App() {
  return (
    <ThemeProvider theme={theme}>{/* Your app components */}</ThemeProvider>
  );
}

Advanced Usage

Async Select with Search

import { AsyncSelect } from '@gnwebsoft/ui/wrappers';

<AsyncSelect
  control={control}
  name="assignee"
  label="Assign to User"
  loadOptions={async searchValue => {
    const response = await api.get(`/users/search?q=${searchValue}`);
    return response.data.map(user => ({
      value: user.id,
      label: `${user.name} (${user.email})`,
    }));
  }}
  placeholder="Search users..."
  noOptionsText="No users found"
/>;

Cascade Selects

import { SelectCascadeElement } from '@gnwebsoft/ui/wrappers';

<SelectCascadeElement
  control={control}
  name="location"
  label="Location"
  options={[
    {
      value: 'us',
      label: 'United States',
      children: [
        { value: 'ny', label: 'New York' },
        { value: 'ca', label: 'California' },
      ],
    },
  ]}
/>;

Testing

Components are built with testing in mind:

import { render, screen } from '@testing-library/react';
import { SimpleButton } from '@gnwebsoft/ui/components';

test('renders button with loading state', () => {
  render(
    <SimpleButton loading loadingText="Loading...">
      Submit
    </SimpleButton>
  );

  expect(screen.getByText('Loading...')).toBeInTheDocument();
  expect(screen.getByRole('button')).toBeDisabled();
});

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Documentation

Comprehensive documentation is available for all components and utilities:

📚 Complete Documentation

🎯 Quick References

📖 Examples

Each component includes:

  • ✅ Basic usage examples
  • ✅ Advanced configuration options
  • ✅ TypeScript integration examples
  • ✅ Testing patterns
  • ✅ Accessibility guidelines
  • ✅ Performance considerations

Development

# Install dependencies
pnpm install

# Start development mode with hot reload
pnpm dev

# Run tests
pnpm test

# Build library
pnpm build

# Generate TypeScript documentation
pnpm docs:generate

# Validate package exports
pnpm run check-exports

Development Workflow

The package supports instant development with hot module reloading:

# Start both UI package and sample app
pnpm dev

# Or start individually
pnpm run dev:ui    # UI package in watch mode
pnpm run dev:web   # Sample web app

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

License

MIT © GNWebsoft Private Limited

Changelog

See CHANGELOG.md for release history.


Made with ❤️ by GNWebsoft Team