@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,577 @@
1
+ import * as React from 'react'
2
+ import {
3
+ closestCenter,
4
+ DndContext,
5
+ KeyboardSensor,
6
+ MouseSensor,
7
+ TouchSensor,
8
+ useSensor,
9
+ useSensors,
10
+ type DragEndEvent,
11
+ type UniqueIdentifier,
12
+ } from '@dnd-kit/core'
13
+ import { restrictToVerticalAxis } from '@dnd-kit/modifiers'
14
+ import {
15
+ arrayMove,
16
+ SortableContext,
17
+ useSortable,
18
+ verticalListSortingStrategy,
19
+ } from '@dnd-kit/sortable'
20
+ import { CSS } from '@dnd-kit/utilities'
21
+ import {
22
+ columnFilteringFeature,
23
+ columnVisibilityFeature,
24
+ createColumnHelper,
25
+ createFilteredRowModel,
26
+ createPaginatedRowModel,
27
+ createSortedRowModel,
28
+ FlexRender,
29
+ rowPaginationFeature,
30
+ rowSelectionFeature,
31
+ rowSortingFeature,
32
+ tableFeatures,
33
+ useTable,
34
+ type ColumnFiltersState,
35
+ type ColumnVisibilityState,
36
+ type Row,
37
+ type SortingState,
38
+ } from '@tanstack/react-table'
39
+ import { toast } from 'sonner'
40
+ import { z } from 'zod'
41
+
42
+ import { Badge } from '@devxcrew/react-ui/components/badge'
43
+ import { Button } from '@devxcrew/react-ui/components/button'
44
+ import { Checkbox } from '@devxcrew/react-ui/components/checkbox'
45
+ import {
46
+ DropdownMenu,
47
+ DropdownMenuCheckboxItem,
48
+ DropdownMenuContent,
49
+ DropdownMenuItem,
50
+ DropdownMenuSeparator,
51
+ DropdownMenuTrigger,
52
+ } from '@devxcrew/react-ui/components/dropdown-menu'
53
+ import { Input } from '@devxcrew/react-ui/components/input'
54
+ import { Label } from '@devxcrew/react-ui/components/label'
55
+ import {
56
+ Select,
57
+ SelectContent,
58
+ SelectGroup,
59
+ SelectItem,
60
+ SelectTrigger,
61
+ SelectValue,
62
+ } from '@devxcrew/react-ui/components/select'
63
+ import {
64
+ Table,
65
+ TableBody,
66
+ TableCell,
67
+ TableHead,
68
+ TableHeader,
69
+ TableRow,
70
+ } from '@devxcrew/react-ui/components/table'
71
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@devxcrew/react-ui/components/tabs'
72
+ import {
73
+ GripVerticalIcon,
74
+ CircleCheckIcon,
75
+ LoaderIcon,
76
+ EllipsisVerticalIcon,
77
+ Columns3Icon,
78
+ ChevronDownIcon,
79
+ PlusIcon,
80
+ ChevronsLeftIcon,
81
+ ChevronLeftIcon,
82
+ ChevronRightIcon,
83
+ ChevronsRightIcon,
84
+ } from 'lucide-react'
85
+
86
+ import { TableCellViewer } from './data-table-cell-viewer'
87
+
88
+ // New in v9: declare the features this table uses — anything you don't
89
+ // register is tree-shaken out of the bundle.
90
+ const features = tableFeatures({
91
+ columnFilteringFeature,
92
+ columnVisibilityFeature,
93
+ rowPaginationFeature,
94
+ rowSelectionFeature,
95
+ rowSortingFeature,
96
+ filteredRowModel: createFilteredRowModel(),
97
+ paginatedRowModel: createPaginatedRowModel(),
98
+ sortedRowModel: createSortedRowModel(),
99
+ })
100
+
101
+ const columnHelper = createColumnHelper<typeof features, z.infer<typeof schema>>()
102
+
103
+ export const schema = z.object({
104
+ id: z.number(),
105
+ header: z.string(),
106
+ type: z.string(),
107
+ status: z.string(),
108
+ target: z.string(),
109
+ limit: z.string(),
110
+ reviewer: z.string(),
111
+ })
112
+
113
+ export type DataTableItem = z.infer<typeof schema>
114
+
115
+ // Create a separate component for the drag handle
116
+ function DragHandle({ id }: { id: number }) {
117
+ const { attributes, listeners } = useSortable({
118
+ id,
119
+ })
120
+ return (
121
+ <Button
122
+ {...attributes}
123
+ {...listeners}
124
+ variant="ghost"
125
+ size="icon"
126
+ className="size-7 text-muted-foreground hover:bg-transparent"
127
+ >
128
+ <GripVerticalIcon className="size-3 text-muted-foreground" />
129
+ <span className="sr-only">Drag to reorder</span>
130
+ </Button>
131
+ )
132
+ }
133
+ const columns = columnHelper.columns([
134
+ columnHelper.display({
135
+ id: 'drag',
136
+ header: () => null,
137
+ cell: ({ row }) => <DragHandle id={row.original.id} />,
138
+ }),
139
+ columnHelper.display({
140
+ id: 'select',
141
+ header: ({ table }) => (
142
+ <div className="flex items-center justify-center">
143
+ <Checkbox
144
+ checked={table.getIsAllPageRowsSelected()}
145
+ indeterminate={table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected()}
146
+ onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
147
+ aria-label="Select all"
148
+ />
149
+ </div>
150
+ ),
151
+ cell: ({ row }) => (
152
+ <div className="flex items-center justify-center">
153
+ <Checkbox
154
+ checked={row.getIsSelected()}
155
+ onCheckedChange={(value) => row.toggleSelected(!!value)}
156
+ aria-label="Select row"
157
+ />
158
+ </div>
159
+ ),
160
+ enableSorting: false,
161
+ enableHiding: false,
162
+ }),
163
+ columnHelper.accessor('header', {
164
+ header: 'Header',
165
+ cell: ({ row }) => {
166
+ return <TableCellViewer item={row.original} />
167
+ },
168
+ enableHiding: false,
169
+ }),
170
+ columnHelper.accessor('type', {
171
+ header: 'Section Type',
172
+ cell: ({ row }) => (
173
+ <div className="w-32">
174
+ <Badge variant="outline" className="px-1.5 text-muted-foreground">
175
+ {row.original.type}
176
+ </Badge>
177
+ </div>
178
+ ),
179
+ }),
180
+ columnHelper.accessor('status', {
181
+ header: 'Status',
182
+ cell: ({ row }) => (
183
+ <Badge variant="outline" className="px-1.5 text-muted-foreground">
184
+ {row.original.status === 'Done' ? (
185
+ <CircleCheckIcon className="fill-green-500 dark:fill-green-400" />
186
+ ) : (
187
+ <LoaderIcon />
188
+ )}
189
+ {row.original.status}
190
+ </Badge>
191
+ ),
192
+ }),
193
+ columnHelper.accessor('target', {
194
+ header: () => <div className="w-full text-right">Target</div>,
195
+ cell: ({ row }) => (
196
+ <form
197
+ onSubmit={(e) => {
198
+ e.preventDefault()
199
+ toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), {
200
+ loading: `Saving ${row.original.header}`,
201
+ success: 'Done',
202
+ error: 'Error',
203
+ })
204
+ }}
205
+ >
206
+ <Label htmlFor={`${row.original.id}-target`} className="sr-only">
207
+ Target
208
+ </Label>
209
+ <Input
210
+ className="h-8 w-16 border-transparent bg-transparent text-right shadow-none hover:bg-input/30 focus-visible:border focus-visible:bg-background dark:bg-transparent dark:hover:bg-input/30 dark:focus-visible:bg-input/30"
211
+ defaultValue={row.original.target}
212
+ id={`${row.original.id}-target`}
213
+ />
214
+ </form>
215
+ ),
216
+ }),
217
+ columnHelper.accessor('limit', {
218
+ header: () => <div className="w-full text-right">Limit</div>,
219
+ cell: ({ row }) => (
220
+ <form
221
+ onSubmit={(e) => {
222
+ e.preventDefault()
223
+ toast.promise(new Promise((resolve) => setTimeout(resolve, 1000)), {
224
+ loading: `Saving ${row.original.header}`,
225
+ success: 'Done',
226
+ error: 'Error',
227
+ })
228
+ }}
229
+ >
230
+ <Label htmlFor={`${row.original.id}-limit`} className="sr-only">
231
+ Limit
232
+ </Label>
233
+ <Input
234
+ className="h-8 w-16 border-transparent bg-transparent text-right shadow-none hover:bg-input/30 focus-visible:border focus-visible:bg-background dark:bg-transparent dark:hover:bg-input/30 dark:focus-visible:bg-input/30"
235
+ defaultValue={row.original.limit}
236
+ id={`${row.original.id}-limit`}
237
+ />
238
+ </form>
239
+ ),
240
+ }),
241
+ columnHelper.accessor('reviewer', {
242
+ header: 'Reviewer',
243
+ cell: ({ row }) => {
244
+ const isAssigned = row.original.reviewer !== 'Assign reviewer'
245
+ if (isAssigned) {
246
+ return row.original.reviewer
247
+ }
248
+ return (
249
+ <>
250
+ <Label htmlFor={`${row.original.id}-reviewer`} className="sr-only">
251
+ Reviewer
252
+ </Label>
253
+ <Select
254
+ items={[
255
+ { label: 'Eddie Lake', value: 'Eddie Lake' },
256
+ { label: 'Jamik Tashpulatov', value: 'Jamik Tashpulatov' },
257
+ ]}
258
+ >
259
+ <SelectTrigger
260
+ className="w-38 **:data-[slot=select-value]:block **:data-[slot=select-value]:truncate"
261
+ size="sm"
262
+ id={`${row.original.id}-reviewer`}
263
+ >
264
+ <SelectValue placeholder="Assign reviewer" />
265
+ </SelectTrigger>
266
+ <SelectContent align="end">
267
+ <SelectGroup>
268
+ <SelectItem value="Eddie Lake">Eddie Lake</SelectItem>
269
+ <SelectItem value="Jamik Tashpulatov">Jamik Tashpulatov</SelectItem>
270
+ </SelectGroup>
271
+ </SelectContent>
272
+ </Select>
273
+ </>
274
+ )
275
+ },
276
+ }),
277
+ columnHelper.display({
278
+ id: 'actions',
279
+ cell: () => (
280
+ <DropdownMenu>
281
+ <DropdownMenuTrigger
282
+ render={
283
+ <Button
284
+ variant="ghost"
285
+ className="flex size-8 text-muted-foreground data-open:bg-muted"
286
+ size="icon"
287
+ />
288
+ }
289
+ >
290
+ <EllipsisVerticalIcon />
291
+ <span className="sr-only">Open menu</span>
292
+ </DropdownMenuTrigger>
293
+ <DropdownMenuContent align="end" className="w-32">
294
+ <DropdownMenuItem>Edit</DropdownMenuItem>
295
+ <DropdownMenuItem>Make a copy</DropdownMenuItem>
296
+ <DropdownMenuItem>Favorite</DropdownMenuItem>
297
+ <DropdownMenuSeparator />
298
+ <DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
299
+ </DropdownMenuContent>
300
+ </DropdownMenu>
301
+ ),
302
+ }),
303
+ ])
304
+ function DraggableRow({ row }: { row: Row<typeof features, z.infer<typeof schema>> }) {
305
+ const { transform, transition, setNodeRef, isDragging } = useSortable({
306
+ id: row.original.id,
307
+ })
308
+ return (
309
+ <TableRow
310
+ data-state={row.getIsSelected() && 'selected'}
311
+ data-dragging={isDragging}
312
+ ref={setNodeRef}
313
+ className="relative z-0 data-[dragging=true]:z-10 data-[dragging=true]:opacity-80"
314
+ style={{
315
+ transform: CSS.Transform.toString(transform),
316
+ transition: transition,
317
+ }}
318
+ >
319
+ {row.getVisibleCells().map((cell) => (
320
+ <TableCell key={cell.id}>
321
+ <FlexRender cell={cell} />
322
+ </TableCell>
323
+ ))}
324
+ </TableRow>
325
+ )
326
+ }
327
+ export function DataTable({ data: initialData }: { data: z.infer<typeof schema>[] }) {
328
+ const [data, setData] = React.useState(() => initialData)
329
+ const [rowSelection, setRowSelection] = React.useState({})
330
+ const [columnVisibility, setColumnVisibility] = React.useState<ColumnVisibilityState>({})
331
+ const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
332
+ const [sorting, setSorting] = React.useState<SortingState>([])
333
+ const [pagination, setPagination] = React.useState({
334
+ pageIndex: 0,
335
+ pageSize: 10,
336
+ })
337
+ const sortableId = React.useId()
338
+ const sensors = useSensors(
339
+ useSensor(MouseSensor, {}),
340
+ useSensor(TouchSensor, {}),
341
+ useSensor(KeyboardSensor, {}),
342
+ )
343
+ const dataIds = React.useMemo<UniqueIdentifier[]>(() => data?.map(({ id }) => id) || [], [data])
344
+ const table = useTable({
345
+ features,
346
+ data,
347
+ columns,
348
+ state: {
349
+ sorting,
350
+ columnVisibility,
351
+ rowSelection,
352
+ columnFilters,
353
+ pagination,
354
+ },
355
+ getRowId: (row) => row.id.toString(),
356
+ enableRowSelection: true,
357
+ onRowSelectionChange: setRowSelection,
358
+ onSortingChange: setSorting,
359
+ onColumnFiltersChange: setColumnFilters,
360
+ onColumnVisibilityChange: setColumnVisibility,
361
+ onPaginationChange: setPagination,
362
+ })
363
+ function handleDragEnd(event: DragEndEvent) {
364
+ const { active, over } = event
365
+ if (active && over && active.id !== over.id) {
366
+ setData((data) => {
367
+ const oldIndex = dataIds.indexOf(active.id)
368
+ const newIndex = dataIds.indexOf(over.id)
369
+ return arrayMove(data, oldIndex, newIndex)
370
+ })
371
+ }
372
+ }
373
+ return (
374
+ <Tabs defaultValue="outline" className="w-full flex-col justify-start gap-6">
375
+ <div className="flex items-center justify-between px-4 lg:px-6">
376
+ <Label htmlFor="view-selector" className="sr-only">
377
+ View
378
+ </Label>
379
+ <Select
380
+ defaultValue="outline"
381
+ items={[
382
+ { label: 'Outline', value: 'outline' },
383
+ { label: 'Past Performance', value: 'past-performance' },
384
+ { label: 'Key Personnel', value: 'key-personnel' },
385
+ { label: 'Focus Documents', value: 'focus-documents' },
386
+ ]}
387
+ >
388
+ <SelectTrigger className="flex w-fit @4xl/main:hidden" size="sm" id="view-selector">
389
+ <SelectValue placeholder="Select a view" />
390
+ </SelectTrigger>
391
+ <SelectContent>
392
+ <SelectGroup>
393
+ <SelectItem value="outline">Outline</SelectItem>
394
+ <SelectItem value="past-performance">Past Performance</SelectItem>
395
+ <SelectItem value="key-personnel">Key Personnel</SelectItem>
396
+ <SelectItem value="focus-documents">Focus Documents</SelectItem>
397
+ </SelectGroup>
398
+ </SelectContent>
399
+ </Select>
400
+ <TabsList className="hidden **:data-[slot=badge]:size-5 **:data-[slot=badge]:rounded-full **:data-[slot=badge]:bg-muted-foreground/30 **:data-[slot=badge]:px-1 @4xl/main:flex">
401
+ <TabsTrigger value="outline">Outline</TabsTrigger>
402
+ <TabsTrigger value="past-performance">
403
+ Past Performance <Badge variant="secondary">3</Badge>
404
+ </TabsTrigger>
405
+ <TabsTrigger value="key-personnel">
406
+ Key Personnel <Badge variant="secondary">2</Badge>
407
+ </TabsTrigger>
408
+ <TabsTrigger value="focus-documents">Focus Documents</TabsTrigger>
409
+ </TabsList>
410
+ <div className="flex items-center gap-2">
411
+ <DropdownMenu>
412
+ <DropdownMenuTrigger render={<Button variant="outline" size="sm" />}>
413
+ <Columns3Icon data-icon="inline-start" />
414
+ Columns
415
+ <ChevronDownIcon data-icon="inline-end" />
416
+ </DropdownMenuTrigger>
417
+ <DropdownMenuContent align="end" className="w-32">
418
+ {table
419
+ .getAllColumns()
420
+ .filter((column) => typeof column.accessorFn !== 'undefined' && column.getCanHide())
421
+ .map((column) => {
422
+ return (
423
+ <DropdownMenuCheckboxItem
424
+ key={column.id}
425
+ className="capitalize"
426
+ checked={column.getIsVisible()}
427
+ onCheckedChange={(value) => column.toggleVisibility(!!value)}
428
+ >
429
+ {column.id}
430
+ </DropdownMenuCheckboxItem>
431
+ )
432
+ })}
433
+ </DropdownMenuContent>
434
+ </DropdownMenu>
435
+ <Button variant="outline" size="sm">
436
+ <PlusIcon />
437
+ <span className="hidden lg:inline">Add Section</span>
438
+ </Button>
439
+ </div>
440
+ </div>
441
+ <TabsContent
442
+ value="outline"
443
+ className="relative flex flex-col gap-4 overflow-auto px-4 lg:px-6"
444
+ >
445
+ <div className="overflow-hidden rounded-lg border">
446
+ <DndContext
447
+ collisionDetection={closestCenter}
448
+ modifiers={[restrictToVerticalAxis]}
449
+ onDragEnd={handleDragEnd}
450
+ sensors={sensors}
451
+ id={sortableId}
452
+ >
453
+ <Table>
454
+ <TableHeader className="sticky top-0 z-10 bg-muted">
455
+ {table.getHeaderGroups().map((headerGroup) => (
456
+ <TableRow key={headerGroup.id}>
457
+ {headerGroup.headers.map((header) => {
458
+ return (
459
+ <TableHead key={header.id} colSpan={header.colSpan}>
460
+ {header.isPlaceholder ? null : <FlexRender header={header} />}
461
+ </TableHead>
462
+ )
463
+ })}
464
+ </TableRow>
465
+ ))}
466
+ </TableHeader>
467
+ <TableBody className="**:data-[slot=table-cell]:first:w-8">
468
+ {table.getRowModel().rows?.length ? (
469
+ <SortableContext items={dataIds} strategy={verticalListSortingStrategy}>
470
+ {table.getRowModel().rows.map((row) => (
471
+ <DraggableRow key={row.id} row={row} />
472
+ ))}
473
+ </SortableContext>
474
+ ) : (
475
+ <TableRow>
476
+ <TableCell colSpan={columns.length} className="h-24 text-center">
477
+ No results.
478
+ </TableCell>
479
+ </TableRow>
480
+ )}
481
+ </TableBody>
482
+ </Table>
483
+ </DndContext>
484
+ </div>
485
+ <div className="flex items-center justify-between px-4">
486
+ <div className="hidden flex-1 text-sm text-muted-foreground lg:flex">
487
+ {table.getFilteredSelectedRowModel().rows.length} of{' '}
488
+ {table.getFilteredRowModel().rows.length} row(s) selected.
489
+ </div>
490
+ <div className="flex w-full items-center gap-8 lg:w-fit">
491
+ <div className="hidden items-center gap-2 lg:flex">
492
+ <Label htmlFor="rows-per-page" className="text-sm font-medium">
493
+ Rows per page
494
+ </Label>
495
+ <Select
496
+ value={`${table.state.pagination.pageSize}`}
497
+ onValueChange={(value) => {
498
+ table.setPageSize(Number(value))
499
+ }}
500
+ items={[10, 20, 30, 40, 50].map((pageSize) => ({
501
+ label: `${pageSize}`,
502
+ value: `${pageSize}`,
503
+ }))}
504
+ >
505
+ <SelectTrigger size="sm" className="w-20" id="rows-per-page">
506
+ <SelectValue placeholder={table.state.pagination.pageSize} />
507
+ </SelectTrigger>
508
+ <SelectContent side="top">
509
+ <SelectGroup>
510
+ {[10, 20, 30, 40, 50].map((pageSize) => (
511
+ <SelectItem key={pageSize} value={`${pageSize}`}>
512
+ {pageSize}
513
+ </SelectItem>
514
+ ))}
515
+ </SelectGroup>
516
+ </SelectContent>
517
+ </Select>
518
+ </div>
519
+ <div className="flex w-fit items-center justify-center text-sm font-medium">
520
+ Page {table.state.pagination.pageIndex + 1} of {table.getPageCount()}
521
+ </div>
522
+ <div className="ml-auto flex items-center gap-2 lg:ml-0">
523
+ <Button
524
+ variant="outline"
525
+ className="hidden h-8 w-8 p-0 lg:flex"
526
+ onClick={() => table.setPageIndex(0)}
527
+ disabled={!table.getCanPreviousPage()}
528
+ >
529
+ <span className="sr-only">Go to first page</span>
530
+ <ChevronsLeftIcon />
531
+ </Button>
532
+ <Button
533
+ variant="outline"
534
+ className="size-8"
535
+ size="icon"
536
+ onClick={() => table.previousPage()}
537
+ disabled={!table.getCanPreviousPage()}
538
+ >
539
+ <span className="sr-only">Go to previous page</span>
540
+ <ChevronLeftIcon />
541
+ </Button>
542
+ <Button
543
+ variant="outline"
544
+ className="size-8"
545
+ size="icon"
546
+ onClick={() => table.nextPage()}
547
+ disabled={!table.getCanNextPage()}
548
+ >
549
+ <span className="sr-only">Go to next page</span>
550
+ <ChevronRightIcon />
551
+ </Button>
552
+ <Button
553
+ variant="outline"
554
+ className="hidden size-8 lg:flex"
555
+ size="icon"
556
+ onClick={() => table.setPageIndex(table.getPageCount() - 1)}
557
+ disabled={!table.getCanNextPage()}
558
+ >
559
+ <span className="sr-only">Go to last page</span>
560
+ <ChevronsRightIcon />
561
+ </Button>
562
+ </div>
563
+ </div>
564
+ </div>
565
+ </TabsContent>
566
+ <TabsContent value="past-performance" className="flex flex-col px-4 lg:px-6">
567
+ <div className="aspect-video w-full flex-1 rounded-lg border border-dashed"></div>
568
+ </TabsContent>
569
+ <TabsContent value="key-personnel" className="flex flex-col px-4 lg:px-6">
570
+ <div className="aspect-video w-full flex-1 rounded-lg border border-dashed"></div>
571
+ </TabsContent>
572
+ <TabsContent value="focus-documents" className="flex flex-col px-4 lg:px-6">
573
+ <div className="aspect-video w-full flex-1 rounded-lg border border-dashed"></div>
574
+ </TabsContent>
575
+ </Tabs>
576
+ )
577
+ }
@@ -0,0 +1,79 @@
1
+ 'use client'
2
+
3
+ import {
4
+ DropdownMenu,
5
+ DropdownMenuContent,
6
+ DropdownMenuItem,
7
+ DropdownMenuSeparator,
8
+ DropdownMenuTrigger,
9
+ } from '@devxcrew/react-ui/components/dropdown-menu'
10
+ import {
11
+ SidebarGroup,
12
+ SidebarGroupLabel,
13
+ SidebarMenu,
14
+ SidebarMenuAction,
15
+ SidebarMenuButton,
16
+ SidebarMenuItem,
17
+ useSidebar,
18
+ } from '@devxcrew/react-ui/components/sidebar'
19
+ import { MoreHorizontalIcon, FolderIcon, ShareIcon, Trash2Icon } from 'lucide-react'
20
+
21
+ export function NavDocuments({
22
+ items,
23
+ }: {
24
+ items: {
25
+ name: string
26
+ url: string
27
+ icon: React.ElementType
28
+ }[]
29
+ }) {
30
+ const { isMobile } = useSidebar()
31
+ return (
32
+ <SidebarGroup className="group-data-[collapsible=icon]:hidden">
33
+ <SidebarGroupLabel>Documents</SidebarGroupLabel>
34
+ <SidebarMenu>
35
+ {items.map((item) => (
36
+ <SidebarMenuItem key={item.name}>
37
+ <SidebarMenuButton render={<a href={item.url} />}>
38
+ <item.icon />
39
+ <span>{item.name}</span>
40
+ </SidebarMenuButton>
41
+ <DropdownMenu>
42
+ <DropdownMenuTrigger
43
+ render={<SidebarMenuAction showOnHover className="aria-expanded:bg-muted" />}
44
+ >
45
+ <MoreHorizontalIcon />
46
+ <span className="sr-only">More</span>
47
+ </DropdownMenuTrigger>
48
+ <DropdownMenuContent
49
+ className="w-24"
50
+ side={isMobile ? 'bottom' : 'right'}
51
+ align={isMobile ? 'end' : 'start'}
52
+ >
53
+ <DropdownMenuItem>
54
+ <FolderIcon />
55
+ <span>Open</span>
56
+ </DropdownMenuItem>
57
+ <DropdownMenuItem>
58
+ <ShareIcon />
59
+ <span>Share</span>
60
+ </DropdownMenuItem>
61
+ <DropdownMenuSeparator />
62
+ <DropdownMenuItem variant="destructive">
63
+ <Trash2Icon />
64
+ <span>Delete</span>
65
+ </DropdownMenuItem>
66
+ </DropdownMenuContent>
67
+ </DropdownMenu>
68
+ </SidebarMenuItem>
69
+ ))}
70
+ <SidebarMenuItem>
71
+ <SidebarMenuButton className="text-sidebar-foreground/70">
72
+ <MoreHorizontalIcon className="text-sidebar-foreground/70" />
73
+ <span>More</span>
74
+ </SidebarMenuButton>
75
+ </SidebarMenuItem>
76
+ </SidebarMenu>
77
+ </SidebarGroup>
78
+ )
79
+ }