@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
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { Button } from "@/components/ui/button"
9
- import { useSecondaryPanel } from "@/components/secondary-panel"
9
+ import { useSecondaryPanel } from "@/components/sidebar"
10
10
 
11
11
  export function RotationsEmptyState() {
12
12
  const { openPanel } = useSecondaryPanel()
@@ -1,6 +1,6 @@
1
1
  "use client"
2
2
 
3
- import { useAutoPanel } from "@/components/secondary-panel"
3
+ import { useAutoPanel } from "@/components/sidebar"
4
4
 
5
5
  export function RotationsPanelActivator() {
6
6
  useAutoPanel("rotations")
@@ -622,7 +622,7 @@ export function SettingsAppearanceCard() {
622
622
  side="top"
623
623
  >
624
624
  <span
625
- className="inline-flex shrink-0 items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-foreground"
625
+ className="inline-flex shrink-0 items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium uppercase tracking-wide text-foreground"
626
626
  aria-label="Active product"
627
627
  >
628
628
  <i
@@ -7,7 +7,7 @@
7
7
  * Radix ID mismatch is suppressed at the CollapsibleContent level instead.
8
8
  */
9
9
  import type { ComponentProps } from "react"
10
- import { AppSidebar } from "@/components/app-sidebar"
10
+ import { AppSidebar } from "./app-sidebar"
11
11
  import type { Sidebar } from "@/components/ui/sidebar"
12
12
 
13
13
  export function AppSidebarDynamic(props: ComponentProps<typeof Sidebar>) {
@@ -67,8 +67,8 @@ import { useModKeyLabel } from "@/hooks/use-mod-key-label"
67
67
  import { useLocationHash } from "@/hooks/use-location-hash"
68
68
  import { useSidebarReflowZoom } from "@/hooks/use-sidebar-reflow-zoom"
69
69
  import { useProduct, type Product } from "@/contexts/product-context"
70
- import { NavUser } from "@/components/nav-user"
71
- import { useSecondaryPanel } from "@/components/secondary-panel"
70
+ import { NavUser } from "./nav-user"
71
+ import { useSecondaryPanel } from "./secondary-panel"
72
72
  import { ExxatProductLogo, ExxatProductMark } from "@/components/exxat-product-logo"
73
73
  import { motionHeaderEnter } from "@/lib/motion-ui"
74
74
  import { customProductBrandConfig, productBrandLabel } from "@/lib/product-brand"
@@ -423,7 +423,7 @@ function CollapsibleNavItem({ item, pathname }: { item: NavLinkItem; pathname: s
423
423
  </span>
424
424
  <span>{item.title}</span>
425
425
  <i
426
- className="fa-light fa-chevron-right ml-auto text-xs text-current transition-transform duration-200 ease-out group-data-[state=open]/collapsible:rotate-90 motion-reduce:transition-none"
426
+ className="fa-light fa-chevron-right ms-auto text-xs text-current transition-transform duration-200 ease-out group-data-[state=open]/collapsible:rotate-90 motion-reduce:transition-none"
427
427
  aria-hidden="true"
428
428
  />
429
429
  </SidebarMenuButton>
@@ -898,7 +898,7 @@ function ProductLogoButton() {
898
898
  className="w-auto shrink-0 max-w-[min(100%,260px)]"
899
899
  />
900
900
  {p.id === product && (
901
- <i className="fa-solid fa-check ml-auto text-brand text-xs" aria-hidden="true" />
901
+ <i className="fa-solid fa-check ms-auto text-brand text-xs" aria-hidden="true" />
902
902
  )}
903
903
  </DropdownMenuItem>
904
904
  ))}
@@ -0,0 +1,16 @@
1
+ // Barrel re-export for the sidebar shell.
2
+ // Consumers SHOULD import via `@/components/sidebar`; per-file paths still
3
+ // work as escape hatch (e.g. `@/components/sidebar/secondary-panel`).
4
+ //
5
+ // See apps/web/docs/components-audit-2026-05.md §2.3.
6
+ export * from "./app-sidebar"
7
+ export * from "./app-sidebar-dynamic"
8
+ export * from "./sidebar-shell"
9
+ export * from "./sidebar-auto-collapse"
10
+ export * from "./sidebar-auto-open"
11
+ export * from "./nav-main"
12
+ export * from "./nav-secondary"
13
+ export * from "./nav-documents"
14
+ export * from "./nav-user"
15
+ export * from "./secondary-nav"
16
+ export * from "./secondary-panel"
@@ -293,7 +293,7 @@ export function SecondaryNavPanel({
293
293
  title={section.action.label}
294
294
  onClick={section.action.onClick}
295
295
  className={cn(
296
- "inline-flex size-6 items-center justify-center rounded-md -mr-1",
296
+ "inline-flex size-6 items-center justify-center rounded-md -me-1",
297
297
  "text-muted-foreground hover:text-interactive-hover-foreground hover:bg-interactive-hover-strong",
298
298
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
299
299
  )}
@@ -318,7 +318,7 @@ export function SecondaryNavPanel({
318
318
  placeholder={section.searchPlaceholder ?? "Search"}
319
319
  aria-label={`Search ${section.label}`}
320
320
  className={cn(
321
- "w-full h-7 pl-7 pr-2 rounded-md text-xs bg-background border border-border",
321
+ "w-full h-7 ps-7 pe-2 rounded-md text-xs bg-background border border-border",
322
322
  "placeholder:text-muted-foreground/70",
323
323
  "focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent"
324
324
  )}
@@ -111,7 +111,10 @@ export function SecondaryPanelProvider({ children }: { children: React.ReactNode
111
111
  // zoom this stays the legacy behavior (full-width on open).
112
112
  setSecondaryPanelCompact(reflowZoom)
113
113
  setActivePanel(id)
114
- setOpen(false) // collapse main sidebar to icon rail
114
+ // `persist: false` collapsing the rail to make room for the secondary
115
+ // panel is an incidental layout side-effect; the user's saved
116
+ // expanded/collapsed preference (cookie) must not be overwritten by it.
117
+ setOpen(false, { persist: false }) // collapse main sidebar to icon rail
115
118
  },
116
119
  [setOpen, reflowZoom],
117
120
  )
@@ -122,9 +125,9 @@ export function SecondaryPanelProvider({ children }: { children: React.ReactNode
122
125
  const mainSidebar = opts?.mainSidebar ?? "leave"
123
126
  if (mainSidebar === "leave") return
124
127
  if (mainSidebar === "collapse") {
125
- setOpen(false)
128
+ setOpen(false, { persist: false })
126
129
  } else {
127
- setOpen(true) // expand main sidebar back
130
+ setOpen(true, { persist: false }) // expand main sidebar back
128
131
  }
129
132
  }, [setOpen])
130
133
 
@@ -7,6 +7,10 @@ import { useSidebar } from "@/components/ui/sidebar"
7
7
  * Collapses the sidebar on mount. Restores previous state on unmount.
8
8
  * Used on the new-placement page so the sidebar collapses when entering
9
9
  * and reverts to whatever it was when leaving.
10
+ *
11
+ * Both transitions pass `{ persist: false }` so the visual collapse never
12
+ * overwrites the user's saved sidebar preference (the `sidebar_state_v2`
13
+ * cookie). Only an explicit toggle (⌘B / sidebar button) persists.
10
14
  */
11
15
  export function SidebarAutoCollapse() {
12
16
  const { open, setOpen } = useSidebar()
@@ -14,8 +18,8 @@ export function SidebarAutoCollapse() {
14
18
 
15
19
  useEffect(() => {
16
20
  prevOpen.current = open
17
- setOpen(false)
18
- return () => { setOpen(prevOpen.current) }
21
+ setOpen(false, { persist: false })
22
+ return () => { setOpen(prevOpen.current, { persist: false }) }
19
23
  // eslint-disable-next-line react-hooks/exhaustive-deps
20
24
  }, [])
21
25
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * SidebarShell — SidebarProvider with layout-aware widths.
5
- * Desktop expanded/collapsed is persisted in the `sidebar_state` cookie by `@exxatdesignux/ui`
5
+ * Desktop expanded/collapsed is persisted in the `sidebar_state_v2` cookie by `@exxatdesignux/ui`
6
6
  * `SidebarProvider` (read on mount + write on toggle). `(app)/layout` passes
7
7
  * `defaultOpen` from the same cookie on the server so SSR matches the first client paint.
8
8
  */
@@ -107,7 +107,7 @@ export function SiteHeader({
107
107
  />
108
108
  )}
109
109
 
110
- <div className="ml-auto shrink-0">
110
+ <div className="ms-auto shrink-0">
111
111
  <AskLeoToggle />
112
112
  </div>
113
113
  </div>
@@ -92,7 +92,7 @@ function SitesPageHeader({
92
92
  )
93
93
  }
94
94
 
95
- export function SitesAllClient() {
95
+ export function SitesClient() {
96
96
  const [exportOpen, setExportOpen] = React.useState(false)
97
97
  const [showMetrics, setShowMetrics] = React.useState(true)
98
98
  const tableRef = React.useRef<SitesTableHandle>(null)
@@ -1,20 +1,17 @@
1
1
  "use client"
2
2
 
3
3
  /**
4
- * Sites hub — same stack as Team / Compliance: DataTableToolbar (search, filters)
5
- * + TablePropertiesDrawer, shared `useTableState` across table | list | board | dashboard.
4
+ * Sites hub — thin wrapper around the centralized `<HubTable>`. Owns only the column defs,
5
+ * the renderers for non-table views, and the mock-data wiring. All `useTableState` /
6
+ * Properties drawer / `ListPageConnectedViewBody` plumbing lives in `HubTable`.
6
7
  */
7
8
 
8
9
  import * as React from "react"
9
10
  import Link from "next/link"
10
11
  import type { SiteDirectoryRow } from "@/lib/mock/sites-directory"
11
- import { DataTable, DataTableToolbar } from "@/components/data-table"
12
- import { useTableState } from "@/components/data-table/use-table-state"
13
12
  import type { ColumnDef } from "@/components/data-table/types"
14
13
  import type { DataListViewType } from "@/lib/data-list-view"
15
- import type { OpenTablePropertiesHandle } from "@/lib/list-page-table-properties"
16
- import { TablePropertiesDrawerButton } from "@/components/table-properties"
17
- import type { ConditionalRule, FilterFieldDef, FilterOperator } from "@/components/table-properties/types"
14
+ import { HubTable, type HubTableHandle, type HubTableRenderers } from "@/components/data-views"
18
15
  import { Button } from "@/components/ui/button"
19
16
  import {
20
17
  DropdownMenu,
@@ -22,51 +19,25 @@ import {
22
19
  DropdownMenuItem,
23
20
  DropdownMenuTrigger,
24
21
  } from "@/components/ui/dropdown-menu"
25
- import { Tip } from "@/components/ui/tip"
26
22
  import { Avatar, AvatarFallback } from "@/components/ui/avatar"
27
23
  import { FinderPanelView, type FinderGroup } from "@/components/data-views/finder-panel-view"
28
24
  import { ListPageSplitHubChrome } from "@/components/data-views/list-page-split-hub-chrome"
25
+ import { ListPageBoardCard } from "@/components/data-views/list-page-board-card"
29
26
  import { SitesCardGrid } from "@/components/sites-board-view"
30
- import { SitesListView } from "@/components/sites-list-view"
31
27
  import { KeyMetrics } from "@/components/key-metrics"
32
28
  import { SITES_KPI_INSIGHT, sitesKpiMetrics } from "@/lib/mock/sites-kpi"
33
- import {
34
- DEFAULT_DATA_LIST_DISPLAY_OPTIONS,
35
- type DataListDisplayOptions,
36
- } from "@/lib/data-list-display-options"
37
-
38
- function columnToFilterFieldDef(c: ColumnDef<SiteDirectoryRow>): FilterFieldDef | null {
39
- if (!c.filter) return null
40
- const f = c.filter
41
- const defaultOps: FilterOperator[] =
42
- f.type === "select" || f.type === "date" ? ["is", "is_not"] : ["contains", "not_contains"]
43
- return {
44
- key: c.key,
45
- label: c.label,
46
- icon: f.icon ?? "fa-filter",
47
- type: f.type,
48
- operators: (f.operators ?? defaultOps) as FilterOperator[],
49
- options: f.options,
50
- ...(f.textMask ? { textMask: f.textMask } : {}),
51
- }
52
- }
53
-
54
- function columnsToFilterFields(cols: ColumnDef<SiteDirectoryRow>[]) {
55
- return cols.map(columnToFilterFieldDef).filter((x): x is FilterFieldDef => x !== null)
56
- }
29
+ import { SITES_SUPPORTED_VIEWS } from "@/lib/sites-supported-views"
57
30
 
58
31
  function buildSitesColumns(): ColumnDef<SiteDirectoryRow>[] {
59
- const COLUMN_SELECT: ColumnDef<SiteDirectoryRow> = {
60
- key: "select",
61
- label: "",
62
- width: 40,
63
- minWidth: 40,
64
- defaultPin: "left",
65
- lockPin: true,
66
- }
67
-
68
32
  return [
69
- COLUMN_SELECT,
33
+ {
34
+ key: "select",
35
+ label: "",
36
+ width: 40,
37
+ minWidth: 40,
38
+ defaultPin: "left",
39
+ lockPin: true,
40
+ },
70
41
  {
71
42
  key: "name",
72
43
  label: "Site",
@@ -97,11 +68,7 @@ function buildSitesColumns(): ColumnDef<SiteDirectoryRow>[] {
97
68
  minWidth: 120,
98
69
  sortable: true,
99
70
  sortKey: "id",
100
- filter: {
101
- type: "text",
102
- icon: "fa-hashtag",
103
- operators: ["contains", "not_contains"],
104
- },
71
+ filter: { type: "text", icon: "fa-hashtag", operators: ["contains", "not_contains"] },
105
72
  cell: row => <span className="text-sm text-foreground/90">{row.id}</span>,
106
73
  },
107
74
  {
@@ -111,11 +78,7 @@ function buildSitesColumns(): ColumnDef<SiteDirectoryRow>[] {
111
78
  minWidth: 140,
112
79
  sortable: true,
113
80
  sortKey: "url",
114
- filter: {
115
- type: "text",
116
- icon: "fa-link",
117
- operators: ["contains", "not_contains"],
118
- },
81
+ filter: { type: "text", icon: "fa-link", operators: ["contains", "not_contains"] },
119
82
  cell: row => (
120
83
  <span className="truncate text-sm text-muted-foreground" title={row.url}>
121
84
  {row.url}
@@ -152,230 +115,134 @@ function buildSitesColumns(): ColumnDef<SiteDirectoryRow>[] {
152
115
  ]
153
116
  }
154
117
 
155
-
156
- export type SitesTableHandle = OpenTablePropertiesHandle
118
+ export type SitesTableHandle = HubTableHandle
157
119
 
158
120
  export const SitesTable = React.forwardRef<
159
121
  SitesTableHandle,
160
122
  { sites: SiteDirectoryRow[]; view?: DataListViewType; onViewChange?: (v: DataListViewType) => void }
161
123
  >(function SitesTable({ sites, view = "board", onViewChange }, ref) {
162
124
  const columns = React.useMemo(() => buildSitesColumns(), [])
163
- const filterFields = React.useMemo(() => columnsToFilterFields(columns), [columns])
164
- const fieldDefinitionsForDrawer = React.useMemo(
165
- () =>
166
- columns
167
- .filter(c => c.key !== "select" && c.key !== "actions")
168
- .map(c => ({ key: c.key, label: c.label, sortable: !!(c.sortable && (c.sortKey ?? c.key)) })),
169
- [columns],
170
- )
171
125
 
172
- const resolveColumnLabel = React.useCallback(
173
- (key: string) => columns.find(c => c.key === key)?.label ?? key,
174
- [columns],
126
+ const panelGroups = React.useCallback(
127
+ (rows: SiteDirectoryRow[]): FinderGroup[] => [
128
+ { id: "all", label: `All sites (${rows.length})`, count: rows.length },
129
+ ],
130
+ [],
175
131
  )
176
132
 
177
- const [displayOptions, setDisplayOptions] = React.useState<DataListDisplayOptions>(DEFAULT_DATA_LIST_DISPLAY_OPTIONS)
178
- const patchDisplay = React.useCallback((patch: Partial<DataListDisplayOptions>) => {
179
- setDisplayOptions(prev => ({ ...prev, ...patch }))
180
- }, [])
181
-
182
- const [conditionalRules, setConditionalRules] = React.useState<ConditionalRule[]>([])
183
-
184
- const addConditionalRule = React.useCallback((rule: Omit<ConditionalRule, "id">) => {
185
- setConditionalRules(prev => [...prev, { ...rule, id: `cr-${Date.now()}` }])
186
- }, [])
187
- const removeConditionalRule = React.useCallback((id: string) => {
188
- setConditionalRules(prev => prev.filter(r => r.id !== id))
189
- }, [])
190
- const updateConditionalRule = React.useCallback((id: string, patch: Partial<ConditionalRule>) => {
191
- setConditionalRules(prev => prev.map(r => (r.id === id ? { ...r, ...patch } : r)))
192
- }, [])
193
-
194
- const tableState = useTableState<SiteDirectoryRow>(sites, columns, { key: "name", dir: "asc" })
195
-
196
- React.useImperativeHandle(
197
- ref,
198
- () => ({
199
- openPropertiesDrawer: () => {
200
- tableState.setSheetOpen(true)
201
- },
202
- }),
203
- // `tableState` is freshly returned each render by useTableState; depending
204
- // on it would re-create the imperative handle on every render. Only the
205
- // React setter is needed (and is referentially stable).
206
- // eslint-disable-next-line react-hooks/exhaustive-deps
207
- [tableState.setSheetOpen],
208
- )
209
-
210
- const dashMetrics = React.useMemo(
211
- () => sitesKpiMetrics(tableState.rows.length),
212
- [tableState.rows.length],
213
- )
214
-
215
- // Generic panel view rendering for sites
216
- const panelGroupsBuilder = (rows: SiteDirectoryRow[]): FinderGroup[] => [
217
- {
218
- id: "all",
219
- label: `All sites (${rows.length})`,
220
- count: rows.length,
221
- },
222
- ]
223
-
224
- const panelRenderListRow = (row: SiteDirectoryRow, _isSelected: boolean) => (
225
- <div className="flex-1 min-w-0 flex items-center gap-2">
226
- <Avatar size="sm" className="size-6 shrink-0">
227
- <AvatarFallback className="bg-brand/10 p-0 text-brand text-xs">
228
- <i className="fa-light fa-hospital text-xs" aria-hidden="true" />
229
- </AvatarFallback>
230
- </Avatar>
231
- <div className="flex-1 min-w-0">
232
- <p className="text-sm font-medium text-foreground truncate">{row.name}</p>
233
- <p className="text-xs text-muted-foreground truncate">{row.url}</p>
234
- </div>
235
- </div>
236
- )
237
-
238
- const panelRenderDetail = (row: SiteDirectoryRow) => (
239
- <div className="flex min-h-0 flex-1 flex-col overflow-y-auto p-4">
240
- <div>
241
- <h3 className="text-sm font-semibold text-foreground mb-2">Site</h3>
242
- <p className="text-sm text-foreground">{row.name}</p>
243
- </div>
244
- <div className="flex flex-col gap-2">
245
- <div>
246
- <span className="text-xs font-medium text-muted-foreground">Key</span>
247
- <p className="text-sm text-foreground font-mono">{row.id}</p>
248
- </div>
249
- <div>
250
- <span className="text-xs font-medium text-muted-foreground">Path</span>
251
- <p className="text-sm text-foreground break-all">{row.url}</p>
252
- </div>
253
- </div>
254
- </div>
255
- )
256
-
257
- const drawerToolbarProps = {
258
- state: tableState,
259
- totalRows: sites.length,
260
- filterFields,
261
- fieldDefinitions: fieldDefinitionsForDrawer,
262
- resolveColumnLabel,
263
- displayOptions,
264
- onDisplayOptionsChange: patchDisplay,
265
- conditionalRules,
266
- onAddConditionalRule: addConditionalRule,
267
- onRemoveConditionalRule: removeConditionalRule,
268
- onUpdateConditionalRule: updateConditionalRule,
269
- currentView: view,
270
- onViewChange,
271
- lifecycleTabLabel: "Sites",
272
- }
273
-
274
- const tableProps = {
275
- data: sites,
276
- columns,
277
- getRowId: (row: SiteDirectoryRow) => row.id,
278
- getRowSelectionLabel: (row: SiteDirectoryRow) => row.name,
279
- selectable: true,
280
- searchable: displayOptions.showToolbarSearch,
281
- showColumnHeaders: displayOptions.showColumnLabels,
282
- groupable: true,
283
- defaultSort: { key: "name", dir: "asc" as const },
284
- emptyState: <p className="text-sm text-muted-foreground">No sites match your filters.</p>,
285
- conditionalRules,
286
- state: tableState,
287
- toolbarSlot: (s: ReturnType<typeof useTableState<SiteDirectoryRow>>) => (
288
- <TablePropertiesDrawerButton {...drawerToolbarProps} state={s} />
289
- ),
290
- bulkActionsSlot: (selected: Set<string | number>) => {
291
- const n = selected.size
292
- if (n === 0) return null
293
- return (
294
- <>
295
- <span className="sr-only">{n} selected</span>
296
- <Tip label="Export selection (demo)">
297
- <Button size="sm" variant="outline" type="button">
298
- <i className="fa-light fa-arrow-down-to-line" aria-hidden="true" />
299
- Export
300
- </Button>
301
- </Tip>
302
- </>
303
- )
304
- },
305
- }
306
-
307
- if (view === "table") {
308
- return (
309
- <div className="pb-6">
310
- <DataTable<SiteDirectoryRow> {...tableProps} />
311
- </div>
312
- )
313
- }
314
-
315
- const sharedToolbar = (
316
- <DataTableToolbar
317
- state={tableState}
318
- columns={columns}
319
- searchable={displayOptions.showToolbarSearch}
320
- searchAriaLabel="Search sites"
321
- toolbarSlot={s => <TablePropertiesDrawerButton {...drawerToolbarProps} state={s} />}
322
- />
323
- )
324
-
325
- if (view === "list") {
326
- return (
327
- <div className="flex min-h-0 flex-1 flex-col">
328
- {sharedToolbar}
329
- <SitesListView rows={tableState.rows} />
330
- </div>
331
- )
332
- }
333
-
334
- if (view === "board") {
335
- return (
336
- <div className="flex min-h-0 flex-1 flex-col">
337
- {sharedToolbar}
338
- <SitesCardGrid rows={tableState.rows} />
339
- </div>
340
- )
341
- }
342
-
343
- if (view === "panel") {
344
- return (
345
- <div className="flex min-h-0 flex-1 flex-col">
346
- {sharedToolbar}
133
+ const renderers: HubTableRenderers<SiteDirectoryRow> = {
134
+ "board-with-toolbar": ({ state, toolbarShell }) =>
135
+ toolbarShell(<SitesCardGrid rows={state.rows} />),
136
+ "panel-with-toolbar": ({ state, toolbarShell }) =>
137
+ toolbarShell(
347
138
  <ListPageSplitHubChrome aria-label="Sites directory panel view">
348
139
  <FinderPanelView<SiteDirectoryRow>
349
140
  embedded
350
141
  groupsColumnTitle="Sites"
351
- groups={panelGroupsBuilder(tableState.rows)}
352
- rows={tableState.rows}
353
- getRowId={(row) => row.id}
142
+ groups={panelGroups(state.rows)}
143
+ rows={state.rows}
144
+ getRowId={row => row.id}
354
145
  getRowGroupId={() => "all"}
355
146
  autoSaveId="sites-panel-view"
356
- renderListRow={panelRenderListRow}
357
- renderDetail={panelRenderDetail}
147
+ renderListRow={(row) => (
148
+ <div className="flex-1 min-w-0 flex items-center gap-2">
149
+ <Avatar size="sm" className="size-6 shrink-0">
150
+ <AvatarFallback className="bg-brand/10 p-0 text-brand text-xs">
151
+ <i className="fa-light fa-hospital text-xs" aria-hidden="true" />
152
+ </AvatarFallback>
153
+ </Avatar>
154
+ <div className="flex-1 min-w-0">
155
+ <p className="text-sm font-medium text-foreground truncate">{row.name}</p>
156
+ <p className="text-xs text-muted-foreground truncate">{row.url}</p>
157
+ </div>
158
+ </div>
159
+ )}
160
+ renderDetail={(row) => (
161
+ <div className="flex min-h-0 flex-1 flex-col overflow-y-auto p-4">
162
+ <div>
163
+ <h3 className="text-sm font-semibold text-foreground mb-2">Site</h3>
164
+ <p className="text-sm text-foreground">{row.name}</p>
165
+ </div>
166
+ <div className="flex flex-col gap-2">
167
+ <div>
168
+ <span className="text-xs font-medium text-muted-foreground">Key</span>
169
+ <p className="text-sm text-foreground font-mono">{row.id}</p>
170
+ </div>
171
+ <div>
172
+ <span className="text-xs font-medium text-muted-foreground">Path</span>
173
+ <p className="text-sm text-foreground break-all">{row.url}</p>
174
+ </div>
175
+ </div>
176
+ </div>
177
+ )}
358
178
  emptyList={<p className="text-sm text-muted-foreground">No sites found.</p>}
359
179
  />
360
- </ListPageSplitHubChrome>
361
- </div>
362
- )
180
+ </ListPageSplitHubChrome>,
181
+ ),
182
+ "dashboard-with-toolbar": ({ state, toolbar }) => {
183
+ const metrics = sitesKpiMetrics(state.rows.length)
184
+ return (
185
+ <div className="flex min-h-0 flex-1 flex-col gap-4">
186
+ {toolbar}
187
+ <div className="px-4 pb-2 lg:px-6">
188
+ <KeyMetrics
189
+ variant="flat"
190
+ metrics={metrics}
191
+ insight={SITES_KPI_INSIGHT}
192
+ showHeader={false}
193
+ metricsSingleRow
194
+ />
195
+ </div>
196
+ <SitesCardGrid rows={state.rows} />
197
+ </div>
198
+ )
199
+ },
363
200
  }
364
201
 
365
202
  return (
366
- <div className="flex min-h-0 flex-1 flex-col gap-4">
367
- {sharedToolbar}
368
- <div className="px-4 pb-2 lg:px-6">
369
- <KeyMetrics
370
- variant="flat"
371
- metrics={dashMetrics}
372
- insight={SITES_KPI_INSIGHT}
373
- showHeader={false}
374
- metricsSingleRow
375
- />
376
- </div>
377
- <SitesCardGrid rows={tableState.rows} />
378
- </div>
203
+ <HubTable<SiteDirectoryRow>
204
+ rows={sites}
205
+ columns={columns}
206
+ view={view}
207
+ onViewChange={onViewChange}
208
+ supportedViewTypes={SITES_SUPPORTED_VIEWS}
209
+ hubLabel="Sites"
210
+ lifecycleTabLabel="Sites"
211
+ searchAriaLabel="Search sites"
212
+ getRowId={row => row.id}
213
+ getRowSelectionLabel={row => row.name}
214
+ defaultSort={{ key: "name", dir: "asc" }}
215
+ emptyState={<p className="text-sm text-muted-foreground">No sites match your filters.</p>}
216
+ listAriaLabel="Sites"
217
+ listEmptyState="No sites match your search."
218
+ renderListRow={site => (
219
+ <Link
220
+ href={site.url}
221
+ className="block rounded-xl text-inherit no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
222
+ >
223
+ <ListPageBoardCard
224
+ layout="row"
225
+ interactive
226
+ rowContainerClassName="flex flex-row items-center gap-3"
227
+ leading={
228
+ <span className="inline-flex size-9 shrink-0 items-center justify-center rounded-md bg-brand/10 text-brand">
229
+ <i className="fa-light fa-hospital text-sm" aria-hidden="true" />
230
+ </span>
231
+ }
232
+ rowEnd={
233
+ <i className="fa-light fa-chevron-right text-xs text-muted-foreground" aria-hidden="true" />
234
+ }
235
+ >
236
+ <div className="space-y-0.5">
237
+ <p className="truncate text-sm font-semibold text-foreground">{site.name}</p>
238
+ <p className="truncate text-xs text-muted-foreground">{site.id}</p>
239
+ </div>
240
+ </ListPageBoardCard>
241
+ </Link>
242
+ )}
243
+ renderers={renderers}
244
+ handleRef={ref}
245
+ />
379
246
  )
380
247
  })
381
248