izen-react-starter 1.1.3 → 2.0.0
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 +1275 -49
- package/dist/{MIMHJGAX-CX0R0gR-.js → MIMHJGAX-DM3PPc6i.js} +1 -1
- package/dist/{Q7LWSL4U-DisRfAmB.js → Q7LWSL4U-Dp8mxbtM.js} +2 -2
- package/dist/{VLTTJS3N-hByn9hgE.js → VLTTJS3N-Dfn6o7Pv.js} +2 -2
- package/dist/components/charts/ChartAreaInteractive.d.ts +2 -0
- package/dist/components/charts/ChartAreaInteractive.d.ts.map +1 -0
- package/dist/components/charts/index.d.ts +2 -0
- package/dist/components/charts/index.d.ts.map +1 -0
- package/dist/components/common/Header.d.ts +13 -0
- package/dist/components/common/Header.d.ts.map +1 -0
- package/dist/components/common/Heading.d.ts +7 -0
- package/dist/components/common/Heading.d.ts.map +1 -0
- package/dist/components/common/PageHead.d.ts +5 -0
- package/dist/components/common/PageHead.d.ts.map +1 -0
- package/dist/components/common/ThemeToggle.d.ts +5 -0
- package/dist/components/common/ThemeToggle.d.ts.map +1 -0
- package/dist/components/common/index.d.ts +5 -0
- package/dist/components/common/index.d.ts.map +1 -0
- package/dist/components/date-picker/DatePickerWithRange.d.ts +8 -0
- package/dist/components/date-picker/DatePickerWithRange.d.ts.map +1 -0
- package/dist/components/date-picker/DateRangeFilter.d.ts +7 -0
- package/dist/components/date-picker/DateRangeFilter.d.ts.map +1 -0
- package/dist/components/date-picker/index.d.ts +3 -0
- package/dist/components/date-picker/index.d.ts.map +1 -0
- package/dist/components/form/CheckboxGroup.d.ts +15 -0
- package/dist/components/form/CheckboxGroup.d.ts.map +1 -0
- package/dist/components/form/ComboboxSelect.d.ts +24 -0
- package/dist/components/form/ComboboxSelect.d.ts.map +1 -0
- package/dist/components/form/DatePicker.d.ts +14 -0
- package/dist/components/form/DatePicker.d.ts.map +1 -0
- package/dist/components/form/FileUploadButton.d.ts +19 -0
- package/dist/components/form/FileUploadButton.d.ts.map +1 -0
- package/dist/components/form/FormButtons.d.ts +19 -0
- package/dist/components/form/FormButtons.d.ts.map +1 -0
- package/dist/components/form/FormInput.d.ts +15 -0
- package/dist/components/form/FormInput.d.ts.map +1 -0
- package/dist/components/form/FormLayout.d.ts +21 -0
- package/dist/components/form/FormLayout.d.ts.map +1 -0
- package/dist/components/form/RadioGroup.d.ts +14 -0
- package/dist/components/form/RadioGroup.d.ts.map +1 -0
- package/dist/components/form/Select.d.ts +21 -0
- package/dist/components/form/Select.d.ts.map +1 -0
- package/dist/components/form/TextInput.d.ts +13 -0
- package/dist/components/form/TextInput.d.ts.map +1 -0
- package/dist/components/form/TimeInput.d.ts +13 -0
- package/dist/components/form/TimeInput.d.ts.map +1 -0
- package/dist/components/form/index.d.ts +23 -0
- package/dist/components/form/index.d.ts.map +1 -0
- package/dist/components/layout/AppSidebar.d.ts +24 -0
- package/dist/components/layout/AppSidebar.d.ts.map +1 -0
- package/dist/components/layout/DashboardLayout.d.ts +12 -0
- package/dist/components/layout/DashboardLayout.d.ts.map +1 -0
- package/dist/components/layout/NavDocuments.d.ts +11 -0
- package/dist/components/layout/NavDocuments.d.ts.map +1 -0
- package/dist/components/layout/NavMain.d.ts +24 -0
- package/dist/components/layout/NavMain.d.ts.map +1 -0
- package/dist/components/layout/NavSecondary.d.ts +14 -0
- package/dist/components/layout/NavSecondary.d.ts.map +1 -0
- package/dist/components/layout/NavUser.d.ts +18 -0
- package/dist/components/layout/NavUser.d.ts.map +1 -0
- package/dist/components/layout/SiteHeader.d.ts +7 -0
- package/dist/components/layout/SiteHeader.d.ts.map +1 -0
- package/dist/components/layout/index.d.ts +8 -0
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/modals/AlertModal.d.ts +10 -0
- package/dist/components/modals/AlertModal.d.ts.map +1 -0
- package/dist/components/modals/DeleteDialog.d.ts +7 -0
- package/dist/components/modals/DeleteDialog.d.ts.map +1 -0
- package/dist/components/modals/PopupModal.d.ts +16 -0
- package/dist/components/modals/PopupModal.d.ts.map +1 -0
- package/dist/components/modals/index.d.ts +4 -0
- package/dist/components/modals/index.d.ts.map +1 -0
- package/dist/components/navigation/DashboardNav.d.ts +18 -0
- package/dist/components/navigation/DashboardNav.d.ts.map +1 -0
- package/dist/components/navigation/MobileSidebar.d.ts +12 -0
- package/dist/components/navigation/MobileSidebar.d.ts.map +1 -0
- package/dist/components/navigation/Sidebar.d.ts +8 -0
- package/dist/components/navigation/Sidebar.d.ts.map +1 -0
- package/dist/components/navigation/UserNav.d.ts +10 -0
- package/dist/components/navigation/UserNav.d.ts.map +1 -0
- package/dist/components/navigation/index.d.ts +5 -0
- package/dist/components/navigation/index.d.ts.map +1 -0
- package/dist/components/overlay/Overlay.d.ts +5 -0
- package/dist/components/overlay/Overlay.d.ts.map +1 -0
- package/dist/components/overlay/index.d.ts +2 -0
- package/dist/components/overlay/index.d.ts.map +1 -0
- package/dist/components/search/TableSearchInput.d.ts +5 -0
- package/dist/components/search/TableSearchInput.d.ts.map +1 -0
- package/dist/components/search/index.d.ts +2 -0
- package/dist/components/search/index.d.ts.map +1 -0
- package/dist/components/table/DataTable.d.ts +14 -0
- package/dist/components/table/DataTable.d.ts.map +1 -0
- package/dist/components/table/DataTableSkeleton.d.ts +9 -0
- package/dist/components/table/DataTableSkeleton.d.ts.map +1 -0
- package/dist/components/table/Pagination.d.ts +7 -0
- package/dist/components/table/Pagination.d.ts.map +1 -0
- package/dist/components/table/PaginationSection.d.ts +8 -0
- package/dist/components/table/PaginationSection.d.ts.map +1 -0
- package/dist/components/table/ServerDataTable.d.ts +10 -0
- package/dist/components/table/ServerDataTable.d.ts.map +1 -0
- package/dist/components/table/SpecialDaysTable.d.ts +26 -0
- package/dist/components/table/SpecialDaysTable.d.ts.map +1 -0
- package/dist/components/table/Table.d.ts +28 -0
- package/dist/components/table/Table.d.ts.map +1 -0
- package/dist/components/table/TableActions.d.ts +19 -0
- package/dist/components/table/TableActions.d.ts.map +1 -0
- package/dist/components/table/TableHeader.d.ts +6 -0
- package/dist/components/table/TableHeader.d.ts.map +1 -0
- package/dist/components/table/index.d.ts +15 -0
- package/dist/components/table/index.d.ts.map +1 -0
- package/dist/components/tabs/GenericTab.d.ts +7 -0
- package/dist/components/tabs/GenericTab.d.ts.map +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.d.ts.map +1 -0
- package/dist/components/ui/index.d.ts +0 -2
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/constants/urls.d.ts +2 -0
- package/dist/constants/urls.d.ts.map +1 -0
- package/dist/index-Dnn3beiE.js +62337 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/react-starter.js +326 -298
- package/dist/react-starter.umd.cjs +373 -199
- package/dist/services/apiService.d.ts +3 -4
- package/dist/services/apiService.d.ts.map +1 -1
- package/package.json +10 -2
- package/dist/index-BlTeKmzn.js +0 -45406
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# izen-react-starter
|
|
2
2
|
|
|
3
3
|
A modern React component library built with Vite, TypeScript, and best practices.
|
|
4
4
|
|
|
@@ -22,20 +22,25 @@ A modern React component library built with Vite, TypeScript, and best practices
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npm install react-starter
|
|
25
|
+
npm install izen-react-starter
|
|
26
26
|
# or
|
|
27
|
-
yarn add react-starter
|
|
27
|
+
yarn add izen-react-starter
|
|
28
28
|
# or
|
|
29
|
-
pnpm add react-starter
|
|
29
|
+
pnpm add izen-react-starter
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
> **Note**: This library has a peer dependency of React ^18.2.0. If you're using React 19, you may need to install with `--legacy-peer-deps` flag:
|
|
33
|
+
> ```bash
|
|
34
|
+
> npm install izen-react-starter --legacy-peer-deps
|
|
35
|
+
> ```
|
|
36
|
+
|
|
32
37
|
### Import Styles
|
|
33
38
|
|
|
34
39
|
Don't forget to import the CSS file in your app entry point:
|
|
35
40
|
|
|
36
41
|
```tsx
|
|
37
42
|
// In your main.tsx or App.tsx
|
|
38
|
-
import 'react-starter/style.css';
|
|
43
|
+
import 'izen-react-starter/style.css';
|
|
39
44
|
```
|
|
40
45
|
|
|
41
46
|
The library includes Tailwind CSS with pre-configured theme variables for:
|
|
@@ -51,7 +56,7 @@ The library includes Tailwind CSS with pre-configured theme variables for:
|
|
|
51
56
|
Wrap your application with `AppProvider` to get all providers in one go:
|
|
52
57
|
|
|
53
58
|
```tsx
|
|
54
|
-
import { AppProvider } from 'react-starter';
|
|
59
|
+
import { AppProvider } from 'izen-react-starter';
|
|
55
60
|
import { AppRouter } from './routes';
|
|
56
61
|
|
|
57
62
|
function App() {
|
|
@@ -69,7 +74,7 @@ function App() {
|
|
|
69
74
|
### Authentication
|
|
70
75
|
|
|
71
76
|
```tsx
|
|
72
|
-
import { AuthProvider, useAuth } from 'react-starter';
|
|
77
|
+
import { AuthProvider, useAuth } from 'izen-react-starter';
|
|
73
78
|
|
|
74
79
|
function LoginPage() {
|
|
75
80
|
const { setAuthData } = useAuth();
|
|
@@ -103,7 +108,7 @@ function ProfilePage() {
|
|
|
103
108
|
### Protected Routes
|
|
104
109
|
|
|
105
110
|
```tsx
|
|
106
|
-
import { RequiredAuth } from 'react-starter';
|
|
111
|
+
import { RequiredAuth } from 'izen-react-starter';
|
|
107
112
|
import { Routes, Route } from 'react-router-dom';
|
|
108
113
|
|
|
109
114
|
function AppRouter() {
|
|
@@ -124,7 +129,7 @@ function AppRouter() {
|
|
|
124
129
|
### Router Hooks
|
|
125
130
|
|
|
126
131
|
```tsx
|
|
127
|
-
import { useRouter, usePathname } from 'react-starter';
|
|
132
|
+
import { useRouter, usePathname } from 'izen-react-starter';
|
|
128
133
|
|
|
129
134
|
function MyComponent() {
|
|
130
135
|
const router = useRouter();
|
|
@@ -147,7 +152,7 @@ function MyComponent() {
|
|
|
147
152
|
### Theme Provider
|
|
148
153
|
|
|
149
154
|
```tsx
|
|
150
|
-
import { ThemeProvider, useTheme } from 'react-starter';
|
|
155
|
+
import { ThemeProvider, useTheme } from 'izen-react-starter';
|
|
151
156
|
|
|
152
157
|
function ThemeToggle() {
|
|
153
158
|
const { theme, setTheme } = useTheme();
|
|
@@ -163,7 +168,7 @@ function ThemeToggle() {
|
|
|
163
168
|
### Modal and Overlay
|
|
164
169
|
|
|
165
170
|
```tsx
|
|
166
|
-
import { ModalProvider, useModal, OverlayProvider, useOverlay } from 'react-starter';
|
|
171
|
+
import { ModalProvider, useModal, OverlayProvider, useOverlay } from 'izen-react-starter';
|
|
167
172
|
|
|
168
173
|
function MyComponent() {
|
|
169
174
|
const { isOpen, setIsOpen } = useModal();
|
|
@@ -181,24 +186,298 @@ function MyComponent() {
|
|
|
181
186
|
### Components
|
|
182
187
|
|
|
183
188
|
```tsx
|
|
184
|
-
import { Button, Card } from 'react-starter';
|
|
189
|
+
import { Button, Card } from 'izen-react-starter';
|
|
185
190
|
|
|
186
191
|
function MyApp() {
|
|
187
192
|
return (
|
|
188
|
-
<Card
|
|
193
|
+
<Card
|
|
194
|
+
title="Hello World"
|
|
195
|
+
elevation="medium"
|
|
196
|
+
style={{ marginBottom: '2rem' }}
|
|
197
|
+
className="custom-card"
|
|
198
|
+
>
|
|
189
199
|
<p>Card content goes here</p>
|
|
190
|
-
<Button variant="primary" onClick={() => alert('Clicked!')}>
|
|
200
|
+
<Button variant="primary" size="medium" onClick={() => alert('Clicked!')}>
|
|
191
201
|
Click Me
|
|
192
202
|
</Button>
|
|
203
|
+
<Button variant="secondary" size="small">
|
|
204
|
+
Small Button
|
|
205
|
+
</Button>
|
|
206
|
+
<Button variant="outline" loading>
|
|
207
|
+
Loading...
|
|
208
|
+
</Button>
|
|
193
209
|
</Card>
|
|
194
210
|
);
|
|
195
211
|
}
|
|
196
212
|
```
|
|
197
213
|
|
|
214
|
+
### Generic Table
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
import { GenericTable, ActionType } from 'izen-react-starter';
|
|
218
|
+
|
|
219
|
+
type SpecialDay = {
|
|
220
|
+
id: number;
|
|
221
|
+
name: string;
|
|
222
|
+
start: string;
|
|
223
|
+
end: string;
|
|
224
|
+
floatingHoliday?: boolean;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
function SpecialDaysView({ rows, pagination, onAction }: { rows: SpecialDay[]; pagination: any; onAction: (row: SpecialDay, action: ActionType) => void }) {
|
|
228
|
+
return (
|
|
229
|
+
<GenericTable
|
|
230
|
+
rows={rows}
|
|
231
|
+
columns={[
|
|
232
|
+
{ header: 'Name', render: (row) => `${row.name}${row.floatingHoliday ? ' (Floating Holiday)' : ''}` },
|
|
233
|
+
{ header: 'Start', render: (row) => new Date(row.start).toLocaleDateString() },
|
|
234
|
+
{ header: 'End', render: (row) => new Date(row.end).toLocaleDateString() },
|
|
235
|
+
]}
|
|
236
|
+
getRowId={(row) => row.id}
|
|
237
|
+
onAction={(row, action) => onAction(row, action)}
|
|
238
|
+
getActionLink={(row) => `/preferences/special-days/${row.id}`}
|
|
239
|
+
pagination={pagination}
|
|
240
|
+
emptyText="No special days found."
|
|
241
|
+
/>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Table Utilities
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
import { TableActions, Pagination, TableHeader, GenericTab } from 'izen-react-starter';
|
|
250
|
+
|
|
251
|
+
// Actions cell example
|
|
252
|
+
<TableActions
|
|
253
|
+
link="/resource/123"
|
|
254
|
+
Item={{ id: 123 }}
|
|
255
|
+
handleAction={(row, action) => console.log(row, action)}
|
|
256
|
+
/>;
|
|
257
|
+
|
|
258
|
+
// Pagination example (expects meta/links/url shape)
|
|
259
|
+
<Pagination
|
|
260
|
+
meta={{ currentPage: 1, itemsPerPage: 10, totalItems: 42 }}
|
|
261
|
+
links={{ prev: null, next: '?page=2', first: '?page=1', last: '?page=5' }}
|
|
262
|
+
url="/api/resources"
|
|
263
|
+
/>;
|
|
264
|
+
|
|
265
|
+
// Table header helper (basic)
|
|
266
|
+
<table>
|
|
267
|
+
<TableHeader headers={["Name", "Email"]} />
|
|
268
|
+
{/* ...rows */}
|
|
269
|
+
</table>;
|
|
270
|
+
|
|
271
|
+
// GenericTab helper to wrap tab content and reuse TableActions
|
|
272
|
+
<GenericTab
|
|
273
|
+
key="notes"
|
|
274
|
+
data={[{ id: 1, text: 'Note text' }]}
|
|
275
|
+
handleAction={(item, action) => console.log(item, action)}
|
|
276
|
+
/>;
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Layout System
|
|
280
|
+
|
|
281
|
+
The library provides a complete layout system with sidebar, header, and navigation components.
|
|
282
|
+
|
|
283
|
+
#### DashboardLayout (Complete Layout)
|
|
284
|
+
|
|
285
|
+
A full dashboard layout that combines sidebar and header:
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { DashboardLayout, Overlay } from 'izen-react-starter';
|
|
289
|
+
import { Home, Settings, FileText, HelpCircle } from 'lucide-react';
|
|
290
|
+
|
|
291
|
+
function App() {
|
|
292
|
+
return (
|
|
293
|
+
<DashboardLayout
|
|
294
|
+
sidebarProps={{
|
|
295
|
+
brandName: "My App",
|
|
296
|
+
brandIcon: Home,
|
|
297
|
+
navMain: [
|
|
298
|
+
{ title: "Dashboard", url: "/dashboard", icon: Home },
|
|
299
|
+
{
|
|
300
|
+
title: "Settings",
|
|
301
|
+
url: "#",
|
|
302
|
+
icon: Settings,
|
|
303
|
+
items: [
|
|
304
|
+
{ title: "Profile", url: "/settings/profile" },
|
|
305
|
+
{ title: "Security", url: "/settings/security" },
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
navSecondary: [
|
|
310
|
+
{ title: "Help", url: "/help", icon: HelpCircle },
|
|
311
|
+
{ title: "Docs", url: "/docs", icon: FileText, target: "_blank" },
|
|
312
|
+
],
|
|
313
|
+
user: {
|
|
314
|
+
name: "John Doe",
|
|
315
|
+
email: "john@example.com",
|
|
316
|
+
avatar: "/avatar.jpg",
|
|
317
|
+
},
|
|
318
|
+
onLogout: () => console.log("Logout"),
|
|
319
|
+
userMenuItems: [
|
|
320
|
+
{ label: "Profile", onClick: () => {} },
|
|
321
|
+
{ label: "Settings", onClick: () => {} },
|
|
322
|
+
],
|
|
323
|
+
}}
|
|
324
|
+
headerProps={{
|
|
325
|
+
pageTitles: {
|
|
326
|
+
"/dashboard": "Dashboard",
|
|
327
|
+
"/settings": "Settings",
|
|
328
|
+
},
|
|
329
|
+
defaultTitle: "My App",
|
|
330
|
+
}}
|
|
331
|
+
defaultOpen={true}
|
|
332
|
+
showOverlay={false}
|
|
333
|
+
overlayComponent={<Overlay show={false} />}
|
|
334
|
+
>
|
|
335
|
+
{/* Your page content */}
|
|
336
|
+
</DashboardLayout>
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### AppSidebar (Sidebar Component)
|
|
342
|
+
|
|
343
|
+
Collapsible sidebar with navigation menu:
|
|
344
|
+
|
|
345
|
+
```tsx
|
|
346
|
+
import { AppSidebar } from 'izen-react-starter';
|
|
347
|
+
import { Home, Settings, Users } from 'lucide-react';
|
|
348
|
+
|
|
349
|
+
<AppSidebar
|
|
350
|
+
brandName="Acme Inc"
|
|
351
|
+
brandIcon={Home}
|
|
352
|
+
navMain={[
|
|
353
|
+
{ title: "Home", url: "/", icon: Home, badge: "3" },
|
|
354
|
+
{
|
|
355
|
+
title: "Settings",
|
|
356
|
+
url: "#",
|
|
357
|
+
icon: Settings,
|
|
358
|
+
items: [
|
|
359
|
+
{ title: "Profile", url: "/settings/profile" },
|
|
360
|
+
{ title: "Security", url: "/settings/security" },
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
]}
|
|
364
|
+
navSecondary={[
|
|
365
|
+
{ title: "Help", url: "/help", icon: HelpCircle },
|
|
366
|
+
]}
|
|
367
|
+
user={{
|
|
368
|
+
name: "Jane Doe",
|
|
369
|
+
email: "jane@example.com",
|
|
370
|
+
avatar: "/avatar.jpg",
|
|
371
|
+
}}
|
|
372
|
+
onLogout={() => console.log("Logging out")}
|
|
373
|
+
userMenuItems={[
|
|
374
|
+
{ label: "Account", onClick: () => {} },
|
|
375
|
+
]}
|
|
376
|
+
/>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### Navigation Components
|
|
380
|
+
|
|
381
|
+
**NavMain** - Main navigation menu with collapsible groups:
|
|
382
|
+
|
|
383
|
+
```tsx
|
|
384
|
+
import { NavMain } from 'izen-react-starter';
|
|
385
|
+
import { Home, Settings } from 'lucide-react';
|
|
386
|
+
|
|
387
|
+
<NavMain
|
|
388
|
+
items={[
|
|
389
|
+
{ title: "Dashboard", url: "/dashboard", icon: Home },
|
|
390
|
+
{
|
|
391
|
+
title: "Settings",
|
|
392
|
+
icon: Settings,
|
|
393
|
+
items: [
|
|
394
|
+
{ title: "Profile", url: "/settings/profile" },
|
|
395
|
+
{ title: "Security", url: "/settings/security", badge: "2" },
|
|
396
|
+
]
|
|
397
|
+
},
|
|
398
|
+
]}
|
|
399
|
+
/>
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**NavSecondary** - Secondary navigation links:
|
|
403
|
+
|
|
404
|
+
```tsx
|
|
405
|
+
import { NavSecondary } from 'izen-react-starter';
|
|
406
|
+
import { HelpCircle, FileText } from 'lucide-react';
|
|
407
|
+
|
|
408
|
+
<NavSecondary
|
|
409
|
+
items={[
|
|
410
|
+
{ title: "Help", url: "/help", icon: HelpCircle },
|
|
411
|
+
{ title: "Documentation", url: "https://docs.example.com", icon: FileText, target: "_blank" },
|
|
412
|
+
]}
|
|
413
|
+
/>
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**NavUser** - User menu dropdown:
|
|
417
|
+
|
|
418
|
+
```tsx
|
|
419
|
+
import { NavUser } from 'izen-react-starter';
|
|
420
|
+
|
|
421
|
+
<NavUser
|
|
422
|
+
user={{
|
|
423
|
+
name: "John Doe",
|
|
424
|
+
email: "john@example.com",
|
|
425
|
+
avatar: "/avatar.jpg",
|
|
426
|
+
}}
|
|
427
|
+
onLogout={() => console.log("Logout")}
|
|
428
|
+
menuItems={[
|
|
429
|
+
{ label: "Profile", onClick: () => {} },
|
|
430
|
+
{ label: "Settings", onClick: () => {} },
|
|
431
|
+
]}
|
|
432
|
+
/>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**NavDocuments** - Document list with actions:
|
|
436
|
+
|
|
437
|
+
```tsx
|
|
438
|
+
import { NavDocuments } from 'izen-react-starter';
|
|
439
|
+
import { FileText } from 'lucide-react';
|
|
440
|
+
|
|
441
|
+
<NavDocuments
|
|
442
|
+
items={[
|
|
443
|
+
{ name: "Report Q1", url: "/docs/q1", icon: FileText },
|
|
444
|
+
{ name: "Budget 2024", url: "/docs/budget", icon: FileText },
|
|
445
|
+
]}
|
|
446
|
+
/>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
#### SiteHeader
|
|
450
|
+
|
|
451
|
+
Header with page title and sidebar trigger:
|
|
452
|
+
|
|
453
|
+
```tsx
|
|
454
|
+
import { SiteHeader } from 'izen-react-starter';
|
|
455
|
+
|
|
456
|
+
<SiteHeader
|
|
457
|
+
pageTitles={{
|
|
458
|
+
"/dashboard": "Dashboard",
|
|
459
|
+
"/settings": "Settings",
|
|
460
|
+
}}
|
|
461
|
+
defaultTitle="My App"
|
|
462
|
+
/>
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Charts and Overlay
|
|
466
|
+
|
|
467
|
+
```tsx
|
|
468
|
+
import { ChartAreaInteractive, Overlay } from 'izen-react-starter';
|
|
469
|
+
|
|
470
|
+
// Chart with timeframe controls
|
|
471
|
+
<ChartAreaInteractive />;
|
|
472
|
+
|
|
473
|
+
// Simple overlay toggled by boolean
|
|
474
|
+
<Overlay show={isLoading} />;
|
|
475
|
+
```
|
|
476
|
+
|
|
198
477
|
### Layout Context
|
|
199
478
|
|
|
200
479
|
```tsx
|
|
201
|
-
import { LayoutProvider, useLayout } from 'react-starter';
|
|
480
|
+
import { LayoutProvider, useLayout } from 'izen-react-starter';
|
|
202
481
|
|
|
203
482
|
function App() {
|
|
204
483
|
return (
|
|
@@ -227,36 +506,56 @@ function MyComponent() {
|
|
|
227
506
|
### API Service
|
|
228
507
|
|
|
229
508
|
```tsx
|
|
230
|
-
import {
|
|
509
|
+
import React, { useEffect } from 'react';
|
|
510
|
+
import { useApiService } from 'izen-react-starter';
|
|
231
511
|
|
|
232
|
-
//
|
|
233
|
-
|
|
512
|
+
// Set the base URL once, typically in your app root
|
|
513
|
+
export function App() {
|
|
514
|
+
const apiService = useApiService();
|
|
234
515
|
|
|
235
|
-
|
|
236
|
-
apiService.
|
|
516
|
+
useEffect(() => {
|
|
517
|
+
apiService.setBaseURL('https://api.example.com');
|
|
518
|
+
}, [apiService]);
|
|
237
519
|
|
|
238
|
-
|
|
239
|
-
async function fetchData() {
|
|
240
|
-
try {
|
|
241
|
-
const data = await apiService.get('/users');
|
|
242
|
-
console.log(data);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.error('Error fetching data:', error);
|
|
245
|
-
}
|
|
520
|
+
return <UsersPage />;
|
|
246
521
|
}
|
|
247
522
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
523
|
+
// Usage in a page/component
|
|
524
|
+
export function UsersPage() {
|
|
525
|
+
const apiService = useApiService();
|
|
526
|
+
|
|
527
|
+
// Fetch users example
|
|
528
|
+
const fetchUsers = async () => {
|
|
529
|
+
try {
|
|
530
|
+
const users = await apiService.get('/users');
|
|
531
|
+
console.log(users);
|
|
532
|
+
} catch (error) {
|
|
533
|
+
console.error('Error fetching users:', error);
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
// Create user example
|
|
538
|
+
const createUser = async () => {
|
|
539
|
+
try {
|
|
540
|
+
const response = await apiService.post('/users', {
|
|
541
|
+
name: 'John Doe',
|
|
542
|
+
email: 'john@example.com',
|
|
543
|
+
});
|
|
544
|
+
console.log(response);
|
|
545
|
+
} catch (error) {
|
|
546
|
+
console.error('Error creating user:', error);
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
return (
|
|
551
|
+
<div>
|
|
552
|
+
<button onClick={fetchUsers}>Fetch Users</button>
|
|
553
|
+
<button onClick={createUser}>Create User</button>
|
|
554
|
+
</div>
|
|
555
|
+
);
|
|
258
556
|
}
|
|
259
557
|
```
|
|
558
|
+
> **Tip:** You only need to set the baseURL once per app session. After that, all requests will use this base URL automatically. The token will always be injected from AuthProvider for every request.
|
|
260
559
|
|
|
261
560
|
### Role-Based Access Control (RBAC)
|
|
262
561
|
|
|
@@ -267,7 +566,7 @@ import {
|
|
|
267
566
|
withAccessControl,
|
|
268
567
|
Action,
|
|
269
568
|
Resource
|
|
270
|
-
} from 'react-starter';
|
|
569
|
+
} from 'izen-react-starter';
|
|
271
570
|
|
|
272
571
|
// Using the hook
|
|
273
572
|
function AdminPanel() {
|
|
@@ -307,7 +606,7 @@ const ProtectedComponent = withAccessControl(MyComponent);
|
|
|
307
606
|
### Utility Functions
|
|
308
607
|
|
|
309
608
|
```tsx
|
|
310
|
-
import { cn, debounce, throttle, capitalize, formatDate } from 'react-starter';
|
|
609
|
+
import { cn, debounce, throttle, capitalize, formatDate } from 'izen-react-starter';
|
|
311
610
|
|
|
312
611
|
// Combine classnames with Tailwind merge
|
|
313
612
|
const className = cn('bg-blue-500', 'text-white', 'hover:bg-blue-600');
|
|
@@ -332,7 +631,7 @@ const formatted = formatDate(new Date(), 'yyyy-MM-dd');
|
|
|
332
631
|
### Custom Hooks
|
|
333
632
|
|
|
334
633
|
```tsx
|
|
335
|
-
import { useIsMobile } from 'react-starter';
|
|
634
|
+
import { useIsMobile } from 'izen-react-starter';
|
|
336
635
|
|
|
337
636
|
function ResponsiveComponent() {
|
|
338
637
|
const isMobile = useIsMobile();
|
|
@@ -348,7 +647,7 @@ function ResponsiveComponent() {
|
|
|
348
647
|
### Cache Management
|
|
349
648
|
|
|
350
649
|
```tsx
|
|
351
|
-
import { handleEditCache, handleSingleEditCache } from 'react-starter';
|
|
650
|
+
import { handleEditCache, handleSingleEditCache } from 'izen-react-starter';
|
|
352
651
|
|
|
353
652
|
// Update cache after editing an item
|
|
354
653
|
handleEditCache({
|
|
@@ -522,11 +821,13 @@ Props:
|
|
|
522
821
|
### Card Component
|
|
523
822
|
|
|
524
823
|
Props:
|
|
525
|
-
- `title`: string (optional)
|
|
526
|
-
- `children`: ReactNode (required)
|
|
527
|
-
- `footer`: ReactNode (optional)
|
|
528
|
-
- `elevation`: 'none' | 'low' | 'medium' | 'high' (default: 'medium')
|
|
529
|
-
- `className`: string (optional)
|
|
824
|
+
- `title`: string (optional) - Card header title
|
|
825
|
+
- `children`: ReactNode (required) - Card body content
|
|
826
|
+
- `footer`: ReactNode (optional) - Card footer content
|
|
827
|
+
- `elevation`: 'none' | 'low' | 'medium' | 'high' (default: 'medium') - Shadow depth
|
|
828
|
+
- `className`: string (optional) - Additional CSS classes
|
|
829
|
+
- `style`: CSSProperties (optional) - Inline styles
|
|
830
|
+
- All standard HTML div attributes (onClick, onMouseEnter, etc.)
|
|
530
831
|
|
|
531
832
|
### Layout Context
|
|
532
833
|
|
|
@@ -547,8 +848,933 @@ Methods:
|
|
|
547
848
|
- `patch<T>(url, data?, config?)`: Promise<T>
|
|
548
849
|
- `delete<T>(url, config?)`: Promise<T>
|
|
549
850
|
- `setBaseURL(baseURL)`: void
|
|
550
|
-
|
|
551
|
-
|
|
851
|
+
|
|
852
|
+
> **Note:** The API service now always uses the latest token from the AuthProvider. Use the `useApiService` hook in your components. You no longer need to call `setAuthToken` or `removeAuthToken` manually.
|
|
853
|
+
### Organized Component Library
|
|
854
|
+
|
|
855
|
+
The library includes a comprehensive set of components organized by functionality:
|
|
856
|
+
|
|
857
|
+
#### Modals
|
|
858
|
+
|
|
859
|
+
Reusable modal dialogs for common user interactions.
|
|
860
|
+
|
|
861
|
+
```tsx
|
|
862
|
+
import { AlertModal, DeleteDialog, PopupModal } from 'izen-react-starter';
|
|
863
|
+
|
|
864
|
+
// Alert Modal - Generic confirmation dialog
|
|
865
|
+
function MyComponent() {
|
|
866
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
867
|
+
|
|
868
|
+
return (
|
|
869
|
+
<AlertModal
|
|
870
|
+
isOpen={isOpen}
|
|
871
|
+
onClose={() => setIsOpen(false)}
|
|
872
|
+
onConfirm={handleConfirm}
|
|
873
|
+
loading={loading}
|
|
874
|
+
title="Are you sure?"
|
|
875
|
+
description="This action cannot be undone."
|
|
876
|
+
/>
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// Delete Dialog - Specific delete confirmation
|
|
881
|
+
<DeleteDialog
|
|
882
|
+
openDeleteDialog={isDeleteOpen}
|
|
883
|
+
setIsOpenDeleteDialog={setIsDeleteOpen}
|
|
884
|
+
onDelete={handleDelete}
|
|
885
|
+
/>
|
|
886
|
+
|
|
887
|
+
// Popup Modal - Complex modal with scroll area and optional "Add New" button
|
|
888
|
+
<PopupModal
|
|
889
|
+
isOpen={modalName === 'create'}
|
|
890
|
+
setIsOpen={setModalName}
|
|
891
|
+
modalName="create"
|
|
892
|
+
title="Add New Item"
|
|
893
|
+
showAddBtn={true}
|
|
894
|
+
isAllowedCreate={true}
|
|
895
|
+
renderModal={(onClose) => (
|
|
896
|
+
<YourForm
|
|
897
|
+
onSubmit={(data) => {
|
|
898
|
+
handleSubmit(data);
|
|
899
|
+
onClose();
|
|
900
|
+
}}
|
|
901
|
+
/>
|
|
902
|
+
)}
|
|
903
|
+
extraBtns={() => (
|
|
904
|
+
<Button onClick={handleExtraAction}>Custom Action</Button>
|
|
905
|
+
)}
|
|
906
|
+
/>
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
#### Navigation Components
|
|
910
|
+
|
|
911
|
+
Complete navigation system with responsive design.
|
|
912
|
+
|
|
913
|
+
```tsx
|
|
914
|
+
import { UserNav, DashboardNav, Sidebar, MobileSidebar, Header } from 'izen-react-starter';
|
|
915
|
+
|
|
916
|
+
// User navigation dropdown with avatar
|
|
917
|
+
<UserNav
|
|
918
|
+
user={{
|
|
919
|
+
name: 'John Doe',
|
|
920
|
+
email: 'john@example.com',
|
|
921
|
+
avatar: 'https://example.com/avatar.jpg'
|
|
922
|
+
}}
|
|
923
|
+
onLogout={handleLogout}
|
|
924
|
+
/>
|
|
925
|
+
|
|
926
|
+
// Dashboard navigation list with icons
|
|
927
|
+
const navItems = [
|
|
928
|
+
{ href: '/dashboard', label: 'Dashboard', icon: 'home', isShow: true },
|
|
929
|
+
{ href: '/settings', label: 'Settings', icon: 'settings', isShow: true },
|
|
930
|
+
{ href: '/users', label: 'Users', icon: 'users', isShow: false } // Hidden item
|
|
931
|
+
];
|
|
932
|
+
|
|
933
|
+
<DashboardNav
|
|
934
|
+
items={navItems}
|
|
935
|
+
setOpen={setIsSidebarOpen} // Optional - for mobile
|
|
936
|
+
/>
|
|
937
|
+
|
|
938
|
+
// Desktop sidebar with branding
|
|
939
|
+
<Sidebar
|
|
940
|
+
navItems={navItems}
|
|
941
|
+
logoText="My App"
|
|
942
|
+
logoHref="/"
|
|
943
|
+
/>
|
|
944
|
+
|
|
945
|
+
// Mobile sidebar with sheet overlay
|
|
946
|
+
<MobileSidebar
|
|
947
|
+
sidebarOpen={isMobileOpen}
|
|
948
|
+
setSidebarOpen={setIsMobileOpen}
|
|
949
|
+
navItems={navItems}
|
|
950
|
+
logoText="My App"
|
|
951
|
+
logoHref="/"
|
|
952
|
+
/>
|
|
953
|
+
|
|
954
|
+
// Complete header with user nav and theme toggle
|
|
955
|
+
<Header
|
|
956
|
+
title="My Application"
|
|
957
|
+
user={{ name: 'John Doe', email: 'john@example.com' }}
|
|
958
|
+
onLogout={handleLogout}
|
|
959
|
+
setTheme={setTheme}
|
|
960
|
+
extraContent={
|
|
961
|
+
<Button>Custom Button</Button>
|
|
962
|
+
}
|
|
963
|
+
/>
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
#### Date Picker Components
|
|
967
|
+
|
|
968
|
+
Date selection and filtering with URL parameter integration.
|
|
969
|
+
|
|
970
|
+
```tsx
|
|
971
|
+
import { DatePickerWithRange, DateRangeFilter } from 'izen-react-starter';
|
|
972
|
+
|
|
973
|
+
// Date range picker with calendar (3 months view)
|
|
974
|
+
<DatePickerWithRange
|
|
975
|
+
startDate={new Date('2024-01-01')}
|
|
976
|
+
endDate={new Date('2024-01-31')}
|
|
977
|
+
onChange={(from, to) => {
|
|
978
|
+
console.log('Selected range:', from, to);
|
|
979
|
+
// Update your state or make API calls
|
|
980
|
+
}}
|
|
981
|
+
className="my-custom-class"
|
|
982
|
+
/>
|
|
983
|
+
|
|
984
|
+
// Date range filter with URL params (great for tables/reports)
|
|
985
|
+
// Automatically syncs with URL query parameters
|
|
986
|
+
<DateRangeFilter
|
|
987
|
+
startDateParamName="startDate" // URL param name, defaults to 'filterStartDate'
|
|
988
|
+
endDateParamName="endDate" // URL param name, defaults to 'filterEndDate'
|
|
989
|
+
className="mb-4"
|
|
990
|
+
/>
|
|
991
|
+
// URL will be updated to: ?startDate=2024-01-01&endDate=2024-01-31
|
|
992
|
+
// Default range: 2 days ago to 3 days ahead
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
#### Search Components
|
|
996
|
+
|
|
997
|
+
Search input with debouncing and URL parameter integration.
|
|
998
|
+
|
|
999
|
+
```tsx
|
|
1000
|
+
import { TableSearchInput } from 'izen-react-starter';
|
|
1001
|
+
|
|
1002
|
+
// Debounced search input (1 second delay)
|
|
1003
|
+
// Automatically updates URL search params
|
|
1004
|
+
<TableSearchInput
|
|
1005
|
+
placeholder="Search users..."
|
|
1006
|
+
/>
|
|
1007
|
+
// Updates URL to: ?search=query&page=1
|
|
1008
|
+
// Integrates with react-router-dom's useSearchParams
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
#### Common UI Components
|
|
1012
|
+
|
|
1013
|
+
Basic UI building blocks used across the application.
|
|
1014
|
+
|
|
1015
|
+
```tsx
|
|
1016
|
+
import { Heading, PageHead, ThemeToggle, Header } from 'izen-react-starter';
|
|
1017
|
+
|
|
1018
|
+
// Page heading with optional description
|
|
1019
|
+
<Heading
|
|
1020
|
+
title="Dashboard"
|
|
1021
|
+
description="Welcome to your dashboard"
|
|
1022
|
+
className="mb-4"
|
|
1023
|
+
/>
|
|
1024
|
+
|
|
1025
|
+
// Document head/title (uses react-helmet-async)
|
|
1026
|
+
<PageHead title="Dashboard | My App" />
|
|
1027
|
+
|
|
1028
|
+
// Theme toggle dropdown (light/dark/pink/system)
|
|
1029
|
+
<ThemeToggle setTheme={(theme) => {
|
|
1030
|
+
// theme: 'light' | 'dark' | 'pink' | 'system'
|
|
1031
|
+
console.log('Theme changed to:', theme);
|
|
1032
|
+
}} />
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
#### Enhanced Table Components
|
|
1036
|
+
|
|
1037
|
+
Advanced table utilities with server-side features.
|
|
1038
|
+
|
|
1039
|
+
```tsx
|
|
1040
|
+
import {
|
|
1041
|
+
DataTableSkeleton,
|
|
1042
|
+
PaginationSection,
|
|
1043
|
+
ServerDataTable,
|
|
1044
|
+
TableSearchInput
|
|
1045
|
+
} from 'izen-react-starter';
|
|
1046
|
+
|
|
1047
|
+
// Loading skeleton while data is fetching
|
|
1048
|
+
<DataTableSkeleton
|
|
1049
|
+
columnCount={5}
|
|
1050
|
+
rowCount={10}
|
|
1051
|
+
searchableColumnCount={1}
|
|
1052
|
+
filterableColumnCount={2}
|
|
1053
|
+
showViewOptions={true}
|
|
1054
|
+
/>
|
|
1055
|
+
|
|
1056
|
+
// Client-side pagination component
|
|
1057
|
+
<PaginationSection
|
|
1058
|
+
totalPosts={100}
|
|
1059
|
+
postsPerPage={10}
|
|
1060
|
+
currentPage={currentPage}
|
|
1061
|
+
setCurrentPage={setCurrentPage}
|
|
1062
|
+
/>
|
|
1063
|
+
|
|
1064
|
+
// Server-side data table with TanStack Table
|
|
1065
|
+
// Automatically syncs with URL params (?page=1&limit=10)
|
|
1066
|
+
const columns: ColumnDef<User>[] = [
|
|
1067
|
+
{
|
|
1068
|
+
accessorKey: 'name',
|
|
1069
|
+
header: 'Name',
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
accessorKey: 'email',
|
|
1073
|
+
header: 'Email',
|
|
1074
|
+
},
|
|
1075
|
+
];
|
|
1076
|
+
|
|
1077
|
+
<ServerDataTable
|
|
1078
|
+
columns={columns}
|
|
1079
|
+
data={users}
|
|
1080
|
+
pageCount={totalPages}
|
|
1081
|
+
pageSizeOptions={[10, 20, 50, 100]}
|
|
1082
|
+
/>
|
|
1083
|
+
// Features:
|
|
1084
|
+
// - Automatic URL sync (?page=2&limit=20)
|
|
1085
|
+
// - Server-side pagination
|
|
1086
|
+
// - Row selection
|
|
1087
|
+
// - Sorting support
|
|
1088
|
+
// - Custom page size options
|
|
1089
|
+
```
|
|
1090
|
+
|
|
1091
|
+
**Complete Table Example with Search and Filters:**
|
|
1092
|
+
|
|
1093
|
+
```tsx
|
|
1094
|
+
import {
|
|
1095
|
+
ServerDataTable,
|
|
1096
|
+
TableSearchInput,
|
|
1097
|
+
DateRangeFilter,
|
|
1098
|
+
DataTableSkeleton
|
|
1099
|
+
} from 'izen-react-starter';
|
|
1100
|
+
|
|
1101
|
+
function UsersTable() {
|
|
1102
|
+
const { data, isLoading } = useQuery({
|
|
1103
|
+
queryKey: ['users', searchParams.toString()],
|
|
1104
|
+
queryFn: () => fetchUsers(searchParams)
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
if (isLoading) {
|
|
1108
|
+
return <DataTableSkeleton columnCount={4} />;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
return (
|
|
1112
|
+
<div>
|
|
1113
|
+
{/* Search and filters */}
|
|
1114
|
+
<div className="flex gap-4 mb-4">
|
|
1115
|
+
<TableSearchInput placeholder="Search users..." />
|
|
1116
|
+
<DateRangeFilter />
|
|
1117
|
+
</div>
|
|
1118
|
+
|
|
1119
|
+
{/* Data table */}
|
|
1120
|
+
<ServerDataTable
|
|
1121
|
+
columns={columns}
|
|
1122
|
+
data={data.users}
|
|
1123
|
+
pageCount={data.totalPages}
|
|
1124
|
+
/>
|
|
1125
|
+
</div>
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
### Form Components
|
|
1131
|
+
|
|
1132
|
+
The library provides a complete set of form components that are library-ready without tight coupling to app-specific contexts.
|
|
1133
|
+
|
|
1134
|
+
#### FileUploadButton
|
|
1135
|
+
|
|
1136
|
+
Flexible file upload button with validation:
|
|
1137
|
+
|
|
1138
|
+
```tsx
|
|
1139
|
+
import { FileUploadButton } from 'izen-react-starter';
|
|
1140
|
+
|
|
1141
|
+
<FileUploadButton
|
|
1142
|
+
title="Upload File"
|
|
1143
|
+
name="document"
|
|
1144
|
+
accept={{
|
|
1145
|
+
'application/pdf': ['.pdf'],
|
|
1146
|
+
'image/*': ['.png', '.jpg', '.jpeg']
|
|
1147
|
+
}}
|
|
1148
|
+
maxSize={5 * 1024 * 1024} // 5MB
|
|
1149
|
+
disabled={false}
|
|
1150
|
+
onValidationError={(error) => {
|
|
1151
|
+
console.error('Validation error:', error);
|
|
1152
|
+
// Show toast or alert
|
|
1153
|
+
}}
|
|
1154
|
+
onSuccess={(file) => {
|
|
1155
|
+
console.log('File uploaded:', file);
|
|
1156
|
+
// Handle file upload
|
|
1157
|
+
}}
|
|
1158
|
+
className="my-4"
|
|
1159
|
+
/>
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
#### DatePicker
|
|
1163
|
+
|
|
1164
|
+
Calendar-based date picker with popover:
|
|
1165
|
+
|
|
1166
|
+
```tsx
|
|
1167
|
+
import { DatePicker } from 'izen-react-starter';
|
|
1168
|
+
|
|
1169
|
+
<DatePicker
|
|
1170
|
+
title="Select Date"
|
|
1171
|
+
name="eventDate"
|
|
1172
|
+
value={selectedDate}
|
|
1173
|
+
onChange={(date) => setSelectedDate(date)}
|
|
1174
|
+
placeholder="Pick a date"
|
|
1175
|
+
error={errors.eventDate}
|
|
1176
|
+
disabled={false}
|
|
1177
|
+
/>
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
#### TimeInput
|
|
1181
|
+
|
|
1182
|
+
Time input with hours, minutes, and optional seconds:
|
|
1183
|
+
|
|
1184
|
+
```tsx
|
|
1185
|
+
import { TimeInput } from 'izen-react-starter';
|
|
1186
|
+
|
|
1187
|
+
<TimeInput
|
|
1188
|
+
title="Event Time"
|
|
1189
|
+
name="startTime"
|
|
1190
|
+
value="14:30"
|
|
1191
|
+
onChange={(time) => console.log('Time:', time)}
|
|
1192
|
+
showSeconds={false}
|
|
1193
|
+
error={errors.startTime}
|
|
1194
|
+
disabled={false}
|
|
1195
|
+
/>
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
#### TextInput
|
|
1199
|
+
|
|
1200
|
+
Versatile text input supporting multiple types and textarea:
|
|
1201
|
+
|
|
1202
|
+
```tsx
|
|
1203
|
+
import { TextInput } from 'izen-react-starter';
|
|
1204
|
+
import { Mail, Lock } from 'lucide-react';
|
|
1205
|
+
|
|
1206
|
+
// Text input with icon
|
|
1207
|
+
<TextInput
|
|
1208
|
+
title="Email"
|
|
1209
|
+
name="email"
|
|
1210
|
+
type="email"
|
|
1211
|
+
icon={<Mail />}
|
|
1212
|
+
placeholder="Enter your email"
|
|
1213
|
+
error={errors.email}
|
|
1214
|
+
/>
|
|
1215
|
+
|
|
1216
|
+
// Password input
|
|
1217
|
+
<TextInput
|
|
1218
|
+
title="Password"
|
|
1219
|
+
name="password"
|
|
1220
|
+
type="password"
|
|
1221
|
+
icon={<Lock />}
|
|
1222
|
+
placeholder="Enter password"
|
|
1223
|
+
error={errors.password}
|
|
1224
|
+
/>
|
|
1225
|
+
|
|
1226
|
+
// Textarea
|
|
1227
|
+
<TextInput
|
|
1228
|
+
title="Description"
|
|
1229
|
+
name="description"
|
|
1230
|
+
type="textarea"
|
|
1231
|
+
rows={5}
|
|
1232
|
+
placeholder="Enter description"
|
|
1233
|
+
error={errors.description}
|
|
1234
|
+
/>
|
|
1235
|
+
|
|
1236
|
+
// Number input
|
|
1237
|
+
<TextInput
|
|
1238
|
+
title="Age"
|
|
1239
|
+
name="age"
|
|
1240
|
+
type="number"
|
|
1241
|
+
min={0}
|
|
1242
|
+
max={120}
|
|
1243
|
+
placeholder="Enter age"
|
|
1244
|
+
/>
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
#### CheckboxGroup
|
|
1248
|
+
|
|
1249
|
+
Checkbox input supporting single or multiple items:
|
|
1250
|
+
|
|
1251
|
+
```tsx
|
|
1252
|
+
import { CheckboxGroup } from 'izen-react-starter';
|
|
1253
|
+
|
|
1254
|
+
// Single checkbox
|
|
1255
|
+
<CheckboxGroup
|
|
1256
|
+
title="Accept Terms"
|
|
1257
|
+
name="terms"
|
|
1258
|
+
items={[
|
|
1259
|
+
{ id: 'terms', name: 'terms', displayName: 'I accept the terms and conditions' }
|
|
1260
|
+
]}
|
|
1261
|
+
error={errors.terms}
|
|
1262
|
+
/>
|
|
1263
|
+
|
|
1264
|
+
// Multiple checkboxes
|
|
1265
|
+
<CheckboxGroup
|
|
1266
|
+
title="Select Features"
|
|
1267
|
+
name="features"
|
|
1268
|
+
items={[
|
|
1269
|
+
{ id: 'feature1', name: 'features', displayName: 'Email Notifications', checked: true },
|
|
1270
|
+
{ id: 'feature2', name: 'features', displayName: 'SMS Alerts', checked: false },
|
|
1271
|
+
{ id: 'feature3', name: 'features', displayName: 'Push Notifications', checked: true },
|
|
1272
|
+
]}
|
|
1273
|
+
onChange={(e) => {
|
|
1274
|
+
const checked = e.target.checked;
|
|
1275
|
+
const id = e.target.id;
|
|
1276
|
+
console.log(`Checkbox ${id} is ${checked ? 'checked' : 'unchecked'}`);
|
|
1277
|
+
}}
|
|
1278
|
+
/>
|
|
1279
|
+
```
|
|
1280
|
+
|
|
1281
|
+
#### RadioGroup
|
|
1282
|
+
|
|
1283
|
+
Radio button group with horizontal or vertical layout:
|
|
1284
|
+
|
|
1285
|
+
```tsx
|
|
1286
|
+
import { RadioGroup } from 'izen-react-starter';
|
|
1287
|
+
|
|
1288
|
+
// Horizontal layout
|
|
1289
|
+
<RadioGroup
|
|
1290
|
+
title="Select Plan"
|
|
1291
|
+
name="plan"
|
|
1292
|
+
items={[
|
|
1293
|
+
{ value: 'free', title: 'Free Plan' },
|
|
1294
|
+
{ value: 'pro', title: 'Pro Plan' },
|
|
1295
|
+
{ value: 'enterprise', title: 'Enterprise Plan' },
|
|
1296
|
+
]}
|
|
1297
|
+
onChange={(e) => console.log('Selected:', e.target.value)}
|
|
1298
|
+
error={errors.plan}
|
|
1299
|
+
/>
|
|
1300
|
+
|
|
1301
|
+
// Vertical layout
|
|
1302
|
+
<RadioGroup
|
|
1303
|
+
title="Notification Preference"
|
|
1304
|
+
name="notifications"
|
|
1305
|
+
vertical={true}
|
|
1306
|
+
items={[
|
|
1307
|
+
{ value: 'all', title: 'All Notifications' },
|
|
1308
|
+
{ value: 'important', title: 'Important Only' },
|
|
1309
|
+
{ value: 'none', title: 'None' },
|
|
1310
|
+
]}
|
|
1311
|
+
onChange={(e) => setNotificationPref(e.target.value)}
|
|
1312
|
+
/>
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
**Complete Form Example:**
|
|
1316
|
+
|
|
1317
|
+
```tsx
|
|
1318
|
+
import {
|
|
1319
|
+
TextInput,
|
|
1320
|
+
DatePicker,
|
|
1321
|
+
TimeInput,
|
|
1322
|
+
CheckboxGroup,
|
|
1323
|
+
RadioGroup,
|
|
1324
|
+
FileUploadButton
|
|
1325
|
+
} from 'izen-react-starter';
|
|
1326
|
+
import { useState } from 'react';
|
|
1327
|
+
|
|
1328
|
+
function EventForm() {
|
|
1329
|
+
const [formData, setFormData] = useState({
|
|
1330
|
+
name: '',
|
|
1331
|
+
date: undefined,
|
|
1332
|
+
time: '09:00',
|
|
1333
|
+
type: 'public',
|
|
1334
|
+
features: [],
|
|
1335
|
+
document: null
|
|
1336
|
+
});
|
|
1337
|
+
|
|
1338
|
+
const [errors, setErrors] = useState({});
|
|
1339
|
+
|
|
1340
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
1341
|
+
e.preventDefault();
|
|
1342
|
+
console.log('Form data:', formData);
|
|
1343
|
+
};
|
|
1344
|
+
|
|
1345
|
+
return (
|
|
1346
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
1347
|
+
<TextInput
|
|
1348
|
+
title="Event Name"
|
|
1349
|
+
name="name"
|
|
1350
|
+
value={formData.name}
|
|
1351
|
+
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
1352
|
+
placeholder="Enter event name"
|
|
1353
|
+
error={errors.name}
|
|
1354
|
+
/>
|
|
1355
|
+
|
|
1356
|
+
<DatePicker
|
|
1357
|
+
title="Event Date"
|
|
1358
|
+
name="date"
|
|
1359
|
+
value={formData.date}
|
|
1360
|
+
onChange={(date) => setFormData({ ...formData, date })}
|
|
1361
|
+
error={errors.date}
|
|
1362
|
+
/>
|
|
1363
|
+
|
|
1364
|
+
<TimeInput
|
|
1365
|
+
title="Start Time"
|
|
1366
|
+
name="time"
|
|
1367
|
+
value={formData.time}
|
|
1368
|
+
onChange={(time) => setFormData({ ...formData, time })}
|
|
1369
|
+
error={errors.time}
|
|
1370
|
+
/>
|
|
1371
|
+
|
|
1372
|
+
<RadioGroup
|
|
1373
|
+
title="Event Type"
|
|
1374
|
+
name="type"
|
|
1375
|
+
items={[
|
|
1376
|
+
{ value: 'public', title: 'Public Event' },
|
|
1377
|
+
{ value: 'private', title: 'Private Event' },
|
|
1378
|
+
]}
|
|
1379
|
+
onChange={(e) => setFormData({ ...formData, type: e.target.value })}
|
|
1380
|
+
/>
|
|
1381
|
+
|
|
1382
|
+
<CheckboxGroup
|
|
1383
|
+
title="Event Features"
|
|
1384
|
+
name="features"
|
|
1385
|
+
items={[
|
|
1386
|
+
{ id: 'catering', name: 'features', displayName: 'Catering' },
|
|
1387
|
+
{ id: 'parking', name: 'features', displayName: 'Parking' },
|
|
1388
|
+
{ id: 'wifi', name: 'features', displayName: 'WiFi' },
|
|
1389
|
+
]}
|
|
1390
|
+
/>
|
|
1391
|
+
|
|
1392
|
+
<FileUploadButton
|
|
1393
|
+
title="Event Document"
|
|
1394
|
+
name="document"
|
|
1395
|
+
accept={{ 'application/pdf': ['.pdf'] }}
|
|
1396
|
+
onSuccess={(file) => setFormData({ ...formData, document: file })}
|
|
1397
|
+
onValidationError={(error) => setErrors({ ...errors, document: error })}
|
|
1398
|
+
/>
|
|
1399
|
+
|
|
1400
|
+
<button type="submit" className="btn btn-primary">
|
|
1401
|
+
Create Event
|
|
1402
|
+
</button>
|
|
1403
|
+
</form>
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
```
|
|
1407
|
+
|
|
1408
|
+
#### FormInput
|
|
1409
|
+
|
|
1410
|
+
Enhanced input component with card number formatting and date display:
|
|
1411
|
+
|
|
1412
|
+
```tsx
|
|
1413
|
+
import { FormInput } from 'izen-react-starter';
|
|
1414
|
+
import { User, Mail, CreditCard } from 'lucide-react';
|
|
1415
|
+
|
|
1416
|
+
// Text input with icon
|
|
1417
|
+
<FormInput
|
|
1418
|
+
title="Full Name"
|
|
1419
|
+
name="fullName"
|
|
1420
|
+
type="text"
|
|
1421
|
+
icon={<User />}
|
|
1422
|
+
placeholder="Enter your name"
|
|
1423
|
+
value={name}
|
|
1424
|
+
onValueChange={(value) => setName(value)}
|
|
1425
|
+
error={errors.name}
|
|
1426
|
+
/>
|
|
1427
|
+
|
|
1428
|
+
// Card number with auto-formatting
|
|
1429
|
+
<FormInput
|
|
1430
|
+
title="Card Number"
|
|
1431
|
+
name="cardNumber"
|
|
1432
|
+
type="cardNumber"
|
|
1433
|
+
icon={<CreditCard />}
|
|
1434
|
+
placeholder="0000 0000 0000 0000"
|
|
1435
|
+
value={cardNumber}
|
|
1436
|
+
onValueChange={(value) => setCardNumber(value)}
|
|
1437
|
+
/>
|
|
1438
|
+
|
|
1439
|
+
// Date input with formatted label
|
|
1440
|
+
<FormInput
|
|
1441
|
+
title="Birth Date"
|
|
1442
|
+
name="birthDate"
|
|
1443
|
+
type="date"
|
|
1444
|
+
value={birthDate}
|
|
1445
|
+
onChange={(e) => setBirthDate(e.target.value)}
|
|
1446
|
+
showDateLabel={true} // Shows formatted date like "(Jan 15)"
|
|
1447
|
+
/>
|
|
1448
|
+
|
|
1449
|
+
// Textarea
|
|
1450
|
+
<FormInput
|
|
1451
|
+
title="Comments"
|
|
1452
|
+
name="comments"
|
|
1453
|
+
type="textarea"
|
|
1454
|
+
rows={4}
|
|
1455
|
+
placeholder="Enter your comments"
|
|
1456
|
+
value={comments}
|
|
1457
|
+
onValueChange={(value) => setComments(value)}
|
|
1458
|
+
/>
|
|
1459
|
+
```
|
|
1460
|
+
|
|
1461
|
+
#### FormSelect
|
|
1462
|
+
|
|
1463
|
+
Standard dropdown select component:
|
|
1464
|
+
|
|
1465
|
+
> **Note:** This component is exported as `FormSelect` to avoid naming conflict with shadcn/ui's `Select` component.
|
|
1466
|
+
|
|
1467
|
+
```tsx
|
|
1468
|
+
import { FormSelect } from 'izen-react-starter';
|
|
1469
|
+
|
|
1470
|
+
<FormSelect
|
|
1471
|
+
title="Country"
|
|
1472
|
+
name="country"
|
|
1473
|
+
placeholder="Select country"
|
|
1474
|
+
value={country}
|
|
1475
|
+
options={[
|
|
1476
|
+
{ value: 'us', label: 'United States' },
|
|
1477
|
+
{ value: 'uk', label: 'United Kingdom' },
|
|
1478
|
+
{ value: 'ca', label: 'Canada' },
|
|
1479
|
+
]}
|
|
1480
|
+
onChange={(value) => setCountry(value)}
|
|
1481
|
+
error={errors.country}
|
|
1482
|
+
/>
|
|
1483
|
+
|
|
1484
|
+
// With "Please Select" option
|
|
1485
|
+
<FormSelect
|
|
1486
|
+
title="Category"
|
|
1487
|
+
name="category"
|
|
1488
|
+
showOtherOption={true}
|
|
1489
|
+
otherOptionLabel="Please Select"
|
|
1490
|
+
options={categories}
|
|
1491
|
+
onChange={(value) => setCategory(value)}
|
|
1492
|
+
/>
|
|
1493
|
+
```
|
|
1494
|
+
|
|
1495
|
+
#### ComboboxSelect
|
|
1496
|
+
|
|
1497
|
+
Advanced searchable select with Command palette:
|
|
1498
|
+
|
|
1499
|
+
```tsx
|
|
1500
|
+
import { ComboboxSelect } from 'izen-react-starter';
|
|
1501
|
+
import { Building } from 'lucide-react';
|
|
1502
|
+
|
|
1503
|
+
<ComboboxSelect
|
|
1504
|
+
title="Company"
|
|
1505
|
+
name="company"
|
|
1506
|
+
icon={<Building />}
|
|
1507
|
+
placeholder="Search companies..."
|
|
1508
|
+
value={selectedCompany}
|
|
1509
|
+
options={companies}
|
|
1510
|
+
onChange={(value) => setSelectedCompany(value)}
|
|
1511
|
+
onSearch={(searchTerm) => {
|
|
1512
|
+
// Trigger API call to search companies
|
|
1513
|
+
fetchCompanies(searchTerm);
|
|
1514
|
+
}}
|
|
1515
|
+
showOtherOption={true}
|
|
1516
|
+
otherOptionLabel="No Company"
|
|
1517
|
+
emptyMessage="No companies found."
|
|
1518
|
+
error={errors.company}
|
|
1519
|
+
/>
|
|
1520
|
+
```
|
|
1521
|
+
|
|
1522
|
+
**Features:**
|
|
1523
|
+
- Searchable with Command palette UI
|
|
1524
|
+
- Toggle selection (click again to deselect)
|
|
1525
|
+
- Optional "other" option
|
|
1526
|
+
- Custom empty state message
|
|
1527
|
+
- Search callback for dynamic loading
|
|
1528
|
+
|
|
1529
|
+
#### FormButtons
|
|
1530
|
+
|
|
1531
|
+
Reusable form action buttons:
|
|
1532
|
+
|
|
1533
|
+
```tsx
|
|
1534
|
+
import { FormButtons } from 'izen-react-starter';
|
|
1535
|
+
|
|
1536
|
+
<FormButtons
|
|
1537
|
+
loading={isSubmitting}
|
|
1538
|
+
showSubmit={true}
|
|
1539
|
+
showCancel={true}
|
|
1540
|
+
showReset={true}
|
|
1541
|
+
submitText="Save"
|
|
1542
|
+
cancelText="Cancel"
|
|
1543
|
+
resetText="Clear"
|
|
1544
|
+
onCancel={() => router.back()}
|
|
1545
|
+
onReset={() => form.reset()}
|
|
1546
|
+
onSubmit={() => form.handleSubmit(onSubmit)()}
|
|
1547
|
+
/>
|
|
1548
|
+
```
|
|
1549
|
+
|
|
1550
|
+
**Props:**
|
|
1551
|
+
- `loading`: Shows "Please wait..." text
|
|
1552
|
+
- `showSubmit/showCancel/showReset`: Toggle button visibility
|
|
1553
|
+
- `submitText/cancelText/resetText`: Custom button labels
|
|
1554
|
+
- `onCancel/onReset/onSubmit`: Click handlers
|
|
1555
|
+
|
|
1556
|
+
#### FormLayout
|
|
1557
|
+
|
|
1558
|
+
Complete form wrapper with error display and action buttons:
|
|
1559
|
+
|
|
1560
|
+
```tsx
|
|
1561
|
+
import { FormLayout, FormInput, FormSelect } from 'izen-react-starter';
|
|
1562
|
+
import { useState } from 'react';
|
|
1563
|
+
|
|
1564
|
+
function CreateUser() {
|
|
1565
|
+
const [loading, setLoading] = useState(false);
|
|
1566
|
+
const [error, setError] = useState('');
|
|
1567
|
+
|
|
1568
|
+
const handleSubmit = async (data: any) => {
|
|
1569
|
+
setLoading(true);
|
|
1570
|
+
setError('');
|
|
1571
|
+
|
|
1572
|
+
try {
|
|
1573
|
+
await createUser(data);
|
|
1574
|
+
router.push('/users');
|
|
1575
|
+
} catch (err) {
|
|
1576
|
+
setError(err.message);
|
|
1577
|
+
} finally {
|
|
1578
|
+
setLoading(false);
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
|
|
1582
|
+
return (
|
|
1583
|
+
<FormLayout
|
|
1584
|
+
onSubmit={handleSubmit}
|
|
1585
|
+
error={error}
|
|
1586
|
+
loading={loading}
|
|
1587
|
+
showSubmit={true}
|
|
1588
|
+
showCancel={true}
|
|
1589
|
+
showReset={true}
|
|
1590
|
+
submitText="Create User"
|
|
1591
|
+
onCancel={() => router.back()}
|
|
1592
|
+
onReset={() => {
|
|
1593
|
+
// Reset form logic
|
|
1594
|
+
}}
|
|
1595
|
+
fullHeight={false}
|
|
1596
|
+
>
|
|
1597
|
+
<FormInput
|
|
1598
|
+
title="Name"
|
|
1599
|
+
name="name"
|
|
1600
|
+
placeholder="Enter name"
|
|
1601
|
+
/>
|
|
1602
|
+
|
|
1603
|
+
<FormInput
|
|
1604
|
+
title="Email"
|
|
1605
|
+
name="email"
|
|
1606
|
+
type="email"
|
|
1607
|
+
placeholder="Enter email"
|
|
1608
|
+
/>
|
|
1609
|
+
|
|
1610
|
+
<FormSelect
|
|
1611
|
+
title="Role"
|
|
1612
|
+
name="role"
|
|
1613
|
+
options={[
|
|
1614
|
+
{ value: 'admin', label: 'Admin' },
|
|
1615
|
+
{ value: 'user', label: 'User' },
|
|
1616
|
+
]}
|
|
1617
|
+
/>
|
|
1618
|
+
</FormLayout>
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
```
|
|
1622
|
+
|
|
1623
|
+
**Features:**
|
|
1624
|
+
- Automatic form submission handling
|
|
1625
|
+
- Error display with Alert component
|
|
1626
|
+
- Integrated FormButtons
|
|
1627
|
+
- Card wrapper with styling
|
|
1628
|
+
- Loading state management
|
|
1629
|
+
- Sticky button footer
|
|
1630
|
+
|
|
1631
|
+
**Complete Advanced Form Example:**
|
|
1632
|
+
|
|
1633
|
+
```tsx
|
|
1634
|
+
import {
|
|
1635
|
+
FormLayout,
|
|
1636
|
+
FormInput,
|
|
1637
|
+
Select,
|
|
1638
|
+
ComboboxSelect,
|
|
1639
|
+
DatePicker,
|
|
1640
|
+
TimeInput,
|
|
1641
|
+
CheckboxGroup,
|
|
1642
|
+
RadioGroup,
|
|
1643
|
+
FileUploadButton
|
|
1644
|
+
} from 'izen-react-starter';
|
|
1645
|
+
import { useState } from 'react';
|
|
1646
|
+
|
|
1647
|
+
function AdvancedForm() {
|
|
1648
|
+
const [loading, setLoading] = useState(false);
|
|
1649
|
+
const [error, setError] = useState('');
|
|
1650
|
+
const [formData, setFormData] = useState({
|
|
1651
|
+
name: '',
|
|
1652
|
+
email: '',
|
|
1653
|
+
cardNumber: '',
|
|
1654
|
+
country: '',
|
|
1655
|
+
company: '',
|
|
1656
|
+
eventDate: undefined,
|
|
1657
|
+
startTime: '09:00',
|
|
1658
|
+
plan: 'free',
|
|
1659
|
+
features: [],
|
|
1660
|
+
document: null
|
|
1661
|
+
});
|
|
1662
|
+
|
|
1663
|
+
const handleSubmit = async (data: any) => {
|
|
1664
|
+
setLoading(true);
|
|
1665
|
+
try {
|
|
1666
|
+
// Process form data
|
|
1667
|
+
await submitForm({ ...formData, ...data });
|
|
1668
|
+
} catch (err) {
|
|
1669
|
+
setError(err.message);
|
|
1670
|
+
} finally {
|
|
1671
|
+
setLoading(false);
|
|
1672
|
+
}
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
return (
|
|
1676
|
+
<FormLayout
|
|
1677
|
+
onSubmit={handleSubmit}
|
|
1678
|
+
error={error}
|
|
1679
|
+
loading={loading}
|
|
1680
|
+
submitText="Submit Registration"
|
|
1681
|
+
fullHeight={false}
|
|
1682
|
+
>
|
|
1683
|
+
<div className="grid grid-cols-2 gap-4">
|
|
1684
|
+
<FormInput
|
|
1685
|
+
title="Full Name"
|
|
1686
|
+
name="name"
|
|
1687
|
+
placeholder="John Doe"
|
|
1688
|
+
value={formData.name}
|
|
1689
|
+
onValueChange={(value) => setFormData({ ...formData, name: value })}
|
|
1690
|
+
/>
|
|
1691
|
+
|
|
1692
|
+
<FormInput
|
|
1693
|
+
title="Email"
|
|
1694
|
+
name="email"
|
|
1695
|
+
type="email"
|
|
1696
|
+
placeholder="john@example.com"
|
|
1697
|
+
value={formData.email}
|
|
1698
|
+
onValueChange={(value) => setFormData({ ...formData, email: value })}
|
|
1699
|
+
/>
|
|
1700
|
+
</div>
|
|
1701
|
+
|
|
1702
|
+
<FormInput
|
|
1703
|
+
title="Card Number"
|
|
1704
|
+
name="cardNumber"
|
|
1705
|
+
type="cardNumber"
|
|
1706
|
+
placeholder="0000 0000 0000 0000"
|
|
1707
|
+
value={formData.cardNumber}
|
|
1708
|
+
onValueChange={(value) => setFormData({ ...formData, cardNumber: value })}
|
|
1709
|
+
/>
|
|
1710
|
+
|
|
1711
|
+
<FormSelect
|
|
1712
|
+
title="Country"
|
|
1713
|
+
name="country"
|
|
1714
|
+
placeholder="Select country"
|
|
1715
|
+
value={formData.country}
|
|
1716
|
+
options={countries}
|
|
1717
|
+
onChange={(value) => setFormData({ ...formData, country: value })}
|
|
1718
|
+
/>
|
|
1719
|
+
|
|
1720
|
+
<ComboboxSelect
|
|
1721
|
+
title="Company"
|
|
1722
|
+
name="company"
|
|
1723
|
+
placeholder="Search companies..."
|
|
1724
|
+
value={formData.company}
|
|
1725
|
+
options={companies}
|
|
1726
|
+
onChange={(value) => setFormData({ ...formData, company: value })}
|
|
1727
|
+
onSearch={(term) => searchCompanies(term)}
|
|
1728
|
+
/>
|
|
1729
|
+
|
|
1730
|
+
<div className="grid grid-cols-2 gap-4">
|
|
1731
|
+
<DatePicker
|
|
1732
|
+
title="Event Date"
|
|
1733
|
+
name="eventDate"
|
|
1734
|
+
value={formData.eventDate}
|
|
1735
|
+
onChange={(date) => setFormData({ ...formData, eventDate: date })}
|
|
1736
|
+
/>
|
|
1737
|
+
|
|
1738
|
+
<TimeInput
|
|
1739
|
+
title="Start Time"
|
|
1740
|
+
name="startTime"
|
|
1741
|
+
value={formData.startTime}
|
|
1742
|
+
onChange={(time) => setFormData({ ...formData, startTime: time })}
|
|
1743
|
+
/>
|
|
1744
|
+
</div>
|
|
1745
|
+
|
|
1746
|
+
<RadioGroup
|
|
1747
|
+
title="Subscription Plan"
|
|
1748
|
+
name="plan"
|
|
1749
|
+
items={[
|
|
1750
|
+
{ value: 'free', title: 'Free' },
|
|
1751
|
+
{ value: 'pro', title: 'Pro' },
|
|
1752
|
+
{ value: 'enterprise', title: 'Enterprise' },
|
|
1753
|
+
]}
|
|
1754
|
+
onChange={(e) => setFormData({ ...formData, plan: e.target.value })}
|
|
1755
|
+
/>
|
|
1756
|
+
|
|
1757
|
+
<CheckboxGroup
|
|
1758
|
+
title="Features"
|
|
1759
|
+
name="features"
|
|
1760
|
+
items={[
|
|
1761
|
+
{ id: 'email', name: 'features', displayName: 'Email Notifications' },
|
|
1762
|
+
{ id: 'sms', name: 'features', displayName: 'SMS Alerts' },
|
|
1763
|
+
{ id: 'push', name: 'features', displayName: 'Push Notifications' },
|
|
1764
|
+
]}
|
|
1765
|
+
/>
|
|
1766
|
+
|
|
1767
|
+
<FileUploadButton
|
|
1768
|
+
title="Upload Document"
|
|
1769
|
+
name="document"
|
|
1770
|
+
accept={{ 'application/pdf': ['.pdf'] }}
|
|
1771
|
+
maxSize={5 * 1024 * 1024}
|
|
1772
|
+
onSuccess={(file) => setFormData({ ...formData, document: file })}
|
|
1773
|
+
/>
|
|
1774
|
+
</FormLayout>
|
|
1775
|
+
);
|
|
1776
|
+
}
|
|
1777
|
+
```
|
|
552
1778
|
|
|
553
1779
|
### RBAC System
|
|
554
1780
|
|