@exxatdesignux/ui 0.2.19 → 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 (688) hide show
  1. package/CHANGELOG.md +60 -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 +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 +4 -15
  36. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +13 -28
  37. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
  38. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +2 -4
  39. package/consumer-extras/handbook/HANDBOOK.md +185 -0
  40. package/consumer-extras/handbook/glossary.md +57 -0
  41. package/consumer-extras/handbook/reference-implementations.md +126 -0
  42. package/consumer-extras/handbook/voice-and-tone.md +262 -0
  43. package/consumer-extras/patterns/command-menu-pattern.md +1 -1
  44. package/consumer-extras/patterns/consumer-upgrade-checklist.md +0 -20
  45. package/consumer-extras/patterns/data-views-pattern.md +17 -54
  46. package/consumer-extras/patterns/shell-surface-elevation-pattern.md +3 -5
  47. package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
  48. package/dist/components/data-table/filter-date-calendar.js +280 -0
  49. package/dist/components/data-table/filter-date-calendar.js.map +1 -0
  50. package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
  51. package/dist/components/data-table/filter-text-value-input.js +561 -0
  52. package/dist/components/data-table/filter-text-value-input.js.map +1 -0
  53. package/dist/components/data-table/index.d.ts +45 -0
  54. package/dist/components/data-table/index.js +3085 -0
  55. package/dist/components/data-table/index.js.map +1 -0
  56. package/dist/components/data-table/pagination.d.ts +28 -0
  57. package/dist/components/data-table/pagination.js +3264 -0
  58. package/dist/components/data-table/pagination.js.map +1 -0
  59. package/dist/components/data-table/types.d.ts +84 -0
  60. package/dist/components/data-table/types.js +3 -0
  61. package/dist/components/data-table/types.js.map +1 -0
  62. package/dist/components/data-table/use-table-state.d.ts +116 -0
  63. package/dist/components/data-table/use-table-state.js +670 -0
  64. package/dist/components/data-table/use-table-state.js.map +1 -0
  65. package/dist/components/data-views/board-card-primitives.d.ts +22 -0
  66. package/dist/components/data-views/board-card-primitives.js +84 -0
  67. package/dist/components/data-views/board-card-primitives.js.map +1 -0
  68. package/dist/components/data-views/data-row-list.d.ts +33 -0
  69. package/dist/components/data-views/data-row-list.js +106 -0
  70. package/dist/components/data-views/data-row-list.js.map +1 -0
  71. package/dist/components/data-views/finder-panel-view.d.ts +54 -0
  72. package/dist/components/data-views/finder-panel-view.js +388 -0
  73. package/dist/components/data-views/finder-panel-view.js.map +1 -0
  74. package/dist/components/data-views/folder-grid-view.d.ts +22 -0
  75. package/dist/components/data-views/folder-grid-view.js +58 -0
  76. package/dist/components/data-views/folder-grid-view.js.map +1 -0
  77. package/dist/components/data-views/hub-table.d.ts +167 -0
  78. package/dist/components/data-views/hub-table.js +5561 -0
  79. package/dist/components/data-views/hub-table.js.map +1 -0
  80. package/dist/components/data-views/index.d.ts +27 -0
  81. package/dist/components/data-views/index.js +6575 -0
  82. package/dist/components/data-views/index.js.map +1 -0
  83. package/dist/components/data-views/list-page-board-card.d.ts +72 -0
  84. package/dist/components/data-views/list-page-board-card.js +264 -0
  85. package/dist/components/data-views/list-page-board-card.js.map +1 -0
  86. package/dist/components/data-views/list-page-board-template.d.ts +24 -0
  87. package/dist/components/data-views/list-page-board-template.js +137 -0
  88. package/dist/components/data-views/list-page-board-template.js.map +1 -0
  89. package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
  90. package/dist/components/data-views/list-page-connected-view-body.js +116 -0
  91. package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
  92. package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
  93. package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
  94. package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
  95. package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
  96. package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
  97. package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
  98. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
  99. package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
  100. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
  101. package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
  102. package/dist/components/data-views/list-page-tree-column-header.js +22 -0
  103. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
  104. package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
  105. package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
  106. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
  107. package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
  108. package/dist/components/data-views/os-folder-glyph.js +104 -0
  109. package/dist/components/data-views/os-folder-glyph.js.map +1 -0
  110. package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
  111. package/dist/components/data-views/outline-tree-menu.js +131 -0
  112. package/dist/components/data-views/outline-tree-menu.js.map +1 -0
  113. package/dist/components/table-properties/column-row.d.ts +22 -0
  114. package/dist/components/table-properties/column-row.js +153 -0
  115. package/dist/components/table-properties/column-row.js.map +1 -0
  116. package/dist/components/table-properties/draggable-list.d.ts +24 -0
  117. package/dist/components/table-properties/draggable-list.js +53 -0
  118. package/dist/components/table-properties/draggable-list.js.map +1 -0
  119. package/dist/components/table-properties/drawer-button.d.ts +110 -0
  120. package/dist/components/table-properties/drawer-button.js +2748 -0
  121. package/dist/components/table-properties/drawer-button.js.map +1 -0
  122. package/dist/components/table-properties/drawer.d.ts +100 -0
  123. package/dist/components/table-properties/drawer.js +2595 -0
  124. package/dist/components/table-properties/drawer.js.map +1 -0
  125. package/dist/components/table-properties/filter-card.d.ts +24 -0
  126. package/dist/components/table-properties/filter-card.js +854 -0
  127. package/dist/components/table-properties/filter-card.js.map +1 -0
  128. package/dist/components/table-properties/index.d.ts +14 -0
  129. package/dist/components/table-properties/index.js +2768 -0
  130. package/dist/components/table-properties/index.js.map +1 -0
  131. package/dist/components/table-properties/sort-card.d.ts +20 -0
  132. package/dist/components/table-properties/sort-card.js +102 -0
  133. package/dist/components/table-properties/sort-card.js.map +1 -0
  134. package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
  135. package/dist/components/templates/dedicated-search-landing-template.js +254 -0
  136. package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
  137. package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
  138. package/dist/components/templates/dedicated-search-results-template.js +16 -0
  139. package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
  140. package/dist/components/templates/index.d.ts +9 -0
  141. package/dist/components/templates/index.js +2720 -0
  142. package/dist/components/templates/index.js.map +1 -0
  143. package/dist/components/templates/list-page.d.ts +83 -0
  144. package/dist/components/templates/list-page.js +2433 -0
  145. package/dist/components/templates/list-page.js.map +1 -0
  146. package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
  147. package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
  148. package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
  149. package/dist/components/ui/accordion.d.ts +10 -0
  150. package/dist/components/ui/accordion.js +74 -0
  151. package/dist/components/ui/accordion.js.map +1 -0
  152. package/dist/components/ui/alert-dialog.d.ts +37 -0
  153. package/dist/components/ui/alert-dialog.js +201 -0
  154. package/dist/components/ui/alert-dialog.js.map +1 -0
  155. package/dist/components/ui/avatar.d.ts +84 -0
  156. package/dist/components/ui/avatar.js +328 -0
  157. package/dist/components/ui/avatar.js.map +1 -0
  158. package/dist/components/ui/badge.d.ts +13 -0
  159. package/dist/components/ui/badge.js +49 -0
  160. package/dist/components/ui/badge.js.map +1 -0
  161. package/dist/components/ui/banner.d.ts +62 -0
  162. package/dist/components/ui/banner.js +364 -0
  163. package/dist/components/ui/banner.js.map +1 -0
  164. package/dist/components/ui/breadcrumb.d.ts +14 -0
  165. package/dist/components/ui/breadcrumb.js +114 -0
  166. package/dist/components/ui/breadcrumb.js.map +1 -0
  167. package/dist/components/ui/button.d.ts +16 -0
  168. package/dist/components/ui/button.js +59 -0
  169. package/dist/components/ui/button.js.map +1 -0
  170. package/dist/components/ui/calendar.d.ts +13 -0
  171. package/dist/components/ui/calendar.js +238 -0
  172. package/dist/components/ui/calendar.js.map +1 -0
  173. package/dist/components/ui/card.d.ts +14 -0
  174. package/dist/components/ui/card.js +102 -0
  175. package/dist/components/ui/card.js.map +1 -0
  176. package/dist/components/ui/chart.d.ts +58 -0
  177. package/dist/components/ui/chart.js +292 -0
  178. package/dist/components/ui/chart.js.map +1 -0
  179. package/dist/components/ui/checkbox.d.ts +23 -0
  180. package/dist/components/ui/checkbox.js +155 -0
  181. package/dist/components/ui/checkbox.js.map +1 -0
  182. package/dist/components/ui/coach-mark.d.ts +27 -0
  183. package/dist/components/ui/coach-mark.js +306 -0
  184. package/dist/components/ui/coach-mark.js.map +1 -0
  185. package/dist/components/ui/collapsible.d.ts +8 -0
  186. package/dist/components/ui/collapsible.js +35 -0
  187. package/dist/components/ui/collapsible.js.map +1 -0
  188. package/dist/components/ui/command.d.ts +36 -0
  189. package/dist/components/ui/command.js +274 -0
  190. package/dist/components/ui/command.js.map +1 -0
  191. package/dist/components/ui/context-menu.d.ts +32 -0
  192. package/dist/components/ui/context-menu.js +245 -0
  193. package/dist/components/ui/context-menu.js.map +1 -0
  194. package/dist/components/ui/date-picker-field.d.ts +38 -0
  195. package/dist/components/ui/date-picker-field.js +550 -0
  196. package/dist/components/ui/date-picker-field.js.map +1 -0
  197. package/dist/components/ui/dialog.d.ts +22 -0
  198. package/dist/components/ui/dialog.js +200 -0
  199. package/dist/components/ui/dialog.js.map +1 -0
  200. package/dist/components/ui/dot-pattern.d.ts +21 -0
  201. package/dist/components/ui/dot-pattern.js +139 -0
  202. package/dist/components/ui/dot-pattern.js.map +1 -0
  203. package/dist/components/ui/drag-handle-grip.d.ts +10 -0
  204. package/dist/components/ui/drag-handle-grip.js +15 -0
  205. package/dist/components/ui/drag-handle-grip.js.map +1 -0
  206. package/dist/components/ui/drawer.d.ts +16 -0
  207. package/dist/components/ui/drawer.js +125 -0
  208. package/dist/components/ui/drawer.js.map +1 -0
  209. package/dist/components/ui/dropdown-menu.d.ts +45 -0
  210. package/dist/components/ui/dropdown-menu.js +353 -0
  211. package/dist/components/ui/dropdown-menu.js.map +1 -0
  212. package/dist/components/ui/export-drawer.d.ts +11 -0
  213. package/dist/components/ui/export-drawer.js +1658 -0
  214. package/dist/components/ui/export-drawer.js.map +1 -0
  215. package/dist/components/ui/field.d.ts +30 -0
  216. package/dist/components/ui/field.js +249 -0
  217. package/dist/components/ui/field.js.map +1 -0
  218. package/dist/components/ui/form.d.ts +28 -0
  219. package/dist/components/ui/form.js +110 -0
  220. package/dist/components/ui/form.js.map +1 -0
  221. package/dist/components/ui/hover-card.d.ts +9 -0
  222. package/dist/components/ui/hover-card.js +43 -0
  223. package/dist/components/ui/hover-card.js.map +1 -0
  224. package/dist/components/ui/input-group.d.ts +20 -0
  225. package/dist/components/ui/input-group.js +219 -0
  226. package/dist/components/ui/input-group.js.map +1 -0
  227. package/dist/components/ui/input-mask.d.ts +39 -0
  228. package/dist/components/ui/input-mask.js +118 -0
  229. package/dist/components/ui/input-mask.js.map +1 -0
  230. package/dist/components/ui/input.d.ts +5 -0
  231. package/dist/components/ui/input.js +30 -0
  232. package/dist/components/ui/input.js.map +1 -0
  233. package/dist/components/ui/kbd.d.ts +20 -0
  234. package/dist/components/ui/kbd.js +45 -0
  235. package/dist/components/ui/kbd.js.map +1 -0
  236. package/dist/components/ui/key-metrics-context.d.ts +19 -0
  237. package/dist/components/ui/key-metrics-context.js +26 -0
  238. package/dist/components/ui/key-metrics-context.js.map +1 -0
  239. package/dist/components/ui/key-metrics.d.ts +131 -0
  240. package/dist/components/ui/key-metrics.js +1015 -0
  241. package/dist/components/ui/key-metrics.js.map +1 -0
  242. package/dist/components/ui/label.d.ts +6 -0
  243. package/dist/components/ui/label.js +28 -0
  244. package/dist/components/ui/label.js.map +1 -0
  245. package/dist/components/ui/list-page-view-frame.d.ts +22 -0
  246. package/dist/components/ui/list-page-view-frame.js +24 -0
  247. package/dist/components/ui/list-page-view-frame.js.map +1 -0
  248. package/dist/components/ui/page-header.d.ts +51 -0
  249. package/dist/components/ui/page-header.js +372 -0
  250. package/dist/components/ui/page-header.js.map +1 -0
  251. package/dist/components/ui/payment-card-fields.d.ts +10 -0
  252. package/dist/components/ui/payment-card-fields.js +80 -0
  253. package/dist/components/ui/payment-card-fields.js.map +1 -0
  254. package/dist/components/ui/popover.d.ts +10 -0
  255. package/dist/components/ui/popover.js +47 -0
  256. package/dist/components/ui/popover.js.map +1 -0
  257. package/dist/components/ui/radio-group.d.ts +29 -0
  258. package/dist/components/ui/radio-group.js +190 -0
  259. package/dist/components/ui/radio-group.js.map +1 -0
  260. package/dist/components/ui/resizable.d.ts +16 -0
  261. package/dist/components/ui/resizable.js +51 -0
  262. package/dist/components/ui/resizable.js.map +1 -0
  263. package/dist/components/ui/scroll-area.d.ts +8 -0
  264. package/dist/components/ui/scroll-area.js +66 -0
  265. package/dist/components/ui/scroll-area.js.map +1 -0
  266. package/dist/components/ui/select.d.ts +18 -0
  267. package/dist/components/ui/select.js +186 -0
  268. package/dist/components/ui/select.js.map +1 -0
  269. package/dist/components/ui/selection-tile-grid.d.ts +52 -0
  270. package/dist/components/ui/selection-tile-grid.js +347 -0
  271. package/dist/components/ui/selection-tile-grid.js.map +1 -0
  272. package/dist/components/ui/separator.d.ts +7 -0
  273. package/dist/components/ui/separator.js +33 -0
  274. package/dist/components/ui/separator.js.map +1 -0
  275. package/dist/components/ui/sheet.d.ts +18 -0
  276. package/dist/components/ui/sheet.js +181 -0
  277. package/dist/components/ui/sheet.js.map +1 -0
  278. package/dist/components/ui/sidebar.d.ts +94 -0
  279. package/dist/components/ui/sidebar.js +805 -0
  280. package/dist/components/ui/sidebar.js.map +1 -0
  281. package/dist/components/ui/skeleton.d.ts +5 -0
  282. package/dist/components/ui/skeleton.js +22 -0
  283. package/dist/components/ui/skeleton.js.map +1 -0
  284. package/dist/components/ui/slider.d.ts +7 -0
  285. package/dist/components/ui/slider.js +66 -0
  286. package/dist/components/ui/slider.js.map +1 -0
  287. package/dist/components/ui/sonner.d.ts +6 -0
  288. package/dist/components/ui/sonner.js +38 -0
  289. package/dist/components/ui/sonner.js.map +1 -0
  290. package/dist/components/ui/status-badge.d.ts +38 -0
  291. package/dist/components/ui/status-badge.js +77 -0
  292. package/dist/components/ui/status-badge.js.map +1 -0
  293. package/dist/components/ui/table.d.ts +13 -0
  294. package/dist/components/ui/table.js +115 -0
  295. package/dist/components/ui/table.js.map +1 -0
  296. package/dist/components/ui/tabs.d.ts +15 -0
  297. package/dist/components/ui/tabs.js +93 -0
  298. package/dist/components/ui/tabs.js.map +1 -0
  299. package/dist/components/ui/textarea.d.ts +6 -0
  300. package/dist/components/ui/textarea.js +25 -0
  301. package/dist/components/ui/textarea.js.map +1 -0
  302. package/dist/components/ui/tip.d.ts +12 -0
  303. package/dist/components/ui/tip.js +61 -0
  304. package/dist/components/ui/tip.js.map +1 -0
  305. package/dist/components/ui/toggle-group.d.ts +14 -0
  306. package/dist/components/ui/toggle-group.js +104 -0
  307. package/dist/components/ui/toggle-group.js.map +1 -0
  308. package/dist/components/ui/toggle-switch.d.ts +10 -0
  309. package/dist/components/ui/toggle-switch.js +33 -0
  310. package/dist/components/ui/toggle-switch.js.map +1 -0
  311. package/dist/components/ui/toggle.d.ts +13 -0
  312. package/dist/components/ui/toggle.js +51 -0
  313. package/dist/components/ui/toggle.js.map +1 -0
  314. package/dist/components/ui/tooltip.d.ts +10 -0
  315. package/dist/components/ui/tooltip.js +68 -0
  316. package/dist/components/ui/tooltip.js.map +1 -0
  317. package/dist/components/ui/view-segmented-control.d.ts +31 -0
  318. package/dist/components/ui/view-segmented-control.js +167 -0
  319. package/dist/components/ui/view-segmented-control.js.map +1 -0
  320. package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
  321. package/dist/hooks/use-app-theme.d.ts +24 -0
  322. package/dist/hooks/use-app-theme.js +286 -0
  323. package/dist/hooks/use-app-theme.js.map +1 -0
  324. package/dist/hooks/use-coach-mark.d.ts +86 -0
  325. package/dist/hooks/use-coach-mark.js +218 -0
  326. package/dist/hooks/use-coach-mark.js.map +1 -0
  327. package/dist/hooks/use-mobile.d.ts +3 -0
  328. package/dist/hooks/use-mobile.js +29 -0
  329. package/dist/hooks/use-mobile.js.map +1 -0
  330. package/dist/hooks/use-mod-key-label.d.ts +6 -0
  331. package/dist/hooks/use-mod-key-label.js +25 -0
  332. package/dist/hooks/use-mod-key-label.js.map +1 -0
  333. package/dist/index.d.ts +120 -0
  334. package/dist/index.js +13324 -0
  335. package/dist/index.js.map +1 -0
  336. package/dist/lib/compose-refs.d.ts +6 -0
  337. package/dist/lib/compose-refs.js +17 -0
  338. package/dist/lib/compose-refs.js.map +1 -0
  339. package/dist/lib/conditional-rule-match.d.ts +30 -0
  340. package/dist/lib/conditional-rule-match.js +66 -0
  341. package/dist/lib/conditional-rule-match.js.map +1 -0
  342. package/dist/lib/data-list-display-options.d.ts +26 -0
  343. package/dist/lib/data-list-display-options.js +14 -0
  344. package/dist/lib/data-list-display-options.js.map +1 -0
  345. package/dist/lib/data-list-view-registry.d.ts +2 -0
  346. package/dist/lib/data-list-view-registry.js +102 -0
  347. package/dist/lib/data-list-view-registry.js.map +1 -0
  348. package/dist/lib/data-list-view-surface.d.ts +2 -0
  349. package/dist/lib/data-list-view-surface.js +80 -0
  350. package/dist/lib/data-list-view-surface.js.map +1 -0
  351. package/dist/lib/data-list-view.d.ts +21 -0
  352. package/dist/lib/data-list-view.js +25 -0
  353. package/dist/lib/data-list-view.js.map +1 -0
  354. package/dist/lib/date-filter.d.ts +22 -0
  355. package/dist/lib/date-filter.js +61 -0
  356. package/dist/lib/date-filter.js.map +1 -0
  357. package/dist/lib/dev-log.d.ts +8 -0
  358. package/dist/lib/dev-log.js +10 -0
  359. package/dist/lib/dev-log.js.map +1 -0
  360. package/dist/lib/dropdown-menu-surface.d.ts +14 -0
  361. package/dist/lib/dropdown-menu-surface.js +6 -0
  362. package/dist/lib/dropdown-menu-surface.js.map +1 -0
  363. package/dist/lib/editable-target.d.ts +12 -0
  364. package/dist/lib/editable-target.js +12 -0
  365. package/dist/lib/editable-target.js.map +1 -0
  366. package/dist/lib/list-page-table-properties.d.ts +35 -0
  367. package/dist/lib/list-page-table-properties.js +81 -0
  368. package/dist/lib/list-page-table-properties.js.map +1 -0
  369. package/dist/lib/raf-throttle.d.ts +23 -0
  370. package/dist/lib/raf-throttle.js +27 -0
  371. package/dist/lib/raf-throttle.js.map +1 -0
  372. package/dist/lib/row-height.d.ts +16 -0
  373. package/dist/lib/row-height.js +10 -0
  374. package/dist/lib/row-height.js.map +1 -0
  375. package/dist/lib/table-properties-types.d.ts +83 -0
  376. package/dist/lib/table-properties-types.js +19 -0
  377. package/dist/lib/table-properties-types.js.map +1 -0
  378. package/dist/lib/utils.d.ts +5 -0
  379. package/dist/lib/utils.js +11 -0
  380. package/dist/lib/utils.js.map +1 -0
  381. package/package.json +83 -19
  382. package/src/components/data-table/filter-date-calendar.tsx +38 -0
  383. package/src/components/data-table/filter-text-value-input.tsx +77 -0
  384. package/src/components/data-table/index.tsx +1678 -0
  385. package/src/components/data-table/pagination.tsx +255 -0
  386. package/src/components/data-table/types.ts +96 -0
  387. package/src/components/data-table/use-table-state.ts +767 -0
  388. package/src/components/data-views/board-card-primitives.tsx +93 -0
  389. package/src/components/data-views/data-row-list.tsx +183 -0
  390. package/src/components/data-views/finder-panel-view.tsx +405 -0
  391. package/src/components/data-views/folder-grid-view.tsx +86 -0
  392. package/src/components/data-views/hub-table.tsx +498 -0
  393. package/src/components/data-views/index.ts +28 -0
  394. package/src/components/data-views/list-page-board-card.tsx +192 -0
  395. package/src/components/data-views/list-page-board-template.tsx +122 -0
  396. package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
  397. package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
  398. package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
  399. package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
  400. package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
  401. package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
  402. package/src/components/data-views/os-folder-glyph.tsx +141 -0
  403. package/src/components/data-views/outline-tree-menu.tsx +157 -0
  404. package/src/components/table-properties/column-row.tsx +90 -0
  405. package/src/components/table-properties/draggable-list.ts +54 -0
  406. package/src/components/table-properties/drawer-button.tsx +300 -0
  407. package/src/components/table-properties/drawer.tsx +1148 -0
  408. package/src/components/table-properties/filter-card.tsx +251 -0
  409. package/src/components/table-properties/index.ts +36 -0
  410. package/src/components/table-properties/sort-card.tsx +63 -0
  411. package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
  412. package/src/components/templates/dedicated-search-results-template.tsx +19 -0
  413. package/src/components/templates/index.ts +33 -0
  414. package/src/components/templates/list-page.tsx +602 -0
  415. package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
  416. package/src/components/ui/accordion.tsx +92 -0
  417. package/src/components/ui/alert-dialog.tsx +221 -0
  418. package/src/components/ui/avatar.tsx +13 -2
  419. package/src/components/ui/banner.tsx +2 -2
  420. package/src/components/ui/button.tsx +4 -4
  421. package/src/components/ui/calendar.tsx +1 -1
  422. package/src/components/ui/coach-mark.tsx +1 -1
  423. package/src/components/ui/context-menu.tsx +291 -0
  424. package/src/components/ui/date-picker-field.tsx +2 -2
  425. package/src/components/ui/dot-pattern.tsx +183 -0
  426. package/src/components/ui/export-drawer.tsx +375 -0
  427. package/src/components/ui/hover-card.tsx +66 -0
  428. package/src/components/ui/key-metrics-context.tsx +78 -0
  429. package/src/components/ui/key-metrics.tsx +1133 -0
  430. package/src/components/ui/list-page-view-frame.tsx +64 -0
  431. package/src/components/ui/page-header.tsx +244 -0
  432. package/src/components/ui/payment-card-fields.tsx +2 -2
  433. package/src/components/ui/resizable.tsx +68 -0
  434. package/src/components/ui/scroll-area.tsx +72 -0
  435. package/src/components/ui/selection-tile-grid.tsx +9 -2
  436. package/src/components/ui/sidebar.tsx +84 -12
  437. package/src/components/ui/slider.tsx +83 -0
  438. package/src/globals.css +2201 -7
  439. package/src/globals.d.ts +20 -0
  440. package/src/index.ts +68 -1
  441. package/src/lib/conditional-rule-match.ts +119 -0
  442. package/src/lib/data-list-display-options.ts +35 -0
  443. package/src/lib/data-list-view-registry.ts +104 -0
  444. package/src/lib/data-list-view-surface.ts +83 -0
  445. package/src/lib/data-list-view.ts +47 -0
  446. package/src/lib/dev-log.ts +10 -0
  447. package/src/lib/editable-target.ts +20 -0
  448. package/src/lib/list-page-table-properties.ts +48 -0
  449. package/src/lib/raf-throttle.ts +45 -0
  450. package/src/lib/row-height.ts +19 -0
  451. package/src/lib/table-properties-types.ts +98 -0
  452. package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
  453. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
  454. package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
  455. package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
  456. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
  457. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  458. package/template/AGENTS.md +104 -78
  459. package/template/app/(app)/dashboard/loading.tsx +15 -3
  460. package/template/app/(app)/dashboard/page.tsx +14 -2
  461. package/template/app/(app)/examples/page.tsx +0 -2
  462. package/template/app/(app)/layout.tsx +17 -4
  463. package/template/app/(app)/loading.tsx +18 -1
  464. package/template/app/(app)/question-bank/find/page.tsx +1 -2
  465. package/template/app/(app)/question-bank/layout.tsx +1 -1
  466. package/template/app/(app)/question-bank/library/page.tsx +1 -2
  467. package/template/app/(app)/question-bank/list/page.tsx +1 -2
  468. package/template/app/(app)/question-bank/new/page.tsx +15 -20
  469. package/template/app/(app)/question-bank/page.tsx +1 -2
  470. package/template/app/(app)/settings/page.tsx +5 -4
  471. package/template/app/globals.css +14 -16
  472. package/template/components/ask-leo-sidebar.tsx +5 -1
  473. package/template/components/brand-color-picker.tsx +2 -2
  474. package/template/components/charts-overview.tsx +1 -1
  475. package/template/components/compliance-board-view.tsx +142 -0
  476. package/template/components/compliance-client.tsx +92 -0
  477. package/template/components/compliance-page-header.tsx +89 -0
  478. package/template/components/compliance-table.tsx +468 -0
  479. package/template/components/dashboard-report-charts.tsx +1 -1
  480. package/template/components/dashboard-tabs.tsx +1 -1
  481. package/template/components/data-table/filter-date-calendar.tsx +1 -38
  482. package/template/components/data-table/filter-text-value-input.tsx +1 -77
  483. package/template/components/data-table/index.tsx +1 -1634
  484. package/template/components/data-table/pagination.tsx +1 -255
  485. package/template/components/data-table/types.ts +1 -94
  486. package/template/components/data-table/use-table-state.test.ts +420 -0
  487. package/template/components/data-table/use-table-state.ts +1 -758
  488. package/template/components/data-view-dashboard-charts-compliance.tsx +963 -0
  489. package/template/components/data-view-dashboard-charts-team.tsx +971 -0
  490. package/template/components/data-view-dashboard-charts.tsx +1503 -0
  491. package/template/components/data-views/board-card-primitives.tsx +1 -93
  492. package/template/components/data-views/data-row-list.tsx +1 -183
  493. package/template/components/data-views/finder-panel-view.tsx +1 -405
  494. package/template/components/data-views/folder-grid-view.tsx +1 -86
  495. package/template/components/data-views/hub-table.tsx +1 -0
  496. package/template/components/data-views/index.ts +50 -37
  497. package/template/components/data-views/list-page-board-card.tsx +1 -192
  498. package/template/components/data-views/list-page-board-template.tsx +1 -122
  499. package/template/components/data-views/list-page-connected-view-body.tsx +1 -66
  500. package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
  501. package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -68
  502. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
  503. package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
  504. package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
  505. package/template/components/data-views/list-page-view-frame.tsx +5 -53
  506. package/template/components/data-views/os-folder-glyph.tsx +1 -129
  507. package/template/components/data-views/outline-tree-menu.tsx +1 -157
  508. package/template/components/export-drawer.test.tsx +71 -0
  509. package/template/components/export-drawer.tsx +1 -375
  510. package/template/components/exxat-product-logo.tsx +5 -5
  511. package/template/components/hub-tree-panel-view.tsx +2 -2
  512. package/template/components/invite-collaborators-drawer.tsx +3 -3
  513. package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
  514. package/template/components/key-metrics.tsx +1 -1063
  515. package/template/components/leo-insight-indicator.tsx +2 -2
  516. package/template/components/new-placement-back-btn.tsx +28 -0
  517. package/template/components/new-placement-form.tsx +942 -0
  518. package/template/components/new-question-composer.tsx +456 -408
  519. package/template/components/onboarding/index.ts +9 -0
  520. package/template/components/onboarding/onboarding-01.tsx +1 -1
  521. package/template/components/onboarding/onboarding-02.tsx +1 -1
  522. package/template/components/onboarding/onboarding-03.tsx +1 -1
  523. package/template/components/onboarding/onboarding-04.tsx +1 -1
  524. package/template/components/page-header.tsx +8 -226
  525. package/template/components/placement-board-card.tsx +250 -0
  526. package/template/components/placement-detail.tsx +438 -0
  527. package/template/components/placements-board-view.tsx +397 -0
  528. package/template/components/placements-client.tsx +220 -0
  529. package/template/components/placements-list-view.tsx +124 -0
  530. package/template/components/placements-page-header.tsx +166 -0
  531. package/template/components/placements-table-cells.test.tsx +22 -0
  532. package/template/components/placements-table-cells.tsx +173 -0
  533. package/template/components/placements-table-columns.tsx +210 -0
  534. package/template/components/placements-table.tsx +934 -0
  535. package/template/components/product-switcher.tsx +3 -4
  536. package/template/components/product-wordmark.tsx +2 -1
  537. package/template/components/question-bank-client.tsx +5 -5
  538. package/template/components/question-bank-hub-client.tsx +1 -1
  539. package/template/components/question-bank-new-folder-sheet.tsx +2 -2
  540. package/template/components/question-bank-secondary-nav.tsx +3 -3
  541. package/template/components/question-bank-table.tsx +541 -431
  542. package/template/components/rotations-empty-state.tsx +50 -0
  543. package/template/components/rotations-panel-activator.tsx +8 -0
  544. package/template/components/settings-appearance-card.tsx +3 -4
  545. package/template/components/settings-client.tsx +15 -59
  546. package/template/components/settings-form-row.tsx +4 -9
  547. package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
  548. package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +59 -74
  549. package/template/components/sidebar/index.ts +16 -0
  550. package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
  551. package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +50 -7
  552. package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
  553. package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
  554. package/template/components/site-header.tsx +1 -1
  555. package/template/components/sites-board-view.tsx +67 -0
  556. package/template/components/sites-client.tsx +154 -0
  557. package/template/components/sites-table.tsx +249 -0
  558. package/template/components/table-properties/column-row.tsx +1 -90
  559. package/template/components/table-properties/draggable-list.ts +1 -49
  560. package/template/components/table-properties/drawer-button.tsx +1 -262
  561. package/template/components/table-properties/drawer.tsx +1 -1166
  562. package/template/components/table-properties/filter-card.tsx +1 -251
  563. package/template/components/table-properties/sort-card.tsx +1 -59
  564. package/template/components/table-properties/types.ts +28 -71
  565. package/template/components/team-board-view.tsx +122 -0
  566. package/template/components/team-client.tsx +100 -0
  567. package/template/components/team-page-header.tsx +92 -0
  568. package/template/components/team-table.tsx +553 -0
  569. package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
  570. package/template/components/templates/dedicated-search-results-template.tsx +1 -19
  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 +1 -1
  575. package/template/components/ui/accordion.tsx +1 -0
  576. package/template/components/ui/alert-dialog.tsx +1 -0
  577. package/template/components/ui/context-menu.tsx +1 -0
  578. package/template/components/ui/dot-pattern.tsx +1 -183
  579. package/template/components/ui/hover-card.tsx +1 -0
  580. package/template/components/ui/resizable.tsx +1 -68
  581. package/template/components/ui/scroll-area.tsx +1 -0
  582. package/template/components/ui/slider.tsx +1 -0
  583. package/template/docs/blueprints/README.md +86 -0
  584. package/template/docs/blueprints/_template.md +91 -0
  585. package/template/docs/blueprints/board-card.md +123 -0
  586. package/template/docs/blueprints/data-table.md +139 -0
  587. package/template/docs/blueprints/key-metrics.md +128 -0
  588. package/template/docs/blueprints/list-page-template.md +123 -0
  589. package/template/docs/blueprints/page-header.md +130 -0
  590. package/template/docs/command-menu-pattern.md +1 -1
  591. package/template/docs/component-selection-guide.md +224 -0
  592. package/template/docs/components-audit-2026-05.md +158 -0
  593. package/template/docs/data-views-pattern.md +17 -54
  594. package/template/docs/drawer-vs-dialog-pattern.md +1 -3
  595. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
  596. package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
  597. package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
  598. package/template/docs/migrations/README.md +100 -0
  599. package/template/docs/migrations/_template.md +64 -0
  600. package/template/docs/shell-surface-elevation-pattern.md +3 -5
  601. package/template/docs/token-taxonomy.md +416 -0
  602. package/template/eslint.config.mjs +27 -0
  603. package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
  604. package/template/lib/command-menu-config.ts +0 -1
  605. package/template/lib/command-menu-search-data.ts +27 -11
  606. package/template/lib/compliance-supported-views.ts +10 -0
  607. package/template/lib/conditional-rule-match.ts +6 -97
  608. package/template/lib/data-list-display-options.ts +1 -49
  609. package/template/lib/data-list-view-registry.ts +1 -104
  610. package/template/lib/data-list-view-surface.ts +1 -83
  611. package/template/lib/data-list-view.ts +1 -47
  612. package/template/lib/data-view-dashboard-placements-layout.ts +215 -0
  613. package/template/lib/data-view-dashboard-storage.ts +35 -38
  614. package/template/lib/dev-log.ts +1 -8
  615. package/template/lib/editable-target.ts +1 -10
  616. package/template/lib/list-page-table-properties.ts +1 -48
  617. package/template/lib/list-status-badges.ts +97 -4
  618. package/template/lib/mock/compliance-kpi.ts +61 -0
  619. package/template/lib/mock/compliance.ts +146 -0
  620. package/template/lib/mock/navigation.tsx +0 -9
  621. package/template/lib/mock/placements-kpi.ts +134 -0
  622. package/template/lib/mock/placements.ts +176 -0
  623. package/template/lib/mock/sites-directory.ts +16 -0
  624. package/template/lib/mock/sites-kpi.ts +25 -0
  625. package/template/lib/mock/team-kpi.ts +60 -0
  626. package/template/lib/mock/team.ts +118 -0
  627. package/template/lib/placement-board-card-layout.ts +79 -0
  628. package/template/lib/placements-supported-views.ts +12 -0
  629. package/template/lib/question-bank-supported-views.ts +0 -1
  630. package/template/lib/raf-throttle.ts +1 -45
  631. package/template/lib/row-height.ts +4 -10
  632. package/template/lib/sidebar-state-cookie.ts +11 -2
  633. package/template/lib/sites-supported-views.ts +10 -0
  634. package/template/lib/table-state-lifecycle.ts +2 -2
  635. package/template/lib/team-supported-views.ts +10 -0
  636. package/template/package.json +1 -0
  637. package/template/tests/setup.ts +25 -0
  638. package/consumer-extras/AGENTS.md +0 -76
  639. package/consumer-extras/cursor-skills/exxat-consumer-app/SKILL.md +0 -37
  640. package/consumer-extras/cursor-skills/exxat-focused-workflow-page/SKILL.md +0 -57
  641. package/consumer-extras/patterns/consumer-app-pattern.md +0 -39
  642. package/consumer-extras/patterns/focused-workflow-page-pattern.md +0 -84
  643. package/src/components/ui/button-group.tsx +0 -81
  644. package/src/theme.css +0 -16
  645. package/src/tokens/README.md +0 -15
  646. package/src/tokens/base.css +0 -337
  647. package/src/tokens/high-contrast.css +0 -1195
  648. package/src/tokens/layers.css +0 -224
  649. package/src/tokens/tailwind-bridge.css +0 -118
  650. package/src/tokens/themes.css +0 -201
  651. package/template/app/(app)/data-list/layout.tsx +0 -43
  652. package/template/app/(app)/data-list/page.tsx +0 -10
  653. package/template/app/(app)/examples/focused-workflow/page.tsx +0 -5
  654. package/template/components/app-route-loading.tsx +0 -14
  655. package/template/components/dashboard-onboarding-gallery.tsx +0 -13
  656. package/template/components/dashboard-onboarding.tsx +0 -21
  657. package/template/components/data-views/list-page-calendar-view.tsx +0 -593
  658. package/template/components/data-views/list-page-folder-columns-panel.tsx +0 -345
  659. package/template/components/examples/focused-workflow-showcase.tsx +0 -183
  660. package/template/components/list-hub-board-view.tsx +0 -68
  661. package/template/components/list-hub-client.tsx +0 -186
  662. package/template/components/list-hub-list-view.tsx +0 -36
  663. package/template/components/list-hub-panel-activator.tsx +0 -8
  664. package/template/components/list-hub-secondary-nav.tsx +0 -121
  665. package/template/components/list-hub-table.tsx +0 -336
  666. package/template/components/question-bank-folder-columns-panel.tsx +0 -104
  667. package/template/components/question-bank-list-view.tsx +0 -53
  668. package/template/components/secondary-panel/nav-link-rows.tsx +0 -83
  669. package/template/components/secondary-panels/list-hub-panel.tsx +0 -39
  670. package/template/components/secondary-panels/question-bank-panel.tsx +0 -39
  671. package/template/components/secondary-panels/registry.tsx +0 -15
  672. package/template/components/section-cards.tsx +0 -106
  673. package/template/components/templates/focused-workflow-layouts.tsx +0 -448
  674. package/template/components/templates/focused-workflow-page-template.tsx +0 -69
  675. package/template/components/templates/page-loading-shell.tsx +0 -262
  676. package/template/components/ui/button-group.tsx +0 -1
  677. package/template/docs/consumer-app-pattern.md +0 -39
  678. package/template/docs/focused-workflow-page-pattern.md +0 -84
  679. package/template/lib/list-hub-nav.ts +0 -121
  680. package/template/lib/mock/list-hub-directory.ts +0 -27
  681. package/template/lib/mock/list-hub-kpi.ts +0 -27
  682. package/template/lib/page-loading-variant.ts +0 -40
  683. /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
  684. /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
  685. /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
  686. /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
  687. /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
  688. /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
@@ -0,0 +1,176 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // Mock data — Placements
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+
5
+ export type Status = "confirmed" | "pending" | "under-review" | "rejected" | "completed"
6
+
7
+ /** Which lifecycle tab owns this row (All shows every row). */
8
+ export type PlacementPhase = "upcoming" | "ongoing" | "completed"
9
+
10
+ export interface Placement extends Record<string, unknown> {
11
+ id: number
12
+ student: string
13
+ email: string
14
+ initials: string
15
+ program: string
16
+ site: string
17
+ siteAddress: string
18
+ status: Status
19
+ start: string
20
+ duration: string
21
+ supervisor: string
22
+ placementPhase: PlacementPhase
23
+ /** Display title for internship column */
24
+ internship: string
25
+ specialization: string
26
+ /** Upcoming */
27
+ compliance: string
28
+ daysUntilStart: number
29
+ readiness: string
30
+ /** Ongoing */
31
+ progressWeeksDone: number
32
+ progressWeeksTotal: number
33
+ endDate: string
34
+ lastCheckin: string
35
+ /** Completed */
36
+ completionDate: string
37
+ finalStatus: string
38
+ rating: number
39
+ suggestedToHire: string
40
+ /** Visual indicator — row has new activity or was recently updated */
41
+ isNew?: boolean
42
+ }
43
+
44
+ export const ALL_PLACEMENTS: Placement[] = [
45
+ {
46
+ id: 1, student: "Sarah Johnson", email: "s.johnson@college.edu", initials: "SJ", program: "Nursing", site: "City Medical Center",
47
+ siteAddress: "1400 N Lake Shore Dr, Chicago, IL", status: "confirmed", start: "03/15/2026", duration: "12 wks", supervisor: "Dr. Patel",
48
+ placementPhase: "ongoing", internship: "Med-Surg Clinical I", specialization: "Adult Health", compliance: "Complete", daysUntilStart: 0,
49
+ readiness: "Ready", progressWeeksDone: 5, progressWeeksTotal: 12, endDate: "06/07/2026", lastCheckin: "03/22/2026",
50
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—", isNew: true,
51
+ },
52
+ {
53
+ id: 2, student: "Mike Chen", email: "m.chen@university.edu", initials: "MC", program: "Physical Therapy", site: "Metro Rehab",
54
+ siteAddress: "250 E Superior St, Chicago, IL", status: "pending", start: "04/01/2026", duration: "8 wks", supervisor: "Dr. Kim",
55
+ placementPhase: "upcoming", internship: "Outpatient PT Rotation", specialization: "Orthopedics", compliance: "In progress", daysUntilStart: 8,
56
+ readiness: "Ready", progressWeeksDone: 0, progressWeeksTotal: 8, endDate: "05/27/2026", lastCheckin: "—",
57
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
58
+ },
59
+ {
60
+ id: 3, student: "Amy Park", email: "a.park@school.edu", initials: "AP", program: "Occupational Therapy", site: "Bay Area Health",
61
+ siteAddress: "3100 Telegraph Ave, Oakland, CA", status: "under-review", start: "03/28/2026", duration: "10 wks", supervisor: "Unassigned",
62
+ placementPhase: "upcoming", internship: "Acute Care OT", specialization: "Hand Therapy", compliance: "Pending documents", daysUntilStart: 4,
63
+ readiness: "At risk", progressWeeksDone: 0, progressWeeksTotal: 10, endDate: "06/06/2026", lastCheckin: "—",
64
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—", isNew: true,
65
+ },
66
+ {
67
+ id: 4, student: "James Williams", email: "j.williams@college.edu", initials: "JW", program: "Nursing", site: "Sunrise Hospital",
68
+ siteAddress: "5775 Wayzata Blvd, Minneapolis, MN", status: "confirmed", start: "04/07/2026", duration: "12 wks", supervisor: "Dr. Torres",
69
+ placementPhase: "ongoing", internship: "ICU Practicum", specialization: "Critical Care", compliance: "Complete", daysUntilStart: 0,
70
+ readiness: "Ready", progressWeeksDone: 2, progressWeeksTotal: 12, endDate: "06/30/2026", lastCheckin: "03/21/2026",
71
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
72
+ },
73
+ {
74
+ id: 5, student: "Emily Davis", email: "e.davis@university.edu", initials: "ED", program: "Social Work", site: "Community Care",
75
+ siteAddress: "220 S State St, Chicago, IL", status: "rejected", start: "—", duration: "—", supervisor: "—",
76
+ placementPhase: "upcoming", internship: "Community SW Field", specialization: "Behavioral Health", compliance: "Incomplete", daysUntilStart: 0,
77
+ readiness: "Blocked", progressWeeksDone: 0, progressWeeksTotal: 10, endDate: "—", lastCheckin: "—",
78
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
79
+ },
80
+ {
81
+ id: 6, student: "Carlos Rivera", email: "c.rivera@school.edu", initials: "CR", program: "Physical Therapy", site: "Summit Sports Med",
82
+ siteAddress: "900 N Michigan Ave, Chicago, IL", status: "pending", start: "04/14/2026", duration: "8 wks", supervisor: "Dr. Lee",
83
+ placementPhase: "upcoming", internship: "Sports Medicine PT", specialization: "Sports Rehab", compliance: "Complete", daysUntilStart: 21,
84
+ readiness: "Ready", progressWeeksDone: 0, progressWeeksTotal: 8, endDate: "06/09/2026", lastCheckin: "—",
85
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
86
+ },
87
+ {
88
+ id: 7, student: "Priya Sharma", email: "p.sharma@college.edu", initials: "PS", program: "Nursing", site: "Harbor Medical",
89
+ siteAddress: "1200 W Harrison St, Chicago, IL", status: "confirmed", start: "03/22/2026", duration: "12 wks", supervisor: "Dr. Patel",
90
+ placementPhase: "ongoing", internship: "Pediatric Nursing", specialization: "Pediatrics", compliance: "Complete", daysUntilStart: 0,
91
+ readiness: "Ready", progressWeeksDone: 7, progressWeeksTotal: 12, endDate: "06/14/2026", lastCheckin: "03/23/2026",
92
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—", isNew: true,
93
+ },
94
+ {
95
+ id: 8, student: "Tom Bradley", email: "t.bradley@university.edu", initials: "TB", program: "Occupational Therapy", site: "Valley Health",
96
+ siteAddress: "4646 N Marine Dr, Chicago, IL", status: "under-review", start: "04/03/2026", duration: "10 wks", supervisor: "Dr. Wong",
97
+ placementPhase: "upcoming", internship: "Rehabilitation OT", specialization: "Neuro", compliance: "Review", daysUntilStart: 10,
98
+ readiness: "In review", progressWeeksDone: 0, progressWeeksTotal: 10, endDate: "06/12/2026", lastCheckin: "—",
99
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
100
+ },
101
+ {
102
+ id: 9, student: "Lena Fischer", email: "l.fischer@school.edu", initials: "LF", program: "Nursing", site: "Westside Clinic",
103
+ siteAddress: "2525 S Michigan Ave, Chicago, IL", status: "confirmed", start: "03/18/2026", duration: "12 wks", supervisor: "Dr. Santos",
104
+ placementPhase: "ongoing", internship: "Primary Care RN", specialization: "Family Practice", compliance: "Complete", daysUntilStart: 0,
105
+ readiness: "Ready", progressWeeksDone: 8, progressWeeksTotal: 12, endDate: "06/10/2026", lastCheckin: "03/24/2026",
106
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
107
+ },
108
+ {
109
+ id: 10, student: "Omar Hassan", email: "o.hassan@college.edu", initials: "OH", program: "Physical Therapy", site: "Metro Rehab",
110
+ siteAddress: "250 E Superior St, Chicago, IL", status: "pending", start: "04/21/2026", duration: "8 wks", supervisor: "Dr. Kim",
111
+ placementPhase: "upcoming", internship: "Neurologic PT", specialization: "Neuro Rehab", compliance: "Pending", daysUntilStart: 28,
112
+ readiness: "Ready", progressWeeksDone: 0, progressWeeksTotal: 8, endDate: "06/16/2026", lastCheckin: "—",
113
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
114
+ },
115
+ {
116
+ id: 11, student: "Nina Patel", email: "n.patel@university.edu", initials: "NP", program: "Social Work", site: "Hope Community Ctr",
117
+ siteAddress: "3517 W Arthington St, Chicago, IL", status: "confirmed", start: "03/25/2026", duration: "10 wks", supervisor: "Ms. Torres",
118
+ placementPhase: "ongoing", internship: "School Social Work", specialization: "Youth Services", compliance: "Complete", daysUntilStart: 0,
119
+ readiness: "Ready", progressWeeksDone: 4, progressWeeksTotal: 10, endDate: "06/03/2026", lastCheckin: "03/19/2026",
120
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
121
+ },
122
+ {
123
+ id: 12, student: "David Okonkwo", email: "d.okonkwo@school.edu", initials: "DO", program: "Nursing", site: "Lakeside Hospital",
124
+ siteAddress: "4440 N Clark St, Chicago, IL", status: "under-review", start: "04/10/2026", duration: "12 wks", supervisor: "Unassigned",
125
+ placementPhase: "upcoming", internship: "Emergency Dept RN", specialization: "Emergency", compliance: "Pending", daysUntilStart: 17,
126
+ readiness: "At risk", progressWeeksDone: 0, progressWeeksTotal: 12, endDate: "07/03/2026", lastCheckin: "—",
127
+ completionDate: "—", finalStatus: "—", rating: 0, suggestedToHire: "—",
128
+ },
129
+ {
130
+ id: 13, student: "Alex Morgan", email: "a.morgan@college.edu", initials: "AM", program: "Nursing", site: "City Medical Center",
131
+ siteAddress: "1400 N Lake Shore Dr, Chicago, IL", status: "completed", start: "01/06/2026", duration: "12 wks", supervisor: "Dr. Patel",
132
+ placementPhase: "completed", internship: "Med-Surg Clinical II", specialization: "Adult Health", compliance: "Complete", daysUntilStart: 0,
133
+ readiness: "Ready", progressWeeksDone: 12, progressWeeksTotal: 12, endDate: "03/30/2026", lastCheckin: "03/28/2026",
134
+ completionDate: "03/30/2026", finalStatus: "Passed", rating: 4.8, suggestedToHire: "Yes",
135
+ },
136
+ {
137
+ id: 14, student: "Jordan Lee", email: "j.lee@university.edu", initials: "JL", program: "Physical Therapy", site: "Metro Rehab",
138
+ siteAddress: "250 E Superior St, Chicago, IL", status: "completed", start: "11/04/2025", duration: "8 wks", supervisor: "Dr. Kim",
139
+ placementPhase: "completed", internship: "Inpatient PT", specialization: "Acute Care", compliance: "Complete", daysUntilStart: 0,
140
+ readiness: "Ready", progressWeeksDone: 8, progressWeeksTotal: 8, endDate: "12/30/2025", lastCheckin: "12/28/2025",
141
+ completionDate: "12/30/2025", finalStatus: "Passed", rating: 4.2, suggestedToHire: "Yes",
142
+ },
143
+ {
144
+ id: 15, student: "Sam Rivera", email: "s.rivera@school.edu", initials: "SR", program: "Occupational Therapy", site: "Bay Area Health",
145
+ siteAddress: "3100 Telegraph Ave, Oakland, CA", status: "completed", start: "10/01/2025", duration: "10 wks", supervisor: "Dr. Nguyen",
146
+ placementPhase: "completed", internship: "Hand Therapy OT", specialization: "Hand Therapy", compliance: "Complete", daysUntilStart: 0,
147
+ readiness: "Ready", progressWeeksDone: 10, progressWeeksTotal: 10, endDate: "12/10/2025", lastCheckin: "12/08/2025",
148
+ completionDate: "12/10/2025", finalStatus: "Incomplete", rating: 3.5, suggestedToHire: "No",
149
+ },
150
+ {
151
+ id: 16, student: "Taylor Brooks", email: "t.brooks@college.edu", initials: "TB", program: "Nursing", site: "Sunrise Hospital",
152
+ siteAddress: "5775 Wayzata Blvd, Minneapolis, MN", status: "completed", start: "09/02/2025", duration: "12 wks", supervisor: "Dr. Torres",
153
+ placementPhase: "completed", internship: "Labor & Delivery", specialization: "Women's Health", compliance: "Complete", daysUntilStart: 0,
154
+ readiness: "Ready", progressWeeksDone: 12, progressWeeksTotal: 12, endDate: "11/25/2025", lastCheckin: "11/22/2025",
155
+ completionDate: "11/25/2025", finalStatus: "Passed", rating: 5, suggestedToHire: "Yes",
156
+ },
157
+ ]
158
+
159
+ /** Distinct sorted values for filter dropdowns (list UI) on text-like columns. */
160
+ export function uniquePlacementFieldOptions(
161
+ key: keyof Placement,
162
+ ): { value: string; label: string }[] {
163
+ const set = new Set<string>()
164
+ for (const r of ALL_PLACEMENTS) {
165
+ const raw = r[key]
166
+ if (raw === undefined || raw === null) continue
167
+ const v = typeof raw === "number" ? String(raw) : String(raw).trim()
168
+ if (!v || v === "—") continue
169
+ set.add(v)
170
+ }
171
+ return [...set].sort((a, b) => a.localeCompare(b)).map(v => ({ value: v, label: v }))
172
+ }
173
+
174
+ export function getPlacementById(id: number): Placement | undefined {
175
+ return ALL_PLACEMENTS.find(p => p.id === id)
176
+ }
@@ -0,0 +1,16 @@
1
+ import { NAV_PRIMARY } from "@/lib/mock/navigation"
2
+
3
+ /** Clinical site row — same source as legacy Sites nav children. */
4
+ export interface SiteDirectoryRow extends Record<string, unknown> {
5
+ id: string
6
+ name: string
7
+ url: string
8
+ }
9
+
10
+ export const SITES_DIRECTORY: SiteDirectoryRow[] = (NAV_PRIMARY.find(i => i.key === "sites")?.children ?? []).map(
11
+ c => ({
12
+ id: c.key,
13
+ name: c.title,
14
+ url: c.url,
15
+ }),
16
+ )
@@ -0,0 +1,25 @@
1
+ import type { MetricInsight, MetricItem } from "@/components/key-metrics"
2
+
3
+ export function sitesKpiMetrics(count: number): MetricItem[] {
4
+ const active = Math.max(0, count - 3)
5
+ const pending = Math.min(count, 3)
6
+ return [
7
+ {
8
+ id: "total-sites",
9
+ label: "Total sites",
10
+ value: count,
11
+ delta: "+4",
12
+ trend: "up",
13
+ href: "#",
14
+ metricVariant: "hero",
15
+ },
16
+ { id: "active", label: "Active", value: active, delta: "+3", trend: "up", href: "#" },
17
+ { id: "pending", label: "Pending", value: pending, delta: "—", trend: "neutral", href: "#" },
18
+ { id: "archived", label: "Archived", value: 0, delta: "—", trend: "neutral", href: "#" },
19
+ ]
20
+ }
21
+
22
+ export const SITES_KPI_INSIGHT: MetricInsight = {
23
+ title: "4 new sites added this month",
24
+ description: "Most recent additions are affiliated with the Nursing program.",
25
+ }
@@ -0,0 +1,60 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // Team page — KPI strip (mirrors placements-kpi pattern for primary list template)
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+
5
+ import type { MetricInsight, MetricItem } from "@/components/key-metrics"
6
+ import type { TeamMember } from "@/lib/mock/team"
7
+
8
+ export function teamKpiMetrics(members: TeamMember[]): MetricItem[] {
9
+ const active = members.filter(m => m.status === "active").length
10
+ const away = members.filter(m => m.status === "away").length
11
+ const invited = members.filter(m => m.status === "invited").length
12
+ return [
13
+ {
14
+ id: "total-members",
15
+ label: "Total members",
16
+ value: members.length,
17
+ delta: "+2",
18
+ trend: "up",
19
+ href: "#",
20
+ metricVariant: "hero",
21
+ },
22
+ {
23
+ id: "active",
24
+ label: "Active",
25
+ value: active,
26
+ delta: "—",
27
+ trend: "neutral",
28
+ href: "#",
29
+ },
30
+ {
31
+ id: "away",
32
+ label: "Away",
33
+ value: away,
34
+ delta: "—",
35
+ trend: "neutral",
36
+ href: "#",
37
+ },
38
+ {
39
+ id: "invited",
40
+ label: "Invited",
41
+ value: invited,
42
+ delta: invited > 0 ? "+1" : "—",
43
+ trend: invited > 0 ? "up" : "neutral",
44
+ href: "#",
45
+ },
46
+ ]
47
+ }
48
+
49
+ export function teamKpiInsight(members: TeamMember[]): MetricInsight {
50
+ const invited = members.filter(m => m.status === "invited").length
51
+ return {
52
+ title: "Pending invites",
53
+ description:
54
+ invited > 0
55
+ ? `${invited} invitation(s) outstanding. Resend or revoke from the roster.`
56
+ : "No pending invitations.",
57
+ severity: invited > 0 ? "warning" : "info",
58
+ actionLabel: "Ask Leo",
59
+ }
60
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Mock team directory — replace with API data in production.
3
+ * Kept at 11+ rows so the Team page demonstrates search / sort / properties toolbar (see data-views-pattern.md).
4
+ */
5
+
6
+ export interface TeamMember extends Record<string, unknown> {
7
+ id: string
8
+ name: string
9
+ role: string
10
+ email: string
11
+ /** US 10-digit storage (filter uses masked entry; matching normalizes digits). */
12
+ phone: string
13
+ initials: string
14
+ /** Shown as a subtle status chip */
15
+ status: "active" | "away" | "invited"
16
+ }
17
+
18
+ export const TEAM_MEMBERS: TeamMember[] = [
19
+ {
20
+ id: "1",
21
+ name: "Alex Rivera",
22
+ role: "Program Administrator",
23
+ email: "alex.rivera@school.edu",
24
+ phone: "5550100001",
25
+ initials: "AR",
26
+ status: "active",
27
+ },
28
+ {
29
+ id: "2",
30
+ name: "Jordan Chen",
31
+ role: "Clinical Coordinator",
32
+ email: "jordan.chen@school.edu",
33
+ phone: "5550100002",
34
+ initials: "JC",
35
+ status: "active",
36
+ },
37
+ {
38
+ id: "3",
39
+ name: "Sam Patel",
40
+ role: "Field Education",
41
+ email: "sam.patel@school.edu",
42
+ phone: "5550100003",
43
+ initials: "SP",
44
+ status: "away",
45
+ },
46
+ {
47
+ id: "4",
48
+ name: "Taylor Brooks",
49
+ role: "Viewer",
50
+ email: "taylor.brooks@school.edu",
51
+ phone: "5550100004",
52
+ initials: "TB",
53
+ status: "invited",
54
+ },
55
+ {
56
+ id: "5",
57
+ name: "Morgan Lee",
58
+ role: "Program Administrator",
59
+ email: "morgan.lee@school.edu",
60
+ phone: "5550100005",
61
+ initials: "ML",
62
+ status: "active",
63
+ },
64
+ {
65
+ id: "6",
66
+ name: "Casey Nguyen",
67
+ role: "Clinical Coordinator",
68
+ email: "casey.nguyen@school.edu",
69
+ phone: "5550100006",
70
+ initials: "CN",
71
+ status: "active",
72
+ },
73
+ {
74
+ id: "7",
75
+ name: "Riley Johnson",
76
+ role: "Field Education",
77
+ email: "riley.johnson@school.edu",
78
+ phone: "5550100007",
79
+ initials: "RJ",
80
+ status: "away",
81
+ },
82
+ {
83
+ id: "8",
84
+ name: "Quinn Martinez",
85
+ role: "Viewer",
86
+ email: "quinn.martinez@school.edu",
87
+ phone: "5550100008",
88
+ initials: "QM",
89
+ status: "active",
90
+ },
91
+ {
92
+ id: "9",
93
+ name: "Jamie Wilson",
94
+ role: "Program Administrator",
95
+ email: "jamie.wilson@school.edu",
96
+ phone: "5550100009",
97
+ initials: "JW",
98
+ status: "invited",
99
+ },
100
+ {
101
+ id: "10",
102
+ name: "Drew Anderson",
103
+ role: "Clinical Coordinator",
104
+ email: "drew.anderson@school.edu",
105
+ phone: "5550100010",
106
+ initials: "DA",
107
+ status: "active",
108
+ },
109
+ {
110
+ id: "11",
111
+ name: "Skyler Kim",
112
+ role: "Field Education",
113
+ email: "skyler.kim@school.edu",
114
+ phone: "5550100011",
115
+ initials: "SK",
116
+ status: "active",
117
+ },
118
+ ]
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Board placement card layout — which fields appear on the card by default,
3
+ * which keys are grouped into header / site / schedule blocks, and helpers to
4
+ * resolve "active" fields against current column visibility.
5
+ *
6
+ * Previously parameterized by `lifecycleTabId` (all / upcoming / ongoing / completed).
7
+ * Lifecycle has been removed — one canonical card definition is used everywhere
8
+ * and the card falls back to existing row data when a column is hidden.
9
+ */
10
+
11
+ import type { ColumnDef } from "@/components/data-table/types"
12
+ import type { Placement } from "@/lib/mock/placements"
13
+
14
+ /** Default card fields — intersected with visible table columns (except header-only rules below). */
15
+ export const DEFAULT_BOARD_CARD_KEYS: readonly string[] = [
16
+ "student",
17
+ "specialization",
18
+ "site",
19
+ "status",
20
+ "internship",
21
+ "start",
22
+ "duration",
23
+ "progressWeeksDone",
24
+ "endDate",
25
+ "daysUntilStart",
26
+ "completionDate",
27
+ "finalStatus",
28
+ ]
29
+
30
+ export const SCHEDULE_KEYS: readonly string[] = [
31
+ "start",
32
+ "duration",
33
+ "daysUntilStart",
34
+ "progressWeeksDone",
35
+ "endDate",
36
+ "completionDate",
37
+ "finalStatus",
38
+ ]
39
+
40
+ /** Keys rendered in the title/header cluster (not as icon rows). */
41
+ export function consumedKeysForCard(): Set<string> {
42
+ return new Set<string>(["student", "status", "site", ...SCHEDULE_KEYS])
43
+ }
44
+
45
+ export function isKeyInBoardWhitelist(key: string): boolean {
46
+ return DEFAULT_BOARD_CARD_KEYS.includes(key)
47
+ }
48
+
49
+ /**
50
+ * Field is allowed on the card when it is in the whitelist, not hidden, and either
51
+ * the column exists in this view and is visible, or the column does not exist —
52
+ * then we still show from row data for header/summary fields.
53
+ */
54
+ export function isBoardFieldActive<Row extends Placement>(
55
+ key: string,
56
+ hiddenColKeys: Set<string>,
57
+ boardColumns: ColumnDef<Row>[],
58
+ ): boolean {
59
+ if (hiddenColKeys.has(key)) return false
60
+ if (!isKeyInBoardWhitelist(key)) return false
61
+ const hasCol = boardColumns.some(c => c.key === key)
62
+ if (!hasCol) return true
63
+ return boardColumns.some(c => c.key === key && !hiddenColKeys.has(c.key))
64
+ }
65
+
66
+ /** Visible columns that pass whitelist (intersection). Order follows boardColumns. */
67
+ export function filterColumnsForBoardCard<Row extends Placement>(
68
+ visibleCols: ColumnDef<Row>[],
69
+ ): ColumnDef<Row>[] {
70
+ return visibleCols.filter(c => isKeyInBoardWhitelist(c.key))
71
+ }
72
+
73
+ /** Body rows only: columns not consumed by title, header badges, site block, or schedule block. */
74
+ export function remainingBodyColumns<Row extends Placement>(
75
+ cardCols: ColumnDef<Row>[],
76
+ ): ColumnDef<Row>[] {
77
+ const consumed = consumedKeysForCard()
78
+ return cardCols.filter(c => !consumed.has(c.key))
79
+ }
@@ -0,0 +1,12 @@
1
+ import type { DataListViewType } from "@/lib/data-list-view"
2
+
3
+ /** Views implemented in `PlacementsTable` — keep in sync with the renderers passed to `HubTable`. */
4
+ export const PLACEMENTS_SUPPORTED_VIEWS = [
5
+ "table",
6
+ "list",
7
+ "board",
8
+ "dashboard",
9
+ "folder",
10
+ "panel",
11
+ "tree-panel",
12
+ ] as const satisfies readonly DataListViewType[]
@@ -6,7 +6,6 @@ export const QUESTION_BANK_SUPPORTED_VIEWS = [
6
6
  "list",
7
7
  "board",
8
8
  "dashboard",
9
- "calendar",
10
9
  "folder",
11
10
  "panel",
12
11
  "tree-panel",
@@ -1,45 +1 @@
1
- /**
2
- * Coalesce many calls to `fn` into one per animation frame.
3
- *
4
- * Use for high-frequency layout-reading event handlers (scroll, resize,
5
- * visualViewport, ResizeObserver) where the work must happen in a frame but
6
- * doing it on every event call (60+/s for resize, hundreds/s for capture
7
- * scrolls) wastes layout/paint cycles. The returned function exposes
8
- * `.cancel()` so effect cleanup can drop a pending frame.
9
- *
10
- * Pattern:
11
- * const apply = () => { ...layout reads + setState... }
12
- * const scheduled = rafThrottle(apply)
13
- * window.addEventListener("scroll", scheduled, { passive: true, capture: true })
14
- * return () => {
15
- * scheduled.cancel()
16
- * window.removeEventListener("scroll", scheduled, { capture: true })
17
- * }
18
- */
19
- export function rafThrottle<TArgs extends unknown[]>(
20
- fn: (...args: TArgs) => void,
21
- ): ((...args: TArgs) => void) & { cancel: () => void } {
22
- let rafId = 0
23
- let lastArgs: TArgs | null = null
24
-
25
- const scheduled = ((...args: TArgs) => {
26
- lastArgs = args
27
- if (rafId !== 0) return
28
- rafId = requestAnimationFrame(() => {
29
- rafId = 0
30
- const a = lastArgs
31
- lastArgs = null
32
- if (a) fn(...a)
33
- })
34
- }) as ((...args: TArgs) => void) & { cancel: () => void }
35
-
36
- scheduled.cancel = () => {
37
- if (rafId !== 0) {
38
- cancelAnimationFrame(rafId)
39
- rafId = 0
40
- }
41
- lastArgs = null
42
- }
43
-
44
- return scheduled
45
- }
1
+ export { rafThrottle } from "@exxatdesignux/ui/lib/raf-throttle"
@@ -1,10 +1,4 @@
1
- /**
2
- * Table row density — shared by Properties drawer tiles and useTableState.
3
- */
4
- export type RowHeight = "compact" | "default" | "comfortable"
5
-
6
- export const ROW_HEIGHT_TILES: readonly { value: RowHeight; label: string; icon: string }[] = [
7
- { value: "compact", label: "Compact", icon: "fa-down-to-line" },
8
- { value: "default", label: "Default", icon: "fa-arrows-up-down" },
9
- { value: "comfortable", label: "Comfortable", icon: "fa-up-to-line" },
10
- ]
1
+ export {
2
+ ROW_HEIGHT_TILES,
3
+ type RowHeight,
4
+ } from "@exxatdesignux/ui/lib/row-height"
@@ -1,9 +1,18 @@
1
- /** Cookie name persisted by `@exxatdesignux/ui` `SidebarProvider` (`setOpen`). */
2
- export const SIDEBAR_STATE_COOKIE_NAME = "sidebar_state"
1
+ /**
2
+ * Cookie name persisted by `@exxatdesignux/ui` `SidebarProvider` (`setOpen`).
3
+ *
4
+ * Versioned (`_v2`) on 2026-05-21 to drop stale values written by the pre-fix
5
+ * code where incidental layout collapses clobbered the user's preference on
6
+ * every navigation. The legacy `sidebar_state` cookie (without `_v2`) is
7
+ * ignored on the server and actively deleted client-side on first mount.
8
+ */
9
+ export const SIDEBAR_STATE_COOKIE_NAME = "sidebar_state_v2"
3
10
 
4
11
  /** Read desktop sidebar expanded state for SSR `defaultOpen` (matches client cookie restore). */
5
12
  export function sidebarDefaultOpenFromCookie(
6
13
  value: string | undefined,
7
14
  ): boolean {
15
+ // No cookie OR malformed value → default expanded.
16
+ // Only an exact `"false"` from the new cookie counts as a saved collapsed preference.
8
17
  return value !== "false"
9
18
  }
@@ -0,0 +1,10 @@
1
+ import type { DataListViewType } from "@/lib/data-list-view"
2
+
3
+ /** Views implemented in `SitesTable` — keep in sync with the renderers passed to `HubTable`. */
4
+ export const SITES_SUPPORTED_VIEWS = [
5
+ "table",
6
+ "list",
7
+ "board",
8
+ "panel",
9
+ "dashboard",
10
+ ] as const satisfies readonly DataListViewType[]
@@ -26,7 +26,7 @@ import type { RowHeight } from "@/lib/row-height"
26
26
  import type { DataListDisplayOptions } from "@/lib/data-list-display-options"
27
27
  import type { ActiveFilter, ConditionalRule, SortRule } from "@/components/table-properties/types"
28
28
  import type { ViewTab } from "@/components/templates/list-page"
29
- import { DATA_LIST_VIEW_TILES, type DataListViewType } from "@/lib/data-list-view"
29
+ import type { DataListViewType } from "@/lib/data-list-view"
30
30
 
31
31
  // ─────────────────────────────────────────────────────────────────────────────
32
32
  // Storage key + debounce config
@@ -139,7 +139,7 @@ export interface TableStatePersistSlice {
139
139
  // Parsers + validators
140
140
  // ─────────────────────────────────────────────────────────────────────────────
141
141
 
142
- const VIEW_TYPES: DataListViewType[] = DATA_LIST_VIEW_TILES.map(t => t.value)
142
+ const VIEW_TYPES: DataListViewType[] = ["table", "list", "board", "dashboard"]
143
143
 
144
144
  function isViewType(v: unknown): v is DataListViewType {
145
145
  return typeof v === "string" && (VIEW_TYPES as string[]).includes(v)
@@ -0,0 +1,10 @@
1
+ import type { DataListViewType } from "@/lib/data-list-view"
2
+
3
+ /** Views implemented in `TeamTable` — keep in sync with the renderers passed to `HubTable`. */
4
+ export const TEAM_SUPPORTED_VIEWS = [
5
+ "table",
6
+ "list",
7
+ "board",
8
+ "panel",
9
+ "dashboard",
10
+ ] as const satisfies readonly DataListViewType[]
@@ -60,6 +60,7 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@eslint/eslintrc": "^3",
63
+ "@exxatdesignux/eslint-plugin": "workspace:*",
63
64
  "@next/bundle-analyzer": "16.2.6",
64
65
  "@tailwindcss/postcss": "^4.2.1",
65
66
  "@testing-library/jest-dom": "^6.9.1",