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.
Files changed (127) hide show
  1. package/README.md +1275 -49
  2. package/dist/{MIMHJGAX-CX0R0gR-.js → MIMHJGAX-DM3PPc6i.js} +1 -1
  3. package/dist/{Q7LWSL4U-DisRfAmB.js → Q7LWSL4U-Dp8mxbtM.js} +2 -2
  4. package/dist/{VLTTJS3N-hByn9hgE.js → VLTTJS3N-Dfn6o7Pv.js} +2 -2
  5. package/dist/components/charts/ChartAreaInteractive.d.ts +2 -0
  6. package/dist/components/charts/ChartAreaInteractive.d.ts.map +1 -0
  7. package/dist/components/charts/index.d.ts +2 -0
  8. package/dist/components/charts/index.d.ts.map +1 -0
  9. package/dist/components/common/Header.d.ts +13 -0
  10. package/dist/components/common/Header.d.ts.map +1 -0
  11. package/dist/components/common/Heading.d.ts +7 -0
  12. package/dist/components/common/Heading.d.ts.map +1 -0
  13. package/dist/components/common/PageHead.d.ts +5 -0
  14. package/dist/components/common/PageHead.d.ts.map +1 -0
  15. package/dist/components/common/ThemeToggle.d.ts +5 -0
  16. package/dist/components/common/ThemeToggle.d.ts.map +1 -0
  17. package/dist/components/common/index.d.ts +5 -0
  18. package/dist/components/common/index.d.ts.map +1 -0
  19. package/dist/components/date-picker/DatePickerWithRange.d.ts +8 -0
  20. package/dist/components/date-picker/DatePickerWithRange.d.ts.map +1 -0
  21. package/dist/components/date-picker/DateRangeFilter.d.ts +7 -0
  22. package/dist/components/date-picker/DateRangeFilter.d.ts.map +1 -0
  23. package/dist/components/date-picker/index.d.ts +3 -0
  24. package/dist/components/date-picker/index.d.ts.map +1 -0
  25. package/dist/components/form/CheckboxGroup.d.ts +15 -0
  26. package/dist/components/form/CheckboxGroup.d.ts.map +1 -0
  27. package/dist/components/form/ComboboxSelect.d.ts +24 -0
  28. package/dist/components/form/ComboboxSelect.d.ts.map +1 -0
  29. package/dist/components/form/DatePicker.d.ts +14 -0
  30. package/dist/components/form/DatePicker.d.ts.map +1 -0
  31. package/dist/components/form/FileUploadButton.d.ts +19 -0
  32. package/dist/components/form/FileUploadButton.d.ts.map +1 -0
  33. package/dist/components/form/FormButtons.d.ts +19 -0
  34. package/dist/components/form/FormButtons.d.ts.map +1 -0
  35. package/dist/components/form/FormInput.d.ts +15 -0
  36. package/dist/components/form/FormInput.d.ts.map +1 -0
  37. package/dist/components/form/FormLayout.d.ts +21 -0
  38. package/dist/components/form/FormLayout.d.ts.map +1 -0
  39. package/dist/components/form/RadioGroup.d.ts +14 -0
  40. package/dist/components/form/RadioGroup.d.ts.map +1 -0
  41. package/dist/components/form/Select.d.ts +21 -0
  42. package/dist/components/form/Select.d.ts.map +1 -0
  43. package/dist/components/form/TextInput.d.ts +13 -0
  44. package/dist/components/form/TextInput.d.ts.map +1 -0
  45. package/dist/components/form/TimeInput.d.ts +13 -0
  46. package/dist/components/form/TimeInput.d.ts.map +1 -0
  47. package/dist/components/form/index.d.ts +23 -0
  48. package/dist/components/form/index.d.ts.map +1 -0
  49. package/dist/components/layout/AppSidebar.d.ts +24 -0
  50. package/dist/components/layout/AppSidebar.d.ts.map +1 -0
  51. package/dist/components/layout/DashboardLayout.d.ts +12 -0
  52. package/dist/components/layout/DashboardLayout.d.ts.map +1 -0
  53. package/dist/components/layout/NavDocuments.d.ts +11 -0
  54. package/dist/components/layout/NavDocuments.d.ts.map +1 -0
  55. package/dist/components/layout/NavMain.d.ts +24 -0
  56. package/dist/components/layout/NavMain.d.ts.map +1 -0
  57. package/dist/components/layout/NavSecondary.d.ts +14 -0
  58. package/dist/components/layout/NavSecondary.d.ts.map +1 -0
  59. package/dist/components/layout/NavUser.d.ts +18 -0
  60. package/dist/components/layout/NavUser.d.ts.map +1 -0
  61. package/dist/components/layout/SiteHeader.d.ts +7 -0
  62. package/dist/components/layout/SiteHeader.d.ts.map +1 -0
  63. package/dist/components/layout/index.d.ts +8 -0
  64. package/dist/components/layout/index.d.ts.map +1 -0
  65. package/dist/components/modals/AlertModal.d.ts +10 -0
  66. package/dist/components/modals/AlertModal.d.ts.map +1 -0
  67. package/dist/components/modals/DeleteDialog.d.ts +7 -0
  68. package/dist/components/modals/DeleteDialog.d.ts.map +1 -0
  69. package/dist/components/modals/PopupModal.d.ts +16 -0
  70. package/dist/components/modals/PopupModal.d.ts.map +1 -0
  71. package/dist/components/modals/index.d.ts +4 -0
  72. package/dist/components/modals/index.d.ts.map +1 -0
  73. package/dist/components/navigation/DashboardNav.d.ts +18 -0
  74. package/dist/components/navigation/DashboardNav.d.ts.map +1 -0
  75. package/dist/components/navigation/MobileSidebar.d.ts +12 -0
  76. package/dist/components/navigation/MobileSidebar.d.ts.map +1 -0
  77. package/dist/components/navigation/Sidebar.d.ts +8 -0
  78. package/dist/components/navigation/Sidebar.d.ts.map +1 -0
  79. package/dist/components/navigation/UserNav.d.ts +10 -0
  80. package/dist/components/navigation/UserNav.d.ts.map +1 -0
  81. package/dist/components/navigation/index.d.ts +5 -0
  82. package/dist/components/navigation/index.d.ts.map +1 -0
  83. package/dist/components/overlay/Overlay.d.ts +5 -0
  84. package/dist/components/overlay/Overlay.d.ts.map +1 -0
  85. package/dist/components/overlay/index.d.ts +2 -0
  86. package/dist/components/overlay/index.d.ts.map +1 -0
  87. package/dist/components/search/TableSearchInput.d.ts +5 -0
  88. package/dist/components/search/TableSearchInput.d.ts.map +1 -0
  89. package/dist/components/search/index.d.ts +2 -0
  90. package/dist/components/search/index.d.ts.map +1 -0
  91. package/dist/components/table/DataTable.d.ts +14 -0
  92. package/dist/components/table/DataTable.d.ts.map +1 -0
  93. package/dist/components/table/DataTableSkeleton.d.ts +9 -0
  94. package/dist/components/table/DataTableSkeleton.d.ts.map +1 -0
  95. package/dist/components/table/Pagination.d.ts +7 -0
  96. package/dist/components/table/Pagination.d.ts.map +1 -0
  97. package/dist/components/table/PaginationSection.d.ts +8 -0
  98. package/dist/components/table/PaginationSection.d.ts.map +1 -0
  99. package/dist/components/table/ServerDataTable.d.ts +10 -0
  100. package/dist/components/table/ServerDataTable.d.ts.map +1 -0
  101. package/dist/components/table/SpecialDaysTable.d.ts +26 -0
  102. package/dist/components/table/SpecialDaysTable.d.ts.map +1 -0
  103. package/dist/components/table/Table.d.ts +28 -0
  104. package/dist/components/table/Table.d.ts.map +1 -0
  105. package/dist/components/table/TableActions.d.ts +19 -0
  106. package/dist/components/table/TableActions.d.ts.map +1 -0
  107. package/dist/components/table/TableHeader.d.ts +6 -0
  108. package/dist/components/table/TableHeader.d.ts.map +1 -0
  109. package/dist/components/table/index.d.ts +15 -0
  110. package/dist/components/table/index.d.ts.map +1 -0
  111. package/dist/components/tabs/GenericTab.d.ts +7 -0
  112. package/dist/components/tabs/GenericTab.d.ts.map +1 -0
  113. package/dist/components/tabs/index.d.ts +2 -0
  114. package/dist/components/tabs/index.d.ts.map +1 -0
  115. package/dist/components/ui/index.d.ts +0 -2
  116. package/dist/components/ui/index.d.ts.map +1 -1
  117. package/dist/constants/urls.d.ts +2 -0
  118. package/dist/constants/urls.d.ts.map +1 -0
  119. package/dist/index-Dnn3beiE.js +62337 -0
  120. package/dist/index.d.ts +14 -0
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/react-starter.js +326 -298
  123. package/dist/react-starter.umd.cjs +373 -199
  124. package/dist/services/apiService.d.ts +3 -4
  125. package/dist/services/apiService.d.ts.map +1 -1
  126. package/package.json +10 -2
  127. package/dist/index-BlTeKmzn.js +0 -45406
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # React Starter
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 title="Hello World">
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 { apiService } from 'react-starter';
509
+ import React, { useEffect } from 'react';
510
+ import { useApiService } from 'izen-react-starter';
231
511
 
232
- // Configure base URL
233
- apiService.setBaseURL('https://api.example.com');
512
+ // Set the base URL once, typically in your app root
513
+ export function App() {
514
+ const apiService = useApiService();
234
515
 
235
- // Set auth token
236
- apiService.setAuthToken('your-token-here');
516
+ useEffect(() => {
517
+ apiService.setBaseURL('https://api.example.com');
518
+ }, [apiService]);
237
519
 
238
- // Make API calls
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
- async function postData() {
249
- try {
250
- const response = await apiService.post('/users', {
251
- name: 'John Doe',
252
- email: 'john@example.com'
253
- });
254
- console.log(response);
255
- } catch (error) {
256
- console.error('Error posting data:', error);
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
- - `setAuthToken(token)`: void
551
- - `removeAuthToken()`: void
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