@eifi1/ui-kit 0.51.6 → 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 +146 -26
- 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 +3 -7
- 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.d.ts +3 -2
- package/dist/auth/complete-name-dialog.js +3 -5
- 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-request.d.ts +11 -2
- package/dist/billing/cancel-request.js +15 -3
- package/dist/billing/cancel-request.js.map +1 -1
- package/dist/billing/cancel-subscription.d.ts +22 -10
- package/dist/billing/cancel-subscription.js +8 -11
- 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 +21 -9
- package/dist/billing/plan-switch.js +10 -8
- 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 +22 -4
- package/dist/components/amount-input.js +3 -3
- 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/calculator.d.ts +21 -2
- package/dist/components/calculator.js +53 -14
- package/dist/components/calculator.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 +119 -7
- package/dist/components/combobox-core.js +151 -46
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +1 -1
- package/dist/components/combobox.js +142 -131
- 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 +36 -7
- package/dist/components/data-table-mobile.js +63 -31
- 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 +25 -8
- package/dist/components/data-table.js +154 -25
- 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/dialog-frame.d.ts +2 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/entity-combobox.js +4 -2
- package/dist/components/entity-combobox.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 +150 -141
- 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 +4 -3
- 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.d.ts +24 -0
- package/dist/components/modal.js +12 -4
- package/dist/components/modal.js.map +1 -1
- package/dist/components/money-draft.js +7 -5
- package/dist/components/money-draft.js.map +1 -1
- package/dist/components/money-field.d.ts +2 -2
- package/dist/components/money-field.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-entity-combobox.js +2 -1
- package/dist/components/multi-entity-combobox.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/number-field.d.ts +6 -4
- package/dist/components/number-field.js +3 -2
- package/dist/components/number-field.js.map +1 -1
- package/dist/components/number-input.d.ts +4 -1
- package/dist/components/number-input.js +3 -2
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.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/reauth-dialog.d.ts +4 -5
- package/dist/components/reauth-dialog.js +1 -4
- package/dist/components/reauth-dialog.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 +10 -3
- package/dist/components/series-chart-axes.js +1 -0
- 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 +13 -11
- 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-dismiss.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.d.ts +7 -1
- package/dist/hooks/use-overlay-history.js +35 -5
- 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/calc.d.ts +7 -1
- package/dist/lib/calc.js +3 -1
- package/dist/lib/calc.js.map +1 -1
- package/dist/lib/clipboard-minus.d.ts +2 -2
- package/dist/lib/clipboard-minus.js +1 -1
- package/dist/lib/clipboard-minus.js.map +1 -1
- 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/decimal-marks.d.ts +7 -1
- package/dist/lib/decimal-marks.js +5 -2
- package/dist/lib/decimal-marks.js.map +1 -1
- 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.d.ts +5 -3
- package/dist/lib/format.js +16 -13
- 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 +38 -0
- package/dist/lib/text-match.js +24 -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 +16 -4
- package/dist/tour/tour.js +62 -778
- 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/tour/use-tour-url-sync.js +2 -2
- package/dist/tour/use-tour-url-sync.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 +12 -8
- 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 +5 -10
- 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 +9 -8
- 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-request.ts +28 -6
- package/src/billing/cancel-subscription.tsx +29 -22
- 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 +31 -20
- 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 +32 -14
- 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/calculator.tsx +98 -17
- 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 +303 -69
- package/src/components/combobox.tsx +184 -155
- 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 +110 -27
- 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 +267 -41
- 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/dialog-frame.tsx +2 -1
- package/src/components/entity-combobox.tsx +4 -1
- 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 +198 -152
- 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 +14 -5
- package/src/components/measured-grid.tsx +8 -4
- package/src/components/mini-calendar.tsx +6 -5
- package/src/components/modal.tsx +45 -4
- package/src/components/money-draft.ts +16 -5
- package/src/components/money-field.tsx +2 -2
- package/src/components/month-grid.tsx +229 -0
- package/src/components/month-picker.tsx +192 -200
- package/src/components/multi-entity-combobox.tsx +1 -0
- package/src/components/multi-select.tsx +21 -9
- package/src/components/number-field.tsx +14 -7
- package/src/components/number-input.tsx +9 -3
- package/src/components/numpad-sheet.tsx +4 -3
- 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/reauth-dialog.tsx +6 -10
- package/src/components/row-actions.tsx +2 -1
- package/src/components/section-nav.tsx +7 -0
- package/src/components/series-chart-axes.ts +11 -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 +35 -19
- 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-dismiss.ts +3 -2
- 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 +70 -5
- 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/calc.ts +13 -2
- package/src/lib/clipboard-minus.ts +14 -4
- package/src/lib/date-format.ts +89 -13
- package/src/lib/day-format.ts +96 -0
- package/src/lib/decimal-marks.ts +12 -3
- 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 +34 -19
- 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 +69 -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 +116 -1193
- package/src/tour/use-tour-progress.ts +1 -1
- package/src/tour/use-tour-url-sync.ts +7 -3
- 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
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a pathname is one a `PathPattern` names — the rule `useLastVisitedPage`'s
|
|
3
|
+
* `exclude` reads (landing/routing.tsx) and the feedback guard's one-shot routes
|
|
4
|
+
* (refactor audit 2026-10-30, FLW-7), here without the router: `landing/routing` imports
|
|
5
|
+
* react-router, which `/feedback` must not drag in. The one copy: routing kept a private
|
|
6
|
+
* one, and the two had drifted within the round (0.52 code review, this file).
|
|
7
|
+
*
|
|
8
|
+
* A string is that path and everything under it (`/join` is `/join` and `/join/abc`, not
|
|
9
|
+
* `/joined`; `/` is only `/`); a RegExp is tested on the pathname (a `g` flag dropped, so
|
|
10
|
+
* `lastIndex` never carries over between calls).
|
|
11
|
+
*
|
|
12
|
+
* Case-INSENSITIVE, as React Router matches a route unless it sets `caseSensitive` (0.52
|
|
13
|
+
* code review, feedback/feedback-page-link.ts): the FLW-7 guard compared case-sensitively,
|
|
14
|
+
* and `/Join?token=` went out as a link the router still rendered as `/join`. A RegExp
|
|
15
|
+
* gets the `i` flag for the same reason. Matching more than a case-sensitive route would
|
|
16
|
+
* only turns a link into text, or leaves a page unrecorded as a resume target: both
|
|
17
|
+
* callers' safe side.
|
|
18
|
+
*
|
|
19
|
+
* @internal Package-private — not re-exported from the barrel.
|
|
20
|
+
*/
|
|
21
|
+
export function matchesPathPattern(pathname: string, pattern: string | RegExp): boolean {
|
|
22
|
+
if (typeof pattern !== "string") {
|
|
23
|
+
return new RegExp(pattern.source, `${pattern.flags.replace(/[gi]/g, "")}i`).test(pathname);
|
|
24
|
+
}
|
|
25
|
+
const path = pathname.toLowerCase();
|
|
26
|
+
if (pattern === "/") return path === "/";
|
|
27
|
+
const base = (pattern.endsWith("/") ? pattern.slice(0, -1) : pattern).toLowerCase();
|
|
28
|
+
return path === base || path.startsWith(`${base}/`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The pathname of `href` (a path with its query and hash) as React Router matches it:
|
|
33
|
+
* each segment percent-decoded, an encoded `/` kept as `%2F` so it never splits a segment
|
|
34
|
+
* (react-router 8, `decodePath` in `matchRoutesImpl`). The 0.52 code review
|
|
35
|
+
* (feedback/feedback-page-link.ts) found `/j%6Fin?token=` passing the FLW-7 guard as a
|
|
36
|
+
* link that the router decoded to `/join`.
|
|
37
|
+
*
|
|
38
|
+
* A malformed escape leaves its own segment as written, where the router gives up on the
|
|
39
|
+
* whole path: the rest still decodes, so the answer is never less than the router's.
|
|
40
|
+
*
|
|
41
|
+
* @internal Package-private — not re-exported from the barrel.
|
|
42
|
+
*/
|
|
43
|
+
export function routerPathname(href: string): string {
|
|
44
|
+
return href
|
|
45
|
+
.replace(/[?#].*$/, "")
|
|
46
|
+
.split("/")
|
|
47
|
+
.map((segment) => {
|
|
48
|
+
try {
|
|
49
|
+
return decodeURIComponent(segment).replace(/\//g, "%2F");
|
|
50
|
+
} catch {
|
|
51
|
+
return segment;
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
.join("/");
|
|
55
|
+
}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* screen only delays its `onClose` — every test suite, the kit's and the apps', reads a
|
|
14
14
|
* closed overlay as gone at once.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
16
|
+
* Public since 0.52 (DUP-8, refactor audit 2026-10-30): Kurvenschmiede's chain animation
|
|
17
|
+
* carried a copy of its own.
|
|
17
18
|
*/
|
|
18
19
|
export function prefersReducedMotion(whereUnknown = false): boolean {
|
|
19
20
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return whereUnknown;
|
package/src/lib/round.ts
CHANGED
|
@@ -25,14 +25,19 @@ function shiftDecimal(value: number, by: number): number {
|
|
|
25
25
|
* `n` rounded to `digits` decimals, half away from zero, in decimal arithmetic:
|
|
26
26
|
* 1.005 → 1.01, -2.5 at 0 → -3. Never NaN for a finite `n`, and never -0 — `formatMoney`
|
|
27
27
|
* prints -0 as "-0,00 €", so a negative that rounds away comes back as 0. A non-finite
|
|
28
|
-
* `n` comes back unchanged.
|
|
28
|
+
* `n` comes back unchanged. `digits` counts in whole decimals, as `toFixed` takes it: 2.5
|
|
29
|
+
* is 2, and NaN is 0.
|
|
29
30
|
*/
|
|
30
31
|
export function roundHalfAway(n: number, digits: number): number {
|
|
31
32
|
if (!Number.isFinite(n)) return n;
|
|
33
|
+
// "1.2345e2.5" is NaN, and `|| 0` below made it 0: MeasuredGrid's `digits`, which went to
|
|
34
|
+
// `toFixed` before DUP-14 brought it here, wrote every computed cell of a table with a
|
|
35
|
+
// fractional one as "0" (0.52 code review, deep, charts, finding 5).
|
|
36
|
+
const places = Math.trunc(digits) || 0;
|
|
32
37
|
const abs = Math.abs(n);
|
|
33
38
|
// Every double from 2^53 up is a whole number already, and scaling one near
|
|
34
39
|
// Number.MAX_VALUE up would overflow to Infinity.
|
|
35
|
-
const magnitude = abs >= 2 ** 53 ? abs : shiftDecimal(Math.round(shiftDecimal(abs,
|
|
40
|
+
const magnitude = abs >= 2 ** 53 ? abs : shiftDecimal(Math.round(shiftDecimal(abs, places)), -places);
|
|
36
41
|
// The sign goes back on after rounding, so `|| 0` must see the signed result.
|
|
37
42
|
return (n < 0 ? -magnitude : magnitude) || 0;
|
|
38
43
|
}
|
package/src/lib/safe-storage.ts
CHANGED
|
@@ -16,8 +16,13 @@
|
|
|
16
16
|
*
|
|
17
17
|
* Since 0.34 (DUP-11, refactor audit 2026-10) it also removes, and guards
|
|
18
18
|
* `sessionStorage` the same way: `landing/routing`, `billing/checkout-processing` and
|
|
19
|
-
* the demo banner each wrote that guard again by hand.
|
|
20
|
-
*
|
|
19
|
+
* the demo banner each wrote that guard again by hand.
|
|
20
|
+
*
|
|
21
|
+
* Since 0.52 all of it but {@link storedKeys} is public, with a JSON pair beside it
|
|
22
|
+
* (DUP-8, refactor audit 2026-10-30). Kept package-private, the guard was written again
|
|
23
|
+
* four times in the kit's showcase and in 16 files across the three apps, some of them
|
|
24
|
+
* without it: a token read that throws where storage is blocked takes every request
|
|
25
|
+
* down with it. (The kit's own DevMenu, 0.51, wrote the session pair a second time too.)
|
|
21
26
|
*/
|
|
22
27
|
|
|
23
28
|
/** `access` on the storage area, or `fallback` where there is none (SSR) or it throws. */
|
|
@@ -37,9 +42,13 @@ export function readStored(key: string): string | null {
|
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
/** Store `value` under `key`, silently doing nothing when storage is unavailable
|
|
40
|
-
* or full. A preference that cannot be persisted is not worth an exception.
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
* or full. A preference that cannot be persisted is not worth an exception. `null`
|
|
46
|
+
* removes the key, as {@link writeSessionStored}'s does (0.52; the two pairs wrote
|
|
47
|
+
* differently, and `null` past the types stored the string "null" — 0.52 code review). */
|
|
48
|
+
export function writeStored(key: string, value: string | null): void {
|
|
49
|
+
guarded("localStorage", undefined, (storage) =>
|
|
50
|
+
value === null ? storage.removeItem(key) : storage.setItem(key, value),
|
|
51
|
+
);
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
/** Forget `key`, silently doing nothing when storage is blocked — there is nothing to
|
|
@@ -60,10 +69,43 @@ export function writeSessionStored(key: string, value: string | null): void {
|
|
|
60
69
|
);
|
|
61
70
|
}
|
|
62
71
|
|
|
72
|
+
/**
|
|
73
|
+
* The JSON stored under `key`, when it parses and `isShape` accepts it; else `null`. Absent,
|
|
74
|
+
* blocked, malformed and another shape all read as "never set" — the caller's default —
|
|
75
|
+
* which is what the six hand-written `JSON.parse(readStored(key))` reads in the kit each
|
|
76
|
+
* answered in their own try/catch (DUP-8). `isShape` gets the parsed value as `unknown`:
|
|
77
|
+
* the shape check is the one part that is the caller's. A shape check that throws reads
|
|
78
|
+
* as another shape: null.
|
|
79
|
+
*/
|
|
80
|
+
export function readStoredJson<T>(key: string, isShape: (value: unknown) => value is T): T | null {
|
|
81
|
+
const text = readStored(key);
|
|
82
|
+
if (text === null) return null;
|
|
83
|
+
try {
|
|
84
|
+
const value: unknown = JSON.parse(text);
|
|
85
|
+
return isShape(value) ? value : null;
|
|
86
|
+
} catch {
|
|
87
|
+
// not JSON, or a shape check that read past what is there
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Store `value` as JSON under `key`, silently doing nothing when storage is unavailable
|
|
93
|
+
* or full, or the value has no JSON form (a cycle, a BigInt) — {@link writeStored}'s rule. */
|
|
94
|
+
export function writeStoredJson(key: string, value: unknown): void {
|
|
95
|
+
let text: string | undefined;
|
|
96
|
+
try {
|
|
97
|
+
text = JSON.stringify(value);
|
|
98
|
+
} catch {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// `undefined` (and a function) has no JSON form either: stringify answers undefined.
|
|
102
|
+
if (text !== undefined) writeStored(key, text);
|
|
103
|
+
}
|
|
104
|
+
|
|
63
105
|
/**
|
|
64
106
|
* Every key in `area` that starts with `prefix`, or `[]` where storage refuses — for the
|
|
65
107
|
* reset of this device's settings, which removes a table's views by their prefix
|
|
66
|
-
* (docs/settings-harmonization.md §11.4). Package-private
|
|
108
|
+
* (docs/settings-harmonization.md §11.4). Package-private: the reset's alone.
|
|
67
109
|
*/
|
|
68
110
|
export function storedKeys(prefix: string, area: "local" | "session" = "local"): string[] {
|
|
69
111
|
return guarded(area === "session" ? "sessionStorage" : "localStorage", [], (storage) => {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
38
|
import type { AxiosLikeInstance, ServerWakeAxiosConfig } from "./server-wake";
|
|
39
|
-
import { httpStatusOf } from "
|
|
39
|
+
import { httpStatusOf } from "./http-status";
|
|
40
40
|
|
|
41
41
|
/** What the app's `refresh` resolves: the new access token, plus whatever its `store`
|
|
42
42
|
* needs (its refresh token, the user). */
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a chart says a share of its whole — PieChart's slices and centre, Treemap's tiles
|
|
3
|
+
* and groups. Internal, not exported from the barrel.
|
|
4
|
+
*
|
|
5
|
+
* Each chart held a copy of the same two `Intl` formats and the same switch between them
|
|
6
|
+
* (0.52 code review of treemap.tsx, finding 9); one copy is the rule both say.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A formatter for shares (0–1) in `locale`, as a percent: one decimal under 10 %, where
|
|
11
|
+
* rounding to whole percents starts to lie — a slice of 0.4 % said as "0%" says it is not
|
|
12
|
+
* there — and whole percents above. Make it once per locale (it builds two `Intl` formats).
|
|
13
|
+
*/
|
|
14
|
+
export function shareFormat(locale: string | undefined): (share: number) => string {
|
|
15
|
+
const whole = new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: 0 });
|
|
16
|
+
const fine = new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: 1 });
|
|
17
|
+
return (share) => (share < 0.1 ? fine : whole).format(share);
|
|
18
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upper-case the first letter only, in `locale` — the one copy of the rule (refactor audit
|
|
3
|
+
* 2026-10-30, DUP-11: MonthPicker and JumpCalendar each had it, and MiniCalendar's caption
|
|
4
|
+
* still used the CSS `capitalize` it was written against).
|
|
5
|
+
*
|
|
6
|
+
* Several locales (fr, es, it, pt, …) write month names in lower case, which at the head
|
|
7
|
+
* of a field or a panel reads as a typo. But only the FIRST letter is ours to change:
|
|
8
|
+
* `capitalize` upper-cases every word, so Spanish read "Septiembre De 2026", and a
|
|
9
|
+
* caption that does not start with the month kept its wrong capital — Hungarian read
|
|
10
|
+
* "2026. Szeptember". This gives "Septiembre de 2026" and "2026. szeptember".
|
|
11
|
+
*
|
|
12
|
+
* In `locale` because the case mapping is the language's: Turkish upper-cases "i" to "İ".
|
|
13
|
+
* `undefined` is the runtime's default, as everywhere `Intl` takes one.
|
|
14
|
+
*
|
|
15
|
+
* Package-private — not re-exported from the barrel.
|
|
16
|
+
*/
|
|
17
|
+
export function upperFirst(text: string, locale: string | undefined): string {
|
|
18
|
+
return text.charAt(0).toLocaleUpperCase(locale) + text.slice(1);
|
|
19
|
+
}
|
package/src/lib/text-match.ts
CHANGED
|
@@ -32,6 +32,18 @@ export function foldForSearch(text: string, locale?: string): string {
|
|
|
32
32
|
.replace(/ß/g, "ss");
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Whether two names are one name as a picker's search reads them: folded
|
|
37
|
+
* ({@link foldForSearch}) and trimmed — "cafe" is Café, " MIGROS " is Migros. For "does
|
|
38
|
+
* the typed text name a record that exists" (a create row, InlineEntityCombobox's blur
|
|
39
|
+
* commit), which compared with plain `toLowerCase` while the list beside it folded, so
|
|
40
|
+
* "cafe" listed Café as a hit and offered "Create “cafe”" too — a duplicate payee or shop
|
|
41
|
+
* chain one Enter away (refactor audit 2026-10-30, DUP-5). Internal: not in the barrel.
|
|
42
|
+
*/
|
|
43
|
+
export function sameName(a: string, b: string, locale?: string): boolean {
|
|
44
|
+
return foldForSearch(a.trim(), locale) === foldForSearch(b.trim(), locale);
|
|
45
|
+
}
|
|
46
|
+
|
|
35
47
|
/**
|
|
36
48
|
* A picker's query as its words, each folded (0.51.4, keksdose's /prices shop picker):
|
|
37
49
|
* "Migros Zürich" → `["migros", "zurich"]`. An empty or blank query has no words.
|
|
@@ -95,8 +107,63 @@ export function rankMatch(
|
|
|
95
107
|
): MatchRank {
|
|
96
108
|
const q = foldForSearch(query.trim(), locale);
|
|
97
109
|
if (!q) return 0;
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
return rankFolded(foldForSearch(label, locale), q, code === undefined ? undefined : foldForSearch(code, locale));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** {@link rankMatch} on a text, a non-empty query and a code all folded already. */
|
|
114
|
+
function rankFolded(text: string, q: string, code: string | undefined): MatchRank {
|
|
115
|
+
if (text === q || code === q) return 0;
|
|
100
116
|
if (text.startsWith(q)) return 1;
|
|
101
117
|
return text.includes(q) ? 2 : -1;
|
|
102
118
|
}
|
|
119
|
+
|
|
120
|
+
/** A row {@link searchRanked} kept, and how well it answers the WHOLE query:
|
|
121
|
+
* {@link rankMatch}'s rank, or `3` for a row that holds the query's words apart
|
|
122
|
+
* ("Zürich Migros" for "migros zürich"). */
|
|
123
|
+
export interface RankedHit<T> {
|
|
124
|
+
row: T;
|
|
125
|
+
rank: Exclude<MatchRank, -1> | 3;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The rows that hold every word of `query`, each ranked for the WHOLE query — for the
|
|
130
|
+
* lists that FILTER by words ({@link matchesSearch}) and RANK by the whole query
|
|
131
|
+
* ({@link rankMatch}): Combobox, CountrySelect and InlineEntityCombobox (refactor audit
|
|
132
|
+
* 2026-10-30, DUP-4). In the order given; sort by `rank` with a stable sort, and the rows
|
|
133
|
+
* of one rank keep it. No words keep every row, at `0`.
|
|
134
|
+
*
|
|
135
|
+
* Each row's texts are folded ONCE, and the query once. The lists asked `matchesSearch`
|
|
136
|
+
* and then `rankMatch` of each row they kept, which folded the row three times and the
|
|
137
|
+
* query once per row, per keystroke — InlineEntityCombobox asked `rankMatch` twice of
|
|
138
|
+
* most rows (0.52 code review, combobox.tsx).
|
|
139
|
+
*
|
|
140
|
+
* `texts(row)`: where a word may stand; the FIRST is the label the rank is for.
|
|
141
|
+
* `code(row)`: a key that answers only WHOLE — a word that IS the code matches the row,
|
|
142
|
+
* and the code as the whole query ranks `0` ("ch" is Switzerland before it is Chad) —
|
|
143
|
+
* never a letter of it ("w" is not Aruba, AW: 0.52 code review, country-select.tsx).
|
|
144
|
+
* Internal: not in the barrel.
|
|
145
|
+
*/
|
|
146
|
+
export function searchRanked<T>(
|
|
147
|
+
rows: readonly T[],
|
|
148
|
+
query: string,
|
|
149
|
+
texts: (row: T) => readonly (string | undefined)[],
|
|
150
|
+
{ code, locale }: { code?: (row: T) => string; locale?: string } = {},
|
|
151
|
+
): RankedHit<T>[] {
|
|
152
|
+
const q = foldForSearch(query.trim(), locale);
|
|
153
|
+
const words = q.split(/\s+/).filter((word) => word !== "");
|
|
154
|
+
if (words.length === 0) return rows.map((row) => ({ row, rank: 0 }));
|
|
155
|
+
const hits: RankedHit<T>[] = [];
|
|
156
|
+
for (const row of rows) {
|
|
157
|
+
const folded = texts(row)
|
|
158
|
+
.filter((t): t is string => t !== undefined)
|
|
159
|
+
.map((t) => foldForSearch(t, locale));
|
|
160
|
+
const key = code === undefined ? undefined : foldForSearch(code(row), locale);
|
|
161
|
+
// One haystack, as `matchesSearch` has it: a word holds no whitespace, so it cannot
|
|
162
|
+
// match across the newline between two texts.
|
|
163
|
+
const hay = folded.join("\n");
|
|
164
|
+
if (!words.every((word) => word === key || hay.includes(word))) continue;
|
|
165
|
+
const rank = rankFolded(folded[0] ?? "", q, key);
|
|
166
|
+
hits.push({ row, rank: rank === -1 ? 3 : rank });
|
|
167
|
+
}
|
|
168
|
+
return hits;
|
|
169
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a callback's answer is a promise to wait for — an object or a function with a
|
|
3
|
+
* `then` (Promises/A+ "thenable"). A callback that answers nothing is done when it
|
|
4
|
+
* returns.
|
|
5
|
+
*
|
|
6
|
+
* The auth forms (`auth/status-parts`), the admin confirm and the feedback mutation each
|
|
7
|
+
* wrote their own, three spellings of one check — and the admin's turned a thenable
|
|
8
|
+
* FUNCTION away (0.52 code review, feedback/feedback-mutation.ts; the refactor audit's
|
|
9
|
+
* DUP findings).
|
|
10
|
+
*
|
|
11
|
+
* @internal Package-private — not re-exported from the barrel.
|
|
12
|
+
*/
|
|
13
|
+
export function isThenable(value: unknown): value is PromiseLike<unknown> {
|
|
14
|
+
return (
|
|
15
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
16
|
+
value !== null &&
|
|
17
|
+
typeof (value as { then?: unknown }).then === "function"
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* the same contract, so the mapping is written once, here.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import {
|
|
25
|
+
import { matchesSearch, searchWords } from "./text-match";
|
|
26
26
|
|
|
27
27
|
// ── Shapes ──────────────────────────────────────────────────────────────────────
|
|
28
28
|
|
|
@@ -407,7 +407,8 @@ export interface TranslationReviewFilter {
|
|
|
407
407
|
source: string;
|
|
408
408
|
namespace: string;
|
|
409
409
|
/** Searched in the key, the text and the reference, folded as every kit list's search
|
|
410
|
-
* is (`foldForSearch`): no case, no accents — "uberweisung" finds "Überweisung".
|
|
410
|
+
* is (`foldForSearch`): no case, no accents — "uberweisung" finds "Überweisung". Every
|
|
411
|
+
* word on its own (0.52): "budget assign" finds `budget.rta`, "Ready to Assign". */
|
|
411
412
|
query: string;
|
|
412
413
|
placeholdersOnly: boolean;
|
|
413
414
|
}
|
|
@@ -420,20 +421,27 @@ export const DEFAULT_TRANSLATION_REVIEW_FILTER: TranslationReviewFilter = {
|
|
|
420
421
|
placeholdersOnly: false,
|
|
421
422
|
};
|
|
422
423
|
|
|
424
|
+
/**
|
|
425
|
+
* The rows the filters leave. `locale` (0.52) folds the query and the texts as the kit's
|
|
426
|
+
* other lists do — the panel passes the provider's; left out, the runtime's default.
|
|
427
|
+
*/
|
|
423
428
|
export function filterTranslationRows(
|
|
424
429
|
rows: readonly TranslationRow[],
|
|
425
430
|
filter: Partial<TranslationReviewFilter>,
|
|
431
|
+
locale?: string,
|
|
426
432
|
): TranslationRow[] {
|
|
427
433
|
const f = { ...DEFAULT_TRANSLATION_REVIEW_FILTER, ...filter };
|
|
428
|
-
// Folded as every kit list's search is (DUP-5, refactor audit 2026-10).
|
|
429
|
-
|
|
434
|
+
// Folded as every kit list's search is (DUP-5, refactor audit 2026-10), and since 0.52
|
|
435
|
+
// word by word, each anywhere in the key, the text or the reference (0.51.4's rule;
|
|
436
|
+
// refactor audit 2026-10-30, DUP-4: the whole query had to be one substring of one).
|
|
437
|
+
const words = searchWords(f.query, locale);
|
|
430
438
|
return rows.filter(
|
|
431
439
|
(row) =>
|
|
432
440
|
(f.status === "all" || row.status === f.status) &&
|
|
433
441
|
(f.source === "all" || row.source === f.source) &&
|
|
434
442
|
(f.namespace === "all" || row.namespace === f.namespace) &&
|
|
435
443
|
(!f.placeholdersOnly || row.placeholderMismatch) &&
|
|
436
|
-
(
|
|
444
|
+
matchesSearch(words, [row.key, row.text, row.reference], locale),
|
|
437
445
|
);
|
|
438
446
|
}
|
|
439
447
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
|
|
3
|
-
import { settle } from "../
|
|
3
|
+
import { settle } from "../hooks/use-mounted";
|
|
4
4
|
|
|
5
5
|
export interface DeviceZoneReportOptions {
|
|
6
6
|
/** The account's `device_timezone` from `/auth/me`; `undefined` while it loads (no
|
|
@@ -2,7 +2,7 @@ import { Bell } from "lucide-react";
|
|
|
2
2
|
import type { LucideIcon } from "lucide-react";
|
|
3
3
|
|
|
4
4
|
import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
5
|
-
import {
|
|
5
|
+
import { useDayFormatter } from "../lib/day-format";
|
|
6
6
|
import { DEFAULT_LIST_LABELS } from "../components/list-labels";
|
|
7
7
|
import { StatusDot } from "../components/status-dot";
|
|
8
8
|
import { TopBarActionMenu } from "../shell/topbar-action-menu";
|
|
@@ -26,7 +26,8 @@ export interface NotificationBellProps<Id extends string | number = string | num
|
|
|
26
26
|
href: string;
|
|
27
27
|
/** The row's glyph for a type, as {@link NotificationInbox}'s; `Bell` by default. */
|
|
28
28
|
icon?: (type: string) => LucideIcon | undefined;
|
|
29
|
-
/** A row's time. Default: the provider's
|
|
29
|
+
/** A row's time. Default: the provider's `formatDate` (the app's date preference) with
|
|
30
|
+
* the language's clock, else date and time in the provider's locale and `timeZone`. */
|
|
30
31
|
formatDate?: (iso: string) => string;
|
|
31
32
|
labels?: LabelOverride<NotificationsLabels>;
|
|
32
33
|
}
|
|
@@ -57,8 +58,10 @@ export function NotificationBell<Id extends string | number = string | number>({
|
|
|
57
58
|
}: NotificationBellProps<Id>) {
|
|
58
59
|
const labels = useNotificationsLabels(labelsProp);
|
|
59
60
|
const list = useKitLabels("list", DEFAULT_LIST_LABELS);
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
// As the inbox's rows: the prop, else the provider's `formatDate` with the language's
|
|
62
|
+
// clock, else the kit's in the provider's locale and `timeZone` (refactor audit 2026-10-30, DUP-2).
|
|
63
|
+
const day = useDayFormatter(formatDateProp);
|
|
64
|
+
const timeOf = (iso: string) => day(iso, { time: true });
|
|
62
65
|
const unread = unreadCount > 0;
|
|
63
66
|
const shown = (items ?? []).slice(0, BELL_ROWS);
|
|
64
67
|
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { ComponentPropsWithRef,
|
|
1
|
+
import { useId, useRef, useState } from "react";
|
|
2
|
+
import type { ComponentPropsWithRef, ReactNode } from "react";
|
|
3
3
|
import { Bell, CheckCheck, Trash2 } from "lucide-react";
|
|
4
4
|
import type { LucideIcon } from "lucide-react";
|
|
5
5
|
|
|
6
6
|
import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
7
7
|
import { DEFAULT_COMMON_LABELS } from "../i18n/shared-labels";
|
|
8
8
|
import { cn } from "../lib/cn";
|
|
9
|
-
import {
|
|
9
|
+
import { useDayFormatter } from "../lib/day-format";
|
|
10
10
|
import { Button } from "../components/button";
|
|
11
11
|
import { Card } from "../components/card";
|
|
12
12
|
import { EmptyState } from "../components/empty-state";
|
|
13
13
|
import { IconButton } from "../components/icon-button";
|
|
14
|
+
import { InlineConfirm } from "../components/inline-confirm";
|
|
14
15
|
import { List, ListItem } from "../components/list";
|
|
15
16
|
import { Skeleton } from "../components/skeleton";
|
|
16
17
|
import { COMMIT_EXCEPT_BILLING } from "../components/write-lock";
|
|
17
18
|
import { SettingsCardTitle } from "../settings/settings-heading";
|
|
18
|
-
import {
|
|
19
|
+
import { safeNextPath } from "../landing/routing";
|
|
20
|
+
import { settle, useMounted } from "../hooks/use-mounted";
|
|
19
21
|
import { describeFailure, FailureLine, useNotificationsLabels } from "./notification-parts";
|
|
20
22
|
import type { NotificationsLabels } from "./notifications-labels";
|
|
21
23
|
|
|
@@ -29,7 +31,8 @@ export interface NotificationInboxItem<Id extends string | number = string | num
|
|
|
29
31
|
notification_type: string;
|
|
30
32
|
title: string;
|
|
31
33
|
body: string;
|
|
32
|
-
/** A path in the app,
|
|
34
|
+
/** A path in the app, or `null` (nothing to open). Never `//` or a scheme (§3.7): a url
|
|
35
|
+
* that does not resolve to this origin is drawn as a row with nothing to open. */
|
|
33
36
|
url: string | null;
|
|
34
37
|
/** ISO date-time. */
|
|
35
38
|
created_at: string;
|
|
@@ -62,10 +65,12 @@ export interface NotificationInboxProps<Id extends string | number = string | nu
|
|
|
62
65
|
onClear: () => Promise<unknown> | void;
|
|
63
66
|
/**
|
|
64
67
|
* Open a row: the kit marks it read first, then calls this, and the app routes to
|
|
65
|
-
* `item.url` (kastlan switches the acting company, `item.company_id`, first)
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
68
|
+
* `item.url` (kastlan switches the acting company, `item.company_id`, first) — through
|
|
69
|
+
* `safeNextPath`, as the kit does. Every row is a button then.
|
|
70
|
+
* Left out, a row with a `url` is a real link through the provider's router link — the
|
|
71
|
+
* url as a same-origin path (`safeNextPath`) — that marks itself read on a click or a
|
|
72
|
+
* middle click (keksdose #451). A row without one, or with one that leaves the origin
|
|
73
|
+
* (`//host`, a scheme), marks itself read and opens nothing.
|
|
69
74
|
*/
|
|
70
75
|
onOpen?: (item: NotificationInboxItem<Id>) => void;
|
|
71
76
|
/** The row's glyph for a type — the app's map (keksdose's `TYPE_ICONS`). `undefined`,
|
|
@@ -77,7 +82,8 @@ export interface NotificationInboxProps<Id extends string | number = string | nu
|
|
|
77
82
|
onLoadMore?: () => void;
|
|
78
83
|
/** The next page is loading. */
|
|
79
84
|
loadingMore?: boolean;
|
|
80
|
-
/** A row's time. Default: the provider's
|
|
85
|
+
/** A row's time. Default: the provider's `formatDate` (the app's date preference) with
|
|
86
|
+
* the language's clock, else date and time in the provider's locale and `timeZone`. */
|
|
81
87
|
formatDate?: (iso: string) => string;
|
|
82
88
|
/** The heading. Default `labels.inboxTitle` ("Inbox"). */
|
|
83
89
|
title?: ReactNode;
|
|
@@ -124,21 +130,18 @@ export function NotificationInbox<Id extends string | number = string | number>(
|
|
|
124
130
|
}: NotificationInboxProps<Id>) {
|
|
125
131
|
const labels = useNotificationsLabels(labelsProp);
|
|
126
132
|
const common = useKitLabels("common", DEFAULT_COMMON_LABELS);
|
|
127
|
-
|
|
133
|
+
// The prop, else the provider's `formatDate` with the language's clock, else the kit's
|
|
134
|
+
// date and time in the provider's locale and `timeZone` (refactor audit 2026-10-30, DUP-2).
|
|
135
|
+
const day = useDayFormatter(formatDateProp);
|
|
128
136
|
const [asking, setAsking] = useState(false);
|
|
129
137
|
const [busy, setBusy] = useState<"read" | "clear" | null>(null);
|
|
130
138
|
const [failure, setFailure] = useState<ReactNode>(null);
|
|
131
139
|
const mounted = useMounted();
|
|
132
140
|
const headingId = useId();
|
|
133
|
-
|
|
141
|
+
// Back to "Clear all" when the confirm leaves, so focus does not fall to <body>.
|
|
134
142
|
const clearRef = useRef<HTMLButtonElement>(null);
|
|
135
|
-
const [returning, setReturning] = useState(false);
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
if (asking) cancelRef.current?.focus();
|
|
138
|
-
else if (returning) clearRef.current?.focus();
|
|
139
|
-
}, [asking, returning]);
|
|
140
143
|
|
|
141
|
-
const timeOf = (iso: string) => (
|
|
144
|
+
const timeOf = (iso: string) => day(iso, { time: true });
|
|
142
145
|
const iconOf = (type: string): LucideIcon => icon?.(type) ?? Bell;
|
|
143
146
|
|
|
144
147
|
const run = (which: "read" | "clear", call: () => unknown, after?: () => void) => {
|
|
@@ -166,42 +169,21 @@ export function NotificationInbox<Id extends string | number = string | number>(
|
|
|
166
169
|
});
|
|
167
170
|
};
|
|
168
171
|
|
|
169
|
-
const leave = () => {
|
|
170
|
-
setReturning(true);
|
|
171
|
-
setAsking(false);
|
|
172
|
-
};
|
|
173
|
-
const escapeLeaves = (event: KeyboardEvent<HTMLButtonElement>) => {
|
|
174
|
-
if (event.key === "Escape") {
|
|
175
|
-
event.preventDefault();
|
|
176
|
-
event.stopPropagation();
|
|
177
|
-
leave();
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
|
|
181
172
|
const count = items?.length ?? 0;
|
|
182
173
|
|
|
183
174
|
const header = asking ? (
|
|
184
|
-
<
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
onKeyDown={escapeLeaves}
|
|
197
|
-
>
|
|
198
|
-
{labels.clearAll}
|
|
199
|
-
</Button>
|
|
200
|
-
<Button ref={cancelRef} type="button" size="sm" variant="ghost" onClick={leave} onKeyDown={escapeLeaves}>
|
|
201
|
-
{common.cancel}
|
|
202
|
-
</Button>
|
|
203
|
-
</div>
|
|
204
|
-
</div>
|
|
175
|
+
<InlineConfirm
|
|
176
|
+
className="border-b border-subtle px-3 py-2"
|
|
177
|
+
data-inbox-confirm=""
|
|
178
|
+
prompt={labels.clearPrompt}
|
|
179
|
+
confirmLabel={labels.clearAll}
|
|
180
|
+
cancelLabel={common.cancel}
|
|
181
|
+
onConfirm={() => run("clear", onClear, () => setAsking(false))}
|
|
182
|
+
onLeave={() => setAsking(false)}
|
|
183
|
+
busy={busy === "clear"}
|
|
184
|
+
commit={COMMIT_EXCEPT_BILLING}
|
|
185
|
+
returnFocusRef={clearRef}
|
|
186
|
+
/>
|
|
205
187
|
) : (
|
|
206
188
|
<div className="flex items-center justify-between gap-2 border-b border-subtle px-3 py-2">
|
|
207
189
|
<SettingsCardTitle id={headingId}>{title ?? labels.inboxTitle}</SettingsCardTitle>
|
|
@@ -223,10 +205,7 @@ export function NotificationInbox<Id extends string | number = string | number>(
|
|
|
223
205
|
size="xs"
|
|
224
206
|
tone="danger"
|
|
225
207
|
commit={COMMIT_EXCEPT_BILLING}
|
|
226
|
-
onClick={() =>
|
|
227
|
-
setReturning(false);
|
|
228
|
-
setAsking(true);
|
|
229
|
-
}}
|
|
208
|
+
onClick={() => setAsking(true)}
|
|
230
209
|
disabled={count === 0 || busy !== null}
|
|
231
210
|
label={labels.clearAll}
|
|
232
211
|
>
|
|
@@ -273,7 +252,11 @@ export function NotificationInbox<Id extends string | number = string | number>(
|
|
|
273
252
|
/>
|
|
274
253
|
);
|
|
275
254
|
}
|
|
276
|
-
|
|
255
|
+
// A same-origin path or nothing (refactor audit 2026-10-30, FLW-8): `//host` starts
|
|
256
|
+
// with "/" and went through the router link off the origin, and any scheme opened
|
|
257
|
+
// as an external link. The urls are server-written; this is defence in depth.
|
|
258
|
+
const path = safeNextPath(item.url);
|
|
259
|
+
if (!path) {
|
|
277
260
|
return <ListItem key={item.id} {...row} data-inbox-item={String(item.id)} onClick={() => markOne(item)} />;
|
|
278
261
|
}
|
|
279
262
|
// A real link, so a middle click opens a background tab; a middle click fires no
|
|
@@ -283,8 +266,7 @@ export function NotificationInbox<Id extends string | number = string | number>(
|
|
|
283
266
|
key={item.id}
|
|
284
267
|
{...row}
|
|
285
268
|
data-inbox-item={String(item.id)}
|
|
286
|
-
href={
|
|
287
|
-
external={!item.url.startsWith("/")}
|
|
269
|
+
href={path}
|
|
288
270
|
onClick={() => markOne(item)}
|
|
289
271
|
onAuxClick={(event) => {
|
|
290
272
|
if (event.button === 1) markOne(item);
|
|
@@ -19,10 +19,9 @@ export function useNotificationsLabels(prop?: LabelOverride<NotificationsLabels>
|
|
|
19
19
|
return useKitLabels("notifications", DEFAULT_NOTIFICATIONS_LABELS, prop);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/** The app's words for a failure, else `fallback
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
22
|
+
/** The app's words for a failure, else `fallback` — in lib/ since 0.52, for the auth forms
|
|
23
|
+
* too (refactor audit 2026-10-30, DUP-14). */
|
|
24
|
+
export { describeFailure } from "../lib/describe-failure";
|
|
26
25
|
|
|
27
26
|
/** A failure, said under the card's controls — nothing toasts (§4.2). */
|
|
28
27
|
export function FailureLine({ children }: { children: ReactNode }) {
|
|
@@ -13,7 +13,7 @@ import { COMMIT_EXCEPT_BILLING } from "../components/write-lock";
|
|
|
13
13
|
import { usePhoneLayout } from "../hooks/use-breakpoint";
|
|
14
14
|
import { CARD_DESCRIPTION_CLASS } from "../settings/settings-card-classes";
|
|
15
15
|
import { SettingsCardTitle } from "../settings/settings-heading";
|
|
16
|
-
import { settle, useMounted } from "../
|
|
16
|
+
import { settle, useMounted } from "../hooks/use-mounted";
|
|
17
17
|
import { describeFailure, FailureLine, useNotificationsLabels, useWriteOverlay } from "./notification-parts";
|
|
18
18
|
import type { WriteOverlay } from "./notification-parts";
|
|
19
19
|
import type { NotificationsLabels } from "./notifications-labels";
|
|
@@ -162,6 +162,12 @@ export interface NotificationsLabels {
|
|
|
162
162
|
/** Account mail is not a notification, and keeps coming. */
|
|
163
163
|
accountMail: string;
|
|
164
164
|
turnBackOn: string;
|
|
165
|
+
/**
|
|
166
|
+
* 0.52: the line under the outcome, {@link accountMail} and {@link turnBackOn} as one
|
|
167
|
+
* text — joined by the catalogue, not by the panel: the panel glued them with an ASCII
|
|
168
|
+
* space, which Chinese does not put between sentences (refactor audit 2026-10-30, DOC-11).
|
|
169
|
+
*/
|
|
170
|
+
stoppedHint: (accountMail: string, turnBackOn: string) => string;
|
|
165
171
|
openSettings: string;
|
|
166
172
|
/** A token the server refused, or one that does not parse. */
|
|
167
173
|
invalidLink: string;
|
|
@@ -273,6 +279,7 @@ export const DEFAULT_NOTIFICATIONS_LABELS: NotificationsLabels = {
|
|
|
273
279
|
stoppedAll: (app) => `Done. You won’t get notification e-mails from ${app} any more.`,
|
|
274
280
|
accountMail: "E-mails about your account still come.",
|
|
275
281
|
turnBackOn: "You can turn them back on at any time in Settings.",
|
|
282
|
+
stoppedHint: (accountMail, turnBackOn) => `${accountMail} ${turnBackOn}`,
|
|
276
283
|
openSettings: "Open Settings",
|
|
277
284
|
invalidLink: "This link doesn’t work any more. You can turn e-mails off in Settings instead.",
|
|
278
285
|
|