@exxatdesignux/ui 0.2.19 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +662 -7
- package/bin/sync-extras.mjs +116 -29
- package/consumer-extras/README.md +42 -7
- package/consumer-extras/cursor-rules/exxat-accessibility.mdc +39 -0
- package/consumer-extras/cursor-rules/exxat-board-cards.mdc +26 -0
- package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +21 -0
- package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +21 -0
- package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +44 -0
- package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +32 -0
- package/consumer-extras/cursor-rules/exxat-command-menu.mdc +22 -0
- package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +53 -0
- package/consumer-extras/cursor-rules/exxat-data-tables.mdc +43 -0
- package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +25 -0
- package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +22 -0
- package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +56 -0
- package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +100 -0
- package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +28 -0
- package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +21 -0
- package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-library-hub-header.mdc +28 -0
- package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
- package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
- package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
- package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
- package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
- package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
- package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -0
- package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +34 -0
- package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +77 -0
- package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +103 -0
- package/consumer-extras/cursor-skills/exxat-accessibility/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +3 -3
- package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +5 -16
- package/consumer-extras/cursor-skills/exxat-collaboration-access/SKILL.md +3 -3
- package/consumer-extras/cursor-skills/exxat-dedicated-search-surfaces/SKILL.md +2 -2
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +19 -34
- package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
- package/consumer-extras/cursor-skills/exxat-kpi-flat-band/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-list-page-view-shells/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-mono-ids/SKILL.md +4 -4
- package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +10 -12
- package/consumer-extras/cursor-skills/exxat-token-economy/SKILL.md +277 -0
- package/consumer-extras/handbook/HANDBOOK.md +187 -0
- package/consumer-extras/handbook/glossary.md +58 -0
- package/consumer-extras/handbook/reference-implementations.md +153 -0
- package/consumer-extras/handbook/voice-and-tone.md +262 -0
- package/consumer-extras/patterns/collaboration-access-pattern.md +7 -7
- package/consumer-extras/patterns/command-menu-pattern.md +1 -1
- package/consumer-extras/patterns/consumer-upgrade-checklist.md +0 -20
- package/consumer-extras/patterns/data-views-pattern.md +31 -66
- package/consumer-extras/patterns/kpi-flat-band-pattern.md +2 -2
- package/consumer-extras/patterns/shell-surface-elevation-pattern.md +3 -5
- package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
- package/dist/components/data-table/filter-date-calendar.js +280 -0
- package/dist/components/data-table/filter-date-calendar.js.map +1 -0
- package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
- package/dist/components/data-table/filter-text-value-input.js +561 -0
- package/dist/components/data-table/filter-text-value-input.js.map +1 -0
- package/dist/components/data-table/index.d.ts +45 -0
- package/dist/components/data-table/index.js +3085 -0
- package/dist/components/data-table/index.js.map +1 -0
- package/dist/components/data-table/pagination.d.ts +28 -0
- package/dist/components/data-table/pagination.js +3264 -0
- package/dist/components/data-table/pagination.js.map +1 -0
- package/dist/components/data-table/types.d.ts +84 -0
- package/dist/components/data-table/types.js +3 -0
- package/dist/components/data-table/types.js.map +1 -0
- package/dist/components/data-table/use-table-state.d.ts +116 -0
- package/dist/components/data-table/use-table-state.js +670 -0
- package/dist/components/data-table/use-table-state.js.map +1 -0
- package/dist/components/data-views/board-card-primitives.d.ts +22 -0
- package/dist/components/data-views/board-card-primitives.js +84 -0
- package/dist/components/data-views/board-card-primitives.js.map +1 -0
- package/dist/components/data-views/data-row-list.d.ts +33 -0
- package/dist/components/data-views/data-row-list.js +106 -0
- package/dist/components/data-views/data-row-list.js.map +1 -0
- package/dist/components/data-views/finder-panel-view.d.ts +54 -0
- package/dist/components/data-views/finder-panel-view.js +388 -0
- package/dist/components/data-views/finder-panel-view.js.map +1 -0
- package/dist/components/data-views/folder-grid-view.d.ts +22 -0
- package/dist/components/data-views/folder-grid-view.js +58 -0
- package/dist/components/data-views/folder-grid-view.js.map +1 -0
- package/dist/components/data-views/hub-table.d.ts +173 -0
- package/dist/components/data-views/hub-table.js +5783 -0
- package/dist/components/data-views/hub-table.js.map +1 -0
- package/dist/components/data-views/index.d.ts +27 -0
- package/dist/components/data-views/index.js +6797 -0
- package/dist/components/data-views/index.js.map +1 -0
- package/dist/components/data-views/list-page-board-card.d.ts +72 -0
- package/dist/components/data-views/list-page-board-card.js +264 -0
- package/dist/components/data-views/list-page-board-card.js.map +1 -0
- package/dist/components/data-views/list-page-board-template.d.ts +24 -0
- package/dist/components/data-views/list-page-board-template.js +137 -0
- package/dist/components/data-views/list-page-board-template.js.map +1 -0
- package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
- package/dist/components/data-views/list-page-connected-view-body.js +116 -0
- package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
- package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
- package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
- package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
- package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
- package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
- package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
- package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
- package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
- package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
- package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
- package/dist/components/data-views/list-page-tree-column-header.js +22 -0
- package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
- package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
- package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
- package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
- package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
- package/dist/components/data-views/os-folder-glyph.js +104 -0
- package/dist/components/data-views/os-folder-glyph.js.map +1 -0
- package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
- package/dist/components/data-views/outline-tree-menu.js +131 -0
- package/dist/components/data-views/outline-tree-menu.js.map +1 -0
- package/dist/components/table-properties/column-row.d.ts +22 -0
- package/dist/components/table-properties/column-row.js +153 -0
- package/dist/components/table-properties/column-row.js.map +1 -0
- package/dist/components/table-properties/draggable-list.d.ts +24 -0
- package/dist/components/table-properties/draggable-list.js +53 -0
- package/dist/components/table-properties/draggable-list.js.map +1 -0
- package/dist/components/table-properties/drawer-button.d.ts +110 -0
- package/dist/components/table-properties/drawer-button.js +2748 -0
- package/dist/components/table-properties/drawer-button.js.map +1 -0
- package/dist/components/table-properties/drawer.d.ts +100 -0
- package/dist/components/table-properties/drawer.js +2595 -0
- package/dist/components/table-properties/drawer.js.map +1 -0
- package/dist/components/table-properties/filter-card.d.ts +24 -0
- package/dist/components/table-properties/filter-card.js +854 -0
- package/dist/components/table-properties/filter-card.js.map +1 -0
- package/dist/components/table-properties/index.d.ts +14 -0
- package/dist/components/table-properties/index.js +2768 -0
- package/dist/components/table-properties/index.js.map +1 -0
- package/dist/components/table-properties/sort-card.d.ts +20 -0
- package/dist/components/table-properties/sort-card.js +102 -0
- package/dist/components/table-properties/sort-card.js.map +1 -0
- package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
- package/dist/components/templates/dedicated-search-landing-template.js +254 -0
- package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
- package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
- package/dist/components/templates/dedicated-search-results-template.js +16 -0
- package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
- package/dist/components/templates/index.d.ts +9 -0
- package/dist/components/templates/index.js +2720 -0
- package/dist/components/templates/index.js.map +1 -0
- package/dist/components/templates/list-page.d.ts +83 -0
- package/dist/components/templates/list-page.js +2433 -0
- package/dist/components/templates/list-page.js.map +1 -0
- package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
- package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
- package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +10 -0
- package/dist/components/ui/accordion.js +74 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +37 -0
- package/dist/components/ui/alert-dialog.js +201 -0
- package/dist/components/ui/alert-dialog.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +84 -0
- package/dist/components/ui/avatar.js +328 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +13 -0
- package/dist/components/ui/badge.js +49 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/banner.d.ts +62 -0
- package/dist/components/ui/banner.js +364 -0
- package/dist/components/ui/banner.js.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +14 -0
- package/dist/components/ui/breadcrumb.js +114 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/button.d.ts +16 -0
- package/dist/components/ui/button.js +59 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/calendar.d.ts +13 -0
- package/dist/components/ui/calendar.js +238 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/card.d.ts +14 -0
- package/dist/components/ui/card.js +102 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/chart.d.ts +58 -0
- package/dist/components/ui/chart.js +292 -0
- package/dist/components/ui/chart.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +23 -0
- package/dist/components/ui/checkbox.js +155 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/coach-mark.d.ts +27 -0
- package/dist/components/ui/coach-mark.js +306 -0
- package/dist/components/ui/coach-mark.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +8 -0
- package/dist/components/ui/collapsible.js +35 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/command.d.ts +36 -0
- package/dist/components/ui/command.js +274 -0
- package/dist/components/ui/command.js.map +1 -0
- package/dist/components/ui/context-menu.d.ts +32 -0
- package/dist/components/ui/context-menu.js +245 -0
- package/dist/components/ui/context-menu.js.map +1 -0
- package/dist/components/ui/date-picker-field.d.ts +38 -0
- package/dist/components/ui/date-picker-field.js +550 -0
- package/dist/components/ui/date-picker-field.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +22 -0
- package/dist/components/ui/dialog.js +200 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/dot-pattern.d.ts +21 -0
- package/dist/components/ui/dot-pattern.js +139 -0
- package/dist/components/ui/dot-pattern.js.map +1 -0
- package/dist/components/ui/drag-handle-grip.d.ts +10 -0
- package/dist/components/ui/drag-handle-grip.js +15 -0
- package/dist/components/ui/drag-handle-grip.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +16 -0
- package/dist/components/ui/drawer.js +125 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +45 -0
- package/dist/components/ui/dropdown-menu.js +353 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/export-drawer.d.ts +11 -0
- package/dist/components/ui/export-drawer.js +1658 -0
- package/dist/components/ui/export-drawer.js.map +1 -0
- package/dist/components/ui/field.d.ts +30 -0
- package/dist/components/ui/field.js +249 -0
- package/dist/components/ui/field.js.map +1 -0
- package/dist/components/ui/form.d.ts +28 -0
- package/dist/components/ui/form.js +110 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/hover-card.d.ts +9 -0
- package/dist/components/ui/hover-card.js +43 -0
- package/dist/components/ui/hover-card.js.map +1 -0
- package/dist/components/ui/input-group.d.ts +20 -0
- package/dist/components/ui/input-group.js +219 -0
- package/dist/components/ui/input-group.js.map +1 -0
- package/dist/components/ui/input-mask.d.ts +39 -0
- package/dist/components/ui/input-mask.js +118 -0
- package/dist/components/ui/input-mask.js.map +1 -0
- package/dist/components/ui/input.d.ts +5 -0
- package/dist/components/ui/input.js +30 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/kbd.d.ts +20 -0
- package/dist/components/ui/kbd.js +45 -0
- package/dist/components/ui/kbd.js.map +1 -0
- package/dist/components/ui/key-metrics-context.d.ts +19 -0
- package/dist/components/ui/key-metrics-context.js +26 -0
- package/dist/components/ui/key-metrics-context.js.map +1 -0
- package/dist/components/ui/key-metrics.d.ts +131 -0
- package/dist/components/ui/key-metrics.js +1015 -0
- package/dist/components/ui/key-metrics.js.map +1 -0
- package/dist/components/ui/label.d.ts +6 -0
- package/dist/components/ui/label.js +28 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/list-page-view-frame.d.ts +22 -0
- package/dist/components/ui/list-page-view-frame.js +24 -0
- package/dist/components/ui/list-page-view-frame.js.map +1 -0
- package/dist/components/ui/page-header.d.ts +51 -0
- package/dist/components/ui/page-header.js +372 -0
- package/dist/components/ui/page-header.js.map +1 -0
- package/dist/components/ui/payment-card-fields.d.ts +10 -0
- package/dist/components/ui/payment-card-fields.js +80 -0
- package/dist/components/ui/payment-card-fields.js.map +1 -0
- package/dist/components/ui/popover.d.ts +10 -0
- package/dist/components/ui/popover.js +47 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/radio-group.d.ts +29 -0
- package/dist/components/ui/radio-group.js +190 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/resizable.d.ts +16 -0
- package/dist/components/ui/resizable.js +51 -0
- package/dist/components/ui/resizable.js.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +8 -0
- package/dist/components/ui/scroll-area.js +66 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/select.d.ts +18 -0
- package/dist/components/ui/select.js +186 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/selection-tile-grid.d.ts +52 -0
- package/dist/components/ui/selection-tile-grid.js +347 -0
- package/dist/components/ui/selection-tile-grid.js.map +1 -0
- package/dist/components/ui/separator.d.ts +7 -0
- package/dist/components/ui/separator.js +33 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/sheet.d.ts +18 -0
- package/dist/components/ui/sheet.js +181 -0
- package/dist/components/ui/sheet.js.map +1 -0
- package/dist/components/ui/sidebar.d.ts +94 -0
- package/dist/components/ui/sidebar.js +805 -0
- package/dist/components/ui/sidebar.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +5 -0
- package/dist/components/ui/skeleton.js +22 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/slider.d.ts +7 -0
- package/dist/components/ui/slider.js +66 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +6 -0
- package/dist/components/ui/sonner.js +38 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/status-badge.d.ts +38 -0
- package/dist/components/ui/status-badge.js +77 -0
- package/dist/components/ui/status-badge.js.map +1 -0
- package/dist/components/ui/table.d.ts +13 -0
- package/dist/components/ui/table.js +115 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.d.ts +15 -0
- package/dist/components/ui/tabs.js +93 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +6 -0
- package/dist/components/ui/textarea.js +25 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/tip.d.ts +12 -0
- package/dist/components/ui/tip.js +61 -0
- package/dist/components/ui/tip.js.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +14 -0
- package/dist/components/ui/toggle-group.js +104 -0
- package/dist/components/ui/toggle-group.js.map +1 -0
- package/dist/components/ui/toggle-switch.d.ts +10 -0
- package/dist/components/ui/toggle-switch.js +33 -0
- package/dist/components/ui/toggle-switch.js.map +1 -0
- package/dist/components/ui/toggle.d.ts +13 -0
- package/dist/components/ui/toggle.js +51 -0
- package/dist/components/ui/toggle.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +10 -0
- package/dist/components/ui/tooltip.js +68 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/components/ui/view-segmented-control.d.ts +31 -0
- package/dist/components/ui/view-segmented-control.js +167 -0
- package/dist/components/ui/view-segmented-control.js.map +1 -0
- package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
- package/dist/hooks/use-app-theme.d.ts +24 -0
- package/dist/hooks/use-app-theme.js +286 -0
- package/dist/hooks/use-app-theme.js.map +1 -0
- package/dist/hooks/use-coach-mark.d.ts +86 -0
- package/dist/hooks/use-coach-mark.js +218 -0
- package/dist/hooks/use-coach-mark.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +3 -0
- package/dist/hooks/use-mobile.js +29 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/hooks/use-mod-key-label.d.ts +6 -0
- package/dist/hooks/use-mod-key-label.js +25 -0
- package/dist/hooks/use-mod-key-label.js.map +1 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.js +13421 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/compose-refs.d.ts +6 -0
- package/dist/lib/compose-refs.js +17 -0
- package/dist/lib/compose-refs.js.map +1 -0
- package/dist/lib/conditional-rule-match.d.ts +30 -0
- package/dist/lib/conditional-rule-match.js +66 -0
- package/dist/lib/conditional-rule-match.js.map +1 -0
- package/dist/lib/data-list-display-options.d.ts +26 -0
- package/dist/lib/data-list-display-options.js +14 -0
- package/dist/lib/data-list-display-options.js.map +1 -0
- package/dist/lib/data-list-view-registry.d.ts +2 -0
- package/dist/lib/data-list-view-registry.js +102 -0
- package/dist/lib/data-list-view-registry.js.map +1 -0
- package/dist/lib/data-list-view-surface.d.ts +2 -0
- package/dist/lib/data-list-view-surface.js +80 -0
- package/dist/lib/data-list-view-surface.js.map +1 -0
- package/dist/lib/data-list-view.d.ts +21 -0
- package/dist/lib/data-list-view.js +25 -0
- package/dist/lib/data-list-view.js.map +1 -0
- package/dist/lib/date-filter.d.ts +22 -0
- package/dist/lib/date-filter.js +61 -0
- package/dist/lib/date-filter.js.map +1 -0
- package/dist/lib/dev-log.d.ts +8 -0
- package/dist/lib/dev-log.js +10 -0
- package/dist/lib/dev-log.js.map +1 -0
- package/dist/lib/dropdown-menu-surface.d.ts +14 -0
- package/dist/lib/dropdown-menu-surface.js +6 -0
- package/dist/lib/dropdown-menu-surface.js.map +1 -0
- package/dist/lib/editable-target.d.ts +12 -0
- package/dist/lib/editable-target.js +12 -0
- package/dist/lib/editable-target.js.map +1 -0
- package/dist/lib/list-page-table-properties.d.ts +35 -0
- package/dist/lib/list-page-table-properties.js +81 -0
- package/dist/lib/list-page-table-properties.js.map +1 -0
- package/dist/lib/raf-throttle.d.ts +23 -0
- package/dist/lib/raf-throttle.js +27 -0
- package/dist/lib/raf-throttle.js.map +1 -0
- package/dist/lib/row-height.d.ts +16 -0
- package/dist/lib/row-height.js +10 -0
- package/dist/lib/row-height.js.map +1 -0
- package/dist/lib/table-properties-types.d.ts +83 -0
- package/dist/lib/table-properties-types.js +19 -0
- package/dist/lib/table-properties-types.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +11 -0
- package/dist/lib/utils.js.map +1 -0
- package/package.json +83 -19
- package/src/components/data-table/filter-date-calendar.tsx +38 -0
- package/src/components/data-table/filter-text-value-input.tsx +77 -0
- package/src/components/data-table/index.tsx +1678 -0
- package/src/components/data-table/pagination.tsx +259 -0
- package/src/components/data-table/types.ts +96 -0
- package/src/components/data-table/use-table-state.ts +767 -0
- package/src/components/data-views/board-card-primitives.tsx +93 -0
- package/src/components/data-views/data-row-list.tsx +183 -0
- package/src/components/data-views/finder-panel-view.tsx +405 -0
- package/src/components/data-views/folder-grid-view.tsx +86 -0
- package/src/components/data-views/hub-table.tsx +606 -0
- package/src/components/data-views/index.ts +28 -0
- package/src/components/data-views/list-page-board-card.tsx +192 -0
- package/src/components/data-views/list-page-board-template.tsx +122 -0
- package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
- package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
- package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
- package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
- package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
- package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
- package/src/components/data-views/os-folder-glyph.tsx +141 -0
- package/src/components/data-views/outline-tree-menu.tsx +157 -0
- package/src/components/table-properties/column-row.tsx +90 -0
- package/src/components/table-properties/draggable-list.ts +54 -0
- package/src/components/table-properties/drawer-button.tsx +300 -0
- package/src/components/table-properties/drawer.tsx +1148 -0
- package/src/components/table-properties/filter-card.tsx +251 -0
- package/src/components/table-properties/index.ts +36 -0
- package/src/components/table-properties/sort-card.tsx +63 -0
- package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
- package/src/components/templates/dedicated-search-results-template.tsx +19 -0
- package/src/components/templates/index.ts +33 -0
- package/src/components/templates/list-page.tsx +602 -0
- package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
- package/src/components/ui/accordion.tsx +92 -0
- package/src/components/ui/alert-dialog.tsx +221 -0
- package/src/components/ui/avatar.tsx +13 -2
- package/src/components/ui/banner.tsx +2 -2
- package/src/components/ui/button.tsx +4 -4
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/coach-mark.tsx +1 -1
- package/src/components/ui/context-menu.tsx +291 -0
- package/src/components/ui/date-picker-field.tsx +2 -2
- package/src/components/ui/dot-pattern.tsx +183 -0
- package/src/components/ui/export-drawer.tsx +375 -0
- package/src/components/ui/hover-card.tsx +66 -0
- package/src/components/ui/key-metrics-context.tsx +78 -0
- package/src/components/ui/key-metrics.tsx +1133 -0
- package/src/components/ui/list-page-view-frame.tsx +64 -0
- package/src/components/ui/page-header.tsx +244 -0
- package/src/components/ui/payment-card-fields.tsx +2 -2
- package/src/components/ui/resizable.tsx +68 -0
- package/src/components/ui/scroll-area.tsx +72 -0
- package/src/components/ui/selection-tile-grid.tsx +9 -2
- package/src/components/ui/sidebar.tsx +84 -12
- package/src/components/ui/slider.tsx +83 -0
- package/src/globals.css +2201 -7
- package/src/globals.d.ts +20 -0
- package/src/index.ts +68 -1
- package/src/lib/conditional-rule-match.ts +119 -0
- package/src/lib/data-list-display-options.ts +35 -0
- package/src/lib/data-list-view-registry.ts +104 -0
- package/src/lib/data-list-view-surface.ts +83 -0
- package/src/lib/data-list-view.ts +47 -0
- package/src/lib/dev-log.ts +10 -0
- package/src/lib/editable-target.ts +20 -0
- package/src/lib/list-page-table-properties.ts +48 -0
- package/src/lib/raf-throttle.ts +45 -0
- package/src/lib/row-height.ts +19 -0
- package/src/lib/table-properties-types.ts +98 -0
- package/template/.claude/skills/exxat-ds-skill/SKILL.md +8 -7
- package/template/.cursor/rules/exxat-accessibility.mdc +1 -1
- package/template/.cursor/rules/exxat-command-menu.mdc +2 -2
- package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +7 -7
- package/template/.cursor/rules/exxat-data-tables.mdc +3 -3
- package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
- package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +7 -7
- package/template/.cursor/rules/exxat-mono-ids.mdc +1 -1
- package/template/.cursor/rules/exxat-page-vs-drawer.mdc +1 -1
- package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
- package/template/AGENTS.md +135 -103
- package/template/app/(app)/columns/page.tsx +11 -0
- package/template/app/(app)/dashboard/loading.tsx +15 -3
- package/template/app/(app)/dashboard/page.tsx +14 -2
- package/template/app/(app)/layout.tsx +17 -4
- package/template/app/(app)/library/all/page.tsx +11 -0
- package/template/app/(app)/library/find/page.tsx +12 -0
- package/template/app/(app)/{question-bank → library}/layout.tsx +17 -17
- package/template/app/(app)/library/list/page.tsx +12 -0
- package/template/app/(app)/library/new/page.tsx +45 -0
- package/template/app/(app)/library/page.tsx +11 -0
- package/template/app/(app)/loading.tsx +18 -1
- package/template/app/(app)/settings/page.tsx +5 -4
- package/template/app/(app)/tokens-themes/page.tsx +11 -0
- package/template/app/globals.css +14 -16
- package/template/components/ask-leo-composer.tsx +2 -2
- package/template/components/ask-leo-sidebar.tsx +5 -1
- package/template/components/brand-color-picker.tsx +2 -2
- package/template/components/charts-overview.tsx +1 -1
- package/template/components/columns-client.tsx +158 -0
- package/template/components/columns-showcase.tsx +541 -0
- package/template/components/dashboard-report-charts.tsx +1 -1
- package/template/components/dashboard-tabs.tsx +1 -1
- package/template/components/data-table/filter-date-calendar.tsx +1 -38
- package/template/components/data-table/filter-text-value-input.tsx +1 -77
- package/template/components/data-table/index.tsx +1 -1634
- package/template/components/data-table/pagination.tsx +1 -255
- package/template/components/data-table/types.ts +1 -94
- package/template/components/data-table/use-table-state.test.ts +420 -0
- package/template/components/data-table/use-table-state.ts +1 -758
- package/template/components/data-views/board-card-primitives.tsx +1 -93
- package/template/components/data-views/data-row-list.tsx +1 -183
- package/template/components/data-views/finder-panel-view.tsx +1 -405
- package/template/components/data-views/folder-grid-view.tsx +1 -86
- package/template/components/data-views/hub-table.tsx +1 -0
- package/template/components/data-views/index.ts +77 -38
- package/template/components/data-views/{question-bank-folder-tree-branch.tsx → library-folder-tree-branch.tsx} +19 -19
- package/template/components/data-views/list-page-board-card.tsx +1 -192
- package/template/components/data-views/list-page-board-template.tsx +1 -122
- package/template/components/data-views/list-page-connected-view-body.tsx +1 -66
- package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
- package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -68
- package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
- package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
- package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
- package/template/components/data-views/list-page-view-frame.tsx +5 -53
- package/template/components/data-views/os-folder-glyph.tsx +1 -129
- package/template/components/data-views/outline-tree-menu.tsx +1 -157
- package/template/components/data-views/table-cells.tsx +673 -0
- package/template/components/export-drawer.test.tsx +71 -0
- package/template/components/export-drawer.tsx +1 -375
- package/template/components/exxat-product-logo.tsx +5 -5
- package/template/components/folder-details-shell.tsx +11 -11
- package/template/components/hub-tree-panel-view.tsx +26 -26
- package/template/components/invite-collaborators-drawer.tsx +3 -3
- package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
- package/template/components/key-metrics.tsx +1 -1063
- package/template/components/leo-insight-indicator.tsx +2 -2
- package/template/components/{question-bank-board-view.tsx → library-board-view.tsx} +44 -44
- package/template/components/{question-bank-client.tsx → library-client.tsx} +83 -83
- package/template/components/{question-bank-dashboard-charts.tsx → library-dashboard-charts.tsx} +14 -14
- package/template/components/{question-bank-favorite-button.tsx → library-favorite-button.tsx} +7 -7
- package/template/components/{question-bank-hub-client.tsx → library-hub-client.tsx} +44 -44
- package/template/components/{question-bank-new-folder-sheet.tsx → library-new-folder-sheet.tsx} +16 -16
- package/template/components/{question-bank-os-folder-view.tsx → library-os-folder-view.tsx} +31 -31
- package/template/components/{question-bank-page-header.tsx → library-page-header.tsx} +6 -6
- package/template/components/library-panel-activator.tsx +8 -0
- package/template/components/{question-bank-secondary-nav.tsx → library-secondary-nav.tsx} +63 -63
- package/template/components/library-table.tsx +839 -0
- package/template/components/list-hub-status-badge.tsx +2 -2
- package/template/components/{new-question-composer.tsx → new-library-item-form.tsx} +489 -441
- package/template/components/onboarding/index.ts +9 -0
- package/template/components/onboarding/onboarding-01.tsx +1 -1
- package/template/components/onboarding/onboarding-02.tsx +1 -1
- package/template/components/onboarding/onboarding-03.tsx +1 -1
- package/template/components/onboarding/onboarding-04.tsx +1 -1
- package/template/components/page-header.tsx +8 -226
- package/template/components/product-switcher.tsx +3 -4
- package/template/components/product-wordmark.tsx +2 -1
- package/template/components/settings-appearance-card.tsx +3 -4
- package/template/components/settings-client.tsx +15 -59
- package/template/components/settings-form-row.tsx +4 -9
- package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
- package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +114 -73
- package/template/components/sidebar/index.ts +16 -0
- package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
- package/template/components/sidebar/secondary-panel.tsx +316 -0
- package/template/components/sidebar/sidebar-auto-collapse.tsx +27 -0
- package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +2 -1
- package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
- package/template/components/site-header.tsx +1 -1
- package/template/components/table-properties/column-row.tsx +1 -90
- package/template/components/table-properties/draggable-list.ts +1 -49
- package/template/components/table-properties/drawer-button.tsx +1 -262
- package/template/components/table-properties/drawer.tsx +1 -1166
- package/template/components/table-properties/filter-card.tsx +1 -251
- package/template/components/table-properties/sort-card.tsx +1 -59
- package/template/components/table-properties/types.ts +28 -71
- package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
- package/template/components/templates/dedicated-search-results-template.tsx +1 -19
- package/template/components/templates/discovery-hub-template.tsx +1 -1
- package/template/components/templates/list-page.tsx +1 -608
- package/template/components/templates/nested-secondary-panel-shell.tsx +1 -63
- package/template/components/templates/new-focus-template.tsx +659 -0
- package/template/components/templates/secondary-panel-hub-template.tsx +2 -2
- package/template/components/tokens-secondary-nav.tsx +192 -0
- package/template/components/tokens-themes-client.tsx +476 -0
- package/template/components/tokens-themes-section.tsx +386 -0
- package/template/components/ui/accordion.tsx +1 -0
- package/template/components/ui/alert-dialog.tsx +1 -0
- package/template/components/ui/context-menu.tsx +1 -0
- package/template/components/ui/dot-pattern.tsx +1 -183
- package/template/components/ui/hover-card.tsx +1 -0
- package/template/components/ui/resizable.tsx +1 -68
- package/template/components/ui/scroll-area.tsx +1 -0
- package/template/components/ui/slider.tsx +1 -0
- package/template/docs/HANDBOOK.md +187 -0
- package/template/docs/blueprints/README.md +86 -0
- package/template/docs/blueprints/_template.md +91 -0
- package/template/docs/blueprints/board-card.md +123 -0
- package/template/docs/blueprints/data-table.md +139 -0
- package/template/docs/blueprints/key-metrics.md +128 -0
- package/template/docs/blueprints/list-page-template.md +123 -0
- package/template/docs/blueprints/page-header.md +130 -0
- package/template/docs/collaboration-access-pattern.md +7 -7
- package/template/docs/command-menu-pattern.md +1 -1
- package/template/docs/component-selection-guide.md +224 -0
- package/template/docs/components-audit-2026-05.md +158 -0
- package/template/docs/data-views-pattern.md +31 -66
- package/template/docs/drawer-vs-dialog-pattern.md +1 -3
- package/template/docs/glossary.md +58 -0
- package/template/docs/kpi-flat-band-pattern.md +3 -3
- package/template/docs/kpi-trend-pattern.md +18 -3
- package/template/docs/large-dataset-strategy.md +155 -0
- package/template/docs/library-hub-header-pattern.md +25 -0
- package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
- package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
- package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
- package/template/docs/migrations/README.md +100 -0
- package/template/docs/migrations/_template.md +64 -0
- package/template/docs/reference-implementations.md +151 -0
- package/template/docs/shell-surface-elevation-pattern.md +3 -5
- package/template/docs/token-taxonomy.md +416 -0
- package/template/docs/voice-and-tone.md +262 -0
- package/template/eslint.config.mjs +27 -0
- package/template/hooks/use-secondary-panel-hub-nav.ts +11 -11
- package/template/lib/ask-leo-route-context.ts +6 -18
- package/template/lib/coach-mark-registry.ts +0 -16
- package/template/lib/command-menu-config.ts +5 -13
- package/template/lib/command-menu-search-data.ts +8 -23
- package/template/lib/conditional-rule-match.ts +6 -97
- package/template/lib/data-list-display-options.ts +1 -49
- package/template/lib/data-list-view-registry.ts +1 -104
- package/template/lib/data-list-view-surface.ts +1 -83
- package/template/lib/data-list-view.ts +1 -47
- package/template/lib/data-view-dashboard-storage.ts +35 -38
- package/template/lib/dev-log.ts +1 -8
- package/template/lib/editable-target.ts +1 -10
- package/template/lib/{question-bank-authoring.ts → library-authoring.ts} +89 -88
- package/template/lib/library-dedicated-search.ts +19 -0
- package/template/lib/library-hub-search.ts +90 -0
- package/template/lib/library-nav.ts +477 -0
- package/template/lib/library-recent-searches.ts +22 -0
- package/template/lib/{question-bank-supported-views.ts → library-supported-views.ts} +2 -3
- package/template/lib/list-page-table-properties.ts +1 -48
- package/template/lib/list-status-badges.ts +16 -11
- package/template/lib/mock/dashboard.ts +1 -1
- package/template/lib/mock/{question-bank-folders.ts → library-folders.ts} +30 -30
- package/template/lib/mock/library-header-collaborators.ts +54 -0
- package/template/lib/mock/{question-bank-inspector.ts → library-inspector.ts} +29 -29
- package/template/lib/mock/{question-bank-kpi.ts → library-kpi.ts} +20 -20
- package/template/lib/mock/library.ts +249 -0
- package/template/lib/mock/navigation.tsx +32 -35
- package/template/lib/raf-throttle.ts +1 -45
- package/template/lib/row-height.ts +4 -10
- package/template/lib/sidebar-state-cookie.ts +11 -2
- package/template/lib/table-state-lifecycle.ts +3 -3
- package/template/next.config.mjs +7 -4
- package/template/package.json +1 -0
- package/template/tests/setup.ts +25 -0
- package/consumer-extras/AGENTS.md +0 -76
- package/consumer-extras/cursor-skills/exxat-consumer-app/SKILL.md +0 -37
- package/consumer-extras/cursor-skills/exxat-focused-workflow-page/SKILL.md +0 -57
- package/consumer-extras/patterns/consumer-app-pattern.md +0 -39
- package/consumer-extras/patterns/focused-workflow-page-pattern.md +0 -84
- package/src/components/ui/button-group.tsx +0 -81
- package/src/theme.css +0 -16
- package/src/tokens/README.md +0 -15
- package/src/tokens/base.css +0 -337
- package/src/tokens/high-contrast.css +0 -1195
- package/src/tokens/layers.css +0 -224
- package/src/tokens/tailwind-bridge.css +0 -118
- package/src/tokens/themes.css +0 -201
- package/template/app/(app)/data-list/layout.tsx +0 -43
- package/template/app/(app)/data-list/page.tsx +0 -10
- package/template/app/(app)/examples/focused-workflow/page.tsx +0 -5
- package/template/app/(app)/examples/page.tsx +0 -43
- package/template/app/(app)/question-bank/find/page.tsx +0 -13
- package/template/app/(app)/question-bank/library/page.tsx +0 -12
- package/template/app/(app)/question-bank/list/page.tsx +0 -13
- package/template/app/(app)/question-bank/new/page.tsx +0 -50
- package/template/app/(app)/question-bank/page.tsx +0 -12
- package/template/components/app-route-loading.tsx +0 -14
- package/template/components/dashboard-onboarding-gallery.tsx +0 -13
- package/template/components/dashboard-onboarding.tsx +0 -21
- package/template/components/data-views/list-page-calendar-view.tsx +0 -593
- package/template/components/data-views/list-page-folder-columns-panel.tsx +0 -345
- package/template/components/examples/focused-workflow-showcase.tsx +0 -183
- package/template/components/list-hub-board-view.tsx +0 -68
- package/template/components/list-hub-client.tsx +0 -186
- package/template/components/list-hub-list-view.tsx +0 -36
- package/template/components/list-hub-panel-activator.tsx +0 -8
- package/template/components/list-hub-secondary-nav.tsx +0 -121
- package/template/components/list-hub-table.tsx +0 -336
- package/template/components/question-bank-folder-columns-panel.tsx +0 -104
- package/template/components/question-bank-list-view.tsx +0 -53
- package/template/components/question-bank-panel-activator.tsx +0 -8
- package/template/components/question-bank-table.tsx +0 -729
- package/template/components/secondary-panel/nav-link-rows.tsx +0 -83
- package/template/components/secondary-panel.tsx +0 -220
- package/template/components/secondary-panels/list-hub-panel.tsx +0 -39
- package/template/components/secondary-panels/question-bank-panel.tsx +0 -39
- package/template/components/secondary-panels/registry.tsx +0 -15
- package/template/components/section-cards.tsx +0 -106
- package/template/components/sidebar-auto-collapse.tsx +0 -23
- package/template/components/templates/focused-workflow-layouts.tsx +0 -448
- package/template/components/templates/focused-workflow-page-template.tsx +0 -69
- package/template/components/templates/page-loading-shell.tsx +0 -262
- package/template/components/ui/button-group.tsx +0 -1
- package/template/docs/consumer-app-pattern.md +0 -39
- package/template/docs/focused-workflow-page-pattern.md +0 -84
- package/template/docs/question-bank-hub-header-pattern.md +0 -25
- package/template/lib/list-hub-nav.ts +0 -121
- package/template/lib/mock/list-hub-directory.ts +0 -27
- package/template/lib/mock/list-hub-kpi.ts +0 -27
- package/template/lib/mock/question-bank-header-collaborators.ts +0 -54
- package/template/lib/mock/question-bank.ts +0 -249
- package/template/lib/page-loading-variant.ts +0 -40
- package/template/lib/question-bank-dedicated-search.ts +0 -19
- package/template/lib/question-bank-hub-search.ts +0 -90
- package/template/lib/question-bank-nav.ts +0 -477
- package/template/lib/question-bank-recent-searches.ts +0 -22
- /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
- /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
- /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
- /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
- /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
|
@@ -67,8 +67,8 @@ import { useModKeyLabel } from "@/hooks/use-mod-key-label"
|
|
|
67
67
|
import { useLocationHash } from "@/hooks/use-location-hash"
|
|
68
68
|
import { useSidebarReflowZoom } from "@/hooks/use-sidebar-reflow-zoom"
|
|
69
69
|
import { useProduct, type Product } from "@/contexts/product-context"
|
|
70
|
-
import { NavUser } from "
|
|
71
|
-
import { useSecondaryPanel } from "
|
|
70
|
+
import { NavUser } from "./nav-user"
|
|
71
|
+
import { useSecondaryPanel } from "./secondary-panel"
|
|
72
72
|
import { ExxatProductLogo, ExxatProductMark } from "@/components/exxat-product-logo"
|
|
73
73
|
import { motionHeaderEnter } from "@/lib/motion-ui"
|
|
74
74
|
import { customProductBrandConfig, productBrandLabel } from "@/lib/product-brand"
|
|
@@ -106,21 +106,57 @@ function normalizedLocationHash(locationHash: string): string {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
109
|
+
* Path → set of hash fragments claimed by *another* nav item at the same path.
|
|
110
|
+
*
|
|
111
|
+
* Why: several rows deliberately share a route and disambiguate via `#fragment`.
|
|
112
|
+
* Example: `Tokens & themes → /settings#appearance` and `Settings → /settings`
|
|
113
|
+
* both render under the same page. Without a registry, when the user is on
|
|
114
|
+
* `/settings#appearance` the no-fragment "Settings" row matches by path-equality
|
|
115
|
+
* (line below: `pathname === pathOnly`) and lights up too — so *both* rows
|
|
116
|
+
* appear active.
|
|
117
|
+
*
|
|
118
|
+
* The registry is computed once from the static nav config and consulted by
|
|
119
|
+
* `isNavActive` to make the no-fragment item defer when a hash-bearing sibling
|
|
120
|
+
* claims the current `location.hash`.
|
|
112
121
|
*/
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
122
|
+
const NAV_HASH_CLAIMS: ReadonlyMap<string, ReadonlySet<string>> = (() => {
|
|
123
|
+
const map = new Map<string, Set<string>>()
|
|
124
|
+
const record = (url: string) => {
|
|
125
|
+
const p = navUrlPath(url)
|
|
126
|
+
const f = navUrlFragment(url)
|
|
127
|
+
if (!p || f === null) return
|
|
128
|
+
let set = map.get(p)
|
|
129
|
+
if (!set) { set = new Set<string>(); map.set(p, set) }
|
|
130
|
+
set.add(f)
|
|
131
|
+
}
|
|
132
|
+
const walk = (items: ReadonlyArray<{ url?: string; children?: ReadonlyArray<{ url?: string; children?: unknown }> }>) => {
|
|
133
|
+
for (const it of items) {
|
|
134
|
+
if (typeof it.url === "string") record(it.url)
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
136
|
+
if (Array.isArray((it as any).children)) walk((it as any).children)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
walk(NAV_PRIMARY)
|
|
140
|
+
walk(NAV_DOCUMENTS)
|
|
141
|
+
walk(NAV_QUICK_ACTIONS)
|
|
142
|
+
walk(NAV_SECONDARY)
|
|
143
|
+
return map
|
|
144
|
+
})()
|
|
145
|
+
|
|
146
|
+
/** True when another nav item at the same path claims the current location hash. */
|
|
147
|
+
function navHasMoreSpecificMatch(pathname: string, locationHash: string): boolean {
|
|
148
|
+
const claims = NAV_HASH_CLAIMS.get(pathname)
|
|
149
|
+
if (!claims) return false
|
|
150
|
+
const h = normalizedLocationHash(locationHash)
|
|
151
|
+
if (h === "") return false
|
|
152
|
+
return claims.has(h)
|
|
116
153
|
}
|
|
117
154
|
|
|
118
155
|
/**
|
|
119
156
|
* Whether `pathname` (+ optional `location.hash`) matches a sidebar `href`.
|
|
120
157
|
* When several links share the same path (e.g. `/settings`), disambiguate with `#fragment`
|
|
121
158
|
* in each `href` — those rows use the `frag !== null` branch below.
|
|
122
|
-
* For `href` without `#…`, an in-page hash (e.g. QB view tabs) does not clear the match
|
|
123
|
-
* except when the hash is reserved for a hash-sibling row on that path.
|
|
159
|
+
* For `href` without `#…`, an in-page hash (e.g. QB view tabs) does not clear the match.
|
|
124
160
|
*/
|
|
125
161
|
function isNavActive(pathname: string, url: string, locationHash = ""): boolean {
|
|
126
162
|
const pathOnly = navUrlPath(url)
|
|
@@ -140,15 +176,18 @@ function isNavActive(pathname: string, url: string, locationHash = ""): boolean
|
|
|
140
176
|
return pathname === pathOnly && h === frag
|
|
141
177
|
}
|
|
142
178
|
|
|
143
|
-
if (pathOnly === "/")
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (h !== "") {
|
|
147
|
-
const exclusive = NAV_EXCLUSIVE_HASH_BY_PATH[pathOnly]
|
|
148
|
-
if (exclusive?.includes(h)) return false
|
|
149
|
-
}
|
|
150
|
-
return true
|
|
179
|
+
if (pathOnly === "/") {
|
|
180
|
+
if (pathname !== "/" || h !== "") return false
|
|
181
|
+
return !navHasMoreSpecificMatch(pathname, locationHash)
|
|
151
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Exact path match — ignore `location.hash` when the nav `href` has no `#…` fragment (QB view tabs use hash).
|
|
185
|
+
* EXCEPTION: when another nav item at the same path claims the current hash
|
|
186
|
+
* (e.g. `Tokens & themes → /settings#appearance` while we're evaluating
|
|
187
|
+
* `Settings → /settings`), defer to that more-specific row — otherwise both
|
|
188
|
+
* would light up. See `NAV_HASH_CLAIMS`.
|
|
189
|
+
*/
|
|
190
|
+
if (pathname === pathOnly) return !navHasMoreSpecificMatch(pathname, locationHash)
|
|
152
191
|
// Design system library — active on hub and detail routes.
|
|
153
192
|
if (pathOnly === "/library") {
|
|
154
193
|
return pathname.startsWith("/library/")
|
|
@@ -184,7 +223,7 @@ function isCollapsibleChildActive(
|
|
|
184
223
|
|
|
185
224
|
if (!isNavActive(pathname, child.url, locationHash)) return false
|
|
186
225
|
|
|
187
|
-
/** Hub entry (`/
|
|
226
|
+
/** Hub entry (`/library`) must not stay “active” on `/library/all` etc. */
|
|
188
227
|
if (parent.primaryHubChildKey && child.key === parent.primaryHubChildKey) {
|
|
189
228
|
const hubPath = navUrlPath(parent.url)
|
|
190
229
|
if (hubPath) {
|
|
@@ -315,7 +354,7 @@ function CollapsibleNavItem({ item, pathname }: { item: NavLinkItem; pathname: s
|
|
|
315
354
|
const iconRailCollapsed = state === "collapsed" && !isMobile
|
|
316
355
|
// In the icon rail the parent icon is the ONLY visible thing for this item
|
|
317
356
|
// (no sub-list, no labels) — so it must reflect "I'm somewhere inside this
|
|
318
|
-
// section" by lighting up on any descendant route (e.g. `/
|
|
357
|
+
// section" by lighting up on any descendant route (e.g. `/library/all`),
|
|
319
358
|
// not only on the parent URL itself. In the expanded view we keep the
|
|
320
359
|
// parent neutral and let the active child row carry `data-active` (see
|
|
321
360
|
// `isCollapsibleParentMenuButtonActive`).
|
|
@@ -440,7 +479,7 @@ function CollapsibleNavItem({ item, pathname }: { item: NavLinkItem; pathname: s
|
|
|
440
479
|
</span>
|
|
441
480
|
<span>{item.title}</span>
|
|
442
481
|
<i
|
|
443
|
-
className="fa-light fa-chevron-right
|
|
482
|
+
className="fa-light fa-chevron-right ms-auto text-xs text-current transition-transform duration-200 ease-out group-data-[state=open]/collapsible:rotate-90 motion-reduce:transition-none"
|
|
444
483
|
aria-hidden="true"
|
|
445
484
|
/>
|
|
446
485
|
</SidebarMenuButton>
|
|
@@ -844,58 +883,60 @@ function ProductLogoButton() {
|
|
|
844
883
|
|
|
845
884
|
return (
|
|
846
885
|
<DropdownMenu>
|
|
847
|
-
<
|
|
848
|
-
<
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
886
|
+
<Tooltip>
|
|
887
|
+
<TooltipTrigger asChild>
|
|
888
|
+
<DropdownMenuTrigger asChild>
|
|
889
|
+
<SidebarMenuButton
|
|
890
|
+
size="lg"
|
|
891
|
+
className={cn(
|
|
892
|
+
"py-2 text-sidebar-foreground data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
|
|
893
|
+
expandedOrMobile &&
|
|
894
|
+
"h-auto min-h-12 !overflow-visible items-center [&>span:last-child]:!overflow-visible [&>span:last-child]:!whitespace-normal [&>span:last-child]:text-clip",
|
|
895
|
+
"group-data-[collapsible=icon]:items-center group-data-[collapsible=icon]:justify-center",
|
|
896
|
+
iconRail &&
|
|
897
|
+
"group-data-[collapsible=icon]:!size-9 group-data-[collapsible=icon]:!min-h-9 group-data-[collapsible=icon]:!max-h-9 group-data-[collapsible=icon]:!p-0 group-data-[collapsible=icon]:overflow-visible",
|
|
898
|
+
)}
|
|
899
|
+
aria-label={`Current product: ${current.label}. Switch product`}
|
|
900
|
+
suppressHydrationWarning
|
|
901
|
+
>
|
|
902
|
+
{iconRail ? (
|
|
903
|
+
// Match the school selector footprint in the icon rail (32px frame,
|
|
904
|
+
// 28px mark — same visual weight as the avatar with inset padding).
|
|
905
|
+
<span className="flex size-8 shrink-0 items-center justify-center">
|
|
906
|
+
<ExxatProductMark product={current.id} className="size-7" />
|
|
907
|
+
</span>
|
|
908
|
+
) : (
|
|
909
|
+
<span className="flex min-h-0 min-w-0 flex-1 items-stretch gap-2">
|
|
910
|
+
<span
|
|
911
|
+
className="flex min-h-0 min-w-0 flex-1 items-center justify-start overflow-visible"
|
|
912
|
+
aria-hidden="true"
|
|
913
|
+
>
|
|
914
|
+
<ExxatProductLogo
|
|
915
|
+
product={current.id}
|
|
916
|
+
variant="mutedSuffix"
|
|
917
|
+
className="w-auto max-w-[min(100%,280px)] object-left object-contain"
|
|
918
|
+
/>
|
|
919
|
+
</span>
|
|
920
|
+
<span
|
|
921
|
+
className="flex w-6 shrink-0 items-center justify-center self-stretch text-muted-foreground"
|
|
922
|
+
aria-hidden="true"
|
|
923
|
+
>
|
|
924
|
+
<i
|
|
925
|
+
className="fa-light fa-chevron-down block text-xs leading-none"
|
|
926
|
+
aria-hidden="true"
|
|
927
|
+
/>
|
|
928
|
+
</span>
|
|
929
|
+
</span>
|
|
930
|
+
)}
|
|
931
|
+
</SidebarMenuButton>
|
|
932
|
+
</DropdownMenuTrigger>
|
|
933
|
+
</TooltipTrigger>
|
|
934
|
+
<TooltipContent side="right" align="center" hidden={state !== "collapsed" || isMobile}>
|
|
935
|
+
{current.label}
|
|
936
|
+
</TooltipContent>
|
|
937
|
+
</Tooltip>
|
|
893
938
|
|
|
894
|
-
<DropdownMenuContent
|
|
895
|
-
align="start"
|
|
896
|
-
side={iconRail ? "right" : "bottom"}
|
|
897
|
-
sideOffset={iconRail ? 8 : 4}
|
|
898
|
-
>
|
|
939
|
+
<DropdownMenuContent align="start" side="right" sideOffset={8}>
|
|
899
940
|
<DropdownMenuLabel className="text-xs text-muted-foreground">
|
|
900
941
|
Switch product
|
|
901
942
|
</DropdownMenuLabel>
|
|
@@ -913,7 +954,7 @@ function ProductLogoButton() {
|
|
|
913
954
|
className="w-auto shrink-0 max-w-[min(100%,260px)]"
|
|
914
955
|
/>
|
|
915
956
|
{p.id === product && (
|
|
916
|
-
<i className="fa-solid fa-check
|
|
957
|
+
<i className="fa-solid fa-check ms-auto text-brand text-xs" aria-hidden="true" />
|
|
917
958
|
)}
|
|
918
959
|
</DropdownMenuItem>
|
|
919
960
|
))}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Barrel re-export for the sidebar shell.
|
|
2
|
+
// Consumers SHOULD import via `@/components/sidebar`; per-file paths still
|
|
3
|
+
// work as escape hatch (e.g. `@/components/sidebar/secondary-panel`).
|
|
4
|
+
//
|
|
5
|
+
// See apps/web/docs/components-audit-2026-05.md §2.3.
|
|
6
|
+
export * from "./app-sidebar"
|
|
7
|
+
export * from "./app-sidebar-dynamic"
|
|
8
|
+
export * from "./sidebar-shell"
|
|
9
|
+
export * from "./sidebar-auto-collapse"
|
|
10
|
+
export * from "./sidebar-auto-open"
|
|
11
|
+
export * from "./nav-main"
|
|
12
|
+
export * from "./nav-secondary"
|
|
13
|
+
export * from "./nav-documents"
|
|
14
|
+
export * from "./nav-user"
|
|
15
|
+
export * from "./secondary-nav"
|
|
16
|
+
export * from "./secondary-panel"
|
|
@@ -293,7 +293,7 @@ export function SecondaryNavPanel({
|
|
|
293
293
|
title={section.action.label}
|
|
294
294
|
onClick={section.action.onClick}
|
|
295
295
|
className={cn(
|
|
296
|
-
"inline-flex size-6 items-center justify-center rounded-md -
|
|
296
|
+
"inline-flex size-6 items-center justify-center rounded-md -me-1",
|
|
297
297
|
"text-muted-foreground hover:text-interactive-hover-foreground hover:bg-interactive-hover-strong",
|
|
298
298
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
299
299
|
)}
|
|
@@ -318,7 +318,7 @@ export function SecondaryNavPanel({
|
|
|
318
318
|
placeholder={section.searchPlaceholder ?? "Search"}
|
|
319
319
|
aria-label={`Search ${section.label}`}
|
|
320
320
|
className={cn(
|
|
321
|
-
"w-full h-7
|
|
321
|
+
"w-full h-7 ps-7 pe-2 rounded-md text-xs bg-background border border-border",
|
|
322
322
|
"placeholder:text-muted-foreground/70",
|
|
323
323
|
"focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent"
|
|
324
324
|
)}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SecondaryPanel — nested rail between the primary icon sidebar and content.
|
|
5
|
+
* Full width shows hub scope nav; **compact** matches the primary sidebar icon rail (`w-12`).
|
|
6
|
+
*
|
|
7
|
+
* Chrome uses {@link NestedSecondaryPanelShell}. Library body stays in
|
|
8
|
+
* `library-secondary-nav.tsx` (domain-specific), not duplicated here.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as React from "react"
|
|
12
|
+
import { useSidebar } from "@/components/ui/sidebar"
|
|
13
|
+
import { Tip } from "@/components/ui/tip"
|
|
14
|
+
import { Button } from "@/components/ui/button"
|
|
15
|
+
import { LibrarySecondaryNav } from "@/components/library-secondary-nav"
|
|
16
|
+
import { TokensSecondaryNav } from "@/components/tokens-secondary-nav"
|
|
17
|
+
import { NestedSecondaryPanelShell } from "@/components/templates/nested-secondary-panel-shell"
|
|
18
|
+
import { useSidebarReflowZoom } from "@/hooks/use-sidebar-reflow-zoom"
|
|
19
|
+
import type { LibraryItem } from "@/lib/mock/library"
|
|
20
|
+
import type { LibraryFolder } from "@/lib/mock/library-folders"
|
|
21
|
+
|
|
22
|
+
export type LibraryFolderBridge = {
|
|
23
|
+
folders: LibraryFolder[]
|
|
24
|
+
onFoldersChange: React.Dispatch<React.SetStateAction<LibraryFolder[]>>
|
|
25
|
+
items: LibraryItem[]
|
|
26
|
+
onItemsChange: React.Dispatch<React.SetStateAction<LibraryItem[]>>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type LibraryAccessBridge = {
|
|
30
|
+
openManageAccess: () => void
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
34
|
+
// Context
|
|
35
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
export type ClosePanelOptions = {
|
|
38
|
+
/**
|
|
39
|
+
* Main app sidebar after the secondary panel closes.
|
|
40
|
+
* - `restore` (default): snap back to the user's saved preference
|
|
41
|
+
* (`sidebar_state_v2` cookie, or `defaultOpen` if unset). Use this when
|
|
42
|
+
* leaving a page whose secondary panel caused an incidental collapse — the
|
|
43
|
+
* rail returns to the state the user explicitly set elsewhere via ⌘B / the
|
|
44
|
+
* sidebar button.
|
|
45
|
+
* - `leave`: only clear the active panel — keep the rail in whatever state it
|
|
46
|
+
* was in (rare; prefer `restore`).
|
|
47
|
+
* - `expand`: force the full primary rail open. Use only when the product
|
|
48
|
+
* explicitly wants the wide rail after dismiss.
|
|
49
|
+
* - `collapse`: keep the icon rail. Use when the next route also wants compact.
|
|
50
|
+
*/
|
|
51
|
+
mainSidebar?: "restore" | "expand" | "collapse" | "leave"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface SecondaryPanelContextValue {
|
|
55
|
+
/** Currently active panel id, or null if none */
|
|
56
|
+
activePanel: string | null
|
|
57
|
+
/** Open a panel by id (always exits compact / full-width). */
|
|
58
|
+
openPanel: (id: string) => void
|
|
59
|
+
/** Close the panel (programmatic / route cleanup). */
|
|
60
|
+
closePanel: (opts?: ClosePanelOptions) => void
|
|
61
|
+
/** Icon-only nested rail while the panel stays “open”. Cleared by {@link openPanel} / {@link closePanel}. */
|
|
62
|
+
secondaryPanelCompact: boolean
|
|
63
|
+
/** Narrow icon rail (primary-sidebar-style); keeps {@link activePanel} mounted. */
|
|
64
|
+
collapseActiveSecondaryPanel: () => void
|
|
65
|
+
/** Library folder tree shared with the secondary nav while the hub is mounted. */
|
|
66
|
+
libraryFolderBridge: LibraryFolderBridge | null
|
|
67
|
+
setLibraryFolderBridge: (bridge: LibraryFolderBridge | null) => void
|
|
68
|
+
/** Opens the hub collaborators sheet from the secondary nav. */
|
|
69
|
+
libraryAccessBridge: LibraryAccessBridge | null
|
|
70
|
+
setLibraryAccessBridge: (bridge: LibraryAccessBridge | null) => void
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const SecondaryPanelContext = React.createContext<SecondaryPanelContextValue>({
|
|
74
|
+
activePanel: null,
|
|
75
|
+
openPanel: () => {},
|
|
76
|
+
closePanel: () => {},
|
|
77
|
+
secondaryPanelCompact: false,
|
|
78
|
+
collapseActiveSecondaryPanel: () => {},
|
|
79
|
+
libraryFolderBridge: null,
|
|
80
|
+
setLibraryFolderBridge: () => {},
|
|
81
|
+
libraryAccessBridge: null,
|
|
82
|
+
setLibraryAccessBridge: () => {},
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
export function useSecondaryPanel() {
|
|
86
|
+
return React.useContext(SecondaryPanelContext)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function SecondaryPanelProvider({ children }: { children: React.ReactNode }) {
|
|
90
|
+
const [activePanel, setActivePanel] = React.useState<string | null>(null)
|
|
91
|
+
const [secondaryPanelCompact, setSecondaryPanelCompact] = React.useState(false)
|
|
92
|
+
const [libraryFolderBridge, setLibraryFolderBridge] =
|
|
93
|
+
React.useState<LibraryFolderBridge | null>(null)
|
|
94
|
+
const [libraryAccessBridge, setLibraryAccessBridge] =
|
|
95
|
+
React.useState<LibraryAccessBridge | null>(null)
|
|
96
|
+
const { setOpen, restoreSavedOpen } = useSidebar()
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Browser zoom ≥ 200% (or very short viewport) — same `useSidebarReflowZoom`
|
|
100
|
+
* signal the primary sidebar uses (WCAG 1.4.10). At that scale the 16rem
|
|
101
|
+
* secondary rail crowds out primary content, so we **auto-collapse it to
|
|
102
|
+
* the icon variant on entering high zoom**. We don't keep overriding —
|
|
103
|
+
* users can re-expand once collapsed; the next zoom-out → zoom-in cycle
|
|
104
|
+
* re-collapses. This matches the pattern users get from clicking the
|
|
105
|
+
* panel's own "Collapse to icons" button.
|
|
106
|
+
*/
|
|
107
|
+
const reflowZoom = useSidebarReflowZoom()
|
|
108
|
+
const wasReflowZoomRef = React.useRef(false)
|
|
109
|
+
React.useEffect(() => {
|
|
110
|
+
if (reflowZoom && !wasReflowZoomRef.current) {
|
|
111
|
+
setSecondaryPanelCompact(true)
|
|
112
|
+
}
|
|
113
|
+
wasReflowZoomRef.current = reflowZoom
|
|
114
|
+
}, [reflowZoom])
|
|
115
|
+
|
|
116
|
+
const openPanel = React.useCallback(
|
|
117
|
+
(id: string) => {
|
|
118
|
+
// High zoom → keep the icon rail (auto-collapse rule above). At normal
|
|
119
|
+
// zoom this stays the legacy behavior (full-width on open).
|
|
120
|
+
setSecondaryPanelCompact(reflowZoom)
|
|
121
|
+
setActivePanel(id)
|
|
122
|
+
// `persist: false` — collapsing the rail to make room for the secondary
|
|
123
|
+
// panel is an incidental layout side-effect; the user's saved
|
|
124
|
+
// expanded/collapsed preference (cookie) must not be overwritten by it.
|
|
125
|
+
setOpen(false, { persist: false }) // collapse main sidebar to icon rail
|
|
126
|
+
},
|
|
127
|
+
[setOpen, reflowZoom],
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
const closePanel = React.useCallback((opts?: ClosePanelOptions) => {
|
|
131
|
+
setSecondaryPanelCompact(false)
|
|
132
|
+
setActivePanel(null)
|
|
133
|
+
/**
|
|
134
|
+
* Default = `restore`. `openPanel` collapsed the rail with `persist: false`
|
|
135
|
+
* (the saved cookie is untouched), so on close we ask the sidebar context
|
|
136
|
+
* to re-apply whatever the user truly saved. This makes the visual collapse
|
|
137
|
+
* scoped to the page that needed it — leave the page → rail comes back to
|
|
138
|
+
* the user's preference.
|
|
139
|
+
*/
|
|
140
|
+
const mainSidebar = opts?.mainSidebar ?? "restore"
|
|
141
|
+
if (mainSidebar === "leave") return
|
|
142
|
+
if (mainSidebar === "restore") {
|
|
143
|
+
restoreSavedOpen()
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
if (mainSidebar === "collapse") {
|
|
147
|
+
setOpen(false, { persist: false })
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
setOpen(true, { persist: false }) // mainSidebar === "expand"
|
|
151
|
+
}, [restoreSavedOpen, setOpen])
|
|
152
|
+
|
|
153
|
+
const collapseActiveSecondaryPanel = React.useCallback(() => {
|
|
154
|
+
setSecondaryPanelCompact(true)
|
|
155
|
+
}, [])
|
|
156
|
+
|
|
157
|
+
const value = React.useMemo(
|
|
158
|
+
() => ({
|
|
159
|
+
activePanel,
|
|
160
|
+
openPanel,
|
|
161
|
+
closePanel,
|
|
162
|
+
secondaryPanelCompact,
|
|
163
|
+
collapseActiveSecondaryPanel,
|
|
164
|
+
libraryFolderBridge,
|
|
165
|
+
setLibraryFolderBridge,
|
|
166
|
+
libraryAccessBridge,
|
|
167
|
+
setLibraryAccessBridge,
|
|
168
|
+
}),
|
|
169
|
+
[
|
|
170
|
+
activePanel,
|
|
171
|
+
openPanel,
|
|
172
|
+
closePanel,
|
|
173
|
+
secondaryPanelCompact,
|
|
174
|
+
collapseActiveSecondaryPanel,
|
|
175
|
+
libraryFolderBridge,
|
|
176
|
+
libraryAccessBridge,
|
|
177
|
+
],
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<SecondaryPanelContext.Provider value={value}>
|
|
182
|
+
{children}
|
|
183
|
+
</SecondaryPanelContext.Provider>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
188
|
+
// SecondaryPanel — the actual rendered panel
|
|
189
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
function LibraryPanel() {
|
|
192
|
+
const { collapseActiveSecondaryPanel, secondaryPanelCompact } = useSecondaryPanel()
|
|
193
|
+
|
|
194
|
+
if (secondaryPanelCompact) {
|
|
195
|
+
return <LibrarySecondaryNav />
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<>
|
|
200
|
+
<div className="flex items-center justify-between gap-2 px-4 pt-4 pb-2">
|
|
201
|
+
<h2
|
|
202
|
+
className="text-xl font-semibold leading-tight text-sidebar-foreground"
|
|
203
|
+
style={{ fontFamily: "var(--font-heading)" }}
|
|
204
|
+
>
|
|
205
|
+
Library
|
|
206
|
+
</h2>
|
|
207
|
+
<Tip label="Collapse to icons" side="bottom">
|
|
208
|
+
<Button
|
|
209
|
+
type="button"
|
|
210
|
+
size="icon"
|
|
211
|
+
variant="ghost"
|
|
212
|
+
onClick={() => collapseActiveSecondaryPanel()}
|
|
213
|
+
aria-label="Collapse to icons"
|
|
214
|
+
>
|
|
215
|
+
<i className="fa-light fa-angles-left" aria-hidden="true" />
|
|
216
|
+
</Button>
|
|
217
|
+
</Tip>
|
|
218
|
+
</div>
|
|
219
|
+
<LibrarySecondaryNav />
|
|
220
|
+
</>
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function TokensPanel() {
|
|
225
|
+
const { collapseActiveSecondaryPanel, secondaryPanelCompact } = useSecondaryPanel()
|
|
226
|
+
|
|
227
|
+
if (secondaryPanelCompact) {
|
|
228
|
+
return <TokensSecondaryNav />
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<>
|
|
233
|
+
<div className="flex items-center justify-between gap-2 px-4 pt-4 pb-2">
|
|
234
|
+
<h2
|
|
235
|
+
className="text-xl font-semibold leading-tight text-sidebar-foreground"
|
|
236
|
+
style={{ fontFamily: "var(--font-heading)" }}
|
|
237
|
+
>
|
|
238
|
+
Tokens
|
|
239
|
+
</h2>
|
|
240
|
+
<Tip label="Collapse to icons" side="bottom">
|
|
241
|
+
<Button
|
|
242
|
+
type="button"
|
|
243
|
+
size="icon"
|
|
244
|
+
variant="ghost"
|
|
245
|
+
onClick={() => collapseActiveSecondaryPanel()}
|
|
246
|
+
aria-label="Collapse to icons"
|
|
247
|
+
>
|
|
248
|
+
<i className="fa-light fa-angles-left" aria-hidden="true" />
|
|
249
|
+
</Button>
|
|
250
|
+
</Tip>
|
|
251
|
+
</div>
|
|
252
|
+
<TokensSecondaryNav />
|
|
253
|
+
</>
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Register panel components by id when a route opts into `secondaryPanel` in nav. */
|
|
258
|
+
const PANELS: Record<string, React.FC> = {
|
|
259
|
+
"library": LibraryPanel,
|
|
260
|
+
tokens: TokensPanel,
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function SecondaryPanel() {
|
|
264
|
+
const { activePanel, secondaryPanelCompact } = useSecondaryPanel()
|
|
265
|
+
const PanelContent = activePanel ? PANELS[activePanel] : null
|
|
266
|
+
|
|
267
|
+
return (
|
|
268
|
+
<NestedSecondaryPanelShell open={Boolean(activePanel)} compact={secondaryPanelCompact}>
|
|
269
|
+
{PanelContent ? <PanelContent /> : null}
|
|
270
|
+
</NestedSecondaryPanelShell>
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
275
|
+
// Auto-open hook — pages call this to show/hide a panel on mount/unmount
|
|
276
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
277
|
+
|
|
278
|
+
export function useAutoPanel(panelId: string) {
|
|
279
|
+
const { openPanel, closePanel } = useSecondaryPanel()
|
|
280
|
+
|
|
281
|
+
React.useEffect(() => {
|
|
282
|
+
openPanel(panelId)
|
|
283
|
+
return () => {
|
|
284
|
+
closePanel()
|
|
285
|
+
}
|
|
286
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
287
|
+
}, [panelId])
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Sync hub folder state into the library secondary nav while the route is mounted. */
|
|
291
|
+
export function LibraryFolderBridge({
|
|
292
|
+
folders,
|
|
293
|
+
onFoldersChange,
|
|
294
|
+
items,
|
|
295
|
+
onItemsChange,
|
|
296
|
+
}: LibraryFolderBridge) {
|
|
297
|
+
const { setLibraryFolderBridge } = useSecondaryPanel()
|
|
298
|
+
|
|
299
|
+
React.useEffect(() => {
|
|
300
|
+
setLibraryFolderBridge({ folders, onFoldersChange, items, onItemsChange })
|
|
301
|
+
return () => setLibraryFolderBridge(null)
|
|
302
|
+
}, [folders, onFoldersChange, items, onItemsChange, setLibraryFolderBridge])
|
|
303
|
+
|
|
304
|
+
return null
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export function LibraryAccessBridge({ openManageAccess }: LibraryAccessBridge) {
|
|
308
|
+
const { setLibraryAccessBridge } = useSecondaryPanel()
|
|
309
|
+
|
|
310
|
+
React.useEffect(() => {
|
|
311
|
+
setLibraryAccessBridge({ openManageAccess })
|
|
312
|
+
return () => setLibraryAccessBridge(null)
|
|
313
|
+
}, [openManageAccess, setLibraryAccessBridge])
|
|
314
|
+
|
|
315
|
+
return null
|
|
316
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef } from "react"
|
|
4
|
+
import { useSidebar } from "@/components/ui/sidebar"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Collapses the sidebar on mount. Restores previous state on unmount.
|
|
8
|
+
* Use on focused full-page forms / wizards so the sidebar collapses when
|
|
9
|
+
* entering and reverts to whatever it was when leaving.
|
|
10
|
+
*
|
|
11
|
+
* Both transitions pass `{ persist: false }` so the visual collapse never
|
|
12
|
+
* overwrites the user's saved sidebar preference (the `sidebar_state_v2`
|
|
13
|
+
* cookie). Only an explicit toggle (⌘B / sidebar button) persists.
|
|
14
|
+
*/
|
|
15
|
+
export function SidebarAutoCollapse() {
|
|
16
|
+
const { open, setOpen } = useSidebar()
|
|
17
|
+
const prevOpen = useRef(open)
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
prevOpen.current = open
|
|
21
|
+
setOpen(false, { persist: false })
|
|
22
|
+
return () => { setOpen(prevOpen.current, { persist: false }) }
|
|
23
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24
|
+
}, [])
|
|
25
|
+
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
import { useEffect, useRef } from "react"
|
|
4
4
|
import { useSidebar } from "@/components/ui/sidebar"
|
|
5
5
|
|
|
6
|
-
/** Reopens the sidebar once
|
|
6
|
+
/** Reopens the sidebar once on mount — pair with `SidebarAutoCollapse` on focused
|
|
7
|
+
* full-page forms / wizards so leaving the form restores the sidebar. */
|
|
7
8
|
export function SidebarAutoOpen() {
|
|
8
9
|
const { setOpen } = useSidebar()
|
|
9
10
|
const ran = useRef(false)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* SidebarShell — SidebarProvider with layout-aware widths.
|
|
5
|
-
* Desktop expanded/collapsed is persisted in the `
|
|
5
|
+
* Desktop expanded/collapsed is persisted in the `sidebar_state_v2` cookie by `@exxatdesignux/ui`
|
|
6
6
|
* `SidebarProvider` (read on mount + write on toggle). `(app)/layout` passes
|
|
7
7
|
* `defaultOpen` from the same cookie on the server so SSR matches the first client paint.
|
|
8
8
|
*/
|