@eifi1/ui-kit 0.54.0 → 0.56.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 +6 -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 +7 -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 +83 -0
- package/dist/components/legended-series-chart.js +77 -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 +9 -12
- 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,282 +0,0 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
2
|
-
import type { ChangeEvent, FocusEvent } from "react";
|
|
3
|
-
import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
4
|
-
import { cn } from "../lib/cn";
|
|
5
|
-
import { PHONE_COUNTRIES, PHONE_DIAL_CODES, formatNationalPhone, formatPhone, isE164, parsePhone } from "../lib/phone";
|
|
6
|
-
import type { ParsedPhone, PhoneCountry, PhoneCountryCode } from "../lib/phone";
|
|
7
|
-
import { useFieldMessages } from "./field-parts";
|
|
8
|
-
import { Input, type InputProps } from "./input";
|
|
9
|
-
import { Select } from "./select";
|
|
10
|
-
import { DEFAULT_PHONE_INPUT_LABELS } from "./phone-input-labels";
|
|
11
|
-
|
|
12
|
-
// ── Labels ────────────────────────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
/** The words {@link PhoneInput} renders on its own behalf. */
|
|
15
|
-
export interface PhoneInputLabels {
|
|
16
|
-
/** The country-code select's accessible name. */
|
|
17
|
-
countryCode: string;
|
|
18
|
-
/** The select's last option: a number from a country not listed, typed with its
|
|
19
|
-
* own "+". */
|
|
20
|
-
other: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Defined in ./phone-input-labels, which holds no component code (0.34, KS U8).
|
|
24
|
-
export { DEFAULT_PHONE_INPUT_LABELS };
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The `phoneInput` namespace: prop > `<UiKitProvider labels>` > English (0.22.0).
|
|
28
|
-
*/
|
|
29
|
-
function usePhoneInputLabels(prop: Partial<PhoneInputLabels> | undefined): PhoneInputLabels {
|
|
30
|
-
const labels: PhoneInputLabels = useKitLabels("phoneInput", DEFAULT_PHONE_INPUT_LABELS, prop);
|
|
31
|
-
return labels;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
35
|
-
|
|
36
|
-
/** A stored value read back: an E.164 number these rules can read, else `null`. */
|
|
37
|
-
function storedNumber(value: string): ParsedPhone | null {
|
|
38
|
-
return isE164(value) ? parsePhone(value, "other") : null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** The select's country for a stored E.164 value, or `null` for free text. */
|
|
42
|
-
function countryOf(value: string): PhoneCountry | null {
|
|
43
|
-
const parsed = storedNumber(value);
|
|
44
|
-
return parsed ? (parsed.country ?? "other") : null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** What the field emits for typed text: E.164 when it reads, the text unchanged when
|
|
48
|
-
* it does not. */
|
|
49
|
-
function emitFor(raw: string, country: PhoneCountry): string {
|
|
50
|
-
return parsePhone(raw, country)?.e164 ?? raw;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* The text a stored value shows, outside of typing. Under its own country: the national
|
|
55
|
-
* number grouped ("21 000 00 01" beside "CH +41"). Under another (a "+33" number while
|
|
56
|
-
* the select says "Other"): the whole international number. Free text: as it is.
|
|
57
|
-
*/
|
|
58
|
-
function displayOf(value: string, country: PhoneCountry): string {
|
|
59
|
-
const parsed = storedNumber(value);
|
|
60
|
-
if (!parsed) return value;
|
|
61
|
-
if (parsed.country !== null && parsed.country === country) {
|
|
62
|
-
return formatNationalPhone(parsed.national, parsed.country);
|
|
63
|
-
}
|
|
64
|
-
return formatPhone(parsed.e164);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// ── Component ─────────────────────────────────────────────────────────────────
|
|
68
|
-
|
|
69
|
-
export interface PhoneInputProps extends Omit<InputProps, "type" | "value" | "defaultValue"> {
|
|
70
|
-
/** The number: E.164 ("+41210000001") for one the field could read, or free text —
|
|
71
|
-
* a value saved before the field existed is shown exactly as it is. `""` is no
|
|
72
|
-
* number. */
|
|
73
|
-
value: string;
|
|
74
|
-
/** On every change: E.164 when the typed text reads as a number of the selected
|
|
75
|
-
* country (or carries its own "+"), otherwise the typed text UNCHANGED. Nothing is
|
|
76
|
-
* refused — see {@link PhoneInput}. Plain `onChange` still fires with the raw event;
|
|
77
|
-
* bind this one to a form. */
|
|
78
|
-
onValueChange?: (value: string) => void;
|
|
79
|
-
/** The country a number typed without "+" belongs to, until the value says
|
|
80
|
-
* otherwise. Default `"CH"`. */
|
|
81
|
-
defaultCountry?: PhoneCountry;
|
|
82
|
-
/** The countries the select offers, in order; "Other" always follows. Default
|
|
83
|
-
* {@link PHONE_COUNTRIES} (CH, LI, DE, AT, FR, IT). A stored number from a country
|
|
84
|
-
* left out still shows under its own code. */
|
|
85
|
-
countries?: readonly PhoneCountryCode[];
|
|
86
|
-
/** See {@link PhoneInputLabels}. */
|
|
87
|
-
labels?: LabelOverride<PhoneInputLabels>;
|
|
88
|
-
/** Classes for the whole field — the select, the input and the lines under them.
|
|
89
|
-
* `inputClassName` reaches the `<input>`. */
|
|
90
|
-
className?: string;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* A phone number field (kastlan): a country-code select and the number, stored as
|
|
95
|
-
* E.164 and shown grouped.
|
|
96
|
-
*
|
|
97
|
-
* kastlan's contacts kept whatever was typed — "079 …", "+41 (0)79 …", "0041 79 …" —
|
|
98
|
-
* which nobody could dial from the app or match against the next import. This field
|
|
99
|
-
* turns all of those into one stored form, "+41210000001", without taking anything
|
|
100
|
-
* away from the person typing:
|
|
101
|
-
*
|
|
102
|
-
* - **A country to type against.** The select (default CH, then LI, DE, AT, FR, IT
|
|
103
|
-
* and "Other") says which country a number without "+" belongs to; the national
|
|
104
|
-
* trunk 0 may be typed or left out. Typing a "+" or "00" overrides it, and the
|
|
105
|
-
* select follows the number ("+49 …" switches it to DE). Changing the select moves
|
|
106
|
-
* the national number to the new country code.
|
|
107
|
-
* - **E.164 when it reads, the text when it does not.** A number the rules read is
|
|
108
|
-
* emitted as E.164; anything else ("ask reception", an extension) is emitted exactly
|
|
109
|
-
* as typed. Never refused, never an error of its own: a contact's number is often
|
|
110
|
-
* known only roughly, and a field that will not save "079 … (mornings)" makes
|
|
111
|
-
* people type it into the notes instead. An app that needs a dialable number
|
|
112
|
-
* checks {@link isE164} on submit.
|
|
113
|
-
* - **Existing values untouched.** A free-text value from before is shown exactly as
|
|
114
|
-
* it is, and normalised only when someone edits it — the field never rewrites a
|
|
115
|
-
* record just by being opened.
|
|
116
|
-
* - **Grouped when settled.** While typing the field shows what was typed; on blur a
|
|
117
|
-
* number it read is regrouped by its country ("21 000 00 01").
|
|
118
|
-
*
|
|
119
|
-
* **The limitation** — there is no libphonenumber behind this (≈150 kB of metadata in
|
|
120
|
-
* every bundle): the six countries have light rules (the trunk 0, a plausible length)
|
|
121
|
-
* and every other country is any "+" with 8–15 digits. A well-formed number that does
|
|
122
|
-
* not exist passes, and German and Austrian landlines, whose area codes vary in length,
|
|
123
|
-
* are grouped only where the split is known (mobile prefixes, the largest cities) and
|
|
124
|
-
* otherwise shown as one block. See `lib/phone.ts`.
|
|
125
|
-
*
|
|
126
|
-
* `label`, `hint`, `error` and `invalid` read as on {@link Input}: the label floats in
|
|
127
|
-
* the number's box, and a text hint and the error go under the whole row, attached to
|
|
128
|
-
* the number with `aria-describedby`. The select is named by `labels.countryCode`, and
|
|
129
|
-
* the pair is a group named by a string `label`.
|
|
130
|
-
*/
|
|
131
|
-
export function PhoneInput({
|
|
132
|
-
ref,
|
|
133
|
-
value,
|
|
134
|
-
onValueChange,
|
|
135
|
-
onChange,
|
|
136
|
-
onBlur,
|
|
137
|
-
defaultCountry = "CH",
|
|
138
|
-
countries = PHONE_COUNTRIES,
|
|
139
|
-
labels,
|
|
140
|
-
className,
|
|
141
|
-
inputClassName,
|
|
142
|
-
label,
|
|
143
|
-
hint,
|
|
144
|
-
help,
|
|
145
|
-
error,
|
|
146
|
-
invalid,
|
|
147
|
-
disabled,
|
|
148
|
-
"aria-describedby": ariaDescribedBy,
|
|
149
|
-
...rest
|
|
150
|
-
}: PhoneInputProps) {
|
|
151
|
-
const text = usePhoneInputLabels(labels);
|
|
152
|
-
const [country, setCountry] = useState<PhoneCountry>(() => countryOf(value) ?? defaultCountry);
|
|
153
|
-
// What was typed, shown for as long as it still reads as the value (AmountInput's
|
|
154
|
-
// draft): the person's own spacing stays under their fingers, and is regrouped on
|
|
155
|
-
// blur.
|
|
156
|
-
const [draft, setDraft] = useState<string | null>(null);
|
|
157
|
-
// The last value this field emitted, to tell its own echo from a value set outside.
|
|
158
|
-
const [emitted, setEmitted] = useState<string | null>(null);
|
|
159
|
-
const [seen, setSeen] = useState(value);
|
|
160
|
-
if (seen !== value) {
|
|
161
|
-
setSeen(value);
|
|
162
|
-
if (value !== emitted) {
|
|
163
|
-
// Set from outside (a reset, another record): its own country, none of our text.
|
|
164
|
-
const own = countryOf(value);
|
|
165
|
-
if (own) setCountry(own);
|
|
166
|
-
setDraft(null);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const emit = (next: string) => {
|
|
171
|
-
setEmitted(next);
|
|
172
|
-
onValueChange?.(next);
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
176
|
-
onChange?.(e);
|
|
177
|
-
const raw = e.target.value;
|
|
178
|
-
setDraft(raw);
|
|
179
|
-
const parsed = parsePhone(raw, country);
|
|
180
|
-
// A number typed with its own "+" takes the select with it.
|
|
181
|
-
if (parsed && parsed.country !== country) setCountry(parsed.country ?? "other");
|
|
182
|
-
emit(parsed?.e164 ?? raw);
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const handleCountry = (next: PhoneCountry) => {
|
|
186
|
-
setCountry(next);
|
|
187
|
-
const stored = storedNumber(value);
|
|
188
|
-
if (stored) {
|
|
189
|
-
// "Other", the same country, or a generic number with its own "+": the number
|
|
190
|
-
// stays, only the way it is shown changes.
|
|
191
|
-
if (next === "other" || stored.country === null || stored.country === next) {
|
|
192
|
-
setDraft(null);
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
// A different listed country: the national number moves to its code. If it does
|
|
196
|
-
// not read there, the digits are kept as text for the person to finish.
|
|
197
|
-
emit(parsePhone(stored.national, next)?.e164 ?? stored.national);
|
|
198
|
-
setDraft(null);
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
// Free text (or a draft): read it again under the new country.
|
|
202
|
-
const source = draft ?? value;
|
|
203
|
-
const parsed = source.trim() === "" ? null : parsePhone(source, next);
|
|
204
|
-
if (parsed && parsed.e164 !== value) {
|
|
205
|
-
setDraft(source);
|
|
206
|
-
emit(parsed.e164);
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
const display = draft !== null && emitFor(draft, country) === value ? draft : displayOf(value, country);
|
|
211
|
-
|
|
212
|
-
// The select offers the configured countries, plus the stored number's own if it
|
|
213
|
-
// is not among them — a select cannot show a value it has no option for.
|
|
214
|
-
const options: PhoneCountryCode[] = [...countries];
|
|
215
|
-
if (country !== "other" && !options.includes(country)) options.push(country);
|
|
216
|
-
|
|
217
|
-
// A FieldHint "?" rides the number's label line; text — and a FieldHint at Large and
|
|
218
|
-
// on touch (§4) — goes under the whole row with the error. Through useFieldMessages
|
|
219
|
-
// since 0.34, not a copy of its rule (DUP-2, DUP-8).
|
|
220
|
-
const messages = useFieldMessages({
|
|
221
|
-
hint,
|
|
222
|
-
// The number's label line takes the help's "?" (0.36); the hint is then the caption.
|
|
223
|
-
help,
|
|
224
|
-
name: label ?? rest["aria-label"],
|
|
225
|
-
error,
|
|
226
|
-
invalid,
|
|
227
|
-
describedBy: ariaDescribedBy,
|
|
228
|
-
ariaInvalid: rest["aria-invalid"],
|
|
229
|
-
});
|
|
230
|
-
const named = typeof label === "string" && label !== "";
|
|
231
|
-
|
|
232
|
-
return (
|
|
233
|
-
<div className={className} role={named ? "group" : undefined} aria-label={named ? label : undefined}>
|
|
234
|
-
{/* On a phone at Large the number takes a line of its own under the country (0.32.1,
|
|
235
|
-
the 360 px Extra-large sweep; docs/text-size-harmonization.md §4 "nothing
|
|
236
|
-
truncates"): the 7rem select is 168 px at 150 %, and on a 360 px phone it left
|
|
237
|
-
the number 82 px — "Ph…" over "021 (". `large:max-sm:`, the scaled phone width,
|
|
238
|
-
so a wider screen at Large and Normal keep the one row. */}
|
|
239
|
-
<div className="flex items-stretch gap-2 large:max-sm:flex-wrap">
|
|
240
|
-
<Select
|
|
241
|
-
aria-label={text.countryCode}
|
|
242
|
-
value={country}
|
|
243
|
-
disabled={disabled}
|
|
244
|
-
onChange={(e) => handleCountry(e.target.value as PhoneCountry)}
|
|
245
|
-
className="w-28 shrink-0"
|
|
246
|
-
// Stretched to the number's height: a labelled field is taller than an
|
|
247
|
-
// unlabelled select, and the pair should read as one row.
|
|
248
|
-
selectClassName="h-full tabular-nums"
|
|
249
|
-
>
|
|
250
|
-
{options.map((code) => (
|
|
251
|
-
<option key={code} value={code}>
|
|
252
|
-
{`${code} +${PHONE_DIAL_CODES[code]}`}
|
|
253
|
-
</option>
|
|
254
|
-
))}
|
|
255
|
-
<option value="other">{text.other}</option>
|
|
256
|
-
</Select>
|
|
257
|
-
{/* Its own flex item, so nothing Input wraps itself in can take the sizing. */}
|
|
258
|
-
<div className="min-w-0 flex-1 large:max-sm:basis-full">
|
|
259
|
-
<Input
|
|
260
|
-
ref={ref}
|
|
261
|
-
{...rest}
|
|
262
|
-
type="tel"
|
|
263
|
-
autoComplete={rest.autoComplete ?? "tel"}
|
|
264
|
-
label={label}
|
|
265
|
-
hint={messages.labelHint}
|
|
266
|
-
invalid={messages.isInvalid}
|
|
267
|
-
aria-describedby={messages.describedBy}
|
|
268
|
-
disabled={disabled}
|
|
269
|
-
value={display}
|
|
270
|
-
onChange={handleChange}
|
|
271
|
-
onBlur={(e: FocusEvent<HTMLInputElement>) => {
|
|
272
|
-
setDraft(null);
|
|
273
|
-
onBlur?.(e);
|
|
274
|
-
}}
|
|
275
|
-
inputClassName={cn("tabular-nums", inputClassName)}
|
|
276
|
-
/>
|
|
277
|
-
</div>
|
|
278
|
-
</div>
|
|
279
|
-
{messages.below}
|
|
280
|
-
</div>
|
|
281
|
-
);
|
|
282
|
-
}
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
import { useMemo, useRef } from "react";
|
|
2
|
-
import { createPortal } from "react-dom";
|
|
3
|
-
import { X } from "lucide-react";
|
|
4
|
-
import type { ComponentPropsWithoutRef, KeyboardEvent, ReactNode, Ref, RefObject } from "react";
|
|
5
|
-
import { cn } from "../lib/cn";
|
|
6
|
-
import { hasContent } from "../lib/presence";
|
|
7
|
-
import { mergeRefs } from "./field-parts";
|
|
8
|
-
import { CLIPS_ATTRIBUTE } from "../lib/clipping";
|
|
9
|
-
import { DropdownSearchHeader } from "./dropdown";
|
|
10
|
-
import { Button } from "./button";
|
|
11
|
-
import { useBodyScrollLock } from "../hooks/use-body-scroll-lock";
|
|
12
|
-
import { useOverlayHistory } from "../hooks/use-overlay-history";
|
|
13
|
-
import { useFocusTrap } from "../hooks/use-focus-trap";
|
|
14
|
-
import { takeEscape, useDismissLayer } from "../hooks/use-dismiss";
|
|
15
|
-
import { useVisualViewport } from "../hooks/use-anchored-panel";
|
|
16
|
-
import { DEFAULT_PICKER_SHEET_LABELS, useKitLabels } from "../i18n/kit-labels";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Two of the div's own attributes are omitted because this component already owns
|
|
20
|
-
* the name: `title` here is the sheet's HEADING (and a ReactNode), not the browser's
|
|
21
|
-
* tooltip string, and `onClose` is "the sheet was dismissed", not the DOM's
|
|
22
|
-
* `<dialog>` close event. Everything else a caller can pass reaches the sheet.
|
|
23
|
-
*/
|
|
24
|
-
export interface PickerSheetProps extends Omit<ComponentPropsWithoutRef<"div">, "title" | "onClose"> {
|
|
25
|
-
open: boolean;
|
|
26
|
-
onClose: () => void;
|
|
27
|
-
/** The field's own label — a sheet that fills the screen has to say what it is
|
|
28
|
-
* asking for, which the anchored panel got for free by sitting under it. */
|
|
29
|
-
title?: ReactNode;
|
|
30
|
-
query: string;
|
|
31
|
-
onQueryChange: (value: string) => void;
|
|
32
|
-
searchPlaceholder?: string;
|
|
33
|
-
/** The search box's accessible name. Default: `searchPlaceholder` — a placeholder is
|
|
34
|
-
* gone the moment a character is typed, and is no name to many readers at all. */
|
|
35
|
-
searchLabel?: string;
|
|
36
|
-
inputRef?: RefObject<HTMLInputElement | null>;
|
|
37
|
-
/** Default: `pickerSheet.close` from the {@link UiKitProvider}, else "Close". */
|
|
38
|
-
closeLabel?: string;
|
|
39
|
-
/**
|
|
40
|
-
* The list's keyboard, on the search box — where focus is while the sheet is up:
|
|
41
|
-
* Up/Down/Home/End/Enter (round 0.34 Wave 2, BUG-5). `ComboboxPanel` passes its own;
|
|
42
|
-
* without it arrows and Enter in the sheet did nothing at all.
|
|
43
|
-
*/
|
|
44
|
-
onSearchKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void;
|
|
45
|
-
/** The `role="listbox"` the search box filters, for its `aria-controls`. */
|
|
46
|
-
listboxId?: string;
|
|
47
|
-
/** The option the arrow keys are on, for the search box's `aria-activedescendant`. */
|
|
48
|
-
activeId?: string;
|
|
49
|
-
children: ReactNode;
|
|
50
|
-
/**
|
|
51
|
-
* A row pinned under the scrolling list — {@link FullBleedDialog}'s `footer`, on the
|
|
52
|
-
* picker's sheet (kk run 79 gap 2). Outside the scroller, so it stays put however long
|
|
53
|
-
* the list; padded for the home indicator, since it is the sheet's bottom edge.
|
|
54
|
-
*/
|
|
55
|
-
footer?: ReactNode;
|
|
56
|
-
/**
|
|
57
|
-
* The kit's one sticky "Done" at the foot of the sheet (Marcel, keksdose #412): the
|
|
58
|
-
* button a multi-select sheet is left by once its rows are ticked. Ticks apply as
|
|
59
|
-
* they are made, so it closes (`onClose`) rather than saves. After any `footer`.
|
|
60
|
-
* {@link ComboboxPanel} turns it on for every `multi` list — `MultiSelect` and
|
|
61
|
-
* `MultiEntityCombobox` — and a single-select sheet, which closes on the tap that
|
|
62
|
-
* picks, has no use for it. Label: `pickerSheet.done`, else "Done" (`doneLabel`).
|
|
63
|
-
*/
|
|
64
|
-
done?: boolean;
|
|
65
|
-
/** Default: `pickerSheet.done` from the {@link UiKitProvider}, else "Done". */
|
|
66
|
-
doneLabel?: string;
|
|
67
|
-
/** The sheet, where the rest of the props go (0.34, API-2, refactor audit 2026-10) —
|
|
68
|
-
* merged with the sheet's own ref, which its focus trap holds. */
|
|
69
|
-
ref?: Ref<HTMLDivElement>;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* The PHONE presentation of a picker: a full-screen dialog with a search box at
|
|
74
|
-
* the top and the list filling everything below it (Keksdose live #200).
|
|
75
|
-
*
|
|
76
|
-
* *"Paid as full screen dialog with input. Similar to the account select that
|
|
77
|
-
* already appears as full screen."* The account field is a native `<select>`, and
|
|
78
|
-
* a phone browser renders that as a full-screen list — so the app's own pickers,
|
|
79
|
-
* which are anchored dropdown panels, were the odd ones out: a 320px-tall panel
|
|
80
|
-
* squeezed between the field and the keyboard, showing three or four rows of a
|
|
81
|
-
* list that might have two hundred entries.
|
|
82
|
-
*
|
|
83
|
-
* What this fixes beyond size: the panel had to be *placed* (above/below, tracking
|
|
84
|
-
* the visual viewport as the keyboard opened — see `useAnchoredPanel`), and every
|
|
85
|
-
* one of those decisions is a chance to be wrong on a screen this small. A sheet
|
|
86
|
-
* has no placement. It also gives the search input somewhere unambiguous to live,
|
|
87
|
-
* which is the other half of the request: *"add filler possibility to the account
|
|
88
|
-
* select or even better right to the hoc the account select is derived from"* —
|
|
89
|
-
* so this lives in the shared picker, not in one form's copy of it.
|
|
90
|
-
*
|
|
91
|
-
* Rows are `min-h-11` (44px): the touch target the rest of the app uses. The list
|
|
92
|
-
* scrolls, the header does not, and the body behind it is scroll-locked so a drag
|
|
93
|
-
* that overshoots the list does not move the page underneath.
|
|
94
|
-
*/
|
|
95
|
-
export function PickerSheet({
|
|
96
|
-
open,
|
|
97
|
-
onClose,
|
|
98
|
-
title,
|
|
99
|
-
query,
|
|
100
|
-
onQueryChange,
|
|
101
|
-
searchPlaceholder,
|
|
102
|
-
searchLabel,
|
|
103
|
-
inputRef,
|
|
104
|
-
closeLabel,
|
|
105
|
-
onSearchKeyDown,
|
|
106
|
-
listboxId,
|
|
107
|
-
activeId,
|
|
108
|
-
children,
|
|
109
|
-
footer,
|
|
110
|
-
done,
|
|
111
|
-
doneLabel,
|
|
112
|
-
"aria-label": ariaLabel,
|
|
113
|
-
className,
|
|
114
|
-
style,
|
|
115
|
-
ref,
|
|
116
|
-
...rest
|
|
117
|
-
}: PickerSheetProps) {
|
|
118
|
-
// Every picker in the kit opens one of these on a phone, and most of them pass
|
|
119
|
-
// their own `closeLabel` through as `undefined` — so this lookup is what makes the
|
|
120
|
-
// one way out of a full-screen sheet speak the app's language without each of
|
|
121
|
-
// them having to (see the prop's note in `EntityCombobox`).
|
|
122
|
-
const labels = useKitLabels("pickerSheet", DEFAULT_PICKER_SHEET_LABELS, { close: closeLabel, done: doneLabel });
|
|
123
|
-
// `hasContent`, so a `footer` of "" draws no empty bar (refactor audit 2026-10-30, DUP-14).
|
|
124
|
-
const hasFooter = hasContent(footer) || Boolean(done);
|
|
125
|
-
useBodyScrollLock(open);
|
|
126
|
-
/**
|
|
127
|
-
* Back closes THE SHEET, not the dialog it was opened from (Keksdose live #309:
|
|
128
|
-
* *"Mouse Back does not only close the select but also the whole edit or create
|
|
129
|
-
* dialog which is cumbersome."*).
|
|
130
|
-
*
|
|
131
|
-
* The sheet is a full-screen overlay over whatever opened it, and on a phone that
|
|
132
|
-
* is almost always the row editor — which DOES push a history entry
|
|
133
|
-
* (`data-table.tsx`). So the sheet was invisible to Back: one press popped the
|
|
134
|
-
* editor's entry and took the whole dialog with it, discarding an edit in progress
|
|
135
|
-
* in order to dismiss a list.
|
|
136
|
-
*
|
|
137
|
-
* `useOverlayHistory` was built for exactly this nesting — its stack unwinds
|
|
138
|
-
* last-in-first-out, and the U-12 regression test in its own suite is written
|
|
139
|
-
* around "a Modal and a PickerSheet inside it". The sheet simply never called it.
|
|
140
|
-
*
|
|
141
|
-
* Nothing else has to change: the hook is a no-op while `open` is false, and it
|
|
142
|
-
* pops its own entry when the sheet closes some other way (the X, a row, the
|
|
143
|
-
* backdrop) so history does not accumulate husks.
|
|
144
|
-
*/
|
|
145
|
-
useOverlayHistory(open, onClose);
|
|
146
|
-
// The visible region, while the sheet is up — see the `style` below for why a
|
|
147
|
-
// full-screen sheet cannot simply be `inset-0` on a phone (live #328).
|
|
148
|
-
const vv = useVisualViewport(open);
|
|
149
|
-
// A fallback ref so a caller that does not need the handle still gets the opening
|
|
150
|
-
// focus, rather than the behaviour depending on whether a prop was passed. What that
|
|
151
|
-
// focus is FOR is on the trap below.
|
|
152
|
-
const ownRef = useRef<HTMLInputElement | null>(null);
|
|
153
|
-
const searchRef = inputRef ?? ownRef;
|
|
154
|
-
|
|
155
|
-
const sheetRef = useRef<HTMLDivElement>(null);
|
|
156
|
-
const setSheet = useMemo(() => mergeRefs(sheetRef, ref), [ref]);
|
|
157
|
-
/**
|
|
158
|
-
* The sheet said `aria-modal="true"` and then left focus on the field behind it, so
|
|
159
|
-
* a screen reader was told to hide the page the user's cursor was still standing in
|
|
160
|
-
* (the audit's *"Only Modal manages focus"*). Through the shared hook rather than
|
|
161
|
-
* the bare `.focus()` that used to live here: the hook re-reads the tabbable list on
|
|
162
|
-
* every Tab, which this panel needs more than most — its list is filtered as you
|
|
163
|
-
* type, so the rows a trap captured at open time are gone by the second keystroke.
|
|
164
|
-
*
|
|
165
|
-
* **`initialFocus` is the search box**, not the container, and this is the one place
|
|
166
|
-
* in the package that overrides `Modal`'s rule. The sheet exists in order to be typed
|
|
167
|
-
* into (live #212: *"make the text input filter active on select click"*), and the
|
|
168
|
-
* callers cannot do it themselves — `Combobox`'s field runs
|
|
169
|
-
* `setOpen(true); sheetInputRef.current?.focus()` in a single `onFocus`, so the focus
|
|
170
|
-
* call happens while this sheet is still unmounted and the ref is null. Only the
|
|
171
|
-
* sheet knows when its own input exists. Popping the keyboard is the POINT here,
|
|
172
|
-
* where in a form dialog it is the cost.
|
|
173
|
-
*
|
|
174
|
-
* **`restoreFocus` is off**, which is the uncomfortable half. `Combobox` and
|
|
175
|
-
* `InlineEntityCombobox` open the sheet from the field's own `onFocus` handler, so
|
|
176
|
-
* handing focus back to that field on close re-opens the sheet the user has just
|
|
177
|
-
* dismissed — a row tap would select a value and immediately put the list back over
|
|
178
|
-
* it. The field that opened it is the only thing that knows whether re-focusing it
|
|
179
|
-
* means "open"; a sheet that cannot tell must not guess. So the caller does it in
|
|
180
|
-
* `onClose` where it can: `ComboboxPanel`'s triggers open on a click, and its
|
|
181
|
-
* `onClose` hands focus back to the trigger (0.52, refactor audit 2026-10-30, INP-7) —
|
|
182
|
-
* a screen-reader user is in exactly this layout, and <body> was where they landed.
|
|
183
|
-
*/
|
|
184
|
-
useFocusTrap(sheetRef, {
|
|
185
|
-
active: open,
|
|
186
|
-
restoreFocus: false,
|
|
187
|
-
initialFocus: () => searchRef.current,
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// The sheet is almost always the INNERMOST overlay — it opens from a field inside a
|
|
191
|
-
// `Modal` or a `FullBleedDialog`. It is a layer on the Escape stack (Wave 2, DUP-1),
|
|
192
|
-
// above the dialog, and takes the key on its own element: one press dismissing this
|
|
193
|
-
// list and the dialog underneath with it was Keksdose live #309 (*"Mouse Back does
|
|
194
|
-
// not only close the select but also the whole edit or create dialog which is
|
|
195
|
-
// cumbersome"*), which the Back gesture already learned, on the key a desktop user
|
|
196
|
-
// reaches for instead.
|
|
197
|
-
useDismissLayer(open, onClose);
|
|
198
|
-
const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
|
|
199
|
-
takeEscape(e);
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
if (!open || typeof document === "undefined") return null;
|
|
203
|
-
return createPortal(
|
|
204
|
-
/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- the dialog
|
|
205
|
-
container, per the APG dialog pattern: `onKeyDown` is Escape-to-close for whatever
|
|
206
|
-
inside it holds focus, and `onMouseDown` only stops propagation (live #328). */
|
|
207
|
-
<div
|
|
208
|
-
// Spread FIRST, and every attribute below it deliberately wins: `style`,
|
|
209
|
-
// `onMouseDown` and `onKeyDown` here are not styling choices, they are live
|
|
210
|
-
// #328, dev#477 and live #309 respectively, and a caller who passed one by
|
|
211
|
-
// accident would re-open a bug three apps have already paid for. `style` is
|
|
212
|
-
// MERGED rather than won outright (see below), which is the one case where a
|
|
213
|
-
// caller has something to add.
|
|
214
|
-
{...rest}
|
|
215
|
-
ref={setSheet}
|
|
216
|
-
// A kit layer and a bottom layer a docked tour card stays clear of (0.50,
|
|
217
|
-
// docs/tours-harmonization.md §11.6).
|
|
218
|
-
data-kit-layer=""
|
|
219
|
-
data-tour-obstruction=""
|
|
220
|
-
role="dialog"
|
|
221
|
-
aria-modal="true"
|
|
222
|
-
// Without it the container cannot take focus, and `useFocusTrap` has nothing to
|
|
223
|
-
// fall back to when the list is empty and the search box is the only thing in
|
|
224
|
-
// here — see the hook's "nothing tabbable" branch.
|
|
225
|
-
tabIndex={-1}
|
|
226
|
-
onKeyDown={handleKeyDown}
|
|
227
|
-
// The caller's own name wins over the heading: a sheet titled "Account" in a
|
|
228
|
-
// form with two of them needs to say WHICH, and `title` is what the user reads
|
|
229
|
-
// rather than what a reader announces.
|
|
230
|
-
aria-label={ariaLabel ?? (typeof title === "string" ? title : undefined)}
|
|
231
|
-
// The sheet is PORTALLED to <body>, so it is not inside the field's own
|
|
232
|
-
// wrapper — and `useDropdown` closes on any document mousedown landing
|
|
233
|
-
// outside that wrapper. Tapping a row therefore unmounted the row (open →
|
|
234
|
-
// false) before its CLICK could fire, so the tap selected nothing at all and
|
|
235
|
-
// the sheet just vanished (Keksdose dev#477).
|
|
236
|
-
//
|
|
237
|
-
// It bit whichever sheet commits on `onClick` — the payee field's, since live
|
|
238
|
-
// #200, where it hid behind the free-text value the search box was already
|
|
239
|
-
// setting; and the account field's the moment dev#477 moved it onto the inline
|
|
240
|
-
// picker. `ComboboxPanel`'s rows happen to commit on `onMouseDown`, so they
|
|
241
|
-
// beat the document listener and were never affected — which is luck, not a
|
|
242
|
-
// design, and exactly why the fix belongs to the sheet.
|
|
243
|
-
//
|
|
244
|
-
// Stopping the mousedown here rather than teaching every caller about the
|
|
245
|
-
// portal: the sheet is modal and full-screen, so "a click in here is not an
|
|
246
|
-
// outside click" is a property of the sheet, not of whoever opened it.
|
|
247
|
-
onMouseDown={(e) => e.stopPropagation()}
|
|
248
|
-
// ⚠️ `inset-0` was the whole of Keksdose live #328: *"When the keyboard overlays
|
|
249
|
-
// the entries I cannot scroll past them … to see also the last entries. Happens
|
|
250
|
-
// when browsing the account select."*
|
|
251
|
-
//
|
|
252
|
-
// This sheet FOCUSES ITS OWN SEARCH BOX on open (see above), so the keyboard is
|
|
253
|
-
// up every single time it is used on a phone. On Android that shrinks the visual
|
|
254
|
-
// viewport and leaves the LAYOUT viewport alone — `inset-0` is the layout
|
|
255
|
-
// viewport — so the sheet kept its full height with its bottom third behind the
|
|
256
|
-
// keyboard. The list below is `flex-1 overflow-y-auto`, so it sized itself to
|
|
257
|
-
// that hidden height too: it scrolled to ITS end while the last rows were still
|
|
258
|
-
// under the keys, and no gesture could bring them out. Nothing was clipped and
|
|
259
|
-
// nothing looked broken, which is why it reads as "I cannot scroll past them".
|
|
260
|
-
//
|
|
261
|
-
// `visualViewport` is the API that answers rather than hints (the live #292
|
|
262
|
-
// lesson): it reports the region actually on screen, keyboard and pinch-pan
|
|
263
|
-
// included, and it fires on the keyboard opening and closing. Pinned to that box,
|
|
264
|
-
// the sheet ends where the keys begin and the list's own scroll covers the rest.
|
|
265
|
-
// `useVisualViewport` returns null when there is nothing to correct, and then
|
|
266
|
-
// this is character-for-character the sheet that was here before.
|
|
267
|
-
// A caller's `style` is kept and the correction laid OVER it: the three values
|
|
268
|
-
// below are the whole of live #328, so they are not negotiable, but a z-index
|
|
269
|
-
// or a transition from outside has nothing to do with them. Without a visual
|
|
270
|
-
// viewport to correct for this is character-for-character what the caller passed.
|
|
271
|
-
style={vv ? { ...style, top: vv.top, height: vv.height, bottom: "auto" } : style}
|
|
272
|
-
className={cn("fixed inset-0 z-50 flex flex-col bg-surface outline-none", className)}
|
|
273
|
-
>
|
|
274
|
-
<div className="flex items-center gap-2 border-b border-subtle px-3 py-2">
|
|
275
|
-
<span className="min-w-0 flex-1 truncate text-sm font-semibold text-primary">{title}</span>
|
|
276
|
-
<button
|
|
277
|
-
type="button"
|
|
278
|
-
aria-label={labels.close}
|
|
279
|
-
onClick={onClose}
|
|
280
|
-
className="rounded p-1.5 text-muted hover:bg-hover"
|
|
281
|
-
>
|
|
282
|
-
<X className="size-5" />
|
|
283
|
-
</button>
|
|
284
|
-
</div>
|
|
285
|
-
<DropdownSearchHeader
|
|
286
|
-
query={query}
|
|
287
|
-
onQueryChange={onQueryChange}
|
|
288
|
-
inputRef={searchRef}
|
|
289
|
-
placeholder={searchPlaceholder}
|
|
290
|
-
aria-label={searchLabel ?? searchPlaceholder}
|
|
291
|
-
// Focus is in this box while the sheet is up, so this is where the list's keys
|
|
292
|
-
// land and what has to name the list and the row the arrows are on (BUG-5).
|
|
293
|
-
onKeyDown={onSearchKeyDown}
|
|
294
|
-
listboxId={listboxId}
|
|
295
|
-
activeId={activeId}
|
|
296
|
-
/>
|
|
297
|
-
{/* min-h-0 so the LIST scrolls rather than the dialog growing past the
|
|
298
|
-
viewport — a flex child defaults to min-height:auto. */}
|
|
299
|
-
{/* Marked as the scroller it is (`CLIPS_ATTRIBUTE`), so a Tooltip in a row —
|
|
300
|
-
`Combobox`'s `optionAdornment` — portals out under jsdom as it does in the
|
|
301
|
-
browser rather than joining the option's name (keksdose E8). */}
|
|
302
|
-
<div {...{ [CLIPS_ATTRIBUTE]: "" }} className="min-h-0 flex-1 overflow-y-auto overscroll-contain">
|
|
303
|
-
{children}
|
|
304
|
-
</div>
|
|
305
|
-
{hasFooter && (
|
|
306
|
-
<div
|
|
307
|
-
data-picker-sheet-footer=""
|
|
308
|
-
className="flex shrink-0 flex-wrap items-center justify-end gap-2 border-t border-subtle bg-surface px-3 pt-3"
|
|
309
|
-
style={{ paddingBottom: "max(0.75rem, env(safe-area-inset-bottom))" }}
|
|
310
|
-
>
|
|
311
|
-
{footer}
|
|
312
|
-
{done && (
|
|
313
|
-
// Full width: the one thing left to do on the sheet, under the thumb.
|
|
314
|
-
<Button type="button" className="flex-1" onClick={onClose}>
|
|
315
|
-
{labels.done}
|
|
316
|
-
</Button>
|
|
317
|
-
)}
|
|
318
|
-
</div>
|
|
319
|
-
)}
|
|
320
|
-
</div>,
|
|
321
|
-
document.body,
|
|
322
|
-
);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/** A row inside a {@link PickerSheet} — the phone-sized version of a dropdown row,
|
|
326
|
-
* so a list is comfortable to hit with a thumb rather than merely legible. */
|
|
327
|
-
export const SHEET_ROW_CLASS = cn(
|
|
328
|
-
"flex min-h-11 w-full items-center gap-2 px-4 py-2 text-start text-base",
|
|
329
|
-
"text-primary hover:bg-hover",
|
|
330
|
-
);
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// All user-facing strings for `PieChart`, as the `pieChart` namespace of
|
|
2
|
-
// `<UiKitProvider labels>`, and per chart the `labels` prop over that.
|
|
3
|
-
//
|
|
4
|
-
// A module of its own, with no recharts in it, for the reason `series-chart-labels`
|
|
5
|
-
// is one: the label registry (src/i18n) imports the defaults, and must not pull the
|
|
6
|
-
// chart library in behind them.
|
|
7
|
-
|
|
8
|
-
export interface PieChartLabels {
|
|
9
|
-
/** Accessible name of the group of keyboard stops laid over the slices — one tab
|
|
10
|
-
* stop, arrow keys between them. */
|
|
11
|
-
slices: string;
|
|
12
|
-
/**
|
|
13
|
-
* One slice's accessible name. `value` arrives through `formatValue`, `percent` as
|
|
14
|
-
* the slice's share of what is drawn, already formatted in the locale ("42 %" in
|
|
15
|
-
* German, "42%" in English) — the function only arranges them.
|
|
16
|
-
*/
|
|
17
|
-
slice: (label: string, value: string, percent: string) => string;
|
|
18
|
-
/**
|
|
19
|
-
* One slice's accessible name under `redact` (0.52): the label and the share, with no
|
|
20
|
-
* amount. `redact` blurs every figure on screen but not the ring, and the ring's names
|
|
21
|
-
* are attributes on untagged elements, which a session replay or a redaction keyed on
|
|
22
|
-
* `[data-private]` reads as they are. `percent` as for {@link PieChartLabels.slice}.
|
|
23
|
-
*/
|
|
24
|
-
sliceShare: (label: string, percent: string) => string;
|
|
25
|
-
/** The caption over the donut's centre figure. */
|
|
26
|
-
total: string;
|
|
27
|
-
/** What a chart with nothing to draw says, when the caller passes no `empty`. */
|
|
28
|
-
empty: string;
|
|
29
|
-
/** Accessible name of the chart's legend (a group of switches, one per slice). */
|
|
30
|
-
legend: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const DEFAULT_PIE_CHART_LABELS: PieChartLabels = {
|
|
34
|
-
slices: "Chart slices",
|
|
35
|
-
slice: (label, value, percent) => `${label}: ${value} (${percent})`,
|
|
36
|
-
sliceShare: (label, percent) => `${label}: ${percent}`,
|
|
37
|
-
total: "Total",
|
|
38
|
-
empty: "No data",
|
|
39
|
-
legend: "Categories",
|
|
40
|
-
};
|