@devxcrew/react-ui 0.0.0-stage → 0.1.7

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 (326) hide show
  1. package/README.md +85 -2
  2. package/package.json +105 -4
  3. package/src/blocks/agent-chat-workspace/agent-chat-workspace.tsx +162 -0
  4. package/src/blocks/agent-chat-workspace/index.ts +2 -0
  5. package/src/blocks/agent-provider-settings/agent-provider-settings.tsx +183 -0
  6. package/src/blocks/agent-provider-settings/index.ts +2 -0
  7. package/src/blocks/agent-task-workspace/agent-task-workspace.tsx +48 -0
  8. package/src/blocks/agent-task-workspace/index.ts +2 -0
  9. package/src/blocks/analysis-context/analysis-context.tsx +6 -0
  10. package/src/blocks/analysis-context/index.ts +1 -0
  11. package/src/blocks/app-header/app-header.tsx +159 -0
  12. package/src/blocks/app-header/index.ts +2 -0
  13. package/src/blocks/archived-chat-workspace/archived-chat-workspace.tsx +29 -0
  14. package/src/blocks/archived-chat-workspace/index.ts +2 -0
  15. package/src/blocks/auth/README.md +32 -0
  16. package/src/blocks/auth/admin-login-page.tsx +15 -0
  17. package/src/blocks/auth/admin-password-forgot-page.tsx +5 -0
  18. package/src/blocks/auth/auth-page-layout.tsx +90 -0
  19. package/src/blocks/auth/client-login-page.tsx +20 -0
  20. package/src/blocks/auth/client-password-forgot-page.tsx +5 -0
  21. package/src/blocks/auth/identity-management-desk.tsx +530 -0
  22. package/src/blocks/auth/index.ts +12 -0
  23. package/src/blocks/auth/login-page.tsx +206 -0
  24. package/src/blocks/auth/password-forgot-page.tsx +60 -0
  25. package/src/blocks/auth/portal-pages.tsx +32 -0
  26. package/src/blocks/auth/privileged-desk.tsx +55 -0
  27. package/src/blocks/auth/register-page.tsx +117 -0
  28. package/src/blocks/auth/session-boundary.tsx +296 -0
  29. package/src/blocks/auth/super-admin-login-page.tsx +15 -0
  30. package/src/blocks/auth/super-admin-password-forgot-page.tsx +5 -0
  31. package/src/blocks/blog/blog-card.tsx +156 -0
  32. package/src/blocks/blog/blog-reader.tsx +175 -0
  33. package/src/blocks/blog/blog-types.ts +47 -0
  34. package/src/blocks/blog/index.ts +3 -0
  35. package/src/blocks/chat-composer/chat-composer.tsx +140 -0
  36. package/src/blocks/chat-composer/index.ts +1 -0
  37. package/src/blocks/chat-history/chat-history.tsx +59 -0
  38. package/src/blocks/chat-history/index.ts +1 -0
  39. package/src/blocks/chat-response-progress/chat-response-progress.tsx +34 -0
  40. package/src/blocks/chat-response-progress/index.ts +2 -0
  41. package/src/blocks/chat-runtime-controls/chat-runtime-controls.tsx +56 -0
  42. package/src/blocks/chat-runtime-controls/index.ts +2 -0
  43. package/src/blocks/chat-runtime-trace/chat-runtime-trace.tsx +71 -0
  44. package/src/blocks/chat-runtime-trace/index.ts +2 -0
  45. package/src/blocks/codex-connection-settings/codex-connection-settings.tsx +42 -0
  46. package/src/blocks/codex-connection-settings/index.ts +1 -0
  47. package/src/blocks/dropzone/dropzone-file-item.tsx +113 -0
  48. package/src/blocks/dropzone/dropzone-types.ts +32 -0
  49. package/src/blocks/dropzone/dropzone.tsx +216 -0
  50. package/src/blocks/dropzone/index.ts +3 -0
  51. package/src/blocks/ecommerce/cart/cart-drawer.tsx +228 -0
  52. package/src/blocks/ecommerce/cart/cart-types.ts +27 -0
  53. package/src/blocks/ecommerce/cart/index.ts +2 -0
  54. package/src/blocks/ecommerce/categories/categories-types.ts +23 -0
  55. package/src/blocks/ecommerce/categories/category-showcase.tsx +125 -0
  56. package/src/blocks/ecommerce/categories/index.ts +2 -0
  57. package/src/blocks/ecommerce/checkout/checkout-types.ts +48 -0
  58. package/src/blocks/ecommerce/checkout/checkout-wizard.tsx +468 -0
  59. package/src/blocks/ecommerce/checkout/index.ts +2 -0
  60. package/src/blocks/ecommerce/comparison/comparison-types.ts +28 -0
  61. package/src/blocks/ecommerce/comparison/index.ts +2 -0
  62. package/src/blocks/ecommerce/comparison/product-comparison.tsx +174 -0
  63. package/src/blocks/ecommerce/coupon-wallet/coupon-wallet-types.ts +21 -0
  64. package/src/blocks/ecommerce/coupon-wallet/coupon-wallet.tsx +154 -0
  65. package/src/blocks/ecommerce/coupon-wallet/index.ts +2 -0
  66. package/src/blocks/ecommerce/delivery-tracker/delivery-tracker-types.ts +20 -0
  67. package/src/blocks/ecommerce/delivery-tracker/delivery-tracker.tsx +169 -0
  68. package/src/blocks/ecommerce/delivery-tracker/index.ts +2 -0
  69. package/src/blocks/ecommerce/index.ts +12 -0
  70. package/src/blocks/ecommerce/payment-methods/index.ts +2 -0
  71. package/src/blocks/ecommerce/payment-methods/payment-method-selector.tsx +224 -0
  72. package/src/blocks/ecommerce/payment-methods/payment-methods-types.ts +21 -0
  73. package/src/blocks/ecommerce/price-history/index.ts +2 -0
  74. package/src/blocks/ecommerce/price-history/price-history-chart.tsx +217 -0
  75. package/src/blocks/ecommerce/price-history/price-history-types.ts +16 -0
  76. package/src/blocks/ecommerce/reviews/index.ts +2 -0
  77. package/src/blocks/ecommerce/reviews/reviews-section.tsx +309 -0
  78. package/src/blocks/ecommerce/reviews/reviews-types.ts +26 -0
  79. package/src/blocks/ecommerce/wishlist/index.ts +2 -0
  80. package/src/blocks/ecommerce/wishlist/wishlist-grid.tsx +149 -0
  81. package/src/blocks/ecommerce/wishlist/wishlist-types.ts +19 -0
  82. package/src/blocks/execution-status/README.md +25 -0
  83. package/src/blocks/execution-status/execution-status.tsx +135 -0
  84. package/src/blocks/execution-status/index.ts +2 -0
  85. package/src/blocks/file-tree/file-icons.tsx +84 -0
  86. package/src/blocks/file-tree/file-tree-node.tsx +158 -0
  87. package/src/blocks/file-tree/file-tree-types.ts +33 -0
  88. package/src/blocks/file-tree/file-tree.tsx +163 -0
  89. package/src/blocks/file-tree/index.ts +5 -0
  90. package/src/blocks/filter-builder/filter-builder.tsx +169 -0
  91. package/src/blocks/filter-builder/filter-row.tsx +164 -0
  92. package/src/blocks/filter-builder/filter-types.ts +61 -0
  93. package/src/blocks/filter-builder/index.ts +12 -0
  94. package/src/blocks/footer/footer-types.ts +35 -0
  95. package/src/blocks/footer/index.ts +2 -0
  96. package/src/blocks/footer/site-footer.tsx +212 -0
  97. package/src/blocks/form/form-block.tsx +113 -0
  98. package/src/blocks/form/form-lookup-field.tsx +60 -0
  99. package/src/blocks/form/index.ts +4 -0
  100. package/src/blocks/handover-stack/handover-stack.tsx +41 -0
  101. package/src/blocks/handover-stack/index.ts +1 -0
  102. package/src/blocks/idea-handover/idea-handover-readiness.ts +41 -0
  103. package/src/blocks/idea-handover/idea-handover-workspace.tsx +150 -0
  104. package/src/blocks/idea-handover/index.ts +4 -0
  105. package/src/blocks/kanban/index.ts +11 -0
  106. package/src/blocks/kanban/kanban-board.tsx +146 -0
  107. package/src/blocks/kanban/kanban-card.tsx +149 -0
  108. package/src/blocks/kanban/kanban-column.tsx +102 -0
  109. package/src/blocks/kanban/kanban-types.ts +38 -0
  110. package/src/blocks/loader/global-loader.tsx +90 -0
  111. package/src/blocks/loader/index.ts +1 -0
  112. package/src/blocks/mascot/README.md +21 -0
  113. package/src/blocks/mascot/index.ts +2 -0
  114. package/src/blocks/mascot/mascot.tsx +202 -0
  115. package/src/blocks/master-list/README.md +21 -0
  116. package/src/blocks/master-list/index.ts +12 -0
  117. package/src/blocks/master-list/master-form.tsx +157 -0
  118. package/src/blocks/master-list/master-list-desk.tsx +370 -0
  119. package/src/blocks/master-list/master-list.tsx +189 -0
  120. package/src/blocks/master-list/types.ts +18 -0
  121. package/src/blocks/mermaid-preview/index.ts +1 -0
  122. package/src/blocks/mermaid-preview/mermaid-preview.tsx +164 -0
  123. package/src/blocks/notifications/README.md +7 -0
  124. package/src/blocks/notifications/index.ts +1 -0
  125. package/src/blocks/notifications/notification-center-page.tsx +73 -0
  126. package/src/blocks/pricing/index.ts +7 -0
  127. package/src/blocks/pricing/pricing-table.tsx +173 -0
  128. package/src/blocks/pricing/pricing-types.ts +34 -0
  129. package/src/blocks/product-card/index.ts +2 -0
  130. package/src/blocks/product-card/product-card-types.ts +35 -0
  131. package/src/blocks/product-card/product-card.tsx +183 -0
  132. package/src/blocks/table/data-table-block.tsx +313 -0
  133. package/src/blocks/table/data-table-filter-menu.tsx +48 -0
  134. package/src/blocks/table/data-table-icon-menu-trigger.tsx +44 -0
  135. package/src/blocks/table/data-table-menu-content.tsx +32 -0
  136. package/src/blocks/table/data-table-pagination.tsx +149 -0
  137. package/src/blocks/table/data-table-row-actions.tsx +53 -0
  138. package/src/blocks/table/data-table-status.tsx +42 -0
  139. package/src/blocks/table/data-table-toolbar.tsx +124 -0
  140. package/src/blocks/table/data-table-totals.tsx +31 -0
  141. package/src/blocks/table/index.ts +13 -0
  142. package/src/blocks/workspace/index.ts +19 -0
  143. package/src/blocks/workspace/workspace-action-card.tsx +73 -0
  144. package/src/blocks/workspace/workspace-application-header.tsx +67 -0
  145. package/src/blocks/workspace/workspace-entity-card.tsx +48 -0
  146. package/src/blocks/workspace/workspace-health-summary.tsx +15 -0
  147. package/src/blocks/workspace/workspace-metric-card.tsx +97 -0
  148. package/src/blocks/workspace/workspace-page-header.tsx +43 -0
  149. package/src/blocks/workspace/workspace-publish-status.tsx +15 -0
  150. package/src/blocks/workspace/workspace-route-checklist.tsx +28 -0
  151. package/src/blocks/workspace/workspace-runtime-status.tsx +48 -0
  152. package/src/blocks/workspace/workspace-section-card.tsx +42 -0
  153. package/src/components/accordion.tsx +65 -0
  154. package/src/components/alert-dialog.tsx +160 -0
  155. package/src/components/alert.tsx +68 -0
  156. package/src/components/aspect-ratio.tsx +22 -0
  157. package/src/components/attachment.tsx +195 -0
  158. package/src/components/avatar.tsx +90 -0
  159. package/src/components/badge.tsx +55 -0
  160. package/src/components/breadcrumb.tsx +100 -0
  161. package/src/components/bubble.tsx +123 -0
  162. package/src/components/button-group.tsx +79 -0
  163. package/src/components/button.tsx +71 -0
  164. package/src/components/calendar.tsx +185 -0
  165. package/src/components/card.tsx +100 -0
  166. package/src/components/carousel.tsx +229 -0
  167. package/src/components/chart.tsx +338 -0
  168. package/src/components/checkbox.tsx +27 -0
  169. package/src/components/collapsible.tsx +15 -0
  170. package/src/components/combobox.tsx +269 -0
  171. package/src/components/command.tsx +181 -0
  172. package/src/components/compact-model-switcher.tsx +128 -0
  173. package/src/components/context-menu.tsx +244 -0
  174. package/src/components/dialog.tsx +138 -0
  175. package/src/components/direction.tsx +1 -0
  176. package/src/components/drawer.tsx +208 -0
  177. package/src/components/dropdown-menu.tsx +257 -0
  178. package/src/components/empty.tsx +93 -0
  179. package/src/components/field.tsx +232 -0
  180. package/src/components/hover-card.tsx +45 -0
  181. package/src/components/input-group.tsx +146 -0
  182. package/src/components/input-otp.tsx +83 -0
  183. package/src/components/input.tsx +19 -0
  184. package/src/components/item.tsx +188 -0
  185. package/src/components/kbd.tsx +26 -0
  186. package/src/components/label.tsx +17 -0
  187. package/src/components/markdown-content.tsx +113 -0
  188. package/src/components/marker.tsx +67 -0
  189. package/src/components/menubar.tsx +267 -0
  190. package/src/components/message-scroller.tsx +91 -0
  191. package/src/components/message.tsx +84 -0
  192. package/src/components/native-select.tsx +54 -0
  193. package/src/components/navigation-menu.tsx +160 -0
  194. package/src/components/pagination.tsx +118 -0
  195. package/src/components/popover.tsx +74 -0
  196. package/src/components/progress.tsx +82 -0
  197. package/src/components/questionnaire.tsx +150 -0
  198. package/src/components/radio-group.tsx +35 -0
  199. package/src/components/resizable.tsx +41 -0
  200. package/src/components/rich-text-editor.tsx +604 -0
  201. package/src/components/scroll-area.tsx +47 -0
  202. package/src/components/select.tsx +189 -0
  203. package/src/components/separator.tsx +18 -0
  204. package/src/components/sheet.tsx +125 -0
  205. package/src/components/sidebar.tsx +693 -0
  206. package/src/components/skeleton.tsx +13 -0
  207. package/src/components/slider.tsx +51 -0
  208. package/src/components/sonner.tsx +45 -0
  209. package/src/components/sparkline.tsx +231 -0
  210. package/src/components/spinner.tsx +20 -0
  211. package/src/components/status-badge.tsx +114 -0
  212. package/src/components/switch.tsx +31 -0
  213. package/src/components/table.tsx +91 -0
  214. package/src/components/tabs.tsx +72 -0
  215. package/src/components/textarea.tsx +17 -0
  216. package/src/components/toast.tsx +222 -0
  217. package/src/components/toggle-group.tsx +85 -0
  218. package/src/components/toggle.tsx +42 -0
  219. package/src/components/tooltip.tsx +53 -0
  220. package/src/design-system/README.md +55 -0
  221. package/src/design-system/action-intents.ts +21 -0
  222. package/src/design-system/agent-manifest.ts +83 -0
  223. package/src/design-system/block-registry.ts +272 -0
  224. package/src/design-system/component-registry.ts +142 -0
  225. package/src/design-system/contracts.ts +69 -0
  226. package/src/design-system/defaults.ts +3 -0
  227. package/src/design-system/index.ts +29 -0
  228. package/src/design-system/mcp-server.ts +156 -0
  229. package/src/design-system/page-registry.ts +74 -0
  230. package/src/design-system/selection.ts +67 -0
  231. package/src/design-system/template-registry.ts +33 -0
  232. package/src/features/interface-topology/index.ts +14 -0
  233. package/src/features/interface-topology/interface-topology.types.ts +40 -0
  234. package/src/features/interface-topology/topology-control.tsx +18 -0
  235. package/src/features/interface-topology/topology-inspector.tsx +228 -0
  236. package/src/features/interface-topology/topology-marker.tsx +47 -0
  237. package/src/features/interface-topology/topology-region.tsx +44 -0
  238. package/src/features/interface-topology/use-interface-topology.ts +178 -0
  239. package/src/hooks/use-mobile.ts +19 -0
  240. package/src/hooks/use-scroll-follow.ts +22 -0
  241. package/src/index.ts +11 -0
  242. package/src/layouts/README.md +65 -0
  243. package/src/layouts/agent-workspace/agent-activity-rail.tsx +101 -0
  244. package/src/layouts/agent-workspace/agent-workspace.tsx +27 -0
  245. package/src/layouts/agent-workspace/agent-workspace.types.ts +28 -0
  246. package/src/layouts/agent-workspace/index.ts +7 -0
  247. package/src/layouts/blog-header/blog-header-types.ts +25 -0
  248. package/src/layouts/blog-header/blog-header.tsx +172 -0
  249. package/src/layouts/blog-header/index.ts +2 -0
  250. package/src/layouts/documentation-workspace/README.md +8 -0
  251. package/src/layouts/documentation-workspace/documentation-workspace.tsx +34 -0
  252. package/src/layouts/documentation-workspace/index.ts +1 -0
  253. package/src/layouts/ecommerce-header/ecommerce-actions.tsx +89 -0
  254. package/src/layouts/ecommerce-header/ecommerce-announcement.tsx +43 -0
  255. package/src/layouts/ecommerce-header/ecommerce-drawer.tsx +97 -0
  256. package/src/layouts/ecommerce-header/ecommerce-header-types.ts +59 -0
  257. package/src/layouts/ecommerce-header/ecommerce-header.tsx +47 -0
  258. package/src/layouts/ecommerce-header/ecommerce-navigation.tsx +98 -0
  259. package/src/layouts/ecommerce-header/ecommerce-search.tsx +86 -0
  260. package/src/layouts/ecommerce-header/index.ts +2 -0
  261. package/src/layouts/main-workspace/index.ts +28 -0
  262. package/src/layouts/mdi/index.ts +1 -0
  263. package/src/layouts/mdi/mdi.tsx +20 -0
  264. package/src/layouts/mdi-main/index.ts +27 -0
  265. package/src/layouts/mdi-main/mdi-app-catalog.generated.ts +159 -0
  266. package/src/layouts/mdi-main/mdi-app-catalog.ts +76 -0
  267. package/src/layouts/mdi-main/mdi-app-switcher.tsx +107 -0
  268. package/src/layouts/mdi-main/mdi-feature-settings.tsx +135 -0
  269. package/src/layouts/mdi-main/mdi-global-search.tsx +192 -0
  270. package/src/layouts/mdi-main/mdi-main.tsx +241 -0
  271. package/src/layouts/mdi-main/mdi-notifications-menu.tsx +197 -0
  272. package/src/layouts/mdi-main/mdi-profile-menu.tsx +79 -0
  273. package/src/layouts/mdi-main/mdi-sidebar-navigation.tsx +226 -0
  274. package/src/layouts/mdi-main/mdi-sidebar.tsx +110 -0
  275. package/src/layouts/mdi-main/mdi-status-bar.tsx +26 -0
  276. package/src/layouts/mdi-main/mdi-top-menu-control.ts +4 -0
  277. package/src/layouts/mdi-main/mdi-top-menu.tsx +117 -0
  278. package/src/layouts/mdi-main/mdi-topology.tsx +297 -0
  279. package/src/layouts/mdi-main/mdi-tweak-panel.tsx +104 -0
  280. package/src/layouts/mdi-main/mdi-types.ts +131 -0
  281. package/src/layouts/mdi-main/use-mdi-features.ts +36 -0
  282. package/src/layouts/mdi-main/use-mdi-sidebar-state.ts +59 -0
  283. package/src/layouts/site-header/announcement-bar.tsx +55 -0
  284. package/src/layouts/site-header/category-strip.tsx +41 -0
  285. package/src/layouts/site-header/index.ts +16 -0
  286. package/src/layouts/site-header/main-navbar.tsx +179 -0
  287. package/src/layouts/site-header/mobile-drawer.tsx +140 -0
  288. package/src/layouts/site-header/site-header-types.ts +63 -0
  289. package/src/layouts/site-header/site-header.tsx +58 -0
  290. package/src/lib/random-id.ts +19 -0
  291. package/src/lib/utils.ts +6 -0
  292. package/src/providers/pdf-provider.ts +137 -0
  293. package/src/styles/globals.css +374 -0
  294. package/src/templates/README.md +12 -0
  295. package/src/templates/dashboard-01/components/app-sidebar.tsx +177 -0
  296. package/src/templates/dashboard-01/components/chart-area-interactive.tsx +276 -0
  297. package/src/templates/dashboard-01/components/data-table-cell-viewer.tsx +213 -0
  298. package/src/templates/dashboard-01/components/data-table.tsx +577 -0
  299. package/src/templates/dashboard-01/components/nav-documents.tsx +79 -0
  300. package/src/templates/dashboard-01/components/nav-main.tsx +55 -0
  301. package/src/templates/dashboard-01/components/nav-secondary.tsx +39 -0
  302. package/src/templates/dashboard-01/components/nav-user.tsx +97 -0
  303. package/src/templates/dashboard-01/components/section-cards.tsx +99 -0
  304. package/src/templates/dashboard-01/components/site-header.tsx +14 -0
  305. package/src/templates/dashboard-01/data.json +614 -0
  306. package/src/templates/dashboard-01/index.ts +7 -0
  307. package/src/templates/documentation-sidebar/app-sidebar.tsx +95 -0
  308. package/src/templates/documentation-sidebar/index.ts +2 -0
  309. package/src/templates/sidebar-07/components/app-sidebar.tsx +175 -0
  310. package/src/templates/sidebar-07/components/nav-main.tsx +64 -0
  311. package/src/templates/sidebar-07/components/nav-projects.tsx +79 -0
  312. package/src/templates/sidebar-07/components/nav-user.tsx +105 -0
  313. package/src/templates/sidebar-07/components/team-switcher.tsx +94 -0
  314. package/src/templates/sidebar-07/index.ts +1 -0
  315. package/src/templates/ui-page/index.ts +7 -0
  316. package/src/templates/ui-page/ui-browser-frame.tsx +27 -0
  317. package/src/templates/ui-page/ui-template-code.tsx +48 -0
  318. package/src/templates/ui-page/ui-template-header.tsx +87 -0
  319. package/src/templates/ui-page/ui-template-navigation.tsx +60 -0
  320. package/src/templates/ui-page/ui-template-page.tsx +97 -0
  321. package/src/theme/index.ts +12 -0
  322. package/src/theme/theme-config.ts +30 -0
  323. package/src/theme/theme-provider.tsx +142 -0
  324. package/src/theme/theme-selector.tsx +75 -0
  325. package/src/tokens/index.ts +15 -0
  326. package/src/vite-env.d.ts +3 -0
@@ -0,0 +1,229 @@
1
+ import * as React from 'react'
2
+ import { cn } from '../lib/utils'
3
+ import useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'
4
+
5
+ import { Button } from '@devxcrew/react-ui/components/button'
6
+ import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
7
+
8
+ type CarouselApi = UseEmblaCarouselType[1]
9
+ type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
10
+ type CarouselOptions = UseCarouselParameters[0]
11
+ type CarouselPlugin = UseCarouselParameters[1]
12
+
13
+ type CarouselProps = {
14
+ opts?: CarouselOptions
15
+ plugins?: CarouselPlugin
16
+ orientation?: 'horizontal' | 'vertical'
17
+ setApi?: (api: CarouselApi) => void
18
+ }
19
+
20
+ type CarouselContextProps = {
21
+ carouselRef: ReturnType<typeof useEmblaCarousel>[0]
22
+ api: ReturnType<typeof useEmblaCarousel>[1]
23
+ scrollPrev: () => void
24
+ scrollNext: () => void
25
+ canScrollPrev: boolean
26
+ canScrollNext: boolean
27
+ } & CarouselProps
28
+
29
+ const CarouselContext = React.createContext<CarouselContextProps | null>(null)
30
+
31
+ function useCarousel() {
32
+ const context = React.useContext(CarouselContext)
33
+
34
+ if (!context) {
35
+ throw new Error('useCarousel must be used within a <Carousel />')
36
+ }
37
+
38
+ return context
39
+ }
40
+
41
+ function Carousel({
42
+ orientation = 'horizontal',
43
+ opts,
44
+ setApi,
45
+ plugins,
46
+ className,
47
+ children,
48
+ ...props
49
+ }: React.ComponentProps<'div'> & CarouselProps) {
50
+ const [carouselRef, api] = useEmblaCarousel(
51
+ {
52
+ ...opts,
53
+ axis: orientation === 'horizontal' ? 'x' : 'y',
54
+ },
55
+ plugins,
56
+ )
57
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false)
58
+ const [canScrollNext, setCanScrollNext] = React.useState(false)
59
+
60
+ const onSelect = React.useCallback((api: CarouselApi) => {
61
+ if (!api) return
62
+ setCanScrollPrev(api.canScrollPrev())
63
+ setCanScrollNext(api.canScrollNext())
64
+ }, [])
65
+
66
+ const scrollPrev = React.useCallback(() => {
67
+ api?.scrollPrev()
68
+ }, [api])
69
+
70
+ const scrollNext = React.useCallback(() => {
71
+ api?.scrollNext()
72
+ }, [api])
73
+
74
+ const handleKeyDown = React.useCallback(
75
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
76
+ if (event.key === 'ArrowLeft') {
77
+ event.preventDefault()
78
+ scrollPrev()
79
+ } else if (event.key === 'ArrowRight') {
80
+ event.preventDefault()
81
+ scrollNext()
82
+ }
83
+ },
84
+ [scrollPrev, scrollNext],
85
+ )
86
+
87
+ React.useEffect(() => {
88
+ if (!api || !setApi) return
89
+ setApi(api)
90
+ }, [api, setApi])
91
+
92
+ React.useEffect(() => {
93
+ if (!api) return
94
+ onSelect(api)
95
+ api.on('reInit', onSelect)
96
+ api.on('select', onSelect)
97
+
98
+ return () => {
99
+ api?.off('select', onSelect)
100
+ }
101
+ }, [api, onSelect])
102
+
103
+ return (
104
+ <CarouselContext.Provider
105
+ value={{
106
+ carouselRef,
107
+ api: api,
108
+ opts,
109
+ orientation: orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),
110
+ scrollPrev,
111
+ scrollNext,
112
+ canScrollPrev,
113
+ canScrollNext,
114
+ }}
115
+ >
116
+ <div
117
+ onKeyDownCapture={handleKeyDown}
118
+ className={cn('relative', className)}
119
+ role="region"
120
+ aria-roledescription="carousel"
121
+ data-slot="carousel"
122
+ {...props}
123
+ >
124
+ {children}
125
+ </div>
126
+ </CarouselContext.Provider>
127
+ )
128
+ }
129
+
130
+ function CarouselContent({ className, ...props }: React.ComponentProps<'div'>) {
131
+ const { carouselRef, orientation } = useCarousel()
132
+
133
+ return (
134
+ <div ref={carouselRef} className="overflow-hidden" data-slot="carousel-content">
135
+ <div
136
+ className={cn('flex', orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col', className)}
137
+ {...props}
138
+ />
139
+ </div>
140
+ )
141
+ }
142
+
143
+ function CarouselItem({ className, ...props }: React.ComponentProps<'div'>) {
144
+ const { orientation } = useCarousel()
145
+
146
+ return (
147
+ <div
148
+ role="group"
149
+ aria-roledescription="slide"
150
+ data-slot="carousel-item"
151
+ className={cn(
152
+ 'min-w-0 shrink-0 grow-0 basis-full',
153
+ orientation === 'horizontal' ? 'pl-4' : 'pt-4',
154
+ className,
155
+ )}
156
+ {...props}
157
+ />
158
+ )
159
+ }
160
+
161
+ function CarouselPrevious({
162
+ className,
163
+ variant = 'outline',
164
+ size = 'icon-sm',
165
+ ...props
166
+ }: React.ComponentProps<typeof Button>) {
167
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel()
168
+
169
+ return (
170
+ <Button
171
+ data-slot="carousel-previous"
172
+ variant={variant}
173
+ size={size}
174
+ className={cn(
175
+ 'absolute touch-manipulation rounded-full',
176
+ orientation === 'horizontal'
177
+ ? 'inset-y-0 -left-12 my-auto'
178
+ : '-top-12 left-1/2 -translate-x-1/2 rotate-90',
179
+ className,
180
+ )}
181
+ disabled={!canScrollPrev}
182
+ onClick={scrollPrev}
183
+ {...props}
184
+ >
185
+ <ChevronLeftIcon />
186
+ <span className="sr-only">Previous slide</span>
187
+ </Button>
188
+ )
189
+ }
190
+
191
+ function CarouselNext({
192
+ className,
193
+ variant = 'outline',
194
+ size = 'icon-sm',
195
+ ...props
196
+ }: React.ComponentProps<typeof Button>) {
197
+ const { orientation, scrollNext, canScrollNext } = useCarousel()
198
+
199
+ return (
200
+ <Button
201
+ data-slot="carousel-next"
202
+ variant={variant}
203
+ size={size}
204
+ className={cn(
205
+ 'absolute touch-manipulation rounded-full',
206
+ orientation === 'horizontal'
207
+ ? 'inset-y-0 -right-12 my-auto'
208
+ : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
209
+ className,
210
+ )}
211
+ disabled={!canScrollNext}
212
+ onClick={scrollNext}
213
+ {...props}
214
+ >
215
+ <ChevronRightIcon />
216
+ <span className="sr-only">Next slide</span>
217
+ </Button>
218
+ )
219
+ }
220
+
221
+ export {
222
+ type CarouselApi,
223
+ Carousel,
224
+ CarouselContent,
225
+ CarouselItem,
226
+ CarouselPrevious,
227
+ CarouselNext,
228
+ useCarousel,
229
+ }
@@ -0,0 +1,338 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { cn } from '../lib/utils'
5
+ import * as RechartsPrimitive from 'recharts'
6
+ import type { TooltipValueType } from 'recharts'
7
+
8
+ // Format: { THEME_NAME: CSS_SELECTOR }
9
+ const THEMES = { light: '', dark: '.dark' } as const
10
+
11
+ const INITIAL_DIMENSION = { width: 320, height: 200 } as const
12
+ type TooltipNameType = number | string
13
+
14
+ export type ChartConfig = Record<
15
+ string,
16
+ {
17
+ label?: React.ReactNode
18
+ icon?: React.ComponentType
19
+ } & (
20
+ | { color?: string; theme?: never }
21
+ | { color?: never; theme: Record<keyof typeof THEMES, string> }
22
+ )
23
+ >
24
+
25
+ type ChartContextProps = {
26
+ config: ChartConfig
27
+ }
28
+
29
+ const ChartContext = React.createContext<ChartContextProps | null>(null)
30
+
31
+ function useChart() {
32
+ const context = React.useContext(ChartContext)
33
+
34
+ if (!context) {
35
+ throw new Error('useChart must be used within a <ChartContainer />')
36
+ }
37
+
38
+ return context
39
+ }
40
+
41
+ function ChartContainer({
42
+ id,
43
+ className,
44
+ children,
45
+ config,
46
+ initialDimension = INITIAL_DIMENSION,
47
+ ...props
48
+ }: React.ComponentProps<'div'> & {
49
+ config: ChartConfig
50
+ children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>['children']
51
+ initialDimension?: {
52
+ width: number
53
+ height: number
54
+ }
55
+ }) {
56
+ const uniqueId = React.useId()
57
+ const chartId = `chart-${id ?? uniqueId.replace(/:/g, '')}`
58
+
59
+ return (
60
+ <ChartContext.Provider value={{ config }}>
61
+ <div
62
+ data-slot="chart"
63
+ data-chart={chartId}
64
+ className={cn(
65
+ "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
66
+ className,
67
+ )}
68
+ {...props}
69
+ >
70
+ <ChartStyle id={chartId} config={config} />
71
+ <RechartsPrimitive.ResponsiveContainer initialDimension={initialDimension}>
72
+ {children}
73
+ </RechartsPrimitive.ResponsiveContainer>
74
+ </div>
75
+ </ChartContext.Provider>
76
+ )
77
+ }
78
+
79
+ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
80
+ const colorConfig = Object.entries(config).filter(([, config]) => config.theme ?? config.color)
81
+
82
+ if (!colorConfig.length) {
83
+ return null
84
+ }
85
+
86
+ return (
87
+ <style
88
+ dangerouslySetInnerHTML={{
89
+ __html: Object.entries(THEMES)
90
+ .map(
91
+ ([theme, prefix]) => `
92
+ ${prefix} [data-chart=${id}] {
93
+ ${colorConfig
94
+ .map(([key, itemConfig]) => {
95
+ const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color
96
+ return color ? ` --color-${key}: ${color};` : null
97
+ })
98
+ .join('\n')}
99
+ }
100
+ `,
101
+ )
102
+ .join('\n'),
103
+ }}
104
+ />
105
+ )
106
+ }
107
+
108
+ const ChartTooltip = RechartsPrimitive.Tooltip
109
+
110
+ function ChartTooltipContent({
111
+ active,
112
+ payload,
113
+ className,
114
+ indicator = 'dot',
115
+ hideLabel = false,
116
+ hideIndicator = false,
117
+ label,
118
+ labelFormatter,
119
+ labelClassName,
120
+ formatter,
121
+ color,
122
+ nameKey,
123
+ labelKey,
124
+ }: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
125
+ React.ComponentProps<'div'> & {
126
+ hideLabel?: boolean
127
+ hideIndicator?: boolean
128
+ indicator?: 'line' | 'dot' | 'dashed'
129
+ nameKey?: string
130
+ labelKey?: string
131
+ } & Omit<
132
+ RechartsPrimitive.DefaultTooltipContentProps<TooltipValueType, TooltipNameType>,
133
+ 'accessibilityLayer'
134
+ >) {
135
+ const { config } = useChart()
136
+
137
+ const tooltipLabel = React.useMemo(() => {
138
+ if (hideLabel || !payload?.length) {
139
+ return null
140
+ }
141
+
142
+ const [item] = payload
143
+ const key = `${labelKey ?? item?.dataKey ?? item?.name ?? 'value'}`
144
+ const itemConfig = getPayloadConfigFromPayload(config, item, key)
145
+ const value =
146
+ !labelKey && typeof label === 'string' ? (config[label]?.label ?? label) : itemConfig?.label
147
+
148
+ if (labelFormatter) {
149
+ return (
150
+ <div className={cn('font-medium', labelClassName)}>{labelFormatter(value, payload)}</div>
151
+ )
152
+ }
153
+
154
+ if (!value) {
155
+ return null
156
+ }
157
+
158
+ return <div className={cn('font-medium', labelClassName)}>{value}</div>
159
+ }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey])
160
+
161
+ if (!active || !payload?.length) {
162
+ return null
163
+ }
164
+
165
+ const nestLabel = payload.length === 1 && indicator !== 'dot'
166
+
167
+ return (
168
+ <div
169
+ className={cn(
170
+ 'grid min-w-32 items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl',
171
+ className,
172
+ )}
173
+ >
174
+ {!nestLabel ? tooltipLabel : null}
175
+ <div className="grid gap-1.5">
176
+ {payload
177
+ .filter((item) => item.type !== 'none')
178
+ .map((item, index) => {
179
+ const key = `${nameKey ?? item.name ?? item.dataKey ?? 'value'}`
180
+ const itemConfig = getPayloadConfigFromPayload(config, item, key)
181
+ const indicatorColor = color ?? item.payload?.fill ?? item.color
182
+
183
+ return (
184
+ <div
185
+ key={index}
186
+ className={cn(
187
+ 'flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground',
188
+ indicator === 'dot' && 'items-center',
189
+ )}
190
+ >
191
+ {formatter && item?.value !== undefined && item.name ? (
192
+ formatter(item.value, item.name, item, index, item.payload)
193
+ ) : (
194
+ <>
195
+ {itemConfig?.icon ? (
196
+ <itemConfig.icon />
197
+ ) : (
198
+ !hideIndicator && (
199
+ <div
200
+ className={cn(
201
+ 'shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)',
202
+ {
203
+ 'h-2.5 w-2.5': indicator === 'dot',
204
+ 'w-1': indicator === 'line',
205
+ 'w-0 border-[1.5px] border-dashed bg-transparent':
206
+ indicator === 'dashed',
207
+ 'my-0.5': nestLabel && indicator === 'dashed',
208
+ },
209
+ )}
210
+ style={
211
+ {
212
+ '--color-bg': indicatorColor,
213
+ '--color-border': indicatorColor,
214
+ } as React.CSSProperties
215
+ }
216
+ />
217
+ )
218
+ )}
219
+ <div
220
+ className={cn(
221
+ 'flex flex-1 justify-between leading-none',
222
+ nestLabel ? 'items-end' : 'items-center',
223
+ )}
224
+ >
225
+ <div className="grid gap-1.5">
226
+ {nestLabel ? tooltipLabel : null}
227
+ <span className="text-muted-foreground">
228
+ {itemConfig?.label ?? item.name}
229
+ </span>
230
+ </div>
231
+ {item.value != null && (
232
+ <span className="font-mono font-medium text-foreground tabular-nums">
233
+ {typeof item.value === 'number'
234
+ ? item.value.toLocaleString()
235
+ : String(item.value)}
236
+ </span>
237
+ )}
238
+ </div>
239
+ </>
240
+ )}
241
+ </div>
242
+ )
243
+ })}
244
+ </div>
245
+ </div>
246
+ )
247
+ }
248
+
249
+ const ChartLegend = RechartsPrimitive.Legend
250
+
251
+ function ChartLegendContent({
252
+ className,
253
+ hideIcon = false,
254
+ payload,
255
+ verticalAlign = 'bottom',
256
+ nameKey,
257
+ }: React.ComponentProps<'div'> & {
258
+ hideIcon?: boolean
259
+ nameKey?: string
260
+ } & RechartsPrimitive.DefaultLegendContentProps) {
261
+ const { config } = useChart()
262
+
263
+ if (!payload?.length) {
264
+ return null
265
+ }
266
+
267
+ return (
268
+ <div
269
+ className={cn(
270
+ 'flex items-center justify-center gap-4',
271
+ verticalAlign === 'top' ? 'pb-3' : 'pt-3',
272
+ className,
273
+ )}
274
+ >
275
+ {payload
276
+ .filter((item) => item.type !== 'none')
277
+ .map((item, index) => {
278
+ const key = `${nameKey ?? item.dataKey ?? 'value'}`
279
+ const itemConfig = getPayloadConfigFromPayload(config, item, key)
280
+
281
+ return (
282
+ <div
283
+ key={index}
284
+ className={cn(
285
+ 'flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground',
286
+ )}
287
+ >
288
+ {itemConfig?.icon && !hideIcon ? (
289
+ <itemConfig.icon />
290
+ ) : (
291
+ <div
292
+ className="h-2 w-2 shrink-0 rounded-[2px]"
293
+ style={{
294
+ backgroundColor: item.color,
295
+ }}
296
+ />
297
+ )}
298
+ {itemConfig?.label}
299
+ </div>
300
+ )
301
+ })}
302
+ </div>
303
+ )
304
+ }
305
+
306
+ function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {
307
+ if (typeof payload !== 'object' || payload === null) {
308
+ return undefined
309
+ }
310
+
311
+ const payloadPayload =
312
+ 'payload' in payload && typeof payload.payload === 'object' && payload.payload !== null
313
+ ? payload.payload
314
+ : undefined
315
+
316
+ let configLabelKey: string = key
317
+
318
+ if (key in payload && typeof payload[key as keyof typeof payload] === 'string') {
319
+ configLabelKey = payload[key as keyof typeof payload] as string
320
+ } else if (
321
+ payloadPayload &&
322
+ key in payloadPayload &&
323
+ typeof payloadPayload[key as keyof typeof payloadPayload] === 'string'
324
+ ) {
325
+ configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string
326
+ }
327
+
328
+ return configLabelKey in config ? config[configLabelKey] : config[key]
329
+ }
330
+
331
+ export {
332
+ ChartContainer,
333
+ ChartTooltip,
334
+ ChartTooltipContent,
335
+ ChartLegend,
336
+ ChartLegendContent,
337
+ ChartStyle,
338
+ }
@@ -0,0 +1,27 @@
1
+ 'use client'
2
+
3
+ import { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox'
4
+ import { cn } from '../lib/utils'
5
+ import { CheckIcon } from 'lucide-react'
6
+
7
+ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
8
+ return (
9
+ <CheckboxPrimitive.Root
10
+ data-slot="checkbox"
11
+ className={cn(
12
+ 'peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary',
13
+ className,
14
+ )}
15
+ {...props}
16
+ >
17
+ <CheckboxPrimitive.Indicator
18
+ data-slot="checkbox-indicator"
19
+ className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
20
+ >
21
+ <CheckIcon />
22
+ </CheckboxPrimitive.Indicator>
23
+ </CheckboxPrimitive.Root>
24
+ )
25
+ }
26
+
27
+ export { Checkbox }
@@ -0,0 +1,15 @@
1
+ import { Collapsible as CollapsiblePrimitive } from '@base-ui/react/collapsible'
2
+
3
+ function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
4
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
5
+ }
6
+
7
+ function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
8
+ return <CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
9
+ }
10
+
11
+ function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
12
+ return <CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
13
+ }
14
+
15
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }