@exxatdesignux/ui 0.3.0 → 0.4.1

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 (214) hide show
  1. package/CHANGELOG.md +701 -6
  2. package/README.md +138 -0
  3. package/bin/init.mjs +134 -31
  4. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +1 -1
  5. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +2 -2
  6. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +1 -1
  7. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +2 -0
  8. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +1 -1
  9. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +3 -3
  10. package/consumer-extras/cursor-rules/exxat-library-hub-header.mdc +28 -0
  11. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +1 -1
  12. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +1 -1
  13. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +6 -6
  14. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +1 -1
  15. package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
  16. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +1 -1
  17. package/consumer-extras/cursor-skills/exxat-collaboration-access/SKILL.md +3 -3
  18. package/consumer-extras/cursor-skills/exxat-dedicated-search-surfaces/SKILL.md +2 -2
  19. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +7 -7
  20. package/consumer-extras/cursor-skills/exxat-kpi-flat-band/SKILL.md +1 -1
  21. package/consumer-extras/cursor-skills/exxat-list-page-view-shells/SKILL.md +1 -1
  22. package/consumer-extras/cursor-skills/exxat-mono-ids/SKILL.md +4 -4
  23. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +8 -8
  24. package/consumer-extras/cursor-skills/exxat-token-economy/SKILL.md +277 -0
  25. package/consumer-extras/handbook/HANDBOOK.md +2 -0
  26. package/consumer-extras/handbook/glossary.md +2 -1
  27. package/consumer-extras/handbook/reference-implementations.md +31 -4
  28. package/consumer-extras/patterns/collaboration-access-pattern.md +7 -7
  29. package/consumer-extras/patterns/data-views-pattern.md +18 -16
  30. package/consumer-extras/patterns/kpi-flat-band-pattern.md +2 -2
  31. package/dist/components/data-table/index.js +2 -2
  32. package/dist/components/data-table/index.js.map +1 -1
  33. package/dist/components/data-table/pagination.js +3 -3
  34. package/dist/components/data-table/pagination.js.map +1 -1
  35. package/dist/components/data-table/use-table-state.d.ts +1 -1
  36. package/dist/components/data-table/use-table-state.js.map +1 -1
  37. package/dist/components/data-views/data-row-list.js.map +1 -1
  38. package/dist/components/data-views/finder-panel-view.d.ts +1 -1
  39. package/dist/components/data-views/finder-panel-view.js.map +1 -1
  40. package/dist/components/data-views/hub-table.d.ts +9 -3
  41. package/dist/components/data-views/hub-table.js +262 -40
  42. package/dist/components/data-views/hub-table.js.map +1 -1
  43. package/dist/components/data-views/index.js +262 -40
  44. package/dist/components/data-views/index.js.map +1 -1
  45. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +2 -2
  46. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -1
  47. package/dist/components/data-views/list-page-tree-column-header.d.ts +1 -1
  48. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -1
  49. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -1
  50. package/dist/components/data-views/os-folder-glyph.d.ts +1 -1
  51. package/dist/components/data-views/os-folder-glyph.js.map +1 -1
  52. package/dist/components/ui/avatar.d.ts +1 -1
  53. package/dist/components/ui/key-metrics.js.map +1 -1
  54. package/dist/index.js +136 -39
  55. package/dist/index.js.map +1 -1
  56. package/package.json +3 -2
  57. package/src/components/data-table/index.tsx +2 -2
  58. package/src/components/data-table/pagination.tsx +5 -1
  59. package/src/components/data-table/use-table-state.ts +1 -1
  60. package/src/components/data-views/data-row-list.tsx +1 -1
  61. package/src/components/data-views/finder-panel-view.tsx +2 -2
  62. package/src/components/data-views/hub-table.tsx +149 -41
  63. package/src/components/data-views/list-page-split-hub-tokens.ts +2 -2
  64. package/src/components/data-views/list-page-tree-column-header.tsx +1 -1
  65. package/src/components/data-views/os-folder-glyph.tsx +1 -1
  66. package/src/components/ui/key-metrics.tsx +1 -1
  67. package/template/.claude/skills/exxat-ds-skill/SKILL.md +8 -7
  68. package/template/.cursor/rules/exxat-accessibility.mdc +1 -1
  69. package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
  70. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +6 -6
  71. package/template/.cursor/rules/exxat-data-tables.mdc +3 -3
  72. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +5 -5
  73. package/template/.cursor/rules/exxat-mono-ids.mdc +1 -1
  74. package/template/.cursor/rules/exxat-page-vs-drawer.mdc +1 -1
  75. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  76. package/template/AGENTS.md +43 -37
  77. package/template/app/(app)/columns/page.tsx +11 -0
  78. package/template/app/(app)/library/all/page.tsx +11 -0
  79. package/template/app/(app)/library/find/page.tsx +12 -0
  80. package/template/app/(app)/{question-bank → library}/layout.tsx +16 -16
  81. package/template/app/(app)/library/list/page.tsx +12 -0
  82. package/template/app/(app)/{question-bank → library}/new/page.tsx +10 -10
  83. package/template/app/(app)/library/page.tsx +11 -0
  84. package/template/app/(app)/tokens-themes/page.tsx +11 -0
  85. package/template/components/ask-leo-composer.tsx +2 -2
  86. package/template/components/columns-client.tsx +158 -0
  87. package/template/components/columns-showcase.tsx +541 -0
  88. package/template/components/data-views/index.ts +32 -6
  89. package/template/components/data-views/{question-bank-folder-tree-branch.tsx → library-folder-tree-branch.tsx} +19 -19
  90. package/template/components/data-views/table-cells.tsx +673 -0
  91. package/template/components/folder-details-shell.tsx +11 -11
  92. package/template/components/hub-tree-panel-view.tsx +24 -24
  93. package/template/components/{question-bank-board-view.tsx → library-board-view.tsx} +44 -44
  94. package/template/components/{question-bank-client.tsx → library-client.tsx} +82 -82
  95. package/template/components/{question-bank-dashboard-charts.tsx → library-dashboard-charts.tsx} +14 -14
  96. package/template/components/{question-bank-favorite-button.tsx → library-favorite-button.tsx} +7 -7
  97. package/template/components/{question-bank-hub-client.tsx → library-hub-client.tsx} +43 -43
  98. package/template/components/{question-bank-new-folder-sheet.tsx → library-new-folder-sheet.tsx} +14 -14
  99. package/template/components/{question-bank-os-folder-view.tsx → library-os-folder-view.tsx} +31 -31
  100. package/template/components/{question-bank-page-header.tsx → library-page-header.tsx} +6 -6
  101. package/template/components/library-panel-activator.tsx +8 -0
  102. package/template/components/{question-bank-secondary-nav.tsx → library-secondary-nav.tsx} +60 -60
  103. package/template/components/{question-bank-table.tsx → library-table.tsx} +97 -97
  104. package/template/components/list-hub-status-badge.tsx +2 -2
  105. package/template/components/{new-question-composer.tsx → new-library-item-form.tsx} +37 -37
  106. package/template/components/sidebar/app-sidebar.tsx +61 -5
  107. package/template/components/sidebar/secondary-panel.tsx +109 -56
  108. package/template/components/sidebar/sidebar-auto-collapse.tsx +2 -2
  109. package/template/components/sidebar/sidebar-auto-open.tsx +2 -1
  110. package/template/components/table-properties/types.ts +1 -1
  111. package/template/components/templates/discovery-hub-template.tsx +1 -1
  112. package/template/components/templates/new-focus-template.tsx +2 -2
  113. package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
  114. package/template/components/tokens-secondary-nav.tsx +192 -0
  115. package/template/components/tokens-themes-client.tsx +476 -0
  116. package/template/components/tokens-themes-section.tsx +386 -0
  117. package/template/docs/HANDBOOK.md +187 -0
  118. package/template/docs/blueprints/README.md +1 -1
  119. package/template/docs/blueprints/board-card.md +1 -1
  120. package/template/docs/blueprints/data-table.md +2 -2
  121. package/template/docs/blueprints/list-page-template.md +3 -3
  122. package/template/docs/blueprints/page-header.md +4 -4
  123. package/template/docs/collaboration-access-pattern.md +7 -7
  124. package/template/docs/component-selection-guide.md +1 -1
  125. package/template/docs/data-views-pattern.md +18 -16
  126. package/template/docs/glossary.md +58 -0
  127. package/template/docs/kpi-flat-band-pattern.md +3 -3
  128. package/template/docs/kpi-trend-pattern.md +18 -3
  129. package/template/docs/large-dataset-strategy.md +155 -0
  130. package/template/docs/library-hub-header-pattern.md +25 -0
  131. package/template/docs/migrations/_template.md +1 -1
  132. package/template/docs/reference-implementations.md +151 -0
  133. package/template/docs/token-taxonomy.md +1 -1
  134. package/template/docs/voice-and-tone.md +262 -0
  135. package/template/eslint.config.mjs +9 -39
  136. package/template/hooks/use-secondary-panel-hub-nav.ts +10 -10
  137. package/template/lib/ask-leo-route-context.ts +6 -18
  138. package/template/lib/coach-mark-registry.ts +0 -16
  139. package/template/lib/command-menu-config.ts +5 -12
  140. package/template/lib/command-menu-search-data.ts +8 -39
  141. package/template/lib/{question-bank-authoring.ts → library-authoring.ts} +89 -88
  142. package/template/lib/library-dedicated-search.ts +19 -0
  143. package/template/lib/library-hub-search.ts +90 -0
  144. package/template/lib/library-nav.ts +477 -0
  145. package/template/lib/library-recent-searches.ts +22 -0
  146. package/template/lib/{placements-supported-views.ts → library-supported-views.ts} +2 -2
  147. package/template/lib/list-status-badges.ts +16 -104
  148. package/template/lib/mock/dashboard.ts +1 -1
  149. package/template/lib/mock/{question-bank-folders.ts → library-folders.ts} +30 -30
  150. package/template/lib/mock/library-header-collaborators.ts +54 -0
  151. package/template/lib/mock/{question-bank-inspector.ts → library-inspector.ts} +29 -29
  152. package/template/lib/mock/{question-bank-kpi.ts → library-kpi.ts} +20 -20
  153. package/template/lib/mock/library.ts +249 -0
  154. package/template/lib/mock/navigation.tsx +32 -26
  155. package/template/lib/table-state-lifecycle.ts +1 -1
  156. package/template/next.config.mjs +7 -4
  157. package/template/package.json +0 -1
  158. package/tokens/hooks-index.json +2874 -0
  159. package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +0 -28
  160. package/template/app/(app)/examples/page.tsx +0 -41
  161. package/template/app/(app)/question-bank/find/page.tsx +0 -12
  162. package/template/app/(app)/question-bank/library/page.tsx +0 -11
  163. package/template/app/(app)/question-bank/list/page.tsx +0 -12
  164. package/template/app/(app)/question-bank/page.tsx +0 -11
  165. package/template/components/compliance-board-view.tsx +0 -142
  166. package/template/components/compliance-client.tsx +0 -92
  167. package/template/components/compliance-page-header.tsx +0 -89
  168. package/template/components/compliance-table.tsx +0 -468
  169. package/template/components/data-view-dashboard-charts-compliance.tsx +0 -963
  170. package/template/components/data-view-dashboard-charts-team.tsx +0 -971
  171. package/template/components/data-view-dashboard-charts.tsx +0 -1503
  172. package/template/components/new-placement-back-btn.tsx +0 -28
  173. package/template/components/new-placement-form.tsx +0 -942
  174. package/template/components/placement-board-card.tsx +0 -250
  175. package/template/components/placement-detail.tsx +0 -438
  176. package/template/components/placements-board-view.tsx +0 -397
  177. package/template/components/placements-client.tsx +0 -220
  178. package/template/components/placements-list-view.tsx +0 -124
  179. package/template/components/placements-page-header.tsx +0 -166
  180. package/template/components/placements-table-cells.test.tsx +0 -22
  181. package/template/components/placements-table-cells.tsx +0 -173
  182. package/template/components/placements-table-columns.tsx +0 -210
  183. package/template/components/placements-table.tsx +0 -934
  184. package/template/components/question-bank-panel-activator.tsx +0 -8
  185. package/template/components/rotations-empty-state.tsx +0 -50
  186. package/template/components/rotations-panel-activator.tsx +0 -8
  187. package/template/components/sites-board-view.tsx +0 -67
  188. package/template/components/sites-client.tsx +0 -154
  189. package/template/components/sites-table.tsx +0 -249
  190. package/template/components/team-board-view.tsx +0 -122
  191. package/template/components/team-client.tsx +0 -100
  192. package/template/components/team-page-header.tsx +0 -92
  193. package/template/components/team-table.tsx +0 -553
  194. package/template/docs/question-bank-hub-header-pattern.md +0 -25
  195. package/template/lib/compliance-supported-views.ts +0 -10
  196. package/template/lib/data-view-dashboard-placements-layout.ts +0 -215
  197. package/template/lib/mock/compliance-kpi.ts +0 -61
  198. package/template/lib/mock/compliance.ts +0 -146
  199. package/template/lib/mock/placements-kpi.ts +0 -134
  200. package/template/lib/mock/placements.ts +0 -176
  201. package/template/lib/mock/question-bank-header-collaborators.ts +0 -54
  202. package/template/lib/mock/question-bank.ts +0 -249
  203. package/template/lib/mock/sites-directory.ts +0 -16
  204. package/template/lib/mock/sites-kpi.ts +0 -25
  205. package/template/lib/mock/team-kpi.ts +0 -60
  206. package/template/lib/mock/team.ts +0 -118
  207. package/template/lib/placement-board-card-layout.ts +0 -79
  208. package/template/lib/question-bank-dedicated-search.ts +0 -19
  209. package/template/lib/question-bank-hub-search.ts +0 -90
  210. package/template/lib/question-bank-nav.ts +0 -477
  211. package/template/lib/question-bank-recent-searches.ts +0 -22
  212. package/template/lib/question-bank-supported-views.ts +0 -12
  213. package/template/lib/sites-supported-views.ts +0 -10
  214. package/template/lib/team-supported-views.ts +0 -10
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Shared layout tokens for list-hub split surfaces (Miller columns, tree + details).
3
- * Keeps Question bank panel / tree and generic `FinderPanelView` visually aligned.
3
+ * Keeps Library panel / tree and generic `FinderPanelView` visually aligned.
4
4
  */
5
- /** `ResizableHandle` between miller / tree columns — matches Question bank panel. */
5
+ /** `ResizableHandle` between miller / tree columns — matches Library panel. */
6
6
  declare const LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS = "w-1 bg-border/40 hover:bg-brand/20 transition-colors";
7
7
  /** Primary column stack (scope list, folder list, record list, …). */
8
8
  declare const LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS = "flex min-h-0 min-w-0 flex-col bg-card";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/data-views/list-page-split-hub-tokens.ts"],"names":[],"mappings":";AAMO,IAAM,sCAAA,GACX;AAGK,IAAM,yCAAA,GACX;AAGK,IAAM,yCAAA,GACX","file":"list-page-split-hub-tokens.js","sourcesContent":["/**\n * Shared layout tokens for list-hub split surfaces (Miller columns, tree + details).\n * Keeps Question bank panel / tree and generic `FinderPanelView` visually aligned.\n */\n\n/** `ResizableHandle` between miller / tree columns — matches Question bank panel. */\nexport const LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS =\n \"w-1 bg-border/40 hover:bg-brand/20 transition-colors\"\n\n/** Primary column stack (scope list, folder list, record list, …). */\nexport const LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n\n/** Right-hand inspector / detail column shell. */\nexport const LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n"]}
1
+ {"version":3,"sources":["../../../src/components/data-views/list-page-split-hub-tokens.ts"],"names":[],"mappings":";AAMO,IAAM,sCAAA,GACX;AAGK,IAAM,yCAAA,GACX;AAGK,IAAM,yCAAA,GACX","file":"list-page-split-hub-tokens.js","sourcesContent":["/**\n * Shared layout tokens for list-hub split surfaces (Miller columns, tree + details).\n * Keeps Library panel / tree and generic `FinderPanelView` visually aligned.\n */\n\n/** `ResizableHandle` between miller / tree columns — matches Library panel. */\nexport const LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS =\n \"w-1 bg-border/40 hover:bg-brand/20 transition-colors\"\n\n/** Primary column stack (scope list, folder list, record list, …). */\nexport const LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n\n/** Right-hand inspector / detail column shell. */\nexport const LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n"]}
@@ -8,7 +8,7 @@ interface ListPageTreeColumnHeaderProps {
8
8
  className?: string;
9
9
  }
10
10
  /**
11
- * Shared left-column header for tree / outline surfaces — matches Question bank “Questions” bar.
11
+ * Shared left-column header for tree / outline surfaces — matches Library “Questions” bar.
12
12
  */
13
13
  declare function ListPageTreeColumnHeader({ title, trailing, className, }: ListPageTreeColumnHeaderProps): react_jsx_runtime.JSX.Element;
14
14
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/data-views/list-page-tree-column-header.tsx"],"names":[],"mappings":";;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACUO,SAAS,wBAAA,CAAyB;AAAA,EACvC,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAkC;AAChC,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,sDAAA,EAAwD,SAAS,CAAA,EAClF,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6CAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,6DAAA,EAA+D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IAClF,2BACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAA,EAAsC,oBAAS,CAAA,GAC5D;AAAA,GAAA,EACN,CAAA,EACF,CAAA;AAEJ","file":"list-page-tree-column-header.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"../../lib/utils\"\n\nexport interface ListPageTreeColumnHeaderProps {\n title: string\n /** Right side (e.g. icon buttons) — keep touch targets ≥ 24px */\n trailing?: React.ReactNode\n className?: string\n}\n\n/**\n * Shared left-column header for tree / outline surfaces — matches Question bank “Questions” bar.\n */\nexport function ListPageTreeColumnHeader({\n title,\n trailing,\n className,\n}: ListPageTreeColumnHeaderProps) {\n return (\n <div className={cn(\"shrink-0 border-b border-border/50 bg-card px-3 py-2\", className)}>\n <div className=\"flex h-9 items-center justify-between gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\">{title}</h3>\n {trailing ? (\n <div className=\"flex shrink-0 items-center gap-0.5\">{trailing}</div>\n ) : null}\n </div>\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/data-views/list-page-tree-column-header.tsx"],"names":[],"mappings":";;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACUO,SAAS,wBAAA,CAAyB;AAAA,EACvC,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAkC;AAChC,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,sDAAA,EAAwD,SAAS,CAAA,EAClF,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6CAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,6DAAA,EAA+D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IAClF,2BACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAA,EAAsC,oBAAS,CAAA,GAC5D;AAAA,GAAA,EACN,CAAA,EACF,CAAA;AAEJ","file":"list-page-tree-column-header.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"../../lib/utils\"\n\nexport interface ListPageTreeColumnHeaderProps {\n title: string\n /** Right side (e.g. icon buttons) — keep touch targets ≥ 24px */\n trailing?: React.ReactNode\n className?: string\n}\n\n/**\n * Shared left-column header for tree / outline surfaces — matches Library “Questions” bar.\n */\nexport function ListPageTreeColumnHeader({\n title,\n trailing,\n className,\n}: ListPageTreeColumnHeaderProps) {\n return (\n <div className={cn(\"shrink-0 border-b border-border/50 bg-card px-3 py-2\", className)}>\n <div className=\"flex h-9 items-center justify-between gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\">{title}</h3>\n {trailing ? (\n <div className=\"flex shrink-0 items-center gap-0.5\">{trailing}</div>\n ) : null}\n </div>\n </div>\n )\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/resizable.tsx","../../../src/components/ui/list-page-view-frame.tsx","../../../src/components/data-views/list-page-split-hub-chrome.tsx","../../../src/components/data-views/list-page-split-hub-tokens.ts","../../../src/components/data-views/list-page-tree-panel-shell.tsx"],"names":["jsx"],"mappings":"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","file":"list-page-tree-panel-shell.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { GripVertical } from \"lucide-react\"\nimport { Group, Panel, Separator } from \"react-resizable-panels\"\nimport type { GroupProps, PanelProps, SeparatorProps } from \"react-resizable-panels\"\n\nimport { cn } from \"../../lib/utils\"\n\n// ─── ResizablePanelGroup ──────────────────────────────────────────────────────\n\nexport type ResizablePanelGroupProps = Omit<GroupProps, \"orientation\"> & {\n direction?: \"horizontal\" | \"vertical\"\n}\n\nexport function ResizablePanelGroup({\n direction = \"horizontal\",\n className,\n ...props\n}: ResizablePanelGroupProps) {\n return (\n <Group\n orientation={direction}\n className={cn(\n \"flex h-full w-full\",\n direction === \"vertical\" && \"flex-col\",\n className,\n )}\n {...props}\n />\n )\n}\n\n// ─── ResizablePanel ───────────────────────────────────────────────────────────\n\nexport type ResizablePanelProps = PanelProps\n\nexport const ResizablePanel = Panel\n\n// ─── ResizableHandle ──────────────────────────────────────────────────────────\n\nexport type ResizableHandleProps = Omit<SeparatorProps, \"children\"> & {\n /** Render a visible grip icon on the handle. */\n withHandle?: boolean\n}\n\nexport function ResizableHandle({ withHandle, className, ...props }: ResizableHandleProps) {\n return (\n <Separator\n className={cn(\n // Base — horizontal handle (between side-by-side panels)\n \"relative flex w-1 shrink-0 cursor-col-resize items-center justify-center bg-border/60\",\n \"transition-colors hover:bg-border active:bg-primary/30\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\",\n // Vertical handle (between stacked panels)\n \"data-[orientation=vertical]:h-1 data-[orientation=vertical]:w-full data-[orientation=vertical]:cursor-row-resize data-[orientation=vertical]:flex-row\",\n className,\n )}\n {...props}\n >\n {withHandle && (\n <div className=\"z-10 flex h-5 w-3.5 items-center justify-center rounded-sm border border-border bg-background shadow-sm\">\n <GripVertical className=\"h-3 w-3 text-muted-foreground\" />\n </div>\n )}\n </Separator>\n )\n}\n","\"use client\"\n\n/**\n * ListPageViewFrame — shared horizontal gutter + optional centered max-width\n * for list-hub **view bodies** (folder icon grid, finder panel chrome,\n * OS-style folder explorer, dashboard slices, etc.).\n *\n * MUST be used instead of ad-hoc `mx-4 lg:mx-6` + `mx-auto max-w-*` pairs on\n * each page — see `apps/web/AGENTS.md` §4.5 and\n * `.cursor/rules/exxat-list-page-view-shells.mdc`.\n *\n * MUST NOT wrap `DataTable` when its toolbar already applies the same inset\n * (avoid double gutter); use this for **non-table** view branches or\n * **sections below** the shared toolbar.\n *\n * Promotion note: this file lived at\n * `apps/web/components/data-views/list-page-view-frame.tsx` until\n * 2026-05-20. It moved into `@exxatdesignux/ui` because the gutter / max-\n * width contract is entity-agnostic and other consumers (a future docs\n * site, partner apps) need the same rhythm without dragging in the whole\n * `data-views/` family.\n */\n\nimport * as React from \"react\"\n\nimport { cn } from \"../../lib/utils\"\n\n/** Default horizontal rhythm for view bodies under `ListPageTemplate` (matches `FolderGridView`). */\nexport const LIST_PAGE_VIEW_FRAME_GUTTER = \"mx-4 mb-6 lg:mx-6\"\n\n/** Typical max width for icon grids / dense tile views on ultra-wide monitors. */\nexport const LIST_PAGE_VIEW_FRAME_MAX_ICON_GRID = \"max-w-6xl\"\n\n/** Slightly wider shell when a view includes toolbar + breadcrumbs + grid (e.g. OS folder explorer). */\nexport const LIST_PAGE_VIEW_FRAME_MAX_WIDE = \"max-w-7xl\"\n\nexport interface ListPageViewFrameProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n /**\n * When set, children are wrapped in `mx-auto w-full min-w-0` + this\n * max-width so the block stays centered inside the primary page column.\n */\n maxWidthClassName?: string\n /** Override outer gutter; default `LIST_PAGE_VIEW_FRAME_GUTTER`. */\n gutterClassName?: string\n}\n\nexport function ListPageViewFrame({\n children,\n className,\n maxWidthClassName,\n gutterClassName = LIST_PAGE_VIEW_FRAME_GUTTER,\n ...rest\n}: ListPageViewFrameProps) {\n return (\n <div className={cn(gutterClassName, className)} {...rest}>\n {maxWidthClassName ? (\n <div className={cn(\"mx-auto w-full min-w-0\", maxWidthClassName)}>{children}</div>\n ) : (\n children\n )}\n </div>\n )\n}\n","\"use client\"\n\n/**\n * Shared **centered** chrome for list-hub split surfaces (finder / tree / multi-column explorers).\n *\n * Composes `ListPageViewFrame` (gutter + max width) with a single bordered card + fixed viewport\n * height so panel and tree views match across routes (`AGENTS.md` §4.5).\n */\n\nimport * as React from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport {\n ListPageViewFrame,\n LIST_PAGE_VIEW_FRAME_GUTTER,\n LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n} from \"../ui/list-page-view-frame\"\n\n/** Default height band for split views under `ListPageTemplate` + toolbar. */\nexport const LIST_PAGE_SPLIT_HUB_HEIGHT_STYLE: React.CSSProperties = {\n height: \"calc(100vh - 280px)\",\n minHeight: 420,\n}\n\nconst SURFACE_CLASS =\n \"flex min-h-0 flex-1 flex-col overflow-hidden rounded-xl border border-border bg-card\"\n\nexport interface ListPageSplitHubChromeProps {\n children: React.ReactNode\n \"aria-label\"?: string\n gutterClassName?: string\n maxWidthClassName?: string\n /** Override default split viewport height / min-height */\n surfaceStyle?: React.CSSProperties\n surfaceClassName?: string\n}\n\nexport function ListPageSplitHubChrome({\n children,\n \"aria-label\": ariaLabel,\n gutterClassName = LIST_PAGE_VIEW_FRAME_GUTTER,\n maxWidthClassName = LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n surfaceStyle,\n surfaceClassName,\n}: ListPageSplitHubChromeProps) {\n return (\n <ListPageViewFrame\n gutterClassName={gutterClassName}\n maxWidthClassName={maxWidthClassName}\n className=\"flex min-h-0 flex-1 flex-col\"\n >\n <div\n className={cn(SURFACE_CLASS, surfaceClassName)}\n style={{ ...LIST_PAGE_SPLIT_HUB_HEIGHT_STYLE, ...surfaceStyle }}\n aria-label={ariaLabel}\n >\n {children}\n </div>\n </ListPageViewFrame>\n )\n}\n","/**\n * Shared layout tokens for list-hub split surfaces (Miller columns, tree + details).\n * Keeps Question bank panel / tree and generic `FinderPanelView` visually aligned.\n */\n\n/** `ResizableHandle` between miller / tree columns — matches Question bank panel. */\nexport const LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS =\n \"w-1 bg-border/40 hover:bg-brand/20 transition-colors\"\n\n/** Primary column stack (scope list, folder list, record list, …). */\nexport const LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n\n/** Right-hand inspector / detail column shell. */\nexport const LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n","\"use client\"\n\n/**\n * Generic two-pane layout: scrollable **tree / outline** column + **details** column,\n * with persisted split sizes (`ResizablePanelGroup` `id`) and shared **split hub chrome**\n * (`ListPageSplitHubChrome`) so tree views match finder / folder panels across the app.\n *\n * Domain hubs pass `tree` and `details` nodes; this module stays entity-agnostic.\n */\n\nimport * as React from \"react\"\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n} from \"../ui/resizable\"\nimport { ListPageSplitHubChrome } from \"./list-page-split-hub-chrome\"\nimport {\n LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS,\n LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS,\n LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS,\n} from \"./list-page-split-hub-tokens\"\nimport {\n LIST_PAGE_VIEW_FRAME_GUTTER,\n LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n} from \"../ui/list-page-view-frame\"\n\nexport interface ListPageTreePanelShellProps {\n /** Stable id for `react-resizable-panels` layout persistence (per hub / route). */\n resizableGroupId: string\n /** Left column (tree chrome + body). */\n tree: React.ReactNode\n /** Right column (detail / inspector). */\n details: React.ReactNode\n /** Accessible name for the split surface, e.g. “Curriculum tree and details”. */\n ariaLabel: string\n treePanelId?: string\n detailsPanelId?: string\n treeDefaultSize?: string\n treeMinSize?: string\n treeMaxSize?: string\n detailsDefaultSize?: string\n detailsMinSize?: string\n gutterClassName?: string\n maxWidthClassName?: string\n}\n\nexport function ListPageTreePanelShell({\n resizableGroupId,\n tree,\n details,\n ariaLabel,\n treePanelId = \"tree\",\n detailsPanelId = \"details\",\n treeDefaultSize = \"40%\",\n treeMinSize = \"20%\",\n treeMaxSize = \"60%\",\n detailsDefaultSize = \"60%\",\n detailsMinSize = \"30%\",\n gutterClassName = LIST_PAGE_VIEW_FRAME_GUTTER,\n maxWidthClassName = LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n}: ListPageTreePanelShellProps) {\n return (\n <ListPageSplitHubChrome\n aria-label={ariaLabel}\n gutterClassName={gutterClassName}\n maxWidthClassName={maxWidthClassName}\n >\n <ResizablePanelGroup id={resizableGroupId} direction=\"horizontal\" className=\"h-full min-h-0 w-full flex-1\">\n <ResizablePanel\n id={treePanelId}\n defaultSize={treeDefaultSize}\n minSize={treeMinSize}\n maxSize={treeMaxSize}\n className={LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS}\n >\n {tree}\n </ResizablePanel>\n <ResizableHandle withHandle className={LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS} />\n <ResizablePanel\n id={detailsPanelId}\n defaultSize={detailsDefaultSize}\n minSize={detailsMinSize}\n className={LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS}\n >\n {details}\n </ResizablePanel>\n </ResizablePanelGroup>\n </ListPageSplitHubChrome>\n )\n}\n"]}
1
+ {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/resizable.tsx","../../../src/components/ui/list-page-view-frame.tsx","../../../src/components/data-views/list-page-split-hub-chrome.tsx","../../../src/components/data-views/list-page-split-hub-tokens.ts","../../../src/components/data-views/list-page-tree-panel-shell.tsx"],"names":["jsx"],"mappings":"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","file":"list-page-tree-panel-shell.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { GripVertical } from \"lucide-react\"\nimport { Group, Panel, Separator } from \"react-resizable-panels\"\nimport type { GroupProps, PanelProps, SeparatorProps } from \"react-resizable-panels\"\n\nimport { cn } from \"../../lib/utils\"\n\n// ─── ResizablePanelGroup ──────────────────────────────────────────────────────\n\nexport type ResizablePanelGroupProps = Omit<GroupProps, \"orientation\"> & {\n direction?: \"horizontal\" | \"vertical\"\n}\n\nexport function ResizablePanelGroup({\n direction = \"horizontal\",\n className,\n ...props\n}: ResizablePanelGroupProps) {\n return (\n <Group\n orientation={direction}\n className={cn(\n \"flex h-full w-full\",\n direction === \"vertical\" && \"flex-col\",\n className,\n )}\n {...props}\n />\n )\n}\n\n// ─── ResizablePanel ───────────────────────────────────────────────────────────\n\nexport type ResizablePanelProps = PanelProps\n\nexport const ResizablePanel = Panel\n\n// ─── ResizableHandle ──────────────────────────────────────────────────────────\n\nexport type ResizableHandleProps = Omit<SeparatorProps, \"children\"> & {\n /** Render a visible grip icon on the handle. */\n withHandle?: boolean\n}\n\nexport function ResizableHandle({ withHandle, className, ...props }: ResizableHandleProps) {\n return (\n <Separator\n className={cn(\n // Base — horizontal handle (between side-by-side panels)\n \"relative flex w-1 shrink-0 cursor-col-resize items-center justify-center bg-border/60\",\n \"transition-colors hover:bg-border active:bg-primary/30\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\",\n // Vertical handle (between stacked panels)\n \"data-[orientation=vertical]:h-1 data-[orientation=vertical]:w-full data-[orientation=vertical]:cursor-row-resize data-[orientation=vertical]:flex-row\",\n className,\n )}\n {...props}\n >\n {withHandle && (\n <div className=\"z-10 flex h-5 w-3.5 items-center justify-center rounded-sm border border-border bg-background shadow-sm\">\n <GripVertical className=\"h-3 w-3 text-muted-foreground\" />\n </div>\n )}\n </Separator>\n )\n}\n","\"use client\"\n\n/**\n * ListPageViewFrame — shared horizontal gutter + optional centered max-width\n * for list-hub **view bodies** (folder icon grid, finder panel chrome,\n * OS-style folder explorer, dashboard slices, etc.).\n *\n * MUST be used instead of ad-hoc `mx-4 lg:mx-6` + `mx-auto max-w-*` pairs on\n * each page — see `apps/web/AGENTS.md` §4.5 and\n * `.cursor/rules/exxat-list-page-view-shells.mdc`.\n *\n * MUST NOT wrap `DataTable` when its toolbar already applies the same inset\n * (avoid double gutter); use this for **non-table** view branches or\n * **sections below** the shared toolbar.\n *\n * Promotion note: this file lived at\n * `apps/web/components/data-views/list-page-view-frame.tsx` until\n * 2026-05-20. It moved into `@exxatdesignux/ui` because the gutter / max-\n * width contract is entity-agnostic and other consumers (a future docs\n * site, partner apps) need the same rhythm without dragging in the whole\n * `data-views/` family.\n */\n\nimport * as React from \"react\"\n\nimport { cn } from \"../../lib/utils\"\n\n/** Default horizontal rhythm for view bodies under `ListPageTemplate` (matches `FolderGridView`). */\nexport const LIST_PAGE_VIEW_FRAME_GUTTER = \"mx-4 mb-6 lg:mx-6\"\n\n/** Typical max width for icon grids / dense tile views on ultra-wide monitors. */\nexport const LIST_PAGE_VIEW_FRAME_MAX_ICON_GRID = \"max-w-6xl\"\n\n/** Slightly wider shell when a view includes toolbar + breadcrumbs + grid (e.g. OS folder explorer). */\nexport const LIST_PAGE_VIEW_FRAME_MAX_WIDE = \"max-w-7xl\"\n\nexport interface ListPageViewFrameProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n /**\n * When set, children are wrapped in `mx-auto w-full min-w-0` + this\n * max-width so the block stays centered inside the primary page column.\n */\n maxWidthClassName?: string\n /** Override outer gutter; default `LIST_PAGE_VIEW_FRAME_GUTTER`. */\n gutterClassName?: string\n}\n\nexport function ListPageViewFrame({\n children,\n className,\n maxWidthClassName,\n gutterClassName = LIST_PAGE_VIEW_FRAME_GUTTER,\n ...rest\n}: ListPageViewFrameProps) {\n return (\n <div className={cn(gutterClassName, className)} {...rest}>\n {maxWidthClassName ? (\n <div className={cn(\"mx-auto w-full min-w-0\", maxWidthClassName)}>{children}</div>\n ) : (\n children\n )}\n </div>\n )\n}\n","\"use client\"\n\n/**\n * Shared **centered** chrome for list-hub split surfaces (finder / tree / multi-column explorers).\n *\n * Composes `ListPageViewFrame` (gutter + max width) with a single bordered card + fixed viewport\n * height so panel and tree views match across routes (`AGENTS.md` §4.5).\n */\n\nimport * as React from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport {\n ListPageViewFrame,\n LIST_PAGE_VIEW_FRAME_GUTTER,\n LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n} from \"../ui/list-page-view-frame\"\n\n/** Default height band for split views under `ListPageTemplate` + toolbar. */\nexport const LIST_PAGE_SPLIT_HUB_HEIGHT_STYLE: React.CSSProperties = {\n height: \"calc(100vh - 280px)\",\n minHeight: 420,\n}\n\nconst SURFACE_CLASS =\n \"flex min-h-0 flex-1 flex-col overflow-hidden rounded-xl border border-border bg-card\"\n\nexport interface ListPageSplitHubChromeProps {\n children: React.ReactNode\n \"aria-label\"?: string\n gutterClassName?: string\n maxWidthClassName?: string\n /** Override default split viewport height / min-height */\n surfaceStyle?: React.CSSProperties\n surfaceClassName?: string\n}\n\nexport function ListPageSplitHubChrome({\n children,\n \"aria-label\": ariaLabel,\n gutterClassName = LIST_PAGE_VIEW_FRAME_GUTTER,\n maxWidthClassName = LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n surfaceStyle,\n surfaceClassName,\n}: ListPageSplitHubChromeProps) {\n return (\n <ListPageViewFrame\n gutterClassName={gutterClassName}\n maxWidthClassName={maxWidthClassName}\n className=\"flex min-h-0 flex-1 flex-col\"\n >\n <div\n className={cn(SURFACE_CLASS, surfaceClassName)}\n style={{ ...LIST_PAGE_SPLIT_HUB_HEIGHT_STYLE, ...surfaceStyle }}\n aria-label={ariaLabel}\n >\n {children}\n </div>\n </ListPageViewFrame>\n )\n}\n","/**\n * Shared layout tokens for list-hub split surfaces (Miller columns, tree + details).\n * Keeps Library panel / tree and generic `FinderPanelView` visually aligned.\n */\n\n/** `ResizableHandle` between miller / tree columns — matches Library panel. */\nexport const LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS =\n \"w-1 bg-border/40 hover:bg-brand/20 transition-colors\"\n\n/** Primary column stack (scope list, folder list, record list, …). */\nexport const LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n\n/** Right-hand inspector / detail column shell. */\nexport const LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS =\n \"flex min-h-0 min-w-0 flex-col bg-card\"\n","\"use client\"\n\n/**\n * Generic two-pane layout: scrollable **tree / outline** column + **details** column,\n * with persisted split sizes (`ResizablePanelGroup` `id`) and shared **split hub chrome**\n * (`ListPageSplitHubChrome`) so tree views match finder / folder panels across the app.\n *\n * Domain hubs pass `tree` and `details` nodes; this module stays entity-agnostic.\n */\n\nimport * as React from \"react\"\nimport {\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n} from \"../ui/resizable\"\nimport { ListPageSplitHubChrome } from \"./list-page-split-hub-chrome\"\nimport {\n LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS,\n LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS,\n LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS,\n} from \"./list-page-split-hub-tokens\"\nimport {\n LIST_PAGE_VIEW_FRAME_GUTTER,\n LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n} from \"../ui/list-page-view-frame\"\n\nexport interface ListPageTreePanelShellProps {\n /** Stable id for `react-resizable-panels` layout persistence (per hub / route). */\n resizableGroupId: string\n /** Left column (tree chrome + body). */\n tree: React.ReactNode\n /** Right column (detail / inspector). */\n details: React.ReactNode\n /** Accessible name for the split surface, e.g. “Curriculum tree and details”. */\n ariaLabel: string\n treePanelId?: string\n detailsPanelId?: string\n treeDefaultSize?: string\n treeMinSize?: string\n treeMaxSize?: string\n detailsDefaultSize?: string\n detailsMinSize?: string\n gutterClassName?: string\n maxWidthClassName?: string\n}\n\nexport function ListPageTreePanelShell({\n resizableGroupId,\n tree,\n details,\n ariaLabel,\n treePanelId = \"tree\",\n detailsPanelId = \"details\",\n treeDefaultSize = \"40%\",\n treeMinSize = \"20%\",\n treeMaxSize = \"60%\",\n detailsDefaultSize = \"60%\",\n detailsMinSize = \"30%\",\n gutterClassName = LIST_PAGE_VIEW_FRAME_GUTTER,\n maxWidthClassName = LIST_PAGE_VIEW_FRAME_MAX_WIDE,\n}: ListPageTreePanelShellProps) {\n return (\n <ListPageSplitHubChrome\n aria-label={ariaLabel}\n gutterClassName={gutterClassName}\n maxWidthClassName={maxWidthClassName}\n >\n <ResizablePanelGroup id={resizableGroupId} direction=\"horizontal\" className=\"h-full min-h-0 w-full flex-1\">\n <ResizablePanel\n id={treePanelId}\n defaultSize={treeDefaultSize}\n minSize={treeMinSize}\n maxSize={treeMaxSize}\n className={LIST_PAGE_SPLIT_MILLER_COLUMN_PANEL_CLASS}\n >\n {tree}\n </ResizablePanel>\n <ResizableHandle withHandle className={LIST_PAGE_SPLIT_RESIZABLE_HANDLE_CLASS} />\n <ResizablePanel\n id={detailsPanelId}\n defaultSize={detailsDefaultSize}\n minSize={detailsMinSize}\n className={LIST_PAGE_SPLIT_MILLER_DETAIL_PANEL_CLASS}\n >\n {details}\n </ResizablePanel>\n </ResizablePanelGroup>\n </ListPageSplitHubChrome>\n )\n}\n"]}
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
3
  /**
4
4
  * Color palette tones shared across folder hubs. Domain-specific palette
5
- * names (e.g. `QuestionBankFolderColorKey`) are structurally identical to
5
+ * names (e.g. `LibraryFolderColorKey`) are structurally identical to
6
6
  * this union and pass through without conversion.
7
7
  */
8
8
  type FolderGlyphColorKey = "brand" | "success" | "warning" | "destructive" | "muted" | "chart1" | "chart2" | "chart3";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/data-views/os-folder-glyph.tsx"],"names":[],"mappings":"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","file":"os-folder-glyph.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\n/**\n * Windows 11–style folder art (Icons8) + optional FA glyph on the pocket.\n * Static asset: `public/folders/icons8-folder-windows-11.svg`\n */\n\nimport * as React from \"react\"\nimport { cn } from \"../../lib/utils\"\n\n/**\n * Color palette tones shared across folder hubs. Domain-specific palette\n * names (e.g. `QuestionBankFolderColorKey`) are structurally identical to\n * this union and pass through without conversion.\n */\nexport type FolderGlyphColorKey =\n | \"brand\"\n | \"success\"\n | \"warning\"\n | \"destructive\"\n | \"muted\"\n | \"chart1\"\n | \"chart2\"\n | \"chart3\"\n\n/** Default asset path (override via `OsFolderGlyph` `src` prop if you ship a different file). */\nexport const OS_FOLDER_GLYPH_SRC = \"/folders/icons8-folder-windows-11.svg\"\n\n/** Subtle hue tweak so “color” choice still reads on the shared yellow asset. */\nconst COLOR_TINT_FILTER: Record<FolderGlyphColorKey, string> = {\n brand: \"hue-rotate(-42deg) saturate(1.25) brightness(0.97)\",\n success: \"hue-rotate(82deg) saturate(1.2) brightness(0.95)\",\n warning: \"hue-rotate(-5deg) saturate(1.35) brightness(1.02)\",\n destructive: \"hue-rotate(300deg) saturate(1.15) brightness(0.92)\",\n muted: \"saturate(0.15) brightness(1.08)\",\n chart1: \"hue-rotate(200deg) saturate(1.2) brightness(0.96)\",\n chart2: \"hue-rotate(95deg) saturate(1.15) brightness(0.96)\",\n chart3: \"hue-rotate(265deg) saturate(1.2) brightness(0.96)\",\n}\n\nconst SIZE_MAP = {\n /** Compact — folder inspector / column headers (matches ~36px row height). */\n xs: \"h-9 w-[2.6rem]\",\n sm: \"h-[3.35rem] w-[3.85rem]\",\n md: \"h-[4.6rem] w-[5.25rem]\",\n lg: \"h-[6.5rem] w-[7.25rem]\",\n}\n\nconst ICON_TEXT: Record<keyof typeof SIZE_MAP, string> = {\n xs: \"text-[13px] leading-none\",\n sm: \"text-lg\",\n md: \"text-2xl\",\n lg: \"text-4xl\",\n}\n\n/** Darker version of each folder color for punched icon appearance. */\nconst ICON_COLOR: Record<FolderGlyphColorKey, string> = {\n brand: \"text-orange-800 dark:text-orange-600\",\n success: \"text-emerald-800 dark:text-emerald-600\",\n warning: \"text-amber-800 dark:text-amber-600\",\n destructive: \"text-red-800 dark:text-red-600\",\n muted: \"text-slate-600 dark:text-slate-400\",\n chart1: \"text-blue-800 dark:text-blue-600\",\n chart2: \"text-lime-800 dark:text-lime-600\",\n chart3: \"text-purple-800 dark:text-purple-600\",\n}\n\nexport interface OsFolderGlyphProps {\n colorKey: FolderGlyphColorKey\n /** Font Awesome icon classes without weight (e.g. `fa-stethoscope`). */\n icon: string\n size?: keyof typeof SIZE_MAP\n className?: string\n variant?: \"solid\" | \"outline\"\n /**\n * When false, exposes `role=\"img\"` + `aria-label` (use with a short label, e.g. sheet preview).\n * When true (default), hides the glyph from AT — parent control should name the action.\n */\n decorative?: boolean\n /** Required when `decorative={false}` */\n label?: string\n}\n\nexport function OsFolderGlyph({\n colorKey,\n icon,\n size = \"md\",\n className,\n variant = \"solid\",\n decorative = true,\n label,\n}: OsFolderGlyphProps) {\n const outline = variant === \"outline\"\n const tint = COLOR_TINT_FILTER[colorKey]\n\n return (\n <div\n className={cn(\n \"group relative shrink-0 select-none transition-[transform,box-shadow] duration-200 ease-out\",\n \"hover:z-[1] hover:scale-105 motion-reduce:transform-none motion-reduce:hover:scale-100\",\n SIZE_MAP[size],\n className,\n )}\n role={!decorative && label ? \"img\" : undefined}\n aria-label={!decorative ? label : undefined}\n aria-hidden={decorative ? true : undefined}\n >\n {/* Static SVG — design-system ships an HTML `<img>` so non-Next consumers\n (Vite, Remix, plain CRA) can use it without `next/image`. Folder\n grids render many of these at once; lazy-loading lets the browser\n skip off-screen glyphs until they scroll near the viewport. */}\n <img\n src={OS_FOLDER_GLYPH_SRC}\n alt=\"\"\n width={240}\n height={240}\n draggable={false}\n loading=\"lazy\"\n decoding=\"async\"\n className={cn(\n \"h-full w-full object-contain\",\n \"transition-[filter] duration-200\",\n outline && \"opacity-75 saturate-[0.65]\",\n )}\n style={outline ? undefined : { filter: tint }}\n />\n <span\n className={cn(\n \"pointer-events-none absolute inset-0 flex items-center justify-center\",\n size === \"xs\" ? \"translate-y-[0.18rem]\" : \"translate-y-[0.35rem]\",\n ICON_TEXT[size],\n outline\n ? \"text-muted-foreground\"\n : cn(ICON_COLOR[colorKey], \"opacity-100\"),\n )}\n >\n <i className={cn(\"fa-solid\", icon)} aria-hidden=\"true\" />\n </span>\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/data-views/os-folder-glyph.tsx"],"names":[],"mappings":"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","file":"os-folder-glyph.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\n/**\n * Windows 11–style folder art (Icons8) + optional FA glyph on the pocket.\n * Static asset: `public/folders/icons8-folder-windows-11.svg`\n */\n\nimport * as React from \"react\"\nimport { cn } from \"../../lib/utils\"\n\n/**\n * Color palette tones shared across folder hubs. Domain-specific palette\n * names (e.g. `LibraryFolderColorKey`) are structurally identical to\n * this union and pass through without conversion.\n */\nexport type FolderGlyphColorKey =\n | \"brand\"\n | \"success\"\n | \"warning\"\n | \"destructive\"\n | \"muted\"\n | \"chart1\"\n | \"chart2\"\n | \"chart3\"\n\n/** Default asset path (override via `OsFolderGlyph` `src` prop if you ship a different file). */\nexport const OS_FOLDER_GLYPH_SRC = \"/folders/icons8-folder-windows-11.svg\"\n\n/** Subtle hue tweak so “color” choice still reads on the shared yellow asset. */\nconst COLOR_TINT_FILTER: Record<FolderGlyphColorKey, string> = {\n brand: \"hue-rotate(-42deg) saturate(1.25) brightness(0.97)\",\n success: \"hue-rotate(82deg) saturate(1.2) brightness(0.95)\",\n warning: \"hue-rotate(-5deg) saturate(1.35) brightness(1.02)\",\n destructive: \"hue-rotate(300deg) saturate(1.15) brightness(0.92)\",\n muted: \"saturate(0.15) brightness(1.08)\",\n chart1: \"hue-rotate(200deg) saturate(1.2) brightness(0.96)\",\n chart2: \"hue-rotate(95deg) saturate(1.15) brightness(0.96)\",\n chart3: \"hue-rotate(265deg) saturate(1.2) brightness(0.96)\",\n}\n\nconst SIZE_MAP = {\n /** Compact — folder inspector / column headers (matches ~36px row height). */\n xs: \"h-9 w-[2.6rem]\",\n sm: \"h-[3.35rem] w-[3.85rem]\",\n md: \"h-[4.6rem] w-[5.25rem]\",\n lg: \"h-[6.5rem] w-[7.25rem]\",\n}\n\nconst ICON_TEXT: Record<keyof typeof SIZE_MAP, string> = {\n xs: \"text-[13px] leading-none\",\n sm: \"text-lg\",\n md: \"text-2xl\",\n lg: \"text-4xl\",\n}\n\n/** Darker version of each folder color for punched icon appearance. */\nconst ICON_COLOR: Record<FolderGlyphColorKey, string> = {\n brand: \"text-orange-800 dark:text-orange-600\",\n success: \"text-emerald-800 dark:text-emerald-600\",\n warning: \"text-amber-800 dark:text-amber-600\",\n destructive: \"text-red-800 dark:text-red-600\",\n muted: \"text-slate-600 dark:text-slate-400\",\n chart1: \"text-blue-800 dark:text-blue-600\",\n chart2: \"text-lime-800 dark:text-lime-600\",\n chart3: \"text-purple-800 dark:text-purple-600\",\n}\n\nexport interface OsFolderGlyphProps {\n colorKey: FolderGlyphColorKey\n /** Font Awesome icon classes without weight (e.g. `fa-stethoscope`). */\n icon: string\n size?: keyof typeof SIZE_MAP\n className?: string\n variant?: \"solid\" | \"outline\"\n /**\n * When false, exposes `role=\"img\"` + `aria-label` (use with a short label, e.g. sheet preview).\n * When true (default), hides the glyph from AT — parent control should name the action.\n */\n decorative?: boolean\n /** Required when `decorative={false}` */\n label?: string\n}\n\nexport function OsFolderGlyph({\n colorKey,\n icon,\n size = \"md\",\n className,\n variant = \"solid\",\n decorative = true,\n label,\n}: OsFolderGlyphProps) {\n const outline = variant === \"outline\"\n const tint = COLOR_TINT_FILTER[colorKey]\n\n return (\n <div\n className={cn(\n \"group relative shrink-0 select-none transition-[transform,box-shadow] duration-200 ease-out\",\n \"hover:z-[1] hover:scale-105 motion-reduce:transform-none motion-reduce:hover:scale-100\",\n SIZE_MAP[size],\n className,\n )}\n role={!decorative && label ? \"img\" : undefined}\n aria-label={!decorative ? label : undefined}\n aria-hidden={decorative ? true : undefined}\n >\n {/* Static SVG — design-system ships an HTML `<img>` so non-Next consumers\n (Vite, Remix, plain CRA) can use it without `next/image`. Folder\n grids render many of these at once; lazy-loading lets the browser\n skip off-screen glyphs until they scroll near the viewport. */}\n <img\n src={OS_FOLDER_GLYPH_SRC}\n alt=\"\"\n width={240}\n height={240}\n draggable={false}\n loading=\"lazy\"\n decoding=\"async\"\n className={cn(\n \"h-full w-full object-contain\",\n \"transition-[filter] duration-200\",\n outline && \"opacity-75 saturate-[0.65]\",\n )}\n style={outline ? undefined : { filter: tint }}\n />\n <span\n className={cn(\n \"pointer-events-none absolute inset-0 flex items-center justify-center\",\n size === \"xs\" ? \"translate-y-[0.18rem]\" : \"translate-y-[0.35rem]\",\n ICON_TEXT[size],\n outline\n ? \"text-muted-foreground\"\n : cn(ICON_COLOR[colorKey], \"opacity-100\"),\n )}\n >\n <i className={cn(\"fa-solid\", icon)} aria-hidden=\"true\" />\n </span>\n </div>\n )\n}\n"]}
@@ -7,7 +7,7 @@ import { VariantProps } from 'class-variance-authority';
7
7
  /** Maps to Shadcn Studio avatar demos (shape / ring / stack). Uses theme tokens only. */
8
8
  declare const avatarRootVariants: (props?: ({
9
9
  size?: "default" | "sm" | "lg" | null | undefined;
10
- shape?: "circle" | "square" | "rounded-lg" | "rounded-sm" | "rounded-md" | "rounded-xl" | null | undefined;
10
+ shape?: "circle" | "square" | "rounded-sm" | "rounded-md" | "rounded-lg" | "rounded-xl" | null | undefined;
11
11
  variant?: "default" | "group" | "ring" | "ring-offset" | null | undefined;
12
12
  } & class_variance_authority_types.ClassProp) | undefined) => string;
13
13
  type AvatarProps = React.ComponentProps<typeof Avatar$1.Root> & VariantProps<typeof avatarRootVariants> & {