@gnwebsoft/ui 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +688 -0
- package/dist/chunk-4H3AFH7A.js +505 -0
- package/dist/chunk-DE62KYFK.js +122 -0
- package/dist/chunk-DEPJRTVT.js +1 -0
- package/dist/chunk-EBRUE2WR.cjs +493 -0
- package/dist/chunk-FD57PCAC.cjs +1 -0
- package/dist/chunk-H3GQLELL.js +2025 -0
- package/dist/chunk-MVPLBJRK.cjs +1 -0
- package/dist/chunk-OJF67RNM.js +1 -0
- package/dist/chunk-OT7COE7R.cjs +2025 -0
- package/dist/chunk-R2YK4LTT.cjs +122 -0
- package/dist/chunk-U6SDYCWF.js +493 -0
- package/dist/chunk-ZC7FGYL2.cjs +505 -0
- package/dist/components/index.cjs +25 -0
- package/dist/components/index.d.cts +752 -0
- package/dist/components/index.d.ts +664 -15
- package/dist/components/index.js +25 -24
- package/dist/enhanced-z-I7EHVS.d.cts +134 -0
- package/dist/enhanced-z-I7EHVS.d.ts +134 -0
- package/dist/hooks/index.cjs +12 -0
- package/dist/hooks/index.d.cts +95 -0
- package/dist/hooks/index.d.ts +82 -4
- package/dist/hooks/index.js +12 -7
- package/dist/index.cjs +127 -0
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +4 -6
- package/dist/index.js +127 -54
- package/dist/types/index.cjs +2 -0
- package/dist/types/index.d.cts +241 -0
- package/dist/types/index.d.ts +205 -20
- package/dist/types/index.js +2 -1
- package/dist/utils/index.cjs +45 -0
- package/dist/utils/index.d.cts +366 -0
- package/dist/utils/index.d.ts +317 -9
- package/dist/utils/index.js +45 -22
- package/dist/wrappers/index.cjs +54 -0
- package/dist/wrappers/index.d.cts +1684 -0
- package/dist/wrappers/index.d.ts +1601 -118
- package/dist/wrappers/index.js +54 -8
- package/package.json +139 -88
- package/dist/AsyncSelectPayload-Cz4bgak0.d.mts +0 -10
- package/dist/AsyncSelectPayload-Cz4bgak0.d.ts +0 -10
- package/dist/chunk-2JFL7TS5.mjs +0 -0
- package/dist/chunk-6BGQA4BQ.js +0 -1
- package/dist/chunk-6JZ35VQJ.js +0 -19
- package/dist/chunk-7M2VOCYN.js +0 -1
- package/dist/chunk-BWQUYXUW.mjs +0 -1634
- package/dist/chunk-D3J7MWAU.js +0 -1634
- package/dist/chunk-EVPUCTZA.mjs +0 -0
- package/dist/chunk-FSU3H777.mjs +0 -473
- package/dist/chunk-GFSTK7KN.mjs +0 -19
- package/dist/chunk-I7EIUZKK.js +0 -332
- package/dist/chunk-JKUOV3MN.js +0 -473
- package/dist/chunk-RQS44YC7.mjs +0 -332
- package/dist/components/index.d.mts +0 -103
- package/dist/components/index.mjs +0 -24
- package/dist/hooks/index.d.mts +0 -17
- package/dist/hooks/index.mjs +0 -7
- package/dist/index.d.mts +0 -16
- package/dist/index.mjs +0 -54
- package/dist/types/index.d.mts +0 -56
- package/dist/types/index.mjs +0 -1
- package/dist/utils/index.d.mts +0 -58
- package/dist/utils/index.mjs +0 -22
- package/dist/wrappers/index.d.mts +0 -201
- package/dist/wrappers/index.mjs +0 -8
package/README.md
ADDED
|
@@ -0,0 +1,688 @@
|
|
|
1
|
+
# @gnwebsoft/ui
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
[](https://badge.fury.io/js/%40gnwebsoft%2Fui)
|
|
6
|
+
[](http://www.typescriptlang.org/)
|
|
7
|
+
[](https://choosealicense.com/licenses/mit/)
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🎨 **MUI v7 Integration** - Built on top of Material-UI components
|
|
12
|
+
- 📝 **Form Controls** - Comprehensive react-hook-form wrappers
|
|
13
|
+
- 🔍 **TypeScript First** - Full type safety and IntelliSense support
|
|
14
|
+
- 🌳 **Tree Shakeable** - Modular exports for optimal bundle size
|
|
15
|
+
- ♿ **Accessible** - WCAG compliant components
|
|
16
|
+
- 🎯 **Modern React** - Hooks, memo, forwardRef patterns
|
|
17
|
+
- 📱 **Responsive** - Mobile-first design approach
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @gnwebsoft/ui
|
|
23
|
+
# or
|
|
24
|
+
yarn add @gnwebsoft/ui
|
|
25
|
+
# or
|
|
26
|
+
pnpm add @gnwebsoft/ui
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Peer Dependencies
|
|
30
|
+
|
|
31
|
+
This library requires the following peer dependencies:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled react-hook-form @hookform/resolvers zod
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
<details>
|
|
38
|
+
<summary>Complete peer dependency list</summary>
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"@emotion/cache": "^11.14.0",
|
|
43
|
+
"@emotion/react": "^11.14.0",
|
|
44
|
+
"@emotion/styled": "^11.14.0",
|
|
45
|
+
"@hookform/resolvers": "^5.2.1",
|
|
46
|
+
"@mui/icons-material": "^7.3.1",
|
|
47
|
+
"@mui/lab": "^7.0.0-beta.16",
|
|
48
|
+
"@mui/material": "^7.3.1",
|
|
49
|
+
"@mui/x-data-grid": "^8.9.2",
|
|
50
|
+
"@mui/x-date-pickers": "^8.9.2",
|
|
51
|
+
"autosuggest-highlight": "^3.3.4",
|
|
52
|
+
"axios": "^1.11.0",
|
|
53
|
+
"dayjs": "^1.11.13",
|
|
54
|
+
"es-toolkit": "^1.39.8",
|
|
55
|
+
"lodash": "^4.17.21",
|
|
56
|
+
"react": "^19.1.1",
|
|
57
|
+
"react-dom": "^19.1.1",
|
|
58
|
+
"react-hook-form": "^7.62.0",
|
|
59
|
+
"typescript": "^5.9.2",
|
|
60
|
+
"zod": "^4.0.15",
|
|
61
|
+
"zustand": "^5.0.2"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
</details>
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import React from 'react';
|
|
70
|
+
import { SimpleButton, LabelText } from '@gnwebsoft/ui';
|
|
71
|
+
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
|
72
|
+
|
|
73
|
+
const theme = createTheme();
|
|
74
|
+
|
|
75
|
+
function App() {
|
|
76
|
+
return (
|
|
77
|
+
<ThemeProvider theme={theme}>
|
|
78
|
+
<div>
|
|
79
|
+
<LabelText>Welcome to @gnwebsoft/ui</LabelText>
|
|
80
|
+
<SimpleButton
|
|
81
|
+
variant="contained"
|
|
82
|
+
color="primary"
|
|
83
|
+
onClick={() => alert('Hello World!')}
|
|
84
|
+
>
|
|
85
|
+
Click Me
|
|
86
|
+
</SimpleButton>
|
|
87
|
+
</div>
|
|
88
|
+
</ThemeProvider>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export default App;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Module Imports
|
|
96
|
+
|
|
97
|
+
For optimal bundle size, import from specific modules:
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
// 🎯 Preferred - Tree-shakeable imports
|
|
101
|
+
import { SimpleButton } from '@gnwebsoft/ui/components';
|
|
102
|
+
import { TextFieldElement } from '@gnwebsoft/ui/wrappers';
|
|
103
|
+
import { useTransform } from '@gnwebsoft/ui/hooks';
|
|
104
|
+
import type { ApiResponse } from '@gnwebsoft/ui/types';
|
|
105
|
+
import { handleServerErrors } from '@gnwebsoft/ui/utils';
|
|
106
|
+
|
|
107
|
+
// 📦 Alternative - Root import (larger bundle)
|
|
108
|
+
import { SimpleButton, TextFieldElement } from '@gnwebsoft/ui';
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Available Modules
|
|
112
|
+
|
|
113
|
+
| Module | Description | Import Path |
|
|
114
|
+
|--------|-------------|-------------|
|
|
115
|
+
| **Components** | UI components | `@gnwebsoft/ui/components` |
|
|
116
|
+
| **Wrappers** | Form element wrappers | `@gnwebsoft/ui/wrappers` |
|
|
117
|
+
| **Hooks** | Custom React hooks | `@gnwebsoft/ui/hooks` |
|
|
118
|
+
| **Types** | TypeScript definitions | `@gnwebsoft/ui/types` |
|
|
119
|
+
| **Utils** | Utility functions | `@gnwebsoft/ui/utils` |
|
|
120
|
+
|
|
121
|
+
## Components
|
|
122
|
+
|
|
123
|
+
### Basic Components
|
|
124
|
+
|
|
125
|
+
#### SimpleButton
|
|
126
|
+
Enhanced MUI Button with loading states and conditional rendering.
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import { SimpleButton } from '@gnwebsoft/ui/components';
|
|
130
|
+
|
|
131
|
+
<SimpleButton
|
|
132
|
+
loading={isSubmitting}
|
|
133
|
+
loadingText="Saving..."
|
|
134
|
+
show={hasPermission}
|
|
135
|
+
variant="contained"
|
|
136
|
+
onClick={handleSubmit}
|
|
137
|
+
>
|
|
138
|
+
Save Changes
|
|
139
|
+
</SimpleButton>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Features:**
|
|
143
|
+
- Loading state with spinner
|
|
144
|
+
- Conditional rendering
|
|
145
|
+
- Automatic disabling during loading
|
|
146
|
+
- Custom loading text support
|
|
147
|
+
- Full TypeScript support
|
|
148
|
+
|
|
149
|
+
#### LabelText
|
|
150
|
+
Responsive label-value display component with grid layout and hover effects.
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { LabelText } from '@gnwebsoft/ui/components';
|
|
154
|
+
|
|
155
|
+
<LabelText
|
|
156
|
+
label="Full Name"
|
|
157
|
+
value="John Doe"
|
|
158
|
+
gridSize={{
|
|
159
|
+
labelSize: { xs: 12, sm: 4, md: 3 },
|
|
160
|
+
valueSize: { xs: 12, sm: 8, md: 9 }
|
|
161
|
+
}}
|
|
162
|
+
/>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Features:**
|
|
166
|
+
- Responsive grid layout
|
|
167
|
+
- Hover effects with background color change
|
|
168
|
+
- Text overflow handling with ellipsis
|
|
169
|
+
- Tooltip on hover showing full value
|
|
170
|
+
- Customizable spacing and styling
|
|
171
|
+
|
|
172
|
+
#### AuthorizedView
|
|
173
|
+
Simple conditional rendering component based on a boolean show prop.
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import { AuthorizedView } from '@gnwebsoft/ui/components';
|
|
177
|
+
|
|
178
|
+
<AuthorizedView show={user.hasAdminRole}>
|
|
179
|
+
<AdminPanel />
|
|
180
|
+
</AuthorizedView>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Features:**
|
|
184
|
+
- Minimal overhead conditional rendering
|
|
185
|
+
- Returns empty fragment when hidden
|
|
186
|
+
- TypeScript support
|
|
187
|
+
|
|
188
|
+
#### ClearButton, CancelButton, FilterButton
|
|
189
|
+
Standardized button components for common form actions.
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
import { ClearButton, CancelButton, FilterButton } from '@gnwebsoft/ui/components';
|
|
193
|
+
|
|
194
|
+
<ClearButton
|
|
195
|
+
isSubmitting={isLoading}
|
|
196
|
+
handleClear={() => reset()}
|
|
197
|
+
storeKey="userFormData" // Optional localStorage cleanup
|
|
198
|
+
/>
|
|
199
|
+
|
|
200
|
+
<CancelButton
|
|
201
|
+
isSubmitting={isLoading}
|
|
202
|
+
handleCancel={() => navigate('/dashboard')}
|
|
203
|
+
/>
|
|
204
|
+
|
|
205
|
+
<FilterButton
|
|
206
|
+
isSubmitting={isFiltering}
|
|
207
|
+
show={hasFilters}
|
|
208
|
+
title="Apply Filters"
|
|
209
|
+
icon={<SearchIcon />}
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Layout Components
|
|
214
|
+
|
|
215
|
+
#### FormWrapper
|
|
216
|
+
Card-based container for forms with header, title, and action buttons.
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
import { FormWrapper } from '@gnwebsoft/ui/components';
|
|
220
|
+
|
|
221
|
+
<FormWrapper
|
|
222
|
+
title="User Profile"
|
|
223
|
+
icon={<PersonIcon />}
|
|
224
|
+
actionButton={
|
|
225
|
+
<SimpleButton variant="outlined" size="small">
|
|
226
|
+
Reset
|
|
227
|
+
</SimpleButton>
|
|
228
|
+
}
|
|
229
|
+
>
|
|
230
|
+
<TextFieldElement name="firstName" label="First Name" />
|
|
231
|
+
<TextFieldElement name="lastName" label="Last Name" />
|
|
232
|
+
</FormWrapper>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Features:**
|
|
236
|
+
- Card-based layout with header and content areas
|
|
237
|
+
- Divider between header and content
|
|
238
|
+
- Flexible action button placement
|
|
239
|
+
- Grid container for content with spacing
|
|
240
|
+
|
|
241
|
+
#### FilterWrapper, ListWrapper, SimpleToolbar
|
|
242
|
+
Specialized container components for different UI patterns.
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
import { FilterWrapper, ListWrapper, SimpleToolbar } from '@gnwebsoft/ui/components';
|
|
246
|
+
|
|
247
|
+
<FilterWrapper>
|
|
248
|
+
<TextField label="Search" />
|
|
249
|
+
<SelectElement name="category" options={categories} />
|
|
250
|
+
</FilterWrapper>
|
|
251
|
+
|
|
252
|
+
<ListWrapper>
|
|
253
|
+
<LabelText label="Name" value={user.name} />
|
|
254
|
+
<LabelText label="Email" value={user.email} />
|
|
255
|
+
</ListWrapper>
|
|
256
|
+
|
|
257
|
+
<SimpleToolbar>
|
|
258
|
+
<SimpleButton variant="contained">Add New</SimpleButton>
|
|
259
|
+
<SimpleButton variant="outlined">Export</SimpleButton>
|
|
260
|
+
</SimpleToolbar>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Form Wrappers
|
|
264
|
+
|
|
265
|
+
All form wrappers integrate seamlessly with react-hook-form:
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
import { useForm } from 'react-hook-form';
|
|
269
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
270
|
+
import { z } from 'zod';
|
|
271
|
+
import {
|
|
272
|
+
TextFieldElement,
|
|
273
|
+
SelectElement,
|
|
274
|
+
DatePickerElement,
|
|
275
|
+
CheckboxElement
|
|
276
|
+
} from '@gnwebsoft/ui/wrappers';
|
|
277
|
+
|
|
278
|
+
const schema = z.object({
|
|
279
|
+
name: z.string().min(1, 'Name is required'),
|
|
280
|
+
email: z.string().email('Invalid email'),
|
|
281
|
+
category: z.string(),
|
|
282
|
+
birthDate: z.date(),
|
|
283
|
+
subscribe: z.boolean()
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
type FormData = z.infer<typeof schema>;
|
|
287
|
+
|
|
288
|
+
function ContactForm() {
|
|
289
|
+
const { control, handleSubmit } = useForm<FormData>({
|
|
290
|
+
resolver: zodResolver(schema)
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
return (
|
|
294
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
295
|
+
<TextFieldElement
|
|
296
|
+
control={control}
|
|
297
|
+
name="name"
|
|
298
|
+
label="Full Name"
|
|
299
|
+
required
|
|
300
|
+
/>
|
|
301
|
+
|
|
302
|
+
<TextFieldElement
|
|
303
|
+
control={control}
|
|
304
|
+
name="email"
|
|
305
|
+
label="Email"
|
|
306
|
+
type="email"
|
|
307
|
+
required
|
|
308
|
+
/>
|
|
309
|
+
|
|
310
|
+
<SelectElement
|
|
311
|
+
control={control}
|
|
312
|
+
name="category"
|
|
313
|
+
label="Category"
|
|
314
|
+
options={[
|
|
315
|
+
{ value: 'general', label: 'General Inquiry' },
|
|
316
|
+
{ value: 'support', label: 'Support' }
|
|
317
|
+
]}
|
|
318
|
+
/>
|
|
319
|
+
|
|
320
|
+
<DatePickerElement
|
|
321
|
+
control={control}
|
|
322
|
+
name="birthDate"
|
|
323
|
+
label="Birth Date"
|
|
324
|
+
/>
|
|
325
|
+
|
|
326
|
+
<CheckboxElement
|
|
327
|
+
control={control}
|
|
328
|
+
name="subscribe"
|
|
329
|
+
label="Subscribe to newsletter"
|
|
330
|
+
/>
|
|
331
|
+
|
|
332
|
+
<SimpleButton type="submit" variant="contained">
|
|
333
|
+
Submit
|
|
334
|
+
</SimpleButton>
|
|
335
|
+
</form>
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Available Form Wrappers
|
|
341
|
+
|
|
342
|
+
| Component | Description | Use Case | Features |
|
|
343
|
+
|-----------|-------------|----------|----------|
|
|
344
|
+
| `TextFieldElement` | Text input wrapper | Single-line text, email, password | Value transformation, grid layout, auto-validation |
|
|
345
|
+
| `PasswordElement` | Password input with visibility toggle | Secure password entry | Eye icon toggle, all TextFieldElement features |
|
|
346
|
+
| `SelectElement` | Single selection dropdown | Categories, statuses | Auto-select single option, custom label/value keys |
|
|
347
|
+
| `SelectMultiElement` | Multiple selection dropdown | Tags, permissions | Chip display, select all/none functionality |
|
|
348
|
+
| `SelectCascadeElement` | Dependent dropdown selections | Country → State → City | Hierarchical options, parent-child relationships |
|
|
349
|
+
| `AsyncSelect` | Async searchable dropdown | User search, API data | Debounced search, loading states, no options handling |
|
|
350
|
+
| `AsyncMultiSelect` | Async multiple selection | Multiple user selection | Async loading with multi-select capabilities |
|
|
351
|
+
| `DatePickerElement` | Date selection | Birth dates, deadlines | MUI date picker integration, keyboard input |
|
|
352
|
+
| `TimePickerElement` | Time selection | Appointments, schedules | MUI time picker integration, 12/24 hour format |
|
|
353
|
+
| `CheckboxElement` | Single checkbox | Agreements, preferences | Boolean value handling, label integration |
|
|
354
|
+
| `CheckboxGroup` | Multiple checkboxes | Multiple selections | Array value handling, group validation |
|
|
355
|
+
| `RadioButtonGroup` | Radio button group | Exclusive selections | Single selection from multiple options |
|
|
356
|
+
|
|
357
|
+
## Hooks
|
|
358
|
+
|
|
359
|
+
### useTransform
|
|
360
|
+
Transform values with memoization and change handling for form components.
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
import { useTransform } from '@gnwebsoft/ui/hooks';
|
|
364
|
+
|
|
365
|
+
const { value, onChange } = useTransform({
|
|
366
|
+
value: formValue,
|
|
367
|
+
onChange: field.onChange,
|
|
368
|
+
transform: {
|
|
369
|
+
input: (value) => value?.toString() || '',
|
|
370
|
+
output: (event) => parseInt(event.target.value) || null
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**Features:**
|
|
376
|
+
- Memoized transformations for performance
|
|
377
|
+
- Input/output transformation support
|
|
378
|
+
- Change event handling
|
|
379
|
+
- TypeScript type safety
|
|
380
|
+
- Integration with form components
|
|
381
|
+
|
|
382
|
+
**Common Use Cases:**
|
|
383
|
+
- Number input formatting
|
|
384
|
+
- Date formatting
|
|
385
|
+
- Currency formatting
|
|
386
|
+
- Array to string conversion
|
|
387
|
+
|
|
388
|
+
## Types
|
|
389
|
+
|
|
390
|
+
Comprehensive TypeScript interfaces for API integration and form handling:
|
|
391
|
+
|
|
392
|
+
```tsx
|
|
393
|
+
import type {
|
|
394
|
+
ApiResponse,
|
|
395
|
+
OperationResponse,
|
|
396
|
+
ValidationErrors,
|
|
397
|
+
OptionItem,
|
|
398
|
+
PostModel,
|
|
399
|
+
ListResponse
|
|
400
|
+
} from '@gnwebsoft/ui/types';
|
|
401
|
+
|
|
402
|
+
// API response structure
|
|
403
|
+
const response: ApiResponse<User[]> = {
|
|
404
|
+
status: 200,
|
|
405
|
+
apiData: users,
|
|
406
|
+
traceId: 'abc123'
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
// Form options
|
|
410
|
+
const options: OptionItem[] = [
|
|
411
|
+
{ Label: 'Option 1', Value: '1' },
|
|
412
|
+
{ Label: 'Option 2', Value: '2' }
|
|
413
|
+
];
|
|
414
|
+
|
|
415
|
+
// Paginated list response
|
|
416
|
+
const listResponse: ListResponse<User> = {
|
|
417
|
+
Data: [/* users */],
|
|
418
|
+
Total: 150
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// Filter/search request
|
|
422
|
+
const filterRequest: PostModel<UserFilter> = {
|
|
423
|
+
filterModel: { name: 'John' },
|
|
424
|
+
pageOffset: 0,
|
|
425
|
+
pageSize: 20,
|
|
426
|
+
sortField: 'name',
|
|
427
|
+
sortOrder: 'asc'
|
|
428
|
+
};
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**Available Types:**
|
|
432
|
+
- `ApiResponse<T>` - Standard API response structure
|
|
433
|
+
- `ValidationErrors` - Form validation errors
|
|
434
|
+
- `OptionItem` / `OptionItem2` - Select options
|
|
435
|
+
- `PostModel<T>` - Filter/pagination requests
|
|
436
|
+
- `ListResponse<T>` - Paginated responses
|
|
437
|
+
- `AsyncSelectPayload` - Async select data
|
|
438
|
+
|
|
439
|
+
## Utilities
|
|
440
|
+
|
|
441
|
+
### API Utilities
|
|
442
|
+
|
|
443
|
+
```tsx
|
|
444
|
+
import { api, handleServerErrors } from '@gnwebsoft/ui/utils';
|
|
445
|
+
|
|
446
|
+
// API calls with automatic authentication
|
|
447
|
+
const users = await api.get<User[]>('/users');
|
|
448
|
+
const newUser = await api.post<User>('/users', userData);
|
|
449
|
+
const filteredUsers = await api.filter<User, UserFilter>('/users/search', filterModel);
|
|
450
|
+
|
|
451
|
+
// File upload
|
|
452
|
+
const uploadResult = await api.upload<UploadResponse>('/upload', formData);
|
|
453
|
+
|
|
454
|
+
// Form error handling
|
|
455
|
+
try {
|
|
456
|
+
await api.post('/submit', formData);
|
|
457
|
+
} catch (error) {
|
|
458
|
+
handleServerErrors({
|
|
459
|
+
errors: error.response.data.errors,
|
|
460
|
+
setError
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Data Transformation
|
|
466
|
+
|
|
467
|
+
```tsx
|
|
468
|
+
import {
|
|
469
|
+
flattenObjectKeys,
|
|
470
|
+
readValueAsDate,
|
|
471
|
+
propertyExists,
|
|
472
|
+
removeLeadingTrailingSlashes,
|
|
473
|
+
getTimezone
|
|
474
|
+
} from '@gnwebsoft/ui/utils';
|
|
475
|
+
|
|
476
|
+
// Flatten nested objects
|
|
477
|
+
const flatData = flattenObjectKeys({ user: { name: 'John', age: 30 } });
|
|
478
|
+
// Result: { 'user.name': 'John', 'user.age': 30, 'user': {...} }
|
|
479
|
+
|
|
480
|
+
// Date conversion
|
|
481
|
+
const date = readValueAsDate('2023-12-25');
|
|
482
|
+
// Result: Date object or null
|
|
483
|
+
|
|
484
|
+
// Property checking
|
|
485
|
+
if (propertyExists(obj, 'user.address.street')) {
|
|
486
|
+
console.log(obj.user.address.street);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// URL cleaning
|
|
490
|
+
const cleanPath = removeLeadingTrailingSlashes('/api/users/');
|
|
491
|
+
// Result: 'api/users'
|
|
492
|
+
|
|
493
|
+
// Timezone info
|
|
494
|
+
const timezone = getTimezone();
|
|
495
|
+
// Result: 'America/New_York' or current timezone
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**Available Utilities:**
|
|
499
|
+
- `api` / `api2` - HTTP clients with authentication
|
|
500
|
+
- `handleServerErrors` - Form error mapping
|
|
501
|
+
- `flattenObjectKeys` - Nested object flattening
|
|
502
|
+
- `readValueAsDate` - Safe date conversion
|
|
503
|
+
- `propertyExists` - Type-safe property checking
|
|
504
|
+
- `removeLeadingTrailingSlashes` - URL path cleaning
|
|
505
|
+
- `getTimezone` - Timezone information
|
|
506
|
+
- `schemaTools` - Zod schema utilities
|
|
507
|
+
|
|
508
|
+
## Styling and Theming
|
|
509
|
+
|
|
510
|
+
Components inherit MUI theme configuration:
|
|
511
|
+
|
|
512
|
+
```tsx
|
|
513
|
+
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
|
514
|
+
|
|
515
|
+
const theme = createTheme({
|
|
516
|
+
palette: {
|
|
517
|
+
primary: {
|
|
518
|
+
main: '#1976d2',
|
|
519
|
+
},
|
|
520
|
+
secondary: {
|
|
521
|
+
main: '#dc004e',
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
typography: {
|
|
525
|
+
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
|
|
526
|
+
},
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
function App() {
|
|
530
|
+
return (
|
|
531
|
+
<ThemeProvider theme={theme}>
|
|
532
|
+
{/* Your app components */}
|
|
533
|
+
</ThemeProvider>
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
## Advanced Usage
|
|
539
|
+
|
|
540
|
+
### Async Select with Search
|
|
541
|
+
|
|
542
|
+
```tsx
|
|
543
|
+
import { AsyncSelect } from '@gnwebsoft/ui/wrappers';
|
|
544
|
+
|
|
545
|
+
<AsyncSelect
|
|
546
|
+
control={control}
|
|
547
|
+
name="assignee"
|
|
548
|
+
label="Assign to User"
|
|
549
|
+
loadOptions={async (searchValue) => {
|
|
550
|
+
const response = await api.get(`/users/search?q=${searchValue}`);
|
|
551
|
+
return response.data.map(user => ({
|
|
552
|
+
value: user.id,
|
|
553
|
+
label: `${user.name} (${user.email})`
|
|
554
|
+
}));
|
|
555
|
+
}}
|
|
556
|
+
placeholder="Search users..."
|
|
557
|
+
noOptionsText="No users found"
|
|
558
|
+
/>
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Cascade Selects
|
|
562
|
+
|
|
563
|
+
```tsx
|
|
564
|
+
import { SelectCascadeElement } from '@gnwebsoft/ui/wrappers';
|
|
565
|
+
|
|
566
|
+
<SelectCascadeElement
|
|
567
|
+
control={control}
|
|
568
|
+
name="location"
|
|
569
|
+
label="Location"
|
|
570
|
+
options={[
|
|
571
|
+
{
|
|
572
|
+
value: 'us',
|
|
573
|
+
label: 'United States',
|
|
574
|
+
children: [
|
|
575
|
+
{ value: 'ny', label: 'New York' },
|
|
576
|
+
{ value: 'ca', label: 'California' }
|
|
577
|
+
]
|
|
578
|
+
}
|
|
579
|
+
]}
|
|
580
|
+
/>
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
## Testing
|
|
584
|
+
|
|
585
|
+
Components are built with testing in mind:
|
|
586
|
+
|
|
587
|
+
```tsx
|
|
588
|
+
import { render, screen } from '@testing-library/react';
|
|
589
|
+
import { SimpleButton } from '@gnwebsoft/ui/components';
|
|
590
|
+
|
|
591
|
+
test('renders button with loading state', () => {
|
|
592
|
+
render(
|
|
593
|
+
<SimpleButton loading loadingText="Loading...">
|
|
594
|
+
Submit
|
|
595
|
+
</SimpleButton>
|
|
596
|
+
);
|
|
597
|
+
|
|
598
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
599
|
+
expect(screen.getByRole('button')).toBeDisabled();
|
|
600
|
+
});
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
## Contributing
|
|
604
|
+
|
|
605
|
+
1. Fork the repository
|
|
606
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
607
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
608
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
609
|
+
5. Open a Pull Request
|
|
610
|
+
|
|
611
|
+
## Documentation
|
|
612
|
+
|
|
613
|
+
Comprehensive documentation is available for all components and utilities:
|
|
614
|
+
|
|
615
|
+
### 📚 Complete Documentation
|
|
616
|
+
- **[Component Documentation](./docs/COMPONENT_DOCUMENTATION.md)** - Detailed guide for all components
|
|
617
|
+
- **[Components](./docs/components/README.md)** - UI Components documentation
|
|
618
|
+
- **[Form Wrappers](./docs/wrappers/README.md)** - Form wrapper components documentation
|
|
619
|
+
- **[Hooks](./docs/hooks/README.md)** - Custom React hooks documentation
|
|
620
|
+
- **[Utilities](./docs/utils/README.md)** - Utility functions documentation
|
|
621
|
+
- **[Types](./docs/types/README.md)** - TypeScript types documentation
|
|
622
|
+
|
|
623
|
+
### 🎯 Quick References
|
|
624
|
+
- **[Getting Started Guide](./docs/guides/getting-started.md)** - Setup and basic usage
|
|
625
|
+
- **[Forms Guide](./docs/guides/forms.md)** - Form handling patterns
|
|
626
|
+
- **[API Documentation](./docs/api/README.md)** - Generated API docs
|
|
627
|
+
|
|
628
|
+
### 📖 Examples
|
|
629
|
+
Each component includes:
|
|
630
|
+
- ✅ Basic usage examples
|
|
631
|
+
- ✅ Advanced configuration options
|
|
632
|
+
- ✅ TypeScript integration examples
|
|
633
|
+
- ✅ Testing patterns
|
|
634
|
+
- ✅ Accessibility guidelines
|
|
635
|
+
- ✅ Performance considerations
|
|
636
|
+
|
|
637
|
+
## Development
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
# Install dependencies
|
|
641
|
+
pnpm install
|
|
642
|
+
|
|
643
|
+
# Start development mode with hot reload
|
|
644
|
+
pnpm dev
|
|
645
|
+
|
|
646
|
+
# Run tests
|
|
647
|
+
pnpm test
|
|
648
|
+
|
|
649
|
+
# Build library
|
|
650
|
+
pnpm build
|
|
651
|
+
|
|
652
|
+
# Generate TypeScript documentation
|
|
653
|
+
pnpm docs:generate
|
|
654
|
+
|
|
655
|
+
# Validate package exports
|
|
656
|
+
pnpm run check-exports
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Development Workflow
|
|
660
|
+
The package supports instant development with hot module reloading:
|
|
661
|
+
|
|
662
|
+
```bash
|
|
663
|
+
# Start both UI package and sample app
|
|
664
|
+
pnpm dev
|
|
665
|
+
|
|
666
|
+
# Or start individually
|
|
667
|
+
pnpm run dev:ui # UI package in watch mode
|
|
668
|
+
pnpm run dev:web # Sample web app
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
## Browser Support
|
|
672
|
+
|
|
673
|
+
- Chrome (latest)
|
|
674
|
+
- Firefox (latest)
|
|
675
|
+
- Safari (latest)
|
|
676
|
+
- Edge (latest)
|
|
677
|
+
|
|
678
|
+
## License
|
|
679
|
+
|
|
680
|
+
MIT © GNWebsoft Private Limited
|
|
681
|
+
|
|
682
|
+
## Changelog
|
|
683
|
+
|
|
684
|
+
See [CHANGELOG.md](./CHANGELOG.md) for release history.
|
|
685
|
+
|
|
686
|
+
---
|
|
687
|
+
|
|
688
|
+
**Made with ❤️ by GNWebsoft Team**
|