@exxatdesignux/ui 0.2.18 → 0.3.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 (618) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/bin/sync-extras.mjs +116 -29
  3. package/consumer-extras/README.md +43 -4
  4. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +39 -0
  5. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +26 -0
  6. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +21 -0
  7. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +21 -0
  8. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +44 -0
  9. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +32 -0
  10. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +22 -0
  11. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +53 -0
  12. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +41 -0
  13. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +25 -0
  14. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +22 -0
  15. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +56 -0
  16. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +31 -0
  17. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +100 -0
  18. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +28 -0
  19. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +21 -0
  20. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +31 -0
  21. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
  22. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
  23. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
  24. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
  25. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
  26. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
  27. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
  28. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -0
  29. package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +28 -0
  30. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +34 -0
  31. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +77 -0
  32. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +103 -0
  33. package/consumer-extras/cursor-skills/exxat-accessibility/SKILL.md +1 -1
  34. package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
  35. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +1 -1
  36. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +9 -9
  37. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
  38. package/consumer-extras/handbook/HANDBOOK.md +185 -0
  39. package/consumer-extras/handbook/glossary.md +57 -0
  40. package/consumer-extras/handbook/reference-implementations.md +126 -0
  41. package/consumer-extras/handbook/voice-and-tone.md +262 -0
  42. package/consumer-extras/patterns/command-menu-pattern.md +1 -1
  43. package/consumer-extras/patterns/data-views-pattern.md +14 -14
  44. package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
  45. package/dist/components/data-table/filter-date-calendar.js +280 -0
  46. package/dist/components/data-table/filter-date-calendar.js.map +1 -0
  47. package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
  48. package/dist/components/data-table/filter-text-value-input.js +561 -0
  49. package/dist/components/data-table/filter-text-value-input.js.map +1 -0
  50. package/dist/components/data-table/index.d.ts +45 -0
  51. package/dist/components/data-table/index.js +3085 -0
  52. package/dist/components/data-table/index.js.map +1 -0
  53. package/dist/components/data-table/pagination.d.ts +28 -0
  54. package/dist/components/data-table/pagination.js +3264 -0
  55. package/dist/components/data-table/pagination.js.map +1 -0
  56. package/dist/components/data-table/types.d.ts +84 -0
  57. package/dist/components/data-table/types.js +3 -0
  58. package/dist/components/data-table/types.js.map +1 -0
  59. package/dist/components/data-table/use-table-state.d.ts +116 -0
  60. package/dist/components/data-table/use-table-state.js +670 -0
  61. package/dist/components/data-table/use-table-state.js.map +1 -0
  62. package/dist/components/data-views/board-card-primitives.d.ts +22 -0
  63. package/dist/components/data-views/board-card-primitives.js +84 -0
  64. package/dist/components/data-views/board-card-primitives.js.map +1 -0
  65. package/dist/components/data-views/data-row-list.d.ts +33 -0
  66. package/dist/components/data-views/data-row-list.js +106 -0
  67. package/dist/components/data-views/data-row-list.js.map +1 -0
  68. package/dist/components/data-views/finder-panel-view.d.ts +54 -0
  69. package/dist/components/data-views/finder-panel-view.js +388 -0
  70. package/dist/components/data-views/finder-panel-view.js.map +1 -0
  71. package/dist/components/data-views/folder-grid-view.d.ts +22 -0
  72. package/dist/components/data-views/folder-grid-view.js +58 -0
  73. package/dist/components/data-views/folder-grid-view.js.map +1 -0
  74. package/dist/components/data-views/hub-table.d.ts +167 -0
  75. package/dist/components/data-views/hub-table.js +5561 -0
  76. package/dist/components/data-views/hub-table.js.map +1 -0
  77. package/dist/components/data-views/index.d.ts +27 -0
  78. package/dist/components/data-views/index.js +6575 -0
  79. package/dist/components/data-views/index.js.map +1 -0
  80. package/dist/components/data-views/list-page-board-card.d.ts +72 -0
  81. package/dist/components/data-views/list-page-board-card.js +264 -0
  82. package/dist/components/data-views/list-page-board-card.js.map +1 -0
  83. package/dist/components/data-views/list-page-board-template.d.ts +24 -0
  84. package/dist/components/data-views/list-page-board-template.js +137 -0
  85. package/dist/components/data-views/list-page-board-template.js.map +1 -0
  86. package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
  87. package/dist/components/data-views/list-page-connected-view-body.js +116 -0
  88. package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
  89. package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
  90. package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
  91. package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
  92. package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
  93. package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
  94. package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
  95. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
  96. package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
  97. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
  98. package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
  99. package/dist/components/data-views/list-page-tree-column-header.js +22 -0
  100. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
  101. package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
  102. package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
  103. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
  104. package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
  105. package/dist/components/data-views/os-folder-glyph.js +104 -0
  106. package/dist/components/data-views/os-folder-glyph.js.map +1 -0
  107. package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
  108. package/dist/components/data-views/outline-tree-menu.js +131 -0
  109. package/dist/components/data-views/outline-tree-menu.js.map +1 -0
  110. package/dist/components/table-properties/column-row.d.ts +22 -0
  111. package/dist/components/table-properties/column-row.js +153 -0
  112. package/dist/components/table-properties/column-row.js.map +1 -0
  113. package/dist/components/table-properties/draggable-list.d.ts +24 -0
  114. package/dist/components/table-properties/draggable-list.js +53 -0
  115. package/dist/components/table-properties/draggable-list.js.map +1 -0
  116. package/dist/components/table-properties/drawer-button.d.ts +110 -0
  117. package/dist/components/table-properties/drawer-button.js +2748 -0
  118. package/dist/components/table-properties/drawer-button.js.map +1 -0
  119. package/dist/components/table-properties/drawer.d.ts +100 -0
  120. package/dist/components/table-properties/drawer.js +2595 -0
  121. package/dist/components/table-properties/drawer.js.map +1 -0
  122. package/dist/components/table-properties/filter-card.d.ts +24 -0
  123. package/dist/components/table-properties/filter-card.js +854 -0
  124. package/dist/components/table-properties/filter-card.js.map +1 -0
  125. package/dist/components/table-properties/index.d.ts +14 -0
  126. package/dist/components/table-properties/index.js +2768 -0
  127. package/dist/components/table-properties/index.js.map +1 -0
  128. package/dist/components/table-properties/sort-card.d.ts +20 -0
  129. package/dist/components/table-properties/sort-card.js +102 -0
  130. package/dist/components/table-properties/sort-card.js.map +1 -0
  131. package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
  132. package/dist/components/templates/dedicated-search-landing-template.js +254 -0
  133. package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
  134. package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
  135. package/dist/components/templates/dedicated-search-results-template.js +16 -0
  136. package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
  137. package/dist/components/templates/index.d.ts +9 -0
  138. package/dist/components/templates/index.js +2720 -0
  139. package/dist/components/templates/index.js.map +1 -0
  140. package/dist/components/templates/list-page.d.ts +83 -0
  141. package/dist/components/templates/list-page.js +2433 -0
  142. package/dist/components/templates/list-page.js.map +1 -0
  143. package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
  144. package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
  145. package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
  146. package/dist/components/ui/accordion.d.ts +10 -0
  147. package/dist/components/ui/accordion.js +74 -0
  148. package/dist/components/ui/accordion.js.map +1 -0
  149. package/dist/components/ui/alert-dialog.d.ts +37 -0
  150. package/dist/components/ui/alert-dialog.js +201 -0
  151. package/dist/components/ui/alert-dialog.js.map +1 -0
  152. package/dist/components/ui/avatar.d.ts +84 -0
  153. package/dist/components/ui/avatar.js +328 -0
  154. package/dist/components/ui/avatar.js.map +1 -0
  155. package/dist/components/ui/badge.d.ts +13 -0
  156. package/dist/components/ui/badge.js +49 -0
  157. package/dist/components/ui/badge.js.map +1 -0
  158. package/dist/components/ui/banner.d.ts +62 -0
  159. package/dist/components/ui/banner.js +364 -0
  160. package/dist/components/ui/banner.js.map +1 -0
  161. package/dist/components/ui/breadcrumb.d.ts +14 -0
  162. package/dist/components/ui/breadcrumb.js +114 -0
  163. package/dist/components/ui/breadcrumb.js.map +1 -0
  164. package/dist/components/ui/button.d.ts +16 -0
  165. package/dist/components/ui/button.js +59 -0
  166. package/dist/components/ui/button.js.map +1 -0
  167. package/dist/components/ui/calendar.d.ts +13 -0
  168. package/dist/components/ui/calendar.js +238 -0
  169. package/dist/components/ui/calendar.js.map +1 -0
  170. package/dist/components/ui/card.d.ts +14 -0
  171. package/dist/components/ui/card.js +102 -0
  172. package/dist/components/ui/card.js.map +1 -0
  173. package/dist/components/ui/chart.d.ts +58 -0
  174. package/dist/components/ui/chart.js +292 -0
  175. package/dist/components/ui/chart.js.map +1 -0
  176. package/dist/components/ui/checkbox.d.ts +23 -0
  177. package/dist/components/ui/checkbox.js +155 -0
  178. package/dist/components/ui/checkbox.js.map +1 -0
  179. package/dist/components/ui/coach-mark.d.ts +27 -0
  180. package/dist/components/ui/coach-mark.js +306 -0
  181. package/dist/components/ui/coach-mark.js.map +1 -0
  182. package/dist/components/ui/collapsible.d.ts +8 -0
  183. package/dist/components/ui/collapsible.js +35 -0
  184. package/dist/components/ui/collapsible.js.map +1 -0
  185. package/dist/components/ui/command.d.ts +36 -0
  186. package/dist/components/ui/command.js +274 -0
  187. package/dist/components/ui/command.js.map +1 -0
  188. package/dist/components/ui/context-menu.d.ts +32 -0
  189. package/dist/components/ui/context-menu.js +245 -0
  190. package/dist/components/ui/context-menu.js.map +1 -0
  191. package/dist/components/ui/date-picker-field.d.ts +38 -0
  192. package/dist/components/ui/date-picker-field.js +550 -0
  193. package/dist/components/ui/date-picker-field.js.map +1 -0
  194. package/dist/components/ui/dialog.d.ts +22 -0
  195. package/dist/components/ui/dialog.js +200 -0
  196. package/dist/components/ui/dialog.js.map +1 -0
  197. package/dist/components/ui/dot-pattern.d.ts +21 -0
  198. package/dist/components/ui/dot-pattern.js +139 -0
  199. package/dist/components/ui/dot-pattern.js.map +1 -0
  200. package/dist/components/ui/drag-handle-grip.d.ts +10 -0
  201. package/dist/components/ui/drag-handle-grip.js +15 -0
  202. package/dist/components/ui/drag-handle-grip.js.map +1 -0
  203. package/dist/components/ui/drawer.d.ts +16 -0
  204. package/dist/components/ui/drawer.js +125 -0
  205. package/dist/components/ui/drawer.js.map +1 -0
  206. package/dist/components/ui/dropdown-menu.d.ts +45 -0
  207. package/dist/components/ui/dropdown-menu.js +353 -0
  208. package/dist/components/ui/dropdown-menu.js.map +1 -0
  209. package/dist/components/ui/export-drawer.d.ts +11 -0
  210. package/dist/components/ui/export-drawer.js +1658 -0
  211. package/dist/components/ui/export-drawer.js.map +1 -0
  212. package/dist/components/ui/field.d.ts +30 -0
  213. package/dist/components/ui/field.js +249 -0
  214. package/dist/components/ui/field.js.map +1 -0
  215. package/dist/components/ui/form.d.ts +28 -0
  216. package/dist/components/ui/form.js +110 -0
  217. package/dist/components/ui/form.js.map +1 -0
  218. package/dist/components/ui/hover-card.d.ts +9 -0
  219. package/dist/components/ui/hover-card.js +43 -0
  220. package/dist/components/ui/hover-card.js.map +1 -0
  221. package/dist/components/ui/input-group.d.ts +20 -0
  222. package/dist/components/ui/input-group.js +219 -0
  223. package/dist/components/ui/input-group.js.map +1 -0
  224. package/dist/components/ui/input-mask.d.ts +39 -0
  225. package/dist/components/ui/input-mask.js +118 -0
  226. package/dist/components/ui/input-mask.js.map +1 -0
  227. package/dist/components/ui/input.d.ts +5 -0
  228. package/dist/components/ui/input.js +30 -0
  229. package/dist/components/ui/input.js.map +1 -0
  230. package/dist/components/ui/kbd.d.ts +20 -0
  231. package/dist/components/ui/kbd.js +45 -0
  232. package/dist/components/ui/kbd.js.map +1 -0
  233. package/dist/components/ui/key-metrics-context.d.ts +19 -0
  234. package/dist/components/ui/key-metrics-context.js +26 -0
  235. package/dist/components/ui/key-metrics-context.js.map +1 -0
  236. package/dist/components/ui/key-metrics.d.ts +131 -0
  237. package/dist/components/ui/key-metrics.js +1015 -0
  238. package/dist/components/ui/key-metrics.js.map +1 -0
  239. package/dist/components/ui/label.d.ts +6 -0
  240. package/dist/components/ui/label.js +28 -0
  241. package/dist/components/ui/label.js.map +1 -0
  242. package/dist/components/ui/list-page-view-frame.d.ts +22 -0
  243. package/dist/components/ui/list-page-view-frame.js +24 -0
  244. package/dist/components/ui/list-page-view-frame.js.map +1 -0
  245. package/dist/components/ui/page-header.d.ts +51 -0
  246. package/dist/components/ui/page-header.js +372 -0
  247. package/dist/components/ui/page-header.js.map +1 -0
  248. package/dist/components/ui/payment-card-fields.d.ts +10 -0
  249. package/dist/components/ui/payment-card-fields.js +80 -0
  250. package/dist/components/ui/payment-card-fields.js.map +1 -0
  251. package/dist/components/ui/popover.d.ts +10 -0
  252. package/dist/components/ui/popover.js +47 -0
  253. package/dist/components/ui/popover.js.map +1 -0
  254. package/dist/components/ui/radio-group.d.ts +29 -0
  255. package/dist/components/ui/radio-group.js +190 -0
  256. package/dist/components/ui/radio-group.js.map +1 -0
  257. package/dist/components/ui/resizable.d.ts +16 -0
  258. package/dist/components/ui/resizable.js +51 -0
  259. package/dist/components/ui/resizable.js.map +1 -0
  260. package/dist/components/ui/scroll-area.d.ts +8 -0
  261. package/dist/components/ui/scroll-area.js +66 -0
  262. package/dist/components/ui/scroll-area.js.map +1 -0
  263. package/dist/components/ui/select.d.ts +18 -0
  264. package/dist/components/ui/select.js +186 -0
  265. package/dist/components/ui/select.js.map +1 -0
  266. package/dist/components/ui/selection-tile-grid.d.ts +52 -0
  267. package/dist/components/ui/selection-tile-grid.js +347 -0
  268. package/dist/components/ui/selection-tile-grid.js.map +1 -0
  269. package/dist/components/ui/separator.d.ts +7 -0
  270. package/dist/components/ui/separator.js +33 -0
  271. package/dist/components/ui/separator.js.map +1 -0
  272. package/dist/components/ui/sheet.d.ts +18 -0
  273. package/dist/components/ui/sheet.js +181 -0
  274. package/dist/components/ui/sheet.js.map +1 -0
  275. package/dist/components/ui/sidebar.d.ts +94 -0
  276. package/dist/components/ui/sidebar.js +805 -0
  277. package/dist/components/ui/sidebar.js.map +1 -0
  278. package/dist/components/ui/skeleton.d.ts +5 -0
  279. package/dist/components/ui/skeleton.js +22 -0
  280. package/dist/components/ui/skeleton.js.map +1 -0
  281. package/dist/components/ui/slider.d.ts +7 -0
  282. package/dist/components/ui/slider.js +66 -0
  283. package/dist/components/ui/slider.js.map +1 -0
  284. package/dist/components/ui/sonner.d.ts +6 -0
  285. package/dist/components/ui/sonner.js +38 -0
  286. package/dist/components/ui/sonner.js.map +1 -0
  287. package/dist/components/ui/status-badge.d.ts +38 -0
  288. package/dist/components/ui/status-badge.js +77 -0
  289. package/dist/components/ui/status-badge.js.map +1 -0
  290. package/dist/components/ui/table.d.ts +13 -0
  291. package/dist/components/ui/table.js +115 -0
  292. package/dist/components/ui/table.js.map +1 -0
  293. package/dist/components/ui/tabs.d.ts +15 -0
  294. package/dist/components/ui/tabs.js +93 -0
  295. package/dist/components/ui/tabs.js.map +1 -0
  296. package/dist/components/ui/textarea.d.ts +6 -0
  297. package/dist/components/ui/textarea.js +25 -0
  298. package/dist/components/ui/textarea.js.map +1 -0
  299. package/dist/components/ui/tip.d.ts +12 -0
  300. package/dist/components/ui/tip.js +61 -0
  301. package/dist/components/ui/tip.js.map +1 -0
  302. package/dist/components/ui/toggle-group.d.ts +14 -0
  303. package/dist/components/ui/toggle-group.js +104 -0
  304. package/dist/components/ui/toggle-group.js.map +1 -0
  305. package/dist/components/ui/toggle-switch.d.ts +10 -0
  306. package/dist/components/ui/toggle-switch.js +33 -0
  307. package/dist/components/ui/toggle-switch.js.map +1 -0
  308. package/dist/components/ui/toggle.d.ts +13 -0
  309. package/dist/components/ui/toggle.js +51 -0
  310. package/dist/components/ui/toggle.js.map +1 -0
  311. package/dist/components/ui/tooltip.d.ts +10 -0
  312. package/dist/components/ui/tooltip.js +68 -0
  313. package/dist/components/ui/tooltip.js.map +1 -0
  314. package/dist/components/ui/view-segmented-control.d.ts +31 -0
  315. package/dist/components/ui/view-segmented-control.js +167 -0
  316. package/dist/components/ui/view-segmented-control.js.map +1 -0
  317. package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
  318. package/dist/hooks/use-app-theme.d.ts +24 -0
  319. package/dist/hooks/use-app-theme.js +286 -0
  320. package/dist/hooks/use-app-theme.js.map +1 -0
  321. package/dist/hooks/use-coach-mark.d.ts +86 -0
  322. package/dist/hooks/use-coach-mark.js +218 -0
  323. package/dist/hooks/use-coach-mark.js.map +1 -0
  324. package/dist/hooks/use-mobile.d.ts +3 -0
  325. package/dist/hooks/use-mobile.js +29 -0
  326. package/dist/hooks/use-mobile.js.map +1 -0
  327. package/dist/hooks/use-mod-key-label.d.ts +6 -0
  328. package/dist/hooks/use-mod-key-label.js +25 -0
  329. package/dist/hooks/use-mod-key-label.js.map +1 -0
  330. package/dist/index.d.ts +120 -0
  331. package/dist/index.js +13324 -0
  332. package/dist/index.js.map +1 -0
  333. package/dist/lib/compose-refs.d.ts +6 -0
  334. package/dist/lib/compose-refs.js +17 -0
  335. package/dist/lib/compose-refs.js.map +1 -0
  336. package/dist/lib/conditional-rule-match.d.ts +30 -0
  337. package/dist/lib/conditional-rule-match.js +66 -0
  338. package/dist/lib/conditional-rule-match.js.map +1 -0
  339. package/dist/lib/data-list-display-options.d.ts +26 -0
  340. package/dist/lib/data-list-display-options.js +14 -0
  341. package/dist/lib/data-list-display-options.js.map +1 -0
  342. package/dist/lib/data-list-view-registry.d.ts +2 -0
  343. package/dist/lib/data-list-view-registry.js +102 -0
  344. package/dist/lib/data-list-view-registry.js.map +1 -0
  345. package/dist/lib/data-list-view-surface.d.ts +2 -0
  346. package/dist/lib/data-list-view-surface.js +80 -0
  347. package/dist/lib/data-list-view-surface.js.map +1 -0
  348. package/dist/lib/data-list-view.d.ts +21 -0
  349. package/dist/lib/data-list-view.js +25 -0
  350. package/dist/lib/data-list-view.js.map +1 -0
  351. package/dist/lib/date-filter.d.ts +22 -0
  352. package/dist/lib/date-filter.js +61 -0
  353. package/dist/lib/date-filter.js.map +1 -0
  354. package/dist/lib/dev-log.d.ts +8 -0
  355. package/dist/lib/dev-log.js +10 -0
  356. package/dist/lib/dev-log.js.map +1 -0
  357. package/dist/lib/dropdown-menu-surface.d.ts +14 -0
  358. package/dist/lib/dropdown-menu-surface.js +6 -0
  359. package/dist/lib/dropdown-menu-surface.js.map +1 -0
  360. package/dist/lib/editable-target.d.ts +12 -0
  361. package/dist/lib/editable-target.js +12 -0
  362. package/dist/lib/editable-target.js.map +1 -0
  363. package/dist/lib/list-page-table-properties.d.ts +35 -0
  364. package/dist/lib/list-page-table-properties.js +81 -0
  365. package/dist/lib/list-page-table-properties.js.map +1 -0
  366. package/dist/lib/raf-throttle.d.ts +23 -0
  367. package/dist/lib/raf-throttle.js +27 -0
  368. package/dist/lib/raf-throttle.js.map +1 -0
  369. package/dist/lib/row-height.d.ts +16 -0
  370. package/dist/lib/row-height.js +10 -0
  371. package/dist/lib/row-height.js.map +1 -0
  372. package/dist/lib/table-properties-types.d.ts +83 -0
  373. package/dist/lib/table-properties-types.js +19 -0
  374. package/dist/lib/table-properties-types.js.map +1 -0
  375. package/dist/lib/utils.d.ts +5 -0
  376. package/dist/lib/utils.js +11 -0
  377. package/dist/lib/utils.js.map +1 -0
  378. package/package.json +83 -18
  379. package/src/components/data-table/filter-date-calendar.tsx +38 -0
  380. package/src/components/data-table/filter-text-value-input.tsx +77 -0
  381. package/src/components/data-table/index.tsx +1678 -0
  382. package/src/components/data-table/pagination.tsx +255 -0
  383. package/src/components/data-table/types.ts +96 -0
  384. package/src/components/data-table/use-table-state.ts +767 -0
  385. package/src/components/data-views/board-card-primitives.tsx +93 -0
  386. package/src/components/data-views/data-row-list.tsx +183 -0
  387. package/src/components/data-views/finder-panel-view.tsx +405 -0
  388. package/src/components/data-views/folder-grid-view.tsx +86 -0
  389. package/src/components/data-views/hub-table.tsx +498 -0
  390. package/src/components/data-views/index.ts +28 -0
  391. package/src/components/data-views/list-page-board-card.tsx +192 -0
  392. package/src/components/data-views/list-page-board-template.tsx +122 -0
  393. package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
  394. package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
  395. package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
  396. package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
  397. package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
  398. package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
  399. package/src/components/data-views/os-folder-glyph.tsx +141 -0
  400. package/src/components/data-views/outline-tree-menu.tsx +157 -0
  401. package/src/components/table-properties/column-row.tsx +90 -0
  402. package/src/components/table-properties/draggable-list.ts +54 -0
  403. package/src/components/table-properties/drawer-button.tsx +300 -0
  404. package/src/components/table-properties/drawer.tsx +1148 -0
  405. package/src/components/table-properties/filter-card.tsx +251 -0
  406. package/src/components/table-properties/index.ts +36 -0
  407. package/src/components/table-properties/sort-card.tsx +63 -0
  408. package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
  409. package/src/components/templates/dedicated-search-results-template.tsx +19 -0
  410. package/src/components/templates/index.ts +33 -0
  411. package/src/components/templates/list-page.tsx +602 -0
  412. package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
  413. package/src/components/ui/accordion.tsx +92 -0
  414. package/src/components/ui/alert-dialog.tsx +221 -0
  415. package/src/components/ui/avatar.tsx +13 -2
  416. package/src/components/ui/banner.tsx +2 -2
  417. package/src/components/ui/calendar.tsx +1 -1
  418. package/src/components/ui/coach-mark.tsx +1 -1
  419. package/src/components/ui/context-menu.tsx +291 -0
  420. package/src/components/ui/date-picker-field.tsx +2 -2
  421. package/src/components/ui/dot-pattern.tsx +183 -0
  422. package/src/components/ui/export-drawer.tsx +375 -0
  423. package/src/components/ui/hover-card.tsx +66 -0
  424. package/src/components/ui/key-metrics-context.tsx +78 -0
  425. package/src/components/ui/key-metrics.tsx +1133 -0
  426. package/src/components/ui/list-page-view-frame.tsx +64 -0
  427. package/src/components/ui/page-header.tsx +244 -0
  428. package/src/components/ui/payment-card-fields.tsx +2 -2
  429. package/src/components/ui/resizable.tsx +68 -0
  430. package/src/components/ui/scroll-area.tsx +72 -0
  431. package/src/components/ui/selection-tile-grid.tsx +9 -2
  432. package/src/components/ui/sidebar.tsx +84 -12
  433. package/src/components/ui/slider.tsx +83 -0
  434. package/src/globals.css +494 -151
  435. package/src/globals.d.ts +20 -0
  436. package/src/index.ts +68 -1
  437. package/src/lib/conditional-rule-match.ts +119 -0
  438. package/src/lib/data-list-display-options.ts +35 -0
  439. package/src/lib/data-list-view-registry.ts +104 -0
  440. package/src/lib/data-list-view-surface.ts +83 -0
  441. package/src/lib/data-list-view.ts +47 -0
  442. package/src/lib/dev-log.ts +10 -0
  443. package/src/lib/editable-target.ts +20 -0
  444. package/src/lib/list-page-table-properties.ts +48 -0
  445. package/src/lib/raf-throttle.ts +45 -0
  446. package/src/lib/row-height.ts +19 -0
  447. package/src/lib/table-properties-types.ts +98 -0
  448. package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
  449. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
  450. package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
  451. package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
  452. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
  453. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  454. package/template/AGENTS.md +84 -20
  455. package/template/app/(app)/examples/page.tsx +0 -1
  456. package/template/app/(app)/layout.tsx +17 -4
  457. package/template/app/(app)/question-bank/layout.tsx +1 -1
  458. package/template/app/(app)/question-bank/new/page.tsx +11 -24
  459. package/template/app/globals.css +13 -1972
  460. package/template/components/ask-leo-sidebar.tsx +5 -1
  461. package/template/components/brand-color-picker.tsx +2 -2
  462. package/template/components/charts-overview.tsx +1 -1
  463. package/template/components/compliance-table.tsx +240 -384
  464. package/template/components/dashboard-report-charts.tsx +1 -1
  465. package/template/components/dashboard-tabs.tsx +1 -1
  466. package/template/components/data-table/filter-date-calendar.tsx +1 -38
  467. package/template/components/data-table/filter-text-value-input.tsx +1 -77
  468. package/template/components/data-table/index.tsx +1 -1634
  469. package/template/components/data-table/pagination.tsx +1 -255
  470. package/template/components/data-table/types.ts +1 -94
  471. package/template/components/data-table/use-table-state.test.ts +420 -0
  472. package/template/components/data-table/use-table-state.ts +1 -758
  473. package/template/components/data-view-dashboard-charts-compliance.tsx +2 -2
  474. package/template/components/data-view-dashboard-charts-team.tsx +2 -2
  475. package/template/components/data-view-dashboard-charts.tsx +2 -2
  476. package/template/components/data-views/board-card-primitives.tsx +1 -93
  477. package/template/components/data-views/data-row-list.tsx +1 -183
  478. package/template/components/data-views/finder-panel-view.tsx +1 -405
  479. package/template/components/data-views/folder-grid-view.tsx +1 -86
  480. package/template/components/data-views/hub-table.tsx +1 -0
  481. package/template/components/data-views/index.ts +42 -1
  482. package/template/components/data-views/list-page-board-card.tsx +1 -192
  483. package/template/components/data-views/list-page-board-template.tsx +1 -122
  484. package/template/components/data-views/list-page-connected-view-body.tsx +1 -0
  485. package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
  486. package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -60
  487. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
  488. package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
  489. package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
  490. package/template/components/data-views/list-page-view-frame.tsx +5 -53
  491. package/template/components/data-views/os-folder-glyph.tsx +1 -129
  492. package/template/components/data-views/outline-tree-menu.tsx +1 -157
  493. package/template/components/export-drawer.test.tsx +71 -0
  494. package/template/components/export-drawer.tsx +1 -375
  495. package/template/components/exxat-product-logo.tsx +5 -5
  496. package/template/components/hub-tree-panel-view.tsx +2 -2
  497. package/template/components/invite-collaborators-drawer.tsx +3 -3
  498. package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
  499. package/template/components/key-metrics.tsx +1 -1063
  500. package/template/components/leo-insight-indicator.tsx +2 -2
  501. package/template/components/new-placement-back-btn.tsx +1 -1
  502. package/template/components/new-placement-form.tsx +63 -189
  503. package/template/components/new-question-composer.tsx +432 -402
  504. package/template/components/onboarding/index.ts +9 -0
  505. package/template/components/onboarding/onboarding-01.tsx +1 -1
  506. package/template/components/onboarding/onboarding-02.tsx +1 -1
  507. package/template/components/onboarding/onboarding-03.tsx +1 -1
  508. package/template/components/onboarding/onboarding-04.tsx +1 -1
  509. package/template/components/page-header.tsx +8 -226
  510. package/template/components/placement-board-card.tsx +71 -83
  511. package/template/components/placements-board-view.tsx +3 -10
  512. package/template/components/placements-client.tsx +10 -42
  513. package/template/components/placements-list-view.tsx +22 -69
  514. package/template/components/placements-table-columns.tsx +8 -438
  515. package/template/components/placements-table.tsx +588 -1296
  516. package/template/components/product-switcher.tsx +1 -1
  517. package/template/components/product-wordmark.tsx +2 -1
  518. package/template/components/question-bank-client.tsx +4 -1
  519. package/template/components/question-bank-hub-client.tsx +1 -1
  520. package/template/components/question-bank-new-folder-sheet.tsx +2 -2
  521. package/template/components/question-bank-secondary-nav.tsx +3 -3
  522. package/template/components/question-bank-table.tsx +294 -526
  523. package/template/components/rotations-empty-state.tsx +1 -1
  524. package/template/components/rotations-panel-activator.tsx +1 -1
  525. package/template/components/settings-appearance-card.tsx +1 -1
  526. package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
  527. package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +4 -4
  528. package/template/components/sidebar/index.ts +16 -0
  529. package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
  530. package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +6 -3
  531. package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
  532. package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
  533. package/template/components/site-header.tsx +1 -1
  534. package/template/components/{sites-all-client.tsx → sites-client.tsx} +1 -1
  535. package/template/components/sites-table.tsx +124 -257
  536. package/template/components/table-properties/column-row.tsx +1 -90
  537. package/template/components/table-properties/draggable-list.ts +1 -49
  538. package/template/components/table-properties/drawer-button.tsx +1 -249
  539. package/template/components/table-properties/drawer.tsx +1 -1105
  540. package/template/components/table-properties/filter-card.tsx +1 -251
  541. package/template/components/table-properties/sort-card.tsx +1 -59
  542. package/template/components/table-properties/types.ts +28 -71
  543. package/template/components/team-table.tsx +242 -382
  544. package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
  545. package/template/components/templates/dedicated-search-results-template.tsx +1 -19
  546. package/template/components/templates/list-page.tsx +1 -584
  547. package/template/components/templates/nested-secondary-panel-shell.tsx +1 -62
  548. package/template/components/templates/new-focus-template.tsx +659 -0
  549. package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
  550. package/template/components/ui/accordion.tsx +1 -0
  551. package/template/components/ui/alert-dialog.tsx +1 -0
  552. package/template/components/ui/context-menu.tsx +1 -0
  553. package/template/components/ui/dot-pattern.tsx +1 -183
  554. package/template/components/ui/hover-card.tsx +1 -0
  555. package/template/components/ui/resizable.tsx +1 -68
  556. package/template/components/ui/scroll-area.tsx +1 -0
  557. package/template/components/ui/slider.tsx +1 -0
  558. package/template/docs/blueprints/README.md +86 -0
  559. package/template/docs/blueprints/_template.md +91 -0
  560. package/template/docs/blueprints/board-card.md +123 -0
  561. package/template/docs/blueprints/data-table.md +139 -0
  562. package/template/docs/blueprints/key-metrics.md +128 -0
  563. package/template/docs/blueprints/list-page-template.md +123 -0
  564. package/template/docs/blueprints/page-header.md +130 -0
  565. package/template/docs/command-menu-pattern.md +1 -1
  566. package/template/docs/component-selection-guide.md +224 -0
  567. package/template/docs/components-audit-2026-05.md +158 -0
  568. package/template/docs/data-views-pattern.md +14 -14
  569. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
  570. package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
  571. package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
  572. package/template/docs/migrations/README.md +100 -0
  573. package/template/docs/migrations/_template.md +64 -0
  574. package/template/docs/token-taxonomy.md +416 -0
  575. package/template/eslint.config.mjs +27 -0
  576. package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
  577. package/template/lib/command-menu-config.ts +0 -1
  578. package/template/lib/compliance-supported-views.ts +10 -0
  579. package/template/lib/conditional-rule-match.ts +6 -97
  580. package/template/lib/data-list-display-options.ts +1 -35
  581. package/template/lib/data-list-view-registry.ts +1 -0
  582. package/template/lib/data-list-view-surface.ts +1 -69
  583. package/template/lib/data-list-view.ts +1 -38
  584. package/template/lib/dev-log.ts +1 -8
  585. package/template/lib/editable-target.ts +1 -10
  586. package/template/lib/hub-connected-view-renderers.ts +58 -0
  587. package/template/lib/list-hub-supported-views.ts +10 -0
  588. package/template/lib/list-page-table-properties.ts +1 -52
  589. package/template/lib/mock/navigation.tsx +0 -8
  590. package/template/lib/mock/placements.ts +0 -7
  591. package/template/lib/placement-board-card-layout.ts +41 -41
  592. package/template/lib/placements-supported-views.ts +12 -0
  593. package/template/lib/question-bank-supported-views.ts +12 -0
  594. package/template/lib/raf-throttle.ts +1 -45
  595. package/template/lib/row-height.ts +4 -10
  596. package/template/lib/sidebar-state-cookie.ts +11 -2
  597. package/template/lib/sites-supported-views.ts +10 -0
  598. package/template/lib/team-supported-views.ts +10 -0
  599. package/template/package.json +1 -0
  600. package/template/tests/setup.ts +25 -0
  601. package/src/theme.css +0 -1132
  602. package/template/app/(app)/data-list/[id]/page.tsx +0 -44
  603. package/template/app/(app)/data-list/new/page.tsx +0 -34
  604. package/template/app/(app)/data-list/page.tsx +0 -10
  605. package/template/components/compliance-list-view.tsx +0 -54
  606. package/template/components/dashboard-onboarding-gallery.tsx +0 -13
  607. package/template/components/dashboard-onboarding.tsx +0 -21
  608. package/template/components/question-bank-list-view.tsx +0 -53
  609. package/template/components/section-cards.tsx +0 -106
  610. package/template/components/sites-list-view.tsx +0 -42
  611. package/template/components/team-list-view.tsx +0 -59
  612. package/template/lib/placement-lifecycle.ts +0 -5
  613. /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
  614. /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
  615. /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
  616. /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
  617. /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
  618. /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
@@ -1,584 +1 @@
1
- "use client"
2
-
3
- /**
4
- * ListPageTemplate — reusable template for any list-based page.
5
- *
6
- * Provides: page header slot, optional key metrics, tabbed views
7
- * (table/list/board/dashboard) with add/remove/configure per-tab,
8
- * and an export drawer.
9
- *
10
- * Usage:
11
- * <ListPageTemplate
12
- * header={<MyPageHeader />}
13
- * metrics={<KeyMetrics ... />}
14
- * defaultTabs={DEFAULT_TABS}
15
- * renderContent={(tab) => <MyTable members={MOCK_ROWS} view={tab.viewType} />}
16
- * />
17
- *
18
- * Connected views (table | list | board | dashboard) must share one `useTableState`
19
- * and pass `tableState.rows` into non-table surfaces — see `docs/data-views-pattern.md`
20
- * and `AGENTS.md` §4.
21
- *
22
- * View chrome is shared with `ViewSegmentedControl` / `viewSegmentedToolbarClass` in
23
- * `@/components/ui/view-segmented-control` and re-exported from `@/components/data-views`.
24
- */
25
-
26
- import * as React from "react"
27
- import { cn } from "@/lib/utils"
28
- import { Tip } from "@/components/ui/tip"
29
- import { ExportDrawer } from "@/components/export-drawer"
30
- import { Button } from "@/components/ui/button"
31
- import { Input } from "@/components/ui/input"
32
- import {
33
- Dialog,
34
- DialogContent,
35
- DialogDescription,
36
- DialogFooter,
37
- DialogHeader,
38
- DialogTitle,
39
- } from "@/components/ui/dialog"
40
- import {
41
- DropdownMenu,
42
- DropdownMenuContent,
43
- DropdownMenuItem,
44
- DropdownMenuLabel,
45
- DropdownMenuSeparator,
46
- DropdownMenuTrigger,
47
- Shortcut,
48
- } from "@/components/ui/dropdown-menu"
49
- import type { DataListViewType } from "@/lib/data-list-view"
50
- import { DATA_LIST_VIEW_TILES, dataListViewAddShortcut } from "@/lib/data-list-view"
51
- import {
52
- createListPageEditViewHandler,
53
- type OpenTablePropertiesHandle,
54
- } from "@/lib/list-page-table-properties"
55
- import {
56
- viewSegmentedToolbarClass,
57
- viewSegmentedButtonClass,
58
- } from "@/components/ui/view-segmented-control"
59
-
60
- // ─────────────────────────────────────────────────────────────────────────────
61
- // Types
62
- // ─────────────────────────────────────────────────────────────────────────────
63
-
64
- export type ViewType = DataListViewType
65
-
66
- /** Same labels/icons as Properties drawer `SelectionTileGrid` — single source in `DATA_LIST_VIEW_TILES`. */
67
- export const VIEW_TYPES: { type: ViewType; label: string; icon: string }[] = DATA_LIST_VIEW_TILES.map(t => ({
68
- type: t.value,
69
- label: t.label,
70
- icon: t.icon,
71
- }))
72
-
73
- export interface FilterOption {
74
- id: string
75
- label: string
76
- }
77
-
78
- export interface ViewTab {
79
- id: string
80
- label: string
81
- viewType: ViewType
82
- icon: string
83
- /** Optional filter key for lifecycle or category-based filtering */
84
- filterId: string
85
- }
86
-
87
- export interface ListPageTemplateProps {
88
- /** Page header — rendered above metrics */
89
- header: React.ReactNode
90
- /** Optional metrics strip — rendered below header */
91
- metrics?: React.ReactNode
92
- /** Whether to show metrics (controlled externally) */
93
- showMetrics?: boolean
94
- /** Initial tabs (uncontrolled mode) */
95
- defaultTabs: ViewTab[]
96
- /**
97
- * Controlled tabs — when all four are provided, tab state is owned by the parent
98
- * (e.g. for localStorage). Otherwise `defaultTabs` + internal state are used.
99
- */
100
- tabs?: ViewTab[]
101
- onTabsChange?: (tabs: ViewTab[]) => void
102
- activeTabId?: string
103
- onActiveTabChange?: (id: string) => void
104
- /** Filter options per tab (e.g. All, Upcoming, Ongoing, Completed) */
105
- filterOptions?: FilterOption[]
106
- /** Label for the filter sub-menu (default: "Filter") */
107
- filterLabel?: string
108
- /** Get count for a tab's filter (for badge) */
109
- getTabCount?: (filterId: string) => number
110
- /** Render the content for the active tab */
111
- renderContent: (tab: ViewTab, updateTab: (patch: Partial<ViewTab>) => void) => React.ReactNode
112
- /** Export drawer props */
113
- exportOpen?: boolean
114
- onExportOpenChange?: (open: boolean) => void
115
- /** Row count for export; if omitted, uses `getTabCount(activeTab.filterId)` when provided */
116
- exportTotalRows?: number
117
- /**
118
- * Tab menu — “Edit” (e.g. open table properties). Parent can switch to table view first, then call ref.
119
- * Overrides `tablePropertiesRef` when both are set.
120
- */
121
- onEditView?: (tab: ViewTab, helpers: { updateTab: (patch: Partial<ViewTab>) => void }) => void
122
- /**
123
- * Ref to the active tab’s table surface (`openPropertiesDrawer`). Wires “View → Edit” to
124
- * `TablePropertiesDrawer` when `onEditView` is omitted.
125
- */
126
- tablePropertiesRef?: React.RefObject<OpenTablePropertiesHandle | null>
127
- /** When true, hide the views tab strip (tabs + add view) — e.g. search landing with a single table surface. */
128
- hideViewsToolbar?: boolean
129
- }
130
-
131
- /** Collision-proof id for a dynamically-added tab. Module-level counters reset
132
- * on HMR while React state survives, so we derive from a timestamp + random. */
133
- function makeTabId(type: string): string {
134
- const rand = Math.random().toString(36).slice(2, 8)
135
- return `${type}-${Date.now().toString(36)}-${rand}`
136
- }
137
-
138
- /** Count pill on the views toolbar — color by lifecycle/status filter (WCAG: dark text on light inactive; light text on solid active). */
139
- export function viewToolbarCountBadgeClass(filterId: string, isActive: boolean): string {
140
- const palettes: Record<string, { active: string; inactive: string }> = {
141
- all: {
142
- active: "bg-slate-600 text-white dark:bg-slate-500",
143
- inactive: "bg-slate-100 text-slate-800 dark:bg-slate-800/70 dark:text-slate-100",
144
- },
145
- upcoming: {
146
- active: "bg-amber-600 text-white",
147
- inactive: "bg-amber-100 text-amber-950 dark:bg-amber-950/45 dark:text-amber-100",
148
- },
149
- ongoing: {
150
- active: "bg-blue-600 text-white",
151
- inactive: "bg-blue-100 text-blue-950 dark:bg-blue-950/45 dark:text-blue-100",
152
- },
153
- completed: {
154
- active: "bg-emerald-600 text-white",
155
- inactive: "bg-emerald-100 text-emerald-950 dark:bg-emerald-950/45 dark:text-emerald-100",
156
- },
157
- }
158
- const p = palettes[filterId] ?? palettes.all
159
- return isActive ? p.active : p.inactive
160
- }
161
-
162
- // ─────────────────────────────────────────────────────────────────────────────
163
- // Component
164
- // ─────────────────────────────────────────────────────────────────────────────
165
-
166
- export function ListPageTemplate({
167
- header,
168
- metrics,
169
- showMetrics = true,
170
- defaultTabs,
171
- tabs: tabsProp,
172
- onTabsChange,
173
- activeTabId: activeTabIdProp,
174
- onActiveTabChange,
175
- getTabCount,
176
- renderContent,
177
- exportOpen = false,
178
- onExportOpenChange,
179
- exportTotalRows = 0,
180
- onEditView,
181
- tablePropertiesRef,
182
- hideViewsToolbar = false,
183
- }: ListPageTemplateProps) {
184
- const controlled =
185
- tabsProp !== undefined &&
186
- onTabsChange !== undefined &&
187
- activeTabIdProp !== undefined &&
188
- onActiveTabChange !== undefined
189
-
190
- const [internalTabs, setInternalTabs] = React.useState<ViewTab[]>(defaultTabs)
191
- const [internalActiveId, setInternalActiveId] = React.useState(defaultTabs[0]?.id ?? "")
192
-
193
- const tabs = controlled ? tabsProp : internalTabs
194
- const setTabsState = React.useCallback(
195
- (action: React.SetStateAction<ViewTab[]>) => {
196
- if (controlled) {
197
- const next = typeof action === "function" ? action(tabsProp!) : action
198
- onTabsChange!(next)
199
- } else {
200
- setInternalTabs(action)
201
- }
202
- },
203
- [controlled, onTabsChange, tabsProp, setInternalTabs],
204
- )
205
- const activeTabId = controlled ? activeTabIdProp : internalActiveId
206
- const setActiveTabId = controlled ? onActiveTabChange : setInternalActiveId
207
- const [renameOpen, setRenameOpen] = React.useState(false)
208
- const [renameValue, setRenameValue] = React.useState("")
209
- const [renameTabId, setRenameTabId] = React.useState<string | null>(null)
210
- const [reviewOpen, setReviewOpen] = React.useState(false)
211
- const [reviewTab, setReviewTab] = React.useState<ViewTab | null>(null)
212
-
213
- const activeTab = tabs.find(t => t.id === activeTabId) ?? tabs[0]
214
-
215
- const editViewFromRef = React.useMemo(
216
- () => (tablePropertiesRef ? createListPageEditViewHandler(tablePropertiesRef) : undefined),
217
- [tablePropertiesRef]
218
- )
219
- const resolvedOnEditView = onEditView ?? editViewFromRef
220
-
221
- function addView(type: ViewType) {
222
- const def = VIEW_TYPES.find(d => d.type === type)!
223
- const count = tabs.filter(t => t.viewType === type).length
224
- const id = makeTabId(type)
225
- const label = count === 0 ? def.label : `${def.label} ${count + 1}`
226
- const newTab: ViewTab = { id, label, viewType: type, icon: def.icon, filterId: "all" }
227
- setTabsState(prev => [...prev, newTab])
228
- setActiveTabId(id)
229
- }
230
-
231
- function removeTab(id: string, e: React.MouseEvent | React.KeyboardEvent) {
232
- e.stopPropagation()
233
- setTabsState(prev => {
234
- const next = prev.filter(t => t.id !== id)
235
- if (activeTabId === id && next.length > 0) {
236
- const idx = Math.max(0, prev.findIndex(t => t.id === id) - 1)
237
- setActiveTabId(next[Math.min(idx, next.length - 1)].id)
238
- }
239
- return next
240
- })
241
- }
242
-
243
- function updateTab(id: string, patch: Partial<ViewTab>) {
244
- setTabsState(prev => prev.map(t => t.id === id ? { ...t, ...patch } : t))
245
- }
246
-
247
- function duplicateTab(tab: ViewTab) {
248
- const id = makeTabId(tab.viewType)
249
- const newTab: ViewTab = {
250
- id,
251
- label: `Copy of ${tab.label}`,
252
- viewType: tab.viewType,
253
- icon: tab.icon,
254
- filterId: tab.filterId,
255
- }
256
- setTabsState(prev => [...prev, newTab])
257
- setActiveTabId(id)
258
- }
259
-
260
- function openRename(tab: ViewTab) {
261
- setRenameTabId(tab.id)
262
- setRenameValue(tab.label)
263
- setRenameOpen(true)
264
- }
265
-
266
- function commitRename() {
267
- if (!renameTabId) return
268
- const v = renameValue.trim()
269
- if (v) updateTab(renameTabId, { label: v })
270
- setRenameOpen(false)
271
- setRenameTabId(null)
272
- }
273
-
274
- return (
275
- <>
276
- {!hideViewsToolbar && VIEW_TYPES.slice(0, 9).map((v, i) => {
277
- const keys = dataListViewAddShortcut(i)
278
- return keys ? (
279
- <Shortcut
280
- key={v.type}
281
- keys={keys}
282
- onInvoke={() => addView(v.type)}
283
- />
284
- ) : null
285
- })}
286
- {activeTab && !hideViewsToolbar && (
287
- <>
288
- <Shortcut keys="F2" onInvoke={() => openRename(activeTab)} />
289
- <Shortcut
290
- keys="⌘E"
291
- disabled={!resolvedOnEditView}
292
- onInvoke={() => resolvedOnEditView?.(activeTab, { updateTab: p => updateTab(activeTab.id, p) })}
293
- />
294
- <Shortcut keys="⌘D" onInvoke={() => duplicateTab(activeTab)} />
295
- <Shortcut keys="⌘I" onInvoke={() => { setReviewTab(activeTab); setReviewOpen(true) }} />
296
- <Shortcut
297
- keys="⌘⌫"
298
- disabled={tabs.length <= 1}
299
- onInvoke={(e) => removeTab(activeTab.id, e as unknown as React.KeyboardEvent)}
300
- />
301
- </>
302
- )}
303
- {header}
304
-
305
- {showMetrics && metrics}
306
-
307
- {/* ── Views toolbar (not tablist: settings/close are not tabs — WCAG 1.3.1 / ARIA) ── */}
308
- {!hideViewsToolbar && (
309
- <>
310
- {/* Outer: horizontal scroll only. Inner: vertical padding so ring-offset focus rings are not clipped
311
- (`overflow-x-auto` forces overflow-y to clip in a single box). */}
312
- <div className="mt-3 shrink-0 overflow-x-auto px-4 lg:px-6">
313
- <div className="flex w-max items-center gap-1 py-1.5">
314
- <div
315
- role="toolbar"
316
- aria-label="Views"
317
- data-slot="view-segmented-toolbar"
318
- className={viewSegmentedToolbarClass()}
319
- >
320
- {tabs.map(tab => {
321
- const isActive = tab.id === activeTabId
322
- const isOnly = tabs.length === 1
323
- const count = getTabCount?.(tab.filterId)
324
- const tabInner = (
325
- <>
326
- <i className={cn("fa-light shrink-0 text-xs", tab.icon)} aria-hidden="true" />
327
- {tab.label}
328
- {count !== undefined && (
329
- <span
330
- data-slot="view-toolbar-count"
331
- className={cn(
332
- "text-xs tabular-nums rounded-full px-1 py-px min-w-[1.125rem] text-center font-semibold",
333
- viewToolbarCountBadgeClass(tab.filterId, isActive),
334
- )}
335
- >
336
- {count}
337
- </span>
338
- )}
339
- </>
340
- )
341
- const viewSettingsMenu = (
342
- <DropdownMenu>
343
- <Tip label="View settings" side="bottom">
344
- <DropdownMenuTrigger asChild>
345
- <button
346
- type="button"
347
- className={cn(
348
- "inline-flex items-center justify-center min-h-8 min-w-6 shrink-0 rounded-r-md rounded-l-none px-0.5",
349
- "text-muted-foreground hover:text-interactive-hover-foreground hover:bg-foreground/[0.04]",
350
- "transition-colors",
351
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:z-10",
352
- )}
353
- aria-label="View settings"
354
- >
355
- <i className="fa-light fa-chevron-down text-xs" aria-hidden="true" />
356
- </button>
357
- </DropdownMenuTrigger>
358
- </Tip>
359
- <DropdownMenuContent align="start">
360
- <DropdownMenuLabel className="text-xs text-muted-foreground">
361
- View: {VIEW_TYPES.find(v => v.type === tab.viewType)?.label}
362
- </DropdownMenuLabel>
363
- <DropdownMenuSeparator />
364
-
365
- <DropdownMenuItem
366
- shortcut="F2"
367
- onSelect={() => openRename(tab)}
368
- >
369
- <i className="fa-light fa-pen text-xs" aria-hidden="true" />
370
- Rename
371
- </DropdownMenuItem>
372
- <DropdownMenuItem
373
- disabled={!resolvedOnEditView}
374
- shortcut="⌘E"
375
- onSelect={() =>
376
- resolvedOnEditView?.(tab, { updateTab: patch => updateTab(tab.id, patch) })
377
- }
378
- >
379
- <i className="fa-light fa-sliders text-xs" aria-hidden="true" />
380
- Edit
381
- </DropdownMenuItem>
382
- <DropdownMenuItem shortcut="⌘D" onSelect={() => duplicateTab(tab)}>
383
- <i className="fa-light fa-copy text-xs" aria-hidden="true" />
384
- Duplicate
385
- </DropdownMenuItem>
386
- <DropdownMenuItem
387
- shortcut="⌘I"
388
- onSelect={() => { setReviewTab(tab); setReviewOpen(true) }}
389
- >
390
- <i className="fa-light fa-clipboard-list text-xs" aria-hidden="true" />
391
- Review view
392
- </DropdownMenuItem>
393
-
394
- <DropdownMenuSeparator />
395
- {!isOnly && (
396
- <DropdownMenuItem
397
- shortcut="⌘⌫"
398
- onSelect={(e) => removeTab(tab.id, e as unknown as React.KeyboardEvent)}
399
- className="text-destructive focus:text-destructive"
400
- >
401
- <i className="fa-light fa-trash text-xs" aria-hidden="true" />
402
- Remove view
403
- </DropdownMenuItem>
404
- )}
405
- </DropdownMenuContent>
406
- </DropdownMenu>
407
- )
408
- return (
409
- <div key={tab.id} className="group relative inline-flex items-center">
410
- {isActive ? (
411
- <div
412
- className={cn(
413
- viewSegmentedButtonClass(true),
414
- "gap-0 p-0 inline-flex items-stretch",
415
- )}
416
- >
417
- <button
418
- type="button"
419
- aria-pressed={true}
420
- data-slot="view-segmented-item"
421
- onClick={() => setActiveTabId(tab.id)}
422
- className={cn(
423
- "inline-flex items-center gap-1.5 pl-2.5 pr-0.5 py-1 text-xs min-h-8",
424
- "rounded-l-md rounded-r-none",
425
- "bg-transparent text-foreground font-medium",
426
- "hover:bg-foreground/[0.04]",
427
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:z-10",
428
- )}
429
- >
430
- {tabInner}
431
- </button>
432
- {viewSettingsMenu}
433
- </div>
434
- ) : (
435
- <button
436
- type="button"
437
- aria-pressed={false}
438
- data-slot="view-segmented-item"
439
- onClick={() => setActiveTabId(tab.id)}
440
- className={cn(
441
- viewSegmentedButtonClass(false),
442
- /* Tighter trailing edge when remove control follows */
443
- !isOnly && "pr-1.5",
444
- )}
445
- >
446
- {tabInner}
447
- </button>
448
- )}
449
-
450
- {/* Close on inactive tabs — native button + 24px min target (WCAG 2.5.8) */}
451
- {!isActive && !isOnly && (
452
- <Tip side="bottom" label={`Remove ${tab.label} view`}>
453
- <button
454
- type="button"
455
- aria-label={`Remove ${tab.label} view`}
456
- onClick={e => removeTab(tab.id, e)}
457
- className="inline-flex items-center justify-center size-6 min-h-6 min-w-6 rounded transition-opacity opacity-0 group-hover:opacity-60 hover:!opacity-100 hover:text-destructive focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
458
- >
459
- <i className="fa-light fa-xmark text-xs" aria-hidden="true" />
460
- </button>
461
- </Tip>
462
- )}
463
- </div>
464
- )
465
- })}
466
- </div>
467
-
468
- {/* Add view */}
469
- <DropdownMenu>
470
- <DropdownMenuTrigger asChild>
471
- <Button
472
- type="button"
473
- variant="ghost"
474
- className="shrink-0 text-muted-foreground"
475
- >
476
- <i className="fa-light fa-plus text-sm" aria-hidden="true" />
477
- Add view
478
- </Button>
479
- </DropdownMenuTrigger>
480
- <DropdownMenuContent align="start">
481
- <DropdownMenuLabel className="text-xs">Add a view</DropdownMenuLabel>
482
- <DropdownMenuSeparator />
483
- {VIEW_TYPES.map((v, i) => (
484
- <DropdownMenuItem
485
- key={v.type}
486
- shortcut={dataListViewAddShortcut(i)}
487
- onSelect={() => addView(v.type)}
488
- >
489
- <i className={`fa-light ${v.icon}`} aria-hidden="true" />
490
- {v.label}
491
- </DropdownMenuItem>
492
- ))}
493
- </DropdownMenuContent>
494
- </DropdownMenu>
495
- </div>
496
- </div>
497
- </>
498
- )}
499
-
500
- {/* ── Content — keyed by tab so each view tab owns its height (no stale min-height). ── */}
501
- {activeTab ? (
502
- <div key={activeTab.id} className="flex min-h-0 flex-1 flex-col">
503
- {renderContent(activeTab, patch => updateTab(activeTab.id, patch))}
504
- </div>
505
- ) : null}
506
-
507
- {/* ── Export ──────────────────────────────────────────────── */}
508
- {onExportOpenChange && (
509
- <ExportDrawer
510
- open={exportOpen}
511
- onOpenChange={onExportOpenChange}
512
- totalRows={exportTotalRows ?? getTabCount?.(activeTab.filterId) ?? 0}
513
- />
514
- )}
515
-
516
- <Dialog open={renameOpen} onOpenChange={setRenameOpen}>
517
- <DialogContent className="max-w-sm">
518
- <DialogHeader>
519
- <DialogTitle>Rename view</DialogTitle>
520
- <DialogDescription>Enter a new name for this view.</DialogDescription>
521
- </DialogHeader>
522
- <Input
523
- className="mt-3 h-9 text-sm"
524
- value={renameValue}
525
- onChange={e => setRenameValue(e.target.value)}
526
- onKeyDown={e => { if (e.key === "Enter") commitRename() }}
527
- autoFocus
528
- aria-label="View name"
529
- />
530
- <DialogFooter>
531
- <Button type="button" variant="outline" size="sm" onClick={() => setRenameOpen(false)}>
532
- Cancel
533
- </Button>
534
- <Button type="button" size="sm" onClick={commitRename}>
535
- Save
536
- </Button>
537
- </DialogFooter>
538
- </DialogContent>
539
- </Dialog>
540
-
541
- <Dialog
542
- open={reviewOpen && !!reviewTab}
543
- onOpenChange={(open) => {
544
- setReviewOpen(open)
545
- if (!open) setReviewTab(null)
546
- }}
547
- >
548
- <DialogContent className="max-w-md">
549
- <DialogHeader>
550
- <DialogTitle>Review view</DialogTitle>
551
- <DialogDescription>Summary of this view’s configuration.</DialogDescription>
552
- </DialogHeader>
553
- {reviewTab && (
554
- <dl className="mt-2 space-y-3 text-sm">
555
- <div className="flex justify-between gap-4 border-b border-border pb-2">
556
- <dt className="text-muted-foreground">Name</dt>
557
- <dd className="font-medium text-foreground text-end">{reviewTab.label}</dd>
558
- </div>
559
- <div className="flex justify-between gap-4 border-b border-border pb-2">
560
- <dt className="text-muted-foreground">View type</dt>
561
- <dd className="text-foreground text-end">{VIEW_TYPES.find(v => v.type === reviewTab.viewType)?.label}</dd>
562
- </div>
563
- <div className="flex justify-between gap-4 border-b border-border pb-2">
564
- <dt className="text-muted-foreground">Lifecycle filter</dt>
565
- <dd className="text-foreground text-end capitalize">{reviewTab.filterId}</dd>
566
- </div>
567
- {getTabCount && (
568
- <div className="flex justify-between gap-4">
569
- <dt className="text-muted-foreground">Row count</dt>
570
- <dd className="tabular-nums text-foreground text-end">{getTabCount(reviewTab.filterId)}</dd>
571
- </div>
572
- )}
573
- </dl>
574
- )}
575
- <DialogFooter>
576
- <Button type="button" size="sm" onClick={() => setReviewOpen(false)}>
577
- Close
578
- </Button>
579
- </DialogFooter>
580
- </DialogContent>
581
- </Dialog>
582
- </>
583
- )
584
- }
1
+ export * from "@exxatdesignux/ui/components/templates/list-page"
@@ -1,62 +1 @@
1
- import * as React from "react"
2
-
3
- import { cn } from "@/lib/utils"
4
-
5
- export interface NestedSecondaryPanelShellProps {
6
- /** When false, the shell is visually hidden (no width). */
7
- open: boolean
8
- /** Icon-only rail (same width token as primary `Sidebar` collapsible icon mode). */
9
- compact: boolean
10
- children: React.ReactNode
11
- /** Forwarded to the outer `<nav>`. */
12
- "aria-label"?: string
13
- className?: string
14
- }
15
-
16
- /**
17
- * Shared chrome for a nested hub rail — full width vs icon rail.
18
- * Fill uses `--secondary-panel-bg` — one step lighter than `--sidebar` (elevation 1).
19
- */
20
- export function NestedSecondaryPanelShell({
21
- open,
22
- compact,
23
- children,
24
- "aria-label": ariaLabel = "Secondary navigation",
25
- className,
26
- }: NestedSecondaryPanelShellProps) {
27
- return (
28
- <nav
29
- aria-label={ariaLabel}
30
- data-state={open ? "open" : "closed"}
31
- data-layout={open ? (compact ? "icon" : "expanded") : "closed"}
32
- className={cn(
33
- "flex flex-col overflow-hidden",
34
- "transition-[width,margin,opacity] duration-200 ease-linear",
35
- open
36
- ? cn(
37
- // Match the primary sidebar: fill the full viewport height
38
- // (minus our 0.5rem top + 0.5rem bottom margin from `m-2` →
39
- // 1rem on desktop where the panel is `md:sticky md:top-2`;
40
- // 2rem on mobile where the panel scrolls inline and we leave
41
- // a little more breathing room). No upper cap so tall screens
42
- // get a fully-extended rail.
43
- "shrink-0 m-2 mx-2 rounded-xl ring-1 ring-sidebar-border shadow-sm relative md:sticky md:top-2 bg-[var(--secondary-panel-bg)]",
44
- compact
45
- ? "w-12 min-w-12 max-w-12 h-[calc(100svh-2rem)] md:h-[calc(100svh-1rem)]"
46
- : "w-64 min-w-64 max-w-64 h-[calc(100svh-2rem)] md:h-[calc(100svh-1rem)]",
47
- )
48
- : "h-0 min-h-0 shrink overflow-hidden border-0 p-0 m-0 min-w-0 w-0 max-w-0 opacity-0 pointer-events-none",
49
- className,
50
- )}
51
- >
52
- <div
53
- className={cn(
54
- "flex flex-1 flex-col overflow-y-auto overflow-x-hidden",
55
- open ? "min-w-0" : "hidden min-w-0 w-0 p-0",
56
- )}
57
- >
58
- {children}
59
- </div>
60
- </nav>
61
- )
62
- }
1
+ export * from "@exxatdesignux/ui/components/templates/nested-secondary-panel-shell"