@exxatdesignux/ui 0.2.19 → 0.4.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 (716) hide show
  1. package/CHANGELOG.md +662 -7
  2. package/bin/sync-extras.mjs +116 -29
  3. package/consumer-extras/README.md +42 -7
  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 +43 -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-library-hub-header.mdc +28 -0
  22. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
  23. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
  24. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
  25. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
  26. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
  27. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
  28. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
  29. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -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 +3 -3
  35. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +5 -16
  36. package/consumer-extras/cursor-skills/exxat-collaboration-access/SKILL.md +3 -3
  37. package/consumer-extras/cursor-skills/exxat-dedicated-search-surfaces/SKILL.md +2 -2
  38. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +19 -34
  39. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
  40. package/consumer-extras/cursor-skills/exxat-kpi-flat-band/SKILL.md +1 -1
  41. package/consumer-extras/cursor-skills/exxat-list-page-view-shells/SKILL.md +1 -1
  42. package/consumer-extras/cursor-skills/exxat-mono-ids/SKILL.md +4 -4
  43. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +10 -12
  44. package/consumer-extras/cursor-skills/exxat-token-economy/SKILL.md +277 -0
  45. package/consumer-extras/handbook/HANDBOOK.md +187 -0
  46. package/consumer-extras/handbook/glossary.md +58 -0
  47. package/consumer-extras/handbook/reference-implementations.md +153 -0
  48. package/consumer-extras/handbook/voice-and-tone.md +262 -0
  49. package/consumer-extras/patterns/collaboration-access-pattern.md +7 -7
  50. package/consumer-extras/patterns/command-menu-pattern.md +1 -1
  51. package/consumer-extras/patterns/consumer-upgrade-checklist.md +0 -20
  52. package/consumer-extras/patterns/data-views-pattern.md +31 -66
  53. package/consumer-extras/patterns/kpi-flat-band-pattern.md +2 -2
  54. package/consumer-extras/patterns/shell-surface-elevation-pattern.md +3 -5
  55. package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
  56. package/dist/components/data-table/filter-date-calendar.js +280 -0
  57. package/dist/components/data-table/filter-date-calendar.js.map +1 -0
  58. package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
  59. package/dist/components/data-table/filter-text-value-input.js +561 -0
  60. package/dist/components/data-table/filter-text-value-input.js.map +1 -0
  61. package/dist/components/data-table/index.d.ts +45 -0
  62. package/dist/components/data-table/index.js +3085 -0
  63. package/dist/components/data-table/index.js.map +1 -0
  64. package/dist/components/data-table/pagination.d.ts +28 -0
  65. package/dist/components/data-table/pagination.js +3264 -0
  66. package/dist/components/data-table/pagination.js.map +1 -0
  67. package/dist/components/data-table/types.d.ts +84 -0
  68. package/dist/components/data-table/types.js +3 -0
  69. package/dist/components/data-table/types.js.map +1 -0
  70. package/dist/components/data-table/use-table-state.d.ts +116 -0
  71. package/dist/components/data-table/use-table-state.js +670 -0
  72. package/dist/components/data-table/use-table-state.js.map +1 -0
  73. package/dist/components/data-views/board-card-primitives.d.ts +22 -0
  74. package/dist/components/data-views/board-card-primitives.js +84 -0
  75. package/dist/components/data-views/board-card-primitives.js.map +1 -0
  76. package/dist/components/data-views/data-row-list.d.ts +33 -0
  77. package/dist/components/data-views/data-row-list.js +106 -0
  78. package/dist/components/data-views/data-row-list.js.map +1 -0
  79. package/dist/components/data-views/finder-panel-view.d.ts +54 -0
  80. package/dist/components/data-views/finder-panel-view.js +388 -0
  81. package/dist/components/data-views/finder-panel-view.js.map +1 -0
  82. package/dist/components/data-views/folder-grid-view.d.ts +22 -0
  83. package/dist/components/data-views/folder-grid-view.js +58 -0
  84. package/dist/components/data-views/folder-grid-view.js.map +1 -0
  85. package/dist/components/data-views/hub-table.d.ts +173 -0
  86. package/dist/components/data-views/hub-table.js +5783 -0
  87. package/dist/components/data-views/hub-table.js.map +1 -0
  88. package/dist/components/data-views/index.d.ts +27 -0
  89. package/dist/components/data-views/index.js +6797 -0
  90. package/dist/components/data-views/index.js.map +1 -0
  91. package/dist/components/data-views/list-page-board-card.d.ts +72 -0
  92. package/dist/components/data-views/list-page-board-card.js +264 -0
  93. package/dist/components/data-views/list-page-board-card.js.map +1 -0
  94. package/dist/components/data-views/list-page-board-template.d.ts +24 -0
  95. package/dist/components/data-views/list-page-board-template.js +137 -0
  96. package/dist/components/data-views/list-page-board-template.js.map +1 -0
  97. package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
  98. package/dist/components/data-views/list-page-connected-view-body.js +116 -0
  99. package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
  100. package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
  101. package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
  102. package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
  103. package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
  104. package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
  105. package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
  106. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
  107. package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
  108. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
  109. package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
  110. package/dist/components/data-views/list-page-tree-column-header.js +22 -0
  111. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
  112. package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
  113. package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
  114. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
  115. package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
  116. package/dist/components/data-views/os-folder-glyph.js +104 -0
  117. package/dist/components/data-views/os-folder-glyph.js.map +1 -0
  118. package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
  119. package/dist/components/data-views/outline-tree-menu.js +131 -0
  120. package/dist/components/data-views/outline-tree-menu.js.map +1 -0
  121. package/dist/components/table-properties/column-row.d.ts +22 -0
  122. package/dist/components/table-properties/column-row.js +153 -0
  123. package/dist/components/table-properties/column-row.js.map +1 -0
  124. package/dist/components/table-properties/draggable-list.d.ts +24 -0
  125. package/dist/components/table-properties/draggable-list.js +53 -0
  126. package/dist/components/table-properties/draggable-list.js.map +1 -0
  127. package/dist/components/table-properties/drawer-button.d.ts +110 -0
  128. package/dist/components/table-properties/drawer-button.js +2748 -0
  129. package/dist/components/table-properties/drawer-button.js.map +1 -0
  130. package/dist/components/table-properties/drawer.d.ts +100 -0
  131. package/dist/components/table-properties/drawer.js +2595 -0
  132. package/dist/components/table-properties/drawer.js.map +1 -0
  133. package/dist/components/table-properties/filter-card.d.ts +24 -0
  134. package/dist/components/table-properties/filter-card.js +854 -0
  135. package/dist/components/table-properties/filter-card.js.map +1 -0
  136. package/dist/components/table-properties/index.d.ts +14 -0
  137. package/dist/components/table-properties/index.js +2768 -0
  138. package/dist/components/table-properties/index.js.map +1 -0
  139. package/dist/components/table-properties/sort-card.d.ts +20 -0
  140. package/dist/components/table-properties/sort-card.js +102 -0
  141. package/dist/components/table-properties/sort-card.js.map +1 -0
  142. package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
  143. package/dist/components/templates/dedicated-search-landing-template.js +254 -0
  144. package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
  145. package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
  146. package/dist/components/templates/dedicated-search-results-template.js +16 -0
  147. package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
  148. package/dist/components/templates/index.d.ts +9 -0
  149. package/dist/components/templates/index.js +2720 -0
  150. package/dist/components/templates/index.js.map +1 -0
  151. package/dist/components/templates/list-page.d.ts +83 -0
  152. package/dist/components/templates/list-page.js +2433 -0
  153. package/dist/components/templates/list-page.js.map +1 -0
  154. package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
  155. package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
  156. package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
  157. package/dist/components/ui/accordion.d.ts +10 -0
  158. package/dist/components/ui/accordion.js +74 -0
  159. package/dist/components/ui/accordion.js.map +1 -0
  160. package/dist/components/ui/alert-dialog.d.ts +37 -0
  161. package/dist/components/ui/alert-dialog.js +201 -0
  162. package/dist/components/ui/alert-dialog.js.map +1 -0
  163. package/dist/components/ui/avatar.d.ts +84 -0
  164. package/dist/components/ui/avatar.js +328 -0
  165. package/dist/components/ui/avatar.js.map +1 -0
  166. package/dist/components/ui/badge.d.ts +13 -0
  167. package/dist/components/ui/badge.js +49 -0
  168. package/dist/components/ui/badge.js.map +1 -0
  169. package/dist/components/ui/banner.d.ts +62 -0
  170. package/dist/components/ui/banner.js +364 -0
  171. package/dist/components/ui/banner.js.map +1 -0
  172. package/dist/components/ui/breadcrumb.d.ts +14 -0
  173. package/dist/components/ui/breadcrumb.js +114 -0
  174. package/dist/components/ui/breadcrumb.js.map +1 -0
  175. package/dist/components/ui/button.d.ts +16 -0
  176. package/dist/components/ui/button.js +59 -0
  177. package/dist/components/ui/button.js.map +1 -0
  178. package/dist/components/ui/calendar.d.ts +13 -0
  179. package/dist/components/ui/calendar.js +238 -0
  180. package/dist/components/ui/calendar.js.map +1 -0
  181. package/dist/components/ui/card.d.ts +14 -0
  182. package/dist/components/ui/card.js +102 -0
  183. package/dist/components/ui/card.js.map +1 -0
  184. package/dist/components/ui/chart.d.ts +58 -0
  185. package/dist/components/ui/chart.js +292 -0
  186. package/dist/components/ui/chart.js.map +1 -0
  187. package/dist/components/ui/checkbox.d.ts +23 -0
  188. package/dist/components/ui/checkbox.js +155 -0
  189. package/dist/components/ui/checkbox.js.map +1 -0
  190. package/dist/components/ui/coach-mark.d.ts +27 -0
  191. package/dist/components/ui/coach-mark.js +306 -0
  192. package/dist/components/ui/coach-mark.js.map +1 -0
  193. package/dist/components/ui/collapsible.d.ts +8 -0
  194. package/dist/components/ui/collapsible.js +35 -0
  195. package/dist/components/ui/collapsible.js.map +1 -0
  196. package/dist/components/ui/command.d.ts +36 -0
  197. package/dist/components/ui/command.js +274 -0
  198. package/dist/components/ui/command.js.map +1 -0
  199. package/dist/components/ui/context-menu.d.ts +32 -0
  200. package/dist/components/ui/context-menu.js +245 -0
  201. package/dist/components/ui/context-menu.js.map +1 -0
  202. package/dist/components/ui/date-picker-field.d.ts +38 -0
  203. package/dist/components/ui/date-picker-field.js +550 -0
  204. package/dist/components/ui/date-picker-field.js.map +1 -0
  205. package/dist/components/ui/dialog.d.ts +22 -0
  206. package/dist/components/ui/dialog.js +200 -0
  207. package/dist/components/ui/dialog.js.map +1 -0
  208. package/dist/components/ui/dot-pattern.d.ts +21 -0
  209. package/dist/components/ui/dot-pattern.js +139 -0
  210. package/dist/components/ui/dot-pattern.js.map +1 -0
  211. package/dist/components/ui/drag-handle-grip.d.ts +10 -0
  212. package/dist/components/ui/drag-handle-grip.js +15 -0
  213. package/dist/components/ui/drag-handle-grip.js.map +1 -0
  214. package/dist/components/ui/drawer.d.ts +16 -0
  215. package/dist/components/ui/drawer.js +125 -0
  216. package/dist/components/ui/drawer.js.map +1 -0
  217. package/dist/components/ui/dropdown-menu.d.ts +45 -0
  218. package/dist/components/ui/dropdown-menu.js +353 -0
  219. package/dist/components/ui/dropdown-menu.js.map +1 -0
  220. package/dist/components/ui/export-drawer.d.ts +11 -0
  221. package/dist/components/ui/export-drawer.js +1658 -0
  222. package/dist/components/ui/export-drawer.js.map +1 -0
  223. package/dist/components/ui/field.d.ts +30 -0
  224. package/dist/components/ui/field.js +249 -0
  225. package/dist/components/ui/field.js.map +1 -0
  226. package/dist/components/ui/form.d.ts +28 -0
  227. package/dist/components/ui/form.js +110 -0
  228. package/dist/components/ui/form.js.map +1 -0
  229. package/dist/components/ui/hover-card.d.ts +9 -0
  230. package/dist/components/ui/hover-card.js +43 -0
  231. package/dist/components/ui/hover-card.js.map +1 -0
  232. package/dist/components/ui/input-group.d.ts +20 -0
  233. package/dist/components/ui/input-group.js +219 -0
  234. package/dist/components/ui/input-group.js.map +1 -0
  235. package/dist/components/ui/input-mask.d.ts +39 -0
  236. package/dist/components/ui/input-mask.js +118 -0
  237. package/dist/components/ui/input-mask.js.map +1 -0
  238. package/dist/components/ui/input.d.ts +5 -0
  239. package/dist/components/ui/input.js +30 -0
  240. package/dist/components/ui/input.js.map +1 -0
  241. package/dist/components/ui/kbd.d.ts +20 -0
  242. package/dist/components/ui/kbd.js +45 -0
  243. package/dist/components/ui/kbd.js.map +1 -0
  244. package/dist/components/ui/key-metrics-context.d.ts +19 -0
  245. package/dist/components/ui/key-metrics-context.js +26 -0
  246. package/dist/components/ui/key-metrics-context.js.map +1 -0
  247. package/dist/components/ui/key-metrics.d.ts +131 -0
  248. package/dist/components/ui/key-metrics.js +1015 -0
  249. package/dist/components/ui/key-metrics.js.map +1 -0
  250. package/dist/components/ui/label.d.ts +6 -0
  251. package/dist/components/ui/label.js +28 -0
  252. package/dist/components/ui/label.js.map +1 -0
  253. package/dist/components/ui/list-page-view-frame.d.ts +22 -0
  254. package/dist/components/ui/list-page-view-frame.js +24 -0
  255. package/dist/components/ui/list-page-view-frame.js.map +1 -0
  256. package/dist/components/ui/page-header.d.ts +51 -0
  257. package/dist/components/ui/page-header.js +372 -0
  258. package/dist/components/ui/page-header.js.map +1 -0
  259. package/dist/components/ui/payment-card-fields.d.ts +10 -0
  260. package/dist/components/ui/payment-card-fields.js +80 -0
  261. package/dist/components/ui/payment-card-fields.js.map +1 -0
  262. package/dist/components/ui/popover.d.ts +10 -0
  263. package/dist/components/ui/popover.js +47 -0
  264. package/dist/components/ui/popover.js.map +1 -0
  265. package/dist/components/ui/radio-group.d.ts +29 -0
  266. package/dist/components/ui/radio-group.js +190 -0
  267. package/dist/components/ui/radio-group.js.map +1 -0
  268. package/dist/components/ui/resizable.d.ts +16 -0
  269. package/dist/components/ui/resizable.js +51 -0
  270. package/dist/components/ui/resizable.js.map +1 -0
  271. package/dist/components/ui/scroll-area.d.ts +8 -0
  272. package/dist/components/ui/scroll-area.js +66 -0
  273. package/dist/components/ui/scroll-area.js.map +1 -0
  274. package/dist/components/ui/select.d.ts +18 -0
  275. package/dist/components/ui/select.js +186 -0
  276. package/dist/components/ui/select.js.map +1 -0
  277. package/dist/components/ui/selection-tile-grid.d.ts +52 -0
  278. package/dist/components/ui/selection-tile-grid.js +347 -0
  279. package/dist/components/ui/selection-tile-grid.js.map +1 -0
  280. package/dist/components/ui/separator.d.ts +7 -0
  281. package/dist/components/ui/separator.js +33 -0
  282. package/dist/components/ui/separator.js.map +1 -0
  283. package/dist/components/ui/sheet.d.ts +18 -0
  284. package/dist/components/ui/sheet.js +181 -0
  285. package/dist/components/ui/sheet.js.map +1 -0
  286. package/dist/components/ui/sidebar.d.ts +94 -0
  287. package/dist/components/ui/sidebar.js +805 -0
  288. package/dist/components/ui/sidebar.js.map +1 -0
  289. package/dist/components/ui/skeleton.d.ts +5 -0
  290. package/dist/components/ui/skeleton.js +22 -0
  291. package/dist/components/ui/skeleton.js.map +1 -0
  292. package/dist/components/ui/slider.d.ts +7 -0
  293. package/dist/components/ui/slider.js +66 -0
  294. package/dist/components/ui/slider.js.map +1 -0
  295. package/dist/components/ui/sonner.d.ts +6 -0
  296. package/dist/components/ui/sonner.js +38 -0
  297. package/dist/components/ui/sonner.js.map +1 -0
  298. package/dist/components/ui/status-badge.d.ts +38 -0
  299. package/dist/components/ui/status-badge.js +77 -0
  300. package/dist/components/ui/status-badge.js.map +1 -0
  301. package/dist/components/ui/table.d.ts +13 -0
  302. package/dist/components/ui/table.js +115 -0
  303. package/dist/components/ui/table.js.map +1 -0
  304. package/dist/components/ui/tabs.d.ts +15 -0
  305. package/dist/components/ui/tabs.js +93 -0
  306. package/dist/components/ui/tabs.js.map +1 -0
  307. package/dist/components/ui/textarea.d.ts +6 -0
  308. package/dist/components/ui/textarea.js +25 -0
  309. package/dist/components/ui/textarea.js.map +1 -0
  310. package/dist/components/ui/tip.d.ts +12 -0
  311. package/dist/components/ui/tip.js +61 -0
  312. package/dist/components/ui/tip.js.map +1 -0
  313. package/dist/components/ui/toggle-group.d.ts +14 -0
  314. package/dist/components/ui/toggle-group.js +104 -0
  315. package/dist/components/ui/toggle-group.js.map +1 -0
  316. package/dist/components/ui/toggle-switch.d.ts +10 -0
  317. package/dist/components/ui/toggle-switch.js +33 -0
  318. package/dist/components/ui/toggle-switch.js.map +1 -0
  319. package/dist/components/ui/toggle.d.ts +13 -0
  320. package/dist/components/ui/toggle.js +51 -0
  321. package/dist/components/ui/toggle.js.map +1 -0
  322. package/dist/components/ui/tooltip.d.ts +10 -0
  323. package/dist/components/ui/tooltip.js +68 -0
  324. package/dist/components/ui/tooltip.js.map +1 -0
  325. package/dist/components/ui/view-segmented-control.d.ts +31 -0
  326. package/dist/components/ui/view-segmented-control.js +167 -0
  327. package/dist/components/ui/view-segmented-control.js.map +1 -0
  328. package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
  329. package/dist/hooks/use-app-theme.d.ts +24 -0
  330. package/dist/hooks/use-app-theme.js +286 -0
  331. package/dist/hooks/use-app-theme.js.map +1 -0
  332. package/dist/hooks/use-coach-mark.d.ts +86 -0
  333. package/dist/hooks/use-coach-mark.js +218 -0
  334. package/dist/hooks/use-coach-mark.js.map +1 -0
  335. package/dist/hooks/use-mobile.d.ts +3 -0
  336. package/dist/hooks/use-mobile.js +29 -0
  337. package/dist/hooks/use-mobile.js.map +1 -0
  338. package/dist/hooks/use-mod-key-label.d.ts +6 -0
  339. package/dist/hooks/use-mod-key-label.js +25 -0
  340. package/dist/hooks/use-mod-key-label.js.map +1 -0
  341. package/dist/index.d.ts +120 -0
  342. package/dist/index.js +13421 -0
  343. package/dist/index.js.map +1 -0
  344. package/dist/lib/compose-refs.d.ts +6 -0
  345. package/dist/lib/compose-refs.js +17 -0
  346. package/dist/lib/compose-refs.js.map +1 -0
  347. package/dist/lib/conditional-rule-match.d.ts +30 -0
  348. package/dist/lib/conditional-rule-match.js +66 -0
  349. package/dist/lib/conditional-rule-match.js.map +1 -0
  350. package/dist/lib/data-list-display-options.d.ts +26 -0
  351. package/dist/lib/data-list-display-options.js +14 -0
  352. package/dist/lib/data-list-display-options.js.map +1 -0
  353. package/dist/lib/data-list-view-registry.d.ts +2 -0
  354. package/dist/lib/data-list-view-registry.js +102 -0
  355. package/dist/lib/data-list-view-registry.js.map +1 -0
  356. package/dist/lib/data-list-view-surface.d.ts +2 -0
  357. package/dist/lib/data-list-view-surface.js +80 -0
  358. package/dist/lib/data-list-view-surface.js.map +1 -0
  359. package/dist/lib/data-list-view.d.ts +21 -0
  360. package/dist/lib/data-list-view.js +25 -0
  361. package/dist/lib/data-list-view.js.map +1 -0
  362. package/dist/lib/date-filter.d.ts +22 -0
  363. package/dist/lib/date-filter.js +61 -0
  364. package/dist/lib/date-filter.js.map +1 -0
  365. package/dist/lib/dev-log.d.ts +8 -0
  366. package/dist/lib/dev-log.js +10 -0
  367. package/dist/lib/dev-log.js.map +1 -0
  368. package/dist/lib/dropdown-menu-surface.d.ts +14 -0
  369. package/dist/lib/dropdown-menu-surface.js +6 -0
  370. package/dist/lib/dropdown-menu-surface.js.map +1 -0
  371. package/dist/lib/editable-target.d.ts +12 -0
  372. package/dist/lib/editable-target.js +12 -0
  373. package/dist/lib/editable-target.js.map +1 -0
  374. package/dist/lib/list-page-table-properties.d.ts +35 -0
  375. package/dist/lib/list-page-table-properties.js +81 -0
  376. package/dist/lib/list-page-table-properties.js.map +1 -0
  377. package/dist/lib/raf-throttle.d.ts +23 -0
  378. package/dist/lib/raf-throttle.js +27 -0
  379. package/dist/lib/raf-throttle.js.map +1 -0
  380. package/dist/lib/row-height.d.ts +16 -0
  381. package/dist/lib/row-height.js +10 -0
  382. package/dist/lib/row-height.js.map +1 -0
  383. package/dist/lib/table-properties-types.d.ts +83 -0
  384. package/dist/lib/table-properties-types.js +19 -0
  385. package/dist/lib/table-properties-types.js.map +1 -0
  386. package/dist/lib/utils.d.ts +5 -0
  387. package/dist/lib/utils.js +11 -0
  388. package/dist/lib/utils.js.map +1 -0
  389. package/package.json +83 -19
  390. package/src/components/data-table/filter-date-calendar.tsx +38 -0
  391. package/src/components/data-table/filter-text-value-input.tsx +77 -0
  392. package/src/components/data-table/index.tsx +1678 -0
  393. package/src/components/data-table/pagination.tsx +259 -0
  394. package/src/components/data-table/types.ts +96 -0
  395. package/src/components/data-table/use-table-state.ts +767 -0
  396. package/src/components/data-views/board-card-primitives.tsx +93 -0
  397. package/src/components/data-views/data-row-list.tsx +183 -0
  398. package/src/components/data-views/finder-panel-view.tsx +405 -0
  399. package/src/components/data-views/folder-grid-view.tsx +86 -0
  400. package/src/components/data-views/hub-table.tsx +606 -0
  401. package/src/components/data-views/index.ts +28 -0
  402. package/src/components/data-views/list-page-board-card.tsx +192 -0
  403. package/src/components/data-views/list-page-board-template.tsx +122 -0
  404. package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
  405. package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
  406. package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
  407. package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
  408. package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
  409. package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
  410. package/src/components/data-views/os-folder-glyph.tsx +141 -0
  411. package/src/components/data-views/outline-tree-menu.tsx +157 -0
  412. package/src/components/table-properties/column-row.tsx +90 -0
  413. package/src/components/table-properties/draggable-list.ts +54 -0
  414. package/src/components/table-properties/drawer-button.tsx +300 -0
  415. package/src/components/table-properties/drawer.tsx +1148 -0
  416. package/src/components/table-properties/filter-card.tsx +251 -0
  417. package/src/components/table-properties/index.ts +36 -0
  418. package/src/components/table-properties/sort-card.tsx +63 -0
  419. package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
  420. package/src/components/templates/dedicated-search-results-template.tsx +19 -0
  421. package/src/components/templates/index.ts +33 -0
  422. package/src/components/templates/list-page.tsx +602 -0
  423. package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
  424. package/src/components/ui/accordion.tsx +92 -0
  425. package/src/components/ui/alert-dialog.tsx +221 -0
  426. package/src/components/ui/avatar.tsx +13 -2
  427. package/src/components/ui/banner.tsx +2 -2
  428. package/src/components/ui/button.tsx +4 -4
  429. package/src/components/ui/calendar.tsx +1 -1
  430. package/src/components/ui/coach-mark.tsx +1 -1
  431. package/src/components/ui/context-menu.tsx +291 -0
  432. package/src/components/ui/date-picker-field.tsx +2 -2
  433. package/src/components/ui/dot-pattern.tsx +183 -0
  434. package/src/components/ui/export-drawer.tsx +375 -0
  435. package/src/components/ui/hover-card.tsx +66 -0
  436. package/src/components/ui/key-metrics-context.tsx +78 -0
  437. package/src/components/ui/key-metrics.tsx +1133 -0
  438. package/src/components/ui/list-page-view-frame.tsx +64 -0
  439. package/src/components/ui/page-header.tsx +244 -0
  440. package/src/components/ui/payment-card-fields.tsx +2 -2
  441. package/src/components/ui/resizable.tsx +68 -0
  442. package/src/components/ui/scroll-area.tsx +72 -0
  443. package/src/components/ui/selection-tile-grid.tsx +9 -2
  444. package/src/components/ui/sidebar.tsx +84 -12
  445. package/src/components/ui/slider.tsx +83 -0
  446. package/src/globals.css +2201 -7
  447. package/src/globals.d.ts +20 -0
  448. package/src/index.ts +68 -1
  449. package/src/lib/conditional-rule-match.ts +119 -0
  450. package/src/lib/data-list-display-options.ts +35 -0
  451. package/src/lib/data-list-view-registry.ts +104 -0
  452. package/src/lib/data-list-view-surface.ts +83 -0
  453. package/src/lib/data-list-view.ts +47 -0
  454. package/src/lib/dev-log.ts +10 -0
  455. package/src/lib/editable-target.ts +20 -0
  456. package/src/lib/list-page-table-properties.ts +48 -0
  457. package/src/lib/raf-throttle.ts +45 -0
  458. package/src/lib/row-height.ts +19 -0
  459. package/src/lib/table-properties-types.ts +98 -0
  460. package/template/.claude/skills/exxat-ds-skill/SKILL.md +8 -7
  461. package/template/.cursor/rules/exxat-accessibility.mdc +1 -1
  462. package/template/.cursor/rules/exxat-command-menu.mdc +2 -2
  463. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +7 -7
  464. package/template/.cursor/rules/exxat-data-tables.mdc +3 -3
  465. package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
  466. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +7 -7
  467. package/template/.cursor/rules/exxat-mono-ids.mdc +1 -1
  468. package/template/.cursor/rules/exxat-page-vs-drawer.mdc +1 -1
  469. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  470. package/template/AGENTS.md +135 -103
  471. package/template/app/(app)/columns/page.tsx +11 -0
  472. package/template/app/(app)/dashboard/loading.tsx +15 -3
  473. package/template/app/(app)/dashboard/page.tsx +14 -2
  474. package/template/app/(app)/layout.tsx +17 -4
  475. package/template/app/(app)/library/all/page.tsx +11 -0
  476. package/template/app/(app)/library/find/page.tsx +12 -0
  477. package/template/app/(app)/{question-bank → library}/layout.tsx +17 -17
  478. package/template/app/(app)/library/list/page.tsx +12 -0
  479. package/template/app/(app)/library/new/page.tsx +45 -0
  480. package/template/app/(app)/library/page.tsx +11 -0
  481. package/template/app/(app)/loading.tsx +18 -1
  482. package/template/app/(app)/settings/page.tsx +5 -4
  483. package/template/app/(app)/tokens-themes/page.tsx +11 -0
  484. package/template/app/globals.css +14 -16
  485. package/template/components/ask-leo-composer.tsx +2 -2
  486. package/template/components/ask-leo-sidebar.tsx +5 -1
  487. package/template/components/brand-color-picker.tsx +2 -2
  488. package/template/components/charts-overview.tsx +1 -1
  489. package/template/components/columns-client.tsx +158 -0
  490. package/template/components/columns-showcase.tsx +541 -0
  491. package/template/components/dashboard-report-charts.tsx +1 -1
  492. package/template/components/dashboard-tabs.tsx +1 -1
  493. package/template/components/data-table/filter-date-calendar.tsx +1 -38
  494. package/template/components/data-table/filter-text-value-input.tsx +1 -77
  495. package/template/components/data-table/index.tsx +1 -1634
  496. package/template/components/data-table/pagination.tsx +1 -255
  497. package/template/components/data-table/types.ts +1 -94
  498. package/template/components/data-table/use-table-state.test.ts +420 -0
  499. package/template/components/data-table/use-table-state.ts +1 -758
  500. package/template/components/data-views/board-card-primitives.tsx +1 -93
  501. package/template/components/data-views/data-row-list.tsx +1 -183
  502. package/template/components/data-views/finder-panel-view.tsx +1 -405
  503. package/template/components/data-views/folder-grid-view.tsx +1 -86
  504. package/template/components/data-views/hub-table.tsx +1 -0
  505. package/template/components/data-views/index.ts +77 -38
  506. package/template/components/data-views/{question-bank-folder-tree-branch.tsx → library-folder-tree-branch.tsx} +19 -19
  507. package/template/components/data-views/list-page-board-card.tsx +1 -192
  508. package/template/components/data-views/list-page-board-template.tsx +1 -122
  509. package/template/components/data-views/list-page-connected-view-body.tsx +1 -66
  510. package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
  511. package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -68
  512. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
  513. package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
  514. package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
  515. package/template/components/data-views/list-page-view-frame.tsx +5 -53
  516. package/template/components/data-views/os-folder-glyph.tsx +1 -129
  517. package/template/components/data-views/outline-tree-menu.tsx +1 -157
  518. package/template/components/data-views/table-cells.tsx +673 -0
  519. package/template/components/export-drawer.test.tsx +71 -0
  520. package/template/components/export-drawer.tsx +1 -375
  521. package/template/components/exxat-product-logo.tsx +5 -5
  522. package/template/components/folder-details-shell.tsx +11 -11
  523. package/template/components/hub-tree-panel-view.tsx +26 -26
  524. package/template/components/invite-collaborators-drawer.tsx +3 -3
  525. package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
  526. package/template/components/key-metrics.tsx +1 -1063
  527. package/template/components/leo-insight-indicator.tsx +2 -2
  528. package/template/components/{question-bank-board-view.tsx → library-board-view.tsx} +44 -44
  529. package/template/components/{question-bank-client.tsx → library-client.tsx} +83 -83
  530. package/template/components/{question-bank-dashboard-charts.tsx → library-dashboard-charts.tsx} +14 -14
  531. package/template/components/{question-bank-favorite-button.tsx → library-favorite-button.tsx} +7 -7
  532. package/template/components/{question-bank-hub-client.tsx → library-hub-client.tsx} +44 -44
  533. package/template/components/{question-bank-new-folder-sheet.tsx → library-new-folder-sheet.tsx} +16 -16
  534. package/template/components/{question-bank-os-folder-view.tsx → library-os-folder-view.tsx} +31 -31
  535. package/template/components/{question-bank-page-header.tsx → library-page-header.tsx} +6 -6
  536. package/template/components/library-panel-activator.tsx +8 -0
  537. package/template/components/{question-bank-secondary-nav.tsx → library-secondary-nav.tsx} +63 -63
  538. package/template/components/library-table.tsx +839 -0
  539. package/template/components/list-hub-status-badge.tsx +2 -2
  540. package/template/components/{new-question-composer.tsx → new-library-item-form.tsx} +489 -441
  541. package/template/components/onboarding/index.ts +9 -0
  542. package/template/components/onboarding/onboarding-01.tsx +1 -1
  543. package/template/components/onboarding/onboarding-02.tsx +1 -1
  544. package/template/components/onboarding/onboarding-03.tsx +1 -1
  545. package/template/components/onboarding/onboarding-04.tsx +1 -1
  546. package/template/components/page-header.tsx +8 -226
  547. package/template/components/product-switcher.tsx +3 -4
  548. package/template/components/product-wordmark.tsx +2 -1
  549. package/template/components/settings-appearance-card.tsx +3 -4
  550. package/template/components/settings-client.tsx +15 -59
  551. package/template/components/settings-form-row.tsx +4 -9
  552. package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
  553. package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +114 -73
  554. package/template/components/sidebar/index.ts +16 -0
  555. package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
  556. package/template/components/sidebar/secondary-panel.tsx +316 -0
  557. package/template/components/sidebar/sidebar-auto-collapse.tsx +27 -0
  558. package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +2 -1
  559. package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
  560. package/template/components/site-header.tsx +1 -1
  561. package/template/components/table-properties/column-row.tsx +1 -90
  562. package/template/components/table-properties/draggable-list.ts +1 -49
  563. package/template/components/table-properties/drawer-button.tsx +1 -262
  564. package/template/components/table-properties/drawer.tsx +1 -1166
  565. package/template/components/table-properties/filter-card.tsx +1 -251
  566. package/template/components/table-properties/sort-card.tsx +1 -59
  567. package/template/components/table-properties/types.ts +28 -71
  568. package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
  569. package/template/components/templates/dedicated-search-results-template.tsx +1 -19
  570. package/template/components/templates/discovery-hub-template.tsx +1 -1
  571. package/template/components/templates/list-page.tsx +1 -608
  572. package/template/components/templates/nested-secondary-panel-shell.tsx +1 -63
  573. package/template/components/templates/new-focus-template.tsx +659 -0
  574. package/template/components/templates/secondary-panel-hub-template.tsx +2 -2
  575. package/template/components/tokens-secondary-nav.tsx +192 -0
  576. package/template/components/tokens-themes-client.tsx +476 -0
  577. package/template/components/tokens-themes-section.tsx +386 -0
  578. package/template/components/ui/accordion.tsx +1 -0
  579. package/template/components/ui/alert-dialog.tsx +1 -0
  580. package/template/components/ui/context-menu.tsx +1 -0
  581. package/template/components/ui/dot-pattern.tsx +1 -183
  582. package/template/components/ui/hover-card.tsx +1 -0
  583. package/template/components/ui/resizable.tsx +1 -68
  584. package/template/components/ui/scroll-area.tsx +1 -0
  585. package/template/components/ui/slider.tsx +1 -0
  586. package/template/docs/HANDBOOK.md +187 -0
  587. package/template/docs/blueprints/README.md +86 -0
  588. package/template/docs/blueprints/_template.md +91 -0
  589. package/template/docs/blueprints/board-card.md +123 -0
  590. package/template/docs/blueprints/data-table.md +139 -0
  591. package/template/docs/blueprints/key-metrics.md +128 -0
  592. package/template/docs/blueprints/list-page-template.md +123 -0
  593. package/template/docs/blueprints/page-header.md +130 -0
  594. package/template/docs/collaboration-access-pattern.md +7 -7
  595. package/template/docs/command-menu-pattern.md +1 -1
  596. package/template/docs/component-selection-guide.md +224 -0
  597. package/template/docs/components-audit-2026-05.md +158 -0
  598. package/template/docs/data-views-pattern.md +31 -66
  599. package/template/docs/drawer-vs-dialog-pattern.md +1 -3
  600. package/template/docs/glossary.md +58 -0
  601. package/template/docs/kpi-flat-band-pattern.md +3 -3
  602. package/template/docs/kpi-trend-pattern.md +18 -3
  603. package/template/docs/large-dataset-strategy.md +155 -0
  604. package/template/docs/library-hub-header-pattern.md +25 -0
  605. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
  606. package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
  607. package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
  608. package/template/docs/migrations/README.md +100 -0
  609. package/template/docs/migrations/_template.md +64 -0
  610. package/template/docs/reference-implementations.md +151 -0
  611. package/template/docs/shell-surface-elevation-pattern.md +3 -5
  612. package/template/docs/token-taxonomy.md +416 -0
  613. package/template/docs/voice-and-tone.md +262 -0
  614. package/template/eslint.config.mjs +27 -0
  615. package/template/hooks/use-secondary-panel-hub-nav.ts +11 -11
  616. package/template/lib/ask-leo-route-context.ts +6 -18
  617. package/template/lib/coach-mark-registry.ts +0 -16
  618. package/template/lib/command-menu-config.ts +5 -13
  619. package/template/lib/command-menu-search-data.ts +8 -23
  620. package/template/lib/conditional-rule-match.ts +6 -97
  621. package/template/lib/data-list-display-options.ts +1 -49
  622. package/template/lib/data-list-view-registry.ts +1 -104
  623. package/template/lib/data-list-view-surface.ts +1 -83
  624. package/template/lib/data-list-view.ts +1 -47
  625. package/template/lib/data-view-dashboard-storage.ts +35 -38
  626. package/template/lib/dev-log.ts +1 -8
  627. package/template/lib/editable-target.ts +1 -10
  628. package/template/lib/{question-bank-authoring.ts → library-authoring.ts} +89 -88
  629. package/template/lib/library-dedicated-search.ts +19 -0
  630. package/template/lib/library-hub-search.ts +90 -0
  631. package/template/lib/library-nav.ts +477 -0
  632. package/template/lib/library-recent-searches.ts +22 -0
  633. package/template/lib/{question-bank-supported-views.ts → library-supported-views.ts} +2 -3
  634. package/template/lib/list-page-table-properties.ts +1 -48
  635. package/template/lib/list-status-badges.ts +16 -11
  636. package/template/lib/mock/dashboard.ts +1 -1
  637. package/template/lib/mock/{question-bank-folders.ts → library-folders.ts} +30 -30
  638. package/template/lib/mock/library-header-collaborators.ts +54 -0
  639. package/template/lib/mock/{question-bank-inspector.ts → library-inspector.ts} +29 -29
  640. package/template/lib/mock/{question-bank-kpi.ts → library-kpi.ts} +20 -20
  641. package/template/lib/mock/library.ts +249 -0
  642. package/template/lib/mock/navigation.tsx +32 -35
  643. package/template/lib/raf-throttle.ts +1 -45
  644. package/template/lib/row-height.ts +4 -10
  645. package/template/lib/sidebar-state-cookie.ts +11 -2
  646. package/template/lib/table-state-lifecycle.ts +3 -3
  647. package/template/next.config.mjs +7 -4
  648. package/template/package.json +1 -0
  649. package/template/tests/setup.ts +25 -0
  650. package/consumer-extras/AGENTS.md +0 -76
  651. package/consumer-extras/cursor-skills/exxat-consumer-app/SKILL.md +0 -37
  652. package/consumer-extras/cursor-skills/exxat-focused-workflow-page/SKILL.md +0 -57
  653. package/consumer-extras/patterns/consumer-app-pattern.md +0 -39
  654. package/consumer-extras/patterns/focused-workflow-page-pattern.md +0 -84
  655. package/src/components/ui/button-group.tsx +0 -81
  656. package/src/theme.css +0 -16
  657. package/src/tokens/README.md +0 -15
  658. package/src/tokens/base.css +0 -337
  659. package/src/tokens/high-contrast.css +0 -1195
  660. package/src/tokens/layers.css +0 -224
  661. package/src/tokens/tailwind-bridge.css +0 -118
  662. package/src/tokens/themes.css +0 -201
  663. package/template/app/(app)/data-list/layout.tsx +0 -43
  664. package/template/app/(app)/data-list/page.tsx +0 -10
  665. package/template/app/(app)/examples/focused-workflow/page.tsx +0 -5
  666. package/template/app/(app)/examples/page.tsx +0 -43
  667. package/template/app/(app)/question-bank/find/page.tsx +0 -13
  668. package/template/app/(app)/question-bank/library/page.tsx +0 -12
  669. package/template/app/(app)/question-bank/list/page.tsx +0 -13
  670. package/template/app/(app)/question-bank/new/page.tsx +0 -50
  671. package/template/app/(app)/question-bank/page.tsx +0 -12
  672. package/template/components/app-route-loading.tsx +0 -14
  673. package/template/components/dashboard-onboarding-gallery.tsx +0 -13
  674. package/template/components/dashboard-onboarding.tsx +0 -21
  675. package/template/components/data-views/list-page-calendar-view.tsx +0 -593
  676. package/template/components/data-views/list-page-folder-columns-panel.tsx +0 -345
  677. package/template/components/examples/focused-workflow-showcase.tsx +0 -183
  678. package/template/components/list-hub-board-view.tsx +0 -68
  679. package/template/components/list-hub-client.tsx +0 -186
  680. package/template/components/list-hub-list-view.tsx +0 -36
  681. package/template/components/list-hub-panel-activator.tsx +0 -8
  682. package/template/components/list-hub-secondary-nav.tsx +0 -121
  683. package/template/components/list-hub-table.tsx +0 -336
  684. package/template/components/question-bank-folder-columns-panel.tsx +0 -104
  685. package/template/components/question-bank-list-view.tsx +0 -53
  686. package/template/components/question-bank-panel-activator.tsx +0 -8
  687. package/template/components/question-bank-table.tsx +0 -729
  688. package/template/components/secondary-panel/nav-link-rows.tsx +0 -83
  689. package/template/components/secondary-panel.tsx +0 -220
  690. package/template/components/secondary-panels/list-hub-panel.tsx +0 -39
  691. package/template/components/secondary-panels/question-bank-panel.tsx +0 -39
  692. package/template/components/secondary-panels/registry.tsx +0 -15
  693. package/template/components/section-cards.tsx +0 -106
  694. package/template/components/sidebar-auto-collapse.tsx +0 -23
  695. package/template/components/templates/focused-workflow-layouts.tsx +0 -448
  696. package/template/components/templates/focused-workflow-page-template.tsx +0 -69
  697. package/template/components/templates/page-loading-shell.tsx +0 -262
  698. package/template/components/ui/button-group.tsx +0 -1
  699. package/template/docs/consumer-app-pattern.md +0 -39
  700. package/template/docs/focused-workflow-page-pattern.md +0 -84
  701. package/template/docs/question-bank-hub-header-pattern.md +0 -25
  702. package/template/lib/list-hub-nav.ts +0 -121
  703. package/template/lib/mock/list-hub-directory.ts +0 -27
  704. package/template/lib/mock/list-hub-kpi.ts +0 -27
  705. package/template/lib/mock/question-bank-header-collaborators.ts +0 -54
  706. package/template/lib/mock/question-bank.ts +0 -249
  707. package/template/lib/page-loading-variant.ts +0 -40
  708. package/template/lib/question-bank-dedicated-search.ts +0 -19
  709. package/template/lib/question-bank-hub-search.ts +0 -90
  710. package/template/lib/question-bank-nav.ts +0 -477
  711. package/template/lib/question-bank-recent-searches.ts +0 -22
  712. /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
  713. /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
  714. /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
  715. /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
  716. /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
@@ -0,0 +1,602 @@
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 "../ui/tip"
29
+ import { ExportDrawer } from "../ui/export-drawer"
30
+ import { Button } from "../ui/button"
31
+ import { Input } from "../ui/input"
32
+ import {
33
+ Dialog,
34
+ DialogContent,
35
+ DialogDescription,
36
+ DialogFooter,
37
+ DialogHeader,
38
+ DialogTitle,
39
+ } from "../ui/dialog"
40
+ import {
41
+ DropdownMenu,
42
+ DropdownMenuContent,
43
+ DropdownMenuItem,
44
+ DropdownMenuLabel,
45
+ DropdownMenuSeparator,
46
+ DropdownMenuTrigger,
47
+ Shortcut,
48
+ } from "../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 "../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
+ * Subset of view types the hub actually implements (e.g. List hub omits Dashboard/Folder).
131
+ * When set, the Add view menu and ⌘1–9 shortcuts are filtered so users cannot add a view the
132
+ * hub cannot render. Defaults to all registered view types (`DATA_LIST_VIEW_TILES`).
133
+ *
134
+ * Pair with `TablePropertiesDrawerButton.supportedViewTypes` to keep Properties consistent.
135
+ */
136
+ supportedViewTypes?: readonly DataListViewType[]
137
+ }
138
+
139
+ /** Collision-proof id for a dynamically-added tab. Module-level counters reset
140
+ * on HMR while React state survives, so we derive from a timestamp + random. */
141
+ function makeTabId(type: string): string {
142
+ const rand = Math.random().toString(36).slice(2, 8)
143
+ return `${type}-${Date.now().toString(36)}-${rand}`
144
+ }
145
+
146
+ /** Count pill on the views toolbar — color by lifecycle/status filter (WCAG: dark text on light inactive; light text on solid active). */
147
+ export function viewToolbarCountBadgeClass(filterId: string, isActive: boolean): string {
148
+ const palettes: Record<string, { active: string; inactive: string }> = {
149
+ all: {
150
+ active: "bg-slate-600 text-white dark:bg-slate-500",
151
+ inactive: "bg-slate-100 text-slate-800 dark:bg-slate-800/70 dark:text-slate-100",
152
+ },
153
+ upcoming: {
154
+ active: "bg-amber-600 text-white",
155
+ inactive: "bg-amber-100 text-amber-950 dark:bg-amber-950/45 dark:text-amber-100",
156
+ },
157
+ ongoing: {
158
+ active: "bg-blue-600 text-white",
159
+ inactive: "bg-blue-100 text-blue-950 dark:bg-blue-950/45 dark:text-blue-100",
160
+ },
161
+ completed: {
162
+ active: "bg-emerald-600 text-white",
163
+ inactive: "bg-emerald-100 text-emerald-950 dark:bg-emerald-950/45 dark:text-emerald-100",
164
+ },
165
+ }
166
+ const p = palettes[filterId] ?? palettes.all
167
+ return isActive ? p.active : p.inactive
168
+ }
169
+
170
+ // ─────────────────────────────────────────────────────────────────────────────
171
+ // Component
172
+ // ─────────────────────────────────────────────────────────────────────────────
173
+
174
+ export function ListPageTemplate({
175
+ header,
176
+ metrics,
177
+ showMetrics = true,
178
+ defaultTabs,
179
+ tabs: tabsProp,
180
+ onTabsChange,
181
+ activeTabId: activeTabIdProp,
182
+ onActiveTabChange,
183
+ getTabCount,
184
+ renderContent,
185
+ exportOpen = false,
186
+ onExportOpenChange,
187
+ exportTotalRows = 0,
188
+ onEditView,
189
+ tablePropertiesRef,
190
+ hideViewsToolbar = false,
191
+ supportedViewTypes,
192
+ }: ListPageTemplateProps) {
193
+ // When a hub declares the views it implements, both the Add view menu and ⌘1–9 shortcut
194
+ // bindings are filtered to that subset so unsupported views are never offered. Without
195
+ // this, a user could ⌘1 → Dashboard into a hub that cannot render it (would show the
196
+ // not-configured empty state). Memoized because it filters on every render path.
197
+ const addableViewTypes = React.useMemo(() => {
198
+ if (!supportedViewTypes || supportedViewTypes.length === 0) return VIEW_TYPES
199
+ const allowed = new Set(supportedViewTypes)
200
+ return VIEW_TYPES.filter(v => allowed.has(v.type))
201
+ }, [supportedViewTypes])
202
+ const controlled =
203
+ tabsProp !== undefined &&
204
+ onTabsChange !== undefined &&
205
+ activeTabIdProp !== undefined &&
206
+ onActiveTabChange !== undefined
207
+
208
+ const [internalTabs, setInternalTabs] = React.useState<ViewTab[]>(defaultTabs)
209
+ const [internalActiveId, setInternalActiveId] = React.useState(defaultTabs[0]?.id ?? "")
210
+
211
+ const tabs = controlled ? tabsProp : internalTabs
212
+ const setTabsState = React.useCallback(
213
+ (action: React.SetStateAction<ViewTab[]>) => {
214
+ if (controlled) {
215
+ const next = typeof action === "function" ? action(tabsProp!) : action
216
+ onTabsChange!(next)
217
+ } else {
218
+ setInternalTabs(action)
219
+ }
220
+ },
221
+ [controlled, onTabsChange, tabsProp, setInternalTabs],
222
+ )
223
+ const activeTabId = controlled ? activeTabIdProp : internalActiveId
224
+ const setActiveTabId = controlled ? onActiveTabChange : setInternalActiveId
225
+ const [renameOpen, setRenameOpen] = React.useState(false)
226
+ const [renameValue, setRenameValue] = React.useState("")
227
+ const [renameTabId, setRenameTabId] = React.useState<string | null>(null)
228
+ const [reviewOpen, setReviewOpen] = React.useState(false)
229
+ const [reviewTab, setReviewTab] = React.useState<ViewTab | null>(null)
230
+
231
+ const activeTab = tabs.find(t => t.id === activeTabId) ?? tabs[0]
232
+
233
+ const editViewFromRef = React.useMemo(
234
+ () => (tablePropertiesRef ? createListPageEditViewHandler(tablePropertiesRef) : undefined),
235
+ [tablePropertiesRef]
236
+ )
237
+ const resolvedOnEditView = onEditView ?? editViewFromRef
238
+
239
+ function addView(type: ViewType) {
240
+ const def = VIEW_TYPES.find(d => d.type === type)!
241
+ const count = tabs.filter(t => t.viewType === type).length
242
+ const id = makeTabId(type)
243
+ const label = count === 0 ? def.label : `${def.label} ${count + 1}`
244
+ const newTab: ViewTab = { id, label, viewType: type, icon: def.icon, filterId: "all" }
245
+ setTabsState(prev => [...prev, newTab])
246
+ setActiveTabId(id)
247
+ }
248
+
249
+ function removeTab(id: string, e: React.MouseEvent | React.KeyboardEvent) {
250
+ e.stopPropagation()
251
+ setTabsState(prev => {
252
+ const next = prev.filter(t => t.id !== id)
253
+ if (activeTabId === id && next.length > 0) {
254
+ const idx = Math.max(0, prev.findIndex(t => t.id === id) - 1)
255
+ setActiveTabId(next[Math.min(idx, next.length - 1)].id)
256
+ }
257
+ return next
258
+ })
259
+ }
260
+
261
+ function updateTab(id: string, patch: Partial<ViewTab>) {
262
+ setTabsState(prev => prev.map(t => t.id === id ? { ...t, ...patch } : t))
263
+ }
264
+
265
+ function duplicateTab(tab: ViewTab) {
266
+ const id = makeTabId(tab.viewType)
267
+ const newTab: ViewTab = {
268
+ id,
269
+ label: `Copy of ${tab.label}`,
270
+ viewType: tab.viewType,
271
+ icon: tab.icon,
272
+ filterId: tab.filterId,
273
+ }
274
+ setTabsState(prev => [...prev, newTab])
275
+ setActiveTabId(id)
276
+ }
277
+
278
+ function openRename(tab: ViewTab) {
279
+ setRenameTabId(tab.id)
280
+ setRenameValue(tab.label)
281
+ setRenameOpen(true)
282
+ }
283
+
284
+ function commitRename() {
285
+ if (!renameTabId) return
286
+ const v = renameValue.trim()
287
+ if (v) updateTab(renameTabId, { label: v })
288
+ setRenameOpen(false)
289
+ setRenameTabId(null)
290
+ }
291
+
292
+ return (
293
+ <>
294
+ {!hideViewsToolbar && addableViewTypes.slice(0, 9).map((v, i) => {
295
+ const keys = dataListViewAddShortcut(i)
296
+ return keys ? (
297
+ <Shortcut
298
+ key={v.type}
299
+ keys={keys}
300
+ onInvoke={() => addView(v.type)}
301
+ />
302
+ ) : null
303
+ })}
304
+ {activeTab && !hideViewsToolbar && (
305
+ <>
306
+ <Shortcut keys="F2" onInvoke={() => openRename(activeTab)} />
307
+ <Shortcut
308
+ keys="⌘E"
309
+ disabled={!resolvedOnEditView}
310
+ onInvoke={() => resolvedOnEditView?.(activeTab, { updateTab: p => updateTab(activeTab.id, p) })}
311
+ />
312
+ <Shortcut keys="⌘D" onInvoke={() => duplicateTab(activeTab)} />
313
+ <Shortcut keys="⌘I" onInvoke={() => { setReviewTab(activeTab); setReviewOpen(true) }} />
314
+ <Shortcut
315
+ keys="⌘⌫"
316
+ disabled={tabs.length <= 1}
317
+ onInvoke={(e) => removeTab(activeTab.id, e as unknown as React.KeyboardEvent)}
318
+ />
319
+ </>
320
+ )}
321
+ {header}
322
+
323
+ {showMetrics && metrics}
324
+
325
+ {/* ── Views toolbar (not tablist: settings/close are not tabs — WCAG 1.3.1 / ARIA) ── */}
326
+ {!hideViewsToolbar && (
327
+ <>
328
+ {/* Outer: horizontal scroll only. Inner: vertical padding so ring-offset focus rings are not clipped
329
+ (`overflow-x-auto` forces overflow-y to clip in a single box). */}
330
+ <div className="mt-3 shrink-0 overflow-x-auto px-4 lg:px-6">
331
+ <div className="flex w-max items-center gap-1 py-1.5">
332
+ <div
333
+ role="toolbar"
334
+ aria-label="Views"
335
+ data-slot="view-segmented-toolbar"
336
+ className={viewSegmentedToolbarClass()}
337
+ >
338
+ {tabs.map(tab => {
339
+ const isActive = tab.id === activeTabId
340
+ const isOnly = tabs.length === 1
341
+ const count = getTabCount?.(tab.filterId)
342
+ const tabInner = (
343
+ <>
344
+ <i className={cn("fa-light shrink-0 text-xs", tab.icon)} aria-hidden="true" />
345
+ {tab.label}
346
+ {count !== undefined && (
347
+ <span
348
+ data-slot="view-toolbar-count"
349
+ className={cn(
350
+ "text-xs tabular-nums rounded-full px-1 py-px min-w-[1.125rem] text-center font-semibold",
351
+ viewToolbarCountBadgeClass(tab.filterId, isActive),
352
+ )}
353
+ >
354
+ {count}
355
+ </span>
356
+ )}
357
+ </>
358
+ )
359
+ const viewSettingsMenu = (
360
+ <DropdownMenu>
361
+ <Tip label="View settings" side="bottom">
362
+ <DropdownMenuTrigger asChild>
363
+ <button
364
+ type="button"
365
+ className={cn(
366
+ "inline-flex items-center justify-center min-h-8 min-w-6 shrink-0 rounded-e-md rounded-s-none px-0.5",
367
+ "text-muted-foreground hover:text-interactive-hover-foreground hover:bg-foreground/[0.04]",
368
+ "transition-colors",
369
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:z-10",
370
+ )}
371
+ aria-label="View settings"
372
+ >
373
+ <i className="fa-light fa-chevron-down text-xs" aria-hidden="true" />
374
+ </button>
375
+ </DropdownMenuTrigger>
376
+ </Tip>
377
+ <DropdownMenuContent align="start">
378
+ <DropdownMenuLabel className="text-xs text-muted-foreground">
379
+ View: {VIEW_TYPES.find(v => v.type === tab.viewType)?.label}
380
+ </DropdownMenuLabel>
381
+ <DropdownMenuSeparator />
382
+
383
+ <DropdownMenuItem
384
+ shortcut="F2"
385
+ onSelect={() => openRename(tab)}
386
+ >
387
+ <i className="fa-light fa-pen text-xs" aria-hidden="true" />
388
+ Rename
389
+ </DropdownMenuItem>
390
+ <DropdownMenuItem
391
+ disabled={!resolvedOnEditView}
392
+ shortcut="⌘E"
393
+ onSelect={() =>
394
+ resolvedOnEditView?.(tab, { updateTab: patch => updateTab(tab.id, patch) })
395
+ }
396
+ >
397
+ <i className="fa-light fa-sliders text-xs" aria-hidden="true" />
398
+ Edit
399
+ </DropdownMenuItem>
400
+ <DropdownMenuItem shortcut="⌘D" onSelect={() => duplicateTab(tab)}>
401
+ <i className="fa-light fa-copy text-xs" aria-hidden="true" />
402
+ Duplicate
403
+ </DropdownMenuItem>
404
+ <DropdownMenuItem
405
+ shortcut="⌘I"
406
+ onSelect={() => { setReviewTab(tab); setReviewOpen(true) }}
407
+ >
408
+ <i className="fa-light fa-clipboard-list text-xs" aria-hidden="true" />
409
+ Review view
410
+ </DropdownMenuItem>
411
+
412
+ <DropdownMenuSeparator />
413
+ {!isOnly && (
414
+ <DropdownMenuItem
415
+ shortcut="⌘⌫"
416
+ onSelect={(e) => removeTab(tab.id, e as unknown as React.KeyboardEvent)}
417
+ className="text-destructive focus:text-destructive"
418
+ >
419
+ <i className="fa-light fa-trash text-xs" aria-hidden="true" />
420
+ Remove view
421
+ </DropdownMenuItem>
422
+ )}
423
+ </DropdownMenuContent>
424
+ </DropdownMenu>
425
+ )
426
+ return (
427
+ <div key={tab.id} className="group relative inline-flex items-center">
428
+ {isActive ? (
429
+ <div
430
+ className={cn(
431
+ viewSegmentedButtonClass(true),
432
+ "gap-0 p-0 inline-flex items-stretch",
433
+ )}
434
+ >
435
+ <button
436
+ type="button"
437
+ aria-pressed={true}
438
+ data-slot="view-segmented-item"
439
+ onClick={() => setActiveTabId(tab.id)}
440
+ className={cn(
441
+ "inline-flex items-center gap-1.5 ps-2.5 pe-0.5 py-1 text-xs min-h-8",
442
+ "rounded-s-md rounded-e-none",
443
+ "bg-transparent text-foreground font-medium",
444
+ "hover:bg-foreground/[0.04]",
445
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:z-10",
446
+ )}
447
+ >
448
+ {tabInner}
449
+ </button>
450
+ {viewSettingsMenu}
451
+ </div>
452
+ ) : (
453
+ <button
454
+ type="button"
455
+ aria-pressed={false}
456
+ data-slot="view-segmented-item"
457
+ onClick={() => setActiveTabId(tab.id)}
458
+ className={cn(
459
+ viewSegmentedButtonClass(false),
460
+ /* Tighter trailing edge when remove control follows */
461
+ !isOnly && "pe-1.5",
462
+ )}
463
+ >
464
+ {tabInner}
465
+ </button>
466
+ )}
467
+
468
+ {/* Close on inactive tabs — native button + 24px min target (WCAG 2.5.8) */}
469
+ {!isActive && !isOnly && (
470
+ <Tip side="bottom" label={`Remove ${tab.label} view`}>
471
+ <button
472
+ type="button"
473
+ aria-label={`Remove ${tab.label} view`}
474
+ onClick={e => removeTab(tab.id, e)}
475
+ 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"
476
+ >
477
+ <i className="fa-light fa-xmark text-xs" aria-hidden="true" />
478
+ </button>
479
+ </Tip>
480
+ )}
481
+ </div>
482
+ )
483
+ })}
484
+ </div>
485
+
486
+ {/* Add view */}
487
+ <DropdownMenu>
488
+ <DropdownMenuTrigger asChild>
489
+ <Button
490
+ type="button"
491
+ variant="ghost"
492
+ className="shrink-0 text-muted-foreground"
493
+ >
494
+ <i className="fa-light fa-plus text-sm" aria-hidden="true" />
495
+ Add view
496
+ </Button>
497
+ </DropdownMenuTrigger>
498
+ <DropdownMenuContent align="start">
499
+ <DropdownMenuLabel className="text-xs">Add a view</DropdownMenuLabel>
500
+ <DropdownMenuSeparator />
501
+ {addableViewTypes.map((v, i) => (
502
+ <DropdownMenuItem
503
+ key={v.type}
504
+ shortcut={dataListViewAddShortcut(i)}
505
+ onSelect={() => addView(v.type)}
506
+ >
507
+ <i className={`fa-light ${v.icon}`} aria-hidden="true" />
508
+ {v.label}
509
+ </DropdownMenuItem>
510
+ ))}
511
+ </DropdownMenuContent>
512
+ </DropdownMenu>
513
+ </div>
514
+ </div>
515
+ </>
516
+ )}
517
+
518
+ {/* ── Content — keyed by tab so each view tab owns its height (no stale min-height). ── */}
519
+ {activeTab ? (
520
+ <div key={activeTab.id} className="flex min-h-0 flex-1 flex-col">
521
+ {renderContent(activeTab, patch => updateTab(activeTab.id, patch))}
522
+ </div>
523
+ ) : null}
524
+
525
+ {/* ── Export ──────────────────────────────────────────────── */}
526
+ {onExportOpenChange && (
527
+ <ExportDrawer
528
+ open={exportOpen}
529
+ onOpenChange={onExportOpenChange}
530
+ totalRows={exportTotalRows ?? getTabCount?.(activeTab.filterId) ?? 0}
531
+ />
532
+ )}
533
+
534
+ <Dialog open={renameOpen} onOpenChange={setRenameOpen}>
535
+ <DialogContent className="max-w-sm">
536
+ <DialogHeader>
537
+ <DialogTitle>Rename view</DialogTitle>
538
+ <DialogDescription>Enter a new name for this view.</DialogDescription>
539
+ </DialogHeader>
540
+ <Input
541
+ className="mt-3 h-9 text-sm"
542
+ value={renameValue}
543
+ onChange={e => setRenameValue(e.target.value)}
544
+ onKeyDown={e => { if (e.key === "Enter") commitRename() }}
545
+ autoFocus
546
+ aria-label="View name"
547
+ />
548
+ <DialogFooter>
549
+ <Button type="button" variant="outline" size="sm" onClick={() => setRenameOpen(false)}>
550
+ Cancel
551
+ </Button>
552
+ <Button type="button" size="sm" onClick={commitRename}>
553
+ Save
554
+ </Button>
555
+ </DialogFooter>
556
+ </DialogContent>
557
+ </Dialog>
558
+
559
+ <Dialog
560
+ open={reviewOpen && !!reviewTab}
561
+ onOpenChange={(open) => {
562
+ setReviewOpen(open)
563
+ if (!open) setReviewTab(null)
564
+ }}
565
+ >
566
+ <DialogContent className="max-w-md">
567
+ <DialogHeader>
568
+ <DialogTitle>Review view</DialogTitle>
569
+ <DialogDescription>Summary of this view’s configuration.</DialogDescription>
570
+ </DialogHeader>
571
+ {reviewTab && (
572
+ <dl className="mt-2 space-y-3 text-sm">
573
+ <div className="flex justify-between gap-4 border-b border-border pb-2">
574
+ <dt className="text-muted-foreground">Name</dt>
575
+ <dd className="font-medium text-foreground text-end">{reviewTab.label}</dd>
576
+ </div>
577
+ <div className="flex justify-between gap-4 border-b border-border pb-2">
578
+ <dt className="text-muted-foreground">View type</dt>
579
+ <dd className="text-foreground text-end">{VIEW_TYPES.find(v => v.type === reviewTab.viewType)?.label}</dd>
580
+ </div>
581
+ <div className="flex justify-between gap-4 border-b border-border pb-2">
582
+ <dt className="text-muted-foreground">Lifecycle filter</dt>
583
+ <dd className="text-foreground text-end capitalize">{reviewTab.filterId}</dd>
584
+ </div>
585
+ {getTabCount && (
586
+ <div className="flex justify-between gap-4">
587
+ <dt className="text-muted-foreground">Row count</dt>
588
+ <dd className="tabular-nums text-foreground text-end">{getTabCount(reviewTab.filterId)}</dd>
589
+ </div>
590
+ )}
591
+ </dl>
592
+ )}
593
+ <DialogFooter>
594
+ <Button type="button" size="sm" onClick={() => setReviewOpen(false)}>
595
+ Close
596
+ </Button>
597
+ </DialogFooter>
598
+ </DialogContent>
599
+ </Dialog>
600
+ </>
601
+ )
602
+ }
@@ -0,0 +1,70 @@
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
+ // The Cursor IDE browser preview injects a `data-cursor-ref` attribute
33
+ // on top-level layout roots BEFORE React hydrates (so it can target
34
+ // them for click automation). React then sees an attribute it didn't
35
+ // SSR and emits a hydration warning. Suppressing here only quiets the
36
+ // warning for THIS element's own attributes — children still hydrate
37
+ // normally and any real mismatch inside the panel will still surface.
38
+ // Has zero effect outside the Cursor IDE preview.
39
+ suppressHydrationWarning
40
+ className={cn(
41
+ "flex flex-col overflow-hidden",
42
+ "transition-[width,margin,opacity] duration-200 ease-linear",
43
+ open
44
+ ? cn(
45
+ // Match the primary sidebar: fill the full viewport height
46
+ // (minus our 0.5rem top + 0.5rem bottom margin from `m-2` →
47
+ // 1rem on desktop where the panel is `md:sticky md:top-2`;
48
+ // 2rem on mobile where the panel scrolls inline and we leave
49
+ // a little more breathing room). No upper cap so tall screens
50
+ // get a fully-extended rail.
51
+ "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)]",
52
+ compact
53
+ ? "w-12 min-w-12 max-w-12 h-[calc(100svh-2rem)] md:h-[calc(100svh-1rem)]"
54
+ : "w-64 min-w-64 max-w-64 h-[calc(100svh-2rem)] md:h-[calc(100svh-1rem)]",
55
+ )
56
+ : "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",
57
+ className,
58
+ )}
59
+ >
60
+ <div
61
+ className={cn(
62
+ "flex flex-1 flex-col overflow-y-auto overflow-x-hidden",
63
+ open ? "min-w-0" : "hidden min-w-0 w-0 p-0",
64
+ )}
65
+ >
66
+ {children}
67
+ </div>
68
+ </nav>
69
+ )
70
+ }