@exxatdesignux/ui 0.5.11 → 0.5.12

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 (476) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/bin/cli.mjs +70 -1
  3. package/bin/init.mjs +18 -4
  4. package/bin/sync-extras.mjs +28 -4
  5. package/consumer-extras/README.md +41 -5
  6. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +2 -1
  7. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +5 -3
  8. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +1 -0
  9. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +1 -0
  10. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +4 -2
  11. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +1 -0
  12. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +3 -2
  13. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +5 -3
  14. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +7 -0
  15. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +2 -1
  16. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +1 -0
  17. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +1 -0
  18. package/consumer-extras/cursor-rules/exxat-hub-supported-views.mdc +6 -4
  19. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +6 -5
  20. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +1 -0
  21. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +1 -0
  22. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +1 -0
  23. package/consumer-extras/cursor-rules/exxat-library-hub-header.mdc +2 -1
  24. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +6 -2
  25. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +2 -1
  26. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +2 -1
  27. package/consumer-extras/cursor-rules/exxat-nav-single-active.mdc +4 -3
  28. package/consumer-extras/cursor-rules/exxat-no-image-pixel-copy.mdc +25 -14
  29. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +8 -2
  30. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +1 -0
  31. package/consumer-extras/cursor-rules/exxat-no-vaul.mdc +2 -1
  32. package/consumer-extras/cursor-rules/exxat-page-header-actions.mdc +6 -4
  33. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +2 -1
  34. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +1 -0
  35. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +2 -1
  36. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +1 -0
  37. package/consumer-extras/cursor-rules/exxat-sidebar-shell.mdc +13 -7
  38. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +5 -3
  39. package/consumer-extras/cursor-rules/exxat-table-row-preview.mdc +1 -0
  40. package/consumer-extras/cursor-rules/exxat-tabs-chrome.mdc +6 -4
  41. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +6 -0
  42. package/consumer-extras/cursor-rules/exxat-ux-discovery-protocol.mdc +28 -0
  43. package/consumer-extras/cursor-rules/exxat-ux-principles.mdc +1 -0
  44. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +1 -1
  45. package/consumer-extras/cursor-skills/exxat-kpi-trends/SKILL.md +5 -3
  46. package/consumer-extras/patterns/command-menu-pattern.md +2 -2
  47. package/consumer-extras/patterns/consumer-upgrade-checklist.md +1 -1
  48. package/consumer-extras/patterns/jobs/README.md +1 -1
  49. package/consumer-extras/patterns/perf-memory-pattern.md +115 -150
  50. package/consumer-extras/scripts/dev-guard.mjs +156 -0
  51. package/consumer-extras/templates/README.md +23 -0
  52. package/consumer-extras/templates/handoff.md +190 -0
  53. package/package.json +2 -2
  54. package/{template → template-vite}/.claude/skills/exxat-ds-skill/SKILL.md +184 -23
  55. package/template-vite/.cursor/rules/exxat-accessibility.mdc +40 -0
  56. package/template-vite/.cursor/rules/exxat-board-cards.mdc +28 -0
  57. package/template-vite/.cursor/rules/exxat-breadcrumbs-no-back.mdc +22 -0
  58. package/template-vite/.cursor/rules/exxat-card-vs-list-rows.mdc +22 -0
  59. package/template-vite/.cursor/rules/exxat-centralized-list-dataset.mdc +46 -0
  60. package/template-vite/.cursor/rules/exxat-collaboration-access.mdc +33 -0
  61. package/{template → template-vite}/.cursor/rules/exxat-command-menu.mdc +5 -5
  62. package/template-vite/.cursor/rules/exxat-data-tables.mdc +47 -0
  63. package/template-vite/.cursor/rules/exxat-dedicated-search-surfaces.mdc +32 -0
  64. package/template-vite/.cursor/rules/exxat-drawer-vs-dialog.mdc +23 -0
  65. package/template-vite/.cursor/rules/exxat-ds-agents.mdc +87 -0
  66. package/template-vite/.cursor/rules/exxat-fontawesome-icons.mdc +32 -0
  67. package/template-vite/.cursor/rules/exxat-hub-supported-views.mdc +56 -0
  68. package/{template → template-vite}/.cursor/rules/exxat-kbd-shortcuts.mdc +1 -0
  69. package/template-vite/.cursor/rules/exxat-kpi-flat-band.mdc +29 -0
  70. package/template-vite/.cursor/rules/exxat-kpi-max-four.mdc +22 -0
  71. package/template-vite/.cursor/rules/exxat-kpi-trends.mdc +32 -0
  72. package/template-vite/.cursor/rules/exxat-library-hub-header.mdc +29 -0
  73. package/template-vite/.cursor/rules/exxat-list-page-connected-views.mdc +28 -0
  74. package/template-vite/.cursor/rules/exxat-list-page-view-shells.mdc +32 -0
  75. package/{template → template-vite}/.cursor/rules/exxat-mono-ids.mdc +1 -0
  76. package/template-vite/.cursor/rules/exxat-nav-single-active.mdc +32 -0
  77. package/template-vite/.cursor/rules/exxat-no-image-pixel-copy.mdc +46 -0
  78. package/template-vite/.cursor/rules/exxat-no-slds-leakage.mdc +84 -0
  79. package/{template → template-vite}/.cursor/rules/exxat-no-toast.mdc +2 -2
  80. package/template-vite/.cursor/rules/exxat-no-vaul.mdc +26 -0
  81. package/template-vite/.cursor/rules/exxat-page-header-actions.mdc +33 -0
  82. package/{template → template-vite}/.cursor/rules/exxat-page-vs-drawer.mdc +5 -3
  83. package/template-vite/.cursor/rules/exxat-person-identity-display.mdc +48 -0
  84. package/template-vite/.cursor/rules/exxat-primary-nav-secondary-panel.mdc +53 -0
  85. package/template-vite/.cursor/rules/exxat-reuse-before-custom.mdc +37 -0
  86. package/template-vite/.cursor/rules/exxat-sidebar-shell.mdc +41 -0
  87. package/template-vite/.cursor/rules/exxat-table-properties-drawer.mdc +79 -0
  88. package/template-vite/.cursor/rules/exxat-table-row-preview.mdc +25 -0
  89. package/template-vite/.cursor/rules/exxat-tabs-chrome.mdc +33 -0
  90. package/template-vite/.cursor/rules/exxat-token-discipline.mdc +109 -0
  91. package/template-vite/.cursor/rules/exxat-ux-discovery-protocol.mdc +202 -0
  92. package/template-vite/.cursor/rules/exxat-ux-principles.mdc +187 -0
  93. package/template-vite/.cursor/skills/exxat-accessibility/SKILL.md +282 -0
  94. package/template-vite/.cursor/skills/exxat-board-cards/SKILL.md +68 -0
  95. package/template-vite/.cursor/skills/exxat-card-vs-list-rows/SKILL.md +20 -0
  96. package/template-vite/.cursor/skills/exxat-centralized-list-dataset/SKILL.md +99 -0
  97. package/template-vite/.cursor/skills/exxat-collaboration-access/SKILL.md +35 -0
  98. package/template-vite/.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md +45 -0
  99. package/template-vite/.cursor/skills/exxat-drawer-vs-dialog/SKILL.md +20 -0
  100. package/template-vite/.cursor/skills/exxat-ds-skill/SKILL.md +893 -0
  101. package/template-vite/.cursor/skills/exxat-ds-skill/references/accessibility.md +142 -0
  102. package/template-vite/.cursor/skills/exxat-ds-skill/references/coach-marks.md +169 -0
  103. package/template-vite/.cursor/skills/exxat-ds-skill/references/data-table-pattern.md +392 -0
  104. package/template-vite/.cursor/skills/exxat-fontawesome-icons/SKILL.md +31 -0
  105. package/template-vite/.cursor/skills/exxat-kpi-flat-band/SKILL.md +38 -0
  106. package/template-vite/.cursor/skills/exxat-kpi-max-four/SKILL.md +19 -0
  107. package/template-vite/.cursor/skills/exxat-kpi-trends/SKILL.md +29 -0
  108. package/template-vite/.cursor/skills/exxat-list-page-view-shells/SKILL.md +36 -0
  109. package/template-vite/.cursor/skills/exxat-mono-ids/SKILL.md +56 -0
  110. package/template-vite/.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md +49 -0
  111. package/template-vite/.cursor/skills/exxat-senior-ux/SKILL.md +198 -0
  112. package/template-vite/.cursor/skills/exxat-token-economy/SKILL.md +287 -0
  113. package/template-vite/.cursor/skills/exxat-ux-audit/SKILL.md +303 -0
  114. package/{template → template-vite}/components/ask-leo-sidebar.tsx +10 -8
  115. package/{template → template-vite}/components/command-menu.tsx +1 -1
  116. package/{template → template-vite}/components/data-views/library-folder-tree-branch.tsx +1 -1
  117. package/{template → template-vite}/components/dedicated-search-recents.tsx +1 -1
  118. package/{template → template-vite}/components/dedicated-search-url-composer.tsx +1 -1
  119. package/{template → template-vite}/components/library-client.tsx +1 -1
  120. package/{template → template-vite}/components/library-hub-client.tsx +2 -2
  121. package/{template → template-vite}/components/library-secondary-nav.tsx +2 -2
  122. package/{template → template-vite}/components/library-table.tsx +35 -27
  123. package/{template → template-vite}/components/new-library-item-form.tsx +1 -1
  124. package/{template → template-vite}/components/page-breadcrumb-trail.tsx +1 -1
  125. package/{template → template-vite}/components/settings-client.tsx +1 -1
  126. package/{template → template-vite}/components/sidebar/app-sidebar.tsx +2 -2
  127. package/{template → template-vite}/components/sidebar/nav-main.tsx +1 -1
  128. package/{template → template-vite}/components/sidebar/nav-user.tsx +1 -1
  129. package/{template → template-vite}/components/sidebar/secondary-nav.tsx +1 -1
  130. package/{template → template-vite}/components/system-banner-slot.tsx +1 -1
  131. package/{template → template-vite}/components/templates/discovery-hub-template.tsx +2 -2
  132. package/{template → template-vite}/components/templates/new-focus-template.tsx +1 -1
  133. package/{template → template-vite}/components/tokens-secondary-nav.tsx +2 -2
  134. package/{template → template-vite}/components/tokens-themes-client.tsx +1 -1
  135. package/{template → template-vite}/hooks/use-secondary-panel-hub-nav.ts +1 -1
  136. package/template-vite/index.html +49 -0
  137. package/template-vite/lib/next-compat.tsx +98 -0
  138. package/{template → template-vite}/package.json +15 -27
  139. package/template-vite/scripts/port-next-imports.mjs +70 -0
  140. package/template-vite/src/App.tsx +103 -0
  141. package/template-vite/src/main.tsx +50 -0
  142. package/{template/app/(app)/error.tsx → template-vite/src/pages/_error.tsx} +12 -24
  143. package/{template/app/(app)/loading.tsx → template-vite/src/pages/_loading.tsx} +4 -2
  144. package/template-vite/src/pages/_not-found.tsx +17 -0
  145. package/template-vite/src/pages/dashboard.tsx +48 -0
  146. package/{template/app/(app)/help/page.tsx → template-vite/src/pages/help.tsx} +3 -2
  147. package/{template/app/(app)/library/layout.tsx → template-vite/src/pages/library/_layout.tsx} +18 -16
  148. package/{template/app/(app)/library/all/page.tsx → template-vite/src/pages/library/all.tsx} +1 -1
  149. package/{template/app/(app)/library/new/page.tsx → template-vite/src/pages/library/new.tsx} +12 -18
  150. package/template-vite/src/routes.tsx +72 -0
  151. package/{template/app → template-vite/src/styles}/globals.css +6 -2
  152. package/{template → template-vite}/tsconfig.json +5 -14
  153. package/template-vite/vite.config.ts +52 -0
  154. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +0 -53
  155. package/template/.agents/skills/shadcn/SKILL.md +0 -242
  156. package/template/.agents/skills/shadcn/agents/openai.yml +0 -5
  157. package/template/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
  158. package/template/.agents/skills/shadcn/assets/shadcn.png +0 -0
  159. package/template/.agents/skills/shadcn/cli.md +0 -257
  160. package/template/.agents/skills/shadcn/customization.md +0 -202
  161. package/template/.agents/skills/shadcn/evals/evals.json +0 -47
  162. package/template/.agents/skills/shadcn/mcp.md +0 -94
  163. package/template/.agents/skills/shadcn/rules/base-vs-radix.md +0 -306
  164. package/template/.agents/skills/shadcn/rules/composition.md +0 -195
  165. package/template/.agents/skills/shadcn/rules/forms.md +0 -192
  166. package/template/.agents/skills/shadcn/rules/icons.md +0 -101
  167. package/template/.agents/skills/shadcn/rules/styling.md +0 -162
  168. package/template/.cursor/rules/exxat-accessibility.mdc +0 -33
  169. package/template/.cursor/rules/exxat-data-tables.mdc +0 -32
  170. package/template/.cursor/rules/exxat-ds-agents.mdc +0 -26
  171. package/template/.cursor/rules/exxat-list-page-connected-views.mdc +0 -16
  172. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +0 -40
  173. package/template/.nvmrc +0 -1
  174. package/template/.prettierignore +0 -7
  175. package/template/Logo/Exxat_Prism.svg +0 -39
  176. package/template/Logo/Exxat_one.svg +0 -36
  177. package/template/app/(app)/dashboard/loading.tsx +0 -18
  178. package/template/app/(app)/dashboard/page.tsx +0 -36
  179. package/template/app/(app)/layout.tsx +0 -77
  180. package/template/app/global-error.tsx +0 -63
  181. package/template/app/layout.tsx +0 -133
  182. package/template/app/page.tsx +0 -9
  183. package/template/docs/HANDBOOK.md +0 -187
  184. package/template/docs/blueprints/README.md +0 -86
  185. package/template/docs/blueprints/_template.md +0 -91
  186. package/template/docs/blueprints/board-card.md +0 -123
  187. package/template/docs/blueprints/data-table.md +0 -139
  188. package/template/docs/blueprints/key-metrics.md +0 -128
  189. package/template/docs/blueprints/list-page-template.md +0 -123
  190. package/template/docs/blueprints/page-header.md +0 -130
  191. package/template/docs/card-vs-rows-pattern.md +0 -36
  192. package/template/docs/collaboration-access-pattern.md +0 -116
  193. package/template/docs/command-menu-pattern.md +0 -45
  194. package/template/docs/component-selection-guide.md +0 -224
  195. package/template/docs/components-audit-2026-05.md +0 -158
  196. package/template/docs/consumer-upgrade-checklist.md +0 -52
  197. package/template/docs/data-views-pattern.md +0 -185
  198. package/template/docs/drawer-vs-dialog-pattern.md +0 -50
  199. package/template/docs/glossary.md +0 -59
  200. package/template/docs/hub-supported-views-pattern.md +0 -53
  201. package/template/docs/jobs/README.md +0 -59
  202. package/template/docs/jobs/record-detail.md +0 -177
  203. package/template/docs/kpi-flat-band-pattern.md +0 -57
  204. package/template/docs/kpi-strip-max-four-pattern.md +0 -30
  205. package/template/docs/kpi-trend-pattern.md +0 -58
  206. package/template/docs/large-dataset-strategy.md +0 -155
  207. package/template/docs/library-hub-header-pattern.md +0 -25
  208. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +0 -95
  209. package/template/docs/migrations/0002-exxat-token-namespace.md +0 -154
  210. package/template/docs/migrations/0003-globals-css-canonical.md +0 -110
  211. package/template/docs/migrations/README.md +0 -100
  212. package/template/docs/migrations/_template.md +0 -64
  213. package/template/docs/modern-saas-patterns.md +0 -165
  214. package/template/docs/perf-memory-pattern.md +0 -206
  215. package/template/docs/reference-implementations.md +0 -153
  216. package/template/docs/shell-surface-elevation-pattern.md +0 -52
  217. package/template/docs/token-taxonomy.md +0 -416
  218. package/template/docs/voice-and-tone.md +0 -262
  219. package/template/ecosystem.config.cjs +0 -32
  220. package/template/next.config.mjs +0 -216
  221. package/template/postcss.config.mjs +0 -8
  222. package/template/public/favicon/favicon.ico +0 -0
  223. package/template/tests/setup.ts +0 -26
  224. package/template/vitest.config.ts +0 -18
  225. /package/{template → template-vite}/.cursor/rules/exxat-dashboard-view-charts.mdc +0 -0
  226. /package/{template → template-vite}/.prettierrc +0 -0
  227. /package/{template → template-vite}/AGENTS.md +0 -0
  228. /package/{template → template-vite}/README.md +0 -0
  229. /package/{template → template-vite}/components/.gitkeep +0 -0
  230. /package/{template → template-vite}/components/ask-leo-composer.tsx +0 -0
  231. /package/{template → template-vite}/components/brand-color-picker.tsx +0 -0
  232. /package/{template → template-vite}/components/chart-area-interactive.tsx +0 -0
  233. /package/{template → template-vite}/components/charts-overview.tsx +0 -0
  234. /package/{template → template-vite}/components/collaboration-access-flow.tsx +0 -0
  235. /package/{template → template-vite}/components/columns-client.tsx +0 -0
  236. /package/{template → template-vite}/components/columns-showcase.tsx +0 -0
  237. /package/{template → template-vite}/components/dashboard-promo-banner.tsx +0 -0
  238. /package/{template → template-vite}/components/dashboard-quota-progress-card.tsx +0 -0
  239. /package/{template → template-vite}/components/dashboard-report-charts.tsx +0 -0
  240. /package/{template → template-vite}/components/dashboard-section-heading.tsx +0 -0
  241. /package/{template → template-vite}/components/dashboard-tabs.tsx +0 -0
  242. /package/{template → template-vite}/components/data-table/filter-date-calendar.tsx +0 -0
  243. /package/{template → template-vite}/components/data-table/filter-text-value-input.tsx +0 -0
  244. /package/{template → template-vite}/components/data-table/index.tsx +0 -0
  245. /package/{template → template-vite}/components/data-table/pagination.tsx +0 -0
  246. /package/{template → template-vite}/components/data-table/types.ts +0 -0
  247. /package/{template → template-vite}/components/data-table/use-table-state.test.ts +0 -0
  248. /package/{template → template-vite}/components/data-table/use-table-state.ts +0 -0
  249. /package/{template → template-vite}/components/data-views/board-card-primitives.tsx +0 -0
  250. /package/{template → template-vite}/components/data-views/data-row-list.tsx +0 -0
  251. /package/{template → template-vite}/components/data-views/finder-panel-view.tsx +0 -0
  252. /package/{template → template-vite}/components/data-views/folder-grid-view.tsx +0 -0
  253. /package/{template → template-vite}/components/data-views/hub-table.tsx +0 -0
  254. /package/{template → template-vite}/components/data-views/index.ts +0 -0
  255. /package/{template → template-vite}/components/data-views/list-page-board-card.tsx +0 -0
  256. /package/{template → template-vite}/components/data-views/list-page-board-template.tsx +0 -0
  257. /package/{template → template-vite}/components/data-views/list-page-connected-view-body.tsx +0 -0
  258. /package/{template → template-vite}/components/data-views/list-page-split-details-placeholder.tsx +0 -0
  259. /package/{template → template-vite}/components/data-views/list-page-split-hub-chrome.tsx +0 -0
  260. /package/{template → template-vite}/components/data-views/list-page-split-hub-tokens.ts +0 -0
  261. /package/{template → template-vite}/components/data-views/list-page-tree-column-header.tsx +0 -0
  262. /package/{template → template-vite}/components/data-views/list-page-tree-panel-shell.tsx +0 -0
  263. /package/{template → template-vite}/components/data-views/list-page-view-frame.tsx +0 -0
  264. /package/{template → template-vite}/components/data-views/os-folder-glyph.tsx +0 -0
  265. /package/{template → template-vite}/components/data-views/outline-tree-menu.tsx +0 -0
  266. /package/{template → template-vite}/components/data-views/table-cells.tsx +0 -0
  267. /package/{template → template-vite}/components/dev-chunk-load-recovery.tsx +0 -0
  268. /package/{template → template-vite}/components/export-drawer.test.tsx +0 -0
  269. /package/{template → template-vite}/components/export-drawer.tsx +0 -0
  270. /package/{template → template-vite}/components/exxat-product-logo.tsx +0 -0
  271. /package/{template → template-vite}/components/folder-details-shell.tsx +0 -0
  272. /package/{template → template-vite}/components/form-layout-01.tsx +0 -0
  273. /package/{template → template-vite}/components/hub-tree-panel-view.tsx +0 -0
  274. /package/{template → template-vite}/components/invite-collaborators-drawer.tsx +0 -0
  275. /package/{template → template-vite}/components/key-metrics-ask-leo-bridge.tsx +0 -0
  276. /package/{template → template-vite}/components/key-metrics.tsx +0 -0
  277. /package/{template → template-vite}/components/leo-insight-indicator.tsx +0 -0
  278. /package/{template → template-vite}/components/leo-typing-dots.tsx +0 -0
  279. /package/{template → template-vite}/components/library-board-view.tsx +0 -0
  280. /package/{template → template-vite}/components/library-dashboard-charts.tsx +0 -0
  281. /package/{template → template-vite}/components/library-favorite-button.tsx +0 -0
  282. /package/{template → template-vite}/components/library-new-folder-sheet.tsx +0 -0
  283. /package/{template → template-vite}/components/library-os-folder-view.tsx +0 -0
  284. /package/{template → template-vite}/components/library-page-header.tsx +0 -0
  285. /package/{template → template-vite}/components/library-panel-activator.tsx +0 -0
  286. /package/{template → template-vite}/components/list-hub-status-badge.tsx +0 -0
  287. /package/{template → template-vite}/components/list-page-dashboard-charts.tsx +0 -0
  288. /package/{template → template-vite}/components/onboarding/getting-started.tsx +0 -0
  289. /package/{template → template-vite}/components/onboarding/index.ts +0 -0
  290. /package/{template → template-vite}/components/onboarding/onboarding-01.tsx +0 -0
  291. /package/{template → template-vite}/components/onboarding/onboarding-02.tsx +0 -0
  292. /package/{template → template-vite}/components/onboarding/onboarding-03.tsx +0 -0
  293. /package/{template → template-vite}/components/onboarding/onboarding-04.tsx +0 -0
  294. /package/{template → template-vite}/components/page-header.tsx +0 -0
  295. /package/{template → template-vite}/components/product-switcher.tsx +0 -0
  296. /package/{template → template-vite}/components/product-wordmark.tsx +0 -0
  297. /package/{template → template-vite}/components/settings-appearance-card.tsx +0 -0
  298. /package/{template → template-vite}/components/settings-form-row.tsx +0 -0
  299. /package/{template → template-vite}/components/sidebar/app-sidebar-dynamic.tsx +0 -0
  300. /package/{template → template-vite}/components/sidebar/index.ts +0 -0
  301. /package/{template → template-vite}/components/sidebar/nav-documents.tsx +0 -0
  302. /package/{template → template-vite}/components/sidebar/nav-secondary.tsx +0 -0
  303. /package/{template → template-vite}/components/sidebar/secondary-panel.tsx +0 -0
  304. /package/{template → template-vite}/components/sidebar/sidebar-auto-collapse.tsx +0 -0
  305. /package/{template → template-vite}/components/sidebar/sidebar-auto-open.tsx +0 -0
  306. /package/{template → template-vite}/components/sidebar/sidebar-shell.tsx +0 -0
  307. /package/{template → template-vite}/components/site-header.tsx +0 -0
  308. /package/{template → template-vite}/components/table-properties/column-row.tsx +0 -0
  309. /package/{template → template-vite}/components/table-properties/draggable-list.ts +0 -0
  310. /package/{template → template-vite}/components/table-properties/drawer-button.tsx +0 -0
  311. /package/{template → template-vite}/components/table-properties/drawer.tsx +0 -0
  312. /package/{template → template-vite}/components/table-properties/filter-card.tsx +0 -0
  313. /package/{template → template-vite}/components/table-properties/index.ts +0 -0
  314. /package/{template → template-vite}/components/table-properties/sort-card.tsx +0 -0
  315. /package/{template → template-vite}/components/table-properties/types.ts +0 -0
  316. /package/{template → template-vite}/components/task-list-panel.tsx +0 -0
  317. /package/{template → template-vite}/components/task-priority-badge.tsx +0 -0
  318. /package/{template → template-vite}/components/templates/dedicated-search-landing-template.tsx +0 -0
  319. /package/{template → template-vite}/components/templates/dedicated-search-results-template.tsx +0 -0
  320. /package/{template → template-vite}/components/templates/list-page.tsx +0 -0
  321. /package/{template → template-vite}/components/templates/nested-secondary-panel-shell.tsx +0 -0
  322. /package/{template → template-vite}/components/templates/primary-page-template.tsx +0 -0
  323. /package/{template → template-vite}/components/templates/secondary-panel-hub-template.tsx +0 -0
  324. /package/{template → template-vite}/components/theme-color-sync.tsx +0 -0
  325. /package/{template → template-vite}/components/theme-provider.tsx +0 -0
  326. /package/{template → template-vite}/components/tinted-icon-disc.tsx +0 -0
  327. /package/{template → template-vite}/components/tokens-hub-auxiliary-views.tsx +0 -0
  328. /package/{template → template-vite}/components/tokens-themes-section.tsx +0 -0
  329. /package/{template → template-vite}/components/ui/accordion.tsx +0 -0
  330. /package/{template → template-vite}/components/ui/ai-thinking-surface.tsx +0 -0
  331. /package/{template → template-vite}/components/ui/alert-dialog.tsx +0 -0
  332. /package/{template → template-vite}/components/ui/avatar.tsx +0 -0
  333. /package/{template → template-vite}/components/ui/badge.tsx +0 -0
  334. /package/{template → template-vite}/components/ui/banner.tsx +0 -0
  335. /package/{template → template-vite}/components/ui/breadcrumb.tsx +0 -0
  336. /package/{template → template-vite}/components/ui/button.tsx +0 -0
  337. /package/{template → template-vite}/components/ui/calendar.tsx +0 -0
  338. /package/{template → template-vite}/components/ui/card.tsx +0 -0
  339. /package/{template → template-vite}/components/ui/chart.tsx +0 -0
  340. /package/{template → template-vite}/components/ui/checkbox.tsx +0 -0
  341. /package/{template → template-vite}/components/ui/coach-mark.tsx +0 -0
  342. /package/{template → template-vite}/components/ui/collapsible.tsx +0 -0
  343. /package/{template → template-vite}/components/ui/command.tsx +0 -0
  344. /package/{template → template-vite}/components/ui/context-menu.tsx +0 -0
  345. /package/{template → template-vite}/components/ui/date-picker-field.tsx +0 -0
  346. /package/{template → template-vite}/components/ui/dialog.tsx +0 -0
  347. /package/{template → template-vite}/components/ui/dot-pattern.tsx +0 -0
  348. /package/{template → template-vite}/components/ui/drag-handle-grip.tsx +0 -0
  349. /package/{template → template-vite}/components/ui/dropdown-menu.tsx +0 -0
  350. /package/{template → template-vite}/components/ui/field.tsx +0 -0
  351. /package/{template → template-vite}/components/ui/form.tsx +0 -0
  352. /package/{template → template-vite}/components/ui/hover-card.tsx +0 -0
  353. /package/{template → template-vite}/components/ui/input-group.tsx +0 -0
  354. /package/{template → template-vite}/components/ui/input-mask.tsx +0 -0
  355. /package/{template → template-vite}/components/ui/input.tsx +0 -0
  356. /package/{template → template-vite}/components/ui/kbd.tsx +0 -0
  357. /package/{template → template-vite}/components/ui/label.tsx +0 -0
  358. /package/{template → template-vite}/components/ui/leo-icon.tsx +0 -0
  359. /package/{template → template-vite}/components/ui/payment-card-fields.tsx +0 -0
  360. /package/{template → template-vite}/components/ui/popover.tsx +0 -0
  361. /package/{template → template-vite}/components/ui/radio-group.tsx +0 -0
  362. /package/{template → template-vite}/components/ui/resizable.tsx +0 -0
  363. /package/{template → template-vite}/components/ui/scroll-area.tsx +0 -0
  364. /package/{template → template-vite}/components/ui/select.tsx +0 -0
  365. /package/{template → template-vite}/components/ui/selection-tile-grid.tsx +0 -0
  366. /package/{template → template-vite}/components/ui/separator.tsx +0 -0
  367. /package/{template → template-vite}/components/ui/sheet.tsx +0 -0
  368. /package/{template → template-vite}/components/ui/sidebar.tsx +0 -0
  369. /package/{template → template-vite}/components/ui/skeleton.tsx +0 -0
  370. /package/{template → template-vite}/components/ui/slider.tsx +0 -0
  371. /package/{template → template-vite}/components/ui/sonner.tsx +0 -0
  372. /package/{template → template-vite}/components/ui/status-badge.tsx +0 -0
  373. /package/{template → template-vite}/components/ui/table.tsx +0 -0
  374. /package/{template → template-vite}/components/ui/tabs.tsx +0 -0
  375. /package/{template → template-vite}/components/ui/textarea.tsx +0 -0
  376. /package/{template → template-vite}/components/ui/tip.tsx +0 -0
  377. /package/{template → template-vite}/components/ui/toggle-group.tsx +0 -0
  378. /package/{template → template-vite}/components/ui/toggle-switch.tsx +0 -0
  379. /package/{template → template-vite}/components/ui/toggle.tsx +0 -0
  380. /package/{template → template-vite}/components/ui/tooltip.tsx +0 -0
  381. /package/{template → template-vite}/components/ui/view-segmented-control.tsx +0 -0
  382. /package/{template → template-vite}/components.json +0 -0
  383. /package/{template → template-vite}/contexts/chart-variant-context.tsx +0 -0
  384. /package/{template → template-vite}/contexts/command-menu-context.tsx +0 -0
  385. /package/{template → template-vite}/contexts/dashboard-view-context.tsx +0 -0
  386. /package/{template → template-vite}/contexts/product-context.tsx +0 -0
  387. /package/{template → template-vite}/contexts/system-banner-context.tsx +0 -0
  388. /package/{template → template-vite}/eslint.config.mjs +0 -0
  389. /package/{template → template-vite}/fontawesome-subset.manifest.json +0 -0
  390. /package/{template → template-vite}/hooks/.gitkeep +0 -0
  391. /package/{template → template-vite}/hooks/use-app-theme.ts +0 -0
  392. /package/{template → template-vite}/hooks/use-coach-mark.ts +0 -0
  393. /package/{template → template-vite}/hooks/use-location-hash.ts +0 -0
  394. /package/{template → template-vite}/hooks/use-mobile.ts +0 -0
  395. /package/{template → template-vite}/hooks/use-mod-key-label.ts +0 -0
  396. /package/{template → template-vite}/hooks/use-sidebar-reflow-zoom.ts +0 -0
  397. /package/{template → template-vite}/lib/.gitkeep +0 -0
  398. /package/{template → template-vite}/lib/ask-leo-route-context.ts +0 -0
  399. /package/{template → template-vite}/lib/chart-keyboard-selection.test.ts +0 -0
  400. /package/{template → template-vite}/lib/chart-keyboard-selection.ts +0 -0
  401. /package/{template → template-vite}/lib/chart-line-dash.ts +0 -0
  402. /package/{template → template-vite}/lib/chunk-load-error.ts +0 -0
  403. /package/{template → template-vite}/lib/coach-mark-registry.ts +0 -0
  404. /package/{template → template-vite}/lib/collaborator-access.ts +0 -0
  405. /package/{template → template-vite}/lib/command-menu-config.ts +0 -0
  406. /package/{template → template-vite}/lib/command-menu-search-data.ts +0 -0
  407. /package/{template → template-vite}/lib/conditional-rule-match.ts +0 -0
  408. /package/{template → template-vite}/lib/dashboard-customize-coach-mark.ts +0 -0
  409. /package/{template → template-vite}/lib/dashboard-layout-merge.ts +0 -0
  410. /package/{template → template-vite}/lib/data-list-display-options.ts +0 -0
  411. /package/{template → template-vite}/lib/data-list-persistence.ts +0 -0
  412. /package/{template → template-vite}/lib/data-list-view-registry.ts +0 -0
  413. /package/{template → template-vite}/lib/data-list-view-surface.ts +0 -0
  414. /package/{template → template-vite}/lib/data-list-view.ts +0 -0
  415. /package/{template → template-vite}/lib/data-view-dashboard-storage.ts +0 -0
  416. /package/{template → template-vite}/lib/date-filter.ts +0 -0
  417. /package/{template → template-vite}/lib/dedicated-search-recents.ts +0 -0
  418. /package/{template → template-vite}/lib/dedicated-search-url.ts +0 -0
  419. /package/{template → template-vite}/lib/dev-log.test.ts +0 -0
  420. /package/{template → template-vite}/lib/dev-log.ts +0 -0
  421. /package/{template → template-vite}/lib/discovery-hub.ts +0 -0
  422. /package/{template → template-vite}/lib/editable-target.ts +0 -0
  423. /package/{template → template-vite}/lib/exxat-palette.json +0 -0
  424. /package/{template → template-vite}/lib/exxat-palette.ts +0 -0
  425. /package/{template → template-vite}/lib/floating-sheet-panel.ts +0 -0
  426. /package/{template → template-vite}/lib/full-hub-supported-views.ts +0 -0
  427. /package/{template → template-vite}/lib/hub-connected-view-renderers.ts +0 -0
  428. /package/{template → template-vite}/lib/initials-from-name.ts +0 -0
  429. /package/{template → template-vite}/lib/library-authoring.ts +0 -0
  430. /package/{template → template-vite}/lib/library-dedicated-search.ts +0 -0
  431. /package/{template → template-vite}/lib/library-hub-search.ts +0 -0
  432. /package/{template → template-vite}/lib/library-nav.ts +0 -0
  433. /package/{template → template-vite}/lib/library-recent-searches.ts +0 -0
  434. /package/{template → template-vite}/lib/library-supported-views.ts +0 -0
  435. /package/{template → template-vite}/lib/list-hub-supported-views.ts +0 -0
  436. /package/{template → template-vite}/lib/list-page-table-properties.ts +0 -0
  437. /package/{template → template-vite}/lib/list-status-badges.ts +0 -0
  438. /package/{template → template-vite}/lib/logo-dev.ts +0 -0
  439. /package/{template → template-vite}/lib/mailto.ts +0 -0
  440. /package/{template → template-vite}/lib/mock/dashboard.ts +0 -0
  441. /package/{template → template-vite}/lib/mock/library-folders.ts +0 -0
  442. /package/{template → template-vite}/lib/mock/library-header-collaborators.ts +0 -0
  443. /package/{template → template-vite}/lib/mock/library-inspector.ts +0 -0
  444. /package/{template → template-vite}/lib/mock/library-kpi.ts +0 -0
  445. /package/{template → template-vite}/lib/mock/library.ts +0 -0
  446. /package/{template → template-vite}/lib/mock/navigation.tsx +0 -0
  447. /package/{template → template-vite}/lib/motion-ui.ts +0 -0
  448. /package/{template → template-vite}/lib/product-brand.ts +0 -0
  449. /package/{template → template-vite}/lib/raf-throttle.ts +0 -0
  450. /package/{template → template-vite}/lib/row-height.ts +0 -0
  451. /package/{template → template-vite}/lib/sidebar-state-cookie.ts +0 -0
  452. /package/{template → template-vite}/lib/stock-portrait.ts +0 -0
  453. /package/{template → template-vite}/lib/table-state-lifecycle.ts +0 -0
  454. /package/{template → template-vite}/lib/utils.test.ts +0 -0
  455. /package/{template → template-vite}/lib/utils.ts +0 -0
  456. /package/{template → template-vite}/public/.gitkeep +0 -0
  457. /package/{template → template-vite}/public/Illustration/Rotation.svg +0 -0
  458. /package/{template → template-vite}/public/avatars/user.svg +0 -0
  459. /package/{template/public → template-vite/public/favicon}/favicon.ico +0 -0
  460. /package/{template/app → template-vite/public}/favicon.ico +0 -0
  461. /package/{template → template-vite}/public/folders/icons8-folder-windows-11.svg +0 -0
  462. /package/{template → template-vite}/public/logos/exxat-one.svg +0 -0
  463. /package/{template → template-vite}/public/logos/exxat-prism.svg +0 -0
  464. /package/{template → template-vite}/public/mock-schools/emory.svg +0 -0
  465. /package/{template → template-vite}/public/mock-schools/rush.svg +0 -0
  466. /package/{template → template-vite}/scripts/fontawesome-subset-audit.mjs +0 -0
  467. /package/{template → template-vite}/scripts/pm2-startup-macos.sh +0 -0
  468. /package/{template → template-vite}/skills-lock.json +0 -0
  469. /package/{template/app/(app)/columns/page.tsx → template-vite/src/pages/columns.tsx} +0 -0
  470. /package/{template/app/(app)/library/find/page.tsx → template-vite/src/pages/library/find.tsx} +0 -0
  471. /package/{template/app/(app)/library/page.tsx → template-vite/src/pages/library/index.tsx} +0 -0
  472. /package/{template/app/(app)/library/list/page.tsx → template-vite/src/pages/library/list.tsx} +0 -0
  473. /package/{template/app/(app)/settings/page.tsx → template-vite/src/pages/settings.tsx} +0 -0
  474. /package/{template/app/(app)/tokens-themes/page.tsx → template-vite/src/pages/tokens-themes.tsx} +0 -0
  475. /package/{template → template-vite}/stores/app-store.ts +0 -0
  476. /package/{template → template-vite}/types/react-payment-inputs.d.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.12
4
+
5
+ ### Patch Changes
6
+
7
+ - **The legacy `template/` (Next.js scaffold) is retired and no longer ships in the npm tarball.** It was already unreachable from the CLI as of 0.5.11 (`create-exxat-app` scaffolds from `template-vite/` only) and was being half-regenerated from the now-Vite `apps/web/` at publish time, leaving consumers with a Next.js eslint config layered over a Vite source tree. Three concrete changes in this release:
8
+ - **`packages/ui/package.json` `files`** drops `template` — `template-vite` is the only scaffold shipped.
9
+ - **CLI help (`exxat-ui update`)** points at `node_modules/@exxatdesignux/ui/template-vite/` when it suggests "compare your app with the reference template".
10
+ - **Workspace rules and skills** (`exxat-nav-single-active.mdc`, `exxat-library-hub-header.mdc`, `exxat-ds-skill`) point at `template-vite/` paths instead of `template/`. `consumer-extras/` regenerates from those sources.
11
+ - The `sync-template-from-web.mjs` script and the workflow step that runs it are kept (now a no-op for the published tarball) so the build pipeline continues to typecheck/lint a known-shaped reference, and so the next migration off it is a small follow-up rather than a workflow edit. Consumers see no regression — `exxat-ui sync-extras` continues to be the supported channel for rules + skills + patterns.
12
+ - **The reference app (`apps/web`) is now Vite + React + react-router-dom — Next.js fully removed.** A six-PR program (May 2026) cut steady-state dev memory from **1.4–4 GB RSS per `next-server`** down to **~250–500 MB per `vite`**, and cold start from 8–12 s to **~150–300 ms**. Designers running long sessions and customers comparing two branches side-by-side were the practical reason; the stack swap is what made it possible. Three layers of the published package change because of this.
13
+ - **`scripts/dev-guard.mjs`** is now Vite-only. The detector that previously listed running `next-server` parents was carrying dead code branches after PR-6; it now matches `vite` processes only and the warning copy is rewritten ("Two parallel Vite servers stabilize at ~500–800 MB combined and confuse HMR"). Customer apps that wired `predev: exxat-ui dev-guard` keep working unchanged — the guard simply reflects the new stack.
14
+ - **`bin/init.mjs`** drops `--stack=vite|next`. There is one starter now and it is `template-vite/` — Vite 6 + React 19 + react-router-dom + Tailwind v4 + TypeScript. The CLI's `--help` text and on-screen messages were rewritten to match. Customers that need a Next.js scaffold can copy `template-vite/` and bring their own `next.config.mjs` — the components, tokens, and rules are all stack-agnostic.
15
+ - **`bin/cli.mjs`** help text is updated: `dev-guard` reads "Detect concurrent Vite dev servers" instead of "Next.js + Vite", and `audit` audits a "React component / route" rather than a "Next.js component / route".
16
+ - **Consumer-extras and patterns refreshed for the Vite stack.** Every `npx exxat-ui sync-extras` payload that mentioned Next now reads as it does in the workspace today:
17
+ - **`patterns/perf-memory-pattern.md`** rewritten end-to-end. It used to be Next + Turbopack tuning ("`NODE_OPTIONS=--max-old-space-size=6144`", "Turbopack mmap'd FS cache", `pnpm clean:cache` for `.next/dev/cache`). It is now a Vite + Node 24 doc — the four knobs that matter (`dev-guard`, `optimizeDeps.include`, `optimizeDeps.exclude` for the workspace package, `resolve.dedupe` for React), how to bust `node_modules/.vite/`, and how to diagnose RSS climbing past 1 GB. A short "History" callout still explains where the 8× memory drop came from for anyone reading the migration in context.
18
+ - **`patterns/consumer-upgrade-checklist.md`** §3 now points at `node_modules/@exxatdesignux/ui/template-vite/` (was `template/`) and adds a "Migrating an existing Next.js consumer to Vite?" pointer for customers ready to follow the same path the reference app took.
19
+ - **`cursor-rules/exxat-no-slds-leakage.mdc`**, **`cursor-rules/exxat-primary-nav-secondary-panel.mdc`**, **`cursor-rules/exxat-list-page-view-shells.mdc`**, **`cursor-rules/exxat-command-menu.mdc`**, **`apps/web/.cursor/rules/exxat-dashboard-view-charts.mdc`** updated: where they cited `app/(app)/...` paths and `Next.js bundle` / `next/Link` / `Next.js app`, they now cite `src/views/...`, `src/App.tsx`, `Vite bundle`, and `react-router-dom Link`. Pure documentation — no rule logic changed, no globs broadened.
20
+ - **`consumer-extras/README.md`** drops the `--stack=next` example and rewords the `dev-guard` description to be Vite-only.
21
+ - **Designer landing page (`DESIGNER_LANDING.html`) refreshed.** The hero hint, "Starting fresh" / "Already coding" paths, and the *Sixty seconds* §ii ("Teach Next to transpile" → "No bundler config needed") all match the new stack. The "Layout that speaks Arabic." highlight card was removed — the DS doesn't yet ship logical-property layout end-to-end and the claim overstated 0.5.3.
22
+ - **Why this is a `0.5.x` patch and not a major bump:** the **runtime API** of `@exxatdesignux/ui` did not change. Every component, hook, token, and CSS export has the same shape it had in 0.5.11. What changed is which sample stack the published `template-vite/` runs, what `dev-guard` looks for in `ps`, and what the bundled rules / patterns / handbook say about the reference app. Customer apps that already install the package keep working with no code changes; running `exxat-ui sync-extras` after the upgrade refreshes the docs and rules in place.
23
+ - **Customer migration steps** (only if you want the new dev-experience pattern):
24
+ 1. **`pnpm add @exxatdesignux/ui@0.5.12`** in your app.
25
+ 2. **`npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras`** to pull the refreshed rules + patterns.
26
+ 3. If you ran a *Next.js* app and want to migrate to Vite, follow the new §7 "Upgrading an existing customer app to the Vite stack" in `perf-memory-pattern.md` (the same six-step program the reference app followed; the codemod for `next/*` → `react-router-dom` lives in commit `d16ec77` of this repo if you need a starting point).
27
+ 4. If you stay on Next.js, no action required — the package supports any React app via `transpilePackages: ["@exxatdesignux/ui"]`.
28
+
3
29
  ## 0.5.11
4
30
 
5
31
  ### Patch Changes
package/bin/cli.mjs CHANGED
@@ -33,6 +33,65 @@ function runSyncExtras() {
33
33
  })
34
34
  }
35
35
 
36
+ function runDevGuard(extraArgs) {
37
+ const script = resolve(__dirname, "../consumer-extras/scripts/dev-guard.mjs")
38
+ if (!existsSync(script)) {
39
+ // Old install — pass through silently so predev hooks never break a build.
40
+ process.exit(0)
41
+ }
42
+ try {
43
+ execFileSync(process.execPath, [script, ...extraArgs], {
44
+ stdio: "inherit",
45
+ cwd: process.cwd(),
46
+ })
47
+ } catch (err) {
48
+ process.exit(err?.status ?? 1)
49
+ }
50
+ }
51
+
52
+ /**
53
+ * `exxat-ui audit <file>` — engineer-facing quality gate.
54
+ *
55
+ * The full audit logic lives in the `exxat-ux-audit` skill (consumed by
56
+ * Cursor / Claude). This subcommand is a *stub* that prints the right
57
+ * invocation for both clients and exits. It is *not* a standalone linter —
58
+ * a full machine audit lives behind the agent so the rules stay in one
59
+ * place (the skill) instead of being duplicated in JS.
60
+ */
61
+ function runAudit(args) {
62
+ const target = args[0]
63
+ if (!target) {
64
+ console.error("Usage: exxat-ui audit <file-or-route>\n")
65
+ console.error("Audits a React component / route against the Exxat DS")
66
+ console.error("rules + UX principles (P1–P20) + modern SaaS patterns (M1–M12).\n")
67
+ console.error("This stub prints the agent prompt to run; the actual audit is")
68
+ console.error("performed by the `exxat-ux-audit` skill in your agent client.")
69
+ process.exitCode = 1
70
+ return
71
+ }
72
+ console.log(`
73
+ Audit target: ${target}
74
+
75
+ Run inside Cursor or Claude Code:
76
+
77
+ /skill exxat-ux-audit
78
+ audit ${target}
79
+
80
+ The skill loads:
81
+ • .cursor/rules/exxat-accessibility.mdc (a11y floor)
82
+ • .cursor/rules/exxat-ux-principles.mdc (P1–P20)
83
+ • .cursor/rules/exxat-token-discipline.mdc (no hex)
84
+ • .cursor/rules/exxat-no-toast.mdc (no Sonner)
85
+ • .cursor/rules/exxat-ds-agents.mdc (top of stack)
86
+
87
+ …and produces a Blocker / Issue / Nit findings report with code citations
88
+ and a fix plan. Text-only Blocker fixes are auto-applied on confirmation.
89
+
90
+ For headless / CI use: hit the same skill via the SDK
91
+ (\`@cursor/sdk\` Agent.prompt) and grep the JSON output for "Blocker:".
92
+ `)
93
+ }
94
+
36
95
  /** @returns {number} negative if a < b, 0 if equal, positive if a > b (x.y.z only) */
37
96
  function compareSemver(a, b) {
38
97
  const pa = a.split(".").map(n => parseInt(n, 10) || 0)
@@ -55,6 +114,10 @@ Commands:
55
114
  update How to upgrade an existing project that depends on this package.
56
115
  changelog Print CHANGELOG.md from the installed package (release notes + AI upgrade hints).
57
116
  doctor Compare this CLI version vs npm registry "latest" (diagnose stale installs).
117
+ dev-guard Detect concurrent Vite dev servers — the #1 memory killer.
118
+ Wire as a "predev" hook to abort if a sibling dev server is already running.
119
+ audit <f> Print the prompt to audit a file against DS rules + UX principles (P1–P20).
120
+ The audit runs inside your agent client (the exxat-ux-audit skill).
58
121
 
59
122
  Do NOT use plain npx @exxatdesignux/ui — use the scoped form below.
60
123
 
@@ -100,7 +163,7 @@ After upgrading — for humans and AI tools:
100
163
  npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras
101
164
 
102
165
  3. Compare your app with the reference template when something new is unclear:
103
- node_modules/@exxatdesignux/ui/template/
166
+ node_modules/@exxatdesignux/ui/template-vite/
104
167
 
105
168
  **Still seeing old code?** Run **exxat-ui doctor** — the npm "latest" tag can lag
106
169
  this Git repo until maintainers publish (git tag **ui-v<version>**).
@@ -191,6 +254,12 @@ switch (cmd) {
191
254
  case "doctor":
192
255
  printDoctor()
193
256
  break
257
+ case "dev-guard":
258
+ runDevGuard(process.argv.slice(3))
259
+ break
260
+ case "audit":
261
+ runAudit(process.argv.slice(3))
262
+ break
194
263
  case "help":
195
264
  case "--help":
196
265
  case "-h":
package/bin/init.mjs CHANGED
@@ -18,15 +18,27 @@ import { fileURLToPath } from "node:url"
18
18
  import { execSync } from "node:child_process"
19
19
 
20
20
  const __dirname = dirname(fileURLToPath(import.meta.url))
21
- const templateDir = resolve(__dirname, "../template")
22
21
  const selfPkgPath = resolve(__dirname, "../package.json")
23
22
  const selfPkg = JSON.parse(readFileSync(selfPkgPath, "utf8"))
24
23
 
25
24
  const args = process.argv.slice(2)
26
- const flags = new Set(args.filter((a) => a.startsWith("--")))
25
+ const allFlags = args.filter((a) => a.startsWith("--"))
26
+ const flags = new Set(allFlags.map((f) => (f.includes("=") ? f.slice(0, f.indexOf("=")) : f)))
27
27
  const positional = args.filter((a) => !a.startsWith("--"))
28
28
  const targetArg = positional[0] ?? "."
29
29
  const targetDir = resolve(process.cwd(), targetArg)
30
+
31
+ // `template-vite/` is the canonical scaffold source. The `template/`
32
+ // (Next.js) directory was retired alongside the apps/web Next removal
33
+ // (PR-6, May 2026); customers who need a Next scaffold can copy
34
+ // `template-vite/` and migrate it.
35
+ const templateDirName = "template-vite"
36
+ const templateDir = resolve(__dirname, `../${templateDirName}`)
37
+ if (!existsSync(templateDir)) {
38
+ console.error(`❌ Template directory ${templateDirName}/ not found in this @exxatdesignux/ui release.`)
39
+ console.error(` Try upgrading: npm i @exxatdesignux/ui@latest`)
40
+ process.exit(1)
41
+ }
30
42
  // `displayName` is what we show in messages and use to derive package.json
31
43
  // `name`. For "." or an absolute path we just use the basename; for a
32
44
  // relative path the user typed (`my-app`, `apps/sandbox`) we keep it as-is.
@@ -41,7 +53,9 @@ const skipExtras = flags.has("--no-extras") || flags.has("--skip-extras")
41
53
 
42
54
  if (flags.has("--help") || flags.has("-h")) {
43
55
  console.log(`
44
- create-exxat-app — scaffold a Next.js app on @exxatdesignux/ui
56
+ create-exxat-app — scaffold a starter app on @exxatdesignux/ui
57
+
58
+ Stack: Vite + React + react-router-dom (low-memory, fast HMR).
45
59
 
46
60
  Usage:
47
61
  create-exxat-app [target-directory] [options]
@@ -97,7 +111,7 @@ if (blockers.length > 0 && !force) {
97
111
  process.exit(1)
98
112
  }
99
113
 
100
- console.log(`📦 Copying Exxat DS starter app into ${displayName}/ …`)
114
+ console.log(`📦 Copying Exxat DS starter app (Vite) into ${displayName}/ …`)
101
115
  cpSync(templateDir, targetDir, { recursive: true })
102
116
 
103
117
  // Pin DS to this CLI's published version so `latest` cache drift cannot
@@ -37,10 +37,11 @@ function log(...m) {
37
37
  }
38
38
 
39
39
  const SOURCES = {
40
- skills: join(pkgRoot, "consumer-extras", "cursor-skills"),
41
- rules: join(pkgRoot, "consumer-extras", "cursor-rules"),
42
- patterns: join(pkgRoot, "consumer-extras", "patterns"),
43
- handbook: join(pkgRoot, "consumer-extras", "handbook"),
40
+ skills: join(pkgRoot, "consumer-extras", "cursor-skills"),
41
+ rules: join(pkgRoot, "consumer-extras", "cursor-rules"),
42
+ patterns: join(pkgRoot, "consumer-extras", "patterns"),
43
+ handbook: join(pkgRoot, "consumer-extras", "handbook"),
44
+ templates: join(pkgRoot, "consumer-extras", "templates"),
44
45
  }
45
46
 
46
47
  const DESTINATIONS = {
@@ -49,6 +50,7 @@ const DESTINATIONS = {
49
50
  cursorRules: join(cwd, ".cursor", "rules"),
50
51
  patterns: join(cwd, "docs", "exxat-ds"),
51
52
  handbook: join(cwd, "docs", "exxat-ds", "handbook"),
53
+ templates: join(cwd, "docs", "exxat-ds", "templates"),
52
54
  }
53
55
 
54
56
  let wrote = 0
@@ -150,11 +152,33 @@ function syncHandbook() {
150
152
  }
151
153
  }
152
154
 
155
+ /**
156
+ * Templates (handoff.md etc.) land in `docs/exxat-ds/templates/` next to the
157
+ * patterns + handbook. The agent fills them in via the `exxat-ux-discovery-protocol`
158
+ * rule at the close of any design task.
159
+ */
160
+ function syncTemplates() {
161
+ if (!existsSync(SOURCES.templates)) {
162
+ console.warn("[sync-extras] no packaged templates (optional)")
163
+ skipped++
164
+ return
165
+ }
166
+ mkdirSync(DESTINATIONS.templates, { recursive: true })
167
+ for (const name of readdirSync(SOURCES.templates)) {
168
+ const src = join(SOURCES.templates, name)
169
+ if (!statSync(src).isFile()) continue
170
+ cpSync(src, join(DESTINATIONS.templates, name))
171
+ log(`[sync-extras] wrote docs/exxat-ds/templates/${name}`)
172
+ wrote++
173
+ }
174
+ }
175
+
153
176
  syncSkillsTo(".cursor/skills", DESTINATIONS.cursorSkills)
154
177
  syncSkillsTo(".claude/skills", DESTINATIONS.claudeSkills)
155
178
  syncRules()
156
179
  syncPatterns()
157
180
  syncHandbook()
181
+ syncTemplates()
158
182
 
159
183
  console.log(`[sync-extras] Done. ${wrote} files / dirs written; ${skipped} optional sources missing.`)
160
184
  if (!QUIET) console.log("[sync-extras] Product routes and app content were not modified.")
@@ -11,6 +11,40 @@ touching product routes or pages.
11
11
  | `cursor-rules/exxat-*.mdc` | `.cursor/rules/exxat-*.mdc` (replaced) — binding **MUST / MUST NOT** files |
12
12
  | `patterns/*.md` | `docs/exxat-ds/*.md` (replaced) — pattern docs + **`consumer-upgrade-checklist.md`** |
13
13
  | `handbook/*.md` | `docs/exxat-ds/handbook/*.md` (replaced) — `HANDBOOK`, `glossary`, `voice-and-tone`, `reference-implementations` |
14
+ | `templates/handoff.md` | `docs/exxat-ds/templates/handoff.md` (replaced) — design → engineering handoff artifact (the agent fills this in at the close of every design task) |
15
+ | `scripts/dev-guard.mjs` | Runs in place via `exxat-ui dev-guard` (no copy) — wire as `predev` to abort if a sibling `vite` is already running and stacking memory |
16
+
17
+ ## CLI — what each subcommand does for your team
18
+
19
+ ```bash
20
+ # Scaffold a new app (Vite + React + react-router-dom — fast cold start, ~250–400 MB RSS):
21
+ npx --package=@exxatdesignux/ui@latest create-exxat-app my-app
22
+
23
+ # Engineering quality-gate — read DS rules + UX principles for a file:
24
+ npx --package=@exxatdesignux/ui@latest exxat-ui audit src/views/students.tsx
25
+
26
+ # Memory guard for designers running long dev sessions:
27
+ "scripts": { "predev": "exxat-ui dev-guard" }
28
+ ```
29
+
30
+ `dev-guard` lists every running `vite` parent and refuses to start a second
31
+ one without confirmation. Per `patterns/perf-memory-pattern.md` §2, two
32
+ parallel Vite servers stabilize at ~500–800 MB combined and confuse HMR —
33
+ even though they're 8× lighter than the Next dev servers this CLI used to
34
+ guard against (May 2026 migration).
35
+
36
+ ## Rule tiers (`appliesTo:` metadata)
37
+
38
+ Every shipped `.mdc` rule carries an `appliesTo:` field:
39
+
40
+ - `[universal]` — UX principles, accessibility floor, anti-patterns, decision
41
+ frameworks. Works for any framework (HTML, React, Vue, iOS).
42
+ - `[react]` — cites React component names / hooks / JSX. Auto-attaches via
43
+ `globs:` when the agent edits matching files; not always-on.
44
+
45
+ Today this is documentation metadata. It is positioned for a future
46
+ `exxat-ui sync-extras --stack=html` flag that filters out `[react]` rules
47
+ for non-React consumers.
14
48
 
15
49
  The CLI is **namespaced**: it only touches files starting with `exxat-` (skills + rules)
16
50
  so a consumer's own non-Exxat rules / skills are preserved. Product code under `app/`,
@@ -41,11 +75,13 @@ pnpm --filter @exxatdesignux/ui vendor:consumer-extras
41
75
  └── exxat-ds/
42
76
  ├── *-pattern.md ← narrative pattern docs (patterns/)
43
77
  ├── consumer-upgrade-checklist.md
44
- └── handbook/
45
- ├── HANDBOOK.md
46
- ├── glossary.md
47
- ├── voice-and-tone.md
48
- └── reference-implementations.md
78
+ ├── handbook/
79
+ ├── HANDBOOK.md
80
+ ├── glossary.md
81
+ ├── voice-and-tone.md
82
+ └── reference-implementations.md
83
+ └── templates/
84
+ └── handoff.md ← design → engineering handoff artifact
49
85
  ```
50
86
 
51
87
  ## Note on handbook link rewriting
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Exxat DS — WCAG 2.1 AA, ARIA tablists, 24px targets, contrast; see AGENTS.md §8 and exxat-accessibility skill
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — accessibility (binding summary)
@@ -26,7 +27,7 @@ alwaysApply: true
26
27
  - **C. Interactive icon-only button/link** (close `×`, chevron, overflow `⋯`, sort direction, filter chip dismiss, copy, Ask Leo toggle, row actions) → MUST pair **`aria-label`** on the `<button>` with a wrapping **`Tooltip`**. `aria-label` alone is NOT enough — sighted mouse users and keyboard users rely on the tooltip to discover what a bare icon does.
27
28
 
28
29
  In all three cases, the inner `<i>` / `<svg>` MUST be `aria-hidden`; the accessible name lives on the wrapping element. Tooltip text MUST match the accessible name. Narrow exception: a chevron inside a labelled composite (`Select`, `Combobox`) where the parent control already names the whole thing. See **§8.6 (Case A/B/C)** in `AGENTS.md` and the accessibility skill.
29
- 10. **Keyboard shortcut hints inside buttons** MUST use **`<Kbd variant="bare">`** (no background, no border, inherits `currentColor` at 70%). The default `tile` variant is reserved for **tooltips** and **menu `shortcut=` slots**. Glue multi-key chords into one bare kbd (e.g. `<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. Reference: `Next` / `Back` buttons in `new-placement-form.tsx`; see `.cursor/rules/exxat-kbd-shortcuts.mdc`.
30
+ 10. **Keyboard shortcut hints inside buttons** MUST use **`<Kbd variant="bare">`** (no background, no border, inherits `currentColor` at 70%). The default `tile` variant is reserved for **tooltips** and **menu `shortcut=` slots**. Glue multi-key chords into one bare kbd (e.g. `<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. Reference: `Next` / `Back` buttons in `new-library-item-form.tsx`; see `.cursor/rules/exxat-kbd-shortcuts.mdc`.
30
31
 
31
32
  After changing **views toolbar** or **tab** UIs, re-run **axe** (or equivalent) on **Placements** (or the affected page).
32
33
 
@@ -1,6 +1,8 @@
1
1
  ---
2
- description: Exxat DS — board (kanban) cards; ListPageBoardCard, badges, primitives
3
- alwaysApply: true
2
+ description: Exxat DS — board (kanban) cards via ListPageBoardCard, badges, primitives. Auto-attaches when editing React board/list files; ask explicitly when designing kanban surfaces.
3
+ globs: apps/web/components/**/*.{tsx,ts}
4
+ alwaysApply: false
5
+ appliesTo: [react]
4
6
  ---
5
7
 
6
8
  # Exxat DS — board cards
@@ -11,7 +13,7 @@ alwaysApply: true
11
13
 
12
14
  1. **Shell** — Use **`ListPageBoardCard`** from **`components/data-views/list-page-board-card.tsx`** for product board cards (same **`Card` `size="sm"`** treatment as Placements).
13
15
  2. **Hierarchy** — **Title** (`ListPageBoardCardTitleRow`) → optional **avatar** (`ListPageBoardCardAvatar` on `trailing`) → **status row** (`ListPageBoardCardBadgeRow` + **`ListHubStatusBadge`** **`surface="board"`**) when the entity has status → **body** (`ListPageBoardCardBody`) with **`BoardCardTwoLineBlock`** / **`BoardCardIconRow`** (**`components/data-views/board-card-primitives.tsx`**).
14
- 3. **Status** — **Placements** (**`PLACEMENT_STATUS_*`** + **`StatusBadge`** in **`placements-table-cells.tsx`**), **Team / Compliance / Library** (**`ListHubStatusBadge`** + entity maps): all labels/tints/icons live in **`lib/list-status-badges.ts`**. **`surface="table"`** in grid/list rows, **`surface="board"`** on kanban cards. Prefer semantic **`LIST_HUB_STATUS_TINT_*`**. **MUST NOT** use **`uppercase`** on those chips.
16
+ 3. **Status** — Use **`ListHubStatusBadge`** with **`surface="table"`** in grid / list rows and **`surface="board"`** on kanban cards. Generic semantic tints live in **`lib/list-status-badges.ts`** (**`LIST_HUB_STATUS_TINT_SUCCESS / WARNING / INFO / NEUTRAL / DANGER`**); compose per-domain label / icon maps next to the entity's mock data. Reference: **`library-board-view.tsx`** + **`lib/mock/library.ts`**. **MUST NOT** use **`uppercase`** on those chips.
15
17
  4. **Simple column boards** — **`ListPageBoardTemplate`** + **`renderCard`**; compose **`ListPageBoardCard`** inside **`renderCard`**.
16
18
 
17
19
  ## MUST NOT
@@ -2,6 +2,7 @@
2
2
  description: Do not duplicate parent navigation with a Back control when breadcrumbs exist
3
3
  globs: apps/web/**/*.tsx
4
4
  alwaysApply: false
5
+ appliesTo: [react]
5
6
  ---
6
7
 
7
8
  # Exxat DS — breadcrumbs and back navigation
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Exxat DS — when to use cards vs DataTable rows vs simple list rows.
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — cards vs rows vs lists
@@ -1,6 +1,8 @@
1
1
  ---
2
- description: Single source of truth for hub rows, KPIs, table properties, detail views, and shared view chrome — dataset + presentation consistency across DataListViewType surfaces
3
- alwaysApply: true
2
+ description: Single source of truth for hub rows, KPIs, table properties, detail views, and shared view chrome — dataset + presentation consistency across DataListViewType surfaces. Auto-attaches when editing list-hub React files.
3
+ globs: apps/web/{components,lib}/**/*.{tsx,ts}
4
+ alwaysApply: false
5
+ appliesTo: [react]
4
6
  ---
5
7
 
6
8
  # Exxat DS — centralized list hub dataset + presentation
@@ -2,6 +2,7 @@
2
2
  description: Shared hubs — collaboration header, invite sheet, library access vs directory roles
3
3
  globs: apps/web/components/**/*.{tsx,ts},apps/web/lib/**/*.{tsx,ts}
4
4
  alwaysApply: false
5
+ appliesTo: [react]
5
6
  ---
6
7
 
7
8
  # Exxat DS — collaboration & access
@@ -1,19 +1,20 @@
1
1
  ---
2
2
  description: Exxat DS — global command palette (⌘K) as search + quick AI vs Ask Leo for long answers.
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — global command palette (`CommandMenu`)
7
8
 
8
9
  ## Intent
9
10
 
10
- - **`CommandMenu`** (**⌘K** / **Ctrl+K**) is **global search** (routes, library, patterns, AI starters, optional row data such as placements / student names) — see **`apps/web/AGENTS.md` §7.1** and **`apps/web/docs/command-menu-pattern.md`**.
11
+ - **`CommandMenu`** (**⌘K** / **Ctrl+K**) is **global search** (routes, library, patterns, AI starters, optional row data such as student names / question stems) — see **`apps/web/AGENTS.md` §7.1** and **`apps/web/docs/command-menu-pattern.md`**.
11
12
  - **Quick / lookup / short AI:** Prefer **results inside the palette** when the product can return compact answers or lightweight “research” without leaving the flow.
12
13
  - **Long or complex answers:** **Ask Leo** side panel (**⌘⌥K** / **Ctrl+Alt+K**)—not forced into the palette.
13
14
 
14
15
  ## Implementation pointers
15
16
 
16
- - Shell: `apps/web/components/command-menu.tsx`; config **`buildCommandMenuConfig()`** in **`apps/web/lib/command-menu-config.ts`**; optional **`dataGroups`** from **`apps/web/lib/command-menu-search-data.ts`** (e.g. **`getCommandMenuSearchDataGroups()`**), wired in **`apps/web/app/(app)/layout.tsx`**. Keep domain mapping out of the shell.
17
+ - Shell: `apps/web/components/command-menu.tsx`; config **`buildCommandMenuConfig()`** in **`apps/web/lib/command-menu-config.ts`**; optional **`dataGroups`** from **`apps/web/lib/command-menu-search-data.ts`** (e.g. **`getCommandMenuSearchDataGroups()`**), wired in **`apps/web/src/App.tsx`**. Keep domain mapping out of the shell.
17
18
  - Large indexes: set **`searchOnly: true`** on **`CommandMenuGroup`** so **`command-menu.tsx`** skips the group until the user types (avoids listing every row on open; cmdk shows all items when the search string is empty).
18
19
 
19
20
  ## See also
@@ -1,6 +1,8 @@
1
1
  ---
2
- description: Exxat DS — product data tables must use DataTable with search, filters, and table properties; no alternate table stacks.
3
- alwaysApply: true
2
+ description: Exxat DS — product data tables must use HubTable/DataTable with search, filters, table properties; no alternate table stacks. Auto-attaches when editing apps/web React files; ask for it explicitly when designing a list/grid surface.
3
+ globs: apps/web/**/*.{tsx,ts}
4
+ alwaysApply: false
5
+ appliesTo: [react]
4
6
  ---
5
7
 
6
8
  # Exxat DS — data tables (mandatory pattern)
@@ -17,7 +19,7 @@ For **any app screen that shows a browsable, filterable grid of records** (direc
17
19
  6. **Table properties:** Always reachable. `HubTable` mounts `TablePropertiesDrawerButton` in `toolbarSlot`; on **`ListPageTemplate`** pages with **table / list / board / dashboard** tabs it **MUST** also receive **`currentView`** and **`onViewChange`** (see **`apps/web/AGENTS.md` §4.2** and **`.cursor/rules/exxat-table-properties-drawer.mdc`**) so Properties matches the selected view.
18
20
  7. **Dropdown menus:** `DropdownMenuContent` uses the shared **`@exxatdesignux/ui`** default (**intrinsic `w-max`**, **`min-w-52`**, capped **`max-w`**) for view settings, row ⋯, column menus, and filter pickers — **pure CSS**, no **`ResizeObserver`**. Override only for deliberate narrow/wide rails (e.g. pagination **`w-20`**, account trigger-width, school switcher **`!w-max min-w-72 …`**). See **`docs/data-views-pattern.md`** (“Dropdown menus”).
19
21
  8. **Cell renderers MUST come from `@/components/data-views` (`table-cells.tsx`).** The DS ships **`ProgressCell`**, **`CurrencyCell`**, **`NumericCell`**, **`RatingCell`**, **`SignalBarsCell`**, **`BooleanToggleCell`**, **`AttachmentCountCell`**, **`ExternalLinkCell`**, **`RelativeTimeCell`**, **`PeopleAvatarRailCell`**, **`PillCell`**, **`TagListCell`**, and a generic **`RowActionsCell<TRow>`**. A `ColumnDef['cell']` for these patterns is a **one-liner** that calls the named cell. **MUST NOT** inline `Intl.NumberFormat`, raw `<a target="_blank">`, `[1,2,3,4,5].map(s => …)` star loops, paperclip + count chips, custom face-rail `AvatarGroup`s, or per-hub `DropdownMenu` overflow menus inside `cell:` — those are signals you're re-deriving a shipped primitive. Catalog: `apps/web/components/columns-showcase.tsx` (`/columns`). Skill: `.cursor/skills/exxat-token-economy/SKILL.md` §3.
20
- 9. **Add view parity** — **`FULL_HUB_SUPPORTED_VIEWS`** + a real renderer per view — **`.cursor/rules/exxat-hub-supported-views.mdc`**, **`docs/exxat-ds/patterns/hub-supported-views-pattern.md`**.
22
+ 9. **Add view parity** — **`FULL_HUB_SUPPORTED_VIEWS`** + a real renderer per view — **`.cursor/rules/exxat-hub-supported-views.mdc`**, **`apps/web/docs/hub-supported-views-pattern.md`**.
21
23
 
22
24
  **Reference implementations:**
23
25
 
@@ -1,3 +1,10 @@
1
+ ---
2
+ description: Dedicated search surfaces — DedicatedSearch* templates, recents storage, landing-vs-results URL composer. Auto-attaches when editing search-related React routes.
3
+ globs: apps/web/{components,app,lib}/**/*.{tsx,ts}
4
+ alwaysApply: false
5
+ appliesTo: [react]
6
+ ---
7
+
1
8
  # Exxat DS — dedicated search surfaces
2
9
 
3
10
  **Authoritative detail:** **`apps/web/AGENTS.md` §4.8**, **`.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md`**.
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Exxat DS — drawer/sheet vs modal dialog vs route for flows and confirmations.
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — drawer vs dialog
@@ -19,4 +20,4 @@ alwaysApply: true
19
20
  ## See also
20
21
 
21
22
  - **`docs/drawer-vs-dialog-pattern.md`** · **`.cursor/skills/exxat-drawer-vs-dialog/SKILL.md`**
22
- - **`exxat-page-vs-drawer.mdc`** (sheet vs **route**)
23
+ - **`exxat-page-vs-drawer.mdc`** (drawer vs **route**)
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Exxat DS — follow AGENTS.md; DataTable, ListPageTemplate, primary hubs, export, Kbd
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — AI handbook (binding)
@@ -2,6 +2,7 @@
2
2
  description: Font Awesome Pro icons — kit, weights, markup, subset audit, accessibility pairing
3
3
  globs: apps/web/**/*.tsx
4
4
  alwaysApply: false
5
+ appliesTo: [react]
5
6
  ---
6
7
 
7
8
  # Exxat DS — Font Awesome icons
@@ -1,6 +1,8 @@
1
1
  ---
2
- description: List-page hubs — FULL_HUB_SUPPORTED_VIEWS, Add view parity, and real renderers (never trimmed allowlists or placeholder list rows)
3
- alwaysApply: true
2
+ description: List-page hubs — FULL_HUB_SUPPORTED_VIEWS, Add view parity, and real renderers (never trimmed allowlists or placeholder list rows). Auto-attaches when editing hub clients / list-page templates.
3
+ globs: apps/web/components/**/*.{tsx,ts}
4
+ alwaysApply: false
5
+ appliesTo: [react]
4
6
  ---
5
7
 
6
8
  # Exxat DS — hub supported views (Add view parity)
@@ -50,5 +52,5 @@ Every **`ListPageTemplate`** + **`HubTable`** hub that mounts a product data gri
50
52
  ## See also
51
53
 
52
54
  - **`.cursor/rules/exxat-data-tables.mdc`**, **`exxat-list-page-connected-views.mdc`**, **`exxat-list-page-view-shells.mdc`**
53
- - **`docs/exxat-ds/patterns/hub-supported-views-pattern.md`** (vendored from monorepo `apps/web/docs/`)
54
- - **`docs/exxat-ds/patterns/data-views-pattern.md`**
55
+ - **`apps/web/docs/hub-supported-views-pattern.md`**
56
+ - **`apps/web/docs/data-views-pattern.md`**
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Exxat DS — show Kbd hints on primary/secondary actions, search, Ask Leo; avoid browser-reserved chords.
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — keyboard shortcuts (`Kbd`)
@@ -24,7 +25,7 @@ Use `@/components/ui/kbd` (`Kbd` + `KbdGroup`) anywhere users discover actions b
24
25
  | Inside a `DropdownMenuItem` via `shortcut=` | menu handles it — pass the chord string |
25
26
  | Standalone helper text on a surface | **default `tile`** |
26
27
 
27
- Glue multi-key chords into **one** bare kbd (`<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. See `new-placement-form.tsx` (Next = `{mod}⏎`, Back = `{mod}{alt}←`) and the primary "Ask Leo" button inside chart insight popovers.
28
+ Glue multi-key chords into **one** bare kbd (`<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. See `new-library-item-form.tsx` (Next = `{mod}⏎`, Back = `{mod}{alt}←`) and the primary "Ask Leo" button inside chart insight popovers.
28
29
 
29
30
  1. **Pair hint with behavior** — If `Kbd` shows a chord, implement the same shortcut. **Preferred:** the shared primitives from `@/components/ui/dropdown-menu`:
30
31
 
@@ -58,8 +59,8 @@ Use `@/components/ui/kbd` (`Kbd` + `KbdGroup`) anywhere users discover actions b
58
59
  | Toggle main sidebar | ⌘/Ctrl + **B** (`components/ui/sidebar.tsx`) |
59
60
  | Table search | ⌘/Ctrl + **K** (no Alt — `DataTable`) |
60
61
  | Ask Leo | ⌘/Ctrl + **⌥/Alt** + **K** |
61
- | New placement (Placements header) | ⌘/Ctrl + **⌥/Alt** + **N** |
62
- | Placements overflow menu | ⌘/Ctrl + **⌥/Alt** + **M** |
62
+ | New record (primary hub header) | ⌘/Ctrl + **⌥/Alt** + **N** |
63
+ | Hub overflow menu (⋯) | ⌘/Ctrl + **⌥/Alt** + **M** |
63
64
  | Export | ⌘/Ctrl + **⇧/Shift** + **E** |
64
65
  | Hide/Show metric section | ⌘/Ctrl + **⌥/Alt** + **H** |
65
66
  | Rename (view, tab) | **F2** |
@@ -79,14 +80,14 @@ Every **workflow surface** (form, dialog, drawer, sheet, multi-step wizard final
79
80
  1. **Primary action (submit/commit)** — **Enter** (⏎). Render the `<Kbd>⏎</Kbd>` **inline inside the button** (after the label, inside a `<KbdGroup className="ml-1.5">`) — NOT inside a hover `Tip`. Primary/secondary workflow buttons must expose the shortcut at rest so it is discoverable without hovering. Pair with a `<Shortcut keys="Enter" onInvoke={...}>` mounted while the surface is open. The shared `useShortcut` hook skips events from inputs/textarea/contenteditable, so Enter inside a text field still types normally — it only fires when focus is on the surface chrome.
80
81
  2. **Secondary action (Cancel/Dismiss)** — **Esc**. Inline `<Kbd>Esc</Kbd>` inside the Cancel button (same `ml-1.5` pattern). Radix `Dialog` / `Sheet` / `AlertDialog` already bind Esc natively.
81
82
 
82
- > Tip-on-hover Kbd hints remain correct for **page-level** actions (e.g. "New placement", ⋯ overflow triggers) where the button is part of dense page chrome and a persistent Kbd would crowd the layout. Workflow buttons inside a form/drawer/dialog are spacious enough to render the Kbd inline.
83
+ > Tip-on-hover Kbd hints remain correct for **page-level** actions (e.g. primary "New " CTA, ⋯ overflow triggers) where the button is part of dense page chrome and a persistent Kbd would crowd the layout. Workflow buttons inside a form/drawer/dialog are spacious enough to render the Kbd inline.
83
84
 
84
85
  **Variant inside a button:** always use `<Kbd variant="bare">` — no background, no border, inherits `currentColor` at 70% opacity. The default tile variant looks like a pasted-on patch on filled primary buttons. Glue multi-key chords into one `<Kbd variant="bare">⌘⌥←</Kbd>` rather than one tile per key.
85
86
  3. **Multi-step wizards** — plain **Enter** must NOT submit on intermediate steps (it would auto-close the review/final step when users hit Enter inside an input). Either:
86
87
  - Gate `form.onSubmit` on `step === lastStep` (`if (step !== N) { e.preventDefault(); return }`), **or**
87
88
  - Remove `type="submit"` on intermediate Next buttons and bind **⌘Enter** to "Next" via `<Shortcut>`.
88
89
  On the final step, plain **Enter** submits and the Kbd hint shows **⏎**.
89
- 4. Examples in-app: `new-placement-form.tsx` (Create placement = Enter on step 5, Back = ⌘⌥←), `export-drawer.tsx` (Export = Enter, Cancel = Esc).
90
+ 4. Examples in-app: `new-library-item-form.tsx` (Create = Enter on the final step, Back = ⌘⌥←), `export-drawer.tsx` (Export = Enter, Cancel = Esc).
90
91
 
91
92
  ## Every action menu MUST carry shortcuts
92
93
 
@@ -2,6 +2,7 @@
2
2
  description: KeyMetrics variant flat — transparent band, brand glow only, OKLCH hairlines
3
3
  globs: apps/web/components/**/*key-metrics*,apps/web/app/globals.css,apps/web/docs/kpi*.md
4
4
  alwaysApply: false
5
+ appliesTo: [react]
5
6
  ---
6
7
 
7
8
  # Exxat DS — KPI flat band (`variant="flat"`)
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Exxat DS — at most four KPI tiles on primary hub strips and key-metrics dashboard cards.
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — KPI strip (max four)
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Exxat DS — KPI deltas and trend arrows must be contextual; use trendPolarity when “up” is not good news.
3
3
  alwaysApply: true
4
+ appliesTo: [universal]
4
5
  ---
5
6
 
6
7
  # Exxat DS — KPI trends (`KeyMetrics` + chart mini-metrics)
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  description: Library library — folder-scoped hub header More menu must expose Customize folder; sheet on hub client
3
- globs: apps/web/components/library-*.tsx, packages/ui/template/components/library-*.tsx
3
+ globs: apps/web/components/library-*.tsx, packages/ui/template-vite/components/library-*.tsx
4
4
  alwaysApply: false
5
+ appliesTo: [react]
5
6
  ---
6
7
 
7
8
  # Exxat DS — Library hub header (folder scope)
@@ -1,6 +1,8 @@
1
1
  ---
2
- description: ListPageTemplate — shared table state across views, mock + KPI helpers, dashboard tab
3
- alwaysApply: true
2
+ description: ListPageTemplate — shared table state across views, mock + KPI helpers, dashboard tab. Auto-attaches when editing list-page React clients.
3
+ globs: apps/web/{components,lib,app}/**/*.{tsx,ts}
4
+ alwaysApply: false
5
+ appliesTo: [react]
4
6
  ---
5
7
 
6
8
  # Exxat DS — list page connected views
@@ -16,9 +18,11 @@ alwaysApply: true
16
18
  5. **List hub metrics strip** — Prefer **`KeyMetrics variant="flat"`** on **`ListPageTemplate`** **`metrics`** slot (transparent band, brand glow only) — **`docs/kpi-flat-band-pattern.md`**, **`.cursor/rules/exxat-kpi-flat-band.mdc`**.
17
19
  6. **MUST NOT** ship “not wired” / “switch to table” placeholders for list/board/dashboard when the stack supports those views.
18
20
  7. **MUST NOT** add a **primary nav** destination that is only placeholder copy with no **`ListPageTemplate`** hub, mock rows, and wired views — see **`apps/web/AGENTS.md` §4.1** (no empty hubs).
21
+ 8. **Add view parity** — Use **`FULL_HUB_SUPPORTED_VIEWS`** (default) and implement **all seven** views with real bodies — **`.cursor/rules/exxat-hub-supported-views.mdc`**. List rows **MUST** use **`ListPageBoardCard`** (`library-table.tsx`), not bare title + id lines.
19
22
 
20
23
  ## See also
21
24
 
22
25
  - **`.cursor/rules/exxat-centralized-list-dataset.mdc`** — single **`tableState.rows`** source for every hub view, inspectors, and **`TablePropertiesDrawer`** on the same **`DataTable`**.
23
26
  - **Centered view bodies + reusable shells:** **`apps/web/AGENTS.md` §4.5**, **`.cursor/rules/exxat-list-page-view-shells.mdc`**, **`ListPageViewFrame`** in **`components/data-views/list-page-view-frame.tsx`**.
24
27
  - **Flat KPI band:** **`docs/kpi-flat-band-pattern.md`**, **`.cursor/rules/exxat-kpi-flat-band.mdc`**.
28
+ - **Hub supported views:** **`docs/hub-supported-views-pattern.md`**, **`.cursor/rules/exxat-hub-supported-views.mdc`**.
@@ -2,6 +2,7 @@
2
2
  description: Exxat DS — centered reusable shells for list-page views (not page-specific markup)
3
3
  globs: apps/web/components/**/*.tsx
4
4
  alwaysApply: false
5
+ appliesTo: [react]
5
6
  ---
6
7
 
7
8
  # Exxat DS — list-page view shells (centered, reusable)
@@ -21,7 +22,7 @@ Domain logic (columns, tiles, folder trees) stays in **`*-table.tsx` / `*-client
21
22
  ## MUST NOT
22
23
 
23
24
  - Wrap **`DataTable`** (or its outer toolbar shell) in **`ListPageViewFrame`** if that **duplicates** horizontal inset already applied by **`DataTable`** / **`DataTableToolbar`** — see **`AGENTS.md` §5** (double indent).
24
- - Ship **view-only** layout classes only inside **`app/(app)/.../page.tsx`** for a hub that other entities will mirror — belong in **`data-views/`** or **`templates/`**.
25
+ - Ship **view-only** layout classes only inside **`src/views/<route>.tsx`** (or any route entry) for a hub that other entities will mirror — belong in **`data-views/`** or **`templates/`**.
25
26
 
26
27
  ## See also
27
28