@exxatdesignux/ui 0.2.16 → 0.2.17

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 (89) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +148 -3
  3. package/consumer-extras/cursor-skills/exxat-ds-skill/references/accessibility.md +142 -0
  4. package/consumer-extras/cursor-skills/exxat-ds-skill/references/coach-marks.md +169 -0
  5. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +382 -0
  6. package/consumer-extras/cursor-skills/exxat-mono-ids/SKILL.md +56 -0
  7. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +14 -0
  8. package/package.json +3 -3
  9. package/src/components/ui/banner.tsx +2 -0
  10. package/src/components/ui/chart.tsx +57 -2
  11. package/src/components/ui/sidebar.tsx +1 -0
  12. package/template/.claude/skills/exxat-ds-skill/SKILL.md +1 -1
  13. package/template/.cursor/rules/exxat-mono-ids.mdc +30 -0
  14. package/template/AGENTS.md +18 -15
  15. package/template/app/(app)/data-list/page.tsx +2 -2
  16. package/template/app/(app)/question-bank/layout.tsx +18 -5
  17. package/template/app/(app)/question-bank/new/page.tsx +58 -0
  18. package/template/app/globals.css +108 -1
  19. package/template/app/layout.tsx +41 -5
  20. package/template/components/app-sidebar.tsx +68 -34
  21. package/template/components/ask-leo-sidebar.tsx +0 -2
  22. package/template/components/brand-color-picker.tsx +344 -0
  23. package/template/components/compliance-list-view.tsx +33 -51
  24. package/template/components/compliance-table.tsx +24 -0
  25. package/template/components/data-table/index.tsx +68 -24
  26. package/template/components/data-table/pagination.tsx +0 -1
  27. package/template/components/data-table/types.ts +4 -1
  28. package/template/components/data-table/use-table-state.ts +243 -94
  29. package/template/components/data-views/data-row-list.tsx +183 -0
  30. package/template/components/data-views/index.ts +7 -3
  31. package/template/components/data-views/os-folder-glyph.tsx +8 -0
  32. package/template/components/export-drawer.tsx +1 -1
  33. package/template/components/exxat-product-logo.tsx +172 -317
  34. package/template/components/invite-collaborators-drawer.tsx +5 -3
  35. package/template/components/key-metrics.tsx +74 -46
  36. package/template/components/new-placement-form.tsx +4 -2
  37. package/template/components/new-question-composer.tsx +2208 -0
  38. package/template/components/page-breadcrumb-trail.tsx +131 -0
  39. package/template/components/page-header.tsx +2 -1
  40. package/template/components/{data-views/placement-board-card.tsx → placement-board-card.tsx} +1 -1
  41. package/template/components/placement-detail.tsx +1 -1
  42. package/template/components/placements-board-view.tsx +1 -1
  43. package/template/components/{data-list-client.tsx → placements-client.tsx} +9 -7
  44. package/template/components/placements-list-view.tsx +18 -132
  45. package/template/components/{data-list-table-cells.test.tsx → placements-table-cells.test.tsx} +2 -2
  46. package/template/components/{data-list-table-cells.tsx → placements-table-cells.tsx} +1 -1
  47. package/template/components/placements-table-columns.tsx +2 -2
  48. package/template/components/{data-list-table.tsx → placements-table.tsx} +67 -58
  49. package/template/components/product-switcher.tsx +26 -8
  50. package/template/components/product-wordmark.tsx +285 -0
  51. package/template/components/question-bank-client.tsx +20 -2
  52. package/template/components/question-bank-hub-client.tsx +108 -115
  53. package/template/components/question-bank-list-view.tsx +30 -54
  54. package/template/components/question-bank-new-folder-sheet.tsx +1 -1
  55. package/template/components/question-bank-secondary-nav.tsx +0 -3
  56. package/template/components/question-bank-table.tsx +30 -5
  57. package/template/components/rotations-empty-state.tsx +3 -0
  58. package/template/components/secondary-panel.tsx +23 -3
  59. package/template/components/settings-appearance-card.tsx +584 -141
  60. package/template/components/site-header.tsx +36 -31
  61. package/template/components/sites-list-view.tsx +31 -36
  62. package/template/components/sites-table.tsx +24 -0
  63. package/template/components/table-properties/drawer.tsx +1 -1
  64. package/template/components/team-client.tsx +1 -1
  65. package/template/components/team-list-view.tsx +34 -50
  66. package/template/components/team-table.tsx +29 -3
  67. package/template/components/templates/nested-secondary-panel-shell.tsx +8 -2
  68. package/template/components/ui/dot-pattern.tsx +50 -26
  69. package/template/components/ui/leo-icon.tsx +23 -3
  70. package/template/contexts/product-context.tsx +51 -7
  71. package/template/contexts/system-banner-context.tsx +112 -4
  72. package/template/eslint.config.mjs +18 -0
  73. package/template/hooks/use-sidebar-reflow-zoom.ts +21 -11
  74. package/template/lib/data-list-persistence.ts +57 -257
  75. package/template/lib/dev-log.test.ts +6 -5
  76. package/template/lib/exxat-palette.json +1462 -0
  77. package/template/lib/exxat-palette.ts +136 -0
  78. package/template/lib/list-page-table-properties.ts +1 -1
  79. package/template/lib/list-status-badges.ts +1 -1
  80. package/template/lib/mailto.ts +29 -0
  81. package/template/lib/placement-board-card-layout.ts +1 -1
  82. package/template/lib/product-brand.ts +268 -0
  83. package/template/lib/question-bank-authoring.ts +308 -0
  84. package/template/lib/question-bank-nav.ts +44 -0
  85. package/template/lib/raf-throttle.ts +45 -0
  86. package/template/lib/table-state-lifecycle.ts +474 -0
  87. package/template/next.config.mjs +156 -0
  88. package/template/package.json +3 -3
  89. package/template/stores/app-store.ts +46 -1
@@ -11,12 +11,37 @@
11
11
  import { create } from "zustand"
12
12
  import { persist } from "zustand/middleware"
13
13
 
14
- export type Product = "exxat-one" | "exxat-prism"
14
+ export type Product = "exxat-one" | "exxat-prism" | "exxat-assessment" | "exxat-custom"
15
+
16
+ export interface CustomProductBrand {
17
+ suffix: string
18
+ brandColor: string
19
+ }
20
+
21
+ export const DEFAULT_CUSTOM_PRODUCT_BRAND: CustomProductBrand = {
22
+ suffix: "Assessment",
23
+ brandColor: "oklch(0.7 0.0913 159.88)",
24
+ }
15
25
 
16
26
  interface AppState {
17
27
  /** Currently active product — drives theme class and sidebar logo */
18
28
  product: Product
19
29
  setProduct: (product: Product) => void
30
+ customProductBrand: CustomProductBrand | null
31
+ setCustomProductBrand: (brand: CustomProductBrand | null) => void
32
+ /**
33
+ * Per-product brand color overrides — drives the mark gradient + wordmark
34
+ * suffix tint when the user picks a custom color for a built-in product
35
+ * (Exxat One / Prism / Assessment) or the custom slot. Settings →
36
+ * Appearance → Product uses these so the color picker actually re-colours
37
+ * the rendered logo (mark + suffix), instead of just the unused `brandColor`
38
+ * on the underlying `ProductBrandConfig`.
39
+ */
40
+ productBrandColors: Partial<Record<Product, string>>
41
+ setProductBrandColor: (product: Product, color: string | null) => void
42
+ hiddenProductIds: Product[]
43
+ hideProduct: (product: Product) => void
44
+ showProduct: (product: Product) => void
20
45
  }
21
46
 
22
47
  export const useAppStore = create<AppState>()(
@@ -24,6 +49,26 @@ export const useAppStore = create<AppState>()(
24
49
  (set) => ({
25
50
  product: "exxat-one",
26
51
  setProduct: (product) => set({ product }),
52
+ customProductBrand: DEFAULT_CUSTOM_PRODUCT_BRAND,
53
+ setCustomProductBrand: (customProductBrand) => set({ customProductBrand }),
54
+ productBrandColors: {},
55
+ setProductBrandColor: (product, color) =>
56
+ set(state => {
57
+ const next = { ...state.productBrandColors }
58
+ if (color && color.trim()) {
59
+ next[product] = color.trim()
60
+ } else {
61
+ delete next[product]
62
+ }
63
+ return { productBrandColors: next }
64
+ }),
65
+ hiddenProductIds: [],
66
+ hideProduct: (product) => set(state => ({
67
+ hiddenProductIds: Array.from(new Set([...state.hiddenProductIds, product])),
68
+ })),
69
+ showProduct: (product) => set(state => ({
70
+ hiddenProductIds: state.hiddenProductIds.filter(id => id !== product),
71
+ })),
27
72
  }),
28
73
  {
29
74
  name: "exxat-app",