@exxatdesignux/ui 0.2.18 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (618) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/bin/sync-extras.mjs +116 -29
  3. package/consumer-extras/README.md +43 -4
  4. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +39 -0
  5. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +26 -0
  6. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +21 -0
  7. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +21 -0
  8. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +44 -0
  9. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +32 -0
  10. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +22 -0
  11. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +53 -0
  12. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +41 -0
  13. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +25 -0
  14. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +22 -0
  15. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +56 -0
  16. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +31 -0
  17. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +100 -0
  18. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +28 -0
  19. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +21 -0
  20. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +31 -0
  21. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
  22. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
  23. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
  24. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
  25. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
  26. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
  27. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
  28. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -0
  29. package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +28 -0
  30. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +34 -0
  31. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +77 -0
  32. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +103 -0
  33. package/consumer-extras/cursor-skills/exxat-accessibility/SKILL.md +1 -1
  34. package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
  35. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +1 -1
  36. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +9 -9
  37. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
  38. package/consumer-extras/handbook/HANDBOOK.md +185 -0
  39. package/consumer-extras/handbook/glossary.md +57 -0
  40. package/consumer-extras/handbook/reference-implementations.md +126 -0
  41. package/consumer-extras/handbook/voice-and-tone.md +262 -0
  42. package/consumer-extras/patterns/command-menu-pattern.md +1 -1
  43. package/consumer-extras/patterns/data-views-pattern.md +14 -14
  44. package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
  45. package/dist/components/data-table/filter-date-calendar.js +280 -0
  46. package/dist/components/data-table/filter-date-calendar.js.map +1 -0
  47. package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
  48. package/dist/components/data-table/filter-text-value-input.js +561 -0
  49. package/dist/components/data-table/filter-text-value-input.js.map +1 -0
  50. package/dist/components/data-table/index.d.ts +45 -0
  51. package/dist/components/data-table/index.js +3085 -0
  52. package/dist/components/data-table/index.js.map +1 -0
  53. package/dist/components/data-table/pagination.d.ts +28 -0
  54. package/dist/components/data-table/pagination.js +3264 -0
  55. package/dist/components/data-table/pagination.js.map +1 -0
  56. package/dist/components/data-table/types.d.ts +84 -0
  57. package/dist/components/data-table/types.js +3 -0
  58. package/dist/components/data-table/types.js.map +1 -0
  59. package/dist/components/data-table/use-table-state.d.ts +116 -0
  60. package/dist/components/data-table/use-table-state.js +670 -0
  61. package/dist/components/data-table/use-table-state.js.map +1 -0
  62. package/dist/components/data-views/board-card-primitives.d.ts +22 -0
  63. package/dist/components/data-views/board-card-primitives.js +84 -0
  64. package/dist/components/data-views/board-card-primitives.js.map +1 -0
  65. package/dist/components/data-views/data-row-list.d.ts +33 -0
  66. package/dist/components/data-views/data-row-list.js +106 -0
  67. package/dist/components/data-views/data-row-list.js.map +1 -0
  68. package/dist/components/data-views/finder-panel-view.d.ts +54 -0
  69. package/dist/components/data-views/finder-panel-view.js +388 -0
  70. package/dist/components/data-views/finder-panel-view.js.map +1 -0
  71. package/dist/components/data-views/folder-grid-view.d.ts +22 -0
  72. package/dist/components/data-views/folder-grid-view.js +58 -0
  73. package/dist/components/data-views/folder-grid-view.js.map +1 -0
  74. package/dist/components/data-views/hub-table.d.ts +167 -0
  75. package/dist/components/data-views/hub-table.js +5561 -0
  76. package/dist/components/data-views/hub-table.js.map +1 -0
  77. package/dist/components/data-views/index.d.ts +27 -0
  78. package/dist/components/data-views/index.js +6575 -0
  79. package/dist/components/data-views/index.js.map +1 -0
  80. package/dist/components/data-views/list-page-board-card.d.ts +72 -0
  81. package/dist/components/data-views/list-page-board-card.js +264 -0
  82. package/dist/components/data-views/list-page-board-card.js.map +1 -0
  83. package/dist/components/data-views/list-page-board-template.d.ts +24 -0
  84. package/dist/components/data-views/list-page-board-template.js +137 -0
  85. package/dist/components/data-views/list-page-board-template.js.map +1 -0
  86. package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
  87. package/dist/components/data-views/list-page-connected-view-body.js +116 -0
  88. package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
  89. package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
  90. package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
  91. package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
  92. package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
  93. package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
  94. package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
  95. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
  96. package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
  97. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
  98. package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
  99. package/dist/components/data-views/list-page-tree-column-header.js +22 -0
  100. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
  101. package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
  102. package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
  103. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
  104. package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
  105. package/dist/components/data-views/os-folder-glyph.js +104 -0
  106. package/dist/components/data-views/os-folder-glyph.js.map +1 -0
  107. package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
  108. package/dist/components/data-views/outline-tree-menu.js +131 -0
  109. package/dist/components/data-views/outline-tree-menu.js.map +1 -0
  110. package/dist/components/table-properties/column-row.d.ts +22 -0
  111. package/dist/components/table-properties/column-row.js +153 -0
  112. package/dist/components/table-properties/column-row.js.map +1 -0
  113. package/dist/components/table-properties/draggable-list.d.ts +24 -0
  114. package/dist/components/table-properties/draggable-list.js +53 -0
  115. package/dist/components/table-properties/draggable-list.js.map +1 -0
  116. package/dist/components/table-properties/drawer-button.d.ts +110 -0
  117. package/dist/components/table-properties/drawer-button.js +2748 -0
  118. package/dist/components/table-properties/drawer-button.js.map +1 -0
  119. package/dist/components/table-properties/drawer.d.ts +100 -0
  120. package/dist/components/table-properties/drawer.js +2595 -0
  121. package/dist/components/table-properties/drawer.js.map +1 -0
  122. package/dist/components/table-properties/filter-card.d.ts +24 -0
  123. package/dist/components/table-properties/filter-card.js +854 -0
  124. package/dist/components/table-properties/filter-card.js.map +1 -0
  125. package/dist/components/table-properties/index.d.ts +14 -0
  126. package/dist/components/table-properties/index.js +2768 -0
  127. package/dist/components/table-properties/index.js.map +1 -0
  128. package/dist/components/table-properties/sort-card.d.ts +20 -0
  129. package/dist/components/table-properties/sort-card.js +102 -0
  130. package/dist/components/table-properties/sort-card.js.map +1 -0
  131. package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
  132. package/dist/components/templates/dedicated-search-landing-template.js +254 -0
  133. package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
  134. package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
  135. package/dist/components/templates/dedicated-search-results-template.js +16 -0
  136. package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
  137. package/dist/components/templates/index.d.ts +9 -0
  138. package/dist/components/templates/index.js +2720 -0
  139. package/dist/components/templates/index.js.map +1 -0
  140. package/dist/components/templates/list-page.d.ts +83 -0
  141. package/dist/components/templates/list-page.js +2433 -0
  142. package/dist/components/templates/list-page.js.map +1 -0
  143. package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
  144. package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
  145. package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
  146. package/dist/components/ui/accordion.d.ts +10 -0
  147. package/dist/components/ui/accordion.js +74 -0
  148. package/dist/components/ui/accordion.js.map +1 -0
  149. package/dist/components/ui/alert-dialog.d.ts +37 -0
  150. package/dist/components/ui/alert-dialog.js +201 -0
  151. package/dist/components/ui/alert-dialog.js.map +1 -0
  152. package/dist/components/ui/avatar.d.ts +84 -0
  153. package/dist/components/ui/avatar.js +328 -0
  154. package/dist/components/ui/avatar.js.map +1 -0
  155. package/dist/components/ui/badge.d.ts +13 -0
  156. package/dist/components/ui/badge.js +49 -0
  157. package/dist/components/ui/badge.js.map +1 -0
  158. package/dist/components/ui/banner.d.ts +62 -0
  159. package/dist/components/ui/banner.js +364 -0
  160. package/dist/components/ui/banner.js.map +1 -0
  161. package/dist/components/ui/breadcrumb.d.ts +14 -0
  162. package/dist/components/ui/breadcrumb.js +114 -0
  163. package/dist/components/ui/breadcrumb.js.map +1 -0
  164. package/dist/components/ui/button.d.ts +16 -0
  165. package/dist/components/ui/button.js +59 -0
  166. package/dist/components/ui/button.js.map +1 -0
  167. package/dist/components/ui/calendar.d.ts +13 -0
  168. package/dist/components/ui/calendar.js +238 -0
  169. package/dist/components/ui/calendar.js.map +1 -0
  170. package/dist/components/ui/card.d.ts +14 -0
  171. package/dist/components/ui/card.js +102 -0
  172. package/dist/components/ui/card.js.map +1 -0
  173. package/dist/components/ui/chart.d.ts +58 -0
  174. package/dist/components/ui/chart.js +292 -0
  175. package/dist/components/ui/chart.js.map +1 -0
  176. package/dist/components/ui/checkbox.d.ts +23 -0
  177. package/dist/components/ui/checkbox.js +155 -0
  178. package/dist/components/ui/checkbox.js.map +1 -0
  179. package/dist/components/ui/coach-mark.d.ts +27 -0
  180. package/dist/components/ui/coach-mark.js +306 -0
  181. package/dist/components/ui/coach-mark.js.map +1 -0
  182. package/dist/components/ui/collapsible.d.ts +8 -0
  183. package/dist/components/ui/collapsible.js +35 -0
  184. package/dist/components/ui/collapsible.js.map +1 -0
  185. package/dist/components/ui/command.d.ts +36 -0
  186. package/dist/components/ui/command.js +274 -0
  187. package/dist/components/ui/command.js.map +1 -0
  188. package/dist/components/ui/context-menu.d.ts +32 -0
  189. package/dist/components/ui/context-menu.js +245 -0
  190. package/dist/components/ui/context-menu.js.map +1 -0
  191. package/dist/components/ui/date-picker-field.d.ts +38 -0
  192. package/dist/components/ui/date-picker-field.js +550 -0
  193. package/dist/components/ui/date-picker-field.js.map +1 -0
  194. package/dist/components/ui/dialog.d.ts +22 -0
  195. package/dist/components/ui/dialog.js +200 -0
  196. package/dist/components/ui/dialog.js.map +1 -0
  197. package/dist/components/ui/dot-pattern.d.ts +21 -0
  198. package/dist/components/ui/dot-pattern.js +139 -0
  199. package/dist/components/ui/dot-pattern.js.map +1 -0
  200. package/dist/components/ui/drag-handle-grip.d.ts +10 -0
  201. package/dist/components/ui/drag-handle-grip.js +15 -0
  202. package/dist/components/ui/drag-handle-grip.js.map +1 -0
  203. package/dist/components/ui/drawer.d.ts +16 -0
  204. package/dist/components/ui/drawer.js +125 -0
  205. package/dist/components/ui/drawer.js.map +1 -0
  206. package/dist/components/ui/dropdown-menu.d.ts +45 -0
  207. package/dist/components/ui/dropdown-menu.js +353 -0
  208. package/dist/components/ui/dropdown-menu.js.map +1 -0
  209. package/dist/components/ui/export-drawer.d.ts +11 -0
  210. package/dist/components/ui/export-drawer.js +1658 -0
  211. package/dist/components/ui/export-drawer.js.map +1 -0
  212. package/dist/components/ui/field.d.ts +30 -0
  213. package/dist/components/ui/field.js +249 -0
  214. package/dist/components/ui/field.js.map +1 -0
  215. package/dist/components/ui/form.d.ts +28 -0
  216. package/dist/components/ui/form.js +110 -0
  217. package/dist/components/ui/form.js.map +1 -0
  218. package/dist/components/ui/hover-card.d.ts +9 -0
  219. package/dist/components/ui/hover-card.js +43 -0
  220. package/dist/components/ui/hover-card.js.map +1 -0
  221. package/dist/components/ui/input-group.d.ts +20 -0
  222. package/dist/components/ui/input-group.js +219 -0
  223. package/dist/components/ui/input-group.js.map +1 -0
  224. package/dist/components/ui/input-mask.d.ts +39 -0
  225. package/dist/components/ui/input-mask.js +118 -0
  226. package/dist/components/ui/input-mask.js.map +1 -0
  227. package/dist/components/ui/input.d.ts +5 -0
  228. package/dist/components/ui/input.js +30 -0
  229. package/dist/components/ui/input.js.map +1 -0
  230. package/dist/components/ui/kbd.d.ts +20 -0
  231. package/dist/components/ui/kbd.js +45 -0
  232. package/dist/components/ui/kbd.js.map +1 -0
  233. package/dist/components/ui/key-metrics-context.d.ts +19 -0
  234. package/dist/components/ui/key-metrics-context.js +26 -0
  235. package/dist/components/ui/key-metrics-context.js.map +1 -0
  236. package/dist/components/ui/key-metrics.d.ts +131 -0
  237. package/dist/components/ui/key-metrics.js +1015 -0
  238. package/dist/components/ui/key-metrics.js.map +1 -0
  239. package/dist/components/ui/label.d.ts +6 -0
  240. package/dist/components/ui/label.js +28 -0
  241. package/dist/components/ui/label.js.map +1 -0
  242. package/dist/components/ui/list-page-view-frame.d.ts +22 -0
  243. package/dist/components/ui/list-page-view-frame.js +24 -0
  244. package/dist/components/ui/list-page-view-frame.js.map +1 -0
  245. package/dist/components/ui/page-header.d.ts +51 -0
  246. package/dist/components/ui/page-header.js +372 -0
  247. package/dist/components/ui/page-header.js.map +1 -0
  248. package/dist/components/ui/payment-card-fields.d.ts +10 -0
  249. package/dist/components/ui/payment-card-fields.js +80 -0
  250. package/dist/components/ui/payment-card-fields.js.map +1 -0
  251. package/dist/components/ui/popover.d.ts +10 -0
  252. package/dist/components/ui/popover.js +47 -0
  253. package/dist/components/ui/popover.js.map +1 -0
  254. package/dist/components/ui/radio-group.d.ts +29 -0
  255. package/dist/components/ui/radio-group.js +190 -0
  256. package/dist/components/ui/radio-group.js.map +1 -0
  257. package/dist/components/ui/resizable.d.ts +16 -0
  258. package/dist/components/ui/resizable.js +51 -0
  259. package/dist/components/ui/resizable.js.map +1 -0
  260. package/dist/components/ui/scroll-area.d.ts +8 -0
  261. package/dist/components/ui/scroll-area.js +66 -0
  262. package/dist/components/ui/scroll-area.js.map +1 -0
  263. package/dist/components/ui/select.d.ts +18 -0
  264. package/dist/components/ui/select.js +186 -0
  265. package/dist/components/ui/select.js.map +1 -0
  266. package/dist/components/ui/selection-tile-grid.d.ts +52 -0
  267. package/dist/components/ui/selection-tile-grid.js +347 -0
  268. package/dist/components/ui/selection-tile-grid.js.map +1 -0
  269. package/dist/components/ui/separator.d.ts +7 -0
  270. package/dist/components/ui/separator.js +33 -0
  271. package/dist/components/ui/separator.js.map +1 -0
  272. package/dist/components/ui/sheet.d.ts +18 -0
  273. package/dist/components/ui/sheet.js +181 -0
  274. package/dist/components/ui/sheet.js.map +1 -0
  275. package/dist/components/ui/sidebar.d.ts +94 -0
  276. package/dist/components/ui/sidebar.js +805 -0
  277. package/dist/components/ui/sidebar.js.map +1 -0
  278. package/dist/components/ui/skeleton.d.ts +5 -0
  279. package/dist/components/ui/skeleton.js +22 -0
  280. package/dist/components/ui/skeleton.js.map +1 -0
  281. package/dist/components/ui/slider.d.ts +7 -0
  282. package/dist/components/ui/slider.js +66 -0
  283. package/dist/components/ui/slider.js.map +1 -0
  284. package/dist/components/ui/sonner.d.ts +6 -0
  285. package/dist/components/ui/sonner.js +38 -0
  286. package/dist/components/ui/sonner.js.map +1 -0
  287. package/dist/components/ui/status-badge.d.ts +38 -0
  288. package/dist/components/ui/status-badge.js +77 -0
  289. package/dist/components/ui/status-badge.js.map +1 -0
  290. package/dist/components/ui/table.d.ts +13 -0
  291. package/dist/components/ui/table.js +115 -0
  292. package/dist/components/ui/table.js.map +1 -0
  293. package/dist/components/ui/tabs.d.ts +15 -0
  294. package/dist/components/ui/tabs.js +93 -0
  295. package/dist/components/ui/tabs.js.map +1 -0
  296. package/dist/components/ui/textarea.d.ts +6 -0
  297. package/dist/components/ui/textarea.js +25 -0
  298. package/dist/components/ui/textarea.js.map +1 -0
  299. package/dist/components/ui/tip.d.ts +12 -0
  300. package/dist/components/ui/tip.js +61 -0
  301. package/dist/components/ui/tip.js.map +1 -0
  302. package/dist/components/ui/toggle-group.d.ts +14 -0
  303. package/dist/components/ui/toggle-group.js +104 -0
  304. package/dist/components/ui/toggle-group.js.map +1 -0
  305. package/dist/components/ui/toggle-switch.d.ts +10 -0
  306. package/dist/components/ui/toggle-switch.js +33 -0
  307. package/dist/components/ui/toggle-switch.js.map +1 -0
  308. package/dist/components/ui/toggle.d.ts +13 -0
  309. package/dist/components/ui/toggle.js +51 -0
  310. package/dist/components/ui/toggle.js.map +1 -0
  311. package/dist/components/ui/tooltip.d.ts +10 -0
  312. package/dist/components/ui/tooltip.js +68 -0
  313. package/dist/components/ui/tooltip.js.map +1 -0
  314. package/dist/components/ui/view-segmented-control.d.ts +31 -0
  315. package/dist/components/ui/view-segmented-control.js +167 -0
  316. package/dist/components/ui/view-segmented-control.js.map +1 -0
  317. package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
  318. package/dist/hooks/use-app-theme.d.ts +24 -0
  319. package/dist/hooks/use-app-theme.js +286 -0
  320. package/dist/hooks/use-app-theme.js.map +1 -0
  321. package/dist/hooks/use-coach-mark.d.ts +86 -0
  322. package/dist/hooks/use-coach-mark.js +218 -0
  323. package/dist/hooks/use-coach-mark.js.map +1 -0
  324. package/dist/hooks/use-mobile.d.ts +3 -0
  325. package/dist/hooks/use-mobile.js +29 -0
  326. package/dist/hooks/use-mobile.js.map +1 -0
  327. package/dist/hooks/use-mod-key-label.d.ts +6 -0
  328. package/dist/hooks/use-mod-key-label.js +25 -0
  329. package/dist/hooks/use-mod-key-label.js.map +1 -0
  330. package/dist/index.d.ts +120 -0
  331. package/dist/index.js +13324 -0
  332. package/dist/index.js.map +1 -0
  333. package/dist/lib/compose-refs.d.ts +6 -0
  334. package/dist/lib/compose-refs.js +17 -0
  335. package/dist/lib/compose-refs.js.map +1 -0
  336. package/dist/lib/conditional-rule-match.d.ts +30 -0
  337. package/dist/lib/conditional-rule-match.js +66 -0
  338. package/dist/lib/conditional-rule-match.js.map +1 -0
  339. package/dist/lib/data-list-display-options.d.ts +26 -0
  340. package/dist/lib/data-list-display-options.js +14 -0
  341. package/dist/lib/data-list-display-options.js.map +1 -0
  342. package/dist/lib/data-list-view-registry.d.ts +2 -0
  343. package/dist/lib/data-list-view-registry.js +102 -0
  344. package/dist/lib/data-list-view-registry.js.map +1 -0
  345. package/dist/lib/data-list-view-surface.d.ts +2 -0
  346. package/dist/lib/data-list-view-surface.js +80 -0
  347. package/dist/lib/data-list-view-surface.js.map +1 -0
  348. package/dist/lib/data-list-view.d.ts +21 -0
  349. package/dist/lib/data-list-view.js +25 -0
  350. package/dist/lib/data-list-view.js.map +1 -0
  351. package/dist/lib/date-filter.d.ts +22 -0
  352. package/dist/lib/date-filter.js +61 -0
  353. package/dist/lib/date-filter.js.map +1 -0
  354. package/dist/lib/dev-log.d.ts +8 -0
  355. package/dist/lib/dev-log.js +10 -0
  356. package/dist/lib/dev-log.js.map +1 -0
  357. package/dist/lib/dropdown-menu-surface.d.ts +14 -0
  358. package/dist/lib/dropdown-menu-surface.js +6 -0
  359. package/dist/lib/dropdown-menu-surface.js.map +1 -0
  360. package/dist/lib/editable-target.d.ts +12 -0
  361. package/dist/lib/editable-target.js +12 -0
  362. package/dist/lib/editable-target.js.map +1 -0
  363. package/dist/lib/list-page-table-properties.d.ts +35 -0
  364. package/dist/lib/list-page-table-properties.js +81 -0
  365. package/dist/lib/list-page-table-properties.js.map +1 -0
  366. package/dist/lib/raf-throttle.d.ts +23 -0
  367. package/dist/lib/raf-throttle.js +27 -0
  368. package/dist/lib/raf-throttle.js.map +1 -0
  369. package/dist/lib/row-height.d.ts +16 -0
  370. package/dist/lib/row-height.js +10 -0
  371. package/dist/lib/row-height.js.map +1 -0
  372. package/dist/lib/table-properties-types.d.ts +83 -0
  373. package/dist/lib/table-properties-types.js +19 -0
  374. package/dist/lib/table-properties-types.js.map +1 -0
  375. package/dist/lib/utils.d.ts +5 -0
  376. package/dist/lib/utils.js +11 -0
  377. package/dist/lib/utils.js.map +1 -0
  378. package/package.json +83 -18
  379. package/src/components/data-table/filter-date-calendar.tsx +38 -0
  380. package/src/components/data-table/filter-text-value-input.tsx +77 -0
  381. package/src/components/data-table/index.tsx +1678 -0
  382. package/src/components/data-table/pagination.tsx +255 -0
  383. package/src/components/data-table/types.ts +96 -0
  384. package/src/components/data-table/use-table-state.ts +767 -0
  385. package/src/components/data-views/board-card-primitives.tsx +93 -0
  386. package/src/components/data-views/data-row-list.tsx +183 -0
  387. package/src/components/data-views/finder-panel-view.tsx +405 -0
  388. package/src/components/data-views/folder-grid-view.tsx +86 -0
  389. package/src/components/data-views/hub-table.tsx +498 -0
  390. package/src/components/data-views/index.ts +28 -0
  391. package/src/components/data-views/list-page-board-card.tsx +192 -0
  392. package/src/components/data-views/list-page-board-template.tsx +122 -0
  393. package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
  394. package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
  395. package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
  396. package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
  397. package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
  398. package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
  399. package/src/components/data-views/os-folder-glyph.tsx +141 -0
  400. package/src/components/data-views/outline-tree-menu.tsx +157 -0
  401. package/src/components/table-properties/column-row.tsx +90 -0
  402. package/src/components/table-properties/draggable-list.ts +54 -0
  403. package/src/components/table-properties/drawer-button.tsx +300 -0
  404. package/src/components/table-properties/drawer.tsx +1148 -0
  405. package/src/components/table-properties/filter-card.tsx +251 -0
  406. package/src/components/table-properties/index.ts +36 -0
  407. package/src/components/table-properties/sort-card.tsx +63 -0
  408. package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
  409. package/src/components/templates/dedicated-search-results-template.tsx +19 -0
  410. package/src/components/templates/index.ts +33 -0
  411. package/src/components/templates/list-page.tsx +602 -0
  412. package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
  413. package/src/components/ui/accordion.tsx +92 -0
  414. package/src/components/ui/alert-dialog.tsx +221 -0
  415. package/src/components/ui/avatar.tsx +13 -2
  416. package/src/components/ui/banner.tsx +2 -2
  417. package/src/components/ui/calendar.tsx +1 -1
  418. package/src/components/ui/coach-mark.tsx +1 -1
  419. package/src/components/ui/context-menu.tsx +291 -0
  420. package/src/components/ui/date-picker-field.tsx +2 -2
  421. package/src/components/ui/dot-pattern.tsx +183 -0
  422. package/src/components/ui/export-drawer.tsx +375 -0
  423. package/src/components/ui/hover-card.tsx +66 -0
  424. package/src/components/ui/key-metrics-context.tsx +78 -0
  425. package/src/components/ui/key-metrics.tsx +1133 -0
  426. package/src/components/ui/list-page-view-frame.tsx +64 -0
  427. package/src/components/ui/page-header.tsx +244 -0
  428. package/src/components/ui/payment-card-fields.tsx +2 -2
  429. package/src/components/ui/resizable.tsx +68 -0
  430. package/src/components/ui/scroll-area.tsx +72 -0
  431. package/src/components/ui/selection-tile-grid.tsx +9 -2
  432. package/src/components/ui/sidebar.tsx +84 -12
  433. package/src/components/ui/slider.tsx +83 -0
  434. package/src/globals.css +494 -151
  435. package/src/globals.d.ts +20 -0
  436. package/src/index.ts +68 -1
  437. package/src/lib/conditional-rule-match.ts +119 -0
  438. package/src/lib/data-list-display-options.ts +35 -0
  439. package/src/lib/data-list-view-registry.ts +104 -0
  440. package/src/lib/data-list-view-surface.ts +83 -0
  441. package/src/lib/data-list-view.ts +47 -0
  442. package/src/lib/dev-log.ts +10 -0
  443. package/src/lib/editable-target.ts +20 -0
  444. package/src/lib/list-page-table-properties.ts +48 -0
  445. package/src/lib/raf-throttle.ts +45 -0
  446. package/src/lib/row-height.ts +19 -0
  447. package/src/lib/table-properties-types.ts +98 -0
  448. package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
  449. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
  450. package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
  451. package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
  452. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
  453. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  454. package/template/AGENTS.md +84 -20
  455. package/template/app/(app)/examples/page.tsx +0 -1
  456. package/template/app/(app)/layout.tsx +17 -4
  457. package/template/app/(app)/question-bank/layout.tsx +1 -1
  458. package/template/app/(app)/question-bank/new/page.tsx +11 -24
  459. package/template/app/globals.css +13 -1972
  460. package/template/components/ask-leo-sidebar.tsx +5 -1
  461. package/template/components/brand-color-picker.tsx +2 -2
  462. package/template/components/charts-overview.tsx +1 -1
  463. package/template/components/compliance-table.tsx +240 -384
  464. package/template/components/dashboard-report-charts.tsx +1 -1
  465. package/template/components/dashboard-tabs.tsx +1 -1
  466. package/template/components/data-table/filter-date-calendar.tsx +1 -38
  467. package/template/components/data-table/filter-text-value-input.tsx +1 -77
  468. package/template/components/data-table/index.tsx +1 -1634
  469. package/template/components/data-table/pagination.tsx +1 -255
  470. package/template/components/data-table/types.ts +1 -94
  471. package/template/components/data-table/use-table-state.test.ts +420 -0
  472. package/template/components/data-table/use-table-state.ts +1 -758
  473. package/template/components/data-view-dashboard-charts-compliance.tsx +2 -2
  474. package/template/components/data-view-dashboard-charts-team.tsx +2 -2
  475. package/template/components/data-view-dashboard-charts.tsx +2 -2
  476. package/template/components/data-views/board-card-primitives.tsx +1 -93
  477. package/template/components/data-views/data-row-list.tsx +1 -183
  478. package/template/components/data-views/finder-panel-view.tsx +1 -405
  479. package/template/components/data-views/folder-grid-view.tsx +1 -86
  480. package/template/components/data-views/hub-table.tsx +1 -0
  481. package/template/components/data-views/index.ts +42 -1
  482. package/template/components/data-views/list-page-board-card.tsx +1 -192
  483. package/template/components/data-views/list-page-board-template.tsx +1 -122
  484. package/template/components/data-views/list-page-connected-view-body.tsx +1 -0
  485. package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
  486. package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -60
  487. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
  488. package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
  489. package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
  490. package/template/components/data-views/list-page-view-frame.tsx +5 -53
  491. package/template/components/data-views/os-folder-glyph.tsx +1 -129
  492. package/template/components/data-views/outline-tree-menu.tsx +1 -157
  493. package/template/components/export-drawer.test.tsx +71 -0
  494. package/template/components/export-drawer.tsx +1 -375
  495. package/template/components/exxat-product-logo.tsx +5 -5
  496. package/template/components/hub-tree-panel-view.tsx +2 -2
  497. package/template/components/invite-collaborators-drawer.tsx +3 -3
  498. package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
  499. package/template/components/key-metrics.tsx +1 -1063
  500. package/template/components/leo-insight-indicator.tsx +2 -2
  501. package/template/components/new-placement-back-btn.tsx +1 -1
  502. package/template/components/new-placement-form.tsx +63 -189
  503. package/template/components/new-question-composer.tsx +432 -402
  504. package/template/components/onboarding/index.ts +9 -0
  505. package/template/components/onboarding/onboarding-01.tsx +1 -1
  506. package/template/components/onboarding/onboarding-02.tsx +1 -1
  507. package/template/components/onboarding/onboarding-03.tsx +1 -1
  508. package/template/components/onboarding/onboarding-04.tsx +1 -1
  509. package/template/components/page-header.tsx +8 -226
  510. package/template/components/placement-board-card.tsx +71 -83
  511. package/template/components/placements-board-view.tsx +3 -10
  512. package/template/components/placements-client.tsx +10 -42
  513. package/template/components/placements-list-view.tsx +22 -69
  514. package/template/components/placements-table-columns.tsx +8 -438
  515. package/template/components/placements-table.tsx +588 -1296
  516. package/template/components/product-switcher.tsx +1 -1
  517. package/template/components/product-wordmark.tsx +2 -1
  518. package/template/components/question-bank-client.tsx +4 -1
  519. package/template/components/question-bank-hub-client.tsx +1 -1
  520. package/template/components/question-bank-new-folder-sheet.tsx +2 -2
  521. package/template/components/question-bank-secondary-nav.tsx +3 -3
  522. package/template/components/question-bank-table.tsx +294 -526
  523. package/template/components/rotations-empty-state.tsx +1 -1
  524. package/template/components/rotations-panel-activator.tsx +1 -1
  525. package/template/components/settings-appearance-card.tsx +1 -1
  526. package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
  527. package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +4 -4
  528. package/template/components/sidebar/index.ts +16 -0
  529. package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
  530. package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +6 -3
  531. package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
  532. package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
  533. package/template/components/site-header.tsx +1 -1
  534. package/template/components/{sites-all-client.tsx → sites-client.tsx} +1 -1
  535. package/template/components/sites-table.tsx +124 -257
  536. package/template/components/table-properties/column-row.tsx +1 -90
  537. package/template/components/table-properties/draggable-list.ts +1 -49
  538. package/template/components/table-properties/drawer-button.tsx +1 -249
  539. package/template/components/table-properties/drawer.tsx +1 -1105
  540. package/template/components/table-properties/filter-card.tsx +1 -251
  541. package/template/components/table-properties/sort-card.tsx +1 -59
  542. package/template/components/table-properties/types.ts +28 -71
  543. package/template/components/team-table.tsx +242 -382
  544. package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
  545. package/template/components/templates/dedicated-search-results-template.tsx +1 -19
  546. package/template/components/templates/list-page.tsx +1 -584
  547. package/template/components/templates/nested-secondary-panel-shell.tsx +1 -62
  548. package/template/components/templates/new-focus-template.tsx +659 -0
  549. package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
  550. package/template/components/ui/accordion.tsx +1 -0
  551. package/template/components/ui/alert-dialog.tsx +1 -0
  552. package/template/components/ui/context-menu.tsx +1 -0
  553. package/template/components/ui/dot-pattern.tsx +1 -183
  554. package/template/components/ui/hover-card.tsx +1 -0
  555. package/template/components/ui/resizable.tsx +1 -68
  556. package/template/components/ui/scroll-area.tsx +1 -0
  557. package/template/components/ui/slider.tsx +1 -0
  558. package/template/docs/blueprints/README.md +86 -0
  559. package/template/docs/blueprints/_template.md +91 -0
  560. package/template/docs/blueprints/board-card.md +123 -0
  561. package/template/docs/blueprints/data-table.md +139 -0
  562. package/template/docs/blueprints/key-metrics.md +128 -0
  563. package/template/docs/blueprints/list-page-template.md +123 -0
  564. package/template/docs/blueprints/page-header.md +130 -0
  565. package/template/docs/command-menu-pattern.md +1 -1
  566. package/template/docs/component-selection-guide.md +224 -0
  567. package/template/docs/components-audit-2026-05.md +158 -0
  568. package/template/docs/data-views-pattern.md +14 -14
  569. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
  570. package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
  571. package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
  572. package/template/docs/migrations/README.md +100 -0
  573. package/template/docs/migrations/_template.md +64 -0
  574. package/template/docs/token-taxonomy.md +416 -0
  575. package/template/eslint.config.mjs +27 -0
  576. package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
  577. package/template/lib/command-menu-config.ts +0 -1
  578. package/template/lib/compliance-supported-views.ts +10 -0
  579. package/template/lib/conditional-rule-match.ts +6 -97
  580. package/template/lib/data-list-display-options.ts +1 -35
  581. package/template/lib/data-list-view-registry.ts +1 -0
  582. package/template/lib/data-list-view-surface.ts +1 -69
  583. package/template/lib/data-list-view.ts +1 -38
  584. package/template/lib/dev-log.ts +1 -8
  585. package/template/lib/editable-target.ts +1 -10
  586. package/template/lib/hub-connected-view-renderers.ts +58 -0
  587. package/template/lib/list-hub-supported-views.ts +10 -0
  588. package/template/lib/list-page-table-properties.ts +1 -52
  589. package/template/lib/mock/navigation.tsx +0 -8
  590. package/template/lib/mock/placements.ts +0 -7
  591. package/template/lib/placement-board-card-layout.ts +41 -41
  592. package/template/lib/placements-supported-views.ts +12 -0
  593. package/template/lib/question-bank-supported-views.ts +12 -0
  594. package/template/lib/raf-throttle.ts +1 -45
  595. package/template/lib/row-height.ts +4 -10
  596. package/template/lib/sidebar-state-cookie.ts +11 -2
  597. package/template/lib/sites-supported-views.ts +10 -0
  598. package/template/lib/team-supported-views.ts +10 -0
  599. package/template/package.json +1 -0
  600. package/template/tests/setup.ts +25 -0
  601. package/src/theme.css +0 -1132
  602. package/template/app/(app)/data-list/[id]/page.tsx +0 -44
  603. package/template/app/(app)/data-list/new/page.tsx +0 -34
  604. package/template/app/(app)/data-list/page.tsx +0 -10
  605. package/template/components/compliance-list-view.tsx +0 -54
  606. package/template/components/dashboard-onboarding-gallery.tsx +0 -13
  607. package/template/components/dashboard-onboarding.tsx +0 -21
  608. package/template/components/question-bank-list-view.tsx +0 -53
  609. package/template/components/section-cards.tsx +0 -106
  610. package/template/components/sites-list-view.tsx +0 -42
  611. package/template/components/team-list-view.tsx +0 -59
  612. package/template/lib/placement-lifecycle.ts +0 -5
  613. /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
  614. /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
  615. /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
  616. /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
  617. /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
  618. /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
@@ -0,0 +1,64 @@
1
+ "use client"
2
+
3
+ /**
4
+ * ListPageViewFrame — shared horizontal gutter + optional centered max-width
5
+ * for list-hub **view bodies** (folder icon grid, finder panel chrome,
6
+ * OS-style folder explorer, dashboard slices, etc.).
7
+ *
8
+ * MUST be used instead of ad-hoc `mx-4 lg:mx-6` + `mx-auto max-w-*` pairs on
9
+ * each page — see `apps/web/AGENTS.md` §4.5 and
10
+ * `.cursor/rules/exxat-list-page-view-shells.mdc`.
11
+ *
12
+ * MUST NOT wrap `DataTable` when its toolbar already applies the same inset
13
+ * (avoid double gutter); use this for **non-table** view branches or
14
+ * **sections below** the shared toolbar.
15
+ *
16
+ * Promotion note: this file lived at
17
+ * `apps/web/components/data-views/list-page-view-frame.tsx` until
18
+ * 2026-05-20. It moved into `@exxatdesignux/ui` because the gutter / max-
19
+ * width contract is entity-agnostic and other consumers (a future docs
20
+ * site, partner apps) need the same rhythm without dragging in the whole
21
+ * `data-views/` family.
22
+ */
23
+
24
+ import * as React from "react"
25
+
26
+ import { cn } from "../../lib/utils"
27
+
28
+ /** Default horizontal rhythm for view bodies under `ListPageTemplate` (matches `FolderGridView`). */
29
+ export const LIST_PAGE_VIEW_FRAME_GUTTER = "mx-4 mb-6 lg:mx-6"
30
+
31
+ /** Typical max width for icon grids / dense tile views on ultra-wide monitors. */
32
+ export const LIST_PAGE_VIEW_FRAME_MAX_ICON_GRID = "max-w-6xl"
33
+
34
+ /** Slightly wider shell when a view includes toolbar + breadcrumbs + grid (e.g. OS folder explorer). */
35
+ export const LIST_PAGE_VIEW_FRAME_MAX_WIDE = "max-w-7xl"
36
+
37
+ export interface ListPageViewFrameProps extends React.HTMLAttributes<HTMLDivElement> {
38
+ children: React.ReactNode
39
+ /**
40
+ * When set, children are wrapped in `mx-auto w-full min-w-0` + this
41
+ * max-width so the block stays centered inside the primary page column.
42
+ */
43
+ maxWidthClassName?: string
44
+ /** Override outer gutter; default `LIST_PAGE_VIEW_FRAME_GUTTER`. */
45
+ gutterClassName?: string
46
+ }
47
+
48
+ export function ListPageViewFrame({
49
+ children,
50
+ className,
51
+ maxWidthClassName,
52
+ gutterClassName = LIST_PAGE_VIEW_FRAME_GUTTER,
53
+ ...rest
54
+ }: ListPageViewFrameProps) {
55
+ return (
56
+ <div className={cn(gutterClassName, className)} {...rest}>
57
+ {maxWidthClassName ? (
58
+ <div className={cn("mx-auto w-full min-w-0", maxWidthClassName)}>{children}</div>
59
+ ) : (
60
+ children
61
+ )}
62
+ </div>
63
+ )
64
+ }
@@ -0,0 +1,244 @@
1
+ "use client"
2
+
3
+ /**
4
+ * PageHeader — Full-width content area header.
5
+ *
6
+ * Sits at the top of a page's main content, BELOW the breadcrumb / topbar.
7
+ * Uses Ivy Presto (Adobe Fonts) for the title via the `--font-heading`
8
+ * CSS variable.
9
+ *
10
+ * **Variant `collaboration`** — optional access line + collaborator faces
11
+ * (or **Add collaborator** when the roster is empty) ahead of the primary
12
+ * `actions` slot. The full **Invite people** flow lives in the consuming
13
+ * page's `actions` overflow menu — this primitive only renders the face row.
14
+ *
15
+ * WCAG 2.1 AA:
16
+ * - `<h1>` landmark — one per page (WCAG 1.3.1)
17
+ * - Sufficient colour contrast >= 4.5:1 on title + subtitle (SC 1.4.3)
18
+ * - Face row: `role="group"` + aggregate `aria-label`; each face has a
19
+ * `Tooltip` name (SC 4.1.2)
20
+ *
21
+ * Promotion note: this file lived at `apps/web/components/page-header.tsx`
22
+ * until 2026-05-20. It moved into `@exxatdesignux/ui` so other apps (and
23
+ * future docs sites) can compose hub headers without duplicating the
24
+ * collaboration variant, h1 styling, or face-row a11y wiring. The
25
+ * `CollaboratorAccessRole` union is duplicated here as a narrow string
26
+ * literal so the primitive stays free of `apps/web/lib/` couplings — the
27
+ * authoritative role labels / icons / capability helpers continue to live
28
+ * in `apps/web/lib/collaborator-access.ts`.
29
+ */
30
+
31
+ import * as React from "react"
32
+
33
+ import { Avatar, AvatarFallback, AvatarImage } from "./avatar"
34
+ import { Button } from "./button"
35
+ import { Separator } from "./separator"
36
+ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip"
37
+ import { cn } from "../../lib/utils"
38
+
39
+ /**
40
+ * Library access role for shared hubs. Mirrors
41
+ * `apps/web/lib/collaborator-access.ts > CollaboratorAccessRole` — kept
42
+ * structurally identical so the apps/web type and this type are mutually
43
+ * assignable wherever consumers pass collaborator rosters to `PageHeader`.
44
+ */
45
+ export type PageHeaderCollaboratorAccessRole =
46
+ | "owner"
47
+ | "editor"
48
+ | "commenter"
49
+ | "viewer"
50
+
51
+ export type PageHeaderVariant = "default" | "collaboration"
52
+
53
+ export interface PageHeaderCollaborator {
54
+ id: string
55
+ name: string
56
+ imageUrl?: string | null
57
+ initials?: string
58
+ email?: string
59
+ access?: PageHeaderCollaboratorAccessRole
60
+ /** Org / directory role tags (e.g. Faculty, Program coordinator). */
61
+ roles?: string[]
62
+ }
63
+
64
+ export interface PageHeaderProps {
65
+ /** Primary page title — rendered as `<h1>` in Ivy Presto serif. */
66
+ title: string
67
+ /** Short descriptor or date shown below the title (and below `accessInfo` when set). */
68
+ subtitle?: React.ReactNode
69
+ /** Layout preset — `collaboration` enables access line + face row ahead of `actions`. */
70
+ variant?: PageHeaderVariant
71
+ /**
72
+ * Role / access copy or badges — rendered between the title and subtitle
73
+ * when `variant="collaboration"` (e.g. lock icon + "Editors can modify").
74
+ */
75
+ accessInfo?: React.ReactNode
76
+ /** People with access — shown as a horizontal row of faces when `variant="collaboration"`. */
77
+ collaborators?: PageHeaderCollaborator[]
78
+ /** Max faces before a `+N` chip — default 3. */
79
+ collaboratorDisplayLimit?: number
80
+ /** Opens the invite collaborators sheet when a face, overflow chip, or empty-state CTA is activated. */
81
+ onCollaboratorsOpen?: () => void
82
+ /** Label for the empty-roster header control — default `"Add collaborator"`. */
83
+ addCollaboratorLabel?: string
84
+ /** Optional slot for right-aligned actions (buttons, selectors, etc.). */
85
+ actions?: React.ReactNode
86
+ /** Extra className for the outer wrapper. */
87
+ className?: string
88
+ /** When false, the title + subtitle are visually hidden (actions remain). */
89
+ showTitleBlock?: boolean
90
+ }
91
+
92
+ function PageHeaderCollaborationAccess({
93
+ people,
94
+ limit,
95
+ onOpenCollaborators,
96
+ addCollaboratorLabel,
97
+ }: {
98
+ people: PageHeaderCollaborator[]
99
+ limit: number
100
+ onOpenCollaborators?: () => void
101
+ addCollaboratorLabel: string
102
+ }) {
103
+ if (people.length === 0) {
104
+ return (
105
+ <div
106
+ role="group"
107
+ aria-label="People with access"
108
+ className="flex shrink-0 items-center"
109
+ >
110
+ <Button
111
+ type="button"
112
+ variant="outline"
113
+ size="lg"
114
+ onClick={onOpenCollaborators}
115
+ disabled={!onOpenCollaborators}
116
+ >
117
+ <i className="fa-light fa-user-plus" aria-hidden="true" />
118
+ {addCollaboratorLabel}
119
+ </Button>
120
+ </div>
121
+ )
122
+ }
123
+
124
+ const visible = people.slice(0, limit)
125
+ const overflow = Math.max(0, people.length - visible.length)
126
+ const names = people.map((p) => p.name).join(", ")
127
+
128
+ return (
129
+ <div
130
+ role="group"
131
+ aria-label={names ? `People with access: ${names}` : "People with access"}
132
+ className="flex shrink-0 items-center gap-2 sm:gap-2.5"
133
+ >
134
+ <div className="flex shrink-0 items-center gap-1.5">
135
+ {visible.map((c) => (
136
+ <Tooltip key={c.id}>
137
+ <TooltipTrigger asChild>
138
+ <button
139
+ type="button"
140
+ className="relative shrink-0 rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
141
+ aria-label={`Open collaborators — ${c.name}`}
142
+ onClick={onOpenCollaborators}
143
+ disabled={!onOpenCollaborators}
144
+ >
145
+ <Avatar size="sm" shape="circle" className="pointer-events-none">
146
+ {c.imageUrl ? (
147
+ <AvatarImage src={c.imageUrl} alt="" referrerPolicy="no-referrer" />
148
+ ) : null}
149
+ <AvatarFallback className="text-xs font-semibold">
150
+ {(c.initials ?? c.name.slice(0, 2)).toUpperCase()}
151
+ </AvatarFallback>
152
+ </Avatar>
153
+ </button>
154
+ </TooltipTrigger>
155
+ <TooltipContent side="bottom">{c.name}</TooltipContent>
156
+ </Tooltip>
157
+ ))}
158
+ {overflow > 0 && (
159
+ <button
160
+ type="button"
161
+ className="flex size-6 shrink-0 items-center justify-center rounded-full bg-muted text-[11px] font-semibold tabular-nums text-muted-foreground ring-1 ring-border/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
162
+ aria-label={`Open collaborators — ${overflow} more people with access`}
163
+ onClick={onOpenCollaborators}
164
+ disabled={!onOpenCollaborators}
165
+ >
166
+ +{overflow}
167
+ </button>
168
+ )}
169
+ </div>
170
+ </div>
171
+ )
172
+ }
173
+
174
+ export function PageHeader({
175
+ title,
176
+ subtitle,
177
+ variant = "default",
178
+ accessInfo,
179
+ collaborators,
180
+ collaboratorDisplayLimit = 3,
181
+ onCollaboratorsOpen,
182
+ addCollaboratorLabel = "Add collaborator",
183
+ actions,
184
+ className,
185
+ showTitleBlock = true,
186
+ }: PageHeaderProps) {
187
+ const isCollaboration = variant === "collaboration"
188
+ const showAccess = Boolean(isCollaboration && accessInfo)
189
+ const showCollaborationAccess = isCollaboration
190
+ const showActionsColumn = Boolean(actions) || showCollaborationAccess
191
+ const showCollaboratorActionsSeparator =
192
+ showCollaborationAccess && Boolean(actions)
193
+
194
+ return (
195
+ <div
196
+ className={cn(
197
+ "flex flex-col gap-1 px-4 pt-2 pb-4 lg:px-6",
198
+ "sm:flex-row sm:items-end sm:gap-4",
199
+ showTitleBlock ? "sm:justify-between" : "sm:justify-end",
200
+ className,
201
+ )}
202
+ >
203
+ {/* Title block — hidden visually when showTitleBlock is false; keep h1 for a11y. */}
204
+ <div className={cn("flex min-w-0 flex-col gap-0.5", !showTitleBlock && "sr-only")}>
205
+ <h1
206
+ className="text-2xl font-semibold tracking-tight leading-tight text-foreground"
207
+ style={{ fontFamily: "var(--font-heading)" }}
208
+ suppressHydrationWarning
209
+ >
210
+ {title}
211
+ </h1>
212
+ {showAccess && (
213
+ <div className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-snug text-muted-foreground">
214
+ {accessInfo}
215
+ </div>
216
+ )}
217
+ {subtitle && (
218
+ <p className="text-sm text-muted-foreground leading-none">{subtitle}</p>
219
+ )}
220
+ </div>
221
+
222
+ {showActionsColumn && (
223
+ <div className="flex flex-wrap items-center gap-2 sm:gap-3 shrink-0 sm:ms-auto sm:justify-end">
224
+ {showCollaborationAccess ? (
225
+ <PageHeaderCollaborationAccess
226
+ people={collaborators ?? []}
227
+ limit={collaboratorDisplayLimit}
228
+ onOpenCollaborators={onCollaboratorsOpen}
229
+ addCollaboratorLabel={addCollaboratorLabel}
230
+ />
231
+ ) : null}
232
+ {showCollaboratorActionsSeparator ? (
233
+ <Separator
234
+ orientation="vertical"
235
+ decorative
236
+ className="h-8 shrink-0"
237
+ />
238
+ ) : null}
239
+ {actions}
240
+ </div>
241
+ )}
242
+ </div>
243
+ )
244
+ }
@@ -49,14 +49,14 @@ export function PaymentCardFieldsGroup({ className }: { className?: string }) {
49
49
  <Input
50
50
  {...getExpiryDateProps()}
51
51
  id={`card-expiry-${id}`}
52
- className="rounded-t-none rounded-r-none shadow-none"
52
+ className="rounded-t-none rounded-e-none shadow-none"
53
53
  />
54
54
  </div>
55
55
  <div className="-ms-px min-w-0 flex-1 focus-within:z-1">
56
56
  <Input
57
57
  {...getCVCProps()}
58
58
  id={`card-cvc-${id}`}
59
- className="rounded-t-none rounded-l-none shadow-none"
59
+ className="rounded-t-none rounded-s-none shadow-none"
60
60
  />
61
61
  </div>
62
62
  </div>
@@ -0,0 +1,68 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { GripVertical } from "lucide-react"
5
+ import { Group, Panel, Separator } from "react-resizable-panels"
6
+ import type { GroupProps, PanelProps, SeparatorProps } from "react-resizable-panels"
7
+
8
+ import { cn } from "../../lib/utils"
9
+
10
+ // ─── ResizablePanelGroup ──────────────────────────────────────────────────────
11
+
12
+ export type ResizablePanelGroupProps = Omit<GroupProps, "orientation"> & {
13
+ direction?: "horizontal" | "vertical"
14
+ }
15
+
16
+ export function ResizablePanelGroup({
17
+ direction = "horizontal",
18
+ className,
19
+ ...props
20
+ }: ResizablePanelGroupProps) {
21
+ return (
22
+ <Group
23
+ orientation={direction}
24
+ className={cn(
25
+ "flex h-full w-full",
26
+ direction === "vertical" && "flex-col",
27
+ className,
28
+ )}
29
+ {...props}
30
+ />
31
+ )
32
+ }
33
+
34
+ // ─── ResizablePanel ───────────────────────────────────────────────────────────
35
+
36
+ export type ResizablePanelProps = PanelProps
37
+
38
+ export const ResizablePanel = Panel
39
+
40
+ // ─── ResizableHandle ──────────────────────────────────────────────────────────
41
+
42
+ export type ResizableHandleProps = Omit<SeparatorProps, "children"> & {
43
+ /** Render a visible grip icon on the handle. */
44
+ withHandle?: boolean
45
+ }
46
+
47
+ export function ResizableHandle({ withHandle, className, ...props }: ResizableHandleProps) {
48
+ return (
49
+ <Separator
50
+ className={cn(
51
+ // Base — horizontal handle (between side-by-side panels)
52
+ "relative flex w-1 shrink-0 cursor-col-resize items-center justify-center bg-border/60",
53
+ "transition-colors hover:bg-border active:bg-primary/30",
54
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
55
+ // Vertical handle (between stacked panels)
56
+ "data-[orientation=vertical]:h-1 data-[orientation=vertical]:w-full data-[orientation=vertical]:cursor-row-resize data-[orientation=vertical]:flex-row",
57
+ className,
58
+ )}
59
+ {...props}
60
+ >
61
+ {withHandle && (
62
+ <div className="z-10 flex h-5 w-3.5 items-center justify-center rounded-sm border border-border bg-background shadow-sm">
63
+ <GripVertical className="h-3 w-3 text-muted-foreground" />
64
+ </div>
65
+ )}
66
+ </Separator>
67
+ )
68
+ }
@@ -0,0 +1,72 @@
1
+ "use client"
2
+
3
+ /**
4
+ * ScrollArea — Radix-backed scroll container with always-visible-on-hover
5
+ * scrollbars that respect platform conventions.
6
+ *
7
+ * Use when you need an **explicitly bounded** scrolling region (lists in
8
+ * popovers, sidebar nav trees, long config panels) and the default
9
+ * browser scrollbar is too coarse or visually noisy.
10
+ *
11
+ * Accessibility:
12
+ * - Radix manages keyboard scrolling parity with native overflow.
13
+ * - The viewport is `role="region"`-compatible — give the wrapper an
14
+ * `aria-label` when the content is a meaningful landmark.
15
+ */
16
+
17
+ import * as React from "react"
18
+ import { ScrollArea as ScrollAreaPrimitive } from "radix-ui"
19
+
20
+ import { cn } from "../../lib/utils"
21
+
22
+ function ScrollArea({
23
+ className,
24
+ children,
25
+ ...props
26
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
27
+ return (
28
+ <ScrollAreaPrimitive.Root
29
+ data-slot="scroll-area"
30
+ className={cn("relative", className)}
31
+ {...props}
32
+ >
33
+ <ScrollAreaPrimitive.Viewport
34
+ data-slot="scroll-area-viewport"
35
+ className="size-full rounded-[inherit] outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
36
+ >
37
+ {children}
38
+ </ScrollAreaPrimitive.Viewport>
39
+ <ScrollBar />
40
+ <ScrollAreaPrimitive.Corner />
41
+ </ScrollAreaPrimitive.Root>
42
+ )
43
+ }
44
+
45
+ function ScrollBar({
46
+ className,
47
+ orientation = "vertical",
48
+ ...props
49
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
50
+ return (
51
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
52
+ data-slot="scroll-area-scrollbar"
53
+ orientation={orientation}
54
+ className={cn(
55
+ "flex touch-none select-none p-px transition-colors",
56
+ orientation === "vertical" &&
57
+ "h-full w-2.5 border-s border-s-transparent",
58
+ orientation === "horizontal" &&
59
+ "h-2.5 w-full flex-col border-t border-t-transparent",
60
+ className,
61
+ )}
62
+ {...props}
63
+ >
64
+ <ScrollAreaPrimitive.ScrollAreaThumb
65
+ data-slot="scroll-area-thumb"
66
+ className="relative flex-1 rounded-full bg-border hover:bg-border/80"
67
+ />
68
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
69
+ )
70
+ }
71
+
72
+ export { ScrollArea, ScrollBar }
@@ -15,10 +15,17 @@ export interface SelectionTileOption<T extends string = string> {
15
15
  leading?: React.ReactNode
16
16
  }
17
17
 
18
- /** Shared surface classes for icon+label tiles (Properties view type, Export format, etc.). */
18
+ /** Shared surface classes for icon+label tiles (Properties view type, Export format, etc.).
19
+ *
20
+ * `aspect-square` + horizontal padding keeps every tile a uniform square regardless of how
21
+ * many tiles are in the row — without it, the last row of a `grid-cols-N` grid (e.g. 3 tiles
22
+ * in a 4-col grid for the Properties view selector) renders the same width per cell but the
23
+ * eye reads them as inconsistent when the row's empty trailing cell shifts visual rhythm.
24
+ * Two-line labels (e.g. "List & details", "Tree & details") still fit because the icon
25
+ * column is only ~18px and the square grows with the cell. */
19
26
  export function selectionTileClassNames(selected: boolean) {
20
27
  return cn(
21
- "flex flex-col items-center justify-center gap-1.5 rounded-lg border py-3 text-xs transition-colors",
28
+ "flex aspect-square flex-col items-center justify-center gap-1.5 rounded-lg border px-2 py-3 text-xs leading-tight transition-colors",
22
29
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
23
30
  selected
24
31
  ? "border-brand bg-brand/5 text-foreground font-medium shadow-sm"
@@ -16,7 +16,21 @@ import {
16
16
  TooltipTrigger,
17
17
  } from "./tooltip"
18
18
 
19
- const SIDEBAR_COOKIE_NAME = "sidebar_state"
19
+ /**
20
+ * Cookie persisting the user's explicit expanded/collapsed preference.
21
+ *
22
+ * Versioned (`_v2`) on 2026-05-21 to drop stale values written by the
23
+ * pre-fix code where incidental layout collapses (secondary panel open,
24
+ * route auto-collapse) would clobber the user's preference on every
25
+ * navigation. Anyone on the old `sidebar_state` cookie falls back to
26
+ * the `defaultOpen` default (expanded), and the next explicit toggle
27
+ * starts persisting under the new name. The old cookie self-expires
28
+ * by `max-age` within a week; if you want immediate cleanup, the
29
+ * client clears it explicitly on first mount (see `useLayoutEffect`
30
+ * below).
31
+ */
32
+ const SIDEBAR_COOKIE_NAME = "sidebar_state_v2"
33
+ const SIDEBAR_COOKIE_LEGACY_NAME = "sidebar_state"
20
34
  const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
21
35
  /** Matches `useIsMobile` / Tailwind `md:` — do not apply desktop cookie to mobile overlay. */
22
36
  const SIDEBAR_COOKIE_VIEWPORT_MQ = "(max-width: 767px)"
@@ -24,14 +38,37 @@ const SIDEBAR_WIDTH = "16rem"
24
38
  const SIDEBAR_WIDTH_ICON = "3rem"
25
39
  const SIDEBAR_KEYBOARD_SHORTCUT = "b"
26
40
 
41
+ /**
42
+ * Options for {@link SidebarContextProps.setOpen}.
43
+ *
44
+ * `persist: false` updates the visual sidebar state **without** writing the
45
+ * `sidebar_state` cookie. Pass it from incidental layout effects — e.g. a
46
+ * secondary panel taking the rail space, a route-level auto-collapse — so
47
+ * the user's explicit preference (their ⌘B toggle / sidebar button) is the
48
+ * only thing that ever rewrites the cookie. Defaults to `true` for
49
+ * backward compatibility with the toggle button and existing callsites.
50
+ */
51
+ type SetOpenOptions = { persist?: boolean }
52
+
27
53
  type SidebarContextProps = {
28
54
  state: "expanded" | "collapsed"
29
55
  open: boolean
30
- setOpen: (open: boolean) => void
56
+ setOpen: (
57
+ open: boolean | ((value: boolean) => boolean),
58
+ opts?: SetOpenOptions,
59
+ ) => void
31
60
  openMobile: boolean
32
61
  setOpenMobile: (open: boolean) => void
33
62
  isMobile: boolean
34
63
  toggleSidebar: () => void
64
+ /**
65
+ * Snap the rail back to the user's saved preference — the value persisted in
66
+ * `sidebar_state_v2`, or `defaultOpen` if no cookie was ever written. Use
67
+ * this from incidental-collapse cleanups (secondary panel closing, route
68
+ * leaves) so the rail doesn't stay stuck in its incidental state once the
69
+ * thing that caused the collapse is gone. Always uses `persist: false`.
70
+ */
71
+ restoreSavedOpen: () => void
35
72
  }
36
73
 
37
74
  const SidebarContext = React.createContext<SidebarContextProps | null>(null)
@@ -73,19 +110,35 @@ function SidebarProvider({
73
110
  const [_open, _setOpen] = React.useState(defaultOpen)
74
111
  const open = openProp ?? _open
75
112
 
76
- // `setOpen` already persists `sidebar_state` to a cookie on desktop; restore it on mount so
113
+ // `setOpen` already persists `sidebar_state_v2` to a cookie on desktop; restore it on mount so
77
114
  // full reloads and new tabs keep the rail expanded/collapsed. Skip when controlled or on mobile.
115
+ // Also actively drop the legacy `sidebar_state` cookie (pre-2026-05-21) so stale
116
+ // collapsed-by-default values written by the old incidental-collapse bug don't linger.
117
+ //
118
+ // MOUNT-ONLY: deps are `[]` so this runs once per `SidebarProvider` mount, NOT
119
+ // every time `open` flips. That matters because incidental collapses
120
+ // (`setOpen(false, { persist: false })` from a secondary panel opening or
121
+ // `SidebarAutoCollapse` route) must NOT trigger a re-reconcile that reads the
122
+ // saved cookie back as "expanded" and snaps the rail open again.
123
+ // The functional setter avoids closing over a stale `open` value.
124
+ // eslint-disable-next-line react-hooks/exhaustive-deps
78
125
  React.useLayoutEffect(() => {
79
- if (openProp !== undefined) return
80
126
  if (typeof window === "undefined") return
127
+ if (typeof document !== "undefined" && document.cookie.includes(`${SIDEBAR_COOKIE_LEGACY_NAME}=`)) {
128
+ document.cookie = `${SIDEBAR_COOKIE_LEGACY_NAME}=; path=/; max-age=0`
129
+ }
130
+ if (openProp !== undefined) return
81
131
  if (window.matchMedia(SIDEBAR_COOKIE_VIEWPORT_MQ).matches) return
82
132
  const fromCookie = readSidebarStateCookie()
83
- if (fromCookie === undefined || fromCookie === open) return
84
- _setOpen(fromCookie)
85
- }, [openProp, open])
133
+ if (fromCookie === undefined) return
134
+ _setOpen((prev) => (prev === fromCookie ? prev : fromCookie))
135
+ }, [])
86
136
 
87
137
  const setOpen = React.useCallback(
88
- (value: boolean | ((value: boolean) => boolean)) => {
138
+ (
139
+ value: boolean | ((value: boolean) => boolean),
140
+ opts?: SetOpenOptions,
141
+ ) => {
89
142
  const openState = typeof value === "function" ? value(open) : value
90
143
  if (setOpenProp) {
91
144
  setOpenProp(openState)
@@ -93,8 +146,12 @@ function SidebarProvider({
93
146
  _setOpen(openState)
94
147
  }
95
148
 
96
- // Persist on desktop only — zooming in and closing shouldn't clobber the desktop state.
97
- if (!isMobile) {
149
+ // Persist on desktop only — zooming in and closing shouldn't clobber the
150
+ // desktop state. Callers can also opt out explicitly (`persist: false`)
151
+ // for incidental layout collapses such as a secondary panel opening or
152
+ // an auto-collapse route; those visual side-effects must not overwrite
153
+ // the user's saved expanded/collapsed preference.
154
+ if (!isMobile && opts?.persist !== false) {
98
155
  document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
99
156
  }
100
157
  },
@@ -106,6 +163,20 @@ function SidebarProvider({
106
163
  setOpen((open) => !open)
107
164
  }, [setOpen])
108
165
 
166
+ /**
167
+ * Snap the rail back to the user's saved preference. Called when a secondary
168
+ * panel closes or an auto-collapse route is left — so an incidental collapse
169
+ * doesn't persist beyond the page that caused it. `persist: false` because
170
+ * this restore is itself incidental; the only writes to the cookie should
171
+ * still come from real user gestures (⌘B, sidebar button).
172
+ */
173
+ const restoreSavedOpen = React.useCallback(() => {
174
+ if (typeof window === "undefined") return
175
+ const fromCookie = readSidebarStateCookie()
176
+ const target = fromCookie ?? defaultOpen
177
+ setOpen(target, { persist: false })
178
+ }, [defaultOpen, setOpen])
179
+
109
180
  // Adds a keyboard shortcut to toggle the sidebar.
110
181
  React.useEffect(() => {
111
182
  const handleKeyDown = (event: KeyboardEvent) => {
@@ -138,8 +209,9 @@ function SidebarProvider({
138
209
  openMobile,
139
210
  setOpenMobile,
140
211
  toggleSidebar,
212
+ restoreSavedOpen,
141
213
  }),
142
- [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
214
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar, restoreSavedOpen]
143
215
  )
144
216
 
145
217
  return (
@@ -569,7 +641,7 @@ const SidebarMenuButton = React.forwardRef<
569
641
  return button
570
642
  }
571
643
 
572
- let tooltipProps: React.ComponentProps<typeof TooltipContent> =
644
+ const tooltipProps: React.ComponentProps<typeof TooltipContent> =
573
645
  typeof tooltip === "string" ? { children: tooltip } : tooltip
574
646
 
575
647
  return (