@eifi1/ui-kit 0.54.0 → 0.55.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/README.md +90 -76
- package/dist/admin/plan-change.js +2 -2
- package/dist/admin/plan-change.js.map +1 -1
- package/dist/admin/user-roster.d.ts +6 -0
- package/dist/admin/user-roster.js +4 -0
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/billing/billing-labels.d.ts +26 -0
- package/dist/billing/billing-labels.js +9 -0
- package/dist/billing/billing-labels.js.map +1 -1
- package/dist/billing/subscription-standing.d.ts +61 -0
- package/dist/billing/subscription-standing.js +51 -0
- package/dist/billing/subscription-standing.js.map +1 -0
- package/dist/billing/usage-meter.d.ts +52 -0
- package/dist/billing/usage-meter.js +52 -0
- package/dist/billing/usage-meter.js.map +1 -0
- package/dist/chart.d.ts +1 -0
- package/dist/chart.js +4 -0
- package/dist/chart.js.map +1 -1
- package/dist/components/alert-banner.js +2 -3
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.js +3 -15
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.js +2 -2
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/bulk-action-bar.js +2 -1
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button.d.ts +35 -1
- package/dist/components/button.js +5 -9
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar-heatmap.js +2 -2
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/camera-button.d.ts +89 -0
- package/dist/components/camera-button.js +122 -0
- package/dist/components/camera-button.js.map +1 -0
- package/dist/components/camera-capture.d.ts +66 -0
- package/dist/components/camera-capture.js +190 -0
- package/dist/components/camera-capture.js.map +1 -0
- package/dist/components/camera-labels.d.ts +20 -0
- package/dist/components/camera-labels.js +15 -0
- package/dist/components/camera-labels.js.map +1 -0
- package/dist/components/chart-edge.d.ts +9 -0
- package/dist/components/chart-edge.js +14 -3
- package/dist/components/chart-edge.js.map +1 -1
- package/dist/components/chart-zoom-core.js +34 -29
- package/dist/components/chart-zoom-core.js.map +1 -1
- package/dist/components/checkbox-group.js +1 -1
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/combobox-core.js +3 -2
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +2 -2
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/consent-again-notice-labels.d.ts +25 -0
- package/dist/components/consent-again-notice-labels.js +15 -0
- package/dist/components/consent-again-notice-labels.js.map +1 -0
- package/dist/components/consent-again-notice.d.ts +85 -0
- package/dist/components/consent-again-notice.js +94 -0
- package/dist/components/consent-again-notice.js.map +1 -0
- package/dist/components/country-select.js +2 -7
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-select.js +2 -2
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.js +2 -2
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-column-settings.js +2 -2
- package/dist/components/data-table-column-settings.js.map +1 -1
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-virtual.js +13 -3
- package/dist/components/data-table-virtual.js.map +1 -1
- package/dist/components/date-field.js +2 -2
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.js +2 -2
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.js +2 -6
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +3 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/dropdown.js +7 -3
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/entity-combobox.js +2 -2
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/field-parts.d.ts +108 -6
- package/dist/components/field-parts.js +59 -6
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-suggestion-labels.d.ts +2 -0
- package/dist/components/field-suggestion-labels.js +10 -0
- package/dist/components/field-suggestion-labels.js.map +1 -0
- package/dist/components/field.js +1 -1
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-button.d.ts +1 -1
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/floating-panel.d.ts +7 -6
- package/dist/components/floating-panel.js +3 -17
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form-actions.d.ts +3 -2
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/hover-menu.js +3 -2
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/icon-button.d.ts +23 -5
- package/dist/components/icon-button.js +6 -8
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/inline-confirm.js +2 -1
- package/dist/components/inline-confirm.js.map +1 -1
- package/dist/components/inline-entity-combobox.js +2 -2
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/input.js +2 -2
- package/dist/components/input.js.map +1 -1
- package/dist/components/jump-calendar.js +3 -3
- package/dist/components/jump-calendar.js.map +1 -1
- package/dist/components/legal.d.ts +13 -1
- package/dist/components/legal.js +12 -0
- package/dist/components/legal.js.map +1 -1
- package/dist/components/legended-series-chart.d.ts +80 -0
- package/dist/components/legended-series-chart.js +70 -0
- package/dist/components/legended-series-chart.js.map +1 -0
- package/dist/components/lightbox.js +2 -1
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/mini-calendar.js +13 -5
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.d.ts +23 -2
- package/dist/components/modal.js +24 -6
- package/dist/components/modal.js.map +1 -1
- package/dist/components/month-picker.d.ts +1 -1
- package/dist/components/month-picker.js +6 -6
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.js +2 -2
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.js +2 -6
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-input.js +2 -2
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/page-header-layout.d.ts +18 -0
- package/dist/components/page-header-layout.js +23 -0
- package/dist/components/page-header-layout.js.map +1 -0
- package/dist/components/page-header-skeleton.d.ts +41 -0
- package/dist/components/page-header-skeleton.js +52 -0
- package/dist/components/page-header-skeleton.js.map +1 -0
- package/dist/components/page-header.js +4 -17
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/popover.js +7 -2
- package/dist/components/popover.js.map +1 -1
- package/dist/components/release-notes-labels.d.ts +16 -0
- package/dist/components/release-notes-labels.js +18 -0
- package/dist/components/release-notes-labels.js.map +1 -0
- package/dist/components/release-notes.d.ts +65 -0
- package/dist/components/release-notes.js +65 -0
- package/dist/components/release-notes.js.map +1 -0
- package/dist/components/select.js +2 -2
- package/dist/components/select.js.map +1 -1
- package/dist/components/series-chart-labels.d.ts +9 -0
- package/dist/components/series-chart-labels.js +3 -1
- package/dist/components/series-chart-labels.js.map +1 -1
- package/dist/components/series-chart.d.ts +5 -0
- package/dist/components/series-chart.js +89 -36
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/toggle-group.js +3 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/treemap-layout.js.map +1 -1
- package/dist/components/treemap.d.ts +17 -15
- package/dist/components/treemap.js +167 -85
- package/dist/components/treemap.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/eslint/role-utilities.d.ts +2 -2
- package/dist/eslint/role-utilities.js.map +1 -1
- package/dist/feedback/feedback-inbox-page.d.ts +260 -0
- package/dist/feedback/feedback-inbox-page.js +207 -0
- package/dist/feedback/feedback-inbox-page.js.map +1 -0
- package/dist/feedback/feedback-vocabulary.js +2 -2
- package/dist/feedback/feedback-vocabulary.js.map +1 -1
- package/dist/feedback.d.ts +1 -0
- package/dist/feedback.js +6 -0
- package/dist/feedback.js.map +1 -1
- package/dist/hooks/use-debounce.d.ts +32 -5
- package/dist/hooks/use-debounce.js +6 -5
- package/dist/hooks/use-debounce.js.map +1 -1
- package/dist/hooks/use-file-picker.d.ts +3 -1
- package/dist/hooks/use-file-picker.js.map +1 -1
- package/dist/hooks/use-focus-trap.d.ts +19 -3
- package/dist/hooks/use-focus-trap.js +15 -5
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-has-camera.d.ts +36 -0
- package/dist/hooks/use-has-camera.js +53 -0
- package/dist/hooks/use-has-camera.js.map +1 -0
- package/dist/hooks/use-hotkey.js +1 -10
- package/dist/hooks/use-hotkey.js.map +1 -1
- package/dist/hooks/use-overlay-history.d.ts +6 -1
- package/dist/hooks/use-overlay-history.js +10 -2
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.js +11 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +75 -3
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +20 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +92 -4
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +71 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +72 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +74 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +74 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +71 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +22 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +24 -5
- package/dist/index.js +35 -1
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-labels.d.ts +8 -0
- package/dist/landing/landing-labels.js +2 -1
- package/dist/landing/landing-labels.js.map +1 -1
- package/dist/lib/changelog.d.ts +130 -0
- package/dist/lib/changelog.js +137 -0
- package/dist/lib/changelog.js.map +1 -0
- package/dist/lib/clipboard-minus.js +2 -2
- package/dist/lib/clipboard-minus.js.map +1 -1
- package/dist/lib/dates.d.ts +29 -3
- package/dist/lib/dates.js +41 -12
- package/dist/lib/dates.js.map +1 -1
- package/dist/lib/editable-content.d.ts +33 -0
- package/dist/lib/editable-content.js +15 -0
- package/dist/lib/editable-content.js.map +1 -0
- package/dist/lib/focus-left.d.ts +47 -1
- package/dist/lib/focus-left.js +11 -2
- package/dist/lib/focus-left.js.map +1 -1
- package/dist/lib/server-wake.d.ts +49 -9
- package/dist/lib/server-wake.js +25 -14
- package/dist/lib/server-wake.js.map +1 -1
- package/dist/lib/session-refresh.d.ts +53 -0
- package/dist/lib/session-refresh.js +27 -1
- package/dist/lib/session-refresh.js.map +1 -1
- package/dist/rhf/fields.js +3 -3
- package/dist/rhf/fields.js.map +1 -1
- package/dist/shell/app-shell.d.ts +25 -1
- package/dist/shell/app-shell.js +3 -1
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/dev-menu.d.ts +3 -0
- package/dist/shell/dev-menu.js +4 -2
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/held-changes-banner-labels.d.ts +23 -0
- package/dist/shell/held-changes-banner-labels.js +14 -0
- package/dist/shell/held-changes-banner-labels.js.map +1 -0
- package/dist/shell/held-changes-banner.d.ts +75 -0
- package/dist/shell/held-changes-banner.js +106 -0
- package/dist/shell/held-changes-banner.js.map +1 -0
- package/dist/shell/sync-status-indicator.d.ts +27 -12
- package/dist/shell/sync-status-indicator.js +13 -4
- package/dist/shell/sync-status-indicator.js.map +1 -1
- package/dist/shell/top-bar-parts-labels.d.ts +5 -0
- package/dist/shell/top-bar-parts-labels.js +3 -1
- package/dist/shell/top-bar-parts-labels.js.map +1 -1
- package/dist/shell.d.ts +2 -0
- package/dist/shell.js +3 -0
- package/dist/shell.js.map +1 -1
- package/dist/sync/engine.d.ts +11 -2
- package/dist/sync/engine.js +13 -5
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/hooks.d.ts +3 -2
- package/dist/sync/hooks.js +4 -2
- package/dist/sync/hooks.js.map +1 -1
- package/dist/testing/css-variables.generated.d.ts +2 -2
- package/dist/testing/css-variables.generated.js +1 -1
- package/dist/testing/css-variables.generated.js.map +1 -1
- package/dist/theme/chart-palette.d.ts +18 -0
- package/dist/theme/chart-palette.js +17 -1
- package/dist/theme/chart-palette.js.map +1 -1
- package/dist/theme/contrast-tokens.d.ts +3 -3
- package/dist/theme/contrast-tokens.js.map +1 -1
- package/dist/theme/contrast.d.ts +4 -4
- package/dist/theme/contrast.js.map +1 -1
- package/dist/tour/tour-overlay.js +2 -1
- package/dist/tour/tour-overlay.js.map +1 -1
- package/package.json +5 -9
- package/tokens.css +19 -54
- package/src/account/account-parts.ts +0 -47
- package/src/account/account-settings-labels.ts +0 -240
- package/src/account/account-settings.tsx +0 -698
- package/src/account/data-export-setting-labels.ts +0 -20
- package/src/account/data-export-setting.tsx +0 -200
- package/src/account/delete-account-setting-labels.ts +0 -33
- package/src/account/delete-account-setting.tsx +0 -342
- package/src/account/email-change-setting-labels.ts +0 -31
- package/src/account/email-change-setting.tsx +0 -443
- package/src/account/passkeys-setting.tsx +0 -445
- package/src/account/sessions-setting-labels.ts +0 -24
- package/src/account/sessions-setting.tsx +0 -283
- package/src/admin/admin-action-confirm-labels.ts +0 -19
- package/src/admin/admin-action-confirm.tsx +0 -509
- package/src/admin/admin-action-log-labels.ts +0 -83
- package/src/admin/admin-action-log.tsx +0 -464
- package/src/admin/admin-area-labels.ts +0 -114
- package/src/admin/admin-forbidden.tsx +0 -75
- package/src/admin/admin-overview.tsx +0 -258
- package/src/admin/admin-parts.ts +0 -68
- package/src/admin/admin-sections.tsx +0 -208
- package/src/admin/admin-tool-links.tsx +0 -90
- package/src/admin/invitations-panel-labels.ts +0 -31
- package/src/admin/invitations-panel.tsx +0 -516
- package/src/admin/mail-test-card-labels.ts +0 -19
- package/src/admin/mail-test-card.tsx +0 -189
- package/src/admin/plan-change-labels.ts +0 -5
- package/src/admin/plan-change.tsx +0 -474
- package/src/admin/reviewer-scope-editor-labels.ts +0 -16
- package/src/admin/reviewer-scope-editor.tsx +0 -224
- package/src/admin/role-select-labels.ts +0 -16
- package/src/admin/role-select.tsx +0 -282
- package/src/admin/transfer-ownership-dialog-labels.ts +0 -20
- package/src/admin/transfer-ownership-dialog.tsx +0 -162
- package/src/admin/user-roster-labels.ts +0 -17
- package/src/admin/user-roster.tsx +0 -559
- package/src/auth/accept-invitation-labels.ts +0 -21
- package/src/auth/accept-invitation.tsx +0 -210
- package/src/auth/auth-errors-labels.ts +0 -23
- package/src/auth/auth-errors.ts +0 -439
- package/src/auth/complete-name-dialog-labels.ts +0 -16
- package/src/auth/complete-name-dialog.tsx +0 -253
- package/src/auth/email-tag.ts +0 -75
- package/src/auth/forgot-password-form-labels.ts +0 -20
- package/src/auth/forgot-password-form.tsx +0 -221
- package/src/auth/form-rules.ts +0 -40
- package/src/auth/new-password-fields.tsx +0 -85
- package/src/auth/not-found-page-labels.ts +0 -12
- package/src/auth/not-found-page.tsx +0 -95
- package/src/auth/register-form-labels.ts +0 -31
- package/src/auth/register-form.tsx +0 -456
- package/src/auth/reset-password-form-labels.ts +0 -27
- package/src/auth/reset-password-form.tsx +0 -341
- package/src/auth/sign-in-form-labels.ts +0 -44
- package/src/auth/sign-in-form.tsx +0 -858
- package/src/auth/status-parts.tsx +0 -132
- package/src/auth/verify-email-labels.ts +0 -26
- package/src/auth/verify-email.tsx +0 -445
- package/src/billing/billing-banner.tsx +0 -258
- package/src/billing/billing-labels.ts +0 -381
- package/src/billing/billing-lock.ts +0 -108
- package/src/billing/billing-overview.ts +0 -157
- package/src/billing/billing-standing.ts +0 -80
- package/src/billing/cancel-request.ts +0 -97
- package/src/billing/cancel-subscription.tsx +0 -98
- package/src/billing/checkout-processing.ts +0 -394
- package/src/billing/checkout-return.ts +0 -90
- package/src/billing/pay-page.ts +0 -330
- package/src/billing/plan-card.tsx +0 -562
- package/src/billing/plan-change-labels.ts +0 -66
- package/src/billing/plan-limit-notice.tsx +0 -148
- package/src/billing/plan-limit-toast.tsx +0 -90
- package/src/billing/plan-limit.ts +0 -52
- package/src/billing/plan-price.ts +0 -98
- package/src/billing/plan-switch.tsx +0 -216
- package/src/billing/provider-page.ts +0 -84
- package/src/billing/subscription-actions.tsx +0 -247
- package/src/billing/subscription-status-chip.tsx +0 -95
- package/src/chart.ts +0 -103
- package/src/components/account-chips-labels.ts +0 -16
- package/src/components/account-chips.tsx +0 -474
- package/src/components/alert-banner.tsx +0 -670
- package/src/components/amount-input.tsx +0 -816
- package/src/components/appearance-labels.ts +0 -63
- package/src/components/authed-image-labels.ts +0 -11
- package/src/components/authed-image.tsx +0 -209
- package/src/components/autocomplete.tsx +0 -645
- package/src/components/breadcrumbs-labels.ts +0 -10
- package/src/components/breadcrumbs.tsx +0 -205
- package/src/components/bulk-action-bar-labels.ts +0 -11
- package/src/components/bulk-action-bar.tsx +0 -443
- package/src/components/button-group.tsx +0 -223
- package/src/components/button-look.ts +0 -256
- package/src/components/button.tsx +0 -339
- package/src/components/calculator.tsx +0 -341
- package/src/components/calendar-heatmap-labels.ts +0 -15
- package/src/components/calendar-heatmap.tsx +0 -600
- package/src/components/card.tsx +0 -377
- package/src/components/chart-edge.ts +0 -106
- package/src/components/chart-figure.tsx +0 -35
- package/src/components/chart-height.ts +0 -30
- package/src/components/chart-zoom-core.tsx +0 -627
- package/src/components/chart-zoom.tsx +0 -22
- package/src/components/chart.tsx +0 -554
- package/src/components/checkbox-group.tsx +0 -247
- package/src/components/checkbox.tsx +0 -346
- package/src/components/chip-input.tsx +0 -370
- package/src/components/chip-labels.ts +0 -13
- package/src/components/chip.tsx +0 -843
- package/src/components/choice-card.tsx +0 -544
- package/src/components/column-mapper-labels.ts +0 -38
- package/src/components/column-mapper.tsx +0 -655
- package/src/components/combobox-core.tsx +0 -1321
- package/src/components/combobox-suggestions.tsx +0 -131
- package/src/components/combobox.tsx +0 -716
- package/src/components/confirm-context.ts +0 -7
- package/src/components/confirm-dialog-labels.ts +0 -13
- package/src/components/confirm-dialog.tsx +0 -341
- package/src/components/copy-button-labels.ts +0 -13
- package/src/components/copy-button.tsx +0 -192
- package/src/components/country-select-labels.ts +0 -11
- package/src/components/country-select.tsx +0 -539
- package/src/components/currency-option-list.tsx +0 -188
- package/src/components/currency-select.tsx +0 -343
- package/src/components/danger-confirm-labels.ts +0 -20
- package/src/components/danger-confirm.tsx +0 -987
- package/src/components/data-table-cells.tsx +0 -118
- package/src/components/data-table-column-settings.tsx +0 -198
- package/src/components/data-table-filter-popover.tsx +0 -289
- package/src/components/data-table-filters.ts +0 -315
- package/src/components/data-table-fit.ts +0 -301
- package/src/components/data-table-groups.tsx +0 -288
- package/src/components/data-table-head.tsx +0 -280
- package/src/components/data-table-labels.ts +0 -198
- package/src/components/data-table-leading-row.tsx +0 -58
- package/src/components/data-table-mobile.tsx +0 -1117
- package/src/components/data-table-pagination.tsx +0 -202
- package/src/components/data-table-resize.ts +0 -188
- package/src/components/data-table-row-actions.tsx +0 -302
- package/src/components/data-table-row.tsx +0 -496
- package/src/components/data-table-selection.ts +0 -71
- package/src/components/data-table-shared.tsx +0 -287
- package/src/components/data-table-sort.ts +0 -163
- package/src/components/data-table-virtual.ts +0 -576
- package/src/components/data-table.tsx +0 -2598
- package/src/components/date-field.tsx +0 -684
- package/src/components/date-format-setting.tsx +0 -64
- package/src/components/date-picker.tsx +0 -404
- package/src/components/date-range-picker.tsx +0 -518
- package/src/components/description-list-labels.ts +0 -9
- package/src/components/description-list.tsx +0 -386
- package/src/components/dialog-frame-labels.ts +0 -7
- package/src/components/dialog-frame.tsx +0 -284
- package/src/components/disclosure.tsx +0 -476
- package/src/components/dropdown.tsx +0 -461
- package/src/components/empty-state.tsx +0 -136
- package/src/components/entity-combobox.tsx +0 -422
- package/src/components/error-boundary-labels.ts +0 -20
- package/src/components/error-boundary.tsx +0 -675
- package/src/components/facing-pair.ts +0 -93
- package/src/components/field-base-labels.ts +0 -20
- package/src/components/field-base.tsx +0 -656
- package/src/components/field-parts.tsx +0 -825
- package/src/components/field-strip.tsx +0 -129
- package/src/components/field.tsx +0 -206
- package/src/components/file-button.tsx +0 -295
- package/src/components/file-dropzone.tsx +0 -559
- package/src/components/floating-panel-labels.ts +0 -10
- package/src/components/floating-panel.tsx +0 -828
- package/src/components/focus-ring.ts +0 -16
- package/src/components/form-actions-labels.ts +0 -11
- package/src/components/form-actions.tsx +0 -578
- package/src/components/full-bleed-dialog.tsx +0 -294
- package/src/components/grouped-picker.tsx +0 -184
- package/src/components/help-popover.tsx +0 -117
- package/src/components/hover-menu.tsx +0 -343
- package/src/components/iban-input-labels.ts +0 -14
- package/src/components/iban-input.tsx +0 -236
- package/src/components/icon-button.tsx +0 -959
- package/src/components/icon-picker-labels.ts +0 -13
- package/src/components/icon-picker.tsx +0 -232
- package/src/components/image-grid-labels.ts +0 -11
- package/src/components/image-grid.tsx +0 -202
- package/src/components/inline-confirm.tsx +0 -116
- package/src/components/inline-edit-field-labels.ts +0 -11
- package/src/components/inline-edit-field.tsx +0 -552
- package/src/components/inline-entity-combobox.tsx +0 -849
- package/src/components/input.tsx +0 -394
- package/src/components/jump-calendar.tsx +0 -265
- package/src/components/language-select.tsx +0 -93
- package/src/components/legal-labels.ts +0 -105
- package/src/components/legal-page.tsx +0 -711
- package/src/components/legal.tsx +0 -668
- package/src/components/lightbox-labels.ts +0 -18
- package/src/components/lightbox.tsx +0 -399
- package/src/components/line-items-labels.ts +0 -14
- package/src/components/line-items.tsx +0 -602
- package/src/components/list-labels.ts +0 -12
- package/src/components/list.tsx +0 -870
- package/src/components/loading-state.tsx +0 -78
- package/src/components/measured-grid-labels.ts +0 -25
- package/src/components/measured-grid.tsx +0 -837
- package/src/components/menu-item.tsx +0 -241
- package/src/components/mini-calendar-labels.ts +0 -17
- package/src/components/mini-calendar.tsx +0 -792
- package/src/components/modal.tsx +0 -534
- package/src/components/money-draft.ts +0 -83
- package/src/components/money-field.tsx +0 -76
- package/src/components/month-grid.tsx +0 -229
- package/src/components/month-picker-labels.ts +0 -22
- package/src/components/month-picker.tsx +0 -1087
- package/src/components/multi-entity-combobox.tsx +0 -369
- package/src/components/multi-select.tsx +0 -376
- package/src/components/nav-pills.tsx +0 -198
- package/src/components/number-field.tsx +0 -327
- package/src/components/number-input.tsx +0 -559
- package/src/components/numeric-field.ts +0 -169
- package/src/components/numpad-sheet.tsx +0 -285
- package/src/components/one-time-code-input.tsx +0 -270
- package/src/components/page-contents-labels.ts +0 -9
- package/src/components/page-contents.tsx +0 -282
- package/src/components/page-header-context.ts +0 -8
- package/src/components/page-header.tsx +0 -298
- package/src/components/password-strength-labels.ts +0 -22
- package/src/components/password-strength.tsx +0 -241
- package/src/components/phone-input-labels.ts +0 -10
- package/src/components/phone-input.tsx +0 -282
- package/src/components/picker-sheet.tsx +0 -330
- package/src/components/pie-chart-labels.ts +0 -40
- package/src/components/pie-chart.tsx +0 -480
- package/src/components/popover-labels.ts +0 -14
- package/src/components/popover.tsx +0 -268
- package/src/components/progress-bar-labels.ts +0 -10
- package/src/components/progress-bar.tsx +0 -479
- package/src/components/qr-code.tsx +0 -76
- package/src/components/reauth-dialog-labels.ts +0 -13
- package/src/components/reauth-dialog.tsx +0 -265
- package/src/components/row-actions-labels.ts +0 -12
- package/src/components/row-actions.tsx +0 -795
- package/src/components/scroll-area.tsx +0 -123
- package/src/components/search-field.tsx +0 -192
- package/src/components/select.tsx +0 -294
- package/src/components/separator.tsx +0 -33
- package/src/components/series-chart-axes.ts +0 -342
- package/src/components/series-chart-budget.ts +0 -150
- package/src/components/series-chart-labels.ts +0 -33
- package/src/components/series-chart-thin.ts +0 -180
- package/src/components/series-chart-ticks.ts +0 -194
- package/src/components/series-chart.tsx +0 -1906
- package/src/components/server-wake-labels.ts +0 -11
- package/src/components/server-wake.tsx +0 -129
- package/src/components/settings-fields.tsx +0 -237
- package/src/components/share-card-labels.ts +0 -30
- package/src/components/share-card.tsx +0 -675
- package/src/components/signature-pad-labels.ts +0 -24
- package/src/components/signature-pad.tsx +0 -747
- package/src/components/signed-amount-labels.ts +0 -10
- package/src/components/signed-amount.tsx +0 -336
- package/src/components/skeleton.tsx +0 -80
- package/src/components/slider.tsx +0 -338
- package/src/components/sparkline-labels.ts +0 -14
- package/src/components/sparkline.tsx +0 -322
- package/src/components/spinner.tsx +0 -81
- package/src/components/stat-tile-labels.ts +0 -15
- package/src/components/stat-tile.tsx +0 -754
- package/src/components/status-dot.tsx +0 -170
- package/src/components/swatch-picker-labels.ts +0 -10
- package/src/components/swatch-picker.tsx +0 -283
- package/src/components/swipeable-row.tsx +0 -386
- package/src/components/switch.tsx +0 -273
- package/src/components/table-skeleton.tsx +0 -136
- package/src/components/table.tsx +0 -647
- package/src/components/tabs-labels.ts +0 -13
- package/src/components/tabs.tsx +0 -693
- package/src/components/text-link.tsx +0 -359
- package/src/components/text.tsx +0 -150
- package/src/components/textarea.tsx +0 -330
- package/src/components/tile-radio.tsx +0 -332
- package/src/components/time-input.tsx +0 -121
- package/src/components/toast-labels.ts +0 -12
- package/src/components/toast.tsx +0 -519
- package/src/components/toggle-group.tsx +0 -752
- package/src/components/toggle-legend.tsx +0 -394
- package/src/components/tooltip.tsx +0 -1149
- package/src/components/translation-review-editor.tsx +0 -290
- package/src/components/translation-review-labels.ts +0 -181
- package/src/components/translation-review-parts.tsx +0 -272
- package/src/components/translation-review.tsx +0 -1240
- package/src/components/tree-view.tsx +0 -589
- package/src/components/treemap-labels.ts +0 -47
- package/src/components/treemap-layout.ts +0 -210
- package/src/components/treemap.tsx +0 -1184
- package/src/components/trigger-aria.ts +0 -44
- package/src/components/use-anchor-dir.ts +0 -20
- package/src/components/use-mobile-reveal.ts +0 -62
- package/src/components/use-table-state.ts +0 -753
- package/src/components/user-avatar.tsx +0 -116
- package/src/components/wizard-stepper.tsx +0 -42
- package/src/components/write-lock-labels.ts +0 -10
- package/src/components/write-lock.tsx +0 -253
- package/src/currencies.ts +0 -90
- package/src/data-table.ts +0 -42
- package/src/demo/demo-banner.tsx +0 -153
- package/src/demo/demo-countdown.ts +0 -136
- package/src/demo/demo-ended.tsx +0 -90
- package/src/demo/demo-labels.ts +0 -78
- package/src/demo/demo-session.ts +0 -32
- package/src/demo/demo-start.tsx +0 -156
- package/src/eslint/index.ts +0 -161
- package/src/eslint/role-utilities.generated.ts +0 -146
- package/src/eslint/role-utilities.ts +0 -233
- package/src/feedback/feedback-attachment-download.tsx +0 -77
- package/src/feedback/feedback-attachment-labels.ts +0 -37
- package/src/feedback/feedback-attachment.tsx +0 -1239
- package/src/feedback/feedback-capture.ts +0 -287
- package/src/feedback/feedback-comment-thread.tsx +0 -353
- package/src/feedback/feedback-context-labels.ts +0 -11
- package/src/feedback/feedback-context.tsx +0 -245
- package/src/feedback/feedback-crash.ts +0 -547
- package/src/feedback/feedback-diagnostics.tsx +0 -41
- package/src/feedback/feedback-dialog-labels.ts +0 -29
- package/src/feedback/feedback-dialog.tsx +0 -452
- package/src/feedback/feedback-entry-file.tsx +0 -150
- package/src/feedback/feedback-inbox.tsx +0 -552
- package/src/feedback/feedback-labels.ts +0 -144
- package/src/feedback/feedback-menu-labels.ts +0 -12
- package/src/feedback/feedback-menu.tsx +0 -177
- package/src/feedback/feedback-mutation.ts +0 -20
- package/src/feedback/feedback-page-link.ts +0 -90
- package/src/feedback/feedback-public-labels.ts +0 -81
- package/src/feedback/feedback-public-list.tsx +0 -524
- package/src/feedback/feedback-public-switch.tsx +0 -102
- package/src/feedback/feedback-public-types.ts +0 -101
- package/src/feedback/feedback-record.ts +0 -428
- package/src/feedback/feedback-replies-context.ts +0 -9
- package/src/feedback/feedback-replies.tsx +0 -343
- package/src/feedback/feedback-rework-entry-chip.tsx +0 -18
- package/src/feedback/feedback-row-detail-labels.ts +0 -31
- package/src/feedback/feedback-row-detail.tsx +0 -871
- package/src/feedback/feedback-status-undo.ts +0 -109
- package/src/feedback/feedback-submit-dialog.tsx +0 -131
- package/src/feedback/feedback-submit.tsx +0 -270
- package/src/feedback/feedback-swipe.tsx +0 -192
- package/src/feedback/feedback-table-labels.ts +0 -27
- package/src/feedback/feedback-table.tsx +0 -912
- package/src/feedback/feedback-thread-labels.ts +0 -22
- package/src/feedback/feedback-thread-parts-labels.ts +0 -41
- package/src/feedback/feedback-thread.tsx +0 -905
- package/src/feedback/feedback-vocabulary.ts +0 -263
- package/src/feedback/feedback-vote-button.tsx +0 -124
- package/src/feedback.ts +0 -116
- package/src/hooks/use-anchored-panel.ts +0 -396
- package/src/hooks/use-anchored-rect.ts +0 -77
- package/src/hooks/use-announce.ts +0 -85
- package/src/hooks/use-authed-src.ts +0 -167
- package/src/hooks/use-body-scroll-lock.ts +0 -119
- package/src/hooks/use-breakpoint.ts +0 -133
- package/src/hooks/use-close-transition.ts +0 -107
- package/src/hooks/use-copy-to-clipboard.ts +0 -122
- package/src/hooks/use-debounce.ts +0 -114
- package/src/hooks/use-dismiss.ts +0 -371
- package/src/hooks/use-document-title.ts +0 -33
- package/src/hooks/use-file-drop.ts +0 -121
- package/src/hooks/use-file-picker-labels.ts +0 -28
- package/src/hooks/use-file-picker.tsx +0 -359
- package/src/hooks/use-focus-trap.ts +0 -199
- package/src/hooks/use-hotkey.ts +0 -212
- package/src/hooks/use-large-text.ts +0 -41
- package/src/hooks/use-long-press.ts +0 -140
- package/src/hooks/use-media-query.ts +0 -39
- package/src/hooks/use-mounted.ts +0 -39
- package/src/hooks/use-noindex.ts +0 -37
- package/src/hooks/use-overlay-history.ts +0 -714
- package/src/hooks/use-row-swipe.ts +0 -207
- package/src/hooks/use-search-param-state.ts +0 -434
- package/src/hooks/use-windowed-rows.ts +0 -225
- package/src/i18n/defaults.ts +0 -267
- package/src/i18n/german.ts +0 -2059
- package/src/i18n/kit-labels.tsx +0 -1003
- package/src/i18n/languages.ts +0 -349
- package/src/i18n/locales/de-CH.ts +0 -24
- package/src/i18n/locales/en.ts +0 -267
- package/src/i18n/locales/es.ts +0 -1999
- package/src/i18n/locales/fr.ts +0 -2037
- package/src/i18n/locales/hu.ts +0 -2004
- package/src/i18n/locales/it.ts +0 -2014
- package/src/i18n/locales/zh.ts +0 -1912
- package/src/i18n/plurals.ts +0 -86
- package/src/i18n/review.ts +0 -475
- package/src/i18n/shared-labels.ts +0 -138
- package/src/i18n/swiss.ts +0 -29
- package/src/index.ts +0 -1191
- package/src/landing/access.ts +0 -93
- package/src/landing/landing-actions.tsx +0 -97
- package/src/landing/landing-labels.ts +0 -59
- package/src/landing/landing-sections.tsx +0 -341
- package/src/landing/page-seo.ts +0 -261
- package/src/landing/public-header.tsx +0 -121
- package/src/landing/public-page.tsx +0 -106
- package/src/landing/routing.tsx +0 -225
- package/src/lib/broadcast.ts +0 -52
- package/src/lib/calc.ts +0 -323
- package/src/lib/chip-edge-snap.ts +0 -212
- package/src/lib/clipboard-minus.ts +0 -107
- package/src/lib/clipping.ts +0 -34
- package/src/lib/cn.ts +0 -28
- package/src/lib/column-mapping.ts +0 -234
- package/src/lib/countries.ts +0 -91
- package/src/lib/data-attributes.ts +0 -14
- package/src/lib/date-format.ts +0 -227
- package/src/lib/dates.ts +0 -288
- package/src/lib/day-format.ts +0 -96
- package/src/lib/decimal-marks.ts +0 -108
- package/src/lib/describe-failure.ts +0 -18
- package/src/lib/device-settings.ts +0 -147
- package/src/lib/direction.ts +0 -74
- package/src/lib/document-navigation.ts +0 -17
- package/src/lib/document-title.ts +0 -41
- package/src/lib/download.ts +0 -172
- package/src/lib/float-clearance.ts +0 -70
- package/src/lib/floating-stack.ts +0 -70
- package/src/lib/focus-left.ts +0 -156
- package/src/lib/format.ts +0 -585
- package/src/lib/http-status.ts +0 -38
- package/src/lib/iban.ts +0 -251
- package/src/lib/ime.ts +0 -24
- package/src/lib/intl-cache.ts +0 -27
- package/src/lib/iso-day.ts +0 -13
- package/src/lib/lazy-with-fallback.ts +0 -82
- package/src/lib/logger.ts +0 -69
- package/src/lib/minus.ts +0 -50
- package/src/lib/path-pattern.ts +0 -55
- package/src/lib/person-name.ts +0 -155
- package/src/lib/phone.ts +0 -208
- package/src/lib/plain-text.ts +0 -22
- package/src/lib/presence.ts +0 -18
- package/src/lib/qr-encode.ts +0 -444
- package/src/lib/quiet-focus.ts +0 -32
- package/src/lib/reduced-motion.ts +0 -22
- package/src/lib/refs.ts +0 -22
- package/src/lib/round.ts +0 -43
- package/src/lib/safe-storage.ts +0 -119
- package/src/lib/server-wake.ts +0 -315
- package/src/lib/session-refresh.ts +0 -472
- package/src/lib/share-format.ts +0 -18
- package/src/lib/status-tone.ts +0 -43
- package/src/lib/strip-fade.ts +0 -287
- package/src/lib/table-text.ts +0 -554
- package/src/lib/text-case.ts +0 -19
- package/src/lib/text-match.ts +0 -169
- package/src/lib/thenable.ts +0 -19
- package/src/lib/translation-review.ts +0 -769
- package/src/notifications/device-zone-report.ts +0 -67
- package/src/notifications/feedback-notification-types-labels.ts +0 -33
- package/src/notifications/feedback-notification-types.ts +0 -71
- package/src/notifications/notification-bell.tsx +0 -119
- package/src/notifications/notification-inbox.tsx +0 -309
- package/src/notifications/notification-parts.tsx +0 -81
- package/src/notifications/notification-types-setting.tsx +0 -406
- package/src/notifications/notification-types.ts +0 -89
- package/src/notifications/notifications-labels.ts +0 -287
- package/src/notifications/push-device-setting.tsx +0 -230
- package/src/notifications/push-devices-setting.tsx +0 -374
- package/src/notifications/push-worker.ts +0 -168
- package/src/notifications/quiet-hours-setting.tsx +0 -238
- package/src/notifications/unsubscribe-panel.tsx +0 -200
- package/src/notifications/use-push-device.ts +0 -448
- package/src/offline/local-first.ts +0 -100
- package/src/offline/pwa-update-prompt-labels.ts +0 -9
- package/src/offline/pwa-update-prompt.tsx +0 -78
- package/src/offline/query-persistence.ts +0 -391
- package/src/offline/service-worker-updates.ts +0 -81
- package/src/offline/shared-computer-labels.ts +0 -8
- package/src/offline/shared-computer.tsx +0 -87
- package/src/offline/sign-out-pending-dialog-labels.ts +0 -21
- package/src/offline/sign-out-pending-dialog.tsx +0 -135
- package/src/offline.ts +0 -37
- package/src/push-worker.ts +0 -25
- package/src/rhf/fields.tsx +0 -2187
- package/src/rhf/form-core.tsx +0 -324
- package/src/rhf/form.tsx +0 -12
- package/src/rhf/line-items.tsx +0 -135
- package/src/rhf/use-rhf-wizard-step.ts +0 -104
- package/src/rhf.ts +0 -21
- package/src/search/command-palette-labels.ts +0 -16
- package/src/search/command-palette.tsx +0 -624
- package/src/search/global-search-labels.ts +0 -13
- package/src/search/global-search.tsx +0 -660
- package/src/search/search-index.ts +0 -283
- package/src/search/use-command-key.ts +0 -23
- package/src/search.ts +0 -14
- package/src/settings/device-reset-setting-labels.ts +0 -20
- package/src/settings/device-reset-setting.tsx +0 -116
- package/src/settings/settings-card-classes.ts +0 -11
- package/src/settings/settings-catalogue.ts +0 -150
- package/src/settings/settings-context.ts +0 -33
- package/src/settings/settings-heading.tsx +0 -67
- package/src/settings/settings-labels.ts +0 -87
- package/src/settings/settings-layout.tsx +0 -471
- package/src/settings/settings-section.tsx +0 -108
- package/src/settings/use-account-appearance.ts +0 -148
- package/src/settings/use-account-language.ts +0 -146
- package/src/settings/use-settings-focus.ts +0 -128
- package/src/settings/use-settings-route.ts +0 -258
- package/src/shell/account-menu-language.tsx +0 -130
- package/src/shell/account-menu-text-size.tsx +0 -80
- package/src/shell/admin-menu.tsx +0 -183
- package/src/shell/app-shell-labels.ts +0 -11
- package/src/shell/app-shell.tsx +0 -1560
- package/src/shell/auth-layout.tsx +0 -186
- package/src/shell/company-switcher-labels.ts +0 -13
- package/src/shell/company-switcher.tsx +0 -136
- package/src/shell/dev-menu.tsx +0 -257
- package/src/shell/fill-height.tsx +0 -45
- package/src/shell/language-code.ts +0 -5
- package/src/shell/option-switcher-menu.tsx +0 -84
- package/src/shell/sync-status-indicator.tsx +0 -303
- package/src/shell/top-bar-actions.tsx +0 -87
- package/src/shell/top-bar-brand.tsx +0 -78
- package/src/shell/top-bar-parts-labels.ts +0 -148
- package/src/shell/top-bar.tsx +0 -40
- package/src/shell/topbar-action-menu.tsx +0 -567
- package/src/shell/topbar-controls.tsx +0 -269
- package/src/shell/tour-menu.tsx +0 -187
- package/src/shell.ts +0 -108
- package/src/sync/db.ts +0 -129
- package/src/sync/engine.ts +0 -1011
- package/src/sync/hooks.ts +0 -98
- package/src/sync/testing.ts +0 -73
- package/src/sync/wire.ts +0 -61
- package/src/sync.ts +0 -37
- package/src/table-text.ts +0 -8
- package/src/testing/css-variables.generated.ts +0 -112
- package/src/testing/css-variables.ts +0 -189
- package/src/testing/index.ts +0 -29
- package/src/testing/react.ts +0 -58
- package/src/testing/tour.ts +0 -41
- package/src/testing/viewport.ts +0 -357
- package/src/theme/chart-palette.ts +0 -232
- package/src/theme/color.ts +0 -272
- package/src/theme/contrast-tokens.ts +0 -268
- package/src/theme/contrast.ts +0 -250
- package/src/theme/palette-derive.ts +0 -825
- package/src/theme/palette-presets.ts +0 -544
- package/src/theme/palette-store.ts +0 -108
- package/src/theme/text-size.ts +0 -289
- package/src/theme/theme-store.ts +0 -157
- package/src/tour/tour-catalogue-labels.ts +0 -75
- package/src/tour/tour-catalogue.tsx +0 -335
- package/src/tour/tour-dock.ts +0 -134
- package/src/tour/tour-engine.ts +0 -37
- package/src/tour/tour-gates.ts +0 -218
- package/src/tour/tour-guide-button.tsx +0 -64
- package/src/tour/tour-guide-labels.ts +0 -15
- package/src/tour/tour-info.ts +0 -144
- package/src/tour/tour-labels.ts +0 -23
- package/src/tour/tour-overlay.tsx +0 -1170
- package/src/tour/tour.tsx +0 -750
- package/src/tour/use-tour-progress.ts +0 -671
- package/src/tour/use-tour-url-sync.ts +0 -266
- package/src/tour.ts +0 -21
- package/src/vite-env.d.ts +0 -23
- package/src/wizard/stepper-nav.tsx +0 -360
- package/src/wizard/types.ts +0 -275
- package/src/wizard/use-wizard.ts +0 -560
- package/src/wizard/validation.ts +0 -39
- package/src/wizard/wizard-context.tsx +0 -74
- package/src/wizard/wizard-labels.ts +0 -29
- package/src/wizard/wizard-step.tsx +0 -76
- package/src/wizard/wizard-summary.tsx +0 -84
- package/src/wizard.ts +0 -15
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
import { useCallback, useId, useMemo } from "react";
|
|
2
|
-
import type { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
|
|
3
|
-
import { FieldChevron, FIELD_TRIGGER, FIELD_INVALID, FIELD_FLOATING_PAD } from "./field-base";
|
|
4
|
-
import { FieldLabel } from "./field-parts";
|
|
5
|
-
import { cn } from "../lib/cn";
|
|
6
|
-
import { ComboboxPanel, useComboboxCore, type ComboOption } from "./combobox-core";
|
|
7
|
-
import {
|
|
8
|
-
assignRef,
|
|
9
|
-
EndHintRow,
|
|
10
|
-
LABEL_IN_ROW,
|
|
11
|
-
LockedReason,
|
|
12
|
-
StaticLabelRow,
|
|
13
|
-
useFieldMessages,
|
|
14
|
-
useLockReason,
|
|
15
|
-
type DisabledReasonDisplay,
|
|
16
|
-
type FieldHelpProps,
|
|
17
|
-
} from "./field-parts";
|
|
18
|
-
import type { CommitScope } from "./write-lock";
|
|
19
|
-
import {
|
|
20
|
-
DEFAULT_COMMON_LABELS,
|
|
21
|
-
DEFAULT_MULTI_SELECT_LABELS,
|
|
22
|
-
useKitLabels,
|
|
23
|
-
type MultiSelectLabels,
|
|
24
|
-
type LabelOverride,
|
|
25
|
-
} from "../i18n/kit-labels";
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* One row of a {@link MultiSelect}. Generic over its value since 0.34 (API-4), so a list of
|
|
29
|
-
* number ids hands `onChange` numbers — `MultiSelectOption` alone is the old
|
|
30
|
-
* `string | number` row.
|
|
31
|
-
*/
|
|
32
|
-
export interface MultiSelectOption<V extends string | number = string | number> {
|
|
33
|
-
value: V;
|
|
34
|
-
label: string;
|
|
35
|
-
/** A second line under the label — a postcode, a count (keksdose #147). Searchable. */
|
|
36
|
-
hint?: string;
|
|
37
|
-
/**
|
|
38
|
-
* Shown but not takeable — {@link ComboOption.disabled}: dimmed, `aria-disabled`, passed
|
|
39
|
-
* over by the arrow keys, and a press does nothing. A chosen disabled row stays chosen:
|
|
40
|
-
* "Select all" and "Clear" leave it as it is. Say why in `hint`.
|
|
41
|
-
*/
|
|
42
|
-
disabled?: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** `onChange` is the kit's — "the selection changed", carrying the new values —
|
|
46
|
-
* rather than the div's form event. Generic over the option value (API-4): `V` is
|
|
47
|
-
* inferred from `options` and `value`, so `onChange` hands back `number[]` for number
|
|
48
|
-
* ids and `string[]` for string ones, and no call site casts. */
|
|
49
|
-
export interface MultiSelectProps<V extends string | number = string | number>
|
|
50
|
-
extends Omit<ComponentPropsWithoutRef<"div">, "onChange">, FieldHelpProps {
|
|
51
|
-
options: readonly MultiSelectOption<V>[];
|
|
52
|
-
/** The chosen values — the select family's `value` (API-4). */
|
|
53
|
-
value?: readonly V[];
|
|
54
|
-
onChange: (next: V[]) => void;
|
|
55
|
-
/** Singular/plural countable label, used when 1+ items are selected. Default:
|
|
56
|
-
* `labels.selectedCount`, else `multiSelect.selectedCount` from the provider — the
|
|
57
|
-
* bare count in English. */
|
|
58
|
-
itemLabel?: (count: number) => string;
|
|
59
|
-
/** Shown when nothing is picked, unless `labels.all` says otherwise — it has always
|
|
60
|
-
* doubled as the "nothing picked" text. */
|
|
61
|
-
placeholder?: string;
|
|
62
|
-
/** Embedded top-boundary label, matching the native Input/Select fields. */
|
|
63
|
-
label?: ReactNode;
|
|
64
|
-
/**
|
|
65
|
-
* Per-instance overrides of the provider's `multiSelect` namespace, over English — the
|
|
66
|
-
* kit's `labels` shape, where this took four string props until 0.35 (API-4: `allLabel`,
|
|
67
|
-
* `searchLabel`, `selectAllLabel`, `clearLabel`). `all` is the trigger when nothing is
|
|
68
|
-
* picked: `labels.all`, then `placeholder`, then the provider's.
|
|
69
|
-
*/
|
|
70
|
-
labels?: LabelOverride<MultiSelectLabels>;
|
|
71
|
-
/**
|
|
72
|
-
* Extra classes for the open PANEL. The panel is portalled now (dev#548) and sizes
|
|
73
|
-
* itself: as wide as the trigger and at least 16rem, growing with its rows up to 32rem
|
|
74
|
-
* (or the trigger) — what this prop was asked for (keksdose feedback #147: the market
|
|
75
|
-
* picker's postcode, distance and receipt-count hints were cut at 16rem). A `w-*` class
|
|
76
|
-
* here no longer sets the width.
|
|
77
|
-
*/
|
|
78
|
-
panelClassName?: string;
|
|
79
|
-
/** Required and unanswered — {@link FIELD_INVALID}, the same rose border the
|
|
80
|
-
* native `Select` has worn since feedback #235. Every field-styled control in
|
|
81
|
-
* this package carries it now, so a form can mark any of its fields rather than
|
|
82
|
-
* only the one that happened to have it first. */
|
|
83
|
-
invalid?: boolean;
|
|
84
|
-
/** What is wrong with the selection, in the caller's words. Rendered under the
|
|
85
|
-
* field, pointed at by the trigger's `aria-describedby` (merged with any the
|
|
86
|
-
* caller passed) and implies `invalid` — {@link Input}'s `error`, on the same
|
|
87
|
-
* rules. */
|
|
88
|
-
error?: ReactNode;
|
|
89
|
-
/**
|
|
90
|
-
* Standing advice for the field — {@link Combobox}'s `hint` (keksdose K4): plain TEXT
|
|
91
|
-
* is a caption under the field on the trigger's `aria-describedby`, before any error;
|
|
92
|
-
* a {@link FieldHint} "?" rides the label line, or with no label sits at the trigger's
|
|
93
|
-
* end edge, outside the box. Not an option's `hint`, which stays on its row.
|
|
94
|
-
*/
|
|
95
|
-
hint?: ReactNode;
|
|
96
|
-
/** The trigger cannot be opened: FIELD_BASE's settled grey, no chevron (as a
|
|
97
|
-
* disabled {@link Select} drops its own), and a dimmed label. */
|
|
98
|
-
disabled?: boolean;
|
|
99
|
-
/**
|
|
100
|
-
* Why the selection cannot be changed — {@link EntityCombobox}'s `disabledReason`: the
|
|
101
|
-
* trigger stays focusable and `aria-disabled`, the list does not open and `onChange`
|
|
102
|
-
* never fires; the reason is a line under the field at Large and on a touch screen,
|
|
103
|
-
* else in the kit {@link Tooltip} (`disabledReasonDisplay`), and on the trigger's
|
|
104
|
-
* `aria-describedby`. Wins over `disabled`.
|
|
105
|
-
*/
|
|
106
|
-
disabledReason?: ReactNode;
|
|
107
|
-
/** Where the reason shows — {@link Button}'s `disabledReasonDisplay`: a line under the
|
|
108
|
-
* field at Large and on a touch screen by default, the tooltip otherwise. */
|
|
109
|
-
disabledReasonDisplay?: DisabledReasonDisplay;
|
|
110
|
-
/** This picker COMMITS — toggling saves (a filter persisted per user, a settings row).
|
|
111
|
-
* Locked the `disabledReason` way under a locked {@link WriteLockProvider}, with the
|
|
112
|
-
* lock's reason. Leave it off inside a form that has its own Save. */
|
|
113
|
-
commit?: CommitScope;
|
|
114
|
-
/** The TRIGGER — the focusable `<button>` — as a React 19 ref prop, as on
|
|
115
|
-
* {@link MultiEntityCombobox} (react-hook-form's focus-on-error). Not the wrapper. */
|
|
116
|
-
ref?: Ref<HTMLButtonElement>;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** "Select all" and "Clear": dimmed, with no hover, while there is nothing for them to do. */
|
|
120
|
-
const TOOLBAR_BUTTON =
|
|
121
|
-
"rounded px-2 py-0.5 text-secondary hover:bg-hover aria-disabled:cursor-not-allowed aria-disabled:opacity-40 aria-disabled:hover:bg-transparent";
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Pick several of a fixed list — a filter's accounts, a comparison's data sets — with a
|
|
125
|
-
* search box, "Select all" and "Clear"; nothing picked reads as "all".
|
|
126
|
-
*
|
|
127
|
-
* Built on the picker family's foundation since round 0.34 (Wave 2, DUP-4):
|
|
128
|
-
* `useComboboxCore` + `ComboboxPanel`, as {@link MultiEntityCombobox} is. It was an
|
|
129
|
-
* absolute `DropdownPanel`, which an `overflow` ancestor clipped (dev#548) and which on a
|
|
130
|
-
* phone was a 16rem panel between the field and the keyboard; it now has the full-screen
|
|
131
|
-
* sheet (live #200), the portal, the live result count, disabled rows and the search
|
|
132
|
-
* that folds accents ("zurich" finds Zürich, DUP-5).
|
|
133
|
-
*/
|
|
134
|
-
export function MultiSelect<V extends string | number = string | number>(props: MultiSelectProps<V>) {
|
|
135
|
-
const {
|
|
136
|
-
options,
|
|
137
|
-
value: valueProp,
|
|
138
|
-
onChange,
|
|
139
|
-
itemLabel,
|
|
140
|
-
placeholder,
|
|
141
|
-
label,
|
|
142
|
-
labels: labelsProp,
|
|
143
|
-
className,
|
|
144
|
-
panelClassName,
|
|
145
|
-
invalid,
|
|
146
|
-
error,
|
|
147
|
-
hint,
|
|
148
|
-
help,
|
|
149
|
-
disabled,
|
|
150
|
-
disabledReason,
|
|
151
|
-
disabledReasonDisplay,
|
|
152
|
-
commit,
|
|
153
|
-
ref,
|
|
154
|
-
id,
|
|
155
|
-
"aria-label": ariaLabel,
|
|
156
|
-
// Off `rest` and onto the trigger, which is the combobox a reader meets: `Field`'s
|
|
157
|
-
// render-prop spreads `{ id, aria-describedby, aria-invalid, aria-required }`, and on
|
|
158
|
-
// the wrapper div the label named nothing and the required state described nothing
|
|
159
|
-
// (DUP-8, refactor audit 2026-10 — Combobox's rule).
|
|
160
|
-
"aria-describedby": ariaDescribedBy,
|
|
161
|
-
"aria-invalid": ariaInvalid,
|
|
162
|
-
"aria-required": ariaRequired,
|
|
163
|
-
...rest
|
|
164
|
-
} = props;
|
|
165
|
-
const value = useMemo<readonly V[]>(() => valueProp ?? [], [valueProp]);
|
|
166
|
-
// The rows as the family's options — the hint is the sublabel, searched like the label.
|
|
167
|
-
const comboOptions = useMemo(
|
|
168
|
-
() =>
|
|
169
|
-
options.map((o): ComboOption<V> => ({ value: o.value, label: o.label, sublabel: o.hint, disabled: o.disabled })),
|
|
170
|
-
[options],
|
|
171
|
-
);
|
|
172
|
-
// Back closes the open list, as it did on `useDropdown` (keksdose live #309).
|
|
173
|
-
const core = useComboboxCore<V>({ options: comboOptions, backCloses: true });
|
|
174
|
-
const { open, setOpen, triggerRef } = core;
|
|
175
|
-
// The core anchors the panel to the trigger and hands focus back to it; the caller's
|
|
176
|
-
// `ref` wants the same element. One callback feeds both.
|
|
177
|
-
const setTrigger = useCallback(
|
|
178
|
-
(el: HTMLButtonElement | null) => {
|
|
179
|
-
triggerRef.current = el;
|
|
180
|
-
assignRef(ref, el);
|
|
181
|
-
},
|
|
182
|
-
[ref, triggerRef],
|
|
183
|
-
);
|
|
184
|
-
// `labels` > the provider's `multiSelect` > English. `all` is resolved apart below:
|
|
185
|
-
// between the instance's and the provider's sits `placeholder`, which has always
|
|
186
|
-
// doubled as the "nothing picked" text, and a caller who set it must keep seeing it.
|
|
187
|
-
const text = useKitLabels("multiSelect", DEFAULT_MULTI_SELECT_LABELS, {
|
|
188
|
-
search: labelsProp?.search,
|
|
189
|
-
selectAll: labelsProp?.selectAll,
|
|
190
|
-
clear: labelsProp?.clear,
|
|
191
|
-
selectedCount: labelsProp?.selectedCount ?? itemLabel,
|
|
192
|
-
});
|
|
193
|
-
const common = useKitLabels("common", DEFAULT_COMMON_LABELS);
|
|
194
|
-
|
|
195
|
-
// The lock — EntityCombobox's: the trigger stays reachable and says why.
|
|
196
|
-
const lock = useLockReason(commit, disabledReason);
|
|
197
|
-
const inert = lock.locked || Boolean(disabled);
|
|
198
|
-
// A lock (or `disabled`) arriving while the list is up closes it — adjusted while
|
|
199
|
-
// rendering, as CountrySelect does, so no frame shows a list that can no longer be used.
|
|
200
|
-
if (inert && open) setOpen(false);
|
|
201
|
-
|
|
202
|
-
// The caller's ids, the caption, a lock's reason, the error — Select's order.
|
|
203
|
-
const field = useFieldMessages({
|
|
204
|
-
hint,
|
|
205
|
-
help,
|
|
206
|
-
name: label ?? ariaLabel,
|
|
207
|
-
error,
|
|
208
|
-
invalid,
|
|
209
|
-
describedBy: ariaDescribedBy,
|
|
210
|
-
ariaInvalid,
|
|
211
|
-
reasonId: lock.locked && lock.reasonId,
|
|
212
|
-
});
|
|
213
|
-
// One id per instance: `aria-controls` on the trigger names the list while the
|
|
214
|
-
// list is still closed.
|
|
215
|
-
const listboxId = `${useId()}-listbox`;
|
|
216
|
-
|
|
217
|
-
const valueSet = useMemo(() => new Set<V>(value), [value]);
|
|
218
|
-
const allChecked = options.length > 0 && options.every((o) => valueSet.has(o.value));
|
|
219
|
-
const selectedSummary =
|
|
220
|
-
value.length === 0 || allChecked ? (labelsProp?.all ?? placeholder ?? text.all) : text.selectedCount(value.length);
|
|
221
|
-
|
|
222
|
-
const toggle = (o: ComboOption<V>) => {
|
|
223
|
-
if (lock.locked) return;
|
|
224
|
-
if (valueSet.has(o.value)) onChange(value.filter((v) => v !== o.value));
|
|
225
|
-
else onChange([...value, o.value]);
|
|
226
|
-
// Stays open, as a pressed row always has: this control answers "which of these",
|
|
227
|
-
// which is rarely one of them.
|
|
228
|
-
};
|
|
229
|
-
// A chosen disabled row stays chosen, an unchosen one stays out — the row refuses to be
|
|
230
|
-
// toggled, by a press or by the two actions.
|
|
231
|
-
const selectAll = () => onChange(options.filter((o) => !o.disabled || valueSet.has(o.value)).map((o) => o.value));
|
|
232
|
-
const clearAll = () => onChange(options.filter((o) => o.disabled && valueSet.has(o.value)).map((o) => o.value));
|
|
233
|
-
const canSelectAll = options.some((o) => !o.disabled && !valueSet.has(o.value));
|
|
234
|
-
const canClear = options.some((o) => !o.disabled && valueSet.has(o.value));
|
|
235
|
-
|
|
236
|
-
const trigger = (
|
|
237
|
-
<button
|
|
238
|
-
ref={setTrigger}
|
|
239
|
-
id={id}
|
|
240
|
-
type="button"
|
|
241
|
-
// The focusable kind of disabled while locked (Button's rule): native `disabled`
|
|
242
|
-
// would take the field out of the tab order, and the reason with it.
|
|
243
|
-
disabled={lock.locked ? undefined : disabled}
|
|
244
|
-
aria-disabled={lock.locked || undefined}
|
|
245
|
-
// A combobox, not a bare button: this trigger carried `aria-invalid`, which
|
|
246
|
-
// `button` does not support, so a required-and-empty filter painted its rose
|
|
247
|
-
// border and announced nothing (ESLint's `role-supports-aria-props`, the
|
|
248
|
-
// audit's §a11y). The role that describes it is the one that also supports
|
|
249
|
-
// the attribute.
|
|
250
|
-
role="combobox"
|
|
251
|
-
aria-expanded={open}
|
|
252
|
-
aria-controls={listboxId}
|
|
253
|
-
aria-haspopup="listbox"
|
|
254
|
-
// The label is a floating <span>, not a <label for>, so without this the
|
|
255
|
-
// trigger announces only its summary — "3 selected", with nothing saying
|
|
256
|
-
// three of WHAT. The label AND the summary, because `aria-label` replaces
|
|
257
|
-
// the content rather than adding to it; the same composition its two
|
|
258
|
-
// siblings use, so a form row of pickers reads the same way throughout.
|
|
259
|
-
// A caller's own name wins: two filters labelled "Accounts" on one screen have
|
|
260
|
-
// to be told apart, and only the caller knows by what.
|
|
261
|
-
aria-label={ariaLabel ?? (typeof label === "string" ? common.fieldValue(label, selectedSummary) : undefined)}
|
|
262
|
-
onClick={() => {
|
|
263
|
-
if (!inert) setOpen((v) => !v);
|
|
264
|
-
}}
|
|
265
|
-
// Down/Up opens the list from the closed trigger, per the APG; Enter and
|
|
266
|
-
// Space already do through the button's own click.
|
|
267
|
-
onKeyDown={(e) => {
|
|
268
|
-
if (inert) return;
|
|
269
|
-
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
270
|
-
e.preventDefault();
|
|
271
|
-
setOpen(true);
|
|
272
|
-
}
|
|
273
|
-
}}
|
|
274
|
-
aria-invalid={field.isInvalid || undefined}
|
|
275
|
-
aria-required={ariaRequired}
|
|
276
|
-
// On the TRIGGER, where focus lands — the `aria-describedby` a caller put on
|
|
277
|
-
// the component is taken off the wrapper for the same reason.
|
|
278
|
-
aria-describedby={field.describedBy}
|
|
279
|
-
className={cn(
|
|
280
|
-
FIELD_TRIGGER,
|
|
281
|
-
"pe-9",
|
|
282
|
-
label !== undefined && FIELD_FLOATING_PAD,
|
|
283
|
-
// FIELD_TRIGGER's hover would still light a trigger nothing can open.
|
|
284
|
-
"disabled:hover:bg-surface-2",
|
|
285
|
-
// Dimmed like EntityCombobox's and MultiEntityCombobox's disabled triggers;
|
|
286
|
-
// only the label was, so a disabled MultiSelect read as live (showcase audit).
|
|
287
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
288
|
-
lock.locked && "cursor-not-allowed opacity-50",
|
|
289
|
-
field.isInvalid && FIELD_INVALID,
|
|
290
|
-
)}
|
|
291
|
-
>
|
|
292
|
-
{/* The summary IS the field's value, so it inherits FIELD_BASE's ink rather
|
|
293
|
-
than restating a lighter one (Keksdose dev#477). An ellipsis at Normal; from
|
|
294
|
-
Large up it wraps and the trigger grows, as DatePicker's value does (text
|
|
295
|
-
size §10.17, round 0.34 T1). */}
|
|
296
|
-
<span className="truncate-until-large">{selectedSummary}</span>
|
|
297
|
-
{!inert && <FieldChevron />}
|
|
298
|
-
</button>
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
return (
|
|
302
|
-
// `rest` dresses the wrapper; the name belongs to the trigger below it, which is
|
|
303
|
-
// the thing with a role. Spread FIRST so the ARIA the trigger composes, and the
|
|
304
|
-
// handlers that open the list, cannot be replaced by accident from outside.
|
|
305
|
-
<div {...rest} className={cn("relative", className)}>
|
|
306
|
-
{label !== undefined && field.labelHint === undefined && (
|
|
307
|
-
<FieldLabel className={inert ? "opacity-50" : undefined}>{label}</FieldLabel>
|
|
308
|
-
)}
|
|
309
|
-
<EndHintRow hint={label === undefined ? field.labelHint : undefined}>
|
|
310
|
-
{lock.locked ? (
|
|
311
|
-
// Button's frame: the line under the trigger, or the Tooltip with a hidden copy
|
|
312
|
-
// for `aria-describedby`.
|
|
313
|
-
<LockedReason lock={lock} display={disabledReasonDisplay} className="block">
|
|
314
|
-
{trigger}
|
|
315
|
-
</LockedReason>
|
|
316
|
-
) : (
|
|
317
|
-
trigger
|
|
318
|
-
)}
|
|
319
|
-
</EndHintRow>
|
|
320
|
-
{/* With a "?" the label shares the top strip with it — after the trigger, so the
|
|
321
|
-
"?" follows the control in the tab order, as on Input and Select. */}
|
|
322
|
-
{label !== undefined && field.labelHint !== undefined && (
|
|
323
|
-
<StaticLabelRow hint={field.labelHint}>
|
|
324
|
-
<FieldLabel className={cn(LABEL_IN_ROW, inert && "opacity-50")}>{label}</FieldLabel>
|
|
325
|
-
</StaticLabelRow>
|
|
326
|
-
)}
|
|
327
|
-
{field.below}
|
|
328
|
-
<ComboboxPanel
|
|
329
|
-
core={core}
|
|
330
|
-
listboxId={listboxId}
|
|
331
|
-
multi
|
|
332
|
-
// On a phone the list is a full-screen sheet, which needs the field's own name
|
|
333
|
-
// to say what it asks for (live #200).
|
|
334
|
-
sheetTitle={label ?? placeholder}
|
|
335
|
-
searchPlaceholder={text.search}
|
|
336
|
-
isSelected={(v) => valueSet.has(v)}
|
|
337
|
-
onChoose={toggle}
|
|
338
|
-
showCreate={false}
|
|
339
|
-
onCreate={() => {}}
|
|
340
|
-
createContent={null}
|
|
341
|
-
// At least the trigger's width and 16rem, growing with the rows to 32rem: the
|
|
342
|
-
// hints are why it was widened at all (keksdose #147).
|
|
343
|
-
width={{ minRem: 16, fit: true, maxRem: 32 }}
|
|
344
|
-
className={panelClassName}
|
|
345
|
-
// Reached by Tab from the search box (the panel's rows are not tab stops), and
|
|
346
|
-
// `aria-disabled` with a guarded click rather than `disabled`: a pressed "Clear"
|
|
347
|
-
// with nothing left to clear disabled itself under the focus, which dropped it to
|
|
348
|
-
// <body> — JumpCalendar's arrows are the rule (refactor audit 2026-10-30, INP-9).
|
|
349
|
-
toolbar={
|
|
350
|
-
<div className="flex items-center justify-between gap-2 px-2 py-1.5 text-xs">
|
|
351
|
-
<button
|
|
352
|
-
type="button"
|
|
353
|
-
onClick={() => {
|
|
354
|
-
if (canSelectAll) selectAll();
|
|
355
|
-
}}
|
|
356
|
-
aria-disabled={!canSelectAll || undefined}
|
|
357
|
-
className={TOOLBAR_BUTTON}
|
|
358
|
-
>
|
|
359
|
-
{text.selectAll}
|
|
360
|
-
</button>
|
|
361
|
-
<button
|
|
362
|
-
type="button"
|
|
363
|
-
onClick={() => {
|
|
364
|
-
if (canClear) clearAll();
|
|
365
|
-
}}
|
|
366
|
-
aria-disabled={!canClear || undefined}
|
|
367
|
-
className={TOOLBAR_BUTTON}
|
|
368
|
-
>
|
|
369
|
-
{text.clear}
|
|
370
|
-
</button>
|
|
371
|
-
</div>
|
|
372
|
-
}
|
|
373
|
-
/>
|
|
374
|
-
</div>
|
|
375
|
-
);
|
|
376
|
-
}
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { useLayoutEffect, useRef } from "react";
|
|
2
|
-
import type { ComponentPropsWithoutRef, ComponentType, MouseEvent, ReactElement, ReactNode, Ref } from "react";
|
|
3
|
-
import { cn } from "../lib/cn";
|
|
4
|
-
import { scrollIntoStrip, useStripFade } from "../lib/strip-fade";
|
|
5
|
-
import { useKitLink } from "../i18n/kit-labels";
|
|
6
|
-
import { FOCUS_RING } from "./focus-ring";
|
|
7
|
-
import { pickLinkRenderer, RenderedKitLink } from "./text-link";
|
|
8
|
-
|
|
9
|
-
export interface NavPillItem<T extends string> {
|
|
10
|
-
value: T;
|
|
11
|
-
label: ReactNode;
|
|
12
|
-
/** Where the pill leads. With one it is a link (see `renderLink`); without, a button
|
|
13
|
-
* that calls `onSelect`. */
|
|
14
|
-
href?: string;
|
|
15
|
-
/** A Lucide icon (or any component taking a `className`), before the label. */
|
|
16
|
-
icon?: ComponentType<{ className?: string; "aria-hidden"?: boolean }>;
|
|
17
|
-
/** Buttons only — a link cannot be disabled. */
|
|
18
|
-
disabled?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** What {@link NavPillsProps.renderLink} is handed. Spread it onto your router's link
|
|
22
|
-
* — `({ href, ...p }) => <Link to={href} {...p} />`. */
|
|
23
|
-
export interface NavPillLinkProps {
|
|
24
|
-
href: string;
|
|
25
|
-
className: string;
|
|
26
|
-
children: ReactNode;
|
|
27
|
-
"aria-current": NavPillsCurrent | undefined;
|
|
28
|
-
onClick: (e: MouseEvent<HTMLAnchorElement>) => void;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** The `aria-current` token the current pill carries. */
|
|
32
|
-
export type NavPillsCurrent = "page" | "step" | "location" | "true";
|
|
33
|
-
|
|
34
|
-
export interface NavPillsProps<T extends string> extends Omit<
|
|
35
|
-
ComponentPropsWithoutRef<"nav">,
|
|
36
|
-
"children" | "onSelect"
|
|
37
|
-
> {
|
|
38
|
-
items: NavPillItem<T>[];
|
|
39
|
-
/** The pill that is current. `null` or a value not in `items`: none is. */
|
|
40
|
-
current: T | null;
|
|
41
|
-
/** Called with the pill's value on a click — of a button, and of a link too (before
|
|
42
|
-
* the router follows it), for a caller that keeps the choice in state as well. */
|
|
43
|
-
onSelect?: (value: T) => void;
|
|
44
|
-
/** Your router's link. Default: the `<UiKitProvider linkComponent>` (for an in-app
|
|
45
|
-
* `href`), then `<a>`. The API `Breadcrumbs`, `Chip` and `ListItem` share. */
|
|
46
|
-
renderLink?: (props: NavPillLinkProps) => ReactElement;
|
|
47
|
-
/** What `aria-current` says on the current pill. Default `page` where the items
|
|
48
|
-
* are links and `true` where they are buttons (keksdose's swipe-surface picker
|
|
49
|
-
* switches a panel on the same page, which is not a page). */
|
|
50
|
-
currentType?: NavPillsCurrent;
|
|
51
|
-
/** `sm`: 12px pills — the compact size of a {@link ToggleGroup}. Default `md`. */
|
|
52
|
-
size?: "sm" | "md";
|
|
53
|
-
/** Render a `<nav>` landmark (default) or a plain `<div role="group">` for a picker
|
|
54
|
-
* that is not the page's navigation. Name either with `aria-label`. */
|
|
55
|
-
landmark?: boolean;
|
|
56
|
-
/** Classes for every pill. */
|
|
57
|
-
itemClassName?: string;
|
|
58
|
-
/**
|
|
59
|
-
* 0.49: `wrap` (default) puts the pills on as many rows as they need. `scroll` keeps
|
|
60
|
-
* them on ONE row that scrolls sideways — faded at a cut edge, the current pill
|
|
61
|
-
* scrolled into view (the row only, never the page) — for a strip that must stay one
|
|
62
|
-
* line high, as a section's pages under a page title on a phone.
|
|
63
|
-
*/
|
|
64
|
-
layout?: "wrap" | "scroll";
|
|
65
|
-
/** The `<nav>` (or the `<div role="group">`) — hence `HTMLElement` (0.34, API-2,
|
|
66
|
-
* refactor audit 2026-10). */
|
|
67
|
-
ref?: Ref<HTMLElement>;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// The pill is a ToggleGroup segment's (`rounded`, `px-3 py-1.5`, the inverse fill for
|
|
71
|
-
// the current one), so a strip of these beside a segmented control reads as the same
|
|
72
|
-
// family. Unlike the segments, a pill never truncates: the strip WRAPS instead. Its focus
|
|
73
|
-
// ring is the kit's one focus frame (text-size §5), in brand; until 0.34 it copied the
|
|
74
|
-
// segment's `ring-strong` too (refactor audit 2026-10, DOC-7).
|
|
75
|
-
const PILL = `inline-flex items-center gap-1.5 whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus:outline-none ${FOCUS_RING} [&_svg]:size-4 [&_svg]:shrink-0`;
|
|
76
|
-
const PILL_SM = "gap-1 px-2 py-1 text-xs [&_svg]:size-3.5";
|
|
77
|
-
const PILL_CURRENT = "bg-inverse text-inverse";
|
|
78
|
-
const PILL_IDLE = "text-secondary hover:bg-hover hover:text-primary";
|
|
79
|
-
const PILL_DISABLED = "cursor-not-allowed opacity-50 hover:bg-transparent hover:text-secondary";
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* A set of links or buttons that WRAPS onto as many rows as it needs, the current one
|
|
83
|
-
* filled and marked `aria-current`.
|
|
84
|
-
*
|
|
85
|
-
* keksdose's swipe-settings card (swipe-settings-card:152) hand-rolled this: four
|
|
86
|
-
* surface names that do not fit a 406px phone, and a sideways scroll would hide the
|
|
87
|
-
* ones that do not fit behind a gesture nothing announces (live #332: *"Have the tabs
|
|
88
|
-
* in more rows, rather than scrolling sideways"*). It is not {@link Tabs} (which
|
|
89
|
-
* scrolls; its multirow `wrap` went in 0.41) because its items are not tabs: a `role="tab"` promises a tabpanel, a roving tab
|
|
90
|
-
* stop and arrow keys, and a set of links to pages (or of buttons that switch the rest
|
|
91
|
-
* of a card) promises none of that. So every pill is its own tab stop, the set is a
|
|
92
|
-
* list (a screen reader hears "list, 4 items"), and "current" is `aria-current` — the
|
|
93
|
-
* attribute a link to where you already are carries.
|
|
94
|
-
*/
|
|
95
|
-
export function NavPills<T extends string>({
|
|
96
|
-
items,
|
|
97
|
-
current,
|
|
98
|
-
onSelect,
|
|
99
|
-
renderLink,
|
|
100
|
-
currentType,
|
|
101
|
-
size = "md",
|
|
102
|
-
landmark = true,
|
|
103
|
-
itemClassName,
|
|
104
|
-
layout = "wrap",
|
|
105
|
-
className,
|
|
106
|
-
ref,
|
|
107
|
-
...rest
|
|
108
|
-
}: NavPillsProps<T>) {
|
|
109
|
-
const kitLink = useKitLink();
|
|
110
|
-
const Root = landmark ? "nav" : "div";
|
|
111
|
-
const scroll = layout === "scroll";
|
|
112
|
-
const listRef = useRef<HTMLUListElement>(null);
|
|
113
|
-
const fade = useStripFade(listRef);
|
|
114
|
-
// The current pill into view — the row only, never the page.
|
|
115
|
-
useLayoutEffect(() => {
|
|
116
|
-
const list = listRef.current;
|
|
117
|
-
const currentPill = list?.querySelector<HTMLElement>("[aria-current]");
|
|
118
|
-
if (scroll && list && currentPill) scrollIntoStrip(list, currentPill);
|
|
119
|
-
}, [scroll, current]);
|
|
120
|
-
return (
|
|
121
|
-
<Root
|
|
122
|
-
{...rest}
|
|
123
|
-
ref={ref as Ref<HTMLDivElement> | undefined}
|
|
124
|
-
role={landmark ? undefined : "group"}
|
|
125
|
-
className={cn("min-w-0", className)}
|
|
126
|
-
>
|
|
127
|
-
<ul
|
|
128
|
-
ref={listRef}
|
|
129
|
-
className={cn(
|
|
130
|
-
"m-0 flex list-none gap-1 p-0",
|
|
131
|
-
scroll ? "flex-nowrap overflow-x-auto overscroll-x-contain [scrollbar-width:none]" : "flex-wrap",
|
|
132
|
-
)}
|
|
133
|
-
data-overflow={scroll ? fade.overflow : undefined}
|
|
134
|
-
style={scroll && fade.mask ? { maskImage: fade.mask, WebkitMaskImage: fade.mask } : undefined}
|
|
135
|
-
>
|
|
136
|
-
{items.map((item) => {
|
|
137
|
-
const isCurrent = item.value === current;
|
|
138
|
-
const Icon = item.icon;
|
|
139
|
-
const pillClass = cn(
|
|
140
|
-
PILL,
|
|
141
|
-
size === "sm" && PILL_SM,
|
|
142
|
-
isCurrent ? PILL_CURRENT : PILL_IDLE,
|
|
143
|
-
item.disabled && item.href === undefined && PILL_DISABLED,
|
|
144
|
-
itemClassName,
|
|
145
|
-
);
|
|
146
|
-
const children = (
|
|
147
|
-
<>
|
|
148
|
-
{Icon && <Icon aria-hidden />}
|
|
149
|
-
{item.label}
|
|
150
|
-
</>
|
|
151
|
-
);
|
|
152
|
-
let pill: ReactNode;
|
|
153
|
-
if (item.href !== undefined) {
|
|
154
|
-
const props: NavPillLinkProps = {
|
|
155
|
-
href: item.href,
|
|
156
|
-
className: pillClass,
|
|
157
|
-
children,
|
|
158
|
-
"aria-current": isCurrent ? (currentType ?? "page") : undefined,
|
|
159
|
-
onClick: () => onSelect?.(item.value),
|
|
160
|
-
};
|
|
161
|
-
const kit = pickLinkRenderer<NavPillLinkProps>(undefined, kitLink, item.href);
|
|
162
|
-
pill = renderLink ? (
|
|
163
|
-
renderLink(props)
|
|
164
|
-
) : kit ? (
|
|
165
|
-
<RenderedKitLink render={kit} props={props} />
|
|
166
|
-
) : (
|
|
167
|
-
<a
|
|
168
|
-
href={props.href}
|
|
169
|
-
className={props.className}
|
|
170
|
-
aria-current={props["aria-current"]}
|
|
171
|
-
onClick={props.onClick}
|
|
172
|
-
>
|
|
173
|
-
{props.children}
|
|
174
|
-
</a>
|
|
175
|
-
);
|
|
176
|
-
} else {
|
|
177
|
-
pill = (
|
|
178
|
-
<button
|
|
179
|
-
type="button"
|
|
180
|
-
disabled={item.disabled}
|
|
181
|
-
aria-current={isCurrent ? (currentType ?? "true") : undefined}
|
|
182
|
-
onClick={() => onSelect?.(item.value)}
|
|
183
|
-
className={pillClass}
|
|
184
|
-
>
|
|
185
|
-
{children}
|
|
186
|
-
</button>
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
return (
|
|
190
|
-
<li key={item.value} className={cn("flex", scroll && "shrink-0")}>
|
|
191
|
-
{pill}
|
|
192
|
-
</li>
|
|
193
|
-
);
|
|
194
|
-
})}
|
|
195
|
-
</ul>
|
|
196
|
-
</Root>
|
|
197
|
-
);
|
|
198
|
-
}
|