@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,155 @@
1
+ import * as React from 'react';
2
+ import { cn } from '../../lib/utils';
3
+ import { cva, type VariantProps } from 'class-variance-authority';
4
+
5
+ // Define input size variants
6
+ const inputVariants = cva(
7
+ `
8
+ flex w-full bg-background border border-input shadow-xs shadow-black/5 transition-[color,box-shadow] text-foreground placeholder:text-muted-foreground/80
9
+ focus-visible:ring-ring/30 focus-visible:border-ring focus-visible:outline-none focus-visible:ring-[3px]
10
+ disabled:cursor-not-allowed disabled:opacity-60
11
+ [&[readonly]]:bg-muted/80 [&[readonly]]:cursor-not-allowed
12
+ file:h-full [&[type=file]]:py-0 file:border-solid file:border-input file:bg-transparent
13
+ file:font-medium file:not-italic file:text-foreground file:p-0 file:border-0 file:border-e
14
+ aria-invalid:border-destructive/60 aria-invalid:ring-destructive/10 dark:aria-invalid:border-destructive dark:aria-invalid:ring-destructive/20
15
+ `,
16
+ {
17
+ variants: {
18
+ variant: {
19
+ lg: 'h-10 px-4 text-sm rounded-md file:pe-4 file:me-4',
20
+ md: 'h-8.5 px-3 text-[0.8125rem] leading-(--text-sm--line-height) rounded-md file:pe-3 file:me-3',
21
+ sm: 'h-7 px-2.5 text-xs rounded-md file:pe-2.5 file:me-2.5',
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: 'md',
26
+ },
27
+ },
28
+ );
29
+
30
+ const inputAddonVariants = cva(
31
+ 'flex items-center shrink-0 justify-center bg-muted border border-input shadow-xs shadow-[rgba(0,0,0,0.05)] text-secondary-foreground [&_svg]:text-secondary-foreground/60',
32
+ {
33
+ variants: {
34
+ variant: {
35
+ sm: 'rounded-md h-7 min-w-7 text-xs px-2.5 [&_svg:not([class*=size-])]:size-3.5',
36
+ md: 'rounded-md h-8.5 min-w-8.5 px-3 text-[0.8125rem] leading-(--text-sm--line-height) [&_svg:not([class*=size-])]:size-4.5',
37
+ lg: 'rounded-md h-10 min-w-10 px-4 text-sm [&_svg:not([class*=size-])]:size-4.5',
38
+ },
39
+ mode: {
40
+ default: '',
41
+ icon: 'px-0 justify-center',
42
+ },
43
+ },
44
+ defaultVariants: {
45
+ variant: 'md',
46
+ mode: 'default',
47
+ },
48
+ },
49
+ );
50
+
51
+ const inputGroupVariants = cva(
52
+ `
53
+ flex items-stretch
54
+ [&_[data-slot=input]]:grow
55
+ [&_[data-slot=input-addon]:has(+[data-slot=input])]:rounded-e-none [&_[data-slot=input-addon]:has(+[data-slot=input])]:border-e-0
56
+ [&_[data-slot=input-addon]:has(+[data-slot=datefield])]:rounded-e-none [&_[data-slot=input-addon]:has(+[data-slot=datefield])]:border-e-0
57
+ [&_[data-slot=input]+[data-slot=input-addon]]:rounded-s-none [&_[data-slot=input]+[data-slot=input-addon]]:border-s-0
58
+ [&_[data-slot=input-addon]:has(+[data-slot=button])]:rounded-e-none
59
+ [&_[data-slot=input]+[data-slot=button]]:rounded-s-none
60
+ [&_[data-slot=button]+[data-slot=input]]:rounded-s-none
61
+ [&_[data-slot=input-addon]+[data-slot=input]]:rounded-s-none
62
+ [&_[data-slot=input-addon]+[data-slot=datefield]]:[&_[data-slot=input]]:rounded-s-none
63
+ [&_[data-slot=datefield]:has(+[data-slot=input-addon])]:[&_[data-slot=input]]:rounded-e-none
64
+ [&_[data-slot=input]:has(+[data-slot=button])]:rounded-e-none
65
+ [&_[data-slot=input]:has(+[data-slot=input-addon])]:rounded-e-none
66
+ [&_[data-slot=datefield]]:grow
67
+ [&_[data-slot=datefield]+[data-slot=input-addon]]:rounded-s-none [&_[data-slot=datefield]+[data-slot=input-addon]]:border-s-0
68
+ `,
69
+ {
70
+ variants: {},
71
+ defaultVariants: {},
72
+ },
73
+ );
74
+
75
+ const inputWrapperVariants = cva(
76
+ `
77
+ flex items-center gap-1.5
78
+ has-[:focus-visible]:ring-ring/30
79
+ has-[:focus-visible]:border-ring
80
+ has-[:focus-visible]:outline-none
81
+ has-[:focus-visible]:ring-[3px]
82
+
83
+ [&_[data-slot=datefield]]:grow
84
+ [&_[data-slot=input]]:data-focus-within:ring-transparent
85
+ [&_[data-slot=input]]:data-focus-within:ring-0
86
+ [&_[data-slot=input]]:data-focus-within:border-0
87
+ [&_[data-slot=input]]:flex
88
+ [&_[data-slot=input]]:w-full
89
+ [&_[data-slot=input]]:outline-none
90
+ [&_[data-slot=input]]:transition-colors
91
+ [&_[data-slot=input]]:text-foreground
92
+ [&_[data-slot=input]]:placeholder:text-muted-foreground
93
+ [&_[data-slot=input]]:border-0
94
+ [&_[data-slot=input]]:bg-transparent
95
+ [&_[data-slot=input]]:p-0
96
+ [&_[data-slot=input]]:shadow-none
97
+ [&_[data-slot=input]]:focus-visible:ring-0
98
+ [&_[data-slot=input]]:h-auto
99
+ [&_[data-slot=input]]:disabled:cursor-not-allowed
100
+ [&_[data-slot=input]]:disabled:opacity-50
101
+
102
+ [&_svg]:text-muted-foreground
103
+ [&_svg]:shrink-0
104
+ `,
105
+ {
106
+ variants: {
107
+ variant: {
108
+ sm: 'gap-1.25 [&_svg:not([class*=size-])]:size-3.5',
109
+ md: 'gap-1.5 [&_svg:not([class*=size-])]:size-4',
110
+ lg: 'gap-1.5 [&_svg:not([class*=size-])]:size-4',
111
+ },
112
+ },
113
+ defaultVariants: {
114
+ variant: 'md',
115
+ },
116
+ },
117
+ );
118
+
119
+ function Input({
120
+ className,
121
+ type,
122
+ variant,
123
+ ...props
124
+ }: React.ComponentProps<'input'> & VariantProps<typeof inputVariants>) {
125
+ return <input data-slot="input" type={type} className={cn(inputVariants({ variant }), className)} {...props} />;
126
+ }
127
+
128
+ function InputAddon({
129
+ className,
130
+ variant,
131
+ mode,
132
+ ...props
133
+ }: React.ComponentProps<'div'> & VariantProps<typeof inputAddonVariants>) {
134
+ return <div data-slot="input-addon" className={cn(inputAddonVariants({ variant, mode }), className)} {...props} />;
135
+ }
136
+
137
+ function InputGroup({ className, ...props }: React.ComponentProps<'div'> & VariantProps<typeof inputGroupVariants>) {
138
+ return <div data-slot="input-group" className={cn(inputGroupVariants(), className)} {...props} />;
139
+ }
140
+
141
+ function InputWrapper({
142
+ className,
143
+ variant,
144
+ ...props
145
+ }: React.ComponentProps<'div'> & VariantProps<typeof inputWrapperVariants>) {
146
+ return (
147
+ <div
148
+ data-slot="input-wrapper"
149
+ className={cn(inputVariants({ variant }), inputWrapperVariants({ variant }), className)}
150
+ {...props}
151
+ />
152
+ );
153
+ }
154
+
155
+ export { Input, InputAddon, InputGroup, InputWrapper, inputVariants, inputAddonVariants };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Kbd — keyboard shortcut notation.
3
+ *
4
+ * <Kbd>⌘K</Kbd> <Kbd>Ctrl + /</Kbd>
5
+ */
6
+ import * as React from 'react';
7
+
8
+ import { cn } from '../../lib/utils';
9
+
10
+ export function Kbd({
11
+ className,
12
+ children,
13
+ ...props
14
+ }: React.HTMLAttributes<HTMLElement>) {
15
+ return (
16
+ <kbd
17
+ className={cn(
18
+ 'pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground',
19
+ className,
20
+ )}
21
+ {...props}
22
+ >
23
+ {children}
24
+ </kbd>
25
+ );
26
+ }
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { cn } from '../../lib/utils';
5
+ import { cva, type VariantProps } from 'class-variance-authority';
6
+ import * as LabelPrimitive from '@radix-ui/react-label';
7
+
8
+ const labelVariants = cva(
9
+ 'text-sm leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
10
+ {
11
+ variants: {
12
+ variant: {
13
+ primary: 'font-medium',
14
+ secondary: 'font-normal',
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ variant: 'primary',
19
+ },
20
+ },
21
+ );
22
+
23
+ function Label({
24
+ className,
25
+ variant,
26
+ ...props
27
+ }: React.ComponentProps<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>) {
28
+ return <LabelPrimitive.Root data-slot="label" className={cn(labelVariants({ variant }), className)} {...props} />;
29
+ }
30
+
31
+ export { Label };
@@ -0,0 +1,168 @@
1
+ import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
2
+ import { cva } from "class-variance-authority"
3
+ import { ChevronDownIcon } from "lucide-react"
4
+ import * as React from "react"
5
+
6
+ import { cn } from "../../lib/utils"
7
+
8
+ function NavigationMenu({
9
+ className,
10
+ children,
11
+ viewport = true,
12
+ ...props
13
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
14
+ viewport?: boolean
15
+ }) {
16
+ return (
17
+ <NavigationMenuPrimitive.Root
18
+ data-slot="navigation-menu"
19
+ data-viewport={viewport}
20
+ className={cn(
21
+ "group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
22
+ className
23
+ )}
24
+ {...props}
25
+ >
26
+ {children}
27
+ {viewport && <NavigationMenuViewport />}
28
+ </NavigationMenuPrimitive.Root>
29
+ )
30
+ }
31
+
32
+ function NavigationMenuList({
33
+ className,
34
+ ...props
35
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
36
+ return (
37
+ <NavigationMenuPrimitive.List
38
+ data-slot="navigation-menu-list"
39
+ className={cn(
40
+ "group flex flex-1 list-none items-center justify-center gap-1",
41
+ className
42
+ )}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+
48
+ function NavigationMenuItem({
49
+ className,
50
+ ...props
51
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
52
+ return (
53
+ <NavigationMenuPrimitive.Item
54
+ data-slot="navigation-menu-item"
55
+ className={cn("relative", className)}
56
+ {...props}
57
+ />
58
+ )
59
+ }
60
+
61
+ const navigationMenuTriggerStyle = cva(
62
+ "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[active=true]:bg-accent/50 data-[state=open]:bg-accent/50 data-[active=true]:text-accent-foreground ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1"
63
+ )
64
+
65
+ function NavigationMenuTrigger({
66
+ className,
67
+ children,
68
+ ...props
69
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
70
+ return (
71
+ <NavigationMenuPrimitive.Trigger
72
+ data-slot="navigation-menu-trigger"
73
+ className={cn(navigationMenuTriggerStyle(), "group", className)}
74
+ {...props}
75
+ >
76
+ {children}{" "}
77
+ <ChevronDownIcon
78
+ className="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
79
+ aria-hidden="true"
80
+ />
81
+ </NavigationMenuPrimitive.Trigger>
82
+ )
83
+ }
84
+
85
+ function NavigationMenuContent({
86
+ className,
87
+ ...props
88
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
89
+ return (
90
+ <NavigationMenuPrimitive.Content
91
+ data-slot="navigation-menu-content"
92
+ className={cn(
93
+ "data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full p-2 pr-2.5 md:absolute md:w-auto",
94
+ "group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none",
95
+ className
96
+ )}
97
+ {...props}
98
+ />
99
+ )
100
+ }
101
+
102
+ function NavigationMenuViewport({
103
+ className,
104
+ ...props
105
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
106
+ return (
107
+ <div
108
+ className={cn(
109
+ "absolute top-full left-0 isolate z-50 flex justify-center"
110
+ )}
111
+ >
112
+ <NavigationMenuPrimitive.Viewport
113
+ data-slot="navigation-menu-viewport"
114
+ className={cn(
115
+ "origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border shadow md:w-[var(--radix-navigation-menu-viewport-width)]",
116
+ className
117
+ )}
118
+ {...props}
119
+ />
120
+ </div>
121
+ )
122
+ }
123
+
124
+ function NavigationMenuLink({
125
+ className,
126
+ ...props
127
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
128
+ return (
129
+ <NavigationMenuPrimitive.Link
130
+ data-slot="navigation-menu-link"
131
+ className={cn(
132
+ "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex flex-col gap-1 rounded-sm p-2 text-sm transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4",
133
+ className
134
+ )}
135
+ {...props}
136
+ />
137
+ )
138
+ }
139
+
140
+ function NavigationMenuIndicator({
141
+ className,
142
+ ...props
143
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
144
+ return (
145
+ <NavigationMenuPrimitive.Indicator
146
+ data-slot="navigation-menu-indicator"
147
+ className={cn(
148
+ "data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
149
+ className
150
+ )}
151
+ {...props}
152
+ >
153
+ <div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
154
+ </NavigationMenuPrimitive.Indicator>
155
+ )
156
+ }
157
+
158
+ export {
159
+ NavigationMenu,
160
+ NavigationMenuList,
161
+ NavigationMenuItem,
162
+ NavigationMenuContent,
163
+ NavigationMenuTrigger,
164
+ NavigationMenuLink,
165
+ NavigationMenuIndicator,
166
+ NavigationMenuViewport,
167
+ navigationMenuTriggerStyle,
168
+ }
@@ -0,0 +1,37 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { cn } from '../../lib/utils';
5
+ import { MoreHorizontal } from 'lucide-react';
6
+
7
+ const Pagination = ({ className, ...props }: React.ComponentProps<'nav'>) => (
8
+ <nav
9
+ data-slot="pagination"
10
+ role="navigation"
11
+ aria-label="pagination"
12
+ className={cn('mx-auto flex w-full justify-center', className)}
13
+ {...props}
14
+ />
15
+ );
16
+
17
+ function PaginationContent({ className, ...props }: React.ComponentProps<'ul'>) {
18
+ return <ul data-slot="pagination-content" className={cn('flex flex-row items-center gap-1', className)} {...props} />;
19
+ }
20
+
21
+ function PaginationItem({ className, ...props }: React.ComponentProps<'li'>) {
22
+ return <li data-slot="pagination-item" className={cn('', className)} {...props} />;
23
+ }
24
+
25
+ const PaginationEllipsis = ({ className, ...props }: React.ComponentProps<'span'>) => (
26
+ <span
27
+ data-slot="pagination-ellipsis"
28
+ aria-hidden
29
+ className={cn('flex h-9 w-9 items-center justify-center', className)}
30
+ {...props}
31
+ >
32
+ <MoreHorizontal className="h-4 w-4" />
33
+ <span className="sr-only">More pages</span>
34
+ </span>
35
+ );
36
+
37
+ export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem };
@@ -0,0 +1,21 @@
1
+ 'use client';
2
+ import { useId } from 'react';
3
+
4
+ interface PlaceholderPatternProps {
5
+ className?: string;
6
+ }
7
+
8
+ export function PlaceholderPattern({ className }: PlaceholderPatternProps) {
9
+ const patternId = useId();
10
+
11
+ return (
12
+ <svg className={className} fill="none">
13
+ <defs>
14
+ <pattern id={patternId} x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse">
15
+ <path d="M-3 13 15-5M-5 5l18-18M-1 21 17 3"></path>
16
+ </pattern>
17
+ </defs>
18
+ <rect stroke="none" fill={`url(#${patternId})`} width="100%" height="100%"></rect>
19
+ </svg>
20
+ );
21
+ }
@@ -0,0 +1,50 @@
1
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
2
+ import * as React from 'react';
3
+
4
+ import { cn } from '../../lib/utils';
5
+
6
+ function Popover({
7
+ ...props
8
+ }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
9
+ return <PopoverPrimitive.Root data-slot="popover" {...props} />;
10
+ }
11
+
12
+ function PopoverTrigger({
13
+ ...props
14
+ }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
15
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
16
+ }
17
+
18
+ function PopoverContent({
19
+ className,
20
+ align = 'center',
21
+ sideOffset = 4,
22
+ ...props
23
+ }: React.ComponentProps<typeof PopoverPrimitive.Content>) {
24
+ return (
25
+ <PopoverPrimitive.Portal>
26
+ <PopoverPrimitive.Content
27
+ data-slot="popover-content"
28
+ align={align}
29
+ sideOffset={sideOffset}
30
+ className={cn(
31
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out',
32
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95',
33
+ 'data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',
34
+ 'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
35
+ 'z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden',
36
+ className,
37
+ )}
38
+ {...props}
39
+ />
40
+ </PopoverPrimitive.Portal>
41
+ );
42
+ }
43
+
44
+ function PopoverAnchor({
45
+ ...props
46
+ }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
47
+ return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
48
+ }
49
+
50
+ export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
@@ -0,0 +1,65 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
5
+ import { cn } from '../../lib/utils';
6
+
7
+ function Progress({
8
+ className,
9
+ indicatorClassName,
10
+ value,
11
+ ...props
12
+ }: React.ComponentProps<typeof ProgressPrimitive.Root> & { indicatorClassName?: string }) {
13
+ return (
14
+ <ProgressPrimitive.Root
15
+ data-slot="progress"
16
+ className={cn('relative h-1.5 w-full overflow-hidden rounded-full bg-secondary', className)}
17
+ {...props}
18
+ >
19
+ <ProgressPrimitive.Indicator
20
+ data-slot="progress-indicator"
21
+ className={cn('h-full w-full flex-1 bg-primary transition-all', indicatorClassName)}
22
+ style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
23
+ />
24
+ </ProgressPrimitive.Root>
25
+ );
26
+ }
27
+
28
+ function ProgressCircle({
29
+ className,
30
+ indicatorClassName,
31
+ trackClassName,
32
+ value = 0,
33
+ size = 48,
34
+ strokeWidth = 4,
35
+ children,
36
+ ...props
37
+ }: React.ComponentProps<'div'> & {
38
+ value?: number;
39
+ size?: number;
40
+ strokeWidth?: number;
41
+ indicatorClassName?: string;
42
+ trackClassName?: string;
43
+ children?: React.ReactNode;
44
+ }) {
45
+ const radius = (size - strokeWidth) / 2;
46
+ const circumference = radius * 2 * Math.PI;
47
+ const offset = circumference - (value / 100) * circumference;
48
+
49
+ return (
50
+ <div
51
+ data-slot="progress-circle"
52
+ className={cn('relative inline-flex items-center justify-center', className)}
53
+ style={{ width: size, height: size }}
54
+ {...props}
55
+ >
56
+ <svg className="absolute inset-0 -rotate-90" width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
57
+ <circle cx={size / 2} cy={size / 2} r={radius} stroke="currentColor" strokeWidth={strokeWidth} fill="none" className={cn('text-secondary', trackClassName)} />
58
+ <circle cx={size / 2} cy={size / 2} r={radius} stroke="currentColor" strokeWidth={strokeWidth} fill="none" strokeDasharray={circumference} strokeDashoffset={offset} strokeLinecap="round" className={cn('text-primary transition-all duration-300 ease-in-out', indicatorClassName)} />
59
+ </svg>
60
+ {children && <div className="relative z-10 flex items-center justify-center text-sm font-medium">{children}</div>}
61
+ </div>
62
+ );
63
+ }
64
+
65
+ export { Progress, ProgressCircle };
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
5
+ import { cva, type VariantProps } from 'class-variance-authority';
6
+ import { Circle } from 'lucide-react';
7
+ import { cn } from '../../lib/utils';
8
+
9
+ const radioGroupVariants = cva('grid gap-2.5', {
10
+ variants: {
11
+ variant: { primary: '', mono: '' },
12
+ size: { sm: '', md: '', lg: '' },
13
+ },
14
+ defaultVariants: { variant: 'primary', size: 'md' },
15
+ });
16
+
17
+ const RadioGroupContext = React.createContext<{ variant: 'primary' | 'mono'; size: 'sm' | 'md' | 'lg' }>({
18
+ variant: 'primary',
19
+ size: 'md',
20
+ });
21
+
22
+ function RadioGroup({
23
+ className,
24
+ variant,
25
+ size,
26
+ ...props
27
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Root> & VariantProps<typeof radioGroupVariants>) {
28
+ return (
29
+ <RadioGroupContext.Provider value={{ variant: variant ?? 'primary', size: size ?? 'md' }}>
30
+ <RadioGroupPrimitive.Root
31
+ data-slot="radio-group"
32
+ className={cn(radioGroupVariants({ variant, size }), className)}
33
+ {...props}
34
+ />
35
+ </RadioGroupContext.Provider>
36
+ );
37
+ }
38
+
39
+ const radioItemVariants = cva(
40
+ 'peer aspect-square rounded-full border outline-hidden ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 border-input text-primary data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground',
41
+ {
42
+ variants: {
43
+ size: {
44
+ sm: 'size-4.5 [&_svg]:size-2',
45
+ md: 'size-5 [&_svg]:size-2.5',
46
+ lg: 'size-5.5 [&_svg]:size-3',
47
+ },
48
+ },
49
+ defaultVariants: { size: 'md' },
50
+ },
51
+ );
52
+
53
+ function RadioGroupItem({
54
+ className,
55
+ size,
56
+ ...props
57
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Item> & VariantProps<typeof radioItemVariants>) {
58
+ const { size: contextSize } = React.useContext(RadioGroupContext);
59
+ const effectiveSize = size ?? contextSize;
60
+ return (
61
+ <RadioGroupPrimitive.Item
62
+ data-slot="radio-group-item"
63
+ className={cn(radioItemVariants({ size: effectiveSize }), className)}
64
+ {...props}
65
+ >
66
+ <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
67
+ <Circle className="fill-current text-current" />
68
+ </RadioGroupPrimitive.Indicator>
69
+ </RadioGroupPrimitive.Item>
70
+ );
71
+ }
72
+
73
+ export { RadioGroup, RadioGroupItem };
@@ -0,0 +1,39 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import * as ResizablePrimitive from 'react-resizable-panels';
5
+ import { GripVertical } from 'lucide-react';
6
+ import { cn } from '../../lib/utils';
7
+
8
+ const ResizablePanelGroup = ({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
9
+ <ResizablePrimitive.PanelGroup
10
+ data-slot="resizable-panel-group"
11
+ className={cn('flex h-full w-full data-[panel-group-direction=vertical]:flex-col', className)}
12
+ {...props}
13
+ />
14
+ );
15
+
16
+ const ResizablePanel = ResizablePrimitive.Panel;
17
+
18
+ const ResizableHandle = ({
19
+ withHandle,
20
+ className,
21
+ ...props
22
+ }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & { withHandle?: boolean }) => (
23
+ <ResizablePrimitive.PanelResizeHandle
24
+ data-slot="resizable-handle"
25
+ className={cn(
26
+ 'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
27
+ className,
28
+ )}
29
+ {...props}
30
+ >
31
+ {withHandle && (
32
+ <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
33
+ <GripVertical className="h-2.5 w-2.5" />
34
+ </div>
35
+ )}
36
+ </ResizablePrimitive.PanelResizeHandle>
37
+ );
38
+
39
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup };