@exxatdesignux/ui 0.2.18 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -1
- package/bin/sync-extras.mjs +116 -29
- package/consumer-extras/README.md +43 -4
- 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 +41 -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-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-question-bank-hub-header.mdc +28 -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 +2 -2
- package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +9 -9
- package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
- package/consumer-extras/handbook/HANDBOOK.md +185 -0
- package/consumer-extras/handbook/glossary.md +57 -0
- package/consumer-extras/handbook/reference-implementations.md +126 -0
- package/consumer-extras/handbook/voice-and-tone.md +262 -0
- package/consumer-extras/patterns/command-menu-pattern.md +1 -1
- package/consumer-extras/patterns/data-views-pattern.md +14 -14
- 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 +167 -0
- package/dist/components/data-views/hub-table.js +5561 -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 +6575 -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 +13324 -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 -18
- 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 +255 -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 +498 -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/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 +494 -151
- 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/.cursor/rules/exxat-command-menu.mdc +1 -1
- package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
- package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
- package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
- package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
- package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
- package/template/AGENTS.md +84 -20
- package/template/app/(app)/examples/page.tsx +0 -1
- package/template/app/(app)/layout.tsx +17 -4
- package/template/app/(app)/question-bank/layout.tsx +1 -1
- package/template/app/(app)/question-bank/new/page.tsx +11 -24
- package/template/app/globals.css +13 -1972
- 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/compliance-table.tsx +240 -384
- 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-view-dashboard-charts-compliance.tsx +2 -2
- package/template/components/data-view-dashboard-charts-team.tsx +2 -2
- package/template/components/data-view-dashboard-charts.tsx +2 -2
- 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 +42 -1
- 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 -0
- 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 -60
- 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/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/hub-tree-panel-view.tsx +2 -2
- 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/new-placement-back-btn.tsx +1 -1
- package/template/components/new-placement-form.tsx +63 -189
- package/template/components/new-question-composer.tsx +432 -402
- 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/placement-board-card.tsx +71 -83
- package/template/components/placements-board-view.tsx +3 -10
- package/template/components/placements-client.tsx +10 -42
- package/template/components/placements-list-view.tsx +22 -69
- package/template/components/placements-table-columns.tsx +8 -438
- package/template/components/placements-table.tsx +588 -1296
- package/template/components/product-switcher.tsx +1 -1
- package/template/components/product-wordmark.tsx +2 -1
- package/template/components/question-bank-client.tsx +4 -1
- package/template/components/question-bank-hub-client.tsx +1 -1
- package/template/components/question-bank-new-folder-sheet.tsx +2 -2
- package/template/components/question-bank-secondary-nav.tsx +3 -3
- package/template/components/question-bank-table.tsx +294 -526
- package/template/components/rotations-empty-state.tsx +1 -1
- package/template/components/rotations-panel-activator.tsx +1 -1
- package/template/components/settings-appearance-card.tsx +1 -1
- package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
- package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +4 -4
- package/template/components/sidebar/index.ts +16 -0
- package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
- package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +6 -3
- package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
- package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
- package/template/components/site-header.tsx +1 -1
- package/template/components/{sites-all-client.tsx → sites-client.tsx} +1 -1
- package/template/components/sites-table.tsx +124 -257
- 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 -249
- package/template/components/table-properties/drawer.tsx +1 -1105
- 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/team-table.tsx +242 -382
- 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/list-page.tsx +1 -584
- package/template/components/templates/nested-secondary-panel-shell.tsx +1 -62
- package/template/components/templates/new-focus-template.tsx +659 -0
- package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
- 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/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/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 +14 -14
- 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/token-taxonomy.md +416 -0
- package/template/eslint.config.mjs +27 -0
- package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
- package/template/lib/command-menu-config.ts +0 -1
- package/template/lib/compliance-supported-views.ts +10 -0
- package/template/lib/conditional-rule-match.ts +6 -97
- package/template/lib/data-list-display-options.ts +1 -35
- package/template/lib/data-list-view-registry.ts +1 -0
- package/template/lib/data-list-view-surface.ts +1 -69
- package/template/lib/data-list-view.ts +1 -38
- package/template/lib/dev-log.ts +1 -8
- package/template/lib/editable-target.ts +1 -10
- package/template/lib/hub-connected-view-renderers.ts +58 -0
- package/template/lib/list-hub-supported-views.ts +10 -0
- package/template/lib/list-page-table-properties.ts +1 -52
- package/template/lib/mock/navigation.tsx +0 -8
- package/template/lib/mock/placements.ts +0 -7
- package/template/lib/placement-board-card-layout.ts +41 -41
- package/template/lib/placements-supported-views.ts +12 -0
- package/template/lib/question-bank-supported-views.ts +12 -0
- 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/sites-supported-views.ts +10 -0
- package/template/lib/team-supported-views.ts +10 -0
- package/template/package.json +1 -0
- package/template/tests/setup.ts +25 -0
- package/src/theme.css +0 -1132
- package/template/app/(app)/data-list/[id]/page.tsx +0 -44
- package/template/app/(app)/data-list/new/page.tsx +0 -34
- package/template/app/(app)/data-list/page.tsx +0 -10
- package/template/components/compliance-list-view.tsx +0 -54
- package/template/components/dashboard-onboarding-gallery.tsx +0 -13
- package/template/components/dashboard-onboarding.tsx +0 -21
- package/template/components/question-bank-list-view.tsx +0 -53
- package/template/components/section-cards.tsx +0 -106
- package/template/components/sites-list-view.tsx +0 -42
- package/template/components/team-list-view.tsx +0 -59
- package/template/lib/placement-lifecycle.ts +0 -5
- /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
- /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NewFocusTemplate — focused, single-task "New X" workflow shell.
|
|
5
|
+
*
|
|
6
|
+
* One template, three variants — pick the one that matches your task shape:
|
|
7
|
+
*
|
|
8
|
+
* 1. `variant="shell"` empty body slot — caller renders anything inside the
|
|
9
|
+
* hero header (title + description + Back link).
|
|
10
|
+
*
|
|
11
|
+
* 2. `variant="workflow"` multi-step wizard like New placement — `StepIndicator`,
|
|
12
|
+
* step content render-prop, sticky footer with progress
|
|
13
|
+
* dots + Back / Next / Submit buttons (Kbd hints + bound
|
|
14
|
+
* ⌘Enter / ⌘⌥← shortcuts).
|
|
15
|
+
*
|
|
16
|
+
* 3. `variant="form-inspector"` two-column layout (form left, sticky inspector right
|
|
17
|
+
* on lg+; stacks on mobile) — like New question composer.
|
|
18
|
+
* Inspector is collapsible via the caller's controlled
|
|
19
|
+
* open state.
|
|
20
|
+
*
|
|
21
|
+
* The template does NOT own form state. Callers wrap `<NewFocusTemplate>` in a
|
|
22
|
+
* `<form>` (or `<Form>` from `react-hook-form`) and pass step validators / submit
|
|
23
|
+
* handlers — this keeps the template framework-agnostic.
|
|
24
|
+
*
|
|
25
|
+
* IMPORTANT — `<form>` MUST flex inside the app shell row.
|
|
26
|
+
* `NewFocusTemplate` renders a `PrimaryPageTemplate` which renders a `SidebarInset`.
|
|
27
|
+
* The `SidebarInset` itself sits as a flex child of the `(app)/layout` row alongside
|
|
28
|
+
* the primary sidebar + secondary panel + Ask Leo rail and uses `w-full flex-1` to
|
|
29
|
+
* fill the remaining space. If the caller wraps `NewFocusTemplate` in a `<form>` (which
|
|
30
|
+
* is the canonical pattern for `react-hook-form`), the `<form>` itself becomes the flex
|
|
31
|
+
* child and `SidebarInset`'s `flex-1` no longer reaches the row. The page then
|
|
32
|
+
* collapses to its intrinsic content width and renders as a thin column with the rest
|
|
33
|
+
* of the viewport empty. ALWAYS apply `flex min-h-0 min-w-0 flex-1 flex-col` to the
|
|
34
|
+
* wrapping `<form>` so it behaves like a normal flex column host:
|
|
35
|
+
*
|
|
36
|
+
* ```tsx
|
|
37
|
+
* <form className="flex min-h-0 min-w-0 flex-1 flex-col" onSubmit={…}>
|
|
38
|
+
* <NewFocusTemplate variant="form-inspector" …>…</NewFocusTemplate>
|
|
39
|
+
* </form>
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* See `new-placement-form.tsx` and `new-question-composer.tsx` for canonical usage.
|
|
43
|
+
*
|
|
44
|
+
* The template owns:
|
|
45
|
+
* • Page chrome (`PrimaryPageTemplate` underneath: `SidebarInset`, `SiteHeader`).
|
|
46
|
+
* • The hero `<h1>` + description + Back link.
|
|
47
|
+
* • For `workflow`: `StepIndicator`, step content render slot, sticky footer with
|
|
48
|
+
* keyboard-shortcut Kbd hints + bound `<Shortcut>` handlers (⌘Enter advance,
|
|
49
|
+
* ⌘⌥← back, plain Enter submit on final step).
|
|
50
|
+
* • For `form-inspector`: 2-column scaffold with sticky inspector rail.
|
|
51
|
+
*
|
|
52
|
+
* WCAG 2.1 AA — same rules as `new-placement-form` / `new-question-composer`:
|
|
53
|
+
* ✓ Hero `<h1>` carries the page title (only one h1 per route).
|
|
54
|
+
* ✓ Step indicator uses `aria-current="step"` and visible labels (1.3.1).
|
|
55
|
+
* ✓ Focus moves to step content when step changes (2.4.3).
|
|
56
|
+
* ✓ Submit/Cancel/Back/Next buttons carry inline Kbd hints + Shortcut bindings.
|
|
57
|
+
* ✓ Footer is sticky and contained within `<form>` so Enter on step 1..n-1 is no-op.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
import * as React from "react"
|
|
61
|
+
import Link from "next/link"
|
|
62
|
+
|
|
63
|
+
import { cn } from "@/lib/utils"
|
|
64
|
+
import { Button } from "@/components/ui/button"
|
|
65
|
+
import { Kbd, KbdGroup } from "@/components/ui/kbd"
|
|
66
|
+
import { Shortcut } from "@/components/ui/dropdown-menu"
|
|
67
|
+
import { Tip } from "@/components/ui/tip"
|
|
68
|
+
import { useModKeyLabel, useAltKeyLabel } from "@/hooks/use-mod-key-label"
|
|
69
|
+
import { SidebarAutoCollapse } from "@/components/sidebar"
|
|
70
|
+
import {
|
|
71
|
+
PrimaryPageTemplate,
|
|
72
|
+
type PrimaryPageTemplateProps,
|
|
73
|
+
} from "@/components/templates/primary-page-template"
|
|
74
|
+
|
|
75
|
+
// ─── Shared types ────────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
interface BackLink {
|
|
78
|
+
href: string
|
|
79
|
+
label?: string
|
|
80
|
+
ariaLabel?: string
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface NewFocusBaseProps {
|
|
84
|
+
/** Page `<h1>` text. */
|
|
85
|
+
title: string
|
|
86
|
+
/** Subhead below the title — short sentence describing the task. */
|
|
87
|
+
description?: React.ReactNode
|
|
88
|
+
/** Back link rendered above the hero (and as `siteHeader.back` if `useSiteHeaderBack`). */
|
|
89
|
+
back: BackLink
|
|
90
|
+
/**
|
|
91
|
+
* When `true`, the parent route's `SiteHeader` carries the back-icon (parent-link only;
|
|
92
|
+
* no hero back link rendered). Mirrors `NewQuestionPage` which passes `back` to `SiteHeader`.
|
|
93
|
+
* Default `false` — Back link is rendered inline above the hero (matches `new-record/page`).
|
|
94
|
+
*/
|
|
95
|
+
useSiteHeaderBack?: boolean
|
|
96
|
+
/**
|
|
97
|
+
* Replace the default hero (Back link + `<h1>` + description) with a fully custom node.
|
|
98
|
+
* Use this when the page needs a `PageHeader`-style chrome (subtitle / actions / row),
|
|
99
|
+
* e.g. New question composer with Save / More actions. Title and description props are
|
|
100
|
+
* ignored when `header` is provided.
|
|
101
|
+
*/
|
|
102
|
+
header?: React.ReactNode
|
|
103
|
+
/**
|
|
104
|
+
* Render alongside the default hero `<h1>` as right-aligned actions (filled CTA + overflow).
|
|
105
|
+
* Ignored when `header` is provided.
|
|
106
|
+
*/
|
|
107
|
+
headerActions?: React.ReactNode
|
|
108
|
+
/**
|
|
109
|
+
* Optional ID-style subtitle rendered below the `<h1>` in lieu of `description`. Use this
|
|
110
|
+
* for stable record identifiers (e.g. draft question id + version).
|
|
111
|
+
*/
|
|
112
|
+
headerSubtitle?: React.ReactNode
|
|
113
|
+
/** Override the `PrimaryPageTemplate` max-width. Default: `max-w-3xl` (workflow / shell), `max-w-[1100px]` (form-inspector). */
|
|
114
|
+
maxWidthClassName?: string
|
|
115
|
+
/** Extra classes for the `PrimaryPageTemplate` body wrapper. Default sets `overflow-y-auto`. */
|
|
116
|
+
bodyClassName?: string
|
|
117
|
+
/** Extra classes for the `PrimaryPageTemplate` content column. */
|
|
118
|
+
contentClassName?: string
|
|
119
|
+
/** Optional extra chrome rendered before `SiteHeader` (e.g. command-menu). `SidebarAutoCollapse` is included by default. */
|
|
120
|
+
beforeSiteHeader?: React.ReactNode
|
|
121
|
+
/** Customize the `siteHeader` props passed to `PrimaryPageTemplate`. */
|
|
122
|
+
siteHeader?: PrimaryPageTemplateProps["siteHeader"]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ─── Variant 1: shell ────────────────────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
interface ShellVariantProps extends NewFocusBaseProps {
|
|
128
|
+
variant: "shell"
|
|
129
|
+
/** Body content rendered below the hero. */
|
|
130
|
+
children: React.ReactNode
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ─── Variant 2: workflow ─────────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
export interface NewFocusStep {
|
|
136
|
+
/** Stable identifier for the step (used as React key + `STEP_FIELDS` map key). */
|
|
137
|
+
id: string
|
|
138
|
+
/** Short label shown under the step circle (e.g. "Student"). */
|
|
139
|
+
label: string
|
|
140
|
+
/** Optional Font Awesome glyph (e.g. `fa-user-graduate`) shown in the section heading. */
|
|
141
|
+
icon?: string
|
|
142
|
+
/** Render the step body. Receives the active step index (0-based). */
|
|
143
|
+
render: (ctx: { stepIndex: number; isActive: boolean }) => React.ReactNode
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
interface WorkflowVariantProps extends NewFocusBaseProps {
|
|
147
|
+
variant: "workflow"
|
|
148
|
+
/** Ordered step list. Length must be ≥ 1. */
|
|
149
|
+
steps: NewFocusStep[]
|
|
150
|
+
/** Active step (0-based). The caller owns this state so a step can be reached via review-section "Edit". */
|
|
151
|
+
step: number
|
|
152
|
+
/** Called when the user clicks a step circle directly (jump). Optional — omit to disable jumps. */
|
|
153
|
+
onStepChange?: (next: number) => void
|
|
154
|
+
/**
|
|
155
|
+
* Called when Next / ⌘Enter is invoked. Caller validates the current step's fields and
|
|
156
|
+
* returns `true` if advance should proceed. Async-friendly for `react-hook-form` triggers.
|
|
157
|
+
*/
|
|
158
|
+
onNext: () => boolean | Promise<boolean>
|
|
159
|
+
/** Called when the form is submitted on the final step. */
|
|
160
|
+
onSubmit: () => void | Promise<void>
|
|
161
|
+
/** Label on the final-step submit button (e.g. "Create placement"). */
|
|
162
|
+
submitLabel: string
|
|
163
|
+
/** Optional icon glyph for the submit button (defaults to `fa-check`). */
|
|
164
|
+
submitIcon?: string
|
|
165
|
+
/** Disable inputs / show spinner when `true`. */
|
|
166
|
+
submitting?: boolean
|
|
167
|
+
/** Override the Next button label. Default `"Next"`. */
|
|
168
|
+
nextLabel?: string
|
|
169
|
+
/** Override the Back button label. Default `"Back"`. */
|
|
170
|
+
backLabel?: string
|
|
171
|
+
/** Scroll to top of window when step changes. Default `true`. */
|
|
172
|
+
scrollOnStepChange?: boolean
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ─── Variant 3: form-inspector ───────────────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
interface FormInspectorVariantProps extends NewFocusBaseProps {
|
|
178
|
+
variant: "form-inspector"
|
|
179
|
+
/** Form body rendered in the left column. */
|
|
180
|
+
children: React.ReactNode
|
|
181
|
+
/**
|
|
182
|
+
* Inspector body rendered in the right rail (sticky on lg+).
|
|
183
|
+
* Either a static node (template handles open/close by toggling visibility) OR a render
|
|
184
|
+
* function that receives `{ open }` so the caller can render different content in collapsed
|
|
185
|
+
* state (e.g. show a single "Open inspector" button when `!open`). Use the function form
|
|
186
|
+
* when the caller's inspector has its own internal show/hide affordance.
|
|
187
|
+
*/
|
|
188
|
+
inspector: React.ReactNode | ((ctx: { open: boolean }) => React.ReactNode)
|
|
189
|
+
/** `true` → inspector expanded; `false` → collapsed to a rail with an "Open" affordance. */
|
|
190
|
+
inspectorOpen: boolean
|
|
191
|
+
/** Called when the toolbar inspector toggle is clicked. */
|
|
192
|
+
onInspectorOpenChange: (open: boolean) => void
|
|
193
|
+
/** Width of the inspector rail when open. Default `"320px"`. */
|
|
194
|
+
inspectorOpenWidth?: string
|
|
195
|
+
/** Width of the inspector rail when collapsed. Default `"3.5rem"` (~56px). */
|
|
196
|
+
inspectorCollapsedWidth?: string
|
|
197
|
+
/** Accessible label on the inspector `<aside>`. Default `"Inspector"`. */
|
|
198
|
+
inspectorAriaLabel?: string
|
|
199
|
+
/**
|
|
200
|
+
* Hide the built-in inspector toggle (sidebar-flip icon). Use this when the caller renders
|
|
201
|
+
* its own toggle in the header actions or inside the inspector body itself
|
|
202
|
+
* (e.g. New question composer routes the toggle through a "More actions" overflow menu).
|
|
203
|
+
*/
|
|
204
|
+
hideInspectorToggle?: boolean
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ─── Union ───────────────────────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
export type NewFocusTemplateProps =
|
|
210
|
+
| ShellVariantProps
|
|
211
|
+
| WorkflowVariantProps
|
|
212
|
+
| FormInspectorVariantProps
|
|
213
|
+
|
|
214
|
+
// ─── Step indicator (workflow variant) ───────────────────────────────────────
|
|
215
|
+
|
|
216
|
+
function StepIndicator({
|
|
217
|
+
steps,
|
|
218
|
+
current,
|
|
219
|
+
onStepClick,
|
|
220
|
+
}: {
|
|
221
|
+
steps: NewFocusStep[]
|
|
222
|
+
current: number
|
|
223
|
+
onStepClick?: (i: number) => void
|
|
224
|
+
}) {
|
|
225
|
+
return (
|
|
226
|
+
<nav aria-label="Form steps" className="mb-8">
|
|
227
|
+
<ol className="flex items-center">
|
|
228
|
+
{steps.map((step, idx) => {
|
|
229
|
+
const isCompleted = idx < current
|
|
230
|
+
const isActive = idx === current
|
|
231
|
+
const isLast = idx === steps.length - 1
|
|
232
|
+
const Circle = (
|
|
233
|
+
<div
|
|
234
|
+
aria-current={isActive ? "step" : undefined}
|
|
235
|
+
className={cn(
|
|
236
|
+
"flex size-9 items-center justify-center rounded-full border-2 text-xs font-semibold transition-all",
|
|
237
|
+
isCompleted && "border-emerald-600 bg-emerald-600 text-white",
|
|
238
|
+
isActive && "border-brand bg-brand/10 text-brand",
|
|
239
|
+
!isCompleted && !isActive && "border-border bg-muted/40 text-muted-foreground",
|
|
240
|
+
)}
|
|
241
|
+
>
|
|
242
|
+
{isCompleted ? (
|
|
243
|
+
<i className="fa-light fa-check text-xs" aria-hidden="true" />
|
|
244
|
+
) : (
|
|
245
|
+
<span>{idx + 1}</span>
|
|
246
|
+
)}
|
|
247
|
+
<span className="sr-only">
|
|
248
|
+
Step {idx + 1}: {step.label}
|
|
249
|
+
{isCompleted ? " (completed)" : isActive ? " (current)" : ""}
|
|
250
|
+
</span>
|
|
251
|
+
</div>
|
|
252
|
+
)
|
|
253
|
+
return (
|
|
254
|
+
<React.Fragment key={step.id}>
|
|
255
|
+
<li className="flex flex-col items-center gap-1.5 shrink-0">
|
|
256
|
+
{onStepClick && isCompleted ? (
|
|
257
|
+
<button
|
|
258
|
+
type="button"
|
|
259
|
+
onClick={() => onStepClick(idx)}
|
|
260
|
+
className="cursor-pointer rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
|
261
|
+
aria-label={`Go to step ${idx + 1}: ${step.label}`}
|
|
262
|
+
>
|
|
263
|
+
{Circle}
|
|
264
|
+
</button>
|
|
265
|
+
) : (
|
|
266
|
+
Circle
|
|
267
|
+
)}
|
|
268
|
+
<span
|
|
269
|
+
className={cn(
|
|
270
|
+
"hidden sm:block text-xs whitespace-nowrap",
|
|
271
|
+
isActive && "text-foreground font-medium",
|
|
272
|
+
isCompleted && "text-emerald-600 font-medium",
|
|
273
|
+
!isCompleted && !isActive && "text-muted-foreground",
|
|
274
|
+
)}
|
|
275
|
+
aria-hidden="true"
|
|
276
|
+
>
|
|
277
|
+
{step.label}
|
|
278
|
+
</span>
|
|
279
|
+
</li>
|
|
280
|
+
{!isLast && (
|
|
281
|
+
<div
|
|
282
|
+
aria-hidden="true"
|
|
283
|
+
className={cn(
|
|
284
|
+
"flex-1 h-0.5 mx-2 mb-5 rounded-full transition-colors",
|
|
285
|
+
idx < current ? "bg-emerald-600" : "bg-border",
|
|
286
|
+
)}
|
|
287
|
+
/>
|
|
288
|
+
)}
|
|
289
|
+
</React.Fragment>
|
|
290
|
+
)
|
|
291
|
+
})}
|
|
292
|
+
</ol>
|
|
293
|
+
</nav>
|
|
294
|
+
)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ─── Hero block (shared) ─────────────────────────────────────────────────────
|
|
298
|
+
|
|
299
|
+
function NewFocusHero({
|
|
300
|
+
title,
|
|
301
|
+
description,
|
|
302
|
+
back,
|
|
303
|
+
showInlineBack,
|
|
304
|
+
actions,
|
|
305
|
+
subtitle,
|
|
306
|
+
}: {
|
|
307
|
+
title: string
|
|
308
|
+
description?: React.ReactNode
|
|
309
|
+
back: BackLink
|
|
310
|
+
showInlineBack: boolean
|
|
311
|
+
actions?: React.ReactNode
|
|
312
|
+
subtitle?: React.ReactNode
|
|
313
|
+
}) {
|
|
314
|
+
const hasActions = actions != null
|
|
315
|
+
return (
|
|
316
|
+
<>
|
|
317
|
+
{showInlineBack ? (
|
|
318
|
+
<Link
|
|
319
|
+
href={back.href}
|
|
320
|
+
className="inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-interactive-hover-foreground transition-colors mb-5 group"
|
|
321
|
+
aria-label={back.ariaLabel ?? `Back to ${back.label ?? "previous page"}`}
|
|
322
|
+
>
|
|
323
|
+
<i
|
|
324
|
+
className="fa-light fa-arrow-left text-xs transition-transform group-hover:-translate-x-0.5"
|
|
325
|
+
aria-hidden="true"
|
|
326
|
+
/>
|
|
327
|
+
{back.label ?? "Back"}
|
|
328
|
+
</Link>
|
|
329
|
+
) : null}
|
|
330
|
+
<div
|
|
331
|
+
className={cn(
|
|
332
|
+
hasActions
|
|
333
|
+
? "mb-8 flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between lg:gap-6"
|
|
334
|
+
: "",
|
|
335
|
+
)}
|
|
336
|
+
>
|
|
337
|
+
<div className={cn(hasActions ? "min-w-0" : "")}>
|
|
338
|
+
<h1
|
|
339
|
+
className="text-[2.25rem] font-semibold tracking-tight leading-none text-foreground mb-2"
|
|
340
|
+
style={{ fontFamily: "var(--font-heading)" }}
|
|
341
|
+
>
|
|
342
|
+
{title}
|
|
343
|
+
</h1>
|
|
344
|
+
{subtitle ? (
|
|
345
|
+
<p className="text-sm text-muted-foreground">{subtitle}</p>
|
|
346
|
+
) : null}
|
|
347
|
+
{description ? (
|
|
348
|
+
<p
|
|
349
|
+
className={cn(
|
|
350
|
+
"text-sm text-muted-foreground",
|
|
351
|
+
hasActions || subtitle ? "" : "mb-8",
|
|
352
|
+
)}
|
|
353
|
+
>
|
|
354
|
+
{description}
|
|
355
|
+
</p>
|
|
356
|
+
) : null}
|
|
357
|
+
</div>
|
|
358
|
+
{hasActions ? (
|
|
359
|
+
<div className="flex shrink-0 items-center gap-2">{actions}</div>
|
|
360
|
+
) : null}
|
|
361
|
+
</div>
|
|
362
|
+
</>
|
|
363
|
+
)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ─── Body renderers ──────────────────────────────────────────────────────────
|
|
367
|
+
|
|
368
|
+
function ShellBody({ children }: { children: React.ReactNode }) {
|
|
369
|
+
return <>{children}</>
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function WorkflowBody(props: WorkflowVariantProps) {
|
|
373
|
+
const {
|
|
374
|
+
steps,
|
|
375
|
+
step,
|
|
376
|
+
onStepChange,
|
|
377
|
+
onNext,
|
|
378
|
+
onSubmit,
|
|
379
|
+
submitLabel,
|
|
380
|
+
submitIcon = "fa-check",
|
|
381
|
+
submitting = false,
|
|
382
|
+
nextLabel = "Next",
|
|
383
|
+
backLabel = "Back",
|
|
384
|
+
scrollOnStepChange = true,
|
|
385
|
+
} = props
|
|
386
|
+
|
|
387
|
+
const lastIndex = steps.length - 1
|
|
388
|
+
const isFinal = step === lastIndex
|
|
389
|
+
const stepHeadingRef = React.useRef<HTMLDivElement>(null)
|
|
390
|
+
const mod = useModKeyLabel()
|
|
391
|
+
const alt = useAltKeyLabel()
|
|
392
|
+
|
|
393
|
+
React.useEffect(() => {
|
|
394
|
+
stepHeadingRef.current?.focus()
|
|
395
|
+
}, [step])
|
|
396
|
+
|
|
397
|
+
const handleNextClick = React.useCallback(async () => {
|
|
398
|
+
const ok = await onNext()
|
|
399
|
+
if (!ok) return
|
|
400
|
+
onStepChange?.(Math.min(step + 1, lastIndex))
|
|
401
|
+
if (scrollOnStepChange) {
|
|
402
|
+
window.scrollTo({ top: 0, behavior: "smooth" })
|
|
403
|
+
}
|
|
404
|
+
}, [onNext, onStepChange, step, lastIndex, scrollOnStepChange])
|
|
405
|
+
|
|
406
|
+
const handleBackClick = React.useCallback(() => {
|
|
407
|
+
onStepChange?.(Math.max(step - 1, 0))
|
|
408
|
+
if (scrollOnStepChange) {
|
|
409
|
+
window.scrollTo({ top: 0, behavior: "smooth" })
|
|
410
|
+
}
|
|
411
|
+
}, [onStepChange, step, scrollOnStepChange])
|
|
412
|
+
|
|
413
|
+
const handleSubmitClick = React.useCallback(() => {
|
|
414
|
+
void onSubmit()
|
|
415
|
+
}, [onSubmit])
|
|
416
|
+
|
|
417
|
+
return (
|
|
418
|
+
<>
|
|
419
|
+
{/*
|
|
420
|
+
Steps 1..n-1: ⌘Enter advances. Final step: ⌘Enter submits — plain Enter is
|
|
421
|
+
intentionally NOT bound globally; a global Enter shortcut would fire when focus
|
|
422
|
+
is on the step container (we focus it after each step for a11y), submitting
|
|
423
|
+
without an explicit submit action ("Review auto-closes" bug). Native Enter on
|
|
424
|
+
the submit button still submits the wrapping `<form>` on the final step.
|
|
425
|
+
*/}
|
|
426
|
+
{!isFinal && (
|
|
427
|
+
<Shortcut keys="⌘Enter" disabled={submitting} onInvoke={handleNextClick} />
|
|
428
|
+
)}
|
|
429
|
+
{isFinal && (
|
|
430
|
+
<Shortcut keys="⌘Enter" disabled={submitting} onInvoke={handleSubmitClick} />
|
|
431
|
+
)}
|
|
432
|
+
{step > 0 && (
|
|
433
|
+
<Shortcut keys="⌘⌥←" disabled={submitting} onInvoke={handleBackClick} />
|
|
434
|
+
)}
|
|
435
|
+
|
|
436
|
+
<StepIndicator
|
|
437
|
+
steps={steps}
|
|
438
|
+
current={step}
|
|
439
|
+
onStepClick={onStepChange ? (i) => onStepChange(i) : undefined}
|
|
440
|
+
/>
|
|
441
|
+
|
|
442
|
+
<div ref={stepHeadingRef} tabIndex={-1} className="outline-none">
|
|
443
|
+
{steps[step]?.render({ stepIndex: step, isActive: true })}
|
|
444
|
+
</div>
|
|
445
|
+
|
|
446
|
+
<div className="sticky bottom-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80 border-t border-border flex items-center justify-between mt-8 py-4">
|
|
447
|
+
<div className="flex items-center gap-1.5" aria-hidden="true">
|
|
448
|
+
{steps.map((s, i) => (
|
|
449
|
+
<div
|
|
450
|
+
key={s.id}
|
|
451
|
+
className={cn(
|
|
452
|
+
"rounded-full transition-all h-1.5",
|
|
453
|
+
i === step ? "w-6 bg-brand" : i < step ? "w-3 bg-brand/40" : "w-3 bg-border",
|
|
454
|
+
)}
|
|
455
|
+
/>
|
|
456
|
+
))}
|
|
457
|
+
</div>
|
|
458
|
+
|
|
459
|
+
<div className="flex items-center gap-2">
|
|
460
|
+
<Button
|
|
461
|
+
type="button"
|
|
462
|
+
variant="outline"
|
|
463
|
+
onClick={handleBackClick}
|
|
464
|
+
disabled={step === 0 || submitting}
|
|
465
|
+
>
|
|
466
|
+
<i className="fa-light fa-arrow-left text-[13px]" aria-hidden="true" />
|
|
467
|
+
{backLabel}
|
|
468
|
+
<KbdGroup className="ms-1.5">
|
|
469
|
+
<Kbd variant="bare">
|
|
470
|
+
{mod}
|
|
471
|
+
{alt}←
|
|
472
|
+
</Kbd>
|
|
473
|
+
</KbdGroup>
|
|
474
|
+
</Button>
|
|
475
|
+
|
|
476
|
+
{!isFinal ? (
|
|
477
|
+
<Button type="button" onClick={handleNextClick} disabled={submitting}>
|
|
478
|
+
{nextLabel}
|
|
479
|
+
<i className="fa-light fa-arrow-right text-[13px]" aria-hidden="true" />
|
|
480
|
+
<KbdGroup className="ms-1.5">
|
|
481
|
+
<Kbd variant="bare">{mod}⏎</Kbd>
|
|
482
|
+
</KbdGroup>
|
|
483
|
+
</Button>
|
|
484
|
+
) : (
|
|
485
|
+
<Button type="submit" disabled={submitting} aria-busy={submitting}>
|
|
486
|
+
{submitting ? (
|
|
487
|
+
<>
|
|
488
|
+
<i className="fa-light fa-spinner-third fa-spin text-[13px]" aria-hidden="true" />
|
|
489
|
+
Saving…
|
|
490
|
+
</>
|
|
491
|
+
) : (
|
|
492
|
+
<>
|
|
493
|
+
<i className={`fa-light ${submitIcon} text-[13px]`} aria-hidden="true" />
|
|
494
|
+
{submitLabel}
|
|
495
|
+
<KbdGroup className="ms-1.5">
|
|
496
|
+
<Kbd variant="bare">{mod}⏎</Kbd>
|
|
497
|
+
</KbdGroup>
|
|
498
|
+
</>
|
|
499
|
+
)}
|
|
500
|
+
</Button>
|
|
501
|
+
)}
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
</>
|
|
505
|
+
)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function FormInspectorBody(props: FormInspectorVariantProps) {
|
|
509
|
+
const {
|
|
510
|
+
children,
|
|
511
|
+
inspector,
|
|
512
|
+
inspectorOpen,
|
|
513
|
+
onInspectorOpenChange,
|
|
514
|
+
inspectorOpenWidth = "320px",
|
|
515
|
+
inspectorCollapsedWidth = "3.5rem",
|
|
516
|
+
inspectorAriaLabel = "Inspector",
|
|
517
|
+
hideInspectorToggle = false,
|
|
518
|
+
} = props
|
|
519
|
+
|
|
520
|
+
return (
|
|
521
|
+
<div
|
|
522
|
+
className={cn(
|
|
523
|
+
"grid grid-cols-1 transition-[gap,grid-template-columns] duration-200 lg:grid-cols-[minmax(0,1fr)_var(--inspector-w)]",
|
|
524
|
+
inspectorOpen ? "lg:gap-x-10" : "lg:gap-x-4",
|
|
525
|
+
)}
|
|
526
|
+
style={
|
|
527
|
+
{
|
|
528
|
+
"--inspector-w": inspectorOpen ? inspectorOpenWidth : inspectorCollapsedWidth,
|
|
529
|
+
} as React.CSSProperties
|
|
530
|
+
}
|
|
531
|
+
>
|
|
532
|
+
<div className="min-w-0">{children}</div>
|
|
533
|
+
|
|
534
|
+
<aside
|
|
535
|
+
aria-label={inspectorAriaLabel}
|
|
536
|
+
className="mt-8 lg:mt-0 lg:sticky lg:top-4 lg:self-start lg:h-fit min-w-0"
|
|
537
|
+
>
|
|
538
|
+
{hideInspectorToggle ? null : (
|
|
539
|
+
<div className="mb-3 flex items-center justify-end">
|
|
540
|
+
<Tip
|
|
541
|
+
side="left"
|
|
542
|
+
label={inspectorOpen ? "Hide inspector" : "Show inspector"}
|
|
543
|
+
>
|
|
544
|
+
<Button
|
|
545
|
+
variant="ghost"
|
|
546
|
+
size="icon"
|
|
547
|
+
className="size-7"
|
|
548
|
+
onClick={() => onInspectorOpenChange(!inspectorOpen)}
|
|
549
|
+
aria-label={inspectorOpen ? "Hide inspector" : "Show inspector"}
|
|
550
|
+
aria-expanded={inspectorOpen}
|
|
551
|
+
>
|
|
552
|
+
<i
|
|
553
|
+
className={cn(
|
|
554
|
+
"fa-light text-sm",
|
|
555
|
+
inspectorOpen ? "fa-sidebar-flip" : "fa-sidebar",
|
|
556
|
+
)}
|
|
557
|
+
aria-hidden="true"
|
|
558
|
+
/>
|
|
559
|
+
</Button>
|
|
560
|
+
</Tip>
|
|
561
|
+
</div>
|
|
562
|
+
)}
|
|
563
|
+
{typeof inspector === "function"
|
|
564
|
+
? inspector({ open: inspectorOpen })
|
|
565
|
+
: inspectorOpen
|
|
566
|
+
? inspector
|
|
567
|
+
: null}
|
|
568
|
+
</aside>
|
|
569
|
+
</div>
|
|
570
|
+
)
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// ─── Public component ───────────────────────────────────────────────────────
|
|
574
|
+
|
|
575
|
+
function defaultMaxWidth(variant: NewFocusTemplateProps["variant"]): string {
|
|
576
|
+
switch (variant) {
|
|
577
|
+
case "form-inspector":
|
|
578
|
+
return "mx-auto w-full max-w-[1100px]"
|
|
579
|
+
case "workflow":
|
|
580
|
+
return "max-w-3xl"
|
|
581
|
+
case "shell":
|
|
582
|
+
default:
|
|
583
|
+
return "max-w-3xl"
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
function defaultContentClass(variant: NewFocusTemplateProps["variant"]): string {
|
|
588
|
+
switch (variant) {
|
|
589
|
+
case "form-inspector":
|
|
590
|
+
return "px-8 py-4 pb-16"
|
|
591
|
+
case "workflow":
|
|
592
|
+
case "shell":
|
|
593
|
+
default:
|
|
594
|
+
return "px-8 pt-10 pb-32"
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function defaultBodyClass(variant: NewFocusTemplateProps["variant"]): string {
|
|
599
|
+
switch (variant) {
|
|
600
|
+
case "form-inspector":
|
|
601
|
+
return "min-h-0 flex-1 overflow-y-auto overscroll-y-contain"
|
|
602
|
+
case "workflow":
|
|
603
|
+
case "shell":
|
|
604
|
+
default:
|
|
605
|
+
return "overflow-y-auto"
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
export function NewFocusTemplate(props: NewFocusTemplateProps) {
|
|
610
|
+
const {
|
|
611
|
+
variant,
|
|
612
|
+
title,
|
|
613
|
+
description,
|
|
614
|
+
back,
|
|
615
|
+
useSiteHeaderBack = false,
|
|
616
|
+
header,
|
|
617
|
+
headerActions,
|
|
618
|
+
headerSubtitle,
|
|
619
|
+
maxWidthClassName,
|
|
620
|
+
bodyClassName,
|
|
621
|
+
contentClassName,
|
|
622
|
+
beforeSiteHeader,
|
|
623
|
+
siteHeader,
|
|
624
|
+
} = props
|
|
625
|
+
|
|
626
|
+
const computedSiteHeader = useSiteHeaderBack
|
|
627
|
+
? { back: { href: back.href, label: back.label ?? "Back", ariaLabel: back.ariaLabel } as const, ...(siteHeader ?? {}) }
|
|
628
|
+
: siteHeader
|
|
629
|
+
|
|
630
|
+
return (
|
|
631
|
+
<PrimaryPageTemplate
|
|
632
|
+
beforeSiteHeader={
|
|
633
|
+
<>
|
|
634
|
+
<SidebarAutoCollapse />
|
|
635
|
+
{beforeSiteHeader}
|
|
636
|
+
</>
|
|
637
|
+
}
|
|
638
|
+
siteHeader={computedSiteHeader}
|
|
639
|
+
maxWidthClassName={maxWidthClassName ?? defaultMaxWidth(variant)}
|
|
640
|
+
bodyClassName={bodyClassName ?? defaultBodyClass(variant)}
|
|
641
|
+
contentClassName={contentClassName ?? defaultContentClass(variant)}
|
|
642
|
+
>
|
|
643
|
+
{header ?? (
|
|
644
|
+
<NewFocusHero
|
|
645
|
+
title={title}
|
|
646
|
+
description={description}
|
|
647
|
+
back={back}
|
|
648
|
+
showInlineBack={!useSiteHeaderBack}
|
|
649
|
+
actions={headerActions}
|
|
650
|
+
subtitle={headerSubtitle}
|
|
651
|
+
/>
|
|
652
|
+
)}
|
|
653
|
+
|
|
654
|
+
{variant === "shell" ? <ShellBody>{props.children}</ShellBody> : null}
|
|
655
|
+
{variant === "workflow" ? <WorkflowBody {...props} /> : null}
|
|
656
|
+
{variant === "form-inspector" ? <FormInspectorBody {...props} /> : null}
|
|
657
|
+
</PrimaryPageTemplate>
|
|
658
|
+
)
|
|
659
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
|
|
3
3
|
import { PrimaryPageTemplate, type PrimaryPageTemplateProps } from "@/components/templates/primary-page-template"
|
|
4
|
-
import { useAutoPanel } from "@/components/
|
|
4
|
+
import { useAutoPanel } from "@/components/sidebar"
|
|
5
5
|
|
|
6
6
|
export interface SecondaryPanelHubActivatorProps {
|
|
7
7
|
panelId: string
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@exxatdesignux/ui/components/accordion"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@exxatdesignux/ui/components/alert-dialog"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@exxatdesignux/ui/components/context-menu"
|