@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
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> **Canonical rules for agents (MUST/MUST NOT, checklists):** [`AGENTS.md`](../AGENTS.md) in this package (including **§8 Accessibility**). This file is the long-form narrative; keep both aligned when patterns change.
|
|
4
4
|
|
|
5
|
+
> **Scaling past ~2K rows:** see [`large-dataset-strategy.md`](./large-dataset-strategy.md) for pagination, server-mode upgrade path, and the virtualization follow-up.
|
|
6
|
+
|
|
5
7
|
This document describes how list pages combine **views**, **toolbar** behavior, **filters**, **properties**, and **persistence** in this codebase.
|
|
6
8
|
|
|
7
9
|
## Reuse existing components (required)
|
|
@@ -10,18 +12,18 @@ This document describes how list pages combine **views**, **toolbar** behavior,
|
|
|
10
12
|
|
|
11
13
|
| Need | Reuse | Where Placements uses it |
|
|
12
14
|
| --- | --- | --- |
|
|
13
|
-
| **View tabs** (table / list / board, lifecycle filters) | `ListPageTemplate` (`ViewTab`, `renderContent`, optional metrics + export) | `components/
|
|
14
|
-
| **Table shell** (search, filter bar, sort, grouping, columns, pagination) | `DataTable`, `DataTableToolbar`, `useTableState` | `components/data-table/`, `components/data-
|
|
15
|
-
| **Properties drawer** (display, columns, filters, sort, view type tiles) | `TablePropertiesDrawer` from `@/components/table-properties` | `DrawerToolbar` / list–board shells in `
|
|
16
|
-
| **Board / list** | `PlacementsBoardView`, `
|
|
17
|
-
| **Page header** (primary CTA + More ⋯ + export) | `
|
|
18
|
-
| **
|
|
19
|
-
| **
|
|
20
|
-
| **Dashboard view (list tab)** | **`KeyMetrics`** (`variant="flat"` or `"card"`) — same KPI system as the template metrics strip; **do not** add ad-hoc `Card` grids for entity summaries | `
|
|
21
|
-
| **List hub metrics strip** | **`KeyMetrics variant="flat"`** — transparent cells, OKLCH brand glow only, border hairlines (**no** grey panel) | **`docs/kpi-flat-band-pattern.md`**, Placements / Team /
|
|
22
|
-
| **Secondary panel chrome** | **`--secondary-panel-bg`** on **`NestedSecondaryPanelShell`** (lighter than sidebar, follows active product) | **`docs/shell-surface-elevation-pattern.md`**,
|
|
23
|
-
| **Export** | `ExportDrawer` | `ListPageTemplate` export props; `
|
|
24
|
-
| **View body layout** (gutter + centered max-width for folder / icon / panel-style content) | **`ListPageViewFrame`** (`components/data-views/list-page-view-frame.tsx`, re-exported from `components/data-views`) | **`FolderGridView`** (uses the frame); **`
|
|
15
|
+
| **View tabs** (table / list / board, lifecycle filters) | `ListPageTemplate` (`ViewTab`, `renderContent`, optional metrics + export) | `components/library-hub-client.tsx` + `components/templates/list-page.tsx` |
|
|
16
|
+
| **Table shell** (search, filter bar, sort, grouping, columns, pagination) | `HubTable` → `DataTable`, `DataTableToolbar`, `useTableState` | `components/data-table/`, `components/data-views/hub-table.tsx`, `components/columns-showcase.tsx` |
|
|
17
|
+
| **Properties drawer** (display, columns, filters, sort, view type tiles) | `TablePropertiesDrawer` from `@/components/table-properties` (auto-wired by `HubTable`) | `DrawerToolbar` / list–board shells in `library-table.tsx` |
|
|
18
|
+
| **Board / list** | `PlacementsBoardView`, `PlacementListRowContent` (wrapped by `HubTable.renderListRow` → `DataRowList`) + same `useTableState` | `PlacementsTable` |
|
|
19
|
+
| **Page header** (primary CTA + More ⋯ + export) | Per-hub page header composing `PageHeader` + `ExportDrawer` button | `components/library-page-header.tsx` |
|
|
20
|
+
| **Primary hub composition** | `*Client` = `ListPageTemplate` + `KeyMetrics` + `*PageHeader` + `*Table`. Reference: `LibraryHubClient`. | `components/library-hub-client.tsx`, `components/columns-client.tsx`, `components/tokens-themes-client.tsx` |
|
|
21
|
+
| **Hub table body** | `HubTable` — wraps `DataTable` + `useTableState` + `TablePropertiesDrawer`; list / board / dashboard read **`tableState.rows`**. Pagination chrome is auto-mounted when the hub passes `pagination` + `onPaginationChange`. | `components/data-views/hub-table.tsx`, `components/library-table.tsx`, `components/columns-showcase.tsx` |
|
|
22
|
+
| **Dashboard view (list tab)** | **`KeyMetrics`** (`variant="flat"` or `"card"`) — same KPI system as the template metrics strip; **do not** add ad-hoc `Card` grids for entity summaries. | `LibraryTable` dashboard branch, `components/library-dashboard-charts.tsx` |
|
|
23
|
+
| **List hub metrics strip** | **`KeyMetrics variant="flat"`** — transparent cells, OKLCH brand glow only, border hairlines (**no** grey panel) | **`docs/kpi-flat-band-pattern.md`**, Placements / Team / Library clients |
|
|
24
|
+
| **Secondary panel chrome** | **`--secondary-panel-bg`** on **`NestedSecondaryPanelShell`** (lighter than sidebar, follows active product) | **`docs/shell-surface-elevation-pattern.md`**, Library |
|
|
25
|
+
| **Export** | `ExportDrawer` | `ListPageTemplate` export props; `PlacementsClient` |
|
|
26
|
+
| **View body layout** (gutter + centered max-width for folder / icon / panel-style content) | **`ListPageViewFrame`** (`components/data-views/list-page-view-frame.tsx`, re-exported from `components/data-views`) | **`FolderGridView`** (uses the frame); **`LibraryOsFolderView`** — see **`AGENTS.md` §4.5** |
|
|
25
27
|
|
|
26
28
|
**Rules:** (1) Import and compose these components; pass **props** and **column defs** for your entity. (2) If something is missing, **extend the shared component** under `components/` (e.g. a new optional slot on `DataTableToolbar`) rather than copying markup into a single page. (3) Card-only or lightweight pages may use a smaller **Properties** sheet only when there is **no** table—otherwise use `TablePropertiesDrawer` with `DataTable` (see Team).
|
|
27
29
|
|
|
@@ -29,7 +31,7 @@ This document describes how list pages combine **views**, **toolbar** behavior,
|
|
|
29
31
|
|
|
30
32
|
If the page uses a **`DataTable`** (or equivalent data grid) as the main surface, it **must** sit under **`ListPageTemplate`** so users get the **views toolbar** (tabs, add view, per-tab settings). The default `ViewTab` entries should include at least one tab whose `viewType` is **`table`** when the primary experience is tabular data. **Do not** render a `DataTable` alone under only `PageHeader` + body.
|
|
31
33
|
|
|
32
|
-
- **Reference:** `
|
|
34
|
+
- **Reference:** `PlacementsClient` (Placements) and `TeamClient` (Team).
|
|
33
35
|
- **Rationale:** Consistent navigation, saved views, per-tab view type (table / list / board), and export at the template level.
|
|
34
36
|
|
|
35
37
|
## View layout frame (centered, reusable)
|
|
@@ -38,45 +40,10 @@ Non-table view branches (e.g. **folder** icon grid, **panel** finder, OS-style f
|
|
|
38
40
|
|
|
39
41
|
**Handbook:** **`AGENTS.md` §4.5**. **Cursor:** **`.cursor/rules/exxat-list-page-view-shells.mdc`**. **Skill:** **`.cursor/skills/exxat-list-page-view-shells/SKILL.md`**. **Do not** wrap **`DataTable`** in the frame if that stacks padding with the table toolbar (**`AGENTS.md` §5**).
|
|
40
42
|
|
|
41
|
-
## View registry and connected bodies (extensibility)
|
|
42
|
-
|
|
43
|
-
To add a **new view type** without breaking existing hubs:
|
|
44
|
-
|
|
45
|
-
1. **Register once** — Add a tile in `lib/data-list-view.ts` (`DATA_LIST_VIEW_TILES`). Capabilities (hub KPI strip, render kind) derive automatically in `lib/data-list-view-registry.ts`.
|
|
46
|
-
2. **Build the body once** — Add or extend a generic surface under `components/data-views/` (e.g. `ListPageCalendarView`). Entity-specific wiring stays in props (`getEventDate`, board `renderCard`), not a second calendar implementation per hub.
|
|
47
|
-
3. **Declare what each hub supports** — `lib/<hub>-supported-views.ts` exports a `const` array; pass the same array to **`ListPageTemplate`** (`supportedViewTypes`), the hub table (`supportedViewTypes` → `TablePropertiesDrawerButton`), and rely on defaults if omitted. **Add view**, **⌘1–9** shortcuts, and **Properties → View type** tiles all use `dataListViewTilesForHub` / `dataListViewSelectionTilesForHub` so users cannot pick a view the hub never implemented.
|
|
48
|
-
4. **Route in the hub table with `ListPageConnectedViewBody`** — Switch on **`getDataListViewRenderKind(view)`**, not raw `view === "…"` chains. Pass one renderer per kind the hub supports via **`defineHubViewRenderers(MY_HUB_SUPPORTED_VIEWS, { … })`** (`lib/hub-connected-view-renderers.ts`) so dev builds warn when a supported view has no body. **Do not** use a default branch that renders dashboard/KPIs; missing renderers show `ListPageViewNotConfigured`.
|
|
49
|
-
5. **Let the template own hub chrome** — `ListPageTemplate` hides the metrics strip on calendar/dashboard via `showsListPageHubMetricsStrip(activeTab.viewType)`. Hub clients pass `showMetrics` only; they do not reimplement per-tab KPI visibility.
|
|
50
|
-
6. **Panel / Miller columns** — Reuse **`ListPageFolderColumnsPanel`** (`components/data-views/list-page-folder-columns-panel.tsx`) for folder + record columns; hub-specific chrome (folder colors, actions) lives in a thin wrapper (e.g. `QuestionBankFolderColumnsPanel`). **Do not** export question-bank-only tree/folder nav from the generic `data-views` barrel.
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
// lib/my-hub-supported-views.ts
|
|
54
|
-
export const MY_HUB_SUPPORTED_VIEWS = ["table", "list", "calendar"] as const satisfies readonly DataListViewType[]
|
|
55
|
-
|
|
56
|
-
// my-hub-client.tsx
|
|
57
|
-
<ListPageTemplate supportedViewTypes={MY_HUB_SUPPORTED_VIEWS} showMetrics={showMetrics} … />
|
|
58
|
-
|
|
59
|
-
// my-hub-table.tsx
|
|
60
|
-
import { defineHubViewRenderers } from "@/lib/hub-connected-view-renderers"
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<ListPageConnectedViewBody
|
|
64
|
-
view={view}
|
|
65
|
-
hubLabel="My hub"
|
|
66
|
-
renderers={defineHubViewRenderers(MY_HUB_SUPPORTED_VIEWS, {
|
|
67
|
-
"data-table": <DataTable … />,
|
|
68
|
-
"calendar-with-toolbar": toolbarShell(<ListPageCalendarView rows={tableState.rows} getEventDate={…} />),
|
|
69
|
-
})}
|
|
70
|
-
/>
|
|
71
|
-
)
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
**Checklist for a new view type:** registry tile → `data-views/` component → update each `*-supported-views.ts` that should expose it → add renderer in each `*-table.tsx` (via `defineHubViewRenderers`) → Properties drawer copy in `table-properties/drawer.tsx` if needed → `table-state-lifecycle` picks up types via `DATA_LIST_VIEW_TILES` (no separate allowlist).
|
|
75
|
-
|
|
76
43
|
## Architecture
|
|
77
44
|
|
|
78
45
|
- **Page shell** — `ListPageTemplate` owns the views toolbar (tabs), optional metrics, and export drawer. Content for the active tab is rendered via `renderContent`.
|
|
79
|
-
- **Per–lifecycle (or category) data** — `
|
|
46
|
+
- **Per–lifecycle (or category) data** — `PlacementsTable` swaps **columns** and **row sets** based on `lifecycleTabId` (e.g. All / Upcoming / Ongoing / Completed). Each lifecycle tab gets its **own** `PlacementsTable` instance (`key={tab.filterId}`) so `useTableState` resets correctly when columns change.
|
|
80
47
|
- **Shared table state** — `useTableState` holds sort, search, filters, grouping, column order/visibility/pins/widths, row height, gridlines, and pagination flags. **Table**, **list**, **board**, and **dashboard** all read the same state so switching view type keeps behavior aligned.
|
|
81
48
|
|
|
82
49
|
## Mock data and connected views
|
|
@@ -94,10 +61,10 @@ return (
|
|
|
94
61
|
|
|
95
62
|
| Concern | Table | List | Board | Dashboard (view tab) |
|
|
96
63
|
| --- | --- | --- | --- | --- |
|
|
97
|
-
| Primary surface | `DataTable` | `
|
|
64
|
+
| Primary surface | `DataTable` | `DataRowList` + entity row body (e.g. `PlacementListRowContent`) wired via `HubTable.renderListRow` | `PlacementsBoardView` / entity board | **`KeyMetrics`** (+ optional charts via shared dashboard components) |
|
|
98
65
|
| Data source | `useTableState` | **`tableState.rows`** | **`tableState.rows`** | **`tableState.rows`** via KPI helpers |
|
|
99
66
|
| Column headers / labels | `showColumnLabels` | Same source columns, list layout | Phase columns + optional board column menu | N/A (metrics from same columns/filters) |
|
|
100
|
-
| Row click / navigation | From `
|
|
67
|
+
| Row click / navigation | From `PlacementsTable` | From list shell | Card `onOpen` | N/A |
|
|
101
68
|
| Pagination | Optional `PaginationBar` + `CountSyncer` | Same pattern | N/A (board uses phase columns) | N/A |
|
|
102
69
|
|
|
103
70
|
## Toolbar and properties
|
|
@@ -124,20 +91,20 @@ return (
|
|
|
124
91
|
- **Status (Team & Compliance)** — `lib/list-status-badges.ts` — single source for label strings + badge `className` tails for **table, list, and board**. Do **not** pair with `uppercase` on the Badge (labels are sentence case, aligned with Placements `BoardStatusBadge`).
|
|
125
92
|
- **Owner initials** — `lib/initials-from-name.ts` when mock rows have a display name but no `initials` field.
|
|
126
93
|
- **Shared column shell** — `components/data-views/list-page-board-template.tsx` — `ListPageBoardTemplate` + `ListPageBoardColumnDef<T>`: define columns with `filter` predicates, `renderCard`, `getRowKey`. Used by **Team** and **Compliance** boards; new hubs should start here before custom chrome.
|
|
127
|
-
- **
|
|
94
|
+
- **Library board** — `components/library-board-view.tsx` — composes **`ListPageBoardCard`** parts with `BoardCardTwoLineBlock` for the body and `ListHubStatusBadge` for the status row. Use this as the reference for any new domain board card.
|
|
128
95
|
- New entities should add their own card component that composes **`ListPageBoardCard`** + primitives rather than duplicating column scroll/layout or ad-hoc card chrome.
|
|
129
96
|
|
|
130
97
|
## Dashboard view (list pages)
|
|
131
98
|
|
|
132
|
-
- **Reuse the dashboard chart bundle** — `components/dashboard-report-charts.tsx` — `DashboardReportCharts`: flat `KeyMetrics` + middle chart section + period comparison `KeyMetrics` card. **`ChartsOverview`**
|
|
133
|
-
- **Data tab canvas charts**
|
|
99
|
+
- **Reuse the dashboard chart bundle** — `components/dashboard-report-charts.tsx` — `DashboardReportCharts`: flat `KeyMetrics` + middle chart section + period comparison `KeyMetrics` card. **`ChartsOverview`** is the default middle section for `/dashboard`. Hubs pass **`chartsSection={<MyDashboardChartsSection rows={tableState.rows} />}`** so charts reflect the hub's own row set. Reference: **`LibraryDashboardChartsSection`** in `components/library-dashboard-charts.tsx`. Chart **style** can follow `ChartVariantProvider` when using `ChartsOverview`.
|
|
100
|
+
- **Data tab canvas charts** share **`ChartFigure`**, **`ChartCard`**, and **`ChartDataTable`** with `charts-overview.tsx`. **Layout** is stored in one place: **`lib/data-view-dashboard-storage.ts`** under a per-hub scope (see `AGENTS.md` §4.3). **Keyboard-selected bars/slices** must use **`lib/chart-keyboard-selection.ts`** (`activeBar` / `activeShape`) so behavior matches the gallery — not opacity-only `Cell` dimming.
|
|
134
101
|
|
|
135
102
|
## Persistence
|
|
136
103
|
|
|
137
|
-
- **Page-level** (`lib/data-list-persistence.ts`, key `exxat-ds:data-list:page:v1`): `displayOptions`, `showMetrics`, `tabs`, `activeTabId`. Loaded in `
|
|
138
|
-
- **Per–lifecycle tab** (key `exxat-ds:data-list:lifecycle:v1:<filterId>`): sort, search, filters, group by, column order/hidden/widths/pins/wrap, column menu search map, row height, gridlines, filter bar visibility, search popover, conditional rules, pagination toggle and page/size. Hydrated in `
|
|
104
|
+
- **Page-level** (`lib/data-list-persistence.ts`, key `exxat-ds:data-list:page:v1`): `displayOptions`, `showMetrics`, `tabs`, `activeTabId`. Loaded in `PlacementsClient` with `useLayoutEffect`, saved debounced on change. `ListPageTemplate` runs in **controlled** mode when `tabs` / `onTabsChange` / `activeTabId` / `onActiveTabChange` are passed.
|
|
105
|
+
- **Per–lifecycle tab** (key `exxat-ds:data-list:lifecycle:v1:<filterId>`): sort, search, filters, group by, column order/hidden/widths/pins/wrap, column menu search map, row height, gridlines, filter bar visibility, search popover, conditional rules, pagination toggle and page/size. Hydrated in `PlacementsTable` with `useLayoutEffect`; saved debounced when those fields change.
|
|
139
106
|
|
|
140
|
-
To add a new page: copy the `
|
|
107
|
+
To add a new page: copy the `PlacementsClient` pattern (controlled `ListPageTemplate` + storage key namespace) or call `schedulePageSave` / `scheduleLifecycleSave` with your own keys.
|
|
141
108
|
|
|
142
109
|
## Rules of thumb
|
|
143
110
|
|
|
@@ -165,13 +132,13 @@ Below the threshold, these may be omitted unless the page is a primary data hub
|
|
|
165
132
|
|
|
166
133
|
## Data pages: primary CTA + More + Export
|
|
167
134
|
|
|
168
|
-
If the page **has exportable data** (rows, members,
|
|
135
|
+
If the page **has exportable data** (rows, members, library items, etc.), follow the **Library** header pattern:
|
|
169
136
|
|
|
170
|
-
1. **Primary action** — One default (filled) button for the main task (e.g. **New
|
|
137
|
+
1. **Primary action** — One default (filled) button for the main task (e.g. **New question**, **Invite collaborator**, **Add token**). Do **not** use `variant="outline"` for that primary action.
|
|
171
138
|
2. **More (⋯)** — An outline **icon** button opening a menu that includes **Export** (and other overflow actions). Wire **Export** to `ExportDrawer` (or equivalent).
|
|
172
139
|
3. **Subtitle** — Prefer a short line with **count + freshness** (e.g. `24 records · Last updated now`), matching `PlacementsPageHeader`.
|
|
173
140
|
|
|
174
|
-
Reference: `components/
|
|
141
|
+
Reference: `components/library-page-header.tsx`, `components/library-hub-client.tsx`.
|
|
175
142
|
|
|
176
143
|
---
|
|
177
144
|
|
|
@@ -181,13 +148,11 @@ Reference: `components/placements-page-header.tsx`, `components/team-page-header
|
|
|
181
148
|
|
|
182
149
|
**When to use a new page (route):** The flow is **primary**, **long-form**, **multi-step**, or should have its **own URL** / bookmark / history **without** the parent page behind it — e.g. full create/edit, wizards, or detail that *is* the task.
|
|
183
150
|
|
|
184
|
-
**
|
|
185
|
-
|
|
186
|
-
**Rule of thumb:** **Context + quick** → **drawer**; **blocking short choice** → **dialog**; **primary / long / wizard / settings** → **focused workflow route** (or other dedicated page).
|
|
151
|
+
**Rule of thumb:** **Context + quick** → **drawer**; **blocking short choice** → **dialog**; **otherwise** → **new page**.
|
|
187
152
|
|
|
188
153
|
**Modal vs side panel (same route):** When the overlay stays on the same URL, prefer **`docs/drawer-vs-dialog-pattern.md`** and **`.cursor/rules/exxat-drawer-vs-dialog.mdc`** — drawers keep the hub visible; dialogs trap focus for confirms.
|
|
189
154
|
|
|
190
|
-
Canonical rules: **`AGENTS.md` §6.4**,
|
|
155
|
+
Canonical rules: **`AGENTS.md` §6.4**, root **`.cursor/rules/exxat-page-vs-drawer.mdc`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**.
|
|
191
156
|
|
|
192
157
|
---
|
|
193
158
|
|
|
@@ -195,7 +160,7 @@ Canonical rules: **`AGENTS.md` §6.4**, **§14**, root **`.cursor/rules/exxat-pa
|
|
|
195
160
|
|
|
196
161
|
When a route is a **primary** destination in nav (main hub for an entity) **and** the dataset is **large** or **highly interactive**:
|
|
197
162
|
|
|
198
|
-
- Use the **primary page template**: `ListPageTemplate` (tabs, metrics strip, export drawer at template level) + data client pattern as in **`
|
|
163
|
+
- Use the **primary page template**: `ListPageTemplate` (tabs, metrics strip, export drawer at template level) + data client pattern as in **`PlacementsClient`** / **`PlacementsTable`** — not a minimal `PageHeader`-only layout.
|
|
199
164
|
- Smaller satellite pages may use **`PageHeader` + section content**; once the dataset grows past the dense-list threshold, add the toolbar rules above and consider promoting to the full template if the page becomes a main hub.
|
|
200
165
|
|
|
201
166
|
---
|
|
@@ -207,7 +172,7 @@ When a route is a **primary** destination in nav (main hub for an entity) **and*
|
|
|
207
172
|
- [ ] **>10 items** → search, filter, sort, properties (per surface type above).
|
|
208
173
|
- [ ] **Has data to export** → **More** menu with **Export** + shared `ExportDrawer` pattern.
|
|
209
174
|
- [ ] **Primary + large / main hub** → `ListPageTemplate`-style shell where applicable.
|
|
210
|
-
- [ ] **Page vs drawer vs dialog (§6.4)** — Quick with parent **context** → drawer/sheet; **blocking** confirm → **dialog**; primary or long flows → **
|
|
175
|
+
- [ ] **Page vs drawer vs dialog (§6.4)** — Quick with parent **context** → drawer/sheet; **blocking** confirm → **dialog**; primary or long flows → **new route** (`docs/drawer-vs-dialog-pattern.md`).
|
|
211
176
|
- [ ] **Primary button** → `Button` default variant (`size="lg"` for parity with Placements), not outline.
|
|
212
177
|
- [ ] **Dashboard view tab** → `KeyMetrics` + shared KPI helpers from **`tableState.rows`**; no duplicate one-off metric cards.
|
|
213
178
|
- [ ] **Data view charts** → `ChartFigure` + `chart-keyboard-selection`; layout persistence via **`data-view-dashboard-storage`** (see `AGENTS.md` §4.3).
|
|
@@ -24,7 +24,7 @@ List hubs and the main dashboard mix view use **`KeyMetrics variant="flat"`** as
|
|
|
24
24
|
|
|
25
25
|
## MUST NOT
|
|
26
26
|
|
|
27
|
-
- Add **`--key-metrics-flat-band-linear`** back into `flatBandStyle` or hub inline styles (e.g.
|
|
27
|
+
- Add **`--key-metrics-flat-band-linear`** back into `flatBandStyle` or hub inline styles (e.g. library hub hero).
|
|
28
28
|
- Use **`variant="card"`** on **`ListPageTemplate`** metrics when the design calls for a **flat strip** on the page background.
|
|
29
29
|
- Duplicate KPI numbers in ad-hoc **`Card`** grids on the same hub.
|
|
30
30
|
- Set **`variant="mutedSuffix"`** on product wordmarks to grey out the **suffix** in dark mode — suffix stays **Exxat pink** (`wordmarkColor`); see **`lib/product-brand.ts`**.
|
|
@@ -42,7 +42,7 @@ Dark mode (`.dark`): same rules — transparent cells, radial glow only, no line
|
|
|
42
42
|
|
|
43
43
|
## Reference implementations
|
|
44
44
|
|
|
45
|
-
- `components/
|
|
45
|
+
- `components/library-client.tsx` — `KeyMetrics variant="flat" metricsSingleRow`
|
|
46
46
|
- `components/dashboard-tabs.tsx` — mix view flat band + insight
|
|
47
47
|
- `components/placements-client.tsx`, `team-client.tsx`, `compliance-client.tsx` — list hub metrics slot
|
|
48
48
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Shell surface elevation (sidebar · secondary panel · page)
|
|
2
2
|
|
|
3
3
|
> **Tokens:** `app/globals.css` — `--sidebar`, `--secondary-panel-bg`, `--background`, `--brand-tint*`.
|
|
4
|
-
> **Shell:** `components/templates/nested-secondary-panel-shell.tsx` — `bg-secondary-panel-bg
|
|
4
|
+
> **Shell:** `components/templates/nested-secondary-panel-shell.tsx` — `bg-[var(--secondary-panel-bg)]`.
|
|
5
5
|
> **Cursor:** `.cursor/rules/exxat-primary-nav-secondary-panel.mdc` · `.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md`
|
|
6
6
|
|
|
7
7
|
## Stack (back → front)
|
|
@@ -24,16 +24,14 @@
|
|
|
24
24
|
## OKLCH formulas (dark)
|
|
25
25
|
|
|
26
26
|
```css
|
|
27
|
-
--secondary-panel-bg: color-mix(in oklch, var(--
|
|
27
|
+
--secondary-panel-bg: color-mix(in oklch, var(--card) 32%, var(--brand-tint) 68%);
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
**Do not** mix with light-mode **`--brand-tint`** in dark — product theme classes keep a light **`--brand-tint`** for logos/KPI glow; the secondary rail must use **`--sidebar-accent`** so the Library panel stays on-hue and dark.
|
|
31
|
-
|
|
32
30
|
Per-product **dark** theme blocks (`.theme-one.dark`, `.theme-prism.dark`, …) set **`--brand-tint-light`** where needed so mixes stay on-hue.
|
|
33
31
|
|
|
34
32
|
## Implementation
|
|
35
33
|
|
|
36
|
-
- **`NestedSecondaryPanelShell`** — `bg-secondary-panel-bg
|
|
34
|
+
- **`NestedSecondaryPanelShell`** — `bg-[var(--secondary-panel-bg)]`, `ring-sidebar-border` (not generic `ring-border` alone).
|
|
37
35
|
- **Do not** set secondary panel to `bg-sidebar` (same as level 0 — loses elevation).
|
|
38
36
|
- **Do not** use `color-mix(… var(--sidebar) …)` without brand tokens if it drifts from active product theme.
|
|
39
37
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/** Single-date calendar for table filters (YYYY-MM-DD). */
|
|
4
|
+
declare function FilterDateCalendar({ valueYmd, onChangeYmd, label, }: {
|
|
5
|
+
valueYmd: string | undefined;
|
|
6
|
+
onChangeYmd: (ymd: string | undefined) => void;
|
|
7
|
+
label: string;
|
|
8
|
+
}): react_jsx_runtime.JSX.Element;
|
|
9
|
+
|
|
10
|
+
export { FilterDateCalendar };
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React2 from 'react';
|
|
3
|
+
import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from 'lucide-react';
|
|
4
|
+
import { getDefaultClassNames, DayPicker } from 'react-day-picker';
|
|
5
|
+
import { clsx } from 'clsx';
|
|
6
|
+
import { twMerge } from 'tailwind-merge';
|
|
7
|
+
import { cva } from 'class-variance-authority';
|
|
8
|
+
import { Slot } from 'radix-ui';
|
|
9
|
+
import { jsx } from 'react/jsx-runtime';
|
|
10
|
+
|
|
11
|
+
function cn(...inputs) {
|
|
12
|
+
return twMerge(clsx(inputs));
|
|
13
|
+
}
|
|
14
|
+
var buttonVariants = cva(
|
|
15
|
+
"group/button inline-flex shrink-0 cursor-pointer items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
16
|
+
{
|
|
17
|
+
variants: {
|
|
18
|
+
variant: {
|
|
19
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
20
|
+
outline: "border-input bg-background hover:bg-interactive-hover hover:text-interactive-hover-foreground aria-expanded:bg-interactive-hover aria-expanded:text-interactive-hover-foreground dark:bg-input/15 dark:hover:bg-input/25",
|
|
21
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
22
|
+
ghost: "hover:bg-interactive-hover hover:text-interactive-hover-foreground aria-expanded:bg-interactive-hover aria-expanded:text-interactive-hover-foreground dark:hover:bg-interactive-hover-subtle",
|
|
23
|
+
destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
24
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
25
|
+
},
|
|
26
|
+
size: {
|
|
27
|
+
default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pe-2.5 has-data-[icon=inline-start]:ps-2.5",
|
|
28
|
+
xs: "h-6 gap-1 px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
29
|
+
sm: "h-8 gap-1 px-3 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2 [&_svg:not([class*='size-'])]:size-3.5",
|
|
30
|
+
lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pe-3.5 has-data-[icon=inline-start]:ps-3.5",
|
|
31
|
+
icon: "size-9",
|
|
32
|
+
"icon-xs": "size-6 in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
33
|
+
"icon-sm": "size-8 in-data-[slot=button-group]:rounded-lg",
|
|
34
|
+
"icon-lg": "size-10"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: "default",
|
|
39
|
+
size: "default"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
var Button = React2.forwardRef(({ className, variant = "default", size = "default", asChild = false, ...props }, ref) => {
|
|
44
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
45
|
+
return /* @__PURE__ */ jsx(
|
|
46
|
+
Comp,
|
|
47
|
+
{
|
|
48
|
+
ref,
|
|
49
|
+
"data-slot": "button",
|
|
50
|
+
"data-variant": variant,
|
|
51
|
+
"data-size": size,
|
|
52
|
+
className: cn(buttonVariants({ variant, size }), className),
|
|
53
|
+
...props
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
Button.displayName = "Button";
|
|
58
|
+
function Calendar({
|
|
59
|
+
className,
|
|
60
|
+
classNames,
|
|
61
|
+
showOutsideDays = true,
|
|
62
|
+
captionLayout = "label",
|
|
63
|
+
buttonVariant = "ghost",
|
|
64
|
+
formatters,
|
|
65
|
+
components,
|
|
66
|
+
...props
|
|
67
|
+
}) {
|
|
68
|
+
const defaultClassNames = getDefaultClassNames();
|
|
69
|
+
return /* @__PURE__ */ jsx(
|
|
70
|
+
DayPicker,
|
|
71
|
+
{
|
|
72
|
+
showOutsideDays,
|
|
73
|
+
className: cn(
|
|
74
|
+
"group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
|
75
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
76
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
77
|
+
className
|
|
78
|
+
),
|
|
79
|
+
captionLayout,
|
|
80
|
+
formatters: {
|
|
81
|
+
formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
|
|
82
|
+
...formatters
|
|
83
|
+
},
|
|
84
|
+
classNames: {
|
|
85
|
+
root: cn("w-fit", defaultClassNames.root),
|
|
86
|
+
months: cn(
|
|
87
|
+
"relative flex flex-col gap-4 md:flex-row",
|
|
88
|
+
defaultClassNames.months
|
|
89
|
+
),
|
|
90
|
+
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
|
|
91
|
+
nav: cn(
|
|
92
|
+
"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
|
|
93
|
+
defaultClassNames.nav
|
|
94
|
+
),
|
|
95
|
+
button_previous: cn(
|
|
96
|
+
buttonVariants({ variant: buttonVariant }),
|
|
97
|
+
"size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
|
|
98
|
+
defaultClassNames.button_previous
|
|
99
|
+
),
|
|
100
|
+
button_next: cn(
|
|
101
|
+
buttonVariants({ variant: buttonVariant }),
|
|
102
|
+
"size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
|
|
103
|
+
defaultClassNames.button_next
|
|
104
|
+
),
|
|
105
|
+
month_caption: cn(
|
|
106
|
+
"flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
|
|
107
|
+
defaultClassNames.month_caption
|
|
108
|
+
),
|
|
109
|
+
dropdowns: cn(
|
|
110
|
+
"flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
|
|
111
|
+
defaultClassNames.dropdowns
|
|
112
|
+
),
|
|
113
|
+
dropdown_root: cn(
|
|
114
|
+
"relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50",
|
|
115
|
+
defaultClassNames.dropdown_root
|
|
116
|
+
),
|
|
117
|
+
dropdown: cn(
|
|
118
|
+
"absolute inset-0 bg-popover opacity-0",
|
|
119
|
+
defaultClassNames.dropdown
|
|
120
|
+
),
|
|
121
|
+
caption_label: cn(
|
|
122
|
+
"font-medium select-none",
|
|
123
|
+
captionLayout === "label" ? "text-sm" : "flex h-8 items-center gap-1 rounded-md pe-1 ps-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
|
|
124
|
+
defaultClassNames.caption_label
|
|
125
|
+
),
|
|
126
|
+
table: "w-full border-collapse",
|
|
127
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
128
|
+
weekday: cn(
|
|
129
|
+
"flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none",
|
|
130
|
+
defaultClassNames.weekday
|
|
131
|
+
),
|
|
132
|
+
week: cn("mt-2 flex w-full", defaultClassNames.week),
|
|
133
|
+
week_number_header: cn(
|
|
134
|
+
"w-(--cell-size) select-none",
|
|
135
|
+
defaultClassNames.week_number_header
|
|
136
|
+
),
|
|
137
|
+
week_number: cn(
|
|
138
|
+
"text-[0.8rem] text-muted-foreground select-none",
|
|
139
|
+
defaultClassNames.week_number
|
|
140
|
+
),
|
|
141
|
+
day: cn(
|
|
142
|
+
"group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md",
|
|
143
|
+
props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md" : "[&:first-child[data-selected=true]_button]:rounded-l-md",
|
|
144
|
+
defaultClassNames.day
|
|
145
|
+
),
|
|
146
|
+
range_start: cn(
|
|
147
|
+
"rounded-l-md bg-accent",
|
|
148
|
+
defaultClassNames.range_start
|
|
149
|
+
),
|
|
150
|
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
|
151
|
+
range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
|
|
152
|
+
today: cn(
|
|
153
|
+
"rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none",
|
|
154
|
+
defaultClassNames.today
|
|
155
|
+
),
|
|
156
|
+
outside: cn(
|
|
157
|
+
"text-muted-foreground aria-selected:text-muted-foreground",
|
|
158
|
+
defaultClassNames.outside
|
|
159
|
+
),
|
|
160
|
+
disabled: cn(
|
|
161
|
+
"text-muted-foreground opacity-50",
|
|
162
|
+
defaultClassNames.disabled
|
|
163
|
+
),
|
|
164
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
165
|
+
...classNames
|
|
166
|
+
},
|
|
167
|
+
components: {
|
|
168
|
+
Root: ({ className: className2, rootRef, ...props2 }) => {
|
|
169
|
+
return /* @__PURE__ */ jsx(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
"data-slot": "calendar",
|
|
173
|
+
ref: rootRef,
|
|
174
|
+
className: cn(className2),
|
|
175
|
+
...props2
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
},
|
|
179
|
+
Chevron: ({ className: className2, orientation, ...props2 }) => {
|
|
180
|
+
if (orientation === "left") {
|
|
181
|
+
return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
|
|
182
|
+
}
|
|
183
|
+
if (orientation === "right") {
|
|
184
|
+
return /* @__PURE__ */ jsx(
|
|
185
|
+
ChevronRightIcon,
|
|
186
|
+
{
|
|
187
|
+
className: cn("size-4", className2),
|
|
188
|
+
...props2
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
|
|
193
|
+
},
|
|
194
|
+
DayButton: CalendarDayButton,
|
|
195
|
+
WeekNumber: ({ children, ...props2 }) => {
|
|
196
|
+
return /* @__PURE__ */ jsx("td", { ...props2, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
|
|
197
|
+
},
|
|
198
|
+
...components
|
|
199
|
+
},
|
|
200
|
+
...props
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
function CalendarDayButton({
|
|
205
|
+
className,
|
|
206
|
+
day,
|
|
207
|
+
modifiers,
|
|
208
|
+
...props
|
|
209
|
+
}) {
|
|
210
|
+
const defaultClassNames = getDefaultClassNames();
|
|
211
|
+
const ref = React2.useRef(null);
|
|
212
|
+
React2.useEffect(() => {
|
|
213
|
+
if (modifiers.focused) ref.current?.focus();
|
|
214
|
+
}, [modifiers.focused]);
|
|
215
|
+
return /* @__PURE__ */ jsx(
|
|
216
|
+
Button,
|
|
217
|
+
{
|
|
218
|
+
ref,
|
|
219
|
+
variant: "ghost",
|
|
220
|
+
size: "icon",
|
|
221
|
+
"data-day": day.date.toLocaleDateString(),
|
|
222
|
+
"data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
|
|
223
|
+
"data-range-start": modifiers.range_start,
|
|
224
|
+
"data-range-end": modifiers.range_end,
|
|
225
|
+
"data-range-middle": modifiers.range_middle,
|
|
226
|
+
className: cn(
|
|
227
|
+
"flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70",
|
|
228
|
+
defaultClassNames.day,
|
|
229
|
+
className
|
|
230
|
+
),
|
|
231
|
+
...props
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/lib/date-filter.ts
|
|
237
|
+
function ymdToLocalDate(ymd) {
|
|
238
|
+
if (!ymd || !/^\d{4}-\d{2}-\d{2}$/.test(ymd)) return void 0;
|
|
239
|
+
const [y, m, d] = ymd.split("-").map(Number);
|
|
240
|
+
return new Date(y, m - 1, d, 12, 0, 0, 0);
|
|
241
|
+
}
|
|
242
|
+
function localDateToYmd(d) {
|
|
243
|
+
const y = d.getFullYear();
|
|
244
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
245
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
246
|
+
return `${y}-${m}-${day}`;
|
|
247
|
+
}
|
|
248
|
+
function FilterDateCalendar({
|
|
249
|
+
valueYmd,
|
|
250
|
+
onChangeYmd,
|
|
251
|
+
label
|
|
252
|
+
}) {
|
|
253
|
+
const [timeZone, setTimeZone] = React2.useState();
|
|
254
|
+
React2.useEffect(() => {
|
|
255
|
+
setTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
256
|
+
}, []);
|
|
257
|
+
return /* @__PURE__ */ jsx(
|
|
258
|
+
"div",
|
|
259
|
+
{
|
|
260
|
+
className: "rounded-lg border border-border overflow-hidden",
|
|
261
|
+
role: "group",
|
|
262
|
+
"aria-label": label,
|
|
263
|
+
children: /* @__PURE__ */ jsx(
|
|
264
|
+
Calendar,
|
|
265
|
+
{
|
|
266
|
+
mode: "single",
|
|
267
|
+
selected: ymdToLocalDate(valueYmd),
|
|
268
|
+
onSelect: (d) => onChangeYmd(d ? localDateToYmd(d) : void 0),
|
|
269
|
+
captionLayout: "dropdown",
|
|
270
|
+
timeZone,
|
|
271
|
+
className: "rounded-lg border-0"
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export { FilterDateCalendar };
|
|
279
|
+
//# sourceMappingURL=filter-date-calendar.js.map
|
|
280
|
+
//# sourceMappingURL=filter-date-calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/button.tsx","../../../src/components/ui/calendar.tsx","../../../src/lib/date-filter.ts","../../../src/components/data-table/filter-date-calendar.tsx"],"names":["React","jsx","className","props","React3"],"mappings":"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","file":"filter-date-calendar.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 cursor-pointer items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-input bg-background hover:bg-interactive-hover hover:text-interactive-hover-foreground aria-expanded:bg-interactive-hover aria-expanded:text-interactive-hover-foreground dark:bg-input/15 dark:hover:bg-input/25\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-interactive-hover hover:text-interactive-hover-foreground aria-expanded:bg-interactive-hover aria-expanded:text-interactive-hover-foreground dark:hover:bg-interactive-hover-subtle\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pe-2.5 has-data-[icon=inline-start]:ps-2.5\",\n xs: \"h-6 gap-1 px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pe-1.5 has-data-[icon=inline-start]:ps-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pe-2 has-data-[icon=inline-start]:ps-2 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pe-3.5 has-data-[icon=inline-start]:ps-3.5\",\n icon: \"size-9\",\n \"icon-xs\":\n \"size-6 in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-8 in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nconst Button = React.forwardRef<\n HTMLButtonElement,\n React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }\n>(({ className, variant = \"default\", size = \"default\", asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n ref={ref}\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n )\n})\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n","\"use client\"\n\nimport * as React from \"react\"\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from \"lucide-react\"\nimport {\n DayPicker,\n getDefaultClassNames,\n type DayButton,\n} from \"react-day-picker\"\n\nimport { cn } from \"../../lib/utils\"\nimport { Button, buttonVariants } from \"./button\"\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = \"label\",\n buttonVariant = \"ghost\",\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker> & {\n buttonVariant?: React.ComponentProps<typeof Button>[\"variant\"]\n}) {\n const defaultClassNames = getDefaultClassNames()\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n \"group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent\",\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className\n )}\n captionLayout={captionLayout}\n formatters={{\n formatMonthDropdown: (date) =>\n date.toLocaleString(\"default\", { month: \"short\" }),\n ...formatters,\n }}\n classNames={{\n root: cn(\"w-fit\", defaultClassNames.root),\n months: cn(\n \"relative flex flex-col gap-4 md:flex-row\",\n defaultClassNames.months\n ),\n month: cn(\"flex w-full flex-col gap-4\", defaultClassNames.month),\n nav: cn(\n \"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1\",\n defaultClassNames.nav\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) p-0 select-none aria-disabled:opacity-50\",\n defaultClassNames.button_previous\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) p-0 select-none aria-disabled:opacity-50\",\n defaultClassNames.button_next\n ),\n month_caption: cn(\n \"flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)\",\n defaultClassNames.month_caption\n ),\n dropdowns: cn(\n \"flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium\",\n defaultClassNames.dropdowns\n ),\n dropdown_root: cn(\n \"relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50\",\n defaultClassNames.dropdown_root\n ),\n dropdown: cn(\n \"absolute inset-0 bg-popover opacity-0\",\n defaultClassNames.dropdown\n ),\n caption_label: cn(\n \"font-medium select-none\",\n captionLayout === \"label\"\n ? \"text-sm\"\n : \"flex h-8 items-center gap-1 rounded-md pe-1 ps-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground\",\n defaultClassNames.caption_label\n ),\n table: \"w-full border-collapse\",\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n weekday: cn(\n \"flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none\",\n defaultClassNames.weekday\n ),\n week: cn(\"mt-2 flex w-full\", defaultClassNames.week),\n week_number_header: cn(\n \"w-(--cell-size) select-none\",\n defaultClassNames.week_number_header\n ),\n week_number: cn(\n \"text-[0.8rem] text-muted-foreground select-none\",\n defaultClassNames.week_number\n ),\n day: cn(\n \"group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md\",\n props.showWeekNumber\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-md\"\n : \"[&:first-child[data-selected=true]_button]:rounded-l-md\",\n defaultClassNames.day\n ),\n range_start: cn(\n \"rounded-l-md bg-accent\",\n defaultClassNames.range_start\n ),\n range_middle: cn(\"rounded-none\", defaultClassNames.range_middle),\n range_end: cn(\"rounded-r-md bg-accent\", defaultClassNames.range_end),\n today: cn(\n \"rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none\",\n defaultClassNames.today\n ),\n outside: cn(\n \"text-muted-foreground aria-selected:text-muted-foreground\",\n defaultClassNames.outside\n ),\n disabled: cn(\n \"text-muted-foreground opacity-50\",\n defaultClassNames.disabled\n ),\n hidden: cn(\"invisible\", defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n Root: ({ className, rootRef, ...props }) => {\n return (\n <div\n data-slot=\"calendar\"\n ref={rootRef}\n className={cn(className)}\n {...props}\n />\n )\n },\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === \"left\") {\n return (\n <ChevronLeftIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n if (orientation === \"right\") {\n return (\n <ChevronRightIcon\n className={cn(\"size-4\", className)}\n {...props}\n />\n )\n }\n\n return (\n <ChevronDownIcon className={cn(\"size-4\", className)} {...props} />\n )\n },\n DayButton: CalendarDayButton,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">\n {children}\n </div>\n </td>\n )\n },\n ...components,\n }}\n {...props}\n />\n )\n}\n\nfunction CalendarDayButton({\n className,\n day,\n modifiers,\n ...props\n}: React.ComponentProps<typeof DayButton>) {\n const defaultClassNames = getDefaultClassNames()\n\n const ref = React.useRef<HTMLButtonElement>(null)\n React.useEffect(() => {\n if (modifiers.focused) ref.current?.focus()\n }, [modifiers.focused])\n\n return (\n <Button\n ref={ref}\n variant=\"ghost\"\n size=\"icon\"\n data-day={day.date.toLocaleDateString()}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n className={cn(\n \"flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70\",\n defaultClassNames.day,\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Calendar, CalendarDayButton }\n","/**\n * Format any date string (ISO, MM/DD/YYYY, \"Mar 15 2026\", etc.) into the\n * app-wide display format: MM/DD/YYYY.\n * Returns \"—\" for empty / unparseable values.\n */\nexport function formatDateUS(raw: string | null | undefined): string {\n if (!raw || raw.trim() === \"—\" || raw.trim() === \"-\") return \"—\"\n // Already MM/DD/YYYY — return as-is\n if (/^\\d{2}\\/\\d{2}\\/\\d{4}$/.test(raw.trim())) return raw.trim()\n const d = new Date(raw)\n if (Number.isNaN(d.getTime())) return raw\n const m = String(d.getMonth() + 1).padStart(2, \"0\")\n const day = String(d.getDate()).padStart(2, \"0\")\n const y = d.getFullYear()\n return `${m}/${day}/${y}`\n}\n\n/** Format a `Date` with local calendar fields as MM/DD/YYYY (avoids UTC drift from `toISOString()`). */\nexport function formatDateFromDate(raw: Date | null | undefined): string {\n if (!raw || Number.isNaN(raw.getTime())) return \"—\"\n const m = String(raw.getMonth() + 1).padStart(2, \"0\")\n const day = String(raw.getDate()).padStart(2, \"0\")\n const y = raw.getFullYear()\n return `${m}/${day}/${y}`\n}\n\n/**\n * Format a Date (or ISO string) into \"MM/DD/YYYY hh:mm AM/PM EST\".\n * Time zone label is always appended as the literal string \"EST\" (display only).\n */\nexport function formatDateTimeUS(raw: Date | string | null | undefined): string {\n if (!raw) return \"—\"\n const d = raw instanceof Date ? raw : new Date(raw)\n if (Number.isNaN(d.getTime())) return String(raw)\n const m = String(d.getMonth() + 1).padStart(2, \"0\")\n const day = String(d.getDate()).padStart(2, \"0\")\n const y = d.getFullYear()\n let h = d.getHours()\n const min = String(d.getMinutes()).padStart(2, \"0\")\n const ampm = h >= 12 ? \"PM\" : \"AM\"\n h = h % 12 || 12\n return `${m}/${day}/${y} ${String(h).padStart(2, \"0\")}:${min} ${ampm} EST`\n}\n\n/** Parse a human-readable date string into YYYY-MM-DD for comparison (local timezone). */\nexport function parseRowDateToYmd(raw: string): string | null {\n const t = raw.trim()\n if (!t || t === \"—\" || t === \"-\") return null\n const d = new Date(t)\n if (Number.isNaN(d.getTime())) return null\n const y = d.getFullYear()\n const m = String(d.getMonth() + 1).padStart(2, \"0\")\n const day = String(d.getDate()).padStart(2, \"0\")\n return `${y}-${m}-${day}`\n}\n\n/** Format YYYY-MM-DD for filter chip labels (MM/DD/YYYY). */\nexport function formatYmdForDisplay(ymd: string): string {\n const d = ymdToLocalDate(ymd)\n if (!d) return ymd\n return formatDateFromDate(d)\n}\n\n/** Local noon to avoid timezone shifting the calendar day. */\nexport function ymdToLocalDate(ymd: string | undefined): Date | undefined {\n if (!ymd || !/^\\d{4}-\\d{2}-\\d{2}$/.test(ymd)) return undefined\n const [y, m, d] = ymd.split(\"-\").map(Number)\n return new Date(y, m - 1, d, 12, 0, 0, 0)\n}\n\nexport function localDateToYmd(d: Date): string {\n const y = d.getFullYear()\n const m = String(d.getMonth() + 1).padStart(2, \"0\")\n const day = String(d.getDate()).padStart(2, \"0\")\n return `${y}-${m}-${day}`\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Calendar } from \"../ui/calendar\"\nimport { localDateToYmd, ymdToLocalDate } from \"../../lib/date-filter\"\n\n/** Single-date calendar for table filters (YYYY-MM-DD). */\nexport function FilterDateCalendar({\n valueYmd,\n onChangeYmd,\n label,\n}: {\n valueYmd: string | undefined\n onChangeYmd: (ymd: string | undefined) => void\n label: string\n}) {\n const [timeZone, setTimeZone] = React.useState<string | undefined>()\n React.useEffect(() => {\n setTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone)\n }, [])\n\n return (\n <div\n className=\"rounded-lg border border-border overflow-hidden\"\n role=\"group\"\n aria-label={label}\n >\n <Calendar\n mode=\"single\"\n selected={ymdToLocalDate(valueYmd)}\n onSelect={(d) => onChangeYmd(d ? localDateToYmd(d) : undefined)}\n captionLayout=\"dropdown\"\n timeZone={timeZone}\n className=\"rounded-lg border-0\"\n />\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { FilterTextMask } from '../../lib/table-properties-types.js';
|
|
3
|
+
|
|
4
|
+
declare function FilterTextValueInput({ id, mask, value, onValueChange, "aria-label": ariaLabel, placeholder, className, autoFocus, }: {
|
|
5
|
+
id?: string;
|
|
6
|
+
mask?: FilterTextMask;
|
|
7
|
+
value: string;
|
|
8
|
+
onValueChange: (next: string) => void;
|
|
9
|
+
"aria-label": string;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
autoFocus?: boolean;
|
|
13
|
+
}): react_jsx_runtime.JSX.Element;
|
|
14
|
+
|
|
15
|
+
export { FilterTextValueInput };
|