npm package: @gnwebsoft/ui
Description: A set of reusable wrappers for MUI v7
Author: GNWebsoft Private Limited
Latest version: 4.2.0

# @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](https://badge.fury.io/js/%40gnwebsoft%2Fui.svg)](https://badge.fury.io/js/%40gnwebsoft%2Fui)
[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)

## 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

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

### Peer Dependencies

This library requires the following peer dependencies:

```bash
npm install react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled react-hook-form @hookform/resolvers zod
```

<details>
<summary>Complete peer dependency list</summary>

```json
{
  "@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"
}
```

</details>

## Quick Start

```tsx
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:

```tsx
// 🎯 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.

```tsx
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.

```tsx
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.

```tsx
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.

```tsx
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.

```tsx
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.

```tsx
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:

```tsx
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.

```tsx
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:

```tsx
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

```tsx
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

```tsx
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:

```tsx
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

```tsx
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

```tsx
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:

```tsx
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

- **[Component Documentation](./docs/COMPONENT_DOCUMENTATION.md)** - Detailed guide for all components
- **[Components](./docs/components/README.md)** - UI Components documentation
- **[Form Wrappers](./docs/wrappers/README.md)** - Form wrapper components documentation
- **[Hooks](./docs/hooks/README.md)** - Custom React hooks documentation
- **[Utilities](./docs/utils/README.md)** - Utility functions documentation
- **[Types](./docs/types/README.md)** - TypeScript types documentation

### 🎯 Quick References

- **[Getting Started Guide](./docs/guides/getting-started.md)** - Setup and basic usage
- **[Forms Guide](./docs/guides/forms.md)** - Form handling patterns
- **[API Documentation](./docs/api/README.md)** - Generated API docs

### 📖 Examples

Each component includes:

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

## Development

```bash
# 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:

```bash
# 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](./CHANGELOG.md) for release history.

---

**Made with ❤️ by GNWebsoft Team**