@trackany-device/components 1.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 (289) hide show
  1. package/package.json +185 -0
  2. package/src/assets/logo.png +0 -0
  3. package/src/assets/map/arrows/map-arrow-blue.png +0 -0
  4. package/src/assets/map/arrows/map-arrow-green.png +0 -0
  5. package/src/assets/map/arrows/map-arrow-purple.png +0 -0
  6. package/src/assets/map/arrows/map-arrow-red.png +0 -0
  7. package/src/assets/map/flags/flag-blue.png +0 -0
  8. package/src/assets/map/flags/flag-green.png +0 -0
  9. package/src/assets/map/flags/flag-red.png +0 -0
  10. package/src/assets/map/flags/flag-yellow.png +0 -0
  11. package/src/assets/map/pins/map-pin-blue.png +0 -0
  12. package/src/assets/map/pins/map-pin-green.png +0 -0
  13. package/src/assets/map/pins/map-pin-purple.png +0 -0
  14. package/src/assets/map/pins/map-pin-red.png +0 -0
  15. package/src/components/Card.tsx +9 -0
  16. package/src/components/alert-error.tsx +24 -0
  17. package/src/components/app-content.tsx +22 -0
  18. package/src/components/app-header.tsx +153 -0
  19. package/src/components/app-logo-icon.tsx +13 -0
  20. package/src/components/app-logo.tsx +21 -0
  21. package/src/components/app-shell.tsx +19 -0
  22. package/src/components/app-sidebar-header.tsx +68 -0
  23. package/src/components/app-sidebar.tsx +106 -0
  24. package/src/components/appearance-tabs.tsx +46 -0
  25. package/src/components/breadcrumbs.tsx +50 -0
  26. package/src/components/cms/blurred-image.tsx +111 -0
  27. package/src/components/cms/section-bg.tsx +473 -0
  28. package/src/components/cms/section-button.tsx +127 -0
  29. package/src/components/cms/sections/banner-5050-section.tsx +135 -0
  30. package/src/components/cms/sections/blogs-listing-section.tsx +270 -0
  31. package/src/components/cms/sections/cards-grid-section.tsx +185 -0
  32. package/src/components/cms/sections/contact-form-section.tsx +157 -0
  33. package/src/components/cms/sections/cta-section.tsx +101 -0
  34. package/src/components/cms/sections/featured-blog-slider-section.tsx +256 -0
  35. package/src/components/cms/sections/featured-products-grid-section.tsx +173 -0
  36. package/src/components/cms/sections/featured-solutions-grid-section.tsx +183 -0
  37. package/src/components/cms/sections/hero-section.tsx +180 -0
  38. package/src/components/cms/sections/solutions-with-filter-section.tsx +234 -0
  39. package/src/components/cms/sections/text-section.tsx +77 -0
  40. package/src/components/cutout-image.tsx +228 -0
  41. package/src/components/devices/devices-mini-map.tsx +275 -0
  42. package/src/components/docs/docs-shell.tsx +280 -0
  43. package/src/components/fleet-hero-animated.tsx +383 -0
  44. package/src/components/input-error.tsx +17 -0
  45. package/src/components/keenicons/assets/duotone/Read Me.txt +7 -0
  46. package/src/components/keenicons/assets/duotone/demo-files/demo.css +160 -0
  47. package/src/components/keenicons/assets/duotone/demo-files/demo.js +32 -0
  48. package/src/components/keenicons/assets/duotone/demo.html +12424 -0
  49. package/src/components/keenicons/assets/duotone/fonts/keenicons-duotone.svg +1109 -0
  50. package/src/components/keenicons/assets/duotone/fonts/keenicons-duotone.ttf +0 -0
  51. package/src/components/keenicons/assets/duotone/fonts/keenicons-duotone.woff +0 -0
  52. package/src/components/keenicons/assets/duotone/selection.json +17313 -0
  53. package/src/components/keenicons/assets/duotone/style.css +4931 -0
  54. package/src/components/keenicons/assets/filled/Read Me.txt +7 -0
  55. package/src/components/keenicons/assets/filled/demo-files/demo.css +160 -0
  56. package/src/components/keenicons/assets/filled/demo-files/demo.js +32 -0
  57. package/src/components/keenicons/assets/filled/demo.html +12370 -0
  58. package/src/components/keenicons/assets/filled/fonts/keenicons-filled.svg +1082 -0
  59. package/src/components/keenicons/assets/filled/fonts/keenicons-filled.ttf +0 -0
  60. package/src/components/keenicons/assets/filled/fonts/keenicons-filled.woff +0 -0
  61. package/src/components/keenicons/assets/filled/selection.json +17096 -0
  62. package/src/components/keenicons/assets/filled/style.css +4769 -0
  63. package/src/components/keenicons/assets/outline/Read Me.txt +7 -0
  64. package/src/components/keenicons/assets/outline/demo-files/demo.css +160 -0
  65. package/src/components/keenicons/assets/outline/demo-files/demo.js +32 -0
  66. package/src/components/keenicons/assets/outline/demo.html +11356 -0
  67. package/src/components/keenicons/assets/outline/fonts/keenicons-outline.svg +575 -0
  68. package/src/components/keenicons/assets/outline/fonts/keenicons-outline.ttf +0 -0
  69. package/src/components/keenicons/assets/outline/fonts/keenicons-outline.woff +0 -0
  70. package/src/components/keenicons/assets/outline/selection.json +13054 -0
  71. package/src/components/keenicons/assets/outline/style.css +1721 -0
  72. package/src/components/keenicons/assets/solid/Read Me.txt +7 -0
  73. package/src/components/keenicons/assets/solid/demo-files/demo.css +160 -0
  74. package/src/components/keenicons/assets/solid/demo-files/demo.js +32 -0
  75. package/src/components/keenicons/assets/solid/demo.html +11356 -0
  76. package/src/components/keenicons/assets/solid/fonts/keenicons-solid.svg +575 -0
  77. package/src/components/keenicons/assets/solid/fonts/keenicons-solid.ttf +0 -0
  78. package/src/components/keenicons/assets/solid/fonts/keenicons-solid.woff +0 -0
  79. package/src/components/keenicons/assets/solid/selection.json +13048 -0
  80. package/src/components/keenicons/assets/solid/style.css +1721 -0
  81. package/src/components/keenicons/assets/styles.css +4 -0
  82. package/src/components/keenicons/index.ts +2 -0
  83. package/src/components/keenicons/keenicons.tsx +16 -0
  84. package/src/components/keenicons/types.ts +7 -0
  85. package/src/components/nav-footer.tsx +49 -0
  86. package/src/components/nav-main.tsx +53 -0
  87. package/src/components/nav-user.tsx +59 -0
  88. package/src/components/notification-bell.tsx +190 -0
  89. package/src/components/products/product-card.tsx +159 -0
  90. package/src/components/text-link.tsx +23 -0
  91. package/src/components/ui/accordion-menu.tsx +322 -0
  92. package/src/components/ui/accordion.tsx +133 -0
  93. package/src/components/ui/alert-dialog.tsx +82 -0
  94. package/src/components/ui/alert.tsx +63 -0
  95. package/src/components/ui/avatar-group.tsx +129 -0
  96. package/src/components/ui/avatar.tsx +67 -0
  97. package/src/components/ui/badge.tsx +230 -0
  98. package/src/components/ui/breadcrumb.tsx +88 -0
  99. package/src/components/ui/button.tsx +412 -0
  100. package/src/components/ui/calendar.tsx +56 -0
  101. package/src/components/ui/card.tsx +147 -0
  102. package/src/components/ui/chart.tsx +290 -0
  103. package/src/components/ui/checkbox.tsx +47 -0
  104. package/src/components/ui/code.tsx +45 -0
  105. package/src/components/ui/collapsible.tsx +31 -0
  106. package/src/components/ui/command-palette.tsx +189 -0
  107. package/src/components/ui/command.tsx +138 -0
  108. package/src/components/ui/cookie-banner.tsx +220 -0
  109. package/src/components/ui/copy-button.tsx +60 -0
  110. package/src/components/ui/data-grid-column-filter.tsx +124 -0
  111. package/src/components/ui/data-grid-column-header.tsx +284 -0
  112. package/src/components/ui/data-grid-column-visibility.tsx +38 -0
  113. package/src/components/ui/data-grid-pagination.tsx +206 -0
  114. package/src/components/ui/data-grid-table-dnd-rows.tsx +147 -0
  115. package/src/components/ui/data-grid-table-dnd.tsx +175 -0
  116. package/src/components/ui/data-grid-table.tsx +500 -0
  117. package/src/components/ui/data-grid.tsx +193 -0
  118. package/src/components/ui/data-list.tsx +76 -0
  119. package/src/components/ui/datefield.tsx +91 -0
  120. package/src/components/ui/dialog.tsx +139 -0
  121. package/src/components/ui/divider.tsx +41 -0
  122. package/src/components/ui/drawer.tsx +59 -0
  123. package/src/components/ui/dropdown-menu.tsx +224 -0
  124. package/src/components/ui/empty-state.tsx +54 -0
  125. package/src/components/ui/file-upload.tsx +152 -0
  126. package/src/components/ui/form.tsx +88 -0
  127. package/src/components/ui/icon.tsx +14 -0
  128. package/src/components/ui/input-otp.tsx +71 -0
  129. package/src/components/ui/input.tsx +155 -0
  130. package/src/components/ui/kbd.tsx +26 -0
  131. package/src/components/ui/label.tsx +31 -0
  132. package/src/components/ui/navigation-menu.tsx +168 -0
  133. package/src/components/ui/pagination.tsx +37 -0
  134. package/src/components/ui/placeholder-pattern.tsx +21 -0
  135. package/src/components/ui/popover.tsx +50 -0
  136. package/src/components/ui/progress.tsx +65 -0
  137. package/src/components/ui/radio-group.tsx +73 -0
  138. package/src/components/ui/resizable.tsx +39 -0
  139. package/src/components/ui/scroll-area.tsx +50 -0
  140. package/src/components/ui/select.tsx +234 -0
  141. package/src/components/ui/separator.tsx +24 -0
  142. package/src/components/ui/sheet.tsx +147 -0
  143. package/src/components/ui/sidebar.tsx +721 -0
  144. package/src/components/ui/skeleton.tsx +15 -0
  145. package/src/components/ui/slider.tsx +35 -0
  146. package/src/components/ui/sonner.tsx +28 -0
  147. package/src/components/ui/sortable.tsx +724 -0
  148. package/src/components/ui/spinner.tsx +17 -0
  149. package/src/components/ui/stat-card.tsx +82 -0
  150. package/src/components/ui/stepper.tsx +410 -0
  151. package/src/components/ui/switch.tsx +68 -0
  152. package/src/components/ui/table.tsx +42 -0
  153. package/src/components/ui/tabs.tsx +196 -0
  154. package/src/components/ui/timeline.tsx +90 -0
  155. package/src/components/ui/toggle-group.tsx +73 -0
  156. package/src/components/ui/toggle.tsx +45 -0
  157. package/src/components/ui/tooltip.tsx +55 -0
  158. package/src/components/user-info.tsx +33 -0
  159. package/src/components/user-menu-content.tsx +53 -0
  160. package/src/components/web/SiteFooter.tsx +154 -0
  161. package/src/components/web/SiteHeader.tsx +159 -0
  162. package/src/components/workflows/workflow-canvas.tsx +321 -0
  163. package/src/controls/Blockquote.tsx +25 -0
  164. package/src/controls/Button.tsx +101 -0
  165. package/src/controls/Checkbox.tsx +29 -0
  166. package/src/controls/DateField.tsx +37 -0
  167. package/src/controls/FormField.tsx +20 -0
  168. package/src/controls/Heading.tsx +28 -0
  169. package/src/controls/Input.tsx +21 -0
  170. package/src/controls/Label.tsx +18 -0
  171. package/src/controls/Paragraph.tsx +39 -0
  172. package/src/controls/PasswordInput.tsx +40 -0
  173. package/src/controls/RadioGroup.tsx +70 -0
  174. package/src/controls/Select.tsx +24 -0
  175. package/src/controls/Slider.tsx +33 -0
  176. package/src/controls/Switch.tsx +31 -0
  177. package/src/controls/Textarea.tsx +22 -0
  178. package/src/elements/ConfirmPasswordForm.tsx +43 -0
  179. package/src/elements/DeviceStatusBadge.tsx +38 -0
  180. package/src/elements/DriverCard.tsx +67 -0
  181. package/src/elements/ForgotPasswordForm.tsx +64 -0
  182. package/src/elements/IncidentCard.tsx +67 -0
  183. package/src/elements/LoginForm.tsx +100 -0
  184. package/src/elements/OtpForm.tsx +71 -0
  185. package/src/elements/RegisterForm.tsx +150 -0
  186. package/src/elements/ResetPasswordForm.tsx +72 -0
  187. package/src/elements/SmsChallengeForm.tsx +104 -0
  188. package/src/elements/VehicleCard.tsx +73 -0
  189. package/src/elements/VerifyEmailForm.tsx +39 -0
  190. package/src/hooks/use-appearance.tsx +117 -0
  191. package/src/hooks/use-applied-theme.ts +98 -0
  192. package/src/hooks/use-clipboard.ts +34 -0
  193. package/src/hooks/use-current-url.ts +83 -0
  194. package/src/hooks/use-dark-mode.ts +48 -0
  195. package/src/hooks/use-flash-toast.ts +29 -0
  196. package/src/hooks/use-initials.tsx +24 -0
  197. package/src/hooks/use-mobile-navigation.ts +12 -0
  198. package/src/hooks/use-mobile.tsx +38 -0
  199. package/src/index.ts +408 -0
  200. package/src/layouts/AppLayout.tsx +60 -0
  201. package/src/layouts/AuthLayout.tsx +32 -0
  202. package/src/layouts/SettingsLayout.tsx +21 -0
  203. package/src/layouts/app/AIChatLayout.tsx +73 -0
  204. package/src/layouts/app/AsideSidebarLayout.tsx +3 -0
  205. package/src/layouts/app/CalendarSidebarLayout.tsx +69 -0
  206. package/src/layouts/app/CommunitiesNavbarLayout.tsx +3 -0
  207. package/src/layouts/app/DualNavbarSidebarLayout.tsx +3 -0
  208. package/src/layouts/app/FocusSidebarLayout.tsx +75 -0
  209. package/src/layouts/app/MailLayout.tsx +69 -0
  210. package/src/layouts/app/MegaMenuHeaderLayout.tsx +3 -0
  211. package/src/layouts/app/MegaMenuLayout.tsx +81 -0
  212. package/src/layouts/app/MegaMenuNavbarLayout.tsx +88 -0
  213. package/src/layouts/app/MegaMenuSearchNavbarLayout.tsx +3 -0
  214. package/src/layouts/app/NavbarCollapsibleLayout.tsx +88 -0
  215. package/src/layouts/app/NavbarCollapsibleLinksLayout.tsx +3 -0
  216. package/src/layouts/app/NavbarMinimalLayout.tsx +3 -0
  217. package/src/layouts/app/NavbarMinimalSidebarLayout.tsx +3 -0
  218. package/src/layouts/app/NavbarSidebarDashboardLayout.tsx +3 -0
  219. package/src/layouts/app/NavbarSidebarLayout.tsx +92 -0
  220. package/src/layouts/app/NavbarSimpleSidebarLayout.tsx +3 -0
  221. package/src/layouts/app/NavbarTitledSidebarLayout.tsx +3 -0
  222. package/src/layouts/app/PanelSidebarLayout.tsx +3 -0
  223. package/src/layouts/app/SearchNavbarSidebarLayout.tsx +3 -0
  224. package/src/layouts/app/SidebarBreadcrumbLayout.tsx +3 -0
  225. package/src/layouts/app/SidebarCleanLayout.tsx +3 -0
  226. package/src/layouts/app/SidebarCommunitiesLayout.tsx +3 -0
  227. package/src/layouts/app/SidebarContentLayout.tsx +3 -0
  228. package/src/layouts/app/SidebarDualMenuLayout.tsx +104 -0
  229. package/src/layouts/app/SidebarFixedLayout.tsx +166 -0
  230. package/src/layouts/app/SidebarFooterNavbarLayout.tsx +3 -0
  231. package/src/layouts/app/SidebarHeaderMenuLayout.tsx +3 -0
  232. package/src/layouts/app/SidebarMegaMenuLayout.tsx +4 -0
  233. package/src/layouts/app/SidebarMinimalLayout.tsx +70 -0
  234. package/src/layouts/app/SidebarMobileSearchLayout.tsx +3 -0
  235. package/src/layouts/app/SidebarMultiPanelLayout.tsx +3 -0
  236. package/src/layouts/app/SidebarPrimarySecondaryLayout.tsx +3 -0
  237. package/src/layouts/app/SidebarSearchHeaderLayout.tsx +103 -0
  238. package/src/layouts/app/SidebarSearchToolbarLayout.tsx +3 -0
  239. package/src/layouts/app/SidebarTabsDualLayout.tsx +3 -0
  240. package/src/layouts/app/SidebarTabsLayout.tsx +98 -0
  241. package/src/layouts/app/SidebarTreeLayout.tsx +3 -0
  242. package/src/layouts/app/SplitNavbarLayout.tsx +3 -0
  243. package/src/layouts/app/SplitSidebarDashboardLayout.tsx +3 -0
  244. package/src/layouts/app/SplitSidebarLayout.tsx +99 -0
  245. package/src/layouts/app/TopNavLayout.tsx +105 -0
  246. package/src/layouts/app/TopNavLinksLayout.tsx +3 -0
  247. package/src/layouts/app/WorkspaceBreadcrumbLayout.tsx +3 -0
  248. package/src/layouts/app/WorkspaceCommunitiesLayout.tsx +3 -0
  249. package/src/layouts/app/WorkspaceNavbarLayout.tsx +3 -0
  250. package/src/layouts/app/WorkspaceSidebarLayout.tsx +98 -0
  251. package/src/layouts/app/WorkspaceSidebarTitleLayout.tsx +3 -0
  252. package/src/layouts/app/app-header-layout.tsx +45 -0
  253. package/src/layouts/app/app-sidebar-layout.tsx +56 -0
  254. package/src/layouts/app/layout-context.tsx +44 -0
  255. package/src/layouts/app/layout-types.ts +47 -0
  256. package/src/layouts/app/partials/Footer.tsx +35 -0
  257. package/src/layouts/app/partials/HeaderTopbar.tsx +96 -0
  258. package/src/layouts/app/partials/Navbar.tsx +85 -0
  259. package/src/layouts/app/partials/Toolbar.tsx +47 -0
  260. package/src/layouts/app-layout.tsx +29 -0
  261. package/src/layouts/auth/AuthBrandedLayout.tsx +58 -0
  262. package/src/layouts/auth/AuthCardLayout.tsx +31 -0
  263. package/src/layouts/auth/AuthCenteredLayout.tsx +41 -0
  264. package/src/layouts/auth/AuthClassicLayout.tsx +41 -0
  265. package/src/layouts/auth/AuthSimpleLayout.tsx +33 -0
  266. package/src/layouts/auth/AuthSplitLayout.tsx +89 -0
  267. package/src/layouts/web-app-layout.tsx +162 -0
  268. package/src/layouts/web-layout.tsx +23 -0
  269. package/src/lib/datetime.ts +188 -0
  270. package/src/lib/google-maps-loader.ts +99 -0
  271. package/src/lib/location.ts +127 -0
  272. package/src/lib/lucide-icon-map.ts +132 -0
  273. package/src/lib/map-markers.ts +124 -0
  274. package/src/lib/map-styles.ts +351 -0
  275. package/src/lib/utils.ts +11 -0
  276. package/src/platform/adapters/default.tsx +156 -0
  277. package/src/platform/adapters/inertia.tsx +88 -0
  278. package/src/platform/adapters/nextjs.ts +86 -0
  279. package/src/platform/context.tsx +106 -0
  280. package/src/platform/index.ts +27 -0
  281. package/src/platform/types.ts +105 -0
  282. package/src/styles/layouts/sidebar-fixed.css +161 -0
  283. package/src/styles/themes.css +583 -0
  284. package/src/types/assets.d.ts +5 -0
  285. package/src/types/auth.ts +25 -0
  286. package/src/types/global.d.ts +13 -0
  287. package/src/types/index.ts +9 -0
  288. package/src/types/navigation.ts +15 -0
  289. package/src/types/ui.ts +32 -0
@@ -0,0 +1,193 @@
1
+ 'use client';
2
+
3
+ import { createContext, ReactNode, useContext } from 'react';
4
+ import { cn } from '../../lib/utils';
5
+ import { ColumnFiltersState, RowData, SortingState, Table } from '@tanstack/react-table';
6
+
7
+ declare module '@tanstack/react-table' {
8
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
9
+ interface ColumnMeta<TData extends RowData, TValue> {
10
+ headerTitle?: string;
11
+ headerClassName?: string;
12
+ cellClassName?: string;
13
+ skeleton?: ReactNode;
14
+ expandedContent?: (row: TData) => ReactNode;
15
+ }
16
+ }
17
+
18
+ export type DataGridApiFetchParams = {
19
+ pageIndex: number;
20
+ pageSize: number;
21
+ sorting?: SortingState;
22
+ filters?: ColumnFiltersState;
23
+ searchQuery?: string;
24
+ };
25
+
26
+ export type DataGridApiResponse<T> = {
27
+ data: T[];
28
+ empty: boolean;
29
+ pagination: {
30
+ total: number;
31
+ page: number;
32
+ };
33
+ };
34
+
35
+ export interface DataGridContextProps<TData extends object> {
36
+ props: DataGridProps<TData>;
37
+ table: Table<TData>;
38
+ recordCount: number;
39
+ isLoading: boolean;
40
+ }
41
+
42
+ export type DataGridRequestParams = {
43
+ pageIndex: number;
44
+ pageSize: number;
45
+ sorting?: SortingState;
46
+ columnFilters?: ColumnFiltersState;
47
+ };
48
+
49
+ export interface DataGridProps<TData extends object> {
50
+ className?: string;
51
+ table?: Table<TData>;
52
+ recordCount: number;
53
+ children?: ReactNode;
54
+ onRowClick?: (row: TData) => void;
55
+ isLoading?: boolean;
56
+ loadingMode?: 'skeleton' | 'spinner';
57
+ loadingMessage?: ReactNode | string;
58
+ emptyMessage?: ReactNode | string;
59
+ tableLayout?: {
60
+ dense?: boolean;
61
+ cellBorder?: boolean;
62
+ rowBorder?: boolean;
63
+ rowRounded?: boolean;
64
+ stripped?: boolean;
65
+ headerBackground?: boolean;
66
+ headerBorder?: boolean;
67
+ headerSticky?: boolean;
68
+ width?: 'auto' | 'fixed';
69
+ columnsVisibility?: boolean;
70
+ columnsResizable?: boolean;
71
+ columnsPinnable?: boolean;
72
+ columnsMovable?: boolean;
73
+ columnsDraggable?: boolean;
74
+ rowsDraggable?: boolean;
75
+ };
76
+ tableClassNames?: {
77
+ base?: string;
78
+ header?: string;
79
+ headerRow?: string;
80
+ headerSticky?: string;
81
+ body?: string;
82
+ bodyRow?: string;
83
+ footer?: string;
84
+ edgeCell?: string;
85
+ };
86
+ }
87
+
88
+ const DataGridContext = createContext<
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ DataGridContextProps<any> | undefined
91
+ >(undefined);
92
+
93
+ function useDataGrid() {
94
+ const context = useContext(DataGridContext);
95
+ if (!context) {
96
+ throw new Error('useDataGrid must be used within a DataGridProvider');
97
+ }
98
+ return context;
99
+ }
100
+
101
+ function DataGridProvider<TData extends object>({
102
+ children,
103
+ table,
104
+ ...props
105
+ }: DataGridProps<TData> & { table: Table<TData> }) {
106
+ return (
107
+ <DataGridContext.Provider
108
+ value={{
109
+ props,
110
+ table,
111
+ recordCount: props.recordCount,
112
+ isLoading: props.isLoading || false,
113
+ }}
114
+ >
115
+ {children}
116
+ </DataGridContext.Provider>
117
+ );
118
+ }
119
+
120
+ function DataGrid<TData extends object>({ children, table, ...props }: DataGridProps<TData>) {
121
+ const defaultProps: Partial<DataGridProps<TData>> = {
122
+ loadingMode: 'skeleton',
123
+ tableLayout: {
124
+ dense: false,
125
+ cellBorder: false,
126
+ rowBorder: true,
127
+ rowRounded: false,
128
+ stripped: false,
129
+ headerSticky: false,
130
+ headerBackground: true,
131
+ headerBorder: true,
132
+ width: 'fixed',
133
+ columnsVisibility: false,
134
+ columnsResizable: false,
135
+ columnsPinnable: false,
136
+ columnsMovable: false,
137
+ columnsDraggable: false,
138
+ rowsDraggable: false,
139
+ },
140
+ tableClassNames: {
141
+ base: '',
142
+ header: '',
143
+ headerRow: '',
144
+ headerSticky: 'sticky top-0 z-10 bg-background/90 backdrop-blur-xs',
145
+ body: '',
146
+ bodyRow: '',
147
+ footer: '',
148
+ edgeCell: '',
149
+ },
150
+ };
151
+
152
+ const mergedProps: DataGridProps<TData> = {
153
+ ...defaultProps,
154
+ ...props,
155
+ tableLayout: {
156
+ ...defaultProps.tableLayout,
157
+ ...(props.tableLayout || {}),
158
+ },
159
+ tableClassNames: {
160
+ ...defaultProps.tableClassNames,
161
+ ...(props.tableClassNames || {}),
162
+ },
163
+ };
164
+
165
+ // Ensure table is provided
166
+ if (!table) {
167
+ throw new Error('DataGrid requires a "table" prop');
168
+ }
169
+
170
+ return (
171
+ <DataGridProvider table={table} {...mergedProps}>
172
+ {children}
173
+ </DataGridProvider>
174
+ );
175
+ }
176
+
177
+ function DataGridContainer({
178
+ children,
179
+ className,
180
+ border = true,
181
+ }: {
182
+ children: ReactNode;
183
+ className?: string;
184
+ border?: boolean;
185
+ }) {
186
+ return (
187
+ <div data-slot="data-grid" className={cn('grid w-full', border && 'border border-border rounded-lg', className)}>
188
+ {children}
189
+ </div>
190
+ );
191
+ }
192
+
193
+ export { useDataGrid, DataGridProvider, DataGrid, DataGridContainer, DataGridContext };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * DataList — key/value display (HTML <dl>).
3
+ *
4
+ * Two flavours:
5
+ * - Pass `items` prop: array of { label, value, mono? }
6
+ * - Or compose with <DataListItem> children for richer cells
7
+ *
8
+ * <DataList items={[
9
+ * { label: 'Serial', value: 'P901-00042', mono: true },
10
+ * { label: 'Status', value: <Badge>Active</Badge> },
11
+ * ]} />
12
+ */
13
+ import * as React from 'react';
14
+
15
+ import { cn } from '../../lib/utils';
16
+
17
+ type Item = {
18
+ label: string;
19
+ value: React.ReactNode;
20
+ mono?: boolean;
21
+ };
22
+
23
+ type Props = {
24
+ items?: Item[];
25
+ children?: React.ReactNode;
26
+ className?: string;
27
+ };
28
+
29
+ export function DataList({ items, children, className }: Props) {
30
+ return (
31
+ <dl
32
+ className={cn(
33
+ 'divide-y divide-border rounded-lg border bg-card',
34
+ className,
35
+ )}
36
+ >
37
+ {items
38
+ ? items.map((item) => (
39
+ <DataListItem
40
+ key={item.label}
41
+ label={item.label}
42
+ mono={item.mono}
43
+ >
44
+ {item.value}
45
+ </DataListItem>
46
+ ))
47
+ : children}
48
+ </dl>
49
+ );
50
+ }
51
+
52
+ export function DataListItem({
53
+ label,
54
+ mono,
55
+ children,
56
+ }: {
57
+ label: string;
58
+ mono?: boolean;
59
+ children: React.ReactNode;
60
+ }) {
61
+ return (
62
+ <div className="flex flex-col gap-1 px-4 py-3 sm:flex-row sm:items-center sm:gap-4">
63
+ <dt className="text-xs font-medium uppercase tracking-wide text-muted-foreground sm:w-40">
64
+ {label}
65
+ </dt>
66
+ <dd
67
+ className={cn(
68
+ 'flex-1 text-sm text-foreground',
69
+ mono && 'font-mono',
70
+ )}
71
+ >
72
+ {children}
73
+ </dd>
74
+ </div>
75
+ );
76
+ }
@@ -0,0 +1,91 @@
1
+ 'use client';
2
+
3
+ import { cn } from '../../lib/utils';
4
+ import { inputVariants } from './input';
5
+ import type { VariantProps } from 'class-variance-authority';
6
+ import {
7
+ composeRenderProps,
8
+ DateFieldProps,
9
+ DateField as DateFieldRa,
10
+ DateInputProps as DateInputPropsRa,
11
+ DateInput as DateInputRa,
12
+ DateSegmentProps,
13
+ DateSegment as DateSegmentRa,
14
+ DateValue as DateValueRa,
15
+ TimeFieldProps,
16
+ TimeField as TimeFieldRa,
17
+ TimeValue as TimeValueRa,
18
+ } from 'react-aria-components';
19
+
20
+ function DateField<T extends DateValueRa>({ className, children, ...props }: DateFieldProps<T>) {
21
+ return (
22
+ <DateFieldRa
23
+ className={composeRenderProps(className, (className) => cn(className))}
24
+ data-slot="datefield"
25
+ {...props}
26
+ >
27
+ {children}
28
+ </DateFieldRa>
29
+ );
30
+ }
31
+
32
+ function TimeField<T extends TimeValueRa>({ className, children, ...props }: TimeFieldProps<T>) {
33
+ return (
34
+ <TimeFieldRa
35
+ className={composeRenderProps(className, (className) => cn(className))}
36
+ data-slot="datefield"
37
+ {...props}
38
+ >
39
+ {children}
40
+ </TimeFieldRa>
41
+ );
42
+ }
43
+
44
+ function DateSegment({ className, ...props }: DateSegmentProps) {
45
+ return (
46
+ <DateSegmentRa
47
+ className={composeRenderProps(className, (className) =>
48
+ cn(
49
+ `
50
+ text-foreground inline-flex rounded px-0.5 caret-transparent outline-hidden data-[type=literal]:text-muted-foreground/70 data-[type=literal]:px-0
51
+ data-placeholder:text-muted-foreground/70
52
+ data-invalid:data-focused:bg-destructive data-invalid:data-placeholder:text-destructive data-invalid:text-destructive data-invalid:data-focused:data-placeholder:text-destructive-foreground data-invalid:data-focused:text-destructive-foreground
53
+ data-focused:bg-accent data-focused:data-placeholder:text-foreground data-focused:text-foreground
54
+ data-disabled:cursor-not-allowed data-disabled:opacity-50
55
+ `,
56
+ className,
57
+ ),
58
+ )}
59
+ {...props}
60
+ data-invalid
61
+ />
62
+ );
63
+ }
64
+
65
+ const dateInputStyles = `
66
+ relative inline-flex items-center overflow-hidden whitespace-nowrap
67
+ data-focus-within:ring-ring/30 data-focus-within:border-ring data-focus-within:outline-none data-focus-within:ring-[3px]
68
+ data-focus-within:has-aria-invalid:ring-destructive/20 dark:data-focus-within:has-aria-invalid:ring-destructive/40 data-focus-within:has-aria-invalid:border-destructive
69
+ `;
70
+
71
+ interface DateInputProps extends DateInputPropsRa, VariantProps<typeof inputVariants> {
72
+ className?: string;
73
+ variant?: VariantProps<typeof inputVariants>['variant'];
74
+ }
75
+
76
+ function DateInput({ className, variant = 'md', ...props }: Omit<DateInputProps, 'children'>) {
77
+ return (
78
+ <DateInputRa
79
+ data-slot="input"
80
+ className={composeRenderProps(className, (className) =>
81
+ cn(inputVariants({ variant }), dateInputStyles, className),
82
+ )}
83
+ {...props}
84
+ >
85
+ {(segment) => <DateSegment segment={segment} />}
86
+ </DateInputRa>
87
+ );
88
+ }
89
+
90
+ export { DateField, DateInput, DateSegment, TimeField, dateInputStyles };
91
+ export type { DateInputProps };
@@ -0,0 +1,139 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { cn } from '../../lib/utils';
5
+ import { cva, VariantProps } from 'class-variance-authority';
6
+ import { X } from 'lucide-react';
7
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
8
+
9
+ const dialogContentVariants = cva(
10
+ 'flex flex-col fixed outline-0 z-50 border border-border bg-background p-6 shadow-lg shadow-black/5 duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg',
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: 'left-[50%] top-[50%] max-w-lg translate-x-[-50%] translate-y-[-50%] w-full',
15
+ fullscreen: 'inset-5',
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ variant: 'default',
20
+ },
21
+ },
22
+ );
23
+
24
+ function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
25
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />;
26
+ }
27
+
28
+ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
29
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
30
+ }
31
+
32
+ function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
33
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
34
+ }
35
+
36
+ function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
37
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
38
+ }
39
+
40
+ function DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
41
+ return (
42
+ <DialogPrimitive.Overlay
43
+ data-slot="dialog-overlay"
44
+ className={cn(
45
+ 'fixed inset-0 z-50 bg-black/30 [backdrop-filter:blur(4px)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
46
+ className,
47
+ )}
48
+ {...props}
49
+ />
50
+ );
51
+ }
52
+
53
+ function DialogContent({
54
+ className,
55
+ children,
56
+ showCloseButton = true,
57
+ overlay = true,
58
+ variant,
59
+ ...props
60
+ }: React.ComponentProps<typeof DialogPrimitive.Content> &
61
+ VariantProps<typeof dialogContentVariants> & {
62
+ showCloseButton?: boolean;
63
+ overlay?: boolean;
64
+ }) {
65
+ return (
66
+ <DialogPortal>
67
+ {overlay && <DialogOverlay />}
68
+ <DialogPrimitive.Content
69
+ data-slot="dialog-content"
70
+ className={cn(dialogContentVariants({ variant }), className)}
71
+ {...props}
72
+ >
73
+ {children}
74
+ {showCloseButton && (
75
+ <DialogClose className="cursor-pointer outline-0 absolute end-5 top-5 rounded-sm opacity-60 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
76
+ <X className="size-4" />
77
+ <span className="sr-only">Close</span>
78
+ </DialogClose>
79
+ )}
80
+ </DialogPrimitive.Content>
81
+ </DialogPortal>
82
+ );
83
+ }
84
+
85
+ export default DialogContent;
86
+
87
+ const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
88
+ <div
89
+ data-slot="dialog-header"
90
+ className={cn('flex flex-col space-y-1 text-center sm:text-start mb-5', className)}
91
+ {...props}
92
+ />
93
+ );
94
+
95
+ const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
96
+ <div
97
+ data-slot="dialog-footer"
98
+ className={cn('flex flex-col-reverse sm:flex-row sm:justify-end pt-5 sm:space-x-2.5', className)}
99
+ {...props}
100
+ />
101
+ );
102
+
103
+ function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
104
+ return (
105
+ <DialogPrimitive.Title
106
+ data-slot="dialog-title"
107
+ className={cn('text-lg font-semibold leading-none tracking-tight', className)}
108
+ {...props}
109
+ />
110
+ );
111
+ }
112
+
113
+ const DialogBody = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
114
+ <div data-slot="dialog-body" className={cn('grow', className)} {...props} />
115
+ );
116
+
117
+ function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {
118
+ return (
119
+ <DialogPrimitive.Description
120
+ data-slot="dialog-description"
121
+ className={cn('text-sm text-muted-foreground', className)}
122
+ {...props}
123
+ />
124
+ );
125
+ }
126
+
127
+ export {
128
+ Dialog,
129
+ DialogBody,
130
+ DialogClose,
131
+ DialogContent,
132
+ DialogDescription,
133
+ DialogFooter,
134
+ DialogHeader,
135
+ DialogOverlay,
136
+ DialogPortal,
137
+ DialogTitle,
138
+ DialogTrigger,
139
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Divider — horizontal rule with optional centred label.
3
+ *
4
+ * <Divider />
5
+ * <Divider>OR</Divider>
6
+ */
7
+ import * as React from 'react';
8
+
9
+ import { cn } from '../../lib/utils';
10
+
11
+ type Props = {
12
+ children?: React.ReactNode;
13
+ className?: string;
14
+ decorative?: boolean;
15
+ };
16
+
17
+ export function Divider({ children, className, decorative = true }: Props) {
18
+ if (!children) {
19
+ return (
20
+ <hr
21
+ role={decorative ? 'presentation' : 'separator'}
22
+ aria-hidden={decorative ? 'true' : undefined}
23
+ className={cn('my-4 border-border', className)}
24
+ />
25
+ );
26
+ }
27
+
28
+ return (
29
+ <div
30
+ role={decorative ? 'presentation' : 'separator'}
31
+ aria-hidden={decorative ? 'true' : undefined}
32
+ className={cn('my-4 flex items-center gap-3', className)}
33
+ >
34
+ <span className="h-px flex-1 bg-border" />
35
+ <span className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
36
+ {children}
37
+ </span>
38
+ <span className="h-px flex-1 bg-border" />
39
+ </div>
40
+ );
41
+ }
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { Drawer as DrawerPrimitive } from 'vaul';
5
+ import { cn } from '../../lib/utils';
6
+
7
+ const Drawer = ({ shouldScaleBackground = true, ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
8
+ <DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />
9
+ );
10
+
11
+ function DrawerTrigger({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
12
+ return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
13
+ }
14
+
15
+ function DrawerPortal({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
16
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
17
+ }
18
+
19
+ function DrawerClose({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
20
+ return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
21
+ }
22
+
23
+ function DrawerOverlay({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
24
+ return <DrawerPrimitive.Overlay data-slot="drawer-overlay" className={cn('fixed inset-0 z-50 bg-black/80', className)} {...props} />;
25
+ }
26
+
27
+ function DrawerContent({ className, children, ...props }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
28
+ return (
29
+ <DrawerPortal>
30
+ <DrawerOverlay />
31
+ <DrawerPrimitive.Content
32
+ data-slot="drawer-content"
33
+ className={cn('bg-background fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border', className)}
34
+ {...props}
35
+ >
36
+ <div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
37
+ {children}
38
+ </DrawerPrimitive.Content>
39
+ </DrawerPortal>
40
+ );
41
+ }
42
+
43
+ const DrawerHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
44
+ <div data-slot="drawer-header" className={cn('grid gap-1.5 p-4 text-center sm:text-left', className)} {...props} />
45
+ );
46
+
47
+ const DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
48
+ <div data-slot="drawer-footer" className={cn('mt-auto flex flex-col gap-2 p-4', className)} {...props} />
49
+ );
50
+
51
+ function DrawerTitle({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
52
+ return <DrawerPrimitive.Title data-slot="drawer-title" className={cn('text-lg font-semibold leading-none tracking-tight', className)} {...props} />;
53
+ }
54
+
55
+ function DrawerDescription({ className, ...props }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
56
+ return <DrawerPrimitive.Description data-slot="drawer-description" className={cn('text-sm text-muted-foreground', className)} {...props} />;
57
+ }
58
+
59
+ export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger };