@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
@@ -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"
@@ -106,21 +106,57 @@ function normalizedLocationHash(locationHash: string): string {
106
106
  }
107
107
 
108
108
  /**
109
- * Paths where a sibling sidebar row uses `#fragment` on the same pathname
110
- * (e.g. Settings vs Tokens & themes). The plain-path row must not stay active
111
- * when the hash belongs to that sibling.
109
+ * Path set of hash fragments claimed by *another* nav item at the same path.
110
+ *
111
+ * Why: several rows deliberately share a route and disambiguate via `#fragment`.
112
+ * Example: `Tokens & themes → /settings#appearance` and `Settings → /settings`
113
+ * both render under the same page. Without a registry, when the user is on
114
+ * `/settings#appearance` the no-fragment "Settings" row matches by path-equality
115
+ * (line below: `pathname === pathOnly`) and lights up too — so *both* rows
116
+ * appear active.
117
+ *
118
+ * The registry is computed once from the static nav config and consulted by
119
+ * `isNavActive` to make the no-fragment item defer when a hash-bearing sibling
120
+ * claims the current `location.hash`.
112
121
  */
113
- const NAV_EXCLUSIVE_HASH_BY_PATH: Readonly<Record<string, readonly string[]>> = {
114
- "/settings": ["appearance"],
115
- "/help": ["more"],
122
+ const NAV_HASH_CLAIMS: ReadonlyMap<string, ReadonlySet<string>> = (() => {
123
+ const map = new Map<string, Set<string>>()
124
+ const record = (url: string) => {
125
+ const p = navUrlPath(url)
126
+ const f = navUrlFragment(url)
127
+ if (!p || f === null) return
128
+ let set = map.get(p)
129
+ if (!set) { set = new Set<string>(); map.set(p, set) }
130
+ set.add(f)
131
+ }
132
+ const walk = (items: ReadonlyArray<{ url?: string; children?: ReadonlyArray<{ url?: string; children?: unknown }> }>) => {
133
+ for (const it of items) {
134
+ if (typeof it.url === "string") record(it.url)
135
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
+ if (Array.isArray((it as any).children)) walk((it as any).children)
137
+ }
138
+ }
139
+ walk(NAV_PRIMARY)
140
+ walk(NAV_DOCUMENTS)
141
+ walk(NAV_QUICK_ACTIONS)
142
+ walk(NAV_SECONDARY)
143
+ return map
144
+ })()
145
+
146
+ /** True when another nav item at the same path claims the current location hash. */
147
+ function navHasMoreSpecificMatch(pathname: string, locationHash: string): boolean {
148
+ const claims = NAV_HASH_CLAIMS.get(pathname)
149
+ if (!claims) return false
150
+ const h = normalizedLocationHash(locationHash)
151
+ if (h === "") return false
152
+ return claims.has(h)
116
153
  }
117
154
 
118
155
  /**
119
156
  * Whether `pathname` (+ optional `location.hash`) matches a sidebar `href`.
120
157
  * When several links share the same path (e.g. `/settings`), disambiguate with `#fragment`
121
158
  * in each `href` — those rows use the `frag !== null` branch below.
122
- * For `href` without `#…`, an in-page hash (e.g. QB view tabs) does not clear the match,
123
- * except when the hash is reserved for a hash-sibling row on that path.
159
+ * For `href` without `#…`, an in-page hash (e.g. QB view tabs) does not clear the match.
124
160
  */
125
161
  function isNavActive(pathname: string, url: string, locationHash = ""): boolean {
126
162
  const pathOnly = navUrlPath(url)
@@ -140,15 +176,18 @@ function isNavActive(pathname: string, url: string, locationHash = ""): boolean
140
176
  return pathname === pathOnly && h === frag
141
177
  }
142
178
 
143
- if (pathOnly === "/") return pathname === "/" && h === ""
144
- /** Exact path match ignore `location.hash` when the nav `href` has no `#…` fragment (QB view tabs use hash). */
145
- if (pathname === pathOnly) {
146
- if (h !== "") {
147
- const exclusive = NAV_EXCLUSIVE_HASH_BY_PATH[pathOnly]
148
- if (exclusive?.includes(h)) return false
149
- }
150
- return true
179
+ if (pathOnly === "/") {
180
+ if (pathname !== "/" || h !== "") return false
181
+ return !navHasMoreSpecificMatch(pathname, locationHash)
151
182
  }
183
+ /**
184
+ * Exact path match — ignore `location.hash` when the nav `href` has no `#…` fragment (QB view tabs use hash).
185
+ * EXCEPTION: when another nav item at the same path claims the current hash
186
+ * (e.g. `Tokens & themes → /settings#appearance` while we're evaluating
187
+ * `Settings → /settings`), defer to that more-specific row — otherwise both
188
+ * would light up. See `NAV_HASH_CLAIMS`.
189
+ */
190
+ if (pathname === pathOnly) return !navHasMoreSpecificMatch(pathname, locationHash)
152
191
  // Design system library — active on hub and detail routes.
153
192
  if (pathOnly === "/library") {
154
193
  return pathname.startsWith("/library/")
@@ -184,7 +223,7 @@ function isCollapsibleChildActive(
184
223
 
185
224
  if (!isNavActive(pathname, child.url, locationHash)) return false
186
225
 
187
- /** Hub entry (`/question-bank`) must not stay “active” on `/question-bank/library` etc. */
226
+ /** Hub entry (`/library`) must not stay “active” on `/library/all` etc. */
188
227
  if (parent.primaryHubChildKey && child.key === parent.primaryHubChildKey) {
189
228
  const hubPath = navUrlPath(parent.url)
190
229
  if (hubPath) {
@@ -315,7 +354,7 @@ function CollapsibleNavItem({ item, pathname }: { item: NavLinkItem; pathname: s
315
354
  const iconRailCollapsed = state === "collapsed" && !isMobile
316
355
  // In the icon rail the parent icon is the ONLY visible thing for this item
317
356
  // (no sub-list, no labels) — so it must reflect "I'm somewhere inside this
318
- // section" by lighting up on any descendant route (e.g. `/question-bank/library`),
357
+ // section" by lighting up on any descendant route (e.g. `/library/all`),
319
358
  // not only on the parent URL itself. In the expanded view we keep the
320
359
  // parent neutral and let the active child row carry `data-active` (see
321
360
  // `isCollapsibleParentMenuButtonActive`).
@@ -440,7 +479,7 @@ function CollapsibleNavItem({ item, pathname }: { item: NavLinkItem; pathname: s
440
479
  </span>
441
480
  <span>{item.title}</span>
442
481
  <i
443
- 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"
482
+ 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"
444
483
  aria-hidden="true"
445
484
  />
446
485
  </SidebarMenuButton>
@@ -844,58 +883,60 @@ function ProductLogoButton() {
844
883
 
845
884
  return (
846
885
  <DropdownMenu>
847
- <DropdownMenuTrigger asChild>
848
- <SidebarMenuButton
849
- size="lg"
850
- tooltip={iconRail ? current.label : undefined}
851
- className={cn(
852
- "py-2 text-sidebar-foreground data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
853
- expandedOrMobile &&
854
- "h-auto min-h-12 !overflow-visible items-center [&>span:last-child]:!overflow-visible [&>span:last-child]:!whitespace-normal [&>span:last-child]:text-clip",
855
- "group-data-[collapsible=icon]:items-center group-data-[collapsible=icon]:justify-center",
856
- iconRail &&
857
- "group-data-[collapsible=icon]:!size-9 group-data-[collapsible=icon]:!min-h-9 group-data-[collapsible=icon]:!max-h-9 group-data-[collapsible=icon]:!p-0 group-data-[collapsible=icon]:overflow-visible",
858
- )}
859
- aria-label={`Current product: ${current.label}. Switch product`}
860
- suppressHydrationWarning
861
- >
862
- {iconRail ? (
863
- // Match the school selector footprint in the icon rail (32px frame,
864
- // 28px mark same visual weight as the avatar with inset padding).
865
- <span className="flex size-8 shrink-0 items-center justify-center">
866
- <ExxatProductMark product={current.id} className="size-7" />
867
- </span>
868
- ) : (
869
- <span className="flex min-h-0 min-w-0 flex-1 items-stretch gap-2">
870
- <span
871
- className="flex min-h-0 min-w-0 flex-1 items-center justify-start overflow-visible"
872
- aria-hidden="true"
873
- >
874
- <ExxatProductLogo
875
- product={current.id}
876
- variant="mutedSuffix"
877
- className="w-auto max-w-[min(100%,280px)] object-left object-contain"
878
- />
879
- </span>
880
- <span
881
- className="flex w-6 shrink-0 items-center justify-center self-stretch text-muted-foreground"
882
- aria-hidden="true"
883
- >
884
- <i
885
- className="fa-light fa-chevron-down block text-xs leading-none"
886
- aria-hidden="true"
887
- />
888
- </span>
889
- </span>
890
- )}
891
- </SidebarMenuButton>
892
- </DropdownMenuTrigger>
886
+ <Tooltip>
887
+ <TooltipTrigger asChild>
888
+ <DropdownMenuTrigger asChild>
889
+ <SidebarMenuButton
890
+ size="lg"
891
+ className={cn(
892
+ "py-2 text-sidebar-foreground data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
893
+ expandedOrMobile &&
894
+ "h-auto min-h-12 !overflow-visible items-center [&>span:last-child]:!overflow-visible [&>span:last-child]:!whitespace-normal [&>span:last-child]:text-clip",
895
+ "group-data-[collapsible=icon]:items-center group-data-[collapsible=icon]:justify-center",
896
+ iconRail &&
897
+ "group-data-[collapsible=icon]:!size-9 group-data-[collapsible=icon]:!min-h-9 group-data-[collapsible=icon]:!max-h-9 group-data-[collapsible=icon]:!p-0 group-data-[collapsible=icon]:overflow-visible",
898
+ )}
899
+ aria-label={`Current product: ${current.label}. Switch product`}
900
+ suppressHydrationWarning
901
+ >
902
+ {iconRail ? (
903
+ // Match the school selector footprint in the icon rail (32px frame,
904
+ // 28px mark same visual weight as the avatar with inset padding).
905
+ <span className="flex size-8 shrink-0 items-center justify-center">
906
+ <ExxatProductMark product={current.id} className="size-7" />
907
+ </span>
908
+ ) : (
909
+ <span className="flex min-h-0 min-w-0 flex-1 items-stretch gap-2">
910
+ <span
911
+ className="flex min-h-0 min-w-0 flex-1 items-center justify-start overflow-visible"
912
+ aria-hidden="true"
913
+ >
914
+ <ExxatProductLogo
915
+ product={current.id}
916
+ variant="mutedSuffix"
917
+ className="w-auto max-w-[min(100%,280px)] object-left object-contain"
918
+ />
919
+ </span>
920
+ <span
921
+ className="flex w-6 shrink-0 items-center justify-center self-stretch text-muted-foreground"
922
+ aria-hidden="true"
923
+ >
924
+ <i
925
+ className="fa-light fa-chevron-down block text-xs leading-none"
926
+ aria-hidden="true"
927
+ />
928
+ </span>
929
+ </span>
930
+ )}
931
+ </SidebarMenuButton>
932
+ </DropdownMenuTrigger>
933
+ </TooltipTrigger>
934
+ <TooltipContent side="right" align="center" hidden={state !== "collapsed" || isMobile}>
935
+ {current.label}
936
+ </TooltipContent>
937
+ </Tooltip>
893
938
 
894
- <DropdownMenuContent
895
- align="start"
896
- side={iconRail ? "right" : "bottom"}
897
- sideOffset={iconRail ? 8 : 4}
898
- >
939
+ <DropdownMenuContent align="start" side="right" sideOffset={8}>
899
940
  <DropdownMenuLabel className="text-xs text-muted-foreground">
900
941
  Switch product
901
942
  </DropdownMenuLabel>
@@ -913,7 +954,7 @@ function ProductLogoButton() {
913
954
  className="w-auto shrink-0 max-w-[min(100%,260px)]"
914
955
  />
915
956
  {p.id === product && (
916
- <i className="fa-solid fa-check ml-auto text-brand text-xs" aria-hidden="true" />
957
+ <i className="fa-solid fa-check ms-auto text-brand text-xs" aria-hidden="true" />
917
958
  )}
918
959
  </DropdownMenuItem>
919
960
  ))}
@@ -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
  )}
@@ -0,0 +1,316 @@
1
+ "use client"
2
+
3
+ /**
4
+ * SecondaryPanel — nested rail between the primary icon sidebar and content.
5
+ * Full width shows hub scope nav; **compact** matches the primary sidebar icon rail (`w-12`).
6
+ *
7
+ * Chrome uses {@link NestedSecondaryPanelShell}. Library body stays in
8
+ * `library-secondary-nav.tsx` (domain-specific), not duplicated here.
9
+ */
10
+
11
+ import * as React from "react"
12
+ import { useSidebar } from "@/components/ui/sidebar"
13
+ import { Tip } from "@/components/ui/tip"
14
+ import { Button } from "@/components/ui/button"
15
+ import { LibrarySecondaryNav } from "@/components/library-secondary-nav"
16
+ import { TokensSecondaryNav } from "@/components/tokens-secondary-nav"
17
+ import { NestedSecondaryPanelShell } from "@/components/templates/nested-secondary-panel-shell"
18
+ import { useSidebarReflowZoom } from "@/hooks/use-sidebar-reflow-zoom"
19
+ import type { LibraryItem } from "@/lib/mock/library"
20
+ import type { LibraryFolder } from "@/lib/mock/library-folders"
21
+
22
+ export type LibraryFolderBridge = {
23
+ folders: LibraryFolder[]
24
+ onFoldersChange: React.Dispatch<React.SetStateAction<LibraryFolder[]>>
25
+ items: LibraryItem[]
26
+ onItemsChange: React.Dispatch<React.SetStateAction<LibraryItem[]>>
27
+ }
28
+
29
+ export type LibraryAccessBridge = {
30
+ openManageAccess: () => void
31
+ }
32
+
33
+ // ─────────────────────────────────────────────────────────────────────────────
34
+ // Context
35
+ // ─────────────────────────────────────────────────────────────────────────────
36
+
37
+ export type ClosePanelOptions = {
38
+ /**
39
+ * Main app sidebar after the secondary panel closes.
40
+ * - `restore` (default): snap back to the user's saved preference
41
+ * (`sidebar_state_v2` cookie, or `defaultOpen` if unset). Use this when
42
+ * leaving a page whose secondary panel caused an incidental collapse — the
43
+ * rail returns to the state the user explicitly set elsewhere via ⌘B / the
44
+ * sidebar button.
45
+ * - `leave`: only clear the active panel — keep the rail in whatever state it
46
+ * was in (rare; prefer `restore`).
47
+ * - `expand`: force the full primary rail open. Use only when the product
48
+ * explicitly wants the wide rail after dismiss.
49
+ * - `collapse`: keep the icon rail. Use when the next route also wants compact.
50
+ */
51
+ mainSidebar?: "restore" | "expand" | "collapse" | "leave"
52
+ }
53
+
54
+ interface SecondaryPanelContextValue {
55
+ /** Currently active panel id, or null if none */
56
+ activePanel: string | null
57
+ /** Open a panel by id (always exits compact / full-width). */
58
+ openPanel: (id: string) => void
59
+ /** Close the panel (programmatic / route cleanup). */
60
+ closePanel: (opts?: ClosePanelOptions) => void
61
+ /** Icon-only nested rail while the panel stays “open”. Cleared by {@link openPanel} / {@link closePanel}. */
62
+ secondaryPanelCompact: boolean
63
+ /** Narrow icon rail (primary-sidebar-style); keeps {@link activePanel} mounted. */
64
+ collapseActiveSecondaryPanel: () => void
65
+ /** Library folder tree shared with the secondary nav while the hub is mounted. */
66
+ libraryFolderBridge: LibraryFolderBridge | null
67
+ setLibraryFolderBridge: (bridge: LibraryFolderBridge | null) => void
68
+ /** Opens the hub collaborators sheet from the secondary nav. */
69
+ libraryAccessBridge: LibraryAccessBridge | null
70
+ setLibraryAccessBridge: (bridge: LibraryAccessBridge | null) => void
71
+ }
72
+
73
+ const SecondaryPanelContext = React.createContext<SecondaryPanelContextValue>({
74
+ activePanel: null,
75
+ openPanel: () => {},
76
+ closePanel: () => {},
77
+ secondaryPanelCompact: false,
78
+ collapseActiveSecondaryPanel: () => {},
79
+ libraryFolderBridge: null,
80
+ setLibraryFolderBridge: () => {},
81
+ libraryAccessBridge: null,
82
+ setLibraryAccessBridge: () => {},
83
+ })
84
+
85
+ export function useSecondaryPanel() {
86
+ return React.useContext(SecondaryPanelContext)
87
+ }
88
+
89
+ export function SecondaryPanelProvider({ children }: { children: React.ReactNode }) {
90
+ const [activePanel, setActivePanel] = React.useState<string | null>(null)
91
+ const [secondaryPanelCompact, setSecondaryPanelCompact] = React.useState(false)
92
+ const [libraryFolderBridge, setLibraryFolderBridge] =
93
+ React.useState<LibraryFolderBridge | null>(null)
94
+ const [libraryAccessBridge, setLibraryAccessBridge] =
95
+ React.useState<LibraryAccessBridge | null>(null)
96
+ const { setOpen, restoreSavedOpen } = useSidebar()
97
+
98
+ /**
99
+ * Browser zoom ≥ 200% (or very short viewport) — same `useSidebarReflowZoom`
100
+ * signal the primary sidebar uses (WCAG 1.4.10). At that scale the 16rem
101
+ * secondary rail crowds out primary content, so we **auto-collapse it to
102
+ * the icon variant on entering high zoom**. We don't keep overriding —
103
+ * users can re-expand once collapsed; the next zoom-out → zoom-in cycle
104
+ * re-collapses. This matches the pattern users get from clicking the
105
+ * panel's own "Collapse to icons" button.
106
+ */
107
+ const reflowZoom = useSidebarReflowZoom()
108
+ const wasReflowZoomRef = React.useRef(false)
109
+ React.useEffect(() => {
110
+ if (reflowZoom && !wasReflowZoomRef.current) {
111
+ setSecondaryPanelCompact(true)
112
+ }
113
+ wasReflowZoomRef.current = reflowZoom
114
+ }, [reflowZoom])
115
+
116
+ const openPanel = React.useCallback(
117
+ (id: string) => {
118
+ // High zoom → keep the icon rail (auto-collapse rule above). At normal
119
+ // zoom this stays the legacy behavior (full-width on open).
120
+ setSecondaryPanelCompact(reflowZoom)
121
+ setActivePanel(id)
122
+ // `persist: false` — collapsing the rail to make room for the secondary
123
+ // panel is an incidental layout side-effect; the user's saved
124
+ // expanded/collapsed preference (cookie) must not be overwritten by it.
125
+ setOpen(false, { persist: false }) // collapse main sidebar to icon rail
126
+ },
127
+ [setOpen, reflowZoom],
128
+ )
129
+
130
+ const closePanel = React.useCallback((opts?: ClosePanelOptions) => {
131
+ setSecondaryPanelCompact(false)
132
+ setActivePanel(null)
133
+ /**
134
+ * Default = `restore`. `openPanel` collapsed the rail with `persist: false`
135
+ * (the saved cookie is untouched), so on close we ask the sidebar context
136
+ * to re-apply whatever the user truly saved. This makes the visual collapse
137
+ * scoped to the page that needed it — leave the page → rail comes back to
138
+ * the user's preference.
139
+ */
140
+ const mainSidebar = opts?.mainSidebar ?? "restore"
141
+ if (mainSidebar === "leave") return
142
+ if (mainSidebar === "restore") {
143
+ restoreSavedOpen()
144
+ return
145
+ }
146
+ if (mainSidebar === "collapse") {
147
+ setOpen(false, { persist: false })
148
+ return
149
+ }
150
+ setOpen(true, { persist: false }) // mainSidebar === "expand"
151
+ }, [restoreSavedOpen, setOpen])
152
+
153
+ const collapseActiveSecondaryPanel = React.useCallback(() => {
154
+ setSecondaryPanelCompact(true)
155
+ }, [])
156
+
157
+ const value = React.useMemo(
158
+ () => ({
159
+ activePanel,
160
+ openPanel,
161
+ closePanel,
162
+ secondaryPanelCompact,
163
+ collapseActiveSecondaryPanel,
164
+ libraryFolderBridge,
165
+ setLibraryFolderBridge,
166
+ libraryAccessBridge,
167
+ setLibraryAccessBridge,
168
+ }),
169
+ [
170
+ activePanel,
171
+ openPanel,
172
+ closePanel,
173
+ secondaryPanelCompact,
174
+ collapseActiveSecondaryPanel,
175
+ libraryFolderBridge,
176
+ libraryAccessBridge,
177
+ ],
178
+ )
179
+
180
+ return (
181
+ <SecondaryPanelContext.Provider value={value}>
182
+ {children}
183
+ </SecondaryPanelContext.Provider>
184
+ )
185
+ }
186
+
187
+ // ─────────────────────────────────────────────────────────────────────────────
188
+ // SecondaryPanel — the actual rendered panel
189
+ // ─────────────────────────────────────────────────────────────────────────────
190
+
191
+ function LibraryPanel() {
192
+ const { collapseActiveSecondaryPanel, secondaryPanelCompact } = useSecondaryPanel()
193
+
194
+ if (secondaryPanelCompact) {
195
+ return <LibrarySecondaryNav />
196
+ }
197
+
198
+ return (
199
+ <>
200
+ <div className="flex items-center justify-between gap-2 px-4 pt-4 pb-2">
201
+ <h2
202
+ className="text-xl font-semibold leading-tight text-sidebar-foreground"
203
+ style={{ fontFamily: "var(--font-heading)" }}
204
+ >
205
+ Library
206
+ </h2>
207
+ <Tip label="Collapse to icons" side="bottom">
208
+ <Button
209
+ type="button"
210
+ size="icon"
211
+ variant="ghost"
212
+ onClick={() => collapseActiveSecondaryPanel()}
213
+ aria-label="Collapse to icons"
214
+ >
215
+ <i className="fa-light fa-angles-left" aria-hidden="true" />
216
+ </Button>
217
+ </Tip>
218
+ </div>
219
+ <LibrarySecondaryNav />
220
+ </>
221
+ )
222
+ }
223
+
224
+ function TokensPanel() {
225
+ const { collapseActiveSecondaryPanel, secondaryPanelCompact } = useSecondaryPanel()
226
+
227
+ if (secondaryPanelCompact) {
228
+ return <TokensSecondaryNav />
229
+ }
230
+
231
+ return (
232
+ <>
233
+ <div className="flex items-center justify-between gap-2 px-4 pt-4 pb-2">
234
+ <h2
235
+ className="text-xl font-semibold leading-tight text-sidebar-foreground"
236
+ style={{ fontFamily: "var(--font-heading)" }}
237
+ >
238
+ Tokens
239
+ </h2>
240
+ <Tip label="Collapse to icons" side="bottom">
241
+ <Button
242
+ type="button"
243
+ size="icon"
244
+ variant="ghost"
245
+ onClick={() => collapseActiveSecondaryPanel()}
246
+ aria-label="Collapse to icons"
247
+ >
248
+ <i className="fa-light fa-angles-left" aria-hidden="true" />
249
+ </Button>
250
+ </Tip>
251
+ </div>
252
+ <TokensSecondaryNav />
253
+ </>
254
+ )
255
+ }
256
+
257
+ /** Register panel components by id when a route opts into `secondaryPanel` in nav. */
258
+ const PANELS: Record<string, React.FC> = {
259
+ "library": LibraryPanel,
260
+ tokens: TokensPanel,
261
+ }
262
+
263
+ export function SecondaryPanel() {
264
+ const { activePanel, secondaryPanelCompact } = useSecondaryPanel()
265
+ const PanelContent = activePanel ? PANELS[activePanel] : null
266
+
267
+ return (
268
+ <NestedSecondaryPanelShell open={Boolean(activePanel)} compact={secondaryPanelCompact}>
269
+ {PanelContent ? <PanelContent /> : null}
270
+ </NestedSecondaryPanelShell>
271
+ )
272
+ }
273
+
274
+ // ─────────────────────────────────────────────────────────────────────────────
275
+ // Auto-open hook — pages call this to show/hide a panel on mount/unmount
276
+ // ─────────────────────────────────────────────────────────────────────────────
277
+
278
+ export function useAutoPanel(panelId: string) {
279
+ const { openPanel, closePanel } = useSecondaryPanel()
280
+
281
+ React.useEffect(() => {
282
+ openPanel(panelId)
283
+ return () => {
284
+ closePanel()
285
+ }
286
+ // eslint-disable-next-line react-hooks/exhaustive-deps
287
+ }, [panelId])
288
+ }
289
+
290
+ /** Sync hub folder state into the library secondary nav while the route is mounted. */
291
+ export function LibraryFolderBridge({
292
+ folders,
293
+ onFoldersChange,
294
+ items,
295
+ onItemsChange,
296
+ }: LibraryFolderBridge) {
297
+ const { setLibraryFolderBridge } = useSecondaryPanel()
298
+
299
+ React.useEffect(() => {
300
+ setLibraryFolderBridge({ folders, onFoldersChange, items, onItemsChange })
301
+ return () => setLibraryFolderBridge(null)
302
+ }, [folders, onFoldersChange, items, onItemsChange, setLibraryFolderBridge])
303
+
304
+ return null
305
+ }
306
+
307
+ export function LibraryAccessBridge({ openManageAccess }: LibraryAccessBridge) {
308
+ const { setLibraryAccessBridge } = useSecondaryPanel()
309
+
310
+ React.useEffect(() => {
311
+ setLibraryAccessBridge({ openManageAccess })
312
+ return () => setLibraryAccessBridge(null)
313
+ }, [openManageAccess, setLibraryAccessBridge])
314
+
315
+ return null
316
+ }
@@ -0,0 +1,27 @@
1
+ "use client"
2
+
3
+ import { useEffect, useRef } from "react"
4
+ import { useSidebar } from "@/components/ui/sidebar"
5
+
6
+ /**
7
+ * Collapses the sidebar on mount. Restores previous state on unmount.
8
+ * Use on focused full-page forms / wizards so the sidebar collapses when
9
+ * entering 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.
14
+ */
15
+ export function SidebarAutoCollapse() {
16
+ const { open, setOpen } = useSidebar()
17
+ const prevOpen = useRef(open)
18
+
19
+ useEffect(() => {
20
+ prevOpen.current = open
21
+ setOpen(false, { persist: false })
22
+ return () => { setOpen(prevOpen.current, { persist: false }) }
23
+ // eslint-disable-next-line react-hooks/exhaustive-deps
24
+ }, [])
25
+
26
+ return null
27
+ }
@@ -3,7 +3,8 @@
3
3
  import { useEffect, useRef } from "react"
4
4
  import { useSidebar } from "@/components/ui/sidebar"
5
5
 
6
- /** Reopens the sidebar once when the data-list page mounts (after returning from new-placement). */
6
+ /** Reopens the sidebar once on mount pair with `SidebarAutoCollapse` on focused
7
+ * full-page forms / wizards so leaving the form restores the sidebar. */
7
8
  export function SidebarAutoOpen() {
8
9
  const { setOpen } = useSidebar()
9
10
  const ran = useRef(false)
@@ -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>