# mui-design-system

Design system based on MUI (Material UI) with custom theme, form components, table, and utilities.

---

## Installation

```bash
npm install mui-design-system
```

### Peer dependencies

Install in your project if not already present:

- `react` & `react-dom` (^18.2.0)
- `@mui/material` (^7.3.9)
- `@emotion/react`, `@emotion/styled`
- `styled-components` (^6.1.8)
- `stylis-plugin-rtl` (for RTL)
- For form: `react-hook-form` (^7.51.2)
- For table: `@tanstack/react-table` (^8.17.3)

---

## Quick start

```tsx
import { ReactCacheProvider, themeOptions, Form, colors } from 'mui-design-system';
import { ThemeProvider, createTheme } from '@mui/material/styles';

const theme = createTheme(themeOptions('light', false)); // mode, isRtl

<ThemeProvider theme={theme}>
  <ReactCacheProvider isRtl={false}>
    <App />
  </ReactCacheProvider>
</ThemeProvider>

// Colors from subpath
import { colors } from 'mui-design-system/colors/index';
```

---

## Exports overview

| Category | Exports |
|----------|---------|
| Theme & providers | `themeOptions`, `ReactCacheProvider`, `NextCacheProvider` |
| Form | `Form`, `FormProvider`, and all UF* field components + `CheckboxList` |
| Table | `CustomTable`, `useTable` |
| OTP | `OTPInput` |
| Methods | `debounce`, `result`, `deepMerge` |
| Colors | `colors` (from `mui-design-system/colors/index`) |

---

## 1. Theme & providers

### `themeOptions(mode, isRtl)`

Builds MUI `ThemeOptions` (palette, typography, components, direction).

| Parameter | Type | Description |
|-----------|------|-------------|
| `mode` | `'light' \| 'dark'` | Palette mode |
| `isRtl` | `boolean` | RTL/LTR direction |

**Example:**

```tsx
import { createTheme } from '@mui/material/styles';
import { themeOptions } from 'mui-design-system';

const theme = createTheme(themeOptions('light', false));
```

---

### `ReactCacheProvider`

Emotion cache provider for React apps (non-Next). Use for correct RTL/LTR styling with the theme.

**Props:**

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | — | App content |
| `isRtl` | `boolean` | — | Use RTL cache (with stylis-plugin-rtl) |

**Example:**

```tsx
import { ReactCacheProvider } from 'mui-design-system';

<ReactCacheProvider isRtl={false}>
  <App />
</ReactCacheProvider>
```

---

### `NextCacheProvider`

Provider for Next.js (with `@mui/material-nextjs`). In the current version it mainly wraps `children`; use Next’s config for RTL if needed.

**Props:** `children`, `isRtl`

**Example:**

```tsx
import { NextCacheProvider } from 'mui-design-system';

<NextCacheProvider isRtl={false}>
  <App />
</NextCacheProvider>
```

---

## 2. Form

Form is built on **react-hook-form** and a **schema** array that describes each field.

### `Form`

Renders form fields from a `schema` and a react-hook-form instance.

**Props:**

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `schema` | `TFormSchema` | — | Array of field configs |
| `form` | `UseFormReturn<any>` | — | Return value of `useForm()` |
| `gridContainerProps` | `GridProps` | — | Grid container props |
| `gridItemProps` | `GridProps` | — | Props for each grid item |
| `itemProps` | `any` | — | Shared item props |
| `labelsProps` | `Partial<TypographyProps>` | — | Label typography/style |
| `hideRequiredStar` | `boolean` | `false` | Hide required asterisk |
| `inputLabelMode` | `'static' \| 'relative'` | `'static'` | Label placement |
| `inputVariants` | `'outlined' \| 'filled' \| 'standard'` | `'outlined'` | Text field variant |
| `withoutHelperText` | `boolean` | — | Hide helper text |
| `disabled` | `boolean` | — | Disable entire form |

**Schema item shape (summary):** `name`, `label`, `type`, `rules` (react-hook-form), `defaultValue`, `placeholder`, `options` (for select/radio/etc.), `props` / `itemProps` per type.

**Schema field types:** `'text'`, `'email'`, `'password'`, `'number'`, `'tel'`, `'text-area'`, `'select'`, `'multi-select'`, `'auto-complete'`, `'radio'`, `'checkbox'`, `'multi-checkbox'`, `'switch'`, `'date-picker'`, `'time'`, `'currency'`, `'uploader'`.

**Example:**

```tsx
import { useForm } from 'react-hook-form';
import { Form } from 'mui-design-system';

const schema = [
  { name: 'email', label: 'Email', type: 'email', rules: { required: true } },
  { name: 'age', label: 'Age', type: 'number' },
  {
    name: 'country',
    label: 'Country',
    type: 'select',
    options: [
      { value: 'us', label: 'United States' },
      { value: 'uk', label: 'United Kingdom' },
    ],
  },
];

const MyForm = () => {
  const form = useForm({ defaultValues: { email: '', age: 0, country: '' } });
  return (
    <form onSubmit={form.handleSubmit((data) => console.log(data))}>
      <Form schema={schema} form={form} />
      <button type="submit">Submit</button>
    </form>
  );
};
```

---

### `FormProvider`

Provides form theme and optional custom inputs. Wrap your form when you need default styling or custom field types.

**Props:** `children`, `theme?` (TFormTheme), `customInputs?`

**Example:**

```tsx
import { FormProvider, Form } from 'mui-design-system';

<FormProvider theme={{ text: { /* default TextField props */ } }}>
  <Form schema={schema} form={form} />
</FormProvider>
```

---

### Form field components (UF*)

These are used internally by `Form` but can also be used standalone with react-hook-form’s `register` / `control`. All are wrapped with an error boundary when exported.

#### `UFTextField`

Text input for `text`, `email`, `password`, `number`, `tel`.

**Example:**

```tsx
import { useForm } from 'react-hook-form';
import { UFTextField } from 'mui-design-system';

const MyField = () => {
  const form = useForm({ defaultValues: { username: '' } });
  return (
    <UFTextField
      form={form}
      name="username"
      label="Username"
      type="text"
      placeholder="Enter username"
    />
  );
};
```

---

#### `UFTextArea`

Multiline text field.

**Example:**

```tsx
import { Form, useForm } from 'mui-design-system';

const schema = [
  { name: 'bio', label: 'Bio', type: 'text-area', placeholder: 'Tell us about yourself' },
];
const form = useForm({ defaultValues: { bio: '' } });
<Form schema={schema} form={form} />;
```

---

#### `UFSelect`

Single select dropdown.

**Example:**

```tsx
const schema = [
  {
    name: 'city',
    label: 'City',
    type: 'select',
    options: [
      { value: 'ny', label: 'New York' },
      { value: 'la', label: 'Los Angeles' },
    ],
  },
];
<Form schema={schema} form={form} />;
```

---

#### `UFMultiSelect`

Multi-select dropdown.

**Example:**

```tsx
const schema = [
  {
    name: 'tags',
    label: 'Tags',
    type: 'multi-select',
    options: [
      { value: 'a', label: 'Tag A' },
      { value: 'b', label: 'Tag B' },
    ],
  },
];
<Form schema={schema} form={form} />;
```

---

#### `UFAutoComplete`

Autocomplete with search, options, and optional async loading.

**Example:**

```tsx
const schema = [
  {
    name: 'country',
    label: 'Country',
    type: 'auto-complete',
    options: countries,
    onSearch: (value) => fetchCountries(value),
    isLoading: loading,
  },
];
<Form schema={schema} form={form} />;
```

---

#### `UFCheckbox`

Single checkbox.

**Example:**

```tsx
const schema = [
  { name: 'agree', label: 'I agree to terms', type: 'checkbox' },
];
<Form schema={schema} form={form} />;
```

---

#### `UFMultiCheckbox` / `CheckboxList`

List of checkboxes; used for multi-checkbox fields.

**Example:**

```tsx
const schema = [
  {
    name: 'interests',
    label: 'Interests',
    type: 'multi-checkbox',
    options: [
      { value: 'sports', label: 'Sports' },
      { value: 'music', label: 'Music' },
    ],
  },
];
<Form schema={schema} form={form} />;
```

---

#### `UFRadio`

Radio group.

**Example:**

```tsx
const schema = [
  {
    name: 'gender',
    label: 'Gender',
    type: 'radio',
    options: [
      { value: 'm', label: 'Male' },
      { value: 'f', label: 'Female' },
    ],
  },
];
<Form schema={schema} form={form} />;
```

---

#### `UFSwitch`

Toggle switch.

**Example:**

```tsx
const schema = [
  { name: 'notifications', label: 'Enable notifications', type: 'switch' },
];
<Form schema={schema} form={form} />;
```

---

#### `UFDatePicker`

Date picker field.

**Example:**

```tsx
const schema = [
  { name: 'birthDate', label: 'Birth date', type: 'date-picker' },
];
<Form schema={schema} form={form} />;
```

---

#### `UFTime`

Time input (hours/minutes).

**Example:**

```tsx
const schema = [
  { name: 'appointmentTime', label: 'Time', type: 'time' },
];
<Form schema={schema} form={form} />;
```

---

#### `UFCurrency`

Numeric/currency input with formatting.

**Example:**

```tsx
const schema = [
  { name: 'price', label: 'Price', type: 'currency', placeholder: '0.00' },
];
<Form schema={schema} form={form} />;
```

---

#### `UFUploader`

File upload with optional multiple files and delete handler.

**Example:**

```tsx
const schema = [
  {
    name: 'attachments',
    label: 'Attachments',
    type: 'uploader',
    multiple: true,
    onDelete: (index) => removeFile(index),
  },
];
<Form schema={schema} form={form} />;
```

---

## 3. Table

### `useTable`

Hook that builds a **@tanstack/react-table** instance and returns `table`, `pagination`, and optional selection/expand helpers for `CustomTable`.

**Parameters (`IUseTableProps`):** `columns`, `data`, `pageSize?`, `multiSelect?`, `onSelectRow?`, `getRowId?`, `renderSubComponent?`, `getRowCanExpand?`, `state?`, and other react-table options.

**Returns:** `{ table, pagination, selectedRows, renderSubComponent }`.

**Example:**

```tsx
import { useTable, CustomTable } from 'mui-design-system';

const columns = [
  { accessorKey: 'name', header: 'Name' },
  { accessorKey: 'age', header: 'Age' },
];
const data = [
  { id: '1', name: 'Alice', age: 28 },
  { id: '2', name: 'Bob', age: 32 },
];

const MyTable = () => {
  const { table, pagination, renderSubComponent } = useTable({
    columns,
    data,
    pageSize: 10,
  });
  return (
    <CustomTable
      table={table}
      pagination={pagination}
      renderSubComponent={renderSubComponent}
    />
  );
};
```

---

### `CustomTable`

Table UI with header, body, loading skeleton, pagination, optional row selection (radio/checkbox) and expandable rows.

**Props (`ICustomTable`):** `id?`, `table`, `pagination?`, `variant?` (`'zebra' | 'linear'`), `isLoading?`, `wrapperStackProps?`, `footerProps?`, `onClickRow?`, `renderSubComponent?`, `withRadio?`, `withSelect?`, `withIndex?`, `rowStyle?`, `cellsStyle?`, `headerStyle?`, `headerTypoProps?`, `checkboxProps?`, `radioProps?`, `emptyListComponent?`, `rowBorderRadius?`, `borderRadius?`.

**Example:**

```tsx
import { useTable, CustomTable } from 'mui-design-system';

const columns = [
  { accessorKey: 'name', header: 'Name' },
  { accessorKey: 'email', header: 'Email' },
];
const data = [
  { id: '1', name: 'Alice', email: 'alice@example.com' },
  { id: '2', name: 'Bob', email: 'bob@example.com' },
];

const DataTable = () => {
  const { table, pagination } = useTable({ columns, data, pageSize: 5 });
  return (
    <CustomTable
      id="users-table"
      table={table}
      pagination={pagination}
      variant="zebra"
      emptyListComponent="No users found"
    />
  );
};
```

---

## 4. OTP Input

### `OTPInput`

Multi-digit OTP input (one box per digit).

**Props:** `valueLength`, `value?`, `onChange`, `size?`, `gap?`, `inputStyle?`, `activeInputStyle?`, `onFinish?`, `onBack?`, `containerProp?`, `readonly?`, `disabled?`, `isError?`.

**Example:**

```tsx
import { useState } from 'react';
import { OTPInput } from 'mui-design-system';

const VerifyCode = () => {
  const [otp, setOtp] = useState('');
  return (
    <OTPInput
      valueLength={6}
      value={otp}
      onChange={setOtp}
      onFinish={(val) => console.log('OTP completed:', val)}
      gap={2}
    />
  );
};
```

---

## 5. Methods

### `debounce(func, wait, immediate?)`

Debounces a function (e.g. for search input).

**Example:**

```tsx
import { debounce } from 'mui-design-system';

const handleSearch = debounce((query: string) => {
  fetchSuggestions(query);
}, 300);

// In JSX: <Input onChange={(e) => handleSearch(e.target.value)} />
```

---

### `result(object, key, defaultValue?)`

Reads a value from an object with optional default or lazy default (function).

**Example:**

```tsx
import { result } from 'mui-design-system';

const userName = result(user, 'name', 'Guest');
const value = result(config, 'key', () => computeExpensiveDefault());
```

---

### `deepMerge<T>(...objects)`

Deep-merges objects. Arrays and non-object values are overwritten.

**Example:**

```tsx
import { deepMerge } from 'mui-design-system';

const merged = deepMerge(
  { a: 1, b: { x: 1 } },
  { b: { y: 2 }, c: 3 }
);
// { a: 1, b: { x: 1, y: 2 }, c: 3 }
```

---

## 6. Colors

Color palettes are available from the colors subpath.

**Example:**

```tsx
import { colors } from 'mui-design-system/colors/index';

// Each color has keys 50–900
colors.blue[500];  // "#1e88e5"
colors.grey[700];  // "#535353"

// Available: yellow, blue, green, orange, red, purple, grey
```

**TypeScript types:** `TColors`, `ColorScale` (`"50" | "100" | ... | "900"`), `IColor`.

---

## Export tree (summary)

```
mui-design-system
├── themeOptions
├── ReactCacheProvider
├── NextCacheProvider
├── Form
├── FormProvider
├── UFTextField, UFTextArea, UFSelect, UFMultiSelect, UFAutoComplete
├── UFCheckbox, UFMultiCheckbox, CheckboxList
├── UFRadio, UFSwitch
├── UFDatePicker, UFTime, UFCurrency, UFUploader
├── CustomTable
├── useTable
├── OTPInput
├── debounce, result, deepMerge
└── (colors from mui-design-system/colors/index)
```

---

## Not exported from main entry

These exist in the library but are not re-exported from the main package. You can add them to `index.ts` if needed:

- **`useEffectOnce`** — Hook that runs an effect once (mount) with cleanup. File: `src/lib/hooks/useEffectOnce.ts`
- **`useFormContext`** — Access form context (theme, custom inputs) when inside `FormProvider`. File: `src/lib/context/FormContext.tsx`

---

## Build (for maintainers)

From repo root:

```bash
npm run build:lib
```

Or from this directory (after `npm install` here):

```bash
npm run build
```

---

## License

ISC
