izen-react-starter 1.1.4 → 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 +1233 -25
  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
@@ -211,6 +211,269 @@ function MyApp() {
211
211
  }
212
212
  ```
213
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
+
214
477
  ### Layout Context
215
478
 
216
479
  ```tsx
@@ -243,36 +506,56 @@ function MyComponent() {
243
506
  ### API Service
244
507
 
245
508
  ```tsx
246
- import { apiService } from 'izen-react-starter';
509
+ import React, { useEffect } from 'react';
510
+ import { useApiService } from 'izen-react-starter';
247
511
 
248
- // Configure base URL
249
- 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();
250
515
 
251
- // Set auth token
252
- apiService.setAuthToken('your-token-here');
516
+ useEffect(() => {
517
+ apiService.setBaseURL('https://api.example.com');
518
+ }, [apiService]);
253
519
 
254
- // Make API calls
255
- async function fetchData() {
256
- try {
257
- const data = await apiService.get('/users');
258
- console.log(data);
259
- } catch (error) {
260
- console.error('Error fetching data:', error);
261
- }
520
+ return <UsersPage />;
262
521
  }
263
522
 
264
- async function postData() {
265
- try {
266
- const response = await apiService.post('/users', {
267
- name: 'John Doe',
268
- email: 'john@example.com'
269
- });
270
- console.log(response);
271
- } catch (error) {
272
- console.error('Error posting data:', error);
273
- }
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
+ );
274
556
  }
275
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.
276
559
 
277
560
  ### Role-Based Access Control (RBAC)
278
561
 
@@ -565,8 +848,933 @@ Methods:
565
848
  - `patch<T>(url, data?, config?)`: Promise<T>
566
849
  - `delete<T>(url, config?)`: Promise<T>
567
850
  - `setBaseURL(baseURL)`: void
568
- - `setAuthToken(token)`: void
569
- - `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
+ ```
570
1778
 
571
1779
  ### RBAC System
572
1780