@nadicodeai/ui 12.1.102 → 12.1.103
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/dist/components/accordion.d.ts +38 -12
- package/dist/components/accordion.d.ts.map +1 -1
- package/dist/components/accordion.js +36 -15
- package/dist/components/account-menu.js +2 -2
- package/dist/components/action-menu.d.ts +20 -19
- package/dist/components/action-menu.d.ts.map +1 -1
- package/dist/components/action-menu.js +22 -15
- package/dist/components/action-status.d.ts +14 -10
- package/dist/components/action-status.d.ts.map +1 -1
- package/dist/components/action-status.js +14 -10
- package/dist/components/activity-calendar.d.ts +3 -1
- package/dist/components/activity-calendar.d.ts.map +1 -1
- package/dist/components/activity-calendar.js +16 -2
- package/dist/components/activity-feed.d.ts +2 -2
- package/dist/components/activity-feed.d.ts.map +1 -1
- package/dist/components/activity-feed.js +14 -5
- package/dist/components/agent-card.d.ts +11 -5
- package/dist/components/agent-card.d.ts.map +1 -1
- package/dist/components/agent-card.js +13 -7
- package/dist/components/agent-list-row.js +1 -1
- package/dist/components/agent-orb-appearance.d.ts +7 -1
- package/dist/components/agent-orb-appearance.d.ts.map +1 -1
- package/dist/components/agent-orb-appearance.js +26 -0
- package/dist/components/agent-profile.d.ts +8 -7
- package/dist/components/agent-profile.d.ts.map +1 -1
- package/dist/components/agent-profile.js +6 -6
- package/dist/components/alert-dialog.d.ts +25 -16
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +30 -18
- package/dist/components/alert.d.ts +1 -1
- package/dist/components/avatar.d.ts +83 -17
- package/dist/components/avatar.d.ts.map +1 -1
- package/dist/components/avatar.js +89 -23
- package/dist/components/badge.d.ts +59 -8
- package/dist/components/badge.d.ts.map +1 -1
- package/dist/components/badge.js +57 -14
- package/dist/components/breadcrumb.d.ts +18 -7
- package/dist/components/breadcrumb.d.ts.map +1 -1
- package/dist/components/breadcrumb.js +37 -13
- package/dist/components/button-group.d.ts +12 -15
- package/dist/components/button-group.d.ts.map +1 -1
- package/dist/components/button-group.js +13 -17
- package/dist/components/button.d.ts +126 -23
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +164 -39
- package/dist/components/calendar.d.ts +26 -15
- package/dist/components/calendar.d.ts.map +1 -1
- package/dist/components/calendar.js +60 -46
- package/dist/components/card-row.d.ts +13 -5
- package/dist/components/card-row.d.ts.map +1 -1
- package/dist/components/card-row.js +24 -10
- package/dist/components/card.d.ts +6 -12
- package/dist/components/card.d.ts.map +1 -1
- package/dist/components/card.js +11 -16
- package/dist/components/carousel.d.ts +3 -3
- package/dist/components/carousel.d.ts.map +1 -1
- package/dist/components/carousel.js +7 -7
- package/dist/components/catalog-drawer.d.ts +7 -7
- package/dist/components/catalog-drawer.d.ts.map +1 -1
- package/dist/components/catalog-drawer.js +6 -6
- package/dist/components/chart-area-stacked.d.ts +1 -1
- package/dist/components/chart-area-stacked.d.ts.map +1 -1
- package/dist/components/chart-area-stacked.js +4 -4
- package/dist/components/chart-axis.d.ts +14 -1
- package/dist/components/chart-axis.d.ts.map +1 -1
- package/dist/components/chart-axis.js +11 -1
- package/dist/components/chart-bar-horizontal.d.ts +2 -2
- package/dist/components/chart-bar-horizontal.d.ts.map +1 -1
- package/dist/components/chart-bar-horizontal.js +14 -5
- package/dist/components/chart-bar-multiple.d.ts +1 -1
- package/dist/components/chart-bar-multiple.d.ts.map +1 -1
- package/dist/components/chart-bar-multiple.js +3 -3
- package/dist/components/chart-bar-stacked.d.ts +1 -1
- package/dist/components/chart-bar-stacked.d.ts.map +1 -1
- package/dist/components/chart-bar-stacked.js +3 -3
- package/dist/components/chart-card.d.ts +17 -6
- package/dist/components/chart-card.d.ts.map +1 -1
- package/dist/components/chart-card.js +11 -4
- package/dist/components/chart-date-range-control.d.ts +18 -9
- package/dist/components/chart-date-range-control.d.ts.map +1 -1
- package/dist/components/chart-date-range-control.js +43 -47
- package/dist/components/chart-sparkline.d.ts +4 -3
- package/dist/components/chart-sparkline.d.ts.map +1 -1
- package/dist/components/chart-sparkline.js +6 -5
- package/dist/components/check-counts.d.ts +44 -0
- package/dist/components/check-counts.d.ts.map +1 -0
- package/dist/components/check-counts.js +51 -0
- package/dist/components/checkbox.d.ts +39 -11
- package/dist/components/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox.js +38 -11
- package/dist/components/choicebox.d.ts +96 -0
- package/dist/components/choicebox.d.ts.map +1 -0
- package/dist/components/choicebox.js +113 -0
- package/dist/components/clearable-input.d.ts +57 -0
- package/dist/components/clearable-input.d.ts.map +1 -0
- package/dist/components/clearable-input.js +58 -0
- package/dist/components/code-block.d.ts +77 -17
- package/dist/components/code-block.d.ts.map +1 -1
- package/dist/components/code-block.js +85 -15
- package/dist/components/collapsible.d.ts +27 -10
- package/dist/components/collapsible.d.ts.map +1 -1
- package/dist/components/collapsible.js +24 -9
- package/dist/components/collection-filters.d.ts +3 -1
- package/dist/components/collection-filters.d.ts.map +1 -1
- package/dist/components/collection-filters.js +7 -9
- package/dist/components/collection-page.d.ts +31 -10
- package/dist/components/collection-page.d.ts.map +1 -1
- package/dist/components/collection-page.js +14 -13
- package/dist/components/collection-search.d.ts +32 -10
- package/dist/components/collection-search.d.ts.map +1 -1
- package/dist/components/collection-search.js +24 -13
- package/dist/components/collection-sort.d.ts.map +1 -1
- package/dist/components/collection-sort.js +2 -2
- package/dist/components/collection-toolbar.d.ts +5 -2
- package/dist/components/collection-toolbar.d.ts.map +1 -1
- package/dist/components/collection-toolbar.js +7 -4
- package/dist/components/combobox.d.ts +97 -22
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +80 -28
- package/dist/components/command.d.ts +34 -21
- package/dist/components/command.d.ts.map +1 -1
- package/dist/components/command.js +33 -25
- package/dist/components/confirm-dialog.d.ts +23 -6
- package/dist/components/confirm-dialog.d.ts.map +1 -1
- package/dist/components/confirm-dialog.js +32 -13
- package/dist/components/context-menu.d.ts +14 -10
- package/dist/components/context-menu.d.ts.map +1 -1
- package/dist/components/context-menu.js +17 -12
- package/dist/components/copy-button.d.ts +5 -2
- package/dist/components/copy-button.d.ts.map +1 -1
- package/dist/components/copy-button.js +16 -8
- package/dist/components/data-table.d.ts +120 -54
- package/dist/components/data-table.d.ts.map +1 -1
- package/dist/components/data-table.js +163 -92
- package/dist/components/desktop-shell.d.ts +4 -2
- package/dist/components/desktop-shell.d.ts.map +1 -1
- package/dist/components/desktop-shell.js +3 -3
- package/dist/components/dialog.d.ts +63 -24
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js +52 -31
- package/dist/components/disclosure-row.d.ts +1 -2
- package/dist/components/disclosure-row.d.ts.map +1 -1
- package/dist/components/disclosure-row.js +1 -2
- package/dist/components/disclosure.d.ts +1 -1
- package/dist/components/disclosure.js +1 -1
- package/dist/components/drawer.d.ts +33 -12
- package/dist/components/drawer.d.ts.map +1 -1
- package/dist/components/drawer.js +47 -35
- package/dist/components/dropdown-menu.d.ts +59 -14
- package/dist/components/dropdown-menu.d.ts.map +1 -1
- package/dist/components/dropdown-menu.js +58 -26
- package/dist/components/empty-state.d.ts +35 -12
- package/dist/components/empty-state.d.ts.map +1 -1
- package/dist/components/empty-state.js +35 -17
- package/dist/components/entry-scene.d.ts +4 -4
- package/dist/components/entry-scene.d.ts.map +1 -1
- package/dist/components/entry-scene.js +2 -2
- package/dist/components/field.d.ts +44 -14
- package/dist/components/field.d.ts.map +1 -1
- package/dist/components/field.js +49 -20
- package/dist/components/file-diff.d.ts.map +1 -1
- package/dist/components/file-diff.js +3 -4
- package/dist/components/form-dialog.d.ts +7 -7
- package/dist/components/form-dialog.d.ts.map +1 -1
- package/dist/components/form-dialog.js +13 -11
- package/dist/components/form-drawer.d.ts +10 -7
- package/dist/components/form-drawer.d.ts.map +1 -1
- package/dist/components/form-drawer.js +11 -10
- package/dist/components/gauge.d.ts +64 -0
- package/dist/components/gauge.d.ts.map +1 -0
- package/dist/components/gauge.js +73 -0
- package/dist/components/hover-card.d.ts +72 -14
- package/dist/components/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card.js +51 -17
- package/dist/components/identity-mark.d.ts +8 -1
- package/dist/components/identity-mark.d.ts.map +1 -1
- package/dist/components/identity-mark.js +31 -5
- package/dist/components/input-group.d.ts +44 -21
- package/dist/components/input-group.d.ts.map +1 -1
- package/dist/components/input-group.js +74 -27
- package/dist/components/input.d.ts +64 -12
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +51 -15
- package/dist/components/item.d.ts +37 -15
- package/dist/components/item.d.ts.map +1 -1
- package/dist/components/item.js +41 -22
- package/dist/components/kbd.d.ts +49 -13
- package/dist/components/kbd.d.ts.map +1 -1
- package/dist/components/kbd.js +115 -16
- package/dist/components/kpi-card.d.ts +12 -4
- package/dist/components/kpi-card.d.ts.map +1 -1
- package/dist/components/kpi-card.js +13 -4
- package/dist/components/label.d.ts +17 -10
- package/dist/components/label.d.ts.map +1 -1
- package/dist/components/label.js +18 -11
- package/dist/components/library-shelf.d.ts +6 -6
- package/dist/components/library-shelf.d.ts.map +1 -1
- package/dist/components/library-shelf.js +5 -5
- package/dist/components/load-more-button.d.ts +35 -0
- package/dist/components/load-more-button.d.ts.map +1 -0
- package/dist/components/load-more-button.js +26 -0
- package/dist/components/message-notice.d.ts +8 -13
- package/dist/components/message-notice.d.ts.map +1 -1
- package/dist/components/message-notice.js +25 -22
- package/dist/components/middle-truncate.d.ts +33 -0
- package/dist/components/middle-truncate.d.ts.map +1 -0
- package/dist/components/middle-truncate.js +72 -0
- package/dist/components/multi-select.d.ts +94 -0
- package/dist/components/multi-select.d.ts.map +1 -0
- package/dist/components/multi-select.js +132 -0
- package/dist/components/native-select.d.ts +37 -13
- package/dist/components/native-select.d.ts.map +1 -1
- package/dist/components/native-select.js +27 -11
- package/dist/components/notice-banner.d.ts +17 -10
- package/dist/components/notice-banner.d.ts.map +1 -1
- package/dist/components/notice-banner.js +12 -11
- package/dist/components/numbered-steps.d.ts +10 -4
- package/dist/components/numbered-steps.d.ts.map +1 -1
- package/dist/components/numbered-steps.js +9 -7
- package/dist/components/object-page.d.ts +40 -14
- package/dist/components/object-page.d.ts.map +1 -1
- package/dist/components/object-page.js +12 -10
- package/dist/components/object-workspace.d.ts +29 -10
- package/dist/components/object-workspace.d.ts.map +1 -1
- package/dist/components/object-workspace.js +18 -8
- package/dist/components/overview-page.d.ts +2 -2
- package/dist/components/overview-page.d.ts.map +1 -1
- package/dist/components/overview-page.js +8 -7
- package/dist/components/page-actions.d.ts +28 -8
- package/dist/components/page-actions.d.ts.map +1 -1
- package/dist/components/page-actions.js +22 -25
- package/dist/components/page-header.d.ts +11 -4
- package/dist/components/page-header.d.ts.map +1 -1
- package/dist/components/page-header.js +10 -5
- package/dist/components/pending-label.d.ts +6 -5
- package/dist/components/pending-label.d.ts.map +1 -1
- package/dist/components/pending-label.js +14 -6
- package/dist/components/picture-label.d.ts +2 -2
- package/dist/components/picture-label.d.ts.map +1 -1
- package/dist/components/picture-label.js +3 -3
- package/dist/components/portal-sidebar-frame.d.ts +9 -21
- package/dist/components/portal-sidebar-frame.d.ts.map +1 -1
- package/dist/components/portal-sidebar-frame.js +13 -27
- package/dist/components/progress-checklist.d.ts +46 -0
- package/dist/components/progress-checklist.d.ts.map +1 -0
- package/dist/components/progress-checklist.js +46 -0
- package/dist/components/progress.d.ts +48 -8
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/progress.js +92 -16
- package/dist/components/prose.d.ts +19 -0
- package/dist/components/prose.d.ts.map +1 -0
- package/dist/components/prose.js +29 -0
- package/dist/components/radio-group.d.ts +51 -12
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +42 -12
- package/dist/components/reading-column.js +1 -1
- package/dist/components/record-identity.d.ts +6 -5
- package/dist/components/record-identity.d.ts.map +1 -1
- package/dist/components/record-identity.js +12 -3
- package/dist/components/record-list.d.ts +117 -27
- package/dist/components/record-list.d.ts.map +1 -1
- package/dist/components/record-list.js +185 -55
- package/dist/components/record-time.d.ts +20 -7
- package/dist/components/record-time.d.ts.map +1 -1
- package/dist/components/record-time.js +38 -19
- package/dist/components/resizable.d.ts +7 -5
- package/dist/components/resizable.d.ts.map +1 -1
- package/dist/components/resizable.js +6 -6
- package/dist/components/scope-switcher.d.ts +2 -0
- package/dist/components/scope-switcher.d.ts.map +1 -1
- package/dist/components/scope-switcher.js +2 -2
- package/dist/components/scroll-area.d.ts +47 -11
- package/dist/components/scroll-area.d.ts.map +1 -1
- package/dist/components/scroll-area.js +72 -14
- package/dist/components/segmented-control.d.ts +82 -0
- package/dist/components/segmented-control.d.ts.map +1 -0
- package/dist/components/segmented-control.js +90 -0
- package/dist/components/select.d.ts +55 -15
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +62 -19
- package/dist/components/separator.d.ts +12 -5
- package/dist/components/separator.d.ts.map +1 -1
- package/dist/components/separator.js +11 -6
- package/dist/components/settings-facts.d.ts +34 -14
- package/dist/components/settings-facts.d.ts.map +1 -1
- package/dist/components/settings-facts.js +21 -12
- package/dist/components/settings-page.d.ts +4 -4
- package/dist/components/settings-page.js +5 -5
- package/dist/components/settings-section.d.ts +160 -34
- package/dist/components/settings-section.d.ts.map +1 -1
- package/dist/components/settings-section.js +92 -39
- package/dist/components/sheet.d.ts +47 -16
- package/dist/components/sheet.d.ts.map +1 -1
- package/dist/components/sheet.js +40 -19
- package/dist/components/sidebar-sections.d.ts +16 -12
- package/dist/components/sidebar-sections.d.ts.map +1 -1
- package/dist/components/sidebar-sections.js +30 -15
- package/dist/components/sidebar.d.ts +117 -21
- package/dist/components/sidebar.d.ts.map +1 -1
- package/dist/components/sidebar.js +180 -55
- package/dist/components/skeleton.d.ts +54 -8
- package/dist/components/skeleton.d.ts.map +1 -1
- package/dist/components/skeleton.js +44 -9
- package/dist/components/slider.d.ts +53 -11
- package/dist/components/slider.d.ts.map +1 -1
- package/dist/components/slider.js +71 -17
- package/dist/components/snippet.d.ts +57 -0
- package/dist/components/snippet.d.ts.map +1 -0
- package/dist/components/snippet.js +60 -0
- package/dist/components/sonner.d.ts +13 -14
- package/dist/components/sonner.d.ts.map +1 -1
- package/dist/components/sonner.js +25 -22
- package/dist/components/status-badge.d.ts +37 -11
- package/dist/components/status-badge.d.ts.map +1 -1
- package/dist/components/status-badge.js +63 -15
- package/dist/components/status-dot.d.ts +42 -11
- package/dist/components/status-dot.d.ts.map +1 -1
- package/dist/components/status-dot.js +40 -11
- package/dist/components/switch.d.ts +43 -12
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/switch.js +42 -12
- package/dist/components/table-card.d.ts +21 -12
- package/dist/components/table-card.d.ts.map +1 -1
- package/dist/components/table-card.js +17 -9
- package/dist/components/table-layouts.d.ts +40 -8
- package/dist/components/table-layouts.d.ts.map +1 -1
- package/dist/components/table-layouts.js +52 -8
- package/dist/components/table-value.d.ts +4 -3
- package/dist/components/table-value.d.ts.map +1 -1
- package/dist/components/table-value.js +6 -5
- package/dist/components/table.d.ts +62 -25
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/table.js +62 -26
- package/dist/components/tabs.d.ts +86 -17
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +93 -22
- package/dist/components/text-link.d.ts +4 -1
- package/dist/components/text-link.d.ts.map +1 -1
- package/dist/components/text-link.js +4 -1
- package/dist/components/text-with-copy-button.d.ts +30 -0
- package/dist/components/text-with-copy-button.d.ts.map +1 -0
- package/dist/components/text-with-copy-button.js +32 -0
- package/dist/components/textarea.d.ts +40 -10
- package/dist/components/textarea.d.ts.map +1 -1
- package/dist/components/textarea.js +50 -11
- package/dist/components/theme-mode-switcher.d.ts +18 -1
- package/dist/components/theme-mode-switcher.d.ts.map +1 -1
- package/dist/components/theme-mode-switcher.js +20 -2
- package/dist/components/toggle-group.d.ts +28 -8
- package/dist/components/toggle-group.d.ts.map +1 -1
- package/dist/components/toggle-group.js +12 -6
- package/dist/components/toggle.d.ts +6 -3
- package/dist/components/toggle.d.ts.map +1 -1
- package/dist/components/toggle.js +10 -7
- package/dist/components/tooltip.d.ts +43 -12
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +45 -16
- package/dist/components/trend-badge.js +1 -1
- package/dist/components/update-card.js +1 -1
- package/dist/eslint/index.js +82 -0
- package/dist/eslint/rules/badge-is-static-label.js +93 -0
- package/dist/eslint/rules/button-icon-slot.js +102 -0
- package/dist/eslint/rules/button-link-for-navigation.js +146 -0
- package/dist/eslint/rules/button-no-aria-label-with-text.js +75 -0
- package/dist/eslint/rules/button-type-roles-only-in-buttons.js +83 -0
- package/dist/eslint/rules/choice-control-has-a-name.js +98 -0
- package/dist/eslint/rules/choice-group-in-fieldset.js +86 -0
- package/dist/eslint/rules/command-shortcut-single-owner.js +118 -0
- package/dist/eslint/rules/confirm-dialog-words.js +63 -0
- package/dist/eslint/rules/data-table-one-unsized-column.js +96 -0
- package/dist/eslint/rules/destructive-action-placement.js +69 -0
- package/dist/eslint/rules/disabled-choice-says-why.js +71 -0
- package/dist/eslint/rules/ellipsis-opens-a-dialog.js +110 -0
- package/dist/eslint/rules/input-group-owners.js +155 -0
- package/dist/eslint/rules/kbd-children-no-modifier-text.js +128 -0
- package/dist/eslint/rules/literal-text.js +41 -0
- package/dist/eslint/rules/middle-truncate-placement.js +69 -0
- package/dist/eslint/rules/no-bare-button-label.js +55 -0
- package/dist/eslint/rules/no-control-in-read-only-surface.js +106 -0
- package/dist/eslint/rules/no-hand-built-busy.js +104 -0
- package/dist/eslint/rules/no-hand-built-theme-picker.js +144 -0
- package/dist/eslint/rules/no-hand-built-tile.js +41 -0
- package/dist/eslint/rules/no-hand-formatted-date.js +87 -0
- package/dist/eslint/rules/no-hand-stacked-avatars.js +67 -0
- package/dist/eslint/rules/no-nested-collapse.js +60 -0
- package/dist/eslint/rules/no-search-in-form.js +47 -0
- package/dist/eslint/rules/no-shadcn-appearance-override.js +2 -16
- package/dist/eslint/rules/no-shell-prompt-in-snippet.js +74 -0
- package/dist/eslint/rules/no-stock-error-words.js +56 -0
- package/dist/eslint/rules/no-tooltip-around-labelled-field.js +72 -0
- package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +57 -0
- package/dist/eslint/rules/one-submenu-level.js +43 -0
- package/dist/eslint/rules/one-toast-per-flow.js +91 -0
- package/dist/eslint/rules/option-count.js +167 -0
- package/dist/eslint/rules/page-command-link-not-render.js +43 -0
- package/dist/eslint/rules/progress-needs-name.js +57 -0
- package/dist/eslint/rules/settings-limit-in-footer.js +94 -0
- package/dist/eslint/rules/skeleton-in-region.js +80 -0
- package/dist/eslint/rules/sortable-heading-uses-sort.js +79 -0
- package/dist/eslint/rules/table-cell-inset-owner.js +107 -0
- package/dist/eslint/rules/tabs-selection-is-controlled.js +47 -0
- package/dist/eslint/rules/tooltip-only-arrow.js +38 -0
- package/dist/eslint/rules/tooltip-trigger-accessible-name.js +114 -0
- package/dist/eslint/strict-design-system.js +21 -7
- package/dist/index.d.ts +13 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -13
- package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
- package/dist/internal/assistant-ui/attachment.js +2 -2
- package/dist/internal/assistant-ui/reasoning.d.ts +1 -1
- package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tool-fallback.js +1 -1
- package/dist/internal/assistant-ui/tool-group.d.ts +1 -1
- package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +2 -3
- package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -1
- package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
- package/dist/internal/catalog-list.js +2 -2
- package/dist/internal/collection-note.d.ts +23 -0
- package/dist/internal/collection-note.d.ts.map +1 -0
- package/dist/internal/collection-note.js +17 -0
- package/dist/internal/collection-rail.d.ts +57 -0
- package/dist/internal/collection-rail.d.ts.map +1 -0
- package/dist/internal/collection-rail.js +33 -0
- package/dist/internal/company-logo.d.ts +18 -0
- package/dist/internal/company-logo.d.ts.map +1 -0
- package/dist/internal/company-logo.js +14 -0
- package/dist/internal/control-name.d.ts +12 -0
- package/dist/internal/control-name.d.ts.map +1 -0
- package/dist/internal/control-name.js +1 -0
- package/dist/internal/diff-line.d.ts +9 -0
- package/dist/internal/diff-line.d.ts.map +1 -0
- package/dist/internal/diff-line.js +8 -0
- package/dist/internal/empty.d.ts +8 -4
- package/dist/internal/empty.d.ts.map +1 -1
- package/dist/internal/empty.js +14 -8
- package/dist/internal/field-frame.d.ts +33 -0
- package/dist/internal/field-frame.d.ts.map +1 -0
- package/dist/internal/field-frame.js +20 -0
- package/dist/internal/final-focus.d.ts +8 -0
- package/dist/internal/final-focus.d.ts.map +1 -0
- package/dist/internal/final-focus.js +10 -0
- package/dist/internal/footer-strip.d.ts.map +1 -1
- package/dist/internal/footer-strip.js +3 -1
- package/dist/internal/form-submit.d.ts +9 -5
- package/dist/internal/form-submit.d.ts.map +1 -1
- package/dist/internal/form-submit.js +31 -2
- package/dist/internal/input-box.d.ts +26 -0
- package/dist/internal/input-box.d.ts.map +1 -0
- package/dist/internal/input-box.js +59 -0
- package/dist/internal/menu-surface.d.ts +10 -3
- package/dist/internal/menu-surface.d.ts.map +1 -1
- package/dist/internal/menu-surface.js +10 -3
- package/dist/internal/notice.d.ts +25 -0
- package/dist/internal/notice.d.ts.map +1 -0
- package/dist/internal/notice.js +33 -0
- package/dist/internal/overlay-stem.d.ts +5 -0
- package/dist/internal/overlay-stem.d.ts.map +1 -0
- package/dist/internal/overlay-stem.js +7 -0
- package/dist/internal/phone-sheet.d.ts +4 -0
- package/dist/internal/phone-sheet.d.ts.map +1 -0
- package/dist/internal/phone-sheet.js +2 -0
- package/dist/internal/present-content.d.ts +3 -0
- package/dist/internal/present-content.d.ts.map +1 -0
- package/dist/internal/present-content.js +1 -0
- package/dist/internal/record-menu-items.d.ts +4 -3
- package/dist/internal/record-menu-items.d.ts.map +1 -1
- package/dist/internal/record-menu-items.js +21 -6
- package/dist/internal/settings-save.d.ts +9 -2
- package/dist/internal/settings-save.d.ts.map +1 -1
- package/dist/internal/settings-save.js +9 -6
- package/dist/internal/table-compact-line.d.ts +38 -0
- package/dist/internal/table-compact-line.d.ts.map +1 -0
- package/dist/internal/table-compact-line.js +35 -0
- package/dist/internal/title-when-cut.d.ts +8 -0
- package/dist/internal/title-when-cut.d.ts.map +1 -0
- package/dist/internal/title-when-cut.js +22 -0
- package/dist/internal/unsaved-guard.d.ts +18 -0
- package/dist/internal/unsaved-guard.d.ts.map +1 -0
- package/dist/internal/unsaved-guard.js +31 -0
- package/dist/lib/merge-tokens.generated.js +2 -2
- package/dist/showcase/foundations.d.ts.map +1 -1
- package/dist/showcase/foundations.js +10 -2
- package/dist/showcase/specimens/actions.d.ts +2 -0
- package/dist/showcase/specimens/actions.d.ts.map +1 -1
- package/dist/showcase/specimens/actions.js +30 -5
- package/dist/showcase/specimens/charts.d.ts.map +1 -1
- package/dist/showcase/specimens/charts.js +22 -13
- package/dist/showcase/specimens/choices.d.ts +14 -3
- package/dist/showcase/specimens/choices.d.ts.map +1 -1
- package/dist/showcase/specimens/choices.js +93 -13
- package/dist/showcase/specimens/compositions.d.ts.map +1 -1
- package/dist/showcase/specimens/compositions.js +136 -23
- package/dist/showcase/specimens/data.d.ts +12 -7
- package/dist/showcase/specimens/data.d.ts.map +1 -1
- package/dist/showcase/specimens/data.js +139 -35
- package/dist/showcase/specimens/feedback.d.ts +2 -0
- package/dist/showcase/specimens/feedback.d.ts.map +1 -1
- package/dist/showcase/specimens/feedback.js +39 -15
- package/dist/showcase/specimens/index.d.ts +20 -12
- package/dist/showcase/specimens/index.d.ts.map +1 -1
- package/dist/showcase/specimens/inputs.d.ts +4 -2
- package/dist/showcase/specimens/inputs.d.ts.map +1 -1
- package/dist/showcase/specimens/inputs.js +62 -19
- package/dist/showcase/specimens/menus.d.ts +0 -1
- package/dist/showcase/specimens/menus.d.ts.map +1 -1
- package/dist/showcase/specimens/menus.js +47 -17
- package/dist/showcase/specimens/navigation.d.ts +6 -4
- package/dist/showcase/specimens/navigation.d.ts.map +1 -1
- package/dist/showcase/specimens/navigation.js +61 -32
- package/dist/showcase/specimens/other.d.ts +1 -3
- package/dist/showcase/specimens/other.d.ts.map +1 -1
- package/dist/showcase/specimens/other.js +17 -13
- package/dist/showcase/specimens/status.d.ts +4 -1
- package/dist/showcase/specimens/status.d.ts.map +1 -1
- package/dist/showcase/specimens/status.js +64 -11
- package/dist/showcase/usage.generated.d.ts +1 -1
- package/dist/showcase/usage.generated.d.ts.map +1 -1
- package/dist/showcase/usage.generated.js +632 -544
- package/dist/standalone/index.js +1 -1
- package/dist/styles/components.css +13 -13
- package/dist/styles/globals.css +25 -0
- package/package.json +2 -3
- package/dist/components/approval-row.d.ts +0 -34
- package/dist/components/approval-row.d.ts.map +0 -1
- package/dist/components/approval-row.js +0 -27
- package/dist/components/channel-view.d.ts +0 -112
- package/dist/components/channel-view.d.ts.map +0 -1
- package/dist/components/channel-view.js +0 -84
- package/dist/components/dashboard-shell.d.ts +0 -51
- package/dist/components/dashboard-shell.d.ts.map +0 -1
- package/dist/components/dashboard-shell.js +0 -89
- package/dist/components/direction.d.ts +0 -2
- package/dist/components/direction.d.ts.map +0 -1
- package/dist/components/direction.js +0 -1
- package/dist/components/expandable-block.d.ts +0 -20
- package/dist/components/expandable-block.d.ts.map +0 -1
- package/dist/components/expandable-block.js +0 -32
- package/dist/components/form.d.ts +0 -42
- package/dist/components/form.d.ts.map +0 -1
- package/dist/components/form.js +0 -91
- package/dist/components/label-system.d.ts +0 -17
- package/dist/components/label-system.d.ts.map +0 -1
- package/dist/components/label-system.js +0 -21
- package/dist/components/memory-item.d.ts +0 -21
- package/dist/components/memory-item.d.ts.map +0 -1
- package/dist/components/memory-item.js +0 -18
- package/dist/components/menubar.d.ts +0 -43
- package/dist/components/menubar.d.ts.map +0 -1
- package/dist/components/menubar.js +0 -69
- package/dist/components/navigation-menu.d.ts +0 -26
- package/dist/components/navigation-menu.d.ts.map +0 -1
- package/dist/components/navigation-menu.js +0 -45
- package/dist/components/pagination.d.ts +0 -33
- package/dist/components/pagination.d.ts.map +0 -1
- package/dist/components/pagination.js +0 -41
- package/dist/components/plugin-slot-boundary.d.ts +0 -42
- package/dist/components/plugin-slot-boundary.d.ts.map +0 -1
- package/dist/components/plugin-slot-boundary.js +0 -41
- package/dist/components/status-row.d.ts +0 -32
- package/dist/components/status-row.d.ts.map +0 -1
- package/dist/components/status-row.js +0 -35
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from "react";
|
|
2
|
+
import { HoverCardContent } from "./hover-card.js";
|
|
1
3
|
export type RecordTimeProps = {
|
|
2
|
-
/** When it happened. */
|
|
3
|
-
at: Date | number | string;
|
|
4
|
+
/** When it happened; null or a time that names no moment draws `children`, or nothing. */
|
|
5
|
+
at: Date | number | string | null | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* A state the time cannot describe, such as "Just now", "Pending" or "Queued". It replaces the
|
|
8
|
+
* sentence while `at` names a moment, and stands alone, without a card, while it does not.
|
|
9
|
+
*/
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
/** Which side of the time the card opens on; above by default. */
|
|
12
|
+
side?: ComponentProps<typeof HoverCardContent>["side"];
|
|
4
13
|
/** The person's language; the runtime's when left out. */
|
|
5
14
|
locale?: string;
|
|
6
15
|
/**
|
|
@@ -31,11 +40,15 @@ export declare function recordDate(at: Date | number | string | null | undefined
|
|
|
31
40
|
* says what, or the time of day in a feed's time column.
|
|
32
41
|
*
|
|
33
42
|
* @family Data
|
|
34
|
-
* @when
|
|
35
|
-
*
|
|
36
|
-
* @
|
|
37
|
-
*
|
|
38
|
-
* @
|
|
43
|
+
* @when "Use `<RelativeTimeCard>` anywhere a recent timestamp appears in scannable surfaces: `Table` cells, `Entity` rows, deploy lists, activity feeds." (https://vercel.com/geist/relative-time-card)
|
|
44
|
+
* Ours: `RelativeTimeCard` is `RecordTime`: the moment a record was made, changed or last ran, in its row or its facts, and the time of each event in an ActivityFeed or a RunTimeline step (`mode="clock"`).
|
|
45
|
+
* @instead "For a static date in body prose past 7 days, render `Mar 14, 2026` directly." (https://vercel.com/geist/relative-time-card)
|
|
46
|
+
* Ours: a date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product (*Took 4 min*).
|
|
47
|
+
* @behaviour "The hover card already shows absolute UTC and local time, so don’t duplicate that copy elsewhere on the row." (https://vercel.com/geist/relative-time-card)
|
|
48
|
+
* Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing.
|
|
49
|
+
* @words "Pass `date` as a number (Unix ms or epoch)." "Don’t pre-format the value, and don’t replace `children` with a formatted string." "The component’s short formatter is the canonical form (`2m`, `5h`, `Yesterday`)." "Don’t append `ago` after the component." "The formatter already produces `2m ago` / `5h ago`, so `<RelativeTimeCard /> ago` reads as `2m ago ago`." "Use `children` only for non-time labels (`Just now`, `Pending`, `Queued`) where the formatter can’t describe the state." "Pair with a leading label when the row is ambiguous on its own: `Last deploy <RelativeTimeCard date={ts} />`." (https://vercel.com/geist/relative-time-card)
|
|
50
|
+
* Ours: `at` takes a Date, epoch milliseconds or an ISO string, never a display string such as *3 hours ago*. The reading is the locale's long form (*3 hours ago*, *12 Sep*), not `2m`. The product writes the sentence through `phrase` (*Updated {when}*, *Ran {when}*), so *ago* is never added after it; the clock needs no words. The package formats every date with the person's `locale`.
|
|
51
|
+
* @access Ours: a `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
|
|
39
52
|
*/
|
|
40
53
|
export declare function RecordTime(props: RecordTimeProps): import("react").JSX.Element | null;
|
|
41
54
|
//# sourceMappingURL=record-time.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-time.d.ts","sourceRoot":"","sources":["../../src/components/record-time.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"record-time.d.ts","sourceRoot":"","sources":["../../src/components/record-time.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAa,gBAAgB,EAAoB,MAAM,yBAAyB,CAAC;AAYxF,MAAM,MAAM,eAAe,GAAG;IAC5B,0FAA0F;IAC1F,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9C;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,kEAAkE;IAClE,IAAI,CAAC,EAAE,cAAc,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;IACvD,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,CACA;IACE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAClC;AACH,gEAAgE;GAC9D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CACpB,CAAC;AAEF,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,IAAI,EACR,MAAM,CAAC,EAAE,MAAM,EACf,GAAG,SAAa,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAcR;AAeD,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAIrF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,sCAyEhD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from "./hover-card.js";
|
|
4
4
|
import { useHydrated } from "../hooks/use-hydrated.js";
|
|
5
5
|
const DAY = 86_400_000;
|
|
@@ -27,6 +27,17 @@ export function formatRecordTime(at, locale, now = Date.now(), timeZone) {
|
|
|
27
27
|
shown.year = "numeric";
|
|
28
28
|
return new Intl.DateTimeFormat(locale, shown).format(at);
|
|
29
29
|
}
|
|
30
|
+
function offsetLabel(at, locale, timeZone) {
|
|
31
|
+
return new Intl.DateTimeFormat(locale, { timeZone, timeZoneName: "shortOffset" })
|
|
32
|
+
.formatToParts(at)
|
|
33
|
+
.find((part) => part.type === "timeZoneName")?.value;
|
|
34
|
+
}
|
|
35
|
+
function exactMoment(at, locale, timeZone) {
|
|
36
|
+
return {
|
|
37
|
+
date: new Intl.DateTimeFormat(locale, { dateStyle: "long", timeZone }).format(at),
|
|
38
|
+
time: new Intl.DateTimeFormat(locale, { timeStyle: "medium", timeZone }).format(at),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
30
41
|
/** The moment `at` names, or null when it names none, such as an empty or malformed time. */
|
|
31
42
|
export function recordDate(at) {
|
|
32
43
|
if (at == null)
|
|
@@ -39,35 +50,43 @@ export function recordDate(at) {
|
|
|
39
50
|
* says what, or the time of day in a feed's time column.
|
|
40
51
|
*
|
|
41
52
|
* @family Data
|
|
42
|
-
* @when
|
|
43
|
-
*
|
|
44
|
-
* @
|
|
45
|
-
*
|
|
46
|
-
* @
|
|
53
|
+
* @when "Use `<RelativeTimeCard>` anywhere a recent timestamp appears in scannable surfaces: `Table` cells, `Entity` rows, deploy lists, activity feeds." (https://vercel.com/geist/relative-time-card)
|
|
54
|
+
* Ours: `RelativeTimeCard` is `RecordTime`: the moment a record was made, changed or last ran, in its row or its facts, and the time of each event in an ActivityFeed or a RunTimeline step (`mode="clock"`).
|
|
55
|
+
* @instead "For a static date in body prose past 7 days, render `Mar 14, 2026` directly." (https://vercel.com/geist/relative-time-card)
|
|
56
|
+
* Ours: a date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product (*Took 4 min*).
|
|
57
|
+
* @behaviour "The hover card already shows absolute UTC and local time, so don’t duplicate that copy elsewhere on the row." (https://vercel.com/geist/relative-time-card)
|
|
58
|
+
* Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing.
|
|
59
|
+
* @words "Pass `date` as a number (Unix ms or epoch)." "Don’t pre-format the value, and don’t replace `children` with a formatted string." "The component’s short formatter is the canonical form (`2m`, `5h`, `Yesterday`)." "Don’t append `ago` after the component." "The formatter already produces `2m ago` / `5h ago`, so `<RelativeTimeCard /> ago` reads as `2m ago ago`." "Use `children` only for non-time labels (`Just now`, `Pending`, `Queued`) where the formatter can’t describe the state." "Pair with a leading label when the row is ambiguous on its own: `Last deploy <RelativeTimeCard date={ts} />`." (https://vercel.com/geist/relative-time-card)
|
|
60
|
+
* Ours: `at` takes a Date, epoch milliseconds or an ISO string, never a display string such as *3 hours ago*. The reading is the locale's long form (*3 hours ago*, *12 Sep*), not `2m`. The product writes the sentence through `phrase` (*Updated {when}*, *Ran {when}*), so *ago* is never added after it; the clock needs no words. The package formats every date with the person's `locale`.
|
|
61
|
+
* @access Ours: a `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
|
|
47
62
|
*/
|
|
48
63
|
export function RecordTime(props) {
|
|
49
64
|
const { at, locale, now } = props;
|
|
50
65
|
const hydrated = useHydrated();
|
|
51
66
|
const timeZone = props.timeZone ?? (hydrated ? undefined : "UTC");
|
|
52
67
|
const date = recordDate(at);
|
|
53
|
-
if (!date)
|
|
54
|
-
return null;
|
|
55
|
-
|
|
68
|
+
if (!date) {
|
|
69
|
+
return props.children ? (_jsx("span", { className: "whitespace-nowrap text-muted-foreground", "data-slot": "record-time", children: props.children })) : null;
|
|
70
|
+
}
|
|
71
|
+
const local = new Intl.DateTimeFormat(locale, {
|
|
56
72
|
dateStyle: "long",
|
|
57
73
|
timeStyle: "medium",
|
|
58
74
|
timeZone,
|
|
59
|
-
});
|
|
60
|
-
const local = inZone.format(date);
|
|
61
|
-
const utc = new Intl.DateTimeFormat(locale, {
|
|
62
|
-
dateStyle: "long",
|
|
63
|
-
timeStyle: "medium",
|
|
64
|
-
timeZone: "UTC",
|
|
65
75
|
}).format(date);
|
|
76
|
+
const exactRows = [
|
|
77
|
+
{ id: "utc", zone: "UTC", ...exactMoment(date, locale, "UTC") },
|
|
78
|
+
{
|
|
79
|
+
id: "viewer",
|
|
80
|
+
zone: offsetLabel(date, locale, timeZone) ?? "UTC",
|
|
81
|
+
...exactMoment(date, locale, timeZone),
|
|
82
|
+
},
|
|
83
|
+
];
|
|
66
84
|
const clock = props.mode === "clock";
|
|
67
|
-
const shown =
|
|
68
|
-
|
|
69
|
-
|
|
85
|
+
const shown = props.children ??
|
|
86
|
+
(clock
|
|
87
|
+
? new Intl.DateTimeFormat(locale, { timeStyle: "short", timeZone }).format(date)
|
|
88
|
+
: props.phrase(formatRecordTime(date, locale, now, timeZone)));
|
|
70
89
|
return (_jsxs(HoverCard, { children: [_jsxs(HoverCardTrigger, { render: _jsx("time", { className: clock
|
|
71
90
|
? "whitespace-nowrap tabular-nums text-muted-foreground"
|
|
72
|
-
: "whitespace-nowrap text-muted-foreground", "data-slot": "record-time", dateTime: date.toISOString() }), children: [shown, _jsxs("span", { className: "sr-only", children: [", ", local] })] }), _jsx(HoverCardContent, {
|
|
91
|
+
: "whitespace-nowrap text-muted-foreground", "data-slot": "record-time", dateTime: date.toISOString() }), children: [shown, _jsxs("span", { className: "sr-only", children: [", ", local] })] }), _jsx(HoverCardContent, { side: props.side, sideOffset: 13, children: _jsxs("div", { className: "grid min-w-75 gap-3 text-body-compact", "data-slot": "record-time-exact", children: [_jsx("p", { className: "text-muted-foreground tabular-nums", children: formatRecordTime(date, locale, now, timeZone) }), _jsx("dl", { className: "grid gap-2", children: exactRows.map((row) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("dt", { className: "inline-flex h-4 items-center rounded-xs bg-recessed px-1.5 font-label-mono text-label-mono text-muted-foreground", children: row.zone }), _jsxs("dd", { className: "flex min-w-0 flex-1 items-center justify-between gap-3", children: [_jsx("span", { children: row.date }), _jsx("span", { className: "font-label-mono text-label-mono text-muted-foreground tabular-nums", children: row.time })] })] }, row.id))) })] }) })] }));
|
|
73
92
|
}
|
|
@@ -3,15 +3,17 @@ import * as ResizablePrimitive from "react-resizable-panels";
|
|
|
3
3
|
* Panels a person resizes by dragging the handle between them.
|
|
4
4
|
*
|
|
5
5
|
* @family Other
|
|
6
|
-
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel.
|
|
7
|
-
* @instead The product frame's sidebar resizes through `
|
|
8
|
-
* @behaviour The handle moves on drag and on arrow keys; each panel keeps its minimum and maximum.
|
|
9
|
-
* @words
|
|
10
|
-
* @access The handle is the resizable library's focusable separator.
|
|
6
|
+
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
|
|
7
|
+
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column.
|
|
8
|
+
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum and maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px reach on each side; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else.
|
|
9
|
+
* @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
|
|
10
|
+
* @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
|
|
11
11
|
*/
|
|
12
12
|
declare function ResizablePanelGroup({ className, ...props }: ResizablePrimitive.GroupProps): import("react").JSX.Element;
|
|
13
13
|
declare function ResizablePanel({ ...props }: ResizablePrimitive.PanelProps): import("react").JSX.Element;
|
|
14
14
|
declare function ResizableHandle({ withHandle, className, ...props }: ResizablePrimitive.SeparatorProps & {
|
|
15
|
+
/** Names the handle for assistive technology: "Resize the side panel". */
|
|
16
|
+
"aria-label": string;
|
|
15
17
|
withHandle?: boolean;
|
|
16
18
|
}): import("react").JSX.Element;
|
|
17
19
|
export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../src/components/resizable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,kBAAkB,MAAM,wBAAwB,CAAC;AAI7D;;;;;;;;;GASG;AACH,iBAAS,mBAAmB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BASlF;AAED,iBAAS,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BAElE;AAED,iBAAS,eAAe,CAAC,EACvB,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,cAAc,GAAG;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,+BAaA;AAED,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../src/components/resizable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,kBAAkB,MAAM,wBAAwB,CAAC;AAI7D;;;;;;;;;GASG;AACH,iBAAS,mBAAmB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BASlF;AAED,iBAAS,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,CAAC,UAAU,+BAElE;AAED,iBAAS,eAAe,CAAC,EACvB,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,cAAc,GAAG;IACrC,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,+BAaA;AAED,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -6,11 +6,11 @@ import { cn } from "../lib/utils.js";
|
|
|
6
6
|
* Panels a person resizes by dragging the handle between them.
|
|
7
7
|
*
|
|
8
8
|
* @family Other
|
|
9
|
-
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel.
|
|
10
|
-
* @instead The product frame's sidebar resizes through `
|
|
11
|
-
* @behaviour The handle moves on drag and on arrow keys; each panel keeps its minimum and maximum.
|
|
12
|
-
* @words
|
|
13
|
-
* @access The handle is the resizable library's focusable separator.
|
|
9
|
+
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
|
|
10
|
+
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column.
|
|
11
|
+
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum and maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px reach on each side; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else.
|
|
12
|
+
* @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
|
|
13
|
+
* @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
|
|
14
14
|
*/
|
|
15
15
|
function ResizablePanelGroup({ className, ...props }) {
|
|
16
16
|
return (_jsx(ResizablePrimitive.Group, { "data-slot": "resizable-panel-group", className: cn("flex h-full w-full aria-[orientation=vertical]:flex-col", className), ...props }));
|
|
@@ -19,6 +19,6 @@ function ResizablePanel({ ...props }) {
|
|
|
19
19
|
return _jsx(ResizablePrimitive.Panel, { "data-slot": "resizable-panel", ...props });
|
|
20
20
|
}
|
|
21
21
|
function ResizableHandle({ withHandle, className, ...props }) {
|
|
22
|
-
return (_jsx(ResizablePrimitive.Separator, { "data-slot": "resizable-handle", className: cn("relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90", className), ...props, children: withHandle && _jsx("div", { className: "z-10 flex h-6 w-1 shrink-0 rounded-full bg-border" }) }));
|
|
22
|
+
return (_jsx(ResizablePrimitive.Separator, { "data-slot": "resizable-handle", className: cn("relative flex w-px items-center justify-center bg-border nc-transition-paint data-[separator=active]:bg-ring data-[separator=focus]:bg-ring data-[separator=hover]:bg-ring after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90", className), ...props, children: withHandle && _jsx("div", { className: "z-10 flex h-6 w-1 shrink-0 rounded-full bg-border" }) }));
|
|
23
23
|
}
|
|
24
24
|
export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
|
|
@@ -9,6 +9,8 @@ export type ScopeSwitcherCopy = {
|
|
|
9
9
|
label: string;
|
|
10
10
|
search: string;
|
|
11
11
|
empty: string;
|
|
12
|
+
/** The sentence a screen reader hears as the list narrows, from the catalogue: "3 results". */
|
|
13
|
+
results: (count: number) => string;
|
|
12
14
|
};
|
|
13
15
|
export type ScopeSwitcherProps = {
|
|
14
16
|
value: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-switcher.d.ts","sourceRoot":"","sources":["../../src/components/scope-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"scope-switcher.d.ts","sourceRoot":"","sources":["../../src/components/scope-switcher.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,+FAA+F;IAC/F,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,8DAA8D;IAC9D,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAClD,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,kBAAkB,qBA6FhG"}
|
|
@@ -34,11 +34,11 @@ export function ScopeSwitcher({ value, options, onValueChange, copy, create }) {
|
|
|
34
34
|
onValueChange(next);
|
|
35
35
|
};
|
|
36
36
|
const switchable = options.length > 1 || create !== undefined;
|
|
37
|
-
return (_jsxs("span", { "data-slot": "scope-switcher", className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { "aria-hidden": switchable ? "true" : undefined, className: "text-xs font-medium text-muted-foreground", children: copy.label }), switchable ? (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(Button, { variant: "ghost", "
|
|
37
|
+
return (_jsxs("span", { "data-slot": "scope-switcher", className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { "aria-hidden": switchable ? "true" : undefined, className: "text-xs font-medium text-muted-foreground", children: copy.label }), switchable ? (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(Button, { variant: "ghost", className: "max-w-64", suffix: _jsx(ChevronsUpDown, { "aria-hidden": "true" }) }), children: [_jsxs("span", { className: "sr-only", children: [copy.label, ":"] }), " ", _jsx("span", { className: "truncate", children: currentLabel })] }), _jsxs(PopoverContent, { align: "start", className: "w-72 p-0", initialFocus: search, children: [_jsx(PopoverTitle, { className: "sr-only", children: copy.label }), _jsxs(Command, { label: copy.search, resultCount: copy.results, children: [_jsx(CommandInput, { ref: search, "aria-label": copy.search, placeholder: copy.search }), _jsxs(CommandList, { label: copy.label, children: [_jsx(CommandEmpty, { children: copy.empty }), groups.map(([group, items]) => (_jsx(CommandGroup, { heading: group, children: items.map((option) => (_jsx(CommandItem, { value: option.value, keywords: [
|
|
38
38
|
option.label,
|
|
39
39
|
...(option.group ? [option.group] : []),
|
|
40
40
|
...(option.keywords ?? []),
|
|
41
|
-
], "data-checked": option.value === value, onSelect: () => choose(option.value), children: _jsx("span", { className: "truncate", children: option.label }) }, option.value))) }, group ?? ""))), create ? (_jsxs(_Fragment, { children: [_jsx(CommandSeparator, { alwaysRender: true }), _jsx(CommandGroup, { forceMount: true, children: _jsxs(CommandItem, { value: `create ${create.label}`, forceMount: true, onSelect: () => {
|
|
41
|
+
], "data-checked": option.value === value, onSelect: () => choose(option.value), children: _jsx("span", { className: "truncate", children: option.label }) }, option.value))) }, group ?? ""))), create ? (_jsxs(_Fragment, { children: [_jsx(CommandSeparator, { alwaysRender: true }), _jsx(CommandGroup, { forceMount: true, heading: undefined, children: _jsxs(CommandItem, { value: `create ${create.label}`, forceMount: true, onSelect: () => {
|
|
42
42
|
setOpen(false);
|
|
43
43
|
create.onSelect();
|
|
44
44
|
}, children: [_jsx(Plus, { "aria-hidden": "true" }), create.label] }) })] })) : null] })] })] })] })) : (_jsx("span", { className: "truncate px-3 text-sm", children: currentLabel }))] }));
|
|
@@ -1,18 +1,54 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
|
|
3
|
+
type ButtonLabels = {
|
|
4
|
+
/** Names the move back and what moves, such as "Scroll installations left". */
|
|
5
|
+
previous: string;
|
|
6
|
+
/** Names the move forward and what moves, such as "Scroll installations right". */
|
|
7
|
+
next: string;
|
|
8
|
+
};
|
|
9
|
+
type ScrollAxes = {
|
|
10
|
+
overflow: "y" | "x" | "both";
|
|
11
|
+
buttonLabels?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
overflow: "y" | "x";
|
|
14
|
+
buttonLabels: ButtonLabels;
|
|
15
|
+
};
|
|
16
|
+
type ScrollAreaProps = Omit<ScrollAreaPrimitive.Root.Props, "children" | "render"> & ScrollAxes & {
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
/** Classes of the element that holds the children; its children are what the buttons scroll to. */
|
|
19
|
+
contentClassName?: string | undefined;
|
|
20
|
+
/** Classes of the scrolling box alone, such as a border and radius; the buttons stay outside it. */
|
|
21
|
+
frameClassName?: string | undefined;
|
|
22
|
+
};
|
|
3
23
|
/**
|
|
4
|
-
* An area that scrolls with
|
|
24
|
+
* An area that scrolls along one axis, with a fade where more is waiting.
|
|
5
25
|
*
|
|
6
26
|
* @family Other
|
|
7
|
-
* @when
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
27
|
+
* @when “Use Scroller for an overflowing list of peer items along a single axis: chip rows, log streams, code snippets, command palettes.” (https://vercel.com/geist/scroller)
|
|
28
|
+
* “Pick `vertical` for stacked feeds, `horizontal` for chip and tile rails, `free` only when content genuinely scrolls in both directions (logs with very long lines).” (https://vercel.com/geist/scroller)
|
|
29
|
+
* “For paginated or virtualized data sets larger than a few hundred items, render with a virtualization library inside the Scroller rather than dumping every node into the DOM.” (https://vercel.com/geist/scroller)
|
|
30
|
+
* Ours: Geist's `Scroller` is `ScrollArea`, and `vertical`, `horizontal` and `free` are `overflow="y"`,
|
|
31
|
+
* `"x"` and `"both"`. A bounded area whose content overflows: a side panel's list, a menu's long
|
|
32
|
+
* body, a rail of chips or logos.
|
|
33
|
+
* @instead Ours: a page scrolls as the document. A sequence of slides on the website is `Carousel`.
|
|
34
|
+
* @behaviour “Buttons will automatically scroll to a given **direct** child.” (https://vercel.com/geist/scroller)
|
|
35
|
+
* “Auto-scroll buttons target direct children only. If items are wrapped in extra layout nodes the buttons won’t find their target.” (https://vercel.com/geist/scroller)
|
|
36
|
+
* “Show edge fade or shadow affordances on the clipped axis so users see there’s more content past the viewport.” (https://vercel.com/geist/scroller)
|
|
37
|
+
* “Keep item widths and gaps consistent in horizontal scrollers; ragged edges break the snap rhythm and make the rail feel broken.” (https://vercel.com/geist/scroller)
|
|
38
|
+
* Ours: `overflow` is required. Give the area its height or width with `className`, and a border or
|
|
39
|
+
* radius with `frameClassName`, which draws only the scrolling box and leaves the buttons outside
|
|
40
|
+
* it. The scrollbar is hidden; a 40 px fade of the surface at each clipped edge is the only sign
|
|
41
|
+
* there is more, and it is gone at an edge with nothing beyond it. The viewport scrolls natively, so
|
|
42
|
+
* wheel, touch and keyboard all reach it. `buttonLabels` adds two round 32 px outline buttons, 16 px
|
|
43
|
+
* from the area: above it and centred for `y`, below it and at the start for `x`. They sit disabled
|
|
44
|
+
* at the ends. Smooth scrolling gives way to an instant jump under reduced motion. Colour is neutral
|
|
45
|
+
* only.
|
|
46
|
+
* @words “Scroller buttons need `aria-label`s that name the direction and content (`Scroll customer logos left`), not bare `Previous`/`Next`.” (https://vercel.com/geist/scroller)
|
|
47
|
+
* Ours: *Scroll installations left*; both labels are required with the buttons.
|
|
48
|
+
* @access “Tab order follows DOM order, so place items in reading order regardless of visual scroll direction.” (https://vercel.com/geist/scroller)
|
|
49
|
+
* “Make sure focusing an off-screen item scrolls it into view; the default browser behavior covers this, but custom focus traps can break it.” (https://vercel.com/geist/scroller)
|
|
50
|
+
* Ours: the content keeps its own semantics. The viewport is a tab stop when it scrolls.
|
|
14
51
|
*/
|
|
15
|
-
declare function ScrollArea({ className, children, ...props }:
|
|
16
|
-
|
|
17
|
-
export { ScrollArea, ScrollBar };
|
|
52
|
+
declare function ScrollArea({ className, children, contentClassName, frameClassName, overflow, buttonLabels, ...props }: ScrollAreaProps): React.JSX.Element;
|
|
53
|
+
export { ScrollArea };
|
|
18
54
|
//# sourceMappingURL=scroll-area.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../src/components/scroll-area.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../src/components/scroll-area.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAM/E,KAAK,YAAY,GAAG;IAClB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,UAAU,GACX;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,GAC1D;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAE,CAAC;AAExD,KAAK,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC,GAChF,UAAU,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mGAAmG;IACnG,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,CAAC;AAmCJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,eAAe,qBAyEjB;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -1,22 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
2
4
|
import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
|
|
5
|
+
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from "lucide-react";
|
|
6
|
+
import { Button } from "./button.js";
|
|
3
7
|
import { cn } from "../lib/utils.js";
|
|
8
|
+
const viewportAxis = {
|
|
9
|
+
y: "overflow-x-hidden! [mask-image:linear-gradient(to_bottom,transparent,black_min(2.5rem,var(--scroll-area-overflow-y-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-y-end,0px))),transparent)]",
|
|
10
|
+
x: "overflow-y-hidden! [mask-image:linear-gradient(to_right,transparent,black_min(2.5rem,var(--scroll-area-overflow-x-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-x-end,0px))),transparent)]",
|
|
11
|
+
both: "[mask-composite:intersect] [mask-image:linear-gradient(to_bottom,transparent,black_min(2.5rem,var(--scroll-area-overflow-y-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-y-end,0px))),transparent),linear-gradient(to_right,transparent,black_min(2.5rem,var(--scroll-area-overflow-x-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-x-end,0px))),transparent)]",
|
|
12
|
+
};
|
|
13
|
+
function scrollToNeighbour(viewport, content, axis, direction) {
|
|
14
|
+
const edges = (box) => axis === "y" ? { start: box.top, end: box.bottom } : { start: box.left, end: box.right };
|
|
15
|
+
const view = edges(viewport.getBoundingClientRect());
|
|
16
|
+
const items = Array.from(content.children, (child) => edges(child.getBoundingClientRect()));
|
|
17
|
+
const target = direction === "next"
|
|
18
|
+
? items.find((item) => item.end > view.end + 1)
|
|
19
|
+
: items.reverse().find((item) => item.start < view.start - 1);
|
|
20
|
+
if (!target)
|
|
21
|
+
return;
|
|
22
|
+
const distance = direction === "next"
|
|
23
|
+
? Math.min(target.end - view.end, target.start - view.start)
|
|
24
|
+
: target.start - view.start;
|
|
25
|
+
viewport.scrollBy(axis === "y" ? { top: distance } : { left: distance });
|
|
26
|
+
}
|
|
27
|
+
const buttonIcons = {
|
|
28
|
+
x: { previous: ChevronLeftIcon, next: ChevronRightIcon },
|
|
29
|
+
y: { previous: ChevronUpIcon, next: ChevronDownIcon },
|
|
30
|
+
};
|
|
4
31
|
/**
|
|
5
|
-
* An area that scrolls with
|
|
32
|
+
* An area that scrolls along one axis, with a fade where more is waiting.
|
|
6
33
|
*
|
|
7
34
|
* @family Other
|
|
8
|
-
* @when
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* @
|
|
35
|
+
* @when “Use Scroller for an overflowing list of peer items along a single axis: chip rows, log streams, code snippets, command palettes.” (https://vercel.com/geist/scroller)
|
|
36
|
+
* “Pick `vertical` for stacked feeds, `horizontal` for chip and tile rails, `free` only when content genuinely scrolls in both directions (logs with very long lines).” (https://vercel.com/geist/scroller)
|
|
37
|
+
* “For paginated or virtualized data sets larger than a few hundred items, render with a virtualization library inside the Scroller rather than dumping every node into the DOM.” (https://vercel.com/geist/scroller)
|
|
38
|
+
* Ours: Geist's `Scroller` is `ScrollArea`, and `vertical`, `horizontal` and `free` are `overflow="y"`,
|
|
39
|
+
* `"x"` and `"both"`. A bounded area whose content overflows: a side panel's list, a menu's long
|
|
40
|
+
* body, a rail of chips or logos.
|
|
41
|
+
* @instead Ours: a page scrolls as the document. A sequence of slides on the website is `Carousel`.
|
|
42
|
+
* @behaviour “Buttons will automatically scroll to a given **direct** child.” (https://vercel.com/geist/scroller)
|
|
43
|
+
* “Auto-scroll buttons target direct children only. If items are wrapped in extra layout nodes the buttons won’t find their target.” (https://vercel.com/geist/scroller)
|
|
44
|
+
* “Show edge fade or shadow affordances on the clipped axis so users see there’s more content past the viewport.” (https://vercel.com/geist/scroller)
|
|
45
|
+
* “Keep item widths and gaps consistent in horizontal scrollers; ragged edges break the snap rhythm and make the rail feel broken.” (https://vercel.com/geist/scroller)
|
|
46
|
+
* Ours: `overflow` is required. Give the area its height or width with `className`, and a border or
|
|
47
|
+
* radius with `frameClassName`, which draws only the scrolling box and leaves the buttons outside
|
|
48
|
+
* it. The scrollbar is hidden; a 40 px fade of the surface at each clipped edge is the only sign
|
|
49
|
+
* there is more, and it is gone at an edge with nothing beyond it. The viewport scrolls natively, so
|
|
50
|
+
* wheel, touch and keyboard all reach it. `buttonLabels` adds two round 32 px outline buttons, 16 px
|
|
51
|
+
* from the area: above it and centred for `y`, below it and at the start for `x`. They sit disabled
|
|
52
|
+
* at the ends. Smooth scrolling gives way to an instant jump under reduced motion. Colour is neutral
|
|
53
|
+
* only.
|
|
54
|
+
* @words “Scroller buttons need `aria-label`s that name the direction and content (`Scroll customer logos left`), not bare `Previous`/`Next`.” (https://vercel.com/geist/scroller)
|
|
55
|
+
* Ours: *Scroll installations left*; both labels are required with the buttons.
|
|
56
|
+
* @access “Tab order follows DOM order, so place items in reading order regardless of visual scroll direction.” (https://vercel.com/geist/scroller)
|
|
57
|
+
* “Make sure focusing an off-screen item scrolls it into view; the default browser behavior covers this, but custom focus traps can break it.” (https://vercel.com/geist/scroller)
|
|
58
|
+
* Ours: the content keeps its own semantics. The viewport is a tab stop when it scrolls.
|
|
15
59
|
*/
|
|
16
|
-
function ScrollArea({ className, children, ...props }) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
60
|
+
function ScrollArea({ className, children, contentClassName, frameClassName, overflow, buttonLabels, ...props }) {
|
|
61
|
+
const viewport = React.useRef(null);
|
|
62
|
+
const content = React.useRef(null);
|
|
63
|
+
const axis = overflow === "y" ? "y" : "x";
|
|
64
|
+
const buttons = (disabled) => buttonLabels ? (_jsx("div", { className: cn("m-px flex gap-2", axis === "y" ? "justify-center" : "justify-start"), "data-slot": "scroll-area-buttons", children: ["previous", "next"].map((direction) => {
|
|
65
|
+
const Icon = buttonIcons[axis][direction];
|
|
66
|
+
return (_jsx(Button, { "aria-label": buttonLabels[direction], disabled: disabled[direction], onClick: () => {
|
|
67
|
+
if (viewport.current && content.current) {
|
|
68
|
+
scrollToNeighbour(viewport.current, content.current, axis, direction);
|
|
69
|
+
}
|
|
70
|
+
}, shape: "circle", size: "icon-sm", variant: "outline", children: _jsx(Icon, { "aria-hidden": "true" }) }, direction));
|
|
71
|
+
}) })) : null;
|
|
72
|
+
return (_jsx(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", className: cn("relative flex flex-col gap-4", className), render: (rootProps, state) => {
|
|
73
|
+
const row = buttons({
|
|
74
|
+
previous: axis === "y" ? !state.overflowYStart : !state.overflowXStart,
|
|
75
|
+
next: axis === "y" ? !state.overflowYEnd : !state.overflowXEnd,
|
|
76
|
+
});
|
|
77
|
+
return (_jsxs("div", { ...rootProps, children: [axis === "y" ? row : null, _jsx("div", { className: cn("relative min-h-0 flex-1 rounded-[inherit]", frameClassName), children: rootProps.children }), axis === "x" ? row : null] }));
|
|
78
|
+
}, ...props, children: _jsx(ScrollAreaPrimitive.Viewport, { ref: viewport, "data-slot": "scroll-area-viewport", className: cn("size-full scroll-smooth rounded-[inherit] transition-colors motion-reduce:scroll-auto", viewportAxis[overflow]), children: _jsx(ScrollAreaPrimitive.Content, { ref: content, "data-slot": "scroll-area-content", className: contentClassName, children: children }) }) }));
|
|
21
79
|
}
|
|
22
|
-
export { ScrollArea
|
|
80
|
+
export { ScrollArea };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
|
|
3
|
+
export type SegmentedControlSize = "sm" | "default" | "lg";
|
|
4
|
+
export type SegmentedOption<Value extends string = string> = {
|
|
5
|
+
value: Value;
|
|
6
|
+
/** The option's name. An icon-only option shows it as a tooltip and keeps it as its accessible name. */
|
|
7
|
+
label: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
} & ({
|
|
10
|
+
icon?: undefined;
|
|
11
|
+
iconOnly?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
icon: React.ReactElement;
|
|
14
|
+
iconOnly?: boolean;
|
|
15
|
+
});
|
|
16
|
+
export type SegmentedOptions<Value extends string = string> = readonly [SegmentedOption<Value>, SegmentedOption<Value>] | readonly [SegmentedOption<Value>, SegmentedOption<Value>, SegmentedOption<Value>];
|
|
17
|
+
export type SegmentedControlProps<Value extends string = string> = Omit<RadioGroupPrimitive.Props<Value>, "aria-label" | "aria-labelledby" | "children" | "defaultValue" | "onValueChange" | "readOnly" | "render" | "required" | "value"> & {
|
|
18
|
+
options: SegmentedOptions<Value>;
|
|
19
|
+
size?: SegmentedControlSize;
|
|
20
|
+
/** Stretches the control to its container, with the options sharing the width equally. */
|
|
21
|
+
fullWidth?: boolean;
|
|
22
|
+
} & ({
|
|
23
|
+
"aria-label": string;
|
|
24
|
+
"aria-labelledby"?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
"aria-labelledby": string;
|
|
27
|
+
"aria-label"?: undefined;
|
|
28
|
+
}) & ({
|
|
29
|
+
value: Value;
|
|
30
|
+
defaultValue?: undefined;
|
|
31
|
+
onValueChange: (value: Value) => void;
|
|
32
|
+
} | {
|
|
33
|
+
defaultValue: Value;
|
|
34
|
+
value?: undefined;
|
|
35
|
+
onValueChange?: (value: Value) => void;
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Two or three options that show different views of one surface, the chosen one filled.
|
|
39
|
+
*
|
|
40
|
+
* @family Choices
|
|
41
|
+
* @when "Use Switch as a segmented selector for 2–3 mutually exclusive options that show different
|
|
42
|
+
* views of the same surface, like `Source` vs `Output`." (https://vercel.com/geist/switch) Ours:
|
|
43
|
+
* Geist's `Switch` is our `SegmentedControl`.
|
|
44
|
+
* @instead "For a boolean on/off setting, use `Toggle`." (https://vercel.com/geist/switch) "Switch
|
|
45
|
+
* implements radio semantics, so two options stay mutually exclusive rather than reading as a
|
|
46
|
+
* checkbox." (https://vercel.com/geist/switch) "Past 3 options or when labels grow beyond a couple
|
|
47
|
+
* of words, switch to `Tabs` or a `Select`." (https://vercel.com/geist/switch) Ours: Geist's
|
|
48
|
+
* `Toggle` is our `Switch`. The theme is `ThemeModeSwitcher`, never a second picker. Four to six
|
|
49
|
+
* that must be compared are a `RadioGroup`. Pressed buttons that can be several or none are a
|
|
50
|
+
* `ToggleGroup`. Panels of one object are `Tabs`.
|
|
51
|
+
* @behaviour "Pass a `name` so the underlying radios are grouped; without it, more than one option
|
|
52
|
+
* can appear selected at once." (https://vercel.com/geist/switch) "Set `defaultChecked` (or
|
|
53
|
+
* controlled `checked`) on exactly one `Switch.Control` so the group has a defined initial state."
|
|
54
|
+
* (https://vercel.com/geist/switch) "Pad each `Switch.Control` so the widest label fits without the
|
|
55
|
+
* active pill resizing on selection." (https://vercel.com/geist/switch) "Test with the longest copy
|
|
56
|
+
* in the set." (https://vercel.com/geist/switch) Ours: the group's name (`aria-label` or
|
|
57
|
+
* `aria-labelledby`), a label on every option and a starting choice (`defaultValue` or `value`) are
|
|
58
|
+
* required; without them it does not compile. The options are one radio group, so they stay
|
|
59
|
+
* exclusive without a form `name`. The
|
|
60
|
+
* options share the width of the widest, so the fill never resizes as the choice moves; where the
|
|
61
|
+
* row is narrower than that, each option keeps its own word's width rather than cutting it. The track
|
|
62
|
+
* is white with a hairline and a 4 px inset, so it is 32, 36 or 40 px high around options of 24, 28
|
|
63
|
+
* or 32 px. Colour: neutral throughout, the chosen option filled grey with ink words and the others
|
|
64
|
+
* grey words that turn ink on hover; nothing takes a hue. Icons are 16 px, 20 px at `lg`. A
|
|
65
|
+
* disabled option keeps the chosen fill, lightens only its words and has no hover change. The
|
|
66
|
+
* options are radios in one group: arrows move and choose, and pressing the chosen one changes
|
|
67
|
+
* nothing. It applies at once; it is not a field that waits for a Save. `fullWidth` when it heads a
|
|
68
|
+
* form or a dialog, as the two-factor form's method switch does.
|
|
69
|
+
* @words "Title Case each `Switch.Control` label." (https://vercel.com/geist/switch) "Keep labels
|
|
70
|
+
* to one or two words and parallel: `Source` / `Output`, not `Source` / `Show output`."
|
|
71
|
+
* (https://vercel.com/geist/switch) Ours: sentence case: *Source*, *Output*.
|
|
72
|
+
* @access "Always provide a `label` on every `Switch.Control`, even when an `icon` carries the
|
|
73
|
+
* meaning, so screen readers announce the option." (https://vercel.com/geist/switch) "The component
|
|
74
|
+
* renders it as `geist-sr-only` for icon-only controls." (https://vercel.com/geist/switch) "Pair an
|
|
75
|
+
* icon-only Switch with a `Tooltip` on each control so sighted users get the same label assistive
|
|
76
|
+
* tech receives." (https://vercel.com/geist/switch) Ours: `role="radiogroup"` named by `aria-label`
|
|
77
|
+
* or `aria-labelledby`; each option a radio named by its label, shown as a tooltip on an icon-only
|
|
78
|
+
* option.
|
|
79
|
+
*/
|
|
80
|
+
declare function SegmentedControl<Value extends string = string>({ options, size, fullWidth, className, ...props }: SegmentedControlProps<Value>): React.JSX.Element;
|
|
81
|
+
export { SegmentedControl };
|
|
82
|
+
//# sourceMappingURL=segmented-control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segmented-control.d.ts","sourceRoot":"","sources":["../../src/components/segmented-control.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AA6C/E,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;AAE3D,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI;IAC3D,KAAK,EAAE,KAAK,CAAC;IACb,wGAAwG;IACxG,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,CAAC;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEpG,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IACtD,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,GACzD,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;AAEtF,MAAM,MAAM,qBAAqB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CACrE,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,EAC9B,YAAY,GACZ,iBAAiB,GACjB,UAAU,GACV,cAAc,GACd,eAAe,GACf,UAAU,GACV,QAAQ,GACR,UAAU,GACV,OAAO,CACV,GAAG;IACF,OAAO,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,0FAA0F;IAC1F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,CACE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,CAC1D,GACD,CACI;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAAC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,GACjF;IAAE,YAAY,EAAE,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,CACrF,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,iBAAS,gBAAgB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,EACvD,OAAO,EACP,IAAgB,EAChB,SAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,qBAAqB,CAAC,KAAK,CAAC,qBAkC9B;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|