@eifi1/ui-kit 0.51.7 → 0.52.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 +141 -23
- package/dist/account/account-parts.d.ts +10 -8
- package/dist/account/account-parts.js +1 -18
- package/dist/account/account-parts.js.map +1 -1
- package/dist/account/data-export-setting-labels.js +1 -1
- package/dist/account/data-export-setting-labels.js.map +1 -1
- package/dist/account/delete-account-setting-labels.js +1 -1
- package/dist/account/delete-account-setting-labels.js.map +1 -1
- package/dist/account/email-change-setting-labels.js +1 -1
- package/dist/account/email-change-setting-labels.js.map +1 -1
- package/dist/account/passkeys-setting.d.ts +9 -2
- package/dist/account/passkeys-setting.js +41 -29
- package/dist/account/passkeys-setting.js.map +1 -1
- package/dist/account/sessions-setting.d.ts +3 -2
- package/dist/account/sessions-setting.js +10 -8
- package/dist/account/sessions-setting.js.map +1 -1
- package/dist/admin/admin-action-confirm.js +1 -3
- package/dist/admin/admin-action-confirm.js.map +1 -1
- package/dist/admin/admin-parts.d.ts +6 -3
- package/dist/admin/admin-parts.js +6 -21
- package/dist/admin/admin-parts.js.map +1 -1
- package/dist/admin/mail-test-card-labels.js +1 -1
- package/dist/admin/mail-test-card-labels.js.map +1 -1
- package/dist/admin/plan-change-labels.d.ts +2 -2
- package/dist/admin/plan-change-labels.js +1 -17
- package/dist/admin/plan-change-labels.js.map +1 -1
- package/dist/admin/plan-change.d.ts +3 -42
- package/dist/admin/plan-change.js +1 -1
- package/dist/admin/plan-change.js.map +1 -1
- package/dist/admin/reviewer-scope-editor.js +3 -3
- package/dist/admin/reviewer-scope-editor.js.map +1 -1
- package/dist/auth/auth-errors-labels.d.ts +11 -0
- package/dist/auth/auth-errors-labels.js +13 -0
- package/dist/auth/auth-errors-labels.js.map +1 -0
- package/dist/auth/auth-errors.d.ts +7 -23
- package/dist/auth/auth-errors.js +2 -15
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/complete-name-dialog.js +2 -1
- package/dist/auth/complete-name-dialog.js.map +1 -1
- package/dist/auth/forgot-password-form-labels.js +1 -1
- package/dist/auth/forgot-password-form-labels.js.map +1 -1
- package/dist/auth/forgot-password-form.js +7 -2
- package/dist/auth/forgot-password-form.js.map +1 -1
- package/dist/auth/register-form-labels.js +1 -1
- package/dist/auth/register-form-labels.js.map +1 -1
- package/dist/auth/reset-password-form-labels.js +1 -1
- package/dist/auth/reset-password-form-labels.js.map +1 -1
- package/dist/auth/reset-password-form.js +5 -1
- package/dist/auth/reset-password-form.js.map +1 -1
- package/dist/auth/sign-in-form-labels.js +1 -1
- package/dist/auth/sign-in-form-labels.js.map +1 -1
- package/dist/auth/status-parts.d.ts +0 -3
- package/dist/auth/status-parts.js +0 -4
- package/dist/auth/status-parts.js.map +1 -1
- package/dist/auth/verify-email-labels.js +1 -1
- package/dist/auth/verify-email-labels.js.map +1 -1
- package/dist/auth/verify-email.js +7 -2
- package/dist/auth/verify-email.js.map +1 -1
- package/dist/billing/cancel-subscription.d.ts +20 -8
- package/dist/billing/cancel-subscription.js +7 -5
- package/dist/billing/cancel-subscription.js.map +1 -1
- package/dist/billing/dialog-close.d.ts +29 -0
- package/dist/billing/dialog-close.js +8 -0
- package/dist/billing/dialog-close.js.map +1 -0
- package/dist/billing/plan-card.d.ts +14 -4
- package/dist/billing/plan-card.js +15 -8
- package/dist/billing/plan-card.js.map +1 -1
- package/dist/billing/plan-change-labels.d.ts +42 -0
- package/dist/billing/plan-change-labels.js +22 -0
- package/dist/billing/plan-change-labels.js.map +1 -0
- package/dist/billing/plan-switch.d.ts +19 -7
- package/dist/billing/plan-switch.js +8 -4
- package/dist/billing/plan-switch.js.map +1 -1
- package/dist/chart.d.ts +12 -0
- package/dist/chart.js +16 -1
- package/dist/chart.js.map +1 -1
- package/dist/components/account-chips.d.ts +5 -5
- package/dist/components/account-chips.js +11 -13
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/alert-banner.d.ts +16 -5
- package/dist/components/alert-banner.js +46 -1
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +13 -0
- package/dist/components/amount-input.js +1 -0
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.js +57 -65
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/bulk-action-bar.d.ts +12 -2
- package/dist/components/bulk-action-bar.js +65 -21
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button-look.d.ts +5 -5
- package/dist/components/button-look.js.map +1 -1
- package/dist/components/button.d.ts +2 -2
- package/dist/components/button.js.map +1 -1
- package/dist/components/chart-edge.d.ts +16 -0
- package/dist/components/chart-edge.js +14 -1
- package/dist/components/chart-edge.js.map +1 -1
- package/dist/components/chart-figure.d.ts +13 -0
- package/dist/components/chart-figure.js +15 -0
- package/dist/components/chart-figure.js.map +1 -0
- package/dist/components/chart-zoom-core.js +1 -4
- package/dist/components/chart-zoom-core.js.map +1 -1
- package/dist/components/chart.d.ts +8 -1
- package/dist/components/chart.js +19 -10
- package/dist/components/chart.js.map +1 -1
- package/dist/components/combobox-core.d.ts +111 -2
- package/dist/components/combobox-core.js +148 -42
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +1 -1
- package/dist/components/combobox.js +141 -130
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/copy-button.d.ts +6 -5
- package/dist/components/copy-button.js +5 -3
- package/dist/components/copy-button.js.map +1 -1
- package/dist/components/country-select.js +2 -2
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/data-table-column-settings.d.ts +1 -1
- package/dist/components/data-table-column-settings.js +33 -7
- package/dist/components/data-table-column-settings.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +4 -2
- package/dist/components/data-table-filters.js +2 -2
- package/dist/components/data-table-filters.js.map +1 -1
- package/dist/components/data-table-fit.d.ts +6 -4
- package/dist/components/data-table-fit.js +4 -1
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-groups.d.ts +1 -1
- package/dist/components/data-table-groups.js.map +1 -1
- package/dist/components/data-table-head.d.ts +1 -1
- package/dist/components/data-table-head.js +15 -12
- package/dist/components/data-table-head.js.map +1 -1
- package/dist/components/data-table-mobile.d.ts +12 -7
- package/dist/components/data-table-mobile.js +43 -30
- package/dist/components/data-table-mobile.js.map +1 -1
- package/dist/components/data-table-pagination.js +11 -6
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table-resize.d.ts +1 -1
- package/dist/components/data-table-resize.js.map +1 -1
- package/dist/components/data-table-row-actions.d.ts +2 -2
- package/dist/components/data-table-row-actions.js.map +1 -1
- package/dist/components/data-table-row.d.ts +6 -2
- package/dist/components/data-table-row.js +17 -10
- package/dist/components/data-table-row.js.map +1 -1
- package/dist/components/data-table-selection.d.ts +1 -1
- package/dist/components/data-table-selection.js.map +1 -1
- package/dist/components/data-table-shared.d.ts +10 -2
- package/dist/components/data-table-shared.js +18 -0
- package/dist/components/data-table-shared.js.map +1 -1
- package/dist/components/data-table-sort.d.ts +21 -2
- package/dist/components/data-table-sort.js +24 -0
- package/dist/components/data-table-sort.js.map +1 -1
- package/dist/components/data-table-virtual.d.ts +1 -1
- package/dist/components/data-table-virtual.js +18 -6
- package/dist/components/data-table-virtual.js.map +1 -1
- package/dist/components/data-table.d.ts +13 -4
- package/dist/components/data-table.js +139 -36
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-field.d.ts +24 -2
- package/dist/components/date-field.js +33 -8
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.d.ts +15 -2
- package/dist/components/date-picker.js +55 -26
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.d.ts +47 -20
- package/dist/components/date-range-picker.js +23 -7
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/error-boundary.js +37 -30
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/{ui-labels.d.ts → field-base-labels.d.ts} +0 -2
- package/dist/components/{ui-labels.js → field-base-labels.js} +2 -9
- package/dist/components/field-base-labels.js.map +1 -0
- package/dist/components/field-base.d.ts +4 -3
- package/dist/components/field-base.js +3 -3
- package/dist/components/field-base.js.map +1 -1
- package/dist/components/field-sync-labels.d.ts +1 -0
- package/dist/components/field-sync-labels.js.map +1 -1
- package/dist/components/field-sync.d.ts +23 -1
- package/dist/components/field-sync.js.map +1 -1
- package/dist/components/form-actions.js +11 -5
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/hover-menu.d.ts +3 -0
- package/dist/components/hover-menu.js +5 -3
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/icon-button.js +14 -9
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/inline-confirm.d.ts +43 -0
- package/dist/components/inline-confirm.js +67 -0
- package/dist/components/inline-confirm.js.map +1 -0
- package/dist/components/inline-entity-combobox.d.ts +4 -3
- package/dist/components/inline-entity-combobox.js +148 -140
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/input.js +1 -1
- package/dist/components/input.js.map +1 -1
- package/dist/components/jump-calendar.js +28 -112
- package/dist/components/jump-calendar.js.map +1 -1
- package/dist/components/legal-page.d.ts +3 -1
- package/dist/components/legal-page.js +3 -2
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +4 -2
- package/dist/components/legal.js.map +1 -1
- package/dist/components/lightbox.d.ts +2 -2
- package/dist/components/lightbox.js +17 -6
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/list.d.ts +6 -2
- package/dist/components/list.js +3 -2
- package/dist/components/list.js.map +1 -1
- package/dist/components/measured-grid.d.ts +1 -1
- package/dist/components/measured-grid.js +2 -1
- package/dist/components/measured-grid.js.map +1 -1
- package/dist/components/mini-calendar.js +3 -5
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.js +3 -1
- package/dist/components/modal.js.map +1 -1
- package/dist/components/month-grid.d.ts +55 -0
- package/dist/components/month-grid.js +148 -0
- package/dist/components/month-grid.js.map +1 -0
- package/dist/components/month-picker.d.ts +36 -4
- package/dist/components/month-picker.js +123 -146
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-select.d.ts +2 -2
- package/dist/components/multi-select.js +11 -6
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/picker-sheet.js +2 -1
- package/dist/components/picker-sheet.js.map +1 -1
- package/dist/components/pie-chart-labels.d.ts +7 -0
- package/dist/components/pie-chart-labels.js +1 -0
- package/dist/components/pie-chart-labels.js.map +1 -1
- package/dist/components/pie-chart.d.ts +5 -3
- package/dist/components/pie-chart.js +7 -22
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/popover.d.ts +3 -0
- package/dist/components/popover.js +7 -1
- package/dist/components/popover.js.map +1 -1
- package/dist/components/row-actions.js +2 -1
- package/dist/components/row-actions.js.map +1 -1
- package/dist/components/section-nav.d.ts +7 -0
- package/dist/components/section-nav.js.map +1 -1
- package/dist/components/series-chart-axes.d.ts +3 -3
- package/dist/components/series-chart-axes.js.map +1 -1
- package/dist/components/series-chart-labels.d.ts +7 -4
- package/dist/components/series-chart-labels.js.map +1 -1
- package/dist/components/series-chart.d.ts +31 -7
- package/dist/components/series-chart.js +72 -29
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/share-card.js +3 -3
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/sign-chip-labels.d.ts +1 -0
- package/dist/components/sign-chip-labels.js.map +1 -1
- package/dist/components/sign-chip.d.ts +10 -1
- package/dist/components/sign-chip.js.map +1 -1
- package/dist/components/tabs-labels.d.ts +2 -0
- package/dist/components/tabs-labels.js +11 -0
- package/dist/components/tabs-labels.js.map +1 -0
- package/dist/components/tabs.d.ts +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/toggle-legend.d.ts +2 -2
- package/dist/components/toggle-legend.js +6 -6
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/translation-review-editor.d.ts +4 -2
- package/dist/components/translation-review-editor.js +2 -3
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review.d.ts +2 -1
- package/dist/components/translation-review.js +2 -2
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/treemap-labels.d.ts +26 -0
- package/dist/components/treemap-labels.js +10 -0
- package/dist/components/treemap-labels.js.map +1 -0
- package/dist/components/treemap-layout.d.ts +62 -0
- package/dist/components/treemap-layout.js +126 -0
- package/dist/components/treemap-layout.js.map +1 -0
- package/dist/components/treemap.d.ts +140 -17
- package/dist/components/treemap.js +324 -97
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/use-table-state.d.ts +5 -5
- package/dist/components/use-table-state.js +4 -1
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/data-table.d.ts +6 -2
- package/dist/data-table.js +7 -2
- package/dist/data-table.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/eslint/role-utilities.d.ts +36 -7
- package/dist/eslint/role-utilities.js +42 -9
- package/dist/eslint/role-utilities.js.map +1 -1
- package/dist/feedback/feedback-dialog.d.ts +25 -16
- package/dist/feedback/feedback-dialog.js +6 -2
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-mutation.d.ts +30 -0
- package/dist/feedback/feedback-mutation.js +16 -0
- package/dist/feedback/feedback-mutation.js.map +1 -0
- package/dist/feedback/feedback-page-link.d.ts +53 -0
- package/dist/feedback/feedback-page-link.js +37 -0
- package/dist/feedback/feedback-page-link.js.map +1 -0
- package/dist/feedback/feedback-public-list.d.ts +12 -3
- package/dist/feedback/feedback-public-list.js +2 -1
- package/dist/feedback/feedback-public-list.js.map +1 -1
- package/dist/feedback/feedback-replies.d.ts +3 -1
- package/dist/feedback/feedback-replies.js +5 -4
- package/dist/feedback/feedback-replies.js.map +1 -1
- package/dist/feedback/feedback-row-detail-labels.js +5 -0
- package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
- package/dist/feedback/feedback-row-detail.d.ts +64 -28
- package/dist/feedback/feedback-row-detail.js +30 -28
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-status-undo.d.ts +30 -11
- package/dist/feedback/feedback-status-undo.js +10 -15
- package/dist/feedback/feedback-status-undo.js.map +1 -1
- package/dist/feedback/feedback-submit-dialog.d.ts +1 -1
- package/dist/feedback/feedback-submit-dialog.js +1 -1
- package/dist/feedback/feedback-submit-dialog.js.map +1 -1
- package/dist/feedback/feedback-submit.js +9 -3
- package/dist/feedback/feedback-submit.js.map +1 -1
- package/dist/feedback/feedback-swipe.d.ts +1 -1
- package/dist/feedback/feedback-swipe.js.map +1 -1
- package/dist/feedback/feedback-table.d.ts +21 -9
- package/dist/feedback/feedback-table.js +45 -25
- package/dist/feedback/feedback-table.js.map +1 -1
- package/dist/feedback/feedback-thread-labels.d.ts +2 -2
- package/dist/feedback/feedback-thread-labels.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +24 -23
- package/dist/feedback/feedback-thread.js +2 -1
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +34 -0
- package/dist/feedback.js +42 -0
- package/dist/feedback.js.map +1 -1
- package/dist/hooks/use-focus-trap.d.ts +35 -0
- package/dist/hooks/use-focus-trap.js +6 -4
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-hotkey.d.ts +5 -2
- package/dist/hooks/use-hotkey.js +5 -4
- package/dist/hooks/use-hotkey.js.map +1 -1
- package/dist/hooks/use-long-press.d.ts +7 -4
- package/dist/hooks/use-long-press.js +3 -0
- package/dist/hooks/use-long-press.js.map +1 -1
- package/dist/hooks/use-media-query.js +12 -4
- package/dist/hooks/use-media-query.js.map +1 -1
- package/dist/hooks/use-mounted.d.ts +22 -0
- package/dist/hooks/use-mounted.js +24 -0
- package/dist/hooks/use-mounted.js.map +1 -0
- package/dist/hooks/use-overlay-history.js +19 -3
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.js +4 -5
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +7 -1
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +9 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +20 -41
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +7 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +20 -10
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +9 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +7 -1
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +8 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +5 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +64 -17
- package/dist/index.js +77 -12
- package/dist/index.js.map +1 -1
- package/dist/landing/routing.d.ts +3 -1
- package/dist/landing/routing.js +4 -7
- package/dist/landing/routing.js.map +1 -1
- package/dist/lib/broadcast.d.ts +17 -0
- package/dist/lib/broadcast.js +30 -0
- package/dist/lib/broadcast.js.map +1 -0
- package/dist/lib/date-format.d.ts +37 -2
- package/dist/lib/date-format.js +34 -8
- package/dist/lib/date-format.js.map +1 -1
- package/dist/lib/day-format.d.ts +46 -0
- package/dist/lib/day-format.js +46 -0
- package/dist/lib/day-format.js.map +1 -0
- package/dist/lib/describe-failure.d.ts +14 -0
- package/dist/lib/describe-failure.js +9 -0
- package/dist/lib/describe-failure.js.map +1 -0
- package/dist/lib/direction.d.ts +16 -0
- package/dist/lib/direction.js +9 -1
- package/dist/lib/direction.js.map +1 -1
- package/dist/lib/focus-left.d.ts +63 -0
- package/dist/lib/focus-left.js +67 -0
- package/dist/lib/focus-left.js.map +1 -0
- package/dist/lib/format.js +5 -14
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/http-status.d.ts +24 -0
- package/dist/lib/http-status.js +14 -0
- package/dist/lib/http-status.js.map +1 -0
- package/dist/lib/intl-cache.d.ts +14 -0
- package/dist/lib/intl-cache.js +15 -0
- package/dist/lib/intl-cache.js.map +1 -0
- package/dist/lib/isin.d.ts +10 -0
- package/dist/lib/isin.js.map +1 -1
- package/dist/lib/iso-day.d.ts +11 -0
- package/dist/lib/iso-day.js +8 -0
- package/dist/lib/iso-day.js.map +1 -0
- package/dist/lib/lazy-with-fallback.d.ts +31 -0
- package/dist/lib/lazy-with-fallback.js +40 -0
- package/dist/lib/lazy-with-fallback.js.map +1 -0
- package/dist/lib/path-pattern.d.ts +34 -0
- package/dist/lib/path-pattern.js +24 -0
- package/dist/lib/path-pattern.js.map +1 -0
- package/dist/lib/reduced-motion.d.ts +2 -1
- package/dist/lib/reduced-motion.js.map +1 -1
- package/dist/lib/round.d.ts +2 -1
- package/dist/lib/round.js +2 -1
- package/dist/lib/round.js.map +1 -1
- package/dist/lib/safe-storage.d.ts +24 -5
- package/dist/lib/safe-storage.js +27 -2
- package/dist/lib/safe-storage.js.map +1 -1
- package/dist/lib/session-refresh.js +1 -1
- package/dist/lib/session-refresh.js.map +1 -1
- package/dist/lib/share-format.d.ts +13 -0
- package/dist/lib/share-format.js +10 -0
- package/dist/lib/share-format.js.map +1 -0
- package/dist/lib/text-case.d.ts +17 -0
- package/dist/lib/text-case.js +8 -0
- package/dist/lib/text-case.js.map +1 -0
- package/dist/lib/text-match.d.ts +29 -0
- package/dist/lib/text-match.js +20 -2
- package/dist/lib/text-match.js.map +1 -1
- package/dist/lib/thenable.d.ts +13 -0
- package/dist/lib/thenable.js +8 -0
- package/dist/lib/thenable.js.map +1 -0
- package/dist/lib/translation-review.d.ts +7 -2
- package/dist/lib/translation-review.js +4 -4
- package/dist/lib/translation-review.js.map +1 -1
- package/dist/notifications/device-zone-report.js +1 -1
- package/dist/notifications/device-zone-report.js.map +1 -1
- package/dist/notifications/notification-bell.d.ts +2 -1
- package/dist/notifications/notification-bell.js +3 -3
- package/dist/notifications/notification-bell.js.map +1 -1
- package/dist/notifications/notification-inbox.d.ts +10 -6
- package/dist/notifications/notification-inbox.js +26 -48
- package/dist/notifications/notification-inbox.js.map +1 -1
- package/dist/notifications/notification-parts.d.ts +3 -2
- package/dist/notifications/notification-parts.js +1 -3
- package/dist/notifications/notification-parts.js.map +1 -1
- package/dist/notifications/notification-types-setting.js +1 -1
- package/dist/notifications/notification-types-setting.js.map +1 -1
- package/dist/notifications/notifications-labels.d.ts +6 -0
- package/dist/notifications/notifications-labels.js +1 -0
- package/dist/notifications/notifications-labels.js.map +1 -1
- package/dist/notifications/push-device-setting.js +1 -1
- package/dist/notifications/push-device-setting.js.map +1 -1
- package/dist/notifications/push-devices-setting.d.ts +2 -1
- package/dist/notifications/push-devices-setting.js +27 -49
- package/dist/notifications/push-devices-setting.js.map +1 -1
- package/dist/notifications/quiet-hours-setting.d.ts +10 -3
- package/dist/notifications/quiet-hours-setting.js +65 -26
- package/dist/notifications/quiet-hours-setting.js.map +1 -1
- package/dist/notifications/unsubscribe-panel.js +4 -7
- package/dist/notifications/unsubscribe-panel.js.map +1 -1
- package/dist/notifications/use-push-device.d.ts +39 -1
- package/dist/notifications/use-push-device.js +28 -7
- package/dist/notifications/use-push-device.js.map +1 -1
- package/dist/offline/query-persistence.d.ts +3 -1
- package/dist/offline/query-persistence.js +19 -2
- package/dist/offline/query-persistence.js.map +1 -1
- package/dist/rhf/fields.d.ts +11 -4
- package/dist/rhf/fields.js.map +1 -1
- package/dist/search/command-palette.js +1 -1
- package/dist/search/command-palette.js.map +1 -1
- package/dist/search/global-search.js +19 -9
- package/dist/search/global-search.js.map +1 -1
- package/dist/search/use-command-key.d.ts +12 -1
- package/dist/search/use-command-key.js +3 -12
- package/dist/search/use-command-key.js.map +1 -1
- package/dist/search.d.ts +7 -0
- package/dist/search.js +10 -0
- package/dist/search.js.map +1 -1
- package/dist/settings/use-settings-focus.js +1 -0
- package/dist/settings/use-settings-focus.js.map +1 -1
- package/dist/shell/account-menu-language.d.ts +21 -5
- package/dist/shell/account-menu-language.js +3 -1
- package/dist/shell/account-menu-language.js.map +1 -1
- package/dist/shell/account-menu-text-size.d.ts +26 -9
- package/dist/shell/account-menu-text-size.js +3 -2
- package/dist/shell/account-menu-text-size.js.map +1 -1
- package/dist/shell/dev-menu.js +5 -18
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/role-switcher.d.ts +7 -0
- package/dist/shell/role-switcher.js.map +1 -1
- package/dist/shell/top-bar-actions.d.ts +1 -1
- package/dist/shell/top-bar-actions.js.map +1 -1
- package/dist/shell/top-bar-parts-labels.d.ts +0 -2
- package/dist/shell/top-bar-parts-labels.js +0 -1
- package/dist/shell/top-bar-parts-labels.js.map +1 -1
- package/dist/shell.d.ts +27 -8
- package/dist/shell.js +28 -7
- package/dist/shell.js.map +1 -1
- package/dist/sync/engine.d.ts +30 -4
- package/dist/sync/engine.js +172 -52
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync.d.ts +6 -2
- package/dist/sync.js +6 -1
- package/dist/sync.js.map +1 -1
- package/dist/testing/css-variables.js +3 -8
- package/dist/testing/css-variables.js.map +1 -1
- package/dist/theme/contrast.d.ts +2 -1
- package/dist/theme/contrast.js +3 -8
- package/dist/theme/contrast.js.map +1 -1
- package/dist/theme/palette-store.js +6 -6
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/text-size.js +3 -8
- package/dist/theme/text-size.js.map +1 -1
- package/dist/theme/theme-store.js +3 -6
- package/dist/theme/theme-store.js.map +1 -1
- package/dist/tour/tour-catalogue.d.ts +7 -4
- package/dist/tour/tour-catalogue.js +12 -10
- package/dist/tour/tour-catalogue.js.map +1 -1
- package/dist/tour/tour-dock.d.ts +0 -2
- package/dist/tour/tour-dock.js +0 -2
- package/dist/tour/tour-dock.js.map +1 -1
- package/dist/tour/tour-gates.d.ts +4 -0
- package/dist/tour/tour-gates.js +14 -0
- package/dist/tour/tour-gates.js.map +1 -1
- package/dist/tour/tour-overlay.d.ts +27 -0
- package/dist/tour/tour-overlay.js +741 -0
- package/dist/tour/tour-overlay.js.map +1 -0
- package/dist/tour/tour.d.ts +13 -3
- package/dist/tour/tour.js +59 -781
- package/dist/tour/tour.js.map +1 -1
- package/dist/tour/use-tour-progress.js +1 -1
- package/dist/tour/use-tour-progress.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +5 -1
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard/types.d.ts +6 -2
- package/dist/wizard/types.js.map +1 -1
- package/dist/wizard/use-wizard.d.ts +3 -1
- package/dist/wizard/use-wizard.js.map +1 -1
- package/dist/wizard/validation.d.ts +3 -1
- package/dist/wizard/validation.js.map +1 -1
- package/package.json +10 -6
- package/src/account/account-parts.ts +5 -25
- package/src/account/data-export-setting-labels.ts +1 -1
- package/src/account/delete-account-setting-labels.ts +1 -1
- package/src/account/email-change-setting-labels.ts +1 -1
- package/src/account/passkeys-setting.tsx +60 -38
- package/src/account/sessions-setting.tsx +18 -12
- package/src/admin/admin-action-confirm.tsx +1 -5
- package/src/admin/admin-parts.ts +11 -25
- package/src/admin/mail-test-card-labels.ts +1 -1
- package/src/admin/plan-change-labels.ts +5 -23
- package/src/admin/plan-change.tsx +7 -44
- package/src/admin/reviewer-scope-editor.tsx +3 -3
- package/src/auth/auth-errors-labels.ts +23 -0
- package/src/auth/auth-errors.ts +11 -38
- package/src/auth/complete-name-dialog.tsx +4 -1
- package/src/auth/forgot-password-form-labels.ts +1 -1
- package/src/auth/forgot-password-form.tsx +11 -6
- package/src/auth/register-form-labels.ts +1 -1
- package/src/auth/reset-password-form-labels.ts +1 -1
- package/src/auth/reset-password-form.tsx +8 -4
- package/src/auth/sign-in-form-labels.ts +1 -1
- package/src/auth/status-parts.tsx +0 -6
- package/src/auth/verify-email-labels.ts +1 -1
- package/src/auth/verify-email.tsx +11 -6
- package/src/billing/cancel-subscription.tsx +26 -12
- package/src/billing/dialog-close.ts +34 -0
- package/src/billing/plan-card.tsx +36 -11
- package/src/billing/plan-change-labels.ts +66 -0
- package/src/billing/plan-switch.tsx +26 -12
- package/src/chart.ts +21 -3
- package/src/components/account-chips.tsx +20 -23
- package/src/components/alert-banner.tsx +82 -5
- package/src/components/amount-input.tsx +18 -7
- package/src/components/autocomplete.tsx +64 -70
- package/src/components/bulk-action-bar.tsx +70 -2
- package/src/components/button-look.ts +5 -5
- package/src/components/button.tsx +2 -2
- package/src/components/chart-edge.ts +34 -1
- package/src/components/chart-figure.tsx +35 -0
- package/src/components/chart-zoom-core.tsx +6 -5
- package/src/components/chart.tsx +26 -5
- package/src/components/combobox-core.tsx +293 -62
- package/src/components/combobox.tsx +183 -153
- package/src/components/copy-button.tsx +34 -23
- package/src/components/country-select.tsx +16 -11
- package/src/components/data-table-column-settings.tsx +52 -10
- package/src/components/data-table-filters.ts +6 -4
- package/src/components/data-table-fit.ts +19 -5
- package/src/components/data-table-groups.tsx +1 -1
- package/src/components/data-table-head.tsx +32 -22
- package/src/components/data-table-mobile.tsx +61 -26
- package/src/components/data-table-pagination.tsx +21 -6
- package/src/components/data-table-resize.ts +1 -1
- package/src/components/data-table-row-actions.tsx +3 -3
- package/src/components/data-table-row.tsx +25 -14
- package/src/components/data-table-selection.ts +1 -1
- package/src/components/data-table-shared.tsx +33 -1
- package/src/components/data-table-sort.ts +57 -2
- package/src/components/data-table-virtual.ts +32 -8
- package/src/components/data-table.tsx +239 -68
- package/src/components/date-field.tsx +65 -8
- package/src/components/date-picker.tsx +125 -48
- package/src/components/date-range-picker.tsx +82 -31
- package/src/components/error-boundary.tsx +53 -39
- package/src/components/field-base-labels.ts +20 -0
- package/src/components/field-base.tsx +13 -7
- package/src/components/field-sync-labels.ts +1 -0
- package/src/components/field-sync.tsx +23 -1
- package/src/components/form-actions.tsx +20 -5
- package/src/components/hover-menu.tsx +18 -8
- package/src/components/icon-button.tsx +14 -9
- package/src/components/inline-confirm.tsx +116 -0
- package/src/components/inline-entity-combobox.tsx +197 -153
- package/src/components/input.tsx +1 -1
- package/src/components/jump-calendar.tsx +30 -146
- package/src/components/legal-page.tsx +10 -7
- package/src/components/legal.tsx +4 -2
- package/src/components/lightbox.tsx +21 -8
- package/src/components/list.tsx +10 -4
- package/src/components/measured-grid.tsx +8 -4
- package/src/components/mini-calendar.tsx +6 -5
- package/src/components/modal.tsx +6 -1
- package/src/components/month-grid.tsx +229 -0
- package/src/components/month-picker.tsx +192 -200
- package/src/components/multi-select.tsx +21 -9
- package/src/components/picker-sheet.tsx +12 -9
- package/src/components/pie-chart-labels.ts +8 -0
- package/src/components/pie-chart.tsx +22 -28
- package/src/components/popover.tsx +18 -1
- package/src/components/row-actions.tsx +2 -1
- package/src/components/section-nav.tsx +7 -0
- package/src/components/series-chart-axes.ts +3 -3
- package/src/components/series-chart-labels.ts +7 -4
- package/src/components/series-chart.tsx +178 -69
- package/src/components/share-card.tsx +6 -6
- package/src/components/sign-chip-labels.ts +1 -0
- package/src/components/sign-chip.tsx +10 -1
- package/src/components/tabs-labels.ts +13 -0
- package/src/components/tabs.tsx +2 -2
- package/src/components/toggle-legend.tsx +16 -11
- package/src/components/translation-review-editor.tsx +6 -5
- package/src/components/translation-review.tsx +4 -3
- package/src/components/treemap-labels.ts +39 -0
- package/src/components/treemap-layout.ts +210 -0
- package/src/components/treemap.tsx +722 -133
- package/src/components/use-table-state.ts +12 -9
- package/src/data-table.ts +9 -2
- package/src/eslint/role-utilities.ts +97 -19
- package/src/feedback/feedback-dialog.tsx +30 -19
- package/src/feedback/feedback-mutation.ts +41 -0
- package/src/feedback/feedback-page-link.ts +90 -0
- package/src/feedback/feedback-public-list.tsx +17 -5
- package/src/feedback/feedback-replies.tsx +13 -6
- package/src/feedback/feedback-row-detail-labels.ts +5 -0
- package/src/feedback/feedback-row-detail.tsx +103 -67
- package/src/feedback/feedback-status-undo.ts +41 -27
- package/src/feedback/feedback-submit-dialog.tsx +2 -2
- package/src/feedback/feedback-submit.tsx +21 -7
- package/src/feedback/feedback-swipe.tsx +1 -1
- package/src/feedback/feedback-table.tsx +86 -38
- package/src/feedback/feedback-thread-labels.ts +2 -2
- package/src/feedback/feedback-thread.tsx +27 -25
- package/src/feedback.ts +42 -0
- package/src/hooks/use-focus-trap.ts +8 -24
- package/src/hooks/use-hotkey.ts +24 -7
- package/src/hooks/use-long-press.ts +16 -2
- package/src/hooks/use-media-query.ts +20 -4
- package/src/hooks/use-mounted.ts +39 -0
- package/src/hooks/use-overlay-history.ts +32 -3
- package/src/i18n/defaults.ts +4 -5
- package/src/i18n/german.ts +8 -2
- package/src/i18n/kit-labels.tsx +9 -2
- package/src/i18n/locales/es.ts +8 -2
- package/src/i18n/locales/fr.ts +21 -13
- package/src/i18n/locales/hu.ts +10 -2
- package/src/i18n/locales/it.ts +8 -2
- package/src/i18n/locales/zh.ts +9 -2
- package/src/i18n/review.ts +5 -0
- package/src/index.ts +103 -13
- package/src/landing/routing.tsx +14 -10
- package/src/lib/broadcast.ts +52 -0
- package/src/lib/date-format.ts +89 -13
- package/src/lib/day-format.ts +96 -0
- package/src/lib/describe-failure.ts +18 -0
- package/src/lib/direction.ts +39 -0
- package/src/lib/focus-left.ts +156 -0
- package/src/lib/format.ts +5 -17
- package/src/lib/http-status.ts +38 -0
- package/src/lib/intl-cache.ts +25 -0
- package/src/lib/isin.ts +10 -0
- package/src/lib/iso-day.ts +13 -0
- package/src/lib/lazy-with-fallback.ts +82 -0
- package/src/lib/path-pattern.ts +55 -0
- package/src/lib/reduced-motion.ts +2 -1
- package/src/lib/round.ts +7 -2
- package/src/lib/safe-storage.ts +48 -6
- package/src/lib/session-refresh.ts +1 -1
- package/src/lib/share-format.ts +18 -0
- package/src/lib/text-case.ts +19 -0
- package/src/lib/text-match.ts +57 -2
- package/src/lib/thenable.ts +19 -0
- package/src/lib/translation-review.ts +13 -5
- package/src/notifications/device-zone-report.ts +1 -1
- package/src/notifications/notification-bell.tsx +7 -4
- package/src/notifications/notification-inbox.tsx +40 -58
- package/src/notifications/notification-parts.tsx +3 -4
- package/src/notifications/notification-types-setting.tsx +1 -1
- package/src/notifications/notifications-labels.ts +7 -0
- package/src/notifications/push-device-setting.tsx +1 -1
- package/src/notifications/push-devices-setting.tsx +30 -55
- package/src/notifications/quiet-hours-setting.tsx +93 -31
- package/src/notifications/unsubscribe-panel.tsx +4 -7
- package/src/notifications/use-push-device.ts +76 -10
- package/src/offline/query-persistence.ts +35 -3
- package/src/rhf/fields.tsx +11 -4
- package/src/search/command-palette.tsx +2 -4
- package/src/search/global-search.tsx +36 -15
- package/src/search/use-command-key.ts +13 -12
- package/src/search.ts +9 -0
- package/src/settings/use-settings-focus.ts +3 -0
- package/src/shell/account-menu-language.tsx +27 -5
- package/src/shell/account-menu-text-size.tsx +32 -10
- package/src/shell/dev-menu.tsx +7 -21
- package/src/shell/role-switcher.tsx +7 -0
- package/src/shell/top-bar-actions.tsx +1 -1
- package/src/shell/top-bar-parts-labels.ts +0 -3
- package/src/shell.ts +40 -9
- package/src/sync/engine.ts +339 -61
- package/src/sync.ts +8 -1
- package/src/testing/css-variables.ts +8 -9
- package/src/theme/contrast.ts +8 -9
- package/src/theme/palette-store.ts +9 -9
- package/src/theme/text-size.ts +6 -8
- package/src/theme/theme-store.ts +7 -9
- package/src/tour/tour-catalogue.tsx +26 -15
- package/src/tour/tour-dock.ts +0 -2
- package/src/tour/tour-gates.ts +23 -0
- package/src/tour/tour-overlay.tsx +1170 -0
- package/src/tour/tour.tsx +108 -1202
- package/src/tour/use-tour-progress.ts +1 -1
- package/src/wizard/stepper-nav.tsx +3 -1
- package/src/wizard/types.ts +11 -2
- package/src/wizard/use-wizard.ts +2 -1
- package/src/wizard/validation.ts +8 -2
- package/tokens.css +2 -1
- package/dist/components/ui-labels.js.map +0 -1
- package/dist/shell/dev-switchers.d.ts +0 -6
- package/dist/shell/dev-switchers.js +0 -12
- package/dist/shell/dev-switchers.js.map +0 -1
- package/src/components/ui-labels.ts +0 -24
- package/src/shell/dev-switchers.tsx +0 -18
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
|
|
1
|
+
import { useId, useMemo, useRef, useState } from "react";
|
|
2
|
+
import type { ComponentPropsWithoutRef, KeyboardEvent, ReactNode, Ref } from "react";
|
|
3
3
|
import { ChevronDown } from "lucide-react";
|
|
4
4
|
import { FIELD_BASE, FIELD_FLOATING_PAD, FIELD_INVALID } from "./field-base";
|
|
5
5
|
import { cn } from "../lib/cn";
|
|
@@ -9,9 +9,18 @@ import { isImeEnter } from "../lib/ime";
|
|
|
9
9
|
import { isQuietFocus } from "../lib/quiet-focus";
|
|
10
10
|
import { usePhoneLayout } from "../hooks/use-breakpoint";
|
|
11
11
|
import { PickerSheet, SHEET_ROW_CLASS } from "./picker-sheet";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
import {
|
|
13
|
+
anchoredHeadingClass,
|
|
14
|
+
ComboboxFieldLabel,
|
|
15
|
+
endHintRowProps,
|
|
16
|
+
GroupedOptions,
|
|
17
|
+
groupRuns,
|
|
18
|
+
SHEET_HEADING_CLASS,
|
|
19
|
+
useTypedListStatus,
|
|
20
|
+
type GroupRun,
|
|
21
|
+
} from "./combobox-core";
|
|
22
|
+
import { DEFAULT_COMBOBOX_LABELS, useKitLabels, useKitLocale } from "../i18n/kit-labels";
|
|
23
|
+
import { sameName, searchRanked } from "../lib/text-match";
|
|
15
24
|
import {
|
|
16
25
|
EndHintRow,
|
|
17
26
|
FieldCaption,
|
|
@@ -44,7 +53,7 @@ export interface ComboboxProps
|
|
|
44
53
|
value: string;
|
|
45
54
|
onChange: (v: string) => void;
|
|
46
55
|
/** Suggestion pool (e.g. existing payee names). */
|
|
47
|
-
options: string[];
|
|
56
|
+
options: readonly string[];
|
|
48
57
|
/** The visible label, a `<label for>` above the field: a ReactNode, as on every kit
|
|
49
58
|
* field (a string until 0.34, refactor audit 2026-10, API-9). Without one, name the
|
|
50
59
|
* field with `aria-label`. */
|
|
@@ -223,6 +232,12 @@ export function Combobox(props: ComboboxProps) {
|
|
|
223
232
|
const { open, setOpen, wrapperRef, panelRef } = useDropdown({ backCloses: !isPhone, escapeLayer: false });
|
|
224
233
|
const primaryOnly = usePrimaryPressOnly();
|
|
225
234
|
const [active, setActive] = useState(-1);
|
|
235
|
+
// A closed list has no row the keyboard is on, however it closed — the sheet's X,
|
|
236
|
+
// Escape or Back, a press outside — adjusted while rendering. The arrows' row outlived
|
|
237
|
+
// it: the list reopens on the whole pool, so the row the arrows had put on "Migros"
|
|
238
|
+
// showed "Aldi" highlighted, and Enter took it over the typed value (0.52 code review,
|
|
239
|
+
// combobox.tsx). An ArrowDown that opens the list sets both at once, and keeps its row.
|
|
240
|
+
if (!open && active !== -1) setActive(-1);
|
|
226
241
|
// The lock (see `lockedKeyDown`): a lock arriving while the list is up closes it,
|
|
227
242
|
// adjusted while rendering so no frame offers a row that can no longer be taken.
|
|
228
243
|
const lock = useLockReason(commit, disabledReason);
|
|
@@ -264,6 +279,9 @@ export function Combobox(props: ComboboxProps) {
|
|
|
264
279
|
const query = typing ? value.trim() : "";
|
|
265
280
|
// Folded as every kit list folds (DUP-5): "zurich" finds Zürich, by the locale's case.
|
|
266
281
|
const locale = useKitLocale();
|
|
282
|
+
// The live status's words (INP-6): the result count and "No results", as the panel
|
|
283
|
+
// pickers say them.
|
|
284
|
+
const labels = useKitLabels("combobox", DEFAULT_COMBOBOX_LABELS);
|
|
267
285
|
const matches = useMemo(() => {
|
|
268
286
|
const seen = new Set<string>();
|
|
269
287
|
const uniq = options.filter((o) => o && !seen.has(o) && seen.add(o));
|
|
@@ -272,13 +290,14 @@ export function Combobox(props: ComboboxProps) {
|
|
|
272
290
|
if (!query) {
|
|
273
291
|
ranked = uniq.slice(0, cap);
|
|
274
292
|
} else {
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
293
|
+
// Every word of the query somewhere in the name (0.51.4's rule, which this list
|
|
294
|
+
// was said to have and did not: refactor audit 2026-10-30, DUP-4), ranked by the
|
|
295
|
+
// WHOLE query — the whole name, then prefix matches, then substring matches, then
|
|
296
|
+
// the names that hold the words apart (`searchRanked`, each name folded once). A
|
|
297
|
+
// stable sort keeps the pool's order within a rank.
|
|
298
|
+
ranked = searchRanked(uniq, query, (o) => [o], { locale })
|
|
280
299
|
.sort((a, b) => a.rank - b.rank)
|
|
281
|
-
.map((x) => x.
|
|
300
|
+
.map((x) => x.row)
|
|
282
301
|
.slice(0, cap);
|
|
283
302
|
}
|
|
284
303
|
if (!groupBy) return ranked;
|
|
@@ -296,27 +315,22 @@ export function Combobox(props: ComboboxProps) {
|
|
|
296
315
|
}, [options, query, groupBy, maxSuggestions, isPhone, locale]);
|
|
297
316
|
|
|
298
317
|
/**
|
|
299
|
-
*
|
|
318
|
+
* The rows cut into their groups — computed once for both lists, each run a
|
|
319
|
+
* `role="group"` its heading names (INP-8). Without `groupBy`, one bare run.
|
|
300
320
|
*
|
|
301
|
-
* The desktop list had
|
|
302
|
-
* `matches[matches.indexOf(o) - 1]`, which is a scan of the list per row and
|
|
303
|
-
* per heading test. That is quadratic in the sheet's own cap of 50, on the
|
|
304
|
-
* that runs on the slowest hardware we ship to — and it answers the wrong
|
|
305
|
-
* besides: `indexOf` finds the FIRST row with that string, so a duplicated
|
|
306
|
-
* would have compared against a neighbour it is not next to. (`matches`
|
|
307
|
-
* today; that is a property of the memo above, not of the row being
|
|
321
|
+
* The desktop list had the boundaries as `matches[i - 1]`, which is free; the sheet had
|
|
322
|
+
* them as `matches[matches.indexOf(o) - 1]`, which is a scan of the list per row and
|
|
323
|
+
* another per heading test. That is quadratic in the sheet's own cap of 50, on the
|
|
324
|
+
* branch that runs on the slowest hardware we ship to — and it answers the wrong
|
|
325
|
+
* question besides: `indexOf` finds the FIRST row with that string, so a duplicated
|
|
326
|
+
* option would have compared against a neighbour it is not next to. (`matches`
|
|
327
|
+
* de-duplicates today; that is a property of the memo above, not of the row being
|
|
328
|
+
* rendered.)
|
|
308
329
|
*/
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
matches.forEach((o, i) => {
|
|
314
|
-
const group = groupBy(o);
|
|
315
|
-
if (group != null && group !== prev) heads.set(i, group);
|
|
316
|
-
prev = group;
|
|
317
|
-
});
|
|
318
|
-
return heads;
|
|
319
|
-
}, [matches, groupBy]);
|
|
330
|
+
const runs = useMemo<GroupRun<string>[]>(
|
|
331
|
+
() => (groupBy ? groupRuns(matches, groupBy) : [{ group: null, start: 0, rows: matches }]),
|
|
332
|
+
[matches, groupBy],
|
|
333
|
+
);
|
|
320
334
|
|
|
321
335
|
const take = (v: string) => {
|
|
322
336
|
if (locked) return;
|
|
@@ -328,18 +342,6 @@ export function Combobox(props: ComboboxProps) {
|
|
|
328
342
|
setTyping(false);
|
|
329
343
|
};
|
|
330
344
|
|
|
331
|
-
// Offered only when the typed text is genuinely NOT in the pool: an exact match —
|
|
332
|
-
// folded as the list matches, so "cafe" is Café ({@link sameName}, DUP-5 in the
|
|
333
|
-
// 2026-10-30 refactor audit) — is an existing entry the list is already showing, and a
|
|
334
|
-
// second way to pick it would be noise. Compared against `options`, not `matches` —
|
|
335
|
-
// `matches` is capped, so a pool of 300 payees would otherwise offer to "add" one
|
|
336
|
-
// that exists but fell off the end of the list.
|
|
337
|
-
// What the field claims the keyboard is on. Only on a pointer device: the phone
|
|
338
|
-
// renders its rows in a {@link PickerSheet} whose own search box owns focus, and a
|
|
339
|
-
// field pointing at an id that is not there is worse than one pointing nowhere.
|
|
340
|
-
const activeId = !isPhone && active >= 0 && active < matches.length ? optionId(active) : undefined;
|
|
341
|
-
useActiveOptionScroll(activeId);
|
|
342
|
-
|
|
343
345
|
// While locked the field sits in the reason's Tooltip — in a fragment with a hidden
|
|
344
346
|
// copy of the reason, Button's anatomy; `block` so a full-width field stays full width.
|
|
345
347
|
const withLock = (box: ReactNode) =>
|
|
@@ -351,19 +353,81 @@ export function Combobox(props: ComboboxProps) {
|
|
|
351
353
|
box
|
|
352
354
|
);
|
|
353
355
|
|
|
356
|
+
// Offered only when the typed text is genuinely NOT in the pool: an exact match —
|
|
357
|
+
// folded as the list matches, so "cafe" is Café ({@link sameName}, DUP-5 in the
|
|
358
|
+
// 2026-10-30 refactor audit) — is an existing entry the list is already showing, and a
|
|
359
|
+
// second way to pick it would be noise. Compared against `options`, not `matches` —
|
|
360
|
+
// `matches` is capped, so a pool of 300 payees would otherwise offer to "add" one
|
|
361
|
+
// that exists but fell off the end of the list.
|
|
354
362
|
const typed = value.trim();
|
|
355
363
|
const createRow =
|
|
356
364
|
createLabel && typed.length > 0 && !options.some((o) => sameName(o, typed, locale)) ? createLabel(typed) : null;
|
|
357
365
|
|
|
366
|
+
// Whether a list shows, the row the keyboard is on — named by the field, or on a phone
|
|
367
|
+
// by the sheet's own search box, which takes the same keys (INP-6, 0.34's BUG-5 for
|
|
368
|
+
// this field) — and the live status: the family's one rule for a typed list.
|
|
369
|
+
const { showing, expanded, activeOption, statusRegion } = useTypedListStatus({
|
|
370
|
+
isPhone,
|
|
371
|
+
open,
|
|
372
|
+
inert,
|
|
373
|
+
rowCount: matches.length,
|
|
374
|
+
extraRow: Boolean(createRow),
|
|
375
|
+
query,
|
|
376
|
+
active: active < matches.length ? active : -1,
|
|
377
|
+
optionId,
|
|
378
|
+
labels,
|
|
379
|
+
});
|
|
358
380
|
// The list is a layer on the Escape stack while it SHOWS (Wave 2, DUP-1): an Escape
|
|
359
381
|
// over an empty "open" list is the dialog's, as it always was. On a phone the sheet
|
|
360
382
|
// is the layer.
|
|
361
|
-
const showing = !isPhone && open && !inert && (matches.length > 0 || Boolean(createRow));
|
|
362
383
|
useDismissLayer(showing, () => {
|
|
363
384
|
setOpen(false);
|
|
364
385
|
setActive(-1);
|
|
365
386
|
});
|
|
366
387
|
|
|
388
|
+
/** The list's keys — in the field and, on a phone, in the sheet's search box. Enter
|
|
389
|
+
* with no row highlighted is "I mean what I typed" in both. */
|
|
390
|
+
const listKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
|
|
391
|
+
if (e.key === "ArrowDown") {
|
|
392
|
+
e.preventDefault();
|
|
393
|
+
setOpen(true);
|
|
394
|
+
setActive((i) => Math.min(i + 1, matches.length - 1));
|
|
395
|
+
} else if (e.key === "ArrowUp") {
|
|
396
|
+
e.preventDefault();
|
|
397
|
+
setActive((i) => Math.max(i - 1, 0));
|
|
398
|
+
} else if (e.key === "Enter") {
|
|
399
|
+
// The Enter that confirms an IME composition is the IME's: it picks no row and
|
|
400
|
+
// submits nothing (BUG-9).
|
|
401
|
+
if (isImeEnter(e)) return;
|
|
402
|
+
if (open && active >= 0 && active < matches.length) {
|
|
403
|
+
e.preventDefault();
|
|
404
|
+
take(matches[active]);
|
|
405
|
+
} else {
|
|
406
|
+
// No row highlighted: the typed text is the answer. `preventDefault` only when a
|
|
407
|
+
// caller is taking Enter, so a plain form submit is otherwise left alone.
|
|
408
|
+
if (onSubmit) e.preventDefault();
|
|
409
|
+
setOpen(false);
|
|
410
|
+
onSubmit?.();
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
/** The rows in their runs — each group a `role="group"` its heading names (INP-8) —
|
|
416
|
+
* for the sheet or the anchored list; `row` draws one option, `grouped` when it
|
|
417
|
+
* stands under a heading. `matches` is group-contiguous, so the boundaries are a
|
|
418
|
+
* property of the list rather than of the branch drawing it (see `runs`). */
|
|
419
|
+
const groupedRows = (sheet: boolean, row: (o: string, i: number, grouped: boolean) => ReactNode) => (
|
|
420
|
+
<GroupedOptions
|
|
421
|
+
runs={runs}
|
|
422
|
+
listboxId={listboxId}
|
|
423
|
+
rowKey={(o) => o}
|
|
424
|
+
row={row}
|
|
425
|
+
// The list's first item sits closer to its top edge; the create row comes first
|
|
426
|
+
// when there is one.
|
|
427
|
+
headingClassName={(run) => (sheet ? SHEET_HEADING_CLASS : anchoredHeadingClass(run, !createRow))}
|
|
428
|
+
/>
|
|
429
|
+
);
|
|
430
|
+
|
|
367
431
|
return (
|
|
368
432
|
// `rest` dresses the outer box — a `data-tour` anchor, a test id. Not the NAME,
|
|
369
433
|
// description, invalid or required state: those belong on the <input> below,
|
|
@@ -400,13 +464,15 @@ export function Combobox(props: ComboboxProps) {
|
|
|
400
464
|
// field otherwise (dev#477: a field with neither announces only its text).
|
|
401
465
|
aria-label={ariaLabel}
|
|
402
466
|
role="combobox"
|
|
403
|
-
aria-expanded={
|
|
467
|
+
aria-expanded={expanded}
|
|
404
468
|
// The list this field is the mouth of. Required by the role, and the half
|
|
405
469
|
// that was missing: the field said it was expanded and never said what it
|
|
406
470
|
// had expanded, so a reader had no way from the box to the options
|
|
407
471
|
// (ESLint's `role-has-required-aria-props`, the audit's §a11y).
|
|
408
472
|
aria-controls={listboxId}
|
|
409
|
-
|
|
473
|
+
// Only on a pointer device: on a phone the sheet's own search box holds
|
|
474
|
+
// focus and names the row, and the field behind it says nothing.
|
|
475
|
+
aria-activedescendant={isPhone ? undefined : activeOption}
|
|
410
476
|
aria-autocomplete="list"
|
|
411
477
|
aria-invalid={field.isInvalid || undefined}
|
|
412
478
|
aria-describedby={mergeDescribedBy(field.describedBy, locked && lock.reasonId)}
|
|
@@ -430,6 +496,7 @@ export function Combobox(props: ComboboxProps) {
|
|
|
430
496
|
if (isQuietFocus(e.currentTarget)) return;
|
|
431
497
|
setOpen(true);
|
|
432
498
|
setTyping(false);
|
|
499
|
+
setActive(-1);
|
|
433
500
|
// The sheet carries its own input, so the field behind it must not also
|
|
434
501
|
// pull up the keyboard and scroll the page under the dialog.
|
|
435
502
|
if (isPhone) sheetInputRef.current?.focus();
|
|
@@ -442,7 +509,10 @@ export function Combobox(props: ComboboxProps) {
|
|
|
442
509
|
onClick={() => {
|
|
443
510
|
if (locked) return;
|
|
444
511
|
setOpen(true);
|
|
512
|
+
// The whole pool again, so no row of the typed list is the keyboard's
|
|
513
|
+
// (0.52 code review, combobox.tsx — see `active`).
|
|
445
514
|
setTyping(false);
|
|
515
|
+
setActive(-1);
|
|
446
516
|
}}
|
|
447
517
|
// `inputMode="none"` rather than readOnly: the field must not look
|
|
448
518
|
// uneditable (FIELD_BASE greys a read-only field since dev#468) and must
|
|
@@ -458,29 +528,8 @@ export function Combobox(props: ComboboxProps) {
|
|
|
458
528
|
}}
|
|
459
529
|
onKeyDown={(e) => {
|
|
460
530
|
if (locked) return lockedKeyDown(e);
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
setOpen(true);
|
|
464
|
-
setActive((i) => Math.min(i + 1, matches.length - 1));
|
|
465
|
-
} else if (e.key === "ArrowUp") {
|
|
466
|
-
e.preventDefault();
|
|
467
|
-
setActive((i) => Math.max(i - 1, 0));
|
|
468
|
-
} else if (e.key === "Enter") {
|
|
469
|
-
// The Enter that confirms an IME composition is the IME's: it picks no
|
|
470
|
-
// row and submits nothing (BUG-9).
|
|
471
|
-
if (isImeEnter(e)) return;
|
|
472
|
-
if (open && active >= 0 && active < matches.length) {
|
|
473
|
-
e.preventDefault();
|
|
474
|
-
take(matches[active]);
|
|
475
|
-
} else {
|
|
476
|
-
// No row highlighted: the typed text is the answer. `preventDefault`
|
|
477
|
-
// only when a caller is taking Enter, so a plain form submit is
|
|
478
|
-
// otherwise left alone.
|
|
479
|
-
if (onSubmit) e.preventDefault();
|
|
480
|
-
setOpen(false);
|
|
481
|
-
onSubmit?.();
|
|
482
|
-
}
|
|
483
|
-
} else if (e.key === "Escape") {
|
|
531
|
+
listKeyDown(e);
|
|
532
|
+
if (e.key === "Escape") {
|
|
484
533
|
// A list that is SHOWING is the top of the Escape stack, and the key
|
|
485
534
|
// closes it and stops here: a Modal or FullBleedDialog around the field
|
|
486
535
|
// otherwise closed with it, form and all (round 0.34 BUG-1). With no
|
|
@@ -535,6 +584,8 @@ export function Combobox(props: ComboboxProps) {
|
|
|
535
584
|
)}
|
|
536
585
|
<FieldCaption parts={hintParts} />
|
|
537
586
|
{field.errorEl}
|
|
587
|
+
{/* The live status — see `useTypedListStatus` for where it goes and why. */}
|
|
588
|
+
{!isPhone && statusRegion}
|
|
538
589
|
{isPhone && (
|
|
539
590
|
<PickerSheet
|
|
540
591
|
open={open && !inert}
|
|
@@ -546,11 +597,17 @@ export function Combobox(props: ComboboxProps) {
|
|
|
546
597
|
query={value}
|
|
547
598
|
onQueryChange={(v) => {
|
|
548
599
|
onChange(v);
|
|
600
|
+
setActive(-1);
|
|
549
601
|
setTyping(true);
|
|
550
602
|
}}
|
|
551
603
|
searchPlaceholder={searchPlaceholder ?? placeholder}
|
|
552
604
|
inputRef={sheetInputRef}
|
|
553
605
|
closeLabel={closeLabel}
|
|
606
|
+
// The field's own keys, in the box focus is in while the sheet is up: arrows
|
|
607
|
+
// and Enter there did nothing (INP-6, as BUG-5 gave the panel pickers).
|
|
608
|
+
onSearchKeyDown={listKeyDown}
|
|
609
|
+
listboxId={listboxId}
|
|
610
|
+
activeId={activeOption}
|
|
554
611
|
>
|
|
555
612
|
<ul id={listboxId} role="listbox">
|
|
556
613
|
{createRow && (
|
|
@@ -569,37 +626,28 @@ export function Combobox(props: ComboboxProps) {
|
|
|
569
626
|
</button>
|
|
570
627
|
</li>
|
|
571
628
|
)}
|
|
572
|
-
{
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
{
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
</li>
|
|
629
|
+
{groupedRows(true, (o, i) => (
|
|
630
|
+
<li role="presentation">
|
|
631
|
+
<button
|
|
632
|
+
type="button"
|
|
633
|
+
id={optionId(i)}
|
|
634
|
+
role="option"
|
|
635
|
+
aria-selected={o === value}
|
|
636
|
+
onClick={() => take(o)}
|
|
637
|
+
className={cn(
|
|
638
|
+
SHEET_ROW_CLASS,
|
|
639
|
+
// The row the sheet's arrows are on.
|
|
640
|
+
i === active && "bg-active",
|
|
641
|
+
optionAdornment && "flex items-center justify-between gap-2",
|
|
586
642
|
)}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
className={cn(SHEET_ROW_CLASS, optionAdornment && "flex items-center justify-between gap-2")}
|
|
594
|
-
>
|
|
595
|
-
{optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
|
|
596
|
-
{optionAdornment?.(o)}
|
|
597
|
-
</button>
|
|
598
|
-
</li>
|
|
599
|
-
</Fragment>
|
|
600
|
-
);
|
|
601
|
-
})}
|
|
643
|
+
>
|
|
644
|
+
{optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
|
|
645
|
+
{optionAdornment?.(o)}
|
|
646
|
+
</button>
|
|
647
|
+
</li>
|
|
648
|
+
))}
|
|
602
649
|
</ul>
|
|
650
|
+
{statusRegion}
|
|
603
651
|
</PickerSheet>
|
|
604
652
|
)}
|
|
605
653
|
{showing && (
|
|
@@ -623,62 +671,44 @@ export function Combobox(props: ComboboxProps) {
|
|
|
623
671
|
</button>
|
|
624
672
|
</li>
|
|
625
673
|
)}
|
|
626
|
-
{
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
674
|
+
{groupedRows(false, (o, i, grouped) => (
|
|
675
|
+
<li role="presentation">
|
|
676
|
+
<button
|
|
677
|
+
type="button"
|
|
678
|
+
id={optionId(i)}
|
|
679
|
+
role="option"
|
|
680
|
+
// CHOSEN, not highlighted. The row the arrows are on is named by the
|
|
681
|
+
// field's `aria-activedescendant`; saying "selected" for it would tell a
|
|
682
|
+
// reader that the row they are passing over is already the answer.
|
|
683
|
+
aria-selected={o === value}
|
|
684
|
+
// Focus stays in the field — that is what `aria-activedescendant` is
|
|
685
|
+
// for — so the rows are not tab stops.
|
|
686
|
+
tabIndex={-1}
|
|
687
|
+
onMouseDown={(e) => {
|
|
688
|
+
// mousedown (not click) so the blur from the input firing first
|
|
689
|
+
// doesn't close the list before the selection registers.
|
|
690
|
+
e.preventDefault();
|
|
691
|
+
take(o);
|
|
692
|
+
}}
|
|
693
|
+
onMouseEnter={() => setActive(i)}
|
|
694
|
+
className={cn(
|
|
695
|
+
rowClass(i === active),
|
|
696
|
+
// Every row of a group indented under its heading — it was the first
|
|
697
|
+
// row of each group only.
|
|
698
|
+
grouped && "ps-6",
|
|
699
|
+
// A row with a badge is a flex row so the label truncates and the
|
|
700
|
+
// badge keeps its width; without one it stays the plain block the
|
|
701
|
+
// other lists render, so nothing shifts for callers that pass none.
|
|
702
|
+
// From Large up the label wraps instead (`truncate-until-large`,
|
|
703
|
+
// text size §10.17, round 0.34 T1), as the badge-less row does.
|
|
704
|
+
optionAdornment && "flex items-center justify-between gap-2",
|
|
643
705
|
)}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
// the field's `aria-activedescendant`; saying "selected" for it
|
|
651
|
-
// would tell a reader that the row they are passing over is
|
|
652
|
-
// already the answer.
|
|
653
|
-
aria-selected={o === value}
|
|
654
|
-
// Focus stays in the field — that is what
|
|
655
|
-
// `aria-activedescendant` is for — so the rows are not tab stops.
|
|
656
|
-
tabIndex={-1}
|
|
657
|
-
onMouseDown={(e) => {
|
|
658
|
-
// mousedown (not click) so the blur from the input firing first
|
|
659
|
-
// doesn't close the list before the selection registers.
|
|
660
|
-
e.preventDefault();
|
|
661
|
-
take(o);
|
|
662
|
-
}}
|
|
663
|
-
onMouseEnter={() => setActive(i)}
|
|
664
|
-
className={cn(
|
|
665
|
-
rowClass(i === active),
|
|
666
|
-
group != null && "ps-6",
|
|
667
|
-
// A row with a badge is a flex row so the label truncates and the
|
|
668
|
-
// badge keeps its width; without one it stays the plain block the
|
|
669
|
-
// other lists render, so nothing shifts for callers that pass none.
|
|
670
|
-
// From Large up the label wraps instead (`truncate-until-large`,
|
|
671
|
-
// text size §10.17, round 0.34 T1), as the badge-less row does.
|
|
672
|
-
optionAdornment && "flex items-center justify-between gap-2",
|
|
673
|
-
)}
|
|
674
|
-
>
|
|
675
|
-
{optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
|
|
676
|
-
{optionAdornment?.(o)}
|
|
677
|
-
</button>
|
|
678
|
-
</li>
|
|
679
|
-
</Fragment>
|
|
680
|
-
);
|
|
681
|
-
})}
|
|
706
|
+
>
|
|
707
|
+
{optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
|
|
708
|
+
{optionAdornment?.(o)}
|
|
709
|
+
</button>
|
|
710
|
+
</li>
|
|
711
|
+
))}
|
|
682
712
|
</SuggestionList>
|
|
683
713
|
)}
|
|
684
714
|
</div>
|
|
@@ -9,7 +9,6 @@ import { Button } from "./button";
|
|
|
9
9
|
import { IconButton } from "./icon-button";
|
|
10
10
|
import type { ButtonSize, ButtonTone, ButtonVariant } from "./button-look";
|
|
11
11
|
import type { IconButtonSize, IconButtonTone } from "./icon-button";
|
|
12
|
-
import { Tooltip } from "./tooltip";
|
|
13
12
|
import type { TooltipSide } from "./tooltip";
|
|
14
13
|
import { DEFAULT_COPY_BUTTON_LABELS } from "./copy-button-labels";
|
|
15
14
|
|
|
@@ -31,8 +30,9 @@ export interface CopyButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonEle
|
|
|
31
30
|
/** What to copy. A function is read at click time — for a value that is expensive
|
|
32
31
|
* to build (a CSV of the table) or that changes under the button. */
|
|
33
32
|
text: string | (() => string);
|
|
34
|
-
/** `icon` (default): a square icon button whose
|
|
35
|
-
*
|
|
33
|
+
/** `icon` (default): a square icon button whose glyph and colour show the result — its
|
|
34
|
+
* words in a bubble, and from Large up beside the glyph, as every labelled IconButton
|
|
35
|
+
* shows them. `label`: a text button whose words change to the result. */
|
|
36
36
|
variant?: "icon" | "label";
|
|
37
37
|
/** The idle accessible name — and, in the `label` variant, the visible text:
|
|
38
38
|
* "Copy IBAN" says WHAT is copied, which a row of three copy icons needs. Default
|
|
@@ -82,9 +82,9 @@ const ICONS: Record<CopyState, typeof Copy> = { idle: Copy, copied: Check, faile
|
|
|
82
82
|
* failure goes through an ASSERTIVE region and a success through a polite one — the
|
|
83
83
|
* failure is the news that changes what they do next.
|
|
84
84
|
*
|
|
85
|
-
* The icon variant keeps the SAME accessible name in every state
|
|
86
|
-
* itself under the focus is announced inconsistently across
|
|
87
|
-
* is the channel that is actually heard.
|
|
85
|
+
* The icon variant keeps the SAME accessible name in every state, and the same words on
|
|
86
|
+
* screen. A button renaming itself under the focus is announced inconsistently across
|
|
87
|
+
* readers; the live region is the channel that is actually heard.
|
|
88
88
|
*/
|
|
89
89
|
export function CopyButton({
|
|
90
90
|
text,
|
|
@@ -156,25 +156,36 @@ export function CopyButton({
|
|
|
156
156
|
);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
// IconButton names itself (0.52, refactor audit 2026-10-30, DSP-21): `label` is the
|
|
160
|
+
// bubble — and the text beside the glyph at Large, as on every labelled IconButton —
|
|
161
|
+
// and `aria-label` keeps the name steady. A Tooltip of our own round it cloned
|
|
162
|
+
// `aria-describedby` onto the button, which then read "Copy, button, Copy".
|
|
163
|
+
//
|
|
164
|
+
// The idle words, in every state (0.52 code review, deep, charts, finding 8). As the
|
|
165
|
+
// state, "Copied" stood at Large beside the glyph of a button named "Copy IBAN": the pill
|
|
166
|
+
// changed width on every copy, and the words on screen were not in the name a voice
|
|
167
|
+
// user says to press it (WCAG 2.5.3, label in name). The glyph and its colour show the
|
|
168
|
+
// result, and the live regions say it.
|
|
159
169
|
return (
|
|
160
170
|
<>
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
171
|
+
<IconButton
|
|
172
|
+
type="button"
|
|
173
|
+
{...rest}
|
|
174
|
+
disabled={disabled}
|
|
175
|
+
label={idleText}
|
|
176
|
+
aria-label={idleText}
|
|
177
|
+
tooltipSide={tooltipSide}
|
|
178
|
+
tooltipPortal={tooltipPortal}
|
|
179
|
+
variant={buttonVariant ?? "ghost"}
|
|
180
|
+
size={(size ?? "sm") as IconButtonSize}
|
|
181
|
+
tone={tone as IconButtonTone | undefined}
|
|
182
|
+
stopPropagation={stopPropagation}
|
|
183
|
+
data-state={state}
|
|
184
|
+
onClick={() => void onClick()}
|
|
185
|
+
className={cn(iconTone, className)}
|
|
186
|
+
>
|
|
187
|
+
<Icon aria-hidden />
|
|
188
|
+
</IconButton>
|
|
178
189
|
{regions}
|
|
179
190
|
</>
|
|
180
191
|
);
|
|
@@ -3,7 +3,7 @@ import type { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
|
|
|
3
3
|
import { X } from "lucide-react";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
5
|
import { COUNTRY_CODES, countryName, normalizeCountryCode } from "../lib/countries";
|
|
6
|
-
import {
|
|
6
|
+
import { searchRanked } from "../lib/text-match";
|
|
7
7
|
import { FieldChevron, FIELD_FLOATING_PAD, FIELD_INVALID, FIELD_TRIGGER, FloatingField } from "./field-base";
|
|
8
8
|
import {
|
|
9
9
|
assignRef,
|
|
@@ -178,17 +178,22 @@ interface Entry {
|
|
|
178
178
|
name: string;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
181
|
+
/** Every word of the query in the name, or the whole code (0.51.4's rule: "kinshasa
|
|
182
|
+
* congo" finds Congo - Kinshasa; refactor audit 2026-10-30, DUP-4), best rank first; a
|
|
183
|
+
* stable sort, so equal ranks keep the collated (or preferred) order they came in. The
|
|
184
|
+
* rank is the kit's one, for the WHOLE query (`rankMatch`, DUP-5 — written here first):
|
|
185
|
+
* the code itself (a two-letter query "ch" means Switzerland before it means Chad), then
|
|
186
|
+
* the start of the name, then anywhere in it, then the words apart (`searchRanked`, each
|
|
187
|
+
* name and code folded once), with accents and case folded — "osterreich" finds
|
|
188
|
+
* Österreich, "cote" Côte d'Ivoire.
|
|
189
|
+
*
|
|
190
|
+
* A word is the code or it is not: searched INSIDE the code, as one more text, "w"
|
|
191
|
+
* listed Aruba (AW) and Samoa (WS) and "d" Germany (DE), names with nothing of the
|
|
192
|
+
* query in them (0.52 code review, country-select.tsx). */
|
|
186
193
|
function search(entries: Entry[], q: string, locale: string): Entry[] {
|
|
187
|
-
return entries
|
|
188
|
-
.
|
|
189
|
-
.
|
|
190
|
-
.sort((a, b) => a.r - b.r)
|
|
191
|
-
.map((x) => x.e);
|
|
194
|
+
return searchRanked(entries, q, (e) => [e.name], { code: (e) => e.code, locale })
|
|
195
|
+
.sort((a, b) => a.rank - b.rank)
|
|
196
|
+
.map((x) => x.row);
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
function toOption(e: Entry, flags: boolean, group?: string): ComboOption<string> {
|