@eifi1/ui-kit 0.51.7 → 0.53.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 +178 -67
- 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 +10 -7
- package/dist/billing/cancel-subscription.js +6 -6
- package/dist/billing/cancel-subscription.js.map +1 -1
- package/dist/billing/plan-card.d.ts +5 -3
- package/dist/billing/plan-card.js +7 -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 +9 -6
- package/dist/billing/plan-switch.js +7 -5
- package/dist/billing/plan-switch.js.map +1 -1
- package/dist/chart.d.ts +4 -3
- package/dist/chart.js +72 -4
- 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 +25 -3
- package/dist/components/date-field.js +33 -8
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.d.ts +16 -3
- 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 +38 -24
- 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/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/nav-pills.d.ts +1 -1
- package/dist/components/nav-pills.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/series-chart-axes.d.ts +4 -4
- 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 +92 -23
- package/dist/components/series-chart.js +74 -30
- 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/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 +31 -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 +167 -19
- package/dist/components/treemap.js +340 -100
- 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 +1 -2
- package/dist/data-table.js +1 -4
- package/dist/data-table.js.map +1 -1
- package/dist/demo/demo-countdown.d.ts +0 -5
- package/dist/demo/demo-countdown.js +0 -4
- package/dist/demo/demo-countdown.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 +18 -0
- package/dist/feedback/feedback-mutation.js +8 -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 +8 -4
- package/dist/feedback/feedback-public-list.js +2 -2
- 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 +0 -3
- package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
- package/dist/feedback/feedback-row-detail.d.ts +33 -44
- package/dist/feedback/feedback-row-detail.js +28 -34
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-status-undo.d.ts +17 -14
- 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 +15 -23
- package/dist/feedback/feedback-thread.js +2 -1
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +6 -6
- package/dist/feedback.js +90 -6
- 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 -9
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +7 -18
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +9 -11
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +15 -64
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +7 -18
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +20 -27
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +9 -18
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +7 -19
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +8 -18
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +12 -2
- package/dist/i18n/review.js.map +1 -1
- package/dist/i18n/shared-labels.js +0 -1
- package/dist/i18n/shared-labels.js.map +1 -1
- package/dist/index.d.ts +21 -23
- package/dist/index.js +50 -65
- 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/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/search-index.d.ts +0 -6
- package/dist/search/search-index.js +0 -4
- package/dist/search/search-index.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 +1 -1
- package/dist/search.js +6 -1
- 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 +5 -3
- package/dist/shell/account-menu-language.js +2 -2
- package/dist/shell/account-menu-language.js.map +1 -1
- package/dist/shell/account-menu-text-size.d.ts +9 -6
- package/dist/shell/account-menu-text-size.js +2 -2
- package/dist/shell/account-menu-text-size.js.map +1 -1
- package/dist/shell/app-shell.d.ts +0 -10
- package/dist/shell/app-shell.js +1 -7
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/company-switcher.d.ts +1 -1
- package/dist/shell/company-switcher.js.map +1 -1
- package/dist/shell/dev-menu.d.ts +1 -1
- package/dist/shell/dev-menu.js +5 -18
- package/dist/shell/dev-menu.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 +1 -3
- 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 +7 -10
- package/dist/shell.js +14 -23
- 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 +2 -2
- package/dist/sync.js +2 -10
- 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/chart-palette.d.ts +0 -5
- package/dist/theme/chart-palette.js +0 -2
- package/dist/theme/chart-palette.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 +15 -12
- package/src/billing/plan-card.tsx +18 -10
- package/src/billing/plan-change-labels.ts +66 -0
- package/src/billing/plan-switch.tsx +15 -12
- package/src/chart.ts +73 -6
- 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 +66 -9
- package/src/components/date-picker.tsx +125 -49
- package/src/components/date-range-picker.tsx +71 -36
- 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/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/nav-pills.tsx +1 -1
- 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/series-chart-axes.ts +9 -4
- package/src/components/series-chart-labels.ts +7 -4
- package/src/components/series-chart.tsx +253 -87
- package/src/components/share-card.tsx +6 -6
- 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 +47 -0
- package/src/components/treemap-layout.ts +210 -0
- package/src/components/treemap.tsx +780 -138
- package/src/components/use-table-state.ts +12 -9
- package/src/data-table.ts +1 -4
- package/src/demo/demo-countdown.ts +3 -8
- package/src/eslint/role-utilities.ts +97 -19
- package/src/feedback/feedback-dialog.tsx +30 -19
- package/src/feedback/feedback-mutation.ts +20 -0
- package/src/feedback/feedback-page-link.ts +90 -0
- package/src/feedback/feedback-public-list.tsx +13 -7
- package/src/feedback/feedback-replies.tsx +13 -6
- package/src/feedback/feedback-row-detail-labels.ts +0 -3
- package/src/feedback/feedback-row-detail.tsx +70 -84
- package/src/feedback/feedback-status-undo.ts +28 -28
- 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 +18 -26
- package/src/feedback.ts +89 -6
- 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 -9
- package/src/i18n/german.ts +8 -19
- package/src/i18n/kit-labels.tsx +9 -11
- package/src/i18n/locales/es.ts +8 -19
- package/src/i18n/locales/fr.ts +21 -30
- package/src/i18n/locales/hu.ts +10 -19
- package/src/i18n/locales/it.ts +8 -20
- package/src/i18n/locales/zh.ts +9 -19
- package/src/i18n/review.ts +12 -2
- package/src/i18n/shared-labels.ts +0 -1
- package/src/index.ts +57 -49
- 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/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/search-index.ts +0 -15
- package/src/search/use-command-key.ts +13 -12
- package/src/search.ts +10 -1
- package/src/settings/use-settings-focus.ts +3 -0
- package/src/shell/account-menu-language.tsx +6 -4
- package/src/shell/account-menu-text-size.tsx +10 -7
- package/src/shell/app-shell.tsx +0 -13
- package/src/shell/company-switcher.tsx +1 -1
- package/src/shell/dev-menu.tsx +8 -22
- package/src/shell/top-bar-actions.tsx +1 -1
- package/src/shell/top-bar-parts-labels.ts +1 -4
- package/src/shell.ts +21 -17
- package/src/sync/engine.ts +339 -61
- package/src/sync.ts +2 -8
- package/src/testing/css-variables.ts +8 -9
- package/src/theme/chart-palette.ts +0 -2
- 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 +6 -5
- package/dist/components/field-sync-labels.d.ts +0 -2
- package/dist/components/field-sync-labels.js +0 -12
- package/dist/components/field-sync-labels.js.map +0 -1
- package/dist/components/field-sync.d.ts +0 -164
- package/dist/components/field-sync.js +0 -269
- package/dist/components/field-sync.js.map +0 -1
- package/dist/components/section-nav.d.ts +0 -37
- package/dist/components/section-nav.js +0 -33
- package/dist/components/section-nav.js.map +0 -1
- package/dist/components/sign-chip-labels.d.ts +0 -2
- package/dist/components/sign-chip-labels.js +0 -11
- package/dist/components/sign-chip-labels.js.map +0 -1
- package/dist/components/sign-chip.d.ts +0 -68
- package/dist/components/sign-chip.js +0 -47
- package/dist/components/sign-chip.js.map +0 -1
- package/dist/components/ui-labels.js.map +0 -1
- package/dist/lib/isin.d.ts +0 -28
- package/dist/lib/isin.js +0 -36
- package/dist/lib/isin.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/dist/shell/role-switcher.d.ts +0 -21
- package/dist/shell/role-switcher.js +0 -31
- package/dist/shell/role-switcher.js.map +0 -1
- package/src/components/field-sync-labels.ts +0 -13
- package/src/components/field-sync.tsx +0 -482
- package/src/components/section-nav.tsx +0 -65
- package/src/components/sign-chip-labels.ts +0 -12
- package/src/components/sign-chip.tsx +0 -124
- package/src/components/ui-labels.ts +0 -24
- package/src/lib/isin.ts +0 -62
- package/src/shell/dev-switchers.tsx +0 -18
- package/src/shell/role-switcher.tsx +0 -46
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { useId, useLayoutEffect, useRef, useState } from "react";
|
|
2
|
-
import type { ComponentPropsWithoutRef, MouseEvent, ReactNode, Ref } from "react";
|
|
1
|
+
import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
2
|
+
import type { ComponentPropsWithoutRef, MouseEvent, ReactNode, Ref, RefObject } from "react";
|
|
3
3
|
import { AlertTriangle, CheckCircle2, ChevronRight, Info, X } from "lucide-react";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
5
|
import { FOCUS_RING } from "./focus-ring";
|
|
6
6
|
import { DEFAULT_COMMON_LABELS, useKitLabels } from "../i18n/kit-labels";
|
|
7
|
+
import { focusFirst, focusIsLost, tabStopsAround, whenFocusLeftForNothing } from "../lib/focus-left";
|
|
7
8
|
|
|
8
9
|
/** `info` (0.8.0) is the sky family, for news that is neither good nor bad: keksdose's
|
|
9
10
|
* preview and beta-performance banners, which borrowed `warning` for want of it and
|
|
@@ -185,10 +186,21 @@ interface AlertBannerBaseProps extends Omit<ComponentPropsWithoutRef<"div">, "on
|
|
|
185
186
|
/** Replaces the tone's glyph — a `<Spinner label={null} />` for "Solving…", say.
|
|
186
187
|
* `null` draws none. Always decorative; the text carries the message. */
|
|
187
188
|
icon?: ReactNode;
|
|
188
|
-
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
189
|
+
/**
|
|
190
|
+
* Renders an × at the end that calls this. The banner does not hide itself — the
|
|
191
|
+
* caller removes it (and remembers that it did), as with every other kit control
|
|
192
|
+
* whose state is app state.
|
|
193
|
+
*
|
|
194
|
+
* The focus (0.52, refactor audit 2026-10-30, DSP-15): the × that held it goes with the
|
|
195
|
+
* banner, and it fell to `<body>`. When the banner unmounts after its × was pressed and
|
|
196
|
+
* the focus has nowhere else, it moves on to the next control after the banner — where
|
|
197
|
+
* Tab from the × would have gone — or, at the end of the page, the one before it; to
|
|
198
|
+
* {@link dismissFocusRef} when given. A banner the caller keeps keeps its ×'s focus.
|
|
199
|
+
*/
|
|
191
200
|
onDismiss?: () => void;
|
|
201
|
+
/** Where the focus goes once the × has removed the banner (DSP-15) — a heading, the
|
|
202
|
+
* control the banner was about. Default: the next control after the banner. */
|
|
203
|
+
dismissFocusRef?: RefObject<HTMLElement | null>;
|
|
192
204
|
/** Accessible name of the ×. Default: `common.dismiss` from the
|
|
193
205
|
* {@link UiKitProvider}, else "Dismiss". */
|
|
194
206
|
dismissLabel?: string;
|
|
@@ -278,6 +290,7 @@ export function AlertBanner({
|
|
|
278
290
|
action,
|
|
279
291
|
icon,
|
|
280
292
|
onDismiss,
|
|
293
|
+
dismissFocusRef,
|
|
281
294
|
dismissLabel,
|
|
282
295
|
clampMobile = false,
|
|
283
296
|
actionPlacement = "own-line",
|
|
@@ -318,6 +331,36 @@ export function AlertBanner({
|
|
|
318
331
|
return () => ro?.disconnect();
|
|
319
332
|
}, [clamp, expanded, children]);
|
|
320
333
|
|
|
334
|
+
// The ×'s focus, once the caller has removed the banner (DSP-15). Where it can go is read
|
|
335
|
+
// at the press, while the banner still has a place in the page to measure from; whether
|
|
336
|
+
// it must is decided at the unmount, in the cleanup of a passive effect — after React has
|
|
337
|
+
// taken the banner's DOM away, when a focus that fell with it is on <body>.
|
|
338
|
+
const dismissedFrom = useRef<HTMLElement[] | null>(null);
|
|
339
|
+
const dismissTarget = useRef(dismissFocusRef);
|
|
340
|
+
useLayoutEffect(() => {
|
|
341
|
+
dismissTarget.current = dismissFocusRef;
|
|
342
|
+
});
|
|
343
|
+
// The note lives until the focus lands outside the banner (0.52 code review,
|
|
344
|
+
// alert-banner.tsx). A caller that keeps the banner — an async dismiss that failed, a
|
|
345
|
+
// snooze — left it standing, and the banner's unmount long after, a route change with
|
|
346
|
+
// the focus on <body>, sent the focus to a stop noted at the press, over the app's own
|
|
347
|
+
// handling of a new page. A `focusin` on the document, not a `focusout` on the banner:
|
|
348
|
+
// a browser that blurs a removed node would drop the note at the very removal it is for.
|
|
349
|
+
// The one `focusout` heard is a move to nothing — a click on the page — and only once a
|
|
350
|
+
// microtask has shown the × still in place (`whenFocusLeftForNothing`). A focus that
|
|
351
|
+
// stays on the × keeps the note, however late the removal: that is DSP-15's own case,
|
|
352
|
+
// an async dismiss whose request resolves.
|
|
353
|
+
const unwatchFocus = useRef<(() => void) | null>(null);
|
|
354
|
+
useEffect(
|
|
355
|
+
() => () => {
|
|
356
|
+
unwatchFocus.current?.();
|
|
357
|
+
const around = dismissedFrom.current;
|
|
358
|
+
if (!around || !focusIsLost()) return;
|
|
359
|
+
focusFirst([dismissTarget.current?.current, ...around]);
|
|
360
|
+
},
|
|
361
|
+
[],
|
|
362
|
+
);
|
|
363
|
+
|
|
321
364
|
const Glyph = TONE_GLYPH[tone];
|
|
322
365
|
// Onto the first line of a box's text: 2px at 14px/20px, 1px at 12px/16px.
|
|
323
366
|
const nudge = inlineRow || strip ? undefined : sm ? "mt-px" : "mt-0.5";
|
|
@@ -448,6 +491,40 @@ export function AlertBanner({
|
|
|
448
491
|
// A dismiss inside a whole-row banner must not also follow the row.
|
|
449
492
|
e.preventDefault();
|
|
450
493
|
e.stopPropagation();
|
|
494
|
+
const frame = e.currentTarget.parentElement;
|
|
495
|
+
// Only a × that holds the focus has one to lose (0.52 code review, alert-banner.tsx):
|
|
496
|
+
// Safari focuses no button on a click, nor on an iOS tap, and with the focus on
|
|
497
|
+
// <body> already the removal sent it on — a ring, on a form field the on-screen
|
|
498
|
+
// keyboard, on a page the user was reading with the pointer.
|
|
499
|
+
if (frame && e.currentTarget.ownerDocument.activeElement === e.currentTarget) {
|
|
500
|
+
const { after, before } = tabStopsAround(frame);
|
|
501
|
+
dismissedFrom.current = [...after, ...before];
|
|
502
|
+
unwatchFocus.current?.();
|
|
503
|
+
const doc = frame.ownerDocument;
|
|
504
|
+
const forget = () => {
|
|
505
|
+
dismissedFrom.current = null;
|
|
506
|
+
unwatch();
|
|
507
|
+
};
|
|
508
|
+
const onFocusIn = (event: FocusEvent) => {
|
|
509
|
+
if (event.target instanceof Node && frame.contains(event.target)) return;
|
|
510
|
+
forget();
|
|
511
|
+
};
|
|
512
|
+
// Focus that left for nothing — a click on the page — took no `focusin` with it
|
|
513
|
+
// (0.52 code review): the user moved on all the same.
|
|
514
|
+
const onFocusOut = (event: FocusEvent) => {
|
|
515
|
+
whenFocusLeftForNothing(event, () => {
|
|
516
|
+
if (unwatchFocus.current === unwatch) forget();
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
const unwatch = () => {
|
|
520
|
+
doc.removeEventListener("focusin", onFocusIn, true);
|
|
521
|
+
frame.removeEventListener("focusout", onFocusOut);
|
|
522
|
+
unwatchFocus.current = null;
|
|
523
|
+
};
|
|
524
|
+
doc.addEventListener("focusin", onFocusIn, true);
|
|
525
|
+
frame.addEventListener("focusout", onFocusOut);
|
|
526
|
+
unwatchFocus.current = unwatch;
|
|
527
|
+
}
|
|
451
528
|
onDismiss();
|
|
452
529
|
}}
|
|
453
530
|
className={cn(
|
|
@@ -338,17 +338,28 @@ function settleAmount(text: string, digits: number | undefined, min?: number, ma
|
|
|
338
338
|
// `lib/decimal-marks.ts`, read through the engine NumberInput and this field share
|
|
339
339
|
// (`numeric-field.ts`, DUP-10).
|
|
340
340
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
341
|
+
/**
|
|
342
|
+
* The figure's colour per {@link AmountInputProps.tone} — public as `AMOUNT_TONE_CLASS`,
|
|
343
|
+
* for a table cell or a test that must paint the same figure the same way (keksdose's
|
|
344
|
+
* receipt lines, dev#556).
|
|
345
|
+
*
|
|
346
|
+
* The consuming app's ONE money palette (`--money-expense` / `--money-income`), not a
|
|
347
|
+
* bespoke rose/emerald pairing: a figure being typed has to wear the same colour the same
|
|
348
|
+
* figure will wear once it is a row in the table behind the form (Keksdose dev#434). The
|
|
349
|
+
* utilities are unlayered and theme-aware, so no `dark:` variant is needed and they win
|
|
350
|
+
* over the field's own text colour regardless of where `cn` puts them.
|
|
351
|
+
*/
|
|
352
|
+
const TONE_CLASS: Readonly<Record<NonNullable<AmountInputProps["tone"]>, string>> = {
|
|
348
353
|
neutral: "",
|
|
349
354
|
outflow: "text-money-neg",
|
|
350
355
|
inflow: "text-money-pos",
|
|
351
356
|
};
|
|
357
|
+
// Exported in 0.52 because keksdose's tests read it out of dist/components/amount-input.js
|
|
358
|
+
// with a regex for `const TONE_CLASS` — the one reach into the kit's dist in three apps,
|
|
359
|
+
// which a rename or a moved module breaks with no public change (MOD-8, refactor audit
|
|
360
|
+
// 2026-10-30; 0.34's move failed 91 of keksdose's test files that way). The local name
|
|
361
|
+
// stays until keksdose imports the export, so the bump itself breaks nothing.
|
|
362
|
+
export { TONE_CLASS as AMOUNT_TONE_CLASS };
|
|
352
363
|
|
|
353
364
|
// The shared chrome-less treatment at money size. `tabular-nums` so digits don't
|
|
354
365
|
// reflow the figure as they are typed; FIELD_DISPLAY's own muted placeholder
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useId, useRef, useState } from "react";
|
|
2
2
|
import type { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
|
+
import { hasContent } from "../lib/presence";
|
|
5
6
|
import { FIELD_BASE, FIELD_FLOATING_PAD, FIELD_INVALID } from "./field-base";
|
|
6
7
|
import { Spinner } from "./spinner";
|
|
7
8
|
import { useAnchoredPanel } from "../hooks/use-anchored-panel";
|
|
@@ -10,10 +11,12 @@ import { isImeEnter } from "../lib/ime";
|
|
|
10
11
|
import { isQuietFocus } from "../lib/quiet-focus";
|
|
11
12
|
import { useAnchorDir } from "./use-anchor-dir";
|
|
12
13
|
import {
|
|
14
|
+
anchoredHeadingClass,
|
|
13
15
|
ComboboxFieldLabel,
|
|
14
16
|
DISABLED_ROW_CLASS,
|
|
15
17
|
endHintRowProps,
|
|
16
|
-
|
|
18
|
+
GroupedOptions,
|
|
19
|
+
groupRuns,
|
|
17
20
|
isOptionEnabled,
|
|
18
21
|
stepEnabled,
|
|
19
22
|
SUGGESTION_LIST_CLASS,
|
|
@@ -293,7 +296,7 @@ export function Autocomplete<V extends string | number = string>(props: Autocomp
|
|
|
293
296
|
active: live,
|
|
294
297
|
});
|
|
295
298
|
|
|
296
|
-
const hasStatus = status
|
|
299
|
+
const hasStatus = hasContent(status);
|
|
297
300
|
// The visible line under the rows. Nothing below `minChars` unless the caller has
|
|
298
301
|
// something to say — an empty field opening a box that says "type more" is noise.
|
|
299
302
|
const statusLine: ReactNode = hasStatus
|
|
@@ -559,75 +562,66 @@ export function Autocomplete<V extends string | number = string>(props: Autocomp
|
|
|
559
562
|
aria-labelledby={labelledBy}
|
|
560
563
|
className="min-h-0 flex-1 overflow-y-auto py-1"
|
|
561
564
|
>
|
|
562
|
-
{
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
//
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
565
|
+
{/* One heading per group, a `role="group"` it names, as in the core panel
|
|
566
|
+
(refactor audit 2026-10-30, INP-8), drawn by the same renderer: an
|
|
567
|
+
option may appear once per group. */}
|
|
568
|
+
<GroupedOptions
|
|
569
|
+
runs={groupRuns(results, (o) => o.group)}
|
|
570
|
+
listboxId={listboxId}
|
|
571
|
+
rowKey={(o) => String(o.value)}
|
|
572
|
+
headingClassName={(run) => anchoredHeadingClass(run)}
|
|
573
|
+
row={(o, i) => (
|
|
574
|
+
<li role="presentation">
|
|
575
|
+
<button
|
|
576
|
+
type="button"
|
|
577
|
+
id={optionId(i)}
|
|
578
|
+
role="option"
|
|
579
|
+
// CHOSEN, never "highlighted" — the family's rule. This
|
|
580
|
+
// field holds no value, so the only row that can be chosen
|
|
581
|
+
// is the one whose label the text already is.
|
|
582
|
+
aria-selected={fillOnSelect && o.label === value}
|
|
583
|
+
// Listed, announced as unavailable, never taken: `take`
|
|
584
|
+
// refuses it and the arrows pass it over.
|
|
585
|
+
aria-disabled={o.disabled || undefined}
|
|
586
|
+
tabIndex={-1}
|
|
587
|
+
onClick={() => take(o)}
|
|
588
|
+
onMouseEnter={() => {
|
|
589
|
+
if (!o.disabled) setActive(i);
|
|
590
|
+
}}
|
|
591
|
+
className={cn(
|
|
592
|
+
// The family's suggestion row (DUP-4): it hand-rolled its
|
|
593
|
+
// own with a plain `truncate`, so a long address was cut at
|
|
594
|
+
// Large, where Combobox's rows wrap (text size §10.17, T1).
|
|
595
|
+
// A flex row here, for the icon and the two lines.
|
|
596
|
+
suggestionRowClass(i === active && !o.disabled),
|
|
597
|
+
"flex items-center gap-2",
|
|
598
|
+
small && "py-1 text-xs",
|
|
599
|
+
o.disabled && DISABLED_ROW_CLASS,
|
|
600
|
+
o.group && "ps-6",
|
|
601
|
+
)}
|
|
602
|
+
>
|
|
603
|
+
{o.icon && (
|
|
604
|
+
<span aria-hidden className="shrink-0 text-muted">
|
|
605
|
+
{o.icon}
|
|
606
|
+
</span>
|
|
607
|
+
)}
|
|
608
|
+
<span className="min-w-0 flex-1">
|
|
609
|
+
<span className="block truncate-until-large text-primary">{o.label}</span>
|
|
610
|
+
{o.sublabel && (
|
|
611
|
+
<span
|
|
612
|
+
className={cn(
|
|
613
|
+
"block truncate-until-large text-placeholder",
|
|
614
|
+
small ? "text-caption" : "text-xs",
|
|
615
|
+
)}
|
|
616
|
+
>
|
|
617
|
+
{o.sublabel}
|
|
611
618
|
</span>
|
|
612
619
|
)}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
"block truncate-until-large text-placeholder",
|
|
619
|
-
small ? "text-caption" : "text-xs",
|
|
620
|
-
)}
|
|
621
|
-
>
|
|
622
|
-
{o.sublabel}
|
|
623
|
-
</span>
|
|
624
|
-
)}
|
|
625
|
-
</span>
|
|
626
|
-
</button>
|
|
627
|
-
</li>
|
|
628
|
-
</Fragment>
|
|
629
|
-
);
|
|
630
|
-
})}
|
|
620
|
+
</span>
|
|
621
|
+
</button>
|
|
622
|
+
</li>
|
|
623
|
+
)}
|
|
624
|
+
/>
|
|
631
625
|
</ul>
|
|
632
626
|
)}
|
|
633
627
|
{statusLine !== null && (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
2
|
-
import type { ComponentPropsWithRef, CSSProperties, KeyboardEvent, ReactNode } from "react";
|
|
2
|
+
import type { ComponentPropsWithRef, CSSProperties, FocusEvent, KeyboardEvent, ReactNode, RefObject } from "react";
|
|
3
3
|
import { X } from "lucide-react";
|
|
4
4
|
|
|
5
5
|
import { cn } from "../lib/cn";
|
|
@@ -8,6 +8,8 @@ import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
|
8
8
|
import { useAnnounce } from "../hooks/use-announce";
|
|
9
9
|
import { useBreakpoint } from "../hooks/use-breakpoint";
|
|
10
10
|
import { OVERLAY_EXIT_MS, skipsExitAnimation } from "../hooks/use-close-transition";
|
|
11
|
+
import { focusFirst, focusIsLost, whenFocusLeftForNothing } from "../lib/focus-left";
|
|
12
|
+
import { hasContent } from "../lib/presence";
|
|
11
13
|
import { Button } from "./button";
|
|
12
14
|
import { IconButton } from "./icon-button";
|
|
13
15
|
import { DEFAULT_BULK_ACTION_BAR_LABELS } from "./bulk-action-bar-labels";
|
|
@@ -124,6 +126,16 @@ export interface BulkActionBarProps extends Omit<ComponentPropsWithRef<"div">, "
|
|
|
124
126
|
panel?: ReactNode;
|
|
125
127
|
/** Default: `bulkActionBar` from the {@link UiKitProvider}, else English. */
|
|
126
128
|
labels?: LabelOverride<BulkActionBarLabels>;
|
|
129
|
+
/**
|
|
130
|
+
* Where the focus goes when the bar leaves while it holds it — after Clear, or an action
|
|
131
|
+
* that empties the selection (0.52, refactor audit 2026-10-30, DSP-15). Without it, the
|
|
132
|
+
* control the focus came into the bar from (the row's box, say), if that is still on the
|
|
133
|
+
* page; with it, this first. Pass one where the selection takes that control with it — a
|
|
134
|
+
* bulk delete removes the rows whose boxes were ticked: the table, the list's heading,
|
|
135
|
+
* the "Select" button that entered selection mode. A bar that leaves without the focus
|
|
136
|
+
* in it moves nothing.
|
|
137
|
+
*/
|
|
138
|
+
returnFocusRef?: RefObject<HTMLElement | null>;
|
|
127
139
|
}
|
|
128
140
|
|
|
129
141
|
/** Where the floating bar sits: clear of the phone nav and of the home indicator,
|
|
@@ -192,10 +204,12 @@ export function BulkActionBar({
|
|
|
192
204
|
open,
|
|
193
205
|
panel,
|
|
194
206
|
labels: labelsProp,
|
|
207
|
+
returnFocusRef,
|
|
195
208
|
className,
|
|
196
209
|
style,
|
|
197
210
|
onKeyDown,
|
|
198
211
|
onFocus,
|
|
212
|
+
onBlur,
|
|
199
213
|
...rest
|
|
200
214
|
}: BulkActionBarProps) {
|
|
201
215
|
const labels = useKitLabels("bulkActionBar", DEFAULT_BULK_ACTION_BAR_LABELS, labelsProp);
|
|
@@ -245,6 +259,51 @@ export function BulkActionBar({
|
|
|
245
259
|
rove(barRef.current, active);
|
|
246
260
|
});
|
|
247
261
|
|
|
262
|
+
// Leaving with the focus in it (refactor audit 2026-10-30, DSP-15): the bar goes `inert`,
|
|
263
|
+
// which blurs the control it holds, then unmounts — and the focus fell to <body>; on a
|
|
264
|
+
// phone VoiceOver's cursor jumped to the top of the page (keksdose's register). Noted on
|
|
265
|
+
// the bar's outermost element, so the `panel`'s fields count: where the focus came in
|
|
266
|
+
// from (the first entry since the bar showed, replaced once that control is gone), and
|
|
267
|
+
// whether it is in the bar. Focus that leaves for nothing because the page took it —
|
|
268
|
+
// inert, a removal — still counts as in it; a real element elsewhere takes it out, and
|
|
269
|
+
// so does a click on the page that left it nowhere (0.52 code review,
|
|
270
|
+
// bulk-action-bar.tsx: the note outlived it, and the bar's hide long after — the last row
|
|
271
|
+
// unticked with the pointer — pulled the focus and the scroll back to the row's box).
|
|
272
|
+
const cameFrom = useRef<HTMLElement | null>(null);
|
|
273
|
+
const holdsFocus = useRef(false);
|
|
274
|
+
const trackFocus = {
|
|
275
|
+
onFocus: (e: FocusEvent<HTMLDivElement>) => {
|
|
276
|
+
holdsFocus.current = true;
|
|
277
|
+
const from = e.relatedTarget;
|
|
278
|
+
if (from instanceof HTMLElement && !e.currentTarget.contains(from) && !cameFrom.current?.isConnected)
|
|
279
|
+
cameFrom.current = from;
|
|
280
|
+
},
|
|
281
|
+
onBlur: (e: FocusEvent<HTMLDivElement>) => {
|
|
282
|
+
onBlur?.(e);
|
|
283
|
+
const to = e.relatedTarget;
|
|
284
|
+
if (to instanceof Element && !e.currentTarget.contains(to)) holdsFocus.current = false;
|
|
285
|
+
whenFocusLeftForNothing(e, () => {
|
|
286
|
+
holdsFocus.current = false;
|
|
287
|
+
});
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
// The commit that hides the bar: the focus goes back while the control holding it is
|
|
291
|
+
// still in place — before `inert` takes it, or, with no exit to play, before <body> does.
|
|
292
|
+
const wasShown = useRef(shown);
|
|
293
|
+
useLayoutEffect(() => {
|
|
294
|
+
if (wasShown.current === shown) return;
|
|
295
|
+
wasShown.current = shown;
|
|
296
|
+
const from = cameFrom.current;
|
|
297
|
+
const held = holdsFocus.current;
|
|
298
|
+
cameFrom.current = null;
|
|
299
|
+
holdsFocus.current = false;
|
|
300
|
+
if (shown) return;
|
|
301
|
+
// The outermost element: the toolbar, or with a `panel` the surface round both.
|
|
302
|
+
const surface = barRef.current?.closest("[data-bulk-action-bar]");
|
|
303
|
+
const inBar = !!surface && surface.contains(document.activeElement);
|
|
304
|
+
if (inBar || (held && focusIsLost())) focusFirst([returnFocusRef?.current, from]);
|
|
305
|
+
}, [shown, returnFocusRef]);
|
|
306
|
+
|
|
248
307
|
const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
|
|
249
308
|
onKeyDown?.(e);
|
|
250
309
|
if (e.defaultPrevented || ownsArrows(e.target as Element)) return;
|
|
@@ -279,7 +338,9 @@ export function BulkActionBar({
|
|
|
279
338
|
</Button>
|
|
280
339
|
);
|
|
281
340
|
|
|
282
|
-
|
|
341
|
+
// `hasContent` (refactor audit 2026-10-30, DUP-14): an empty-string panel drew an empty
|
|
342
|
+
// bordered strip under the bar.
|
|
343
|
+
const hasPanel = hasContent(panel);
|
|
283
344
|
// The surface — where the bar sits and what it looks like — and the toolbar row's
|
|
284
345
|
// own layout. Without a panel they are one element, exactly as before 0.11.0; with
|
|
285
346
|
// one the surface wraps the row and the panel, so both share its tint and position.
|
|
@@ -314,6 +375,7 @@ export function BulkActionBar({
|
|
|
314
375
|
onKeyDown={handleKeyDown}
|
|
315
376
|
onFocus={(e) => {
|
|
316
377
|
onFocus?.(e);
|
|
378
|
+
if (!hasPanel) trackFocus.onFocus(e);
|
|
317
379
|
// Clicking a control is using it: the stop follows the pointer too.
|
|
318
380
|
const hit = itemsOf(barRef.current).find((el) => el === e.target);
|
|
319
381
|
if (hit) {
|
|
@@ -321,6 +383,7 @@ export function BulkActionBar({
|
|
|
321
383
|
rove(barRef.current, active);
|
|
322
384
|
}
|
|
323
385
|
}}
|
|
386
|
+
onBlur={hasPanel ? undefined : trackFocus.onBlur}
|
|
324
387
|
style={hasPanel ? undefined : surfaceStyle}
|
|
325
388
|
className={hasPanel ? rowClass : cn(rowClass, surfaceClass, className)}
|
|
326
389
|
>
|
|
@@ -340,8 +403,13 @@ export function BulkActionBar({
|
|
|
340
403
|
<>
|
|
341
404
|
<span {...regionProps} />
|
|
342
405
|
{hasPanel ? (
|
|
406
|
+
/* eslint-disable-next-line jsx-a11y/no-static-element-interactions -- the focus is
|
|
407
|
+
only noted here (DSP-15): where it came from, whether it is in the bar; the
|
|
408
|
+
controls are the toolbar's and the panel's own. */
|
|
343
409
|
<div
|
|
344
410
|
{...rest}
|
|
411
|
+
onFocus={trackFocus.onFocus}
|
|
412
|
+
onBlur={trackFocus.onBlur}
|
|
345
413
|
data-bulk-action-bar={variant}
|
|
346
414
|
inert={!shown || undefined}
|
|
347
415
|
style={surfaceStyle}
|
|
@@ -9,8 +9,8 @@ import type { KitLinkComponent, KitLinkProps } from "../i18n/kit-labels";
|
|
|
9
9
|
* and its router link. Both now draw from this module, which renders nothing, so neither
|
|
10
10
|
* imports the other.
|
|
11
11
|
*
|
|
12
|
-
* Public through
|
|
13
|
-
* The other exports are the two buttons' shared parts (`@internal`).
|
|
12
|
+
* Public through the barrel (src/index.ts) by name: `buttonClasses`, `TOUCH_TARGET_LARGE`
|
|
13
|
+
* and the four types. The other exports are the two buttons' shared parts (`@internal`).
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -24,9 +24,9 @@ import type { KitLinkComponent, KitLinkProps } from "../i18n/kit-labels";
|
|
|
24
24
|
* (theme/palette-derive.ts), which no button paints.
|
|
25
25
|
* - `secondary`: an outline. `ghost`: text or glyph only. `danger`: solid `--danger`,
|
|
26
26
|
* for an action that destroys something. `link`: a text link that acts (a `<button>`).
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
*
|
|
28
|
+
* 0.49's `primary` and `brand` (aliases of `default` and `accent`) were removed in 0.51;
|
|
29
|
+
* `primary` will not come back with another meaning.
|
|
30
30
|
*/
|
|
31
31
|
export type ButtonVariant = "default" | "accent" | "secondary" | "ghost" | "danger" | "link";
|
|
32
32
|
|
|
@@ -25,8 +25,8 @@ import type { ButtonSize, ButtonTone, ButtonVariant } from "./button-look";
|
|
|
25
25
|
*/
|
|
26
26
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
27
27
|
/** `default` (the quiet action, what a Button without `variant` draws), `accent` (the
|
|
28
|
-
* strong call to action, solid brand), `secondary`, `ghost`, `danger` or `link`.
|
|
29
|
-
*
|
|
28
|
+
* strong call to action, solid brand), `secondary`, `ghost`, `danger` or `link`. See
|
|
29
|
+
* {@link ButtonVariant}. */
|
|
30
30
|
variant?: ButtonVariant;
|
|
31
31
|
/** `md` (default) is the page's action button. `sm` is the compact one — 12px text
|
|
32
32
|
* and `px-2 py-1` — for the secondary actions in a toolbar, a card header or a
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// The live side of `chartEdge` (theme/chart-palette.ts): which colours a FILLED mark is
|
|
2
2
|
// painted with and which grounds it sits on, read off <html> as the page resolves them —
|
|
3
3
|
// so the 1px ink edge follows a theme toggle and a palette switch without the chart
|
|
4
|
-
// knowing either store.
|
|
4
|
+
// knowing either store. And WHETHER a mark gets one: `useEdgesInForce`, the contrast
|
|
5
|
+
// setting's switch. Shared by SeriesChart (bars, areas) and Treemap (tiles).
|
|
5
6
|
import { useCallback, useSyncExternalStore } from "react";
|
|
6
7
|
import { chartEdge } from "../theme/chart-palette";
|
|
7
8
|
import { parseHex } from "../theme/color";
|
|
@@ -71,3 +72,35 @@ export function useChartEdge(): (fill: string | undefined) => string | undefined
|
|
|
71
72
|
[snapshot],
|
|
72
73
|
);
|
|
73
74
|
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* How filled marks are parted — see `TreemapProps.edges` (0.51.6, keksdose dev #642).
|
|
78
|
+
* `"auto"`: `"uniform"` at Standard contrast, `"contrast"` while More contrast is in force.
|
|
79
|
+
*/
|
|
80
|
+
export type ChartEdges = "auto" | "uniform" | "contrast";
|
|
81
|
+
|
|
82
|
+
// `<html data-contrast>`, followed live: what `"auto"` keys on. Read here rather than
|
|
83
|
+
// through theme/contrast, whose store would come into the chart entry with it.
|
|
84
|
+
function subscribeContrast(onChange: () => void): () => void {
|
|
85
|
+
if (typeof MutationObserver === "undefined" || typeof document === "undefined") return () => {};
|
|
86
|
+
const observer = new MutationObserver(onChange);
|
|
87
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-contrast"] });
|
|
88
|
+
return () => observer.disconnect();
|
|
89
|
+
}
|
|
90
|
+
const readMoreContrast = () =>
|
|
91
|
+
typeof document !== "undefined" && document.documentElement.getAttribute("data-contrast") === "more";
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The edges a filled mark draws: `"auto"` resolved against the contrast in force, live.
|
|
95
|
+
*
|
|
96
|
+
* Under `"contrast"` a mark whose hue is under 3:1 against the ground gets the 1px ink
|
|
97
|
+
* edge ({@link useChartEdge}); under `"uniform"` none does. The tiles took this rule in
|
|
98
|
+
* 0.51.6 (#642: "The borders do not look nice when changing from tile to tile"), and
|
|
99
|
+
* SeriesChart's bars and areas in 0.52 (refactor audit 2026-10-30, DSP-18, Marcel's
|
|
100
|
+
* decision 3): at Standard contrast the edge fell on 5 of 8 hues in light, and in dark on
|
|
101
|
+
* chart-5 and chart-7 alone — the same unevenness, in a bar chart.
|
|
102
|
+
*/
|
|
103
|
+
export function useEdgesInForce(edges: ChartEdges = "auto"): "uniform" | "contrast" {
|
|
104
|
+
const more = useSyncExternalStore(subscribeContrast, readMoreContrast, () => false);
|
|
105
|
+
return edges === "auto" ? (more ? "contrast" : "uniform") : edges;
|
|
106
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// A chart's accessible description — internal, not exported from the barrel.
|
|
2
|
+
//
|
|
3
|
+
// A chart is a `role="figure"` named by its `aria-label` and described by a sentence of
|
|
4
|
+
// what it shows (0.52, refactor audit 2026-10-30, DSP-5). SeriesChart and Treemap each
|
|
5
|
+
// built the `hidden` sentence and the `aria-describedby` that points at it, and already
|
|
6
|
+
// differed: Treemap kept a caller's own ids, SeriesChart had none to keep. Both put the
|
|
7
|
+
// sentence AFTER the figure, as its sibling, so the chart stopped being its parent's last
|
|
8
|
+
// child and a stack's `space-y-*` or `divide-y` gave it a margin or a rule underneath (0.52
|
|
9
|
+
// code review, deep, charts, findings 7 and 14). One copy now, rendered inside the root.
|
|
10
|
+
import { useId, type ReactNode } from "react";
|
|
11
|
+
|
|
12
|
+
export interface FigureDescription {
|
|
13
|
+
/** The root's `aria-describedby`: the caller's own ids, then the description's. */
|
|
14
|
+
describedBy: string | undefined;
|
|
15
|
+
/** The description, to render INSIDE the root; `null` when there is none. */
|
|
16
|
+
node: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The description of a figure, and the `aria-describedby` that reads it — after the
|
|
21
|
+
* caller's own ids (`describedBy`), which it keeps. The sentence is `hidden`: it is read
|
|
22
|
+
* through the reference, never a second time in browse mode, and takes no room.
|
|
23
|
+
*/
|
|
24
|
+
export function useFigureDescription(description: string | undefined, describedBy?: string): FigureDescription {
|
|
25
|
+
const id = useId();
|
|
26
|
+
if (!description) return { describedBy, node: null };
|
|
27
|
+
return {
|
|
28
|
+
describedBy: describedBy ? `${describedBy} ${id}` : id,
|
|
29
|
+
node: (
|
|
30
|
+
<span id={id} hidden>
|
|
31
|
+
{description}
|
|
32
|
+
</span>
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -466,7 +466,6 @@ export function withChartZoom<P extends ZoomTarget>(Chart: ComponentType<P>) {
|
|
|
466
466
|
<ZoomLayer
|
|
467
467
|
axisIds={axes.map((axis) => axis.id)}
|
|
468
468
|
only={only}
|
|
469
|
-
label={labels.zoomHint}
|
|
470
469
|
onZoom={(selection) => {
|
|
471
470
|
const next = zoomAfter(state, selection, source);
|
|
472
471
|
if (next.x !== xWindow) setXWindow(next.x);
|
|
@@ -506,17 +505,20 @@ export function withChartZoom<P extends ZoomTarget>(Chart: ComponentType<P>) {
|
|
|
506
505
|
* A transparent rectangle over the plot area that reads the drag. It does NOT stop the
|
|
507
506
|
* event: recharts drives its tooltip from the same pointer move bubbling up to its own
|
|
508
507
|
* wrapper, so swallowing it here would trade the tooltip for the zoom.
|
|
508
|
+
*
|
|
509
|
+
* Nothing to assistive technology (0.52, refactor audit 2026-10-30, DSP-5): it was a
|
|
510
|
+
* `role="application"` named by the drag hint, which could not take focus — the one name
|
|
511
|
+
* on an otherwise unnamed chart. The hint is in the chart's description now
|
|
512
|
+
* (`SeriesChart`'s figure), and `data-zoom-surface` is how a test finds the rect.
|
|
509
513
|
*/
|
|
510
514
|
function ZoomLayer({
|
|
511
515
|
axisIds,
|
|
512
516
|
only,
|
|
513
|
-
label,
|
|
514
517
|
onZoom,
|
|
515
518
|
onReset,
|
|
516
519
|
}: {
|
|
517
520
|
axisIds: string[];
|
|
518
521
|
only?: "x" | "y";
|
|
519
|
-
label: string;
|
|
520
522
|
onZoom: (selection: ZoomSelection) => void;
|
|
521
523
|
onReset: () => void;
|
|
522
524
|
}) {
|
|
@@ -578,8 +580,7 @@ function ZoomLayer({
|
|
|
578
580
|
height={plot.height}
|
|
579
581
|
// `transparent`, not `none`: an unpainted shape takes no pointer events.
|
|
580
582
|
fill="transparent"
|
|
581
|
-
|
|
582
|
-
aria-label={label}
|
|
583
|
+
data-zoom-surface=""
|
|
583
584
|
style={{ cursor: "crosshair" }}
|
|
584
585
|
onPointerDown={(event) => {
|
|
585
586
|
if (event.button !== 0) return;
|