@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,13 +1,17 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from "react";
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import type { KeyboardEvent, ReactNode } from "react";
|
|
3
3
|
import { KeyRound } from "lucide-react";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
|
-
import {
|
|
5
|
+
import { useDayFormatter } from "../lib/day-format";
|
|
6
|
+
import { toDate } from "../lib/format";
|
|
7
|
+
import type { LabelOverride } from "../i18n/kit-labels";
|
|
6
8
|
import { Button } from "../components/button";
|
|
7
9
|
import { Card } from "../components/card";
|
|
8
10
|
import { EmptyState } from "../components/empty-state";
|
|
11
|
+
import { InlineConfirm } from "../components/inline-confirm";
|
|
9
12
|
import { Input } from "../components/input";
|
|
10
13
|
import { Skeleton } from "../components/skeleton";
|
|
14
|
+
import { COMMIT_EXCEPT_BILLING, useWriteLock } from "../components/write-lock";
|
|
11
15
|
import { useAccountSettingsLabels } from "./account-settings-labels";
|
|
12
16
|
import { SettingsCardTitle } from "../settings/settings-heading";
|
|
13
17
|
import type { PasskeysSettingLabels } from "./account-settings-labels";
|
|
@@ -88,7 +92,9 @@ export interface PasskeysSettingProps<Id extends PasskeyId = PasskeyId> extends
|
|
|
88
92
|
* app knows which of those it detected.
|
|
89
93
|
*/
|
|
90
94
|
unavailable?: ReactNode;
|
|
91
|
-
/** A date for the "Added …" / "Last used …" lines. Default: the
|
|
95
|
+
/** A date for the "Added …" / "Last used …" lines. Default: the provider's `formatDate`
|
|
96
|
+
* (the app's date preference), else a medium date in the provider's locale and
|
|
97
|
+
* `timeZone`. */
|
|
92
98
|
formatDate?: (date: Date) => string;
|
|
93
99
|
/** Overrides the provider's locale for the default date format. */
|
|
94
100
|
locale?: string;
|
|
@@ -117,6 +123,11 @@ export interface PasskeysSettingProps<Id extends PasskeyId = PasskeyId> extends
|
|
|
117
123
|
* must work in an app without a `ConfirmProvider`, and the question belongs next to
|
|
118
124
|
* the passkey it names. Focus moves to Cancel, as in every destructive confirm in the
|
|
119
125
|
* kit, so the Enter that pressed Delete cannot also answer it.
|
|
126
|
+
*
|
|
127
|
+
* **Under a write lock** (0.52) Add, Rename, Delete and the confirm are `commit` controls
|
|
128
|
+
* exempt from billing — a lapsed plan still lets the account manage how it signs in, the
|
|
129
|
+
* demo does not. Until 0.52 the passkeys' confirm was the one inline confirm without it,
|
|
130
|
+
* so the demo could delete, rename and add (refactor audit 2026-10-30, DUP-10).
|
|
120
131
|
*/
|
|
121
132
|
export function PasskeysSetting<Id extends PasskeyId = PasskeyId>({
|
|
122
133
|
passkeys,
|
|
@@ -138,7 +149,21 @@ export function PasskeysSetting<Id extends PasskeyId = PasskeyId>({
|
|
|
138
149
|
...rest
|
|
139
150
|
}: PasskeysSettingProps<Id>) {
|
|
140
151
|
const labels = useAccountSettingsLabels("passkeys", labelsProp);
|
|
141
|
-
|
|
152
|
+
// The prop, else the provider's `formatDate`, else the kit's in the provider's locale and
|
|
153
|
+
// `timeZone`; a bare "YYYY-MM-DD" is read on its calendar (refactor audit 2026-10-30,
|
|
154
|
+
// DUP-2: this card parsed with `new Date` and built its own `Intl` formatter).
|
|
155
|
+
// The raw value goes in, so a bare day keeps its calendar; the prop still gets a Date.
|
|
156
|
+
const own = useMemo(
|
|
157
|
+
() =>
|
|
158
|
+
formatDate &&
|
|
159
|
+
((value: PasskeyItem["createdAt"]) => {
|
|
160
|
+
const date = toDate(value);
|
|
161
|
+
return date ? formatDate(date) : "";
|
|
162
|
+
}),
|
|
163
|
+
[formatDate],
|
|
164
|
+
);
|
|
165
|
+
const day = useDayFormatter(own, localeProp);
|
|
166
|
+
const lock = useWriteLock(COMMIT_EXCEPT_BILLING);
|
|
142
167
|
const [name, setName] = useState("");
|
|
143
168
|
// `beforeAdd` is running. State for the button, and a ref for the guard: two clicks
|
|
144
169
|
// in one frame both read the state from before either set it.
|
|
@@ -146,14 +171,12 @@ export function PasskeysSetting<Id extends PasskeyId = PasskeyId>({
|
|
|
146
171
|
const checkingRef = useRef(false);
|
|
147
172
|
|
|
148
173
|
const date = (value: PasskeyItem["createdAt"]): string | null => {
|
|
149
|
-
|
|
150
|
-
const d = value instanceof Date ? value : new Date(value);
|
|
151
|
-
if (Number.isNaN(d.getTime())) return null;
|
|
152
|
-
return formatDate ? formatDate(d) : new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(d);
|
|
174
|
+
return toDate(value) ? day(value) : null;
|
|
153
175
|
};
|
|
154
176
|
|
|
155
177
|
const add = () => {
|
|
156
|
-
|
|
178
|
+
// The name field's Enter reaches here too, past the locked button.
|
|
179
|
+
if (adding || checkingRef.current || lock.locked) return;
|
|
157
180
|
const typed = name;
|
|
158
181
|
const value = typed.trim();
|
|
159
182
|
const send = () =>
|
|
@@ -211,6 +234,7 @@ export function PasskeysSetting<Id extends PasskeyId = PasskeyId>({
|
|
|
211
234
|
lastUsed={date(item.lastUsedAt)}
|
|
212
235
|
attributes={rowProps?.(item)}
|
|
213
236
|
busy={busyId !== undefined && busyId !== null && busyId === item.id}
|
|
237
|
+
locked={lock.locked}
|
|
214
238
|
onRename={onRename}
|
|
215
239
|
onDelete={onDelete}
|
|
216
240
|
labels={labels}
|
|
@@ -234,7 +258,7 @@ export function PasskeysSetting<Id extends PasskeyId = PasskeyId>({
|
|
|
234
258
|
}}
|
|
235
259
|
/>
|
|
236
260
|
)}
|
|
237
|
-
<Button onClick={add} disabled={busy} aria-busy={busy || undefined}>
|
|
261
|
+
<Button onClick={add} commit={COMMIT_EXCEPT_BILLING} disabled={busy} aria-busy={busy || undefined}>
|
|
238
262
|
<KeyRound className="size-4" aria-hidden />
|
|
239
263
|
{adding ? labels.adding : labels.add}
|
|
240
264
|
</Button>
|
|
@@ -265,6 +289,7 @@ function PasskeyRow<Id extends PasskeyId>({
|
|
|
265
289
|
lastUsed,
|
|
266
290
|
attributes,
|
|
267
291
|
busy,
|
|
292
|
+
locked,
|
|
268
293
|
onRename,
|
|
269
294
|
onDelete,
|
|
270
295
|
labels,
|
|
@@ -274,24 +299,26 @@ function PasskeyRow<Id extends PasskeyId>({
|
|
|
274
299
|
lastUsed: string | null;
|
|
275
300
|
attributes?: { id?: string } & PasskeyDataAttributes;
|
|
276
301
|
busy: boolean;
|
|
302
|
+
/** A write lock holds: the rename field's Enter saves nothing. */
|
|
303
|
+
locked: boolean;
|
|
277
304
|
onRename?: PasskeysSettingProps<Id>["onRename"];
|
|
278
305
|
onDelete?: PasskeysSettingProps<Id>["onDelete"];
|
|
279
306
|
labels: PasskeysSettingLabels;
|
|
280
307
|
}) {
|
|
281
308
|
const [mode, setMode] = useState<RowMode>("view");
|
|
282
309
|
const [draft, setDraft] = useState(item.name);
|
|
283
|
-
// Which button opened the sub-mode, so leaving it puts focus back there — the
|
|
284
|
-
//
|
|
310
|
+
// Which button opened the sub-mode, so leaving it puts focus back there — the field or
|
|
311
|
+
// the confirm unmounts under the focus, which otherwise falls to <body>. InlineConfirm
|
|
312
|
+
// returns it on Cancel and Escape; this also covers a delete that succeeded while the
|
|
313
|
+
// row stayed (the list not refreshed yet) and a rename.
|
|
285
314
|
const [returnTo, setReturnTo] = useState<"rename" | "delete" | null>(null);
|
|
286
|
-
const cancelDeleteRef = useRef<HTMLButtonElement>(null);
|
|
287
315
|
const renameRef = useRef<HTMLInputElement>(null);
|
|
288
316
|
const renameButtonRef = useRef<HTMLButtonElement>(null);
|
|
289
317
|
const deleteButtonRef = useRef<HTMLButtonElement>(null);
|
|
290
318
|
|
|
291
319
|
useEffect(() => {
|
|
292
|
-
if (mode === "
|
|
293
|
-
else if (mode === "rename")
|
|
294
|
-
else if (returnTo) (returnTo === "rename" ? renameButtonRef : deleteButtonRef).current?.focus();
|
|
320
|
+
if (mode === "rename") renameRef.current?.select();
|
|
321
|
+
else if (mode === "view" && returnTo) (returnTo === "rename" ? renameButtonRef : deleteButtonRef).current?.focus();
|
|
295
322
|
}, [mode, returnTo]);
|
|
296
323
|
|
|
297
324
|
const open = (next: "rename" | "delete") => {
|
|
@@ -300,17 +327,10 @@ function PasskeyRow<Id extends PasskeyId>({
|
|
|
300
327
|
setMode(next);
|
|
301
328
|
};
|
|
302
329
|
const leave = () => setMode("view");
|
|
303
|
-
const escapeLeaves = (e: KeyboardEvent<HTMLButtonElement>) => {
|
|
304
|
-
if (e.key === "Escape") {
|
|
305
|
-
e.preventDefault();
|
|
306
|
-
e.stopPropagation();
|
|
307
|
-
leave();
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
330
|
|
|
311
331
|
const saveRename = () => {
|
|
312
332
|
const next = draft.trim();
|
|
313
|
-
if (!onRename || !next || busy) return;
|
|
333
|
+
if (!onRename || !next || busy || locked) return;
|
|
314
334
|
if (next === item.name) {
|
|
315
335
|
leave();
|
|
316
336
|
return;
|
|
@@ -356,7 +376,7 @@ function PasskeyRow<Id extends PasskeyId>({
|
|
|
356
376
|
}
|
|
357
377
|
}}
|
|
358
378
|
/>
|
|
359
|
-
<Button size="sm" onClick={saveRename} disabled={busy || !draft.trim()}>
|
|
379
|
+
<Button size="sm" onClick={saveRename} commit={COMMIT_EXCEPT_BILLING} disabled={busy || !draft.trim()}>
|
|
360
380
|
{labels.save}
|
|
361
381
|
</Button>
|
|
362
382
|
<Button size="sm" variant="ghost" onClick={leave}>
|
|
@@ -368,19 +388,19 @@ function PasskeyRow<Id extends PasskeyId>({
|
|
|
368
388
|
|
|
369
389
|
if (mode === "delete") {
|
|
370
390
|
return (
|
|
371
|
-
<
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
391
|
+
<InlineConfirm
|
|
392
|
+
as="li"
|
|
393
|
+
{...li}
|
|
394
|
+
className="py-2"
|
|
395
|
+
prompt={labels.deleteConfirm(item.name)}
|
|
396
|
+
confirmLabel={labels.confirmDelete}
|
|
397
|
+
cancelLabel={labels.cancel}
|
|
398
|
+
onConfirm={confirmDelete}
|
|
399
|
+
onLeave={leave}
|
|
400
|
+
busy={busy}
|
|
401
|
+
commit={COMMIT_EXCEPT_BILLING}
|
|
402
|
+
returnFocusRef={deleteButtonRef}
|
|
403
|
+
/>
|
|
384
404
|
);
|
|
385
405
|
}
|
|
386
406
|
|
|
@@ -398,6 +418,7 @@ function PasskeyRow<Id extends PasskeyId>({
|
|
|
398
418
|
ref={renameButtonRef}
|
|
399
419
|
size="sm"
|
|
400
420
|
variant="ghost"
|
|
421
|
+
commit={COMMIT_EXCEPT_BILLING}
|
|
401
422
|
disabled={busy}
|
|
402
423
|
onClick={() => open("rename")}
|
|
403
424
|
aria-label={labels.renameItem(item.name)}
|
|
@@ -411,6 +432,7 @@ function PasskeyRow<Id extends PasskeyId>({
|
|
|
411
432
|
size="sm"
|
|
412
433
|
variant="ghost"
|
|
413
434
|
tone="danger"
|
|
435
|
+
commit={COMMIT_EXCEPT_BILLING}
|
|
414
436
|
disabled={busy}
|
|
415
437
|
onClick={() => open("delete")}
|
|
416
438
|
aria-label={labels.deleteItem(item.name)}
|
|
@@ -2,9 +2,11 @@ import { useState } from "react";
|
|
|
2
2
|
import type { ComponentPropsWithRef, ReactNode } from "react";
|
|
3
3
|
import { MonitorSmartphone } from "lucide-react";
|
|
4
4
|
|
|
5
|
-
import { useKitLabels,
|
|
5
|
+
import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
6
6
|
import { cn } from "../lib/cn";
|
|
7
|
-
import {
|
|
7
|
+
import { useDayFormatter } from "../lib/day-format";
|
|
8
|
+
import { describeFailure } from "../lib/describe-failure";
|
|
9
|
+
import { toDate, useKitFormat } from "../lib/format";
|
|
8
10
|
import type { DateInput } from "../lib/format";
|
|
9
11
|
import { AlertBanner } from "../components/alert-banner";
|
|
10
12
|
import { Chip } from "../components/chip";
|
|
@@ -107,8 +109,9 @@ export interface SessionsSettingProps<Id extends SessionId = SessionId> extends
|
|
|
107
109
|
onRevoke?: (id: Id) => Promise<unknown> | void;
|
|
108
110
|
/** The app's own words for a failure, or `undefined` for the kit's `failed`. */
|
|
109
111
|
describeError?: (error: unknown, action: SessionsAction) => ReactNode | undefined;
|
|
110
|
-
/** The "Last active" text. Default: how long ago, in the provider's locale
|
|
111
|
-
* date once it is more than a week back
|
|
112
|
+
/** The "Last active" text. Default: how long ago, in the provider's locale and
|
|
113
|
+
* `timeZone`, and the date once it is more than a week back — through the provider's
|
|
114
|
+
* `formatDate` (the app's date preference) when it has one. */
|
|
112
115
|
formatLastActive?: (date: Date) => string;
|
|
113
116
|
/** Overrides the provider's locale for the default format. */
|
|
114
117
|
locale?: string;
|
|
@@ -152,22 +155,25 @@ export function SessionsSetting<Id extends SessionId = SessionId>({
|
|
|
152
155
|
...rest
|
|
153
156
|
}: SessionsSettingProps<Id>) {
|
|
154
157
|
const labels = useKitLabels("sessions", DEFAULT_SESSIONS_LABELS, labelsProp);
|
|
155
|
-
|
|
158
|
+
// The provider's locale and `timeZone`; past a week the words are a date, and a date
|
|
159
|
+
// that names a day follows the app's preference (refactor audit 2026-10-30, DUP-2).
|
|
160
|
+
const { formatDate, formatRelativeTime } = useKitFormat(localeProp);
|
|
161
|
+
const day = useDayFormatter(null, localeProp);
|
|
156
162
|
const [busyId, setBusyId] = useState<Id | null>(null);
|
|
157
163
|
const [failure, setFailure] = useState<ReactNode>(null);
|
|
158
164
|
const mounted = useMounted();
|
|
159
165
|
|
|
160
|
-
const describe = (error: unknown, action: SessionsAction): ReactNode =>
|
|
161
|
-
|
|
162
|
-
return hasContent(own) ? own : labels.failed;
|
|
163
|
-
};
|
|
166
|
+
const describe = (error: unknown, action: SessionsAction): ReactNode =>
|
|
167
|
+
describeFailure(describeError?.(error, action), labels.failed);
|
|
164
168
|
|
|
165
169
|
const lastActive = (value: DateInput): string | null => {
|
|
166
170
|
const date = toDate(value);
|
|
167
171
|
if (!date) return null;
|
|
168
|
-
return formatLastActive
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
if (formatLastActive) return formatLastActive(date);
|
|
173
|
+
const words = formatRelativeTime(date, { absoluteAfterDays: 7, absoluteStyle: "medium" });
|
|
174
|
+
// Past a week the words ARE the medium date ("5 weeks ago" makes a reader do sums);
|
|
175
|
+
// then the day as the app's preference writes it.
|
|
176
|
+
return words === formatDate(date, "medium") ? day(date) : words;
|
|
171
177
|
};
|
|
172
178
|
|
|
173
179
|
const signOutEverywhere = () => {
|
|
@@ -12,6 +12,7 @@ import { authErrorCode } from "../auth/auth-errors";
|
|
|
12
12
|
import type { KitErrorCode } from "../auth/auth-errors";
|
|
13
13
|
import { usePersonLabel } from "./admin-parts";
|
|
14
14
|
import { hasContent } from "../lib/presence";
|
|
15
|
+
import { isThenable } from "../lib/thenable";
|
|
15
16
|
import type { AdminPerson, MaybePromise } from "./admin-parts";
|
|
16
17
|
import { isGroupTarget } from "./admin-action-log";
|
|
17
18
|
import type { AdminGroupTarget } from "./admin-action-log";
|
|
@@ -176,11 +177,6 @@ interface AdminActionConfirmCommonProps {
|
|
|
176
177
|
* and `acknowledge`. */
|
|
177
178
|
export type AdminActionConfirmProps = AdminActionConfirmCommonProps & AdminActionConfirmTarget;
|
|
178
179
|
|
|
179
|
-
/** Whether a callback answered a promise. */
|
|
180
|
-
function isThenable(value: unknown): value is PromiseLike<unknown> {
|
|
181
|
-
return typeof value === "object" && value !== null && typeof (value as PromiseLike<unknown>).then === "function";
|
|
182
|
-
}
|
|
183
|
-
|
|
184
180
|
/** The refusal's words and code. */
|
|
185
181
|
function refusalOf(
|
|
186
182
|
error: unknown,
|
package/src/admin/admin-parts.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useKitLocale } from "../i18n/kit-labels";
|
|
3
|
+
import { useDayFormatter } from "../lib/day-format";
|
|
4
|
+
import { toDate } from "../lib/format";
|
|
4
5
|
import type { DateInput } from "../lib/format";
|
|
5
|
-
import { toLocalIso } from "../lib/dates";
|
|
6
6
|
import { formatPersonName } from "../lib/person-name";
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -54,29 +54,15 @@ export function usePersonLabel(localeProp?: string): (person: AdminPerson | null
|
|
|
54
54
|
/**
|
|
55
55
|
* A day as words in a sentence ("6 Nov 2026"): the provider's `formatDate` when the app
|
|
56
56
|
* set one (keksdose K12), asked for no weekday — a date in a sentence carries none — else
|
|
57
|
-
* `Intl`'s medium date
|
|
57
|
+
* `Intl`'s medium date, in the provider's locale and `timeZone` (0.52: the kit's one day
|
|
58
|
+
* ladder, `useDayFormatter` — refactor audit 2026-10-30, DUP-2). `""` for no date or one
|
|
59
|
+
* that does not parse: the caller leaves the sentence out.
|
|
58
60
|
*/
|
|
59
61
|
export function useDayText(localeProp?: string): (value: DateInput) => string {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
return useCallback(
|
|
63
|
-
(value) => {
|
|
64
|
-
const date = toDate(value);
|
|
65
|
-
if (!date) return "";
|
|
66
|
-
const own = fromProvider
|
|
67
|
-
? fromProvider(toLocalIso(date), { unit: "day", source: "dateMark", locale, weekday: false })
|
|
68
|
-
: "";
|
|
69
|
-
return own || formatDate(date, "medium", { locale });
|
|
70
|
-
},
|
|
71
|
-
[fromProvider, locale],
|
|
72
|
-
);
|
|
62
|
+
const day = useDayFormatter(undefined, localeProp);
|
|
63
|
+
return useCallback((value) => (toDate(value) ? day(value) : ""), [day]);
|
|
73
64
|
}
|
|
74
65
|
|
|
75
|
-
/** Call a callback that may throw or answer a promise, as a promise
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return Promise.resolve(call());
|
|
79
|
-
} catch (error) {
|
|
80
|
-
return Promise.reject(error);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
66
|
+
/** Call a callback that may throw or answer a promise, as a promise — the kit's one
|
|
67
|
+
* (hooks/use-mounted), not a copy of it (0.52 code review, this file). */
|
|
68
|
+
export { settle } from "../hooks/use-mounted";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// catalogue (src/i18n/defaults.ts) imports them without the component, so `en` loads as one
|
|
3
3
|
// chunk like the other languages (0.34, KS U8). ./mail-test-card re-exports them.
|
|
4
4
|
|
|
5
|
-
import { englishRateLimited } from "../auth/auth-errors";
|
|
5
|
+
import { englishRateLimited } from "../auth/auth-errors-labels";
|
|
6
6
|
import type { MailTestCardLabels } from "./mail-test-card";
|
|
7
7
|
|
|
8
8
|
/** docs/admin-harmonization.md §9.2.4, word for word. */
|
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export const DEFAULT_PLAN_CHANGE_LABELS: PlanChangeLabels = {
|
|
8
|
-
column: "Plan",
|
|
9
|
-
title: "Change plan",
|
|
10
|
-
confirm: "Change plan",
|
|
11
|
-
plan: "Plan",
|
|
12
|
-
current: (plan) => `Current plan: ${plan}`,
|
|
13
|
-
keepsItems: "A smaller plan only blocks creating more; nothing is deleted.",
|
|
14
|
-
until: "Free until",
|
|
15
|
-
untilHint: "Leave empty for no end. A running beta keeps its own end.",
|
|
16
|
-
needsChange: "Pick another plan or an end date.",
|
|
17
|
-
changed: (from, to) => `Plan changed from ${from} to ${to}.`,
|
|
18
|
-
set: (to) => `Plan set to ${to}.`,
|
|
19
|
-
keptBeta: "The beta keeps its end; only the plan changed.",
|
|
20
|
-
untilDone: (date) => `Free until ${date}.`,
|
|
21
|
-
overLimit: "Above the new plan’s limit: nothing is removed, new items are blocked.",
|
|
22
|
-
usageOf: (used, limit, dimension) => `${used} of ${limit} ${dimension}`,
|
|
23
|
-
};
|
|
1
|
+
// Moved to billing/plan-change-labels in 0.52 (refactor audit 2026-10-30, MOD-6): the
|
|
2
|
+
// billing and admin folders imported each other through it. Kept so the old path still
|
|
3
|
+
// answers; nothing in the kit imports it any more but the English catalogue.
|
|
4
|
+
export { DEFAULT_PLAN_CHANGE_LABELS } from "../billing/plan-change-labels";
|
|
5
|
+
export type { PlanChangeLabels } from "../billing/plan-change-labels";
|
|
@@ -18,7 +18,8 @@ import { AdminActionConfirm } from "./admin-action-confirm";
|
|
|
18
18
|
import type { AdminActionConfirmValues } from "./admin-action-confirm";
|
|
19
19
|
import { personLabel, useDayText } from "./admin-parts";
|
|
20
20
|
import type { AdminPerson, MaybePromise } from "./admin-parts";
|
|
21
|
-
import { DEFAULT_PLAN_CHANGE_LABELS } from "
|
|
21
|
+
import { DEFAULT_PLAN_CHANGE_LABELS } from "../billing/plan-change-labels";
|
|
22
|
+
import type { PlanChangeLabels } from "../billing/plan-change-labels";
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* The operator's plan parts (docs/billing-harmonization.md §14.12, decision 27):
|
|
@@ -34,49 +35,11 @@ import { DEFAULT_PLAN_CHANGE_LABELS } from "./plan-change-labels";
|
|
|
34
35
|
* whatever the billing switch says.
|
|
35
36
|
*/
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
title: string;
|
|
43
|
-
/** Its confirm button: "Change plan". */
|
|
44
|
-
confirm: string;
|
|
45
|
-
/** The plan select's label: "Plan". */
|
|
46
|
-
plan: string;
|
|
47
|
-
/** The line over the select: "Current plan: Free". */
|
|
48
|
-
current: (plan: string) => string;
|
|
49
|
-
/** Under the select — the fact that is not on the button. */
|
|
50
|
-
keepsItems: string;
|
|
51
|
-
/** The end of a free grant's field: "Free until". */
|
|
52
|
-
until: string;
|
|
53
|
-
/** Under it. */
|
|
54
|
-
untilHint: string;
|
|
55
|
-
/** Why the confirm is held while nothing would change. */
|
|
56
|
-
needsChange: string;
|
|
57
|
-
/** The result: the plan moved from one to another. */
|
|
58
|
-
changed: (from: string, to: string) => string;
|
|
59
|
-
/** The result: an account with no plan before, or the same plan again. */
|
|
60
|
-
set: (to: string) => string;
|
|
61
|
-
/** The result: a running beta kept its own end (§12.34); only the plan moved. */
|
|
62
|
-
keptBeta: string;
|
|
63
|
-
/** The result: the grant runs until `date` (formatted). */
|
|
64
|
-
untilDone: (date: string) => string;
|
|
65
|
-
/** The result: the account owns more than the new plan allows. */
|
|
66
|
-
overLimit: string;
|
|
67
|
-
/**
|
|
68
|
-
* The column's usage, spelled out (its tooltip): "1 of 5 budgets". Figures arrive
|
|
69
|
-
* formatted; `dimension` is the app's word, as `usage.label` gives it — since 0.33.1
|
|
70
|
-
* in the form the LIMIT takes when the label gives its plural forms ("1 of 1 budget",
|
|
71
|
-
* "1 of 5 budgets"): in every shipped language the word follows the limit, or heads
|
|
72
|
-
* the line in German, whose `von` would want a dative plural no app form carries
|
|
73
|
-
* ("Budgets: 1 von 5"). An override of yours gets the same word. Since 0.34 the grant
|
|
74
|
-
* dialog's usage line too, when `usage` comes as the column's shape.
|
|
75
|
-
*/
|
|
76
|
-
usageOf: (used: string, limit: string, dimension: string) => string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Defined in ./plan-change-labels, which holds no component code (0.34, KS U8).
|
|
38
|
+
// The words and their type live in billing/plan-change-labels, which holds no component
|
|
39
|
+
// code (0.34, KS U8): PlanSwitchConfirm reads them too, and billing importing admin while
|
|
40
|
+
// this module imports billing made the two folders import each other (refactor audit
|
|
41
|
+
// 2026-10-30, MOD-6).
|
|
42
|
+
export type { PlanChangeLabels };
|
|
80
43
|
export { DEFAULT_PLAN_CHANGE_LABELS };
|
|
81
44
|
|
|
82
45
|
/** A plan code as the parts compare it: lowercase (§12.16 — an older row's "FREE" is
|
|
@@ -8,6 +8,7 @@ import { CheckboxGroup } from "../components/checkbox-group";
|
|
|
8
8
|
import type { CheckboxGroupOption } from "../components/checkbox-group";
|
|
9
9
|
import { FormActions } from "../components/form-actions";
|
|
10
10
|
import { Caption } from "../components/text";
|
|
11
|
+
import { describeFailure } from "../lib/describe-failure";
|
|
11
12
|
import { hasContent } from "../lib/presence";
|
|
12
13
|
import type { MaybePromise } from "./admin-parts";
|
|
13
14
|
import type { CommitScope } from "../components/write-lock";
|
|
@@ -165,7 +166,7 @@ export function ReviewerScopeEditor({
|
|
|
165
166
|
try {
|
|
166
167
|
result = onSave(scope);
|
|
167
168
|
} catch (error) {
|
|
168
|
-
setFailure(describeError?.(error)
|
|
169
|
+
setFailure(describeFailure(describeError?.(error), labels.failed));
|
|
169
170
|
return;
|
|
170
171
|
}
|
|
171
172
|
if (!result || typeof result.then !== "function") return;
|
|
@@ -174,8 +175,7 @@ export function ReviewerScopeEditor({
|
|
|
174
175
|
() => setPending(false),
|
|
175
176
|
(error: unknown) => {
|
|
176
177
|
setPending(false);
|
|
177
|
-
|
|
178
|
-
setFailure(hasContent(own) ? own : labels.failed);
|
|
178
|
+
setFailure(describeFailure(describeError?.(error), labels.failed));
|
|
179
179
|
},
|
|
180
180
|
);
|
|
181
181
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// The English of every `rateLimited` label, in a module with no component code and no
|
|
2
|
+
// error probing: the English catalogue (src/i18n/defaults.ts) reaches it through nine
|
|
3
|
+
// `*-labels.ts` modules, and until 0.52 that pulled `auth/auth-errors` — and since MOD-6
|
|
4
|
+
// its `lib/http-status` — into the `en` chunk (refactor audit 2026-10-30, MOD-6).
|
|
5
|
+
// auth/auth-errors re-exports both.
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The English of every `rateLimited` label (0.30.0): "Too many attempts. Try again in
|
|
9
|
+
* 30 s." with a wait under a minute, in whole minutes from one minute up (keksdose's
|
|
10
|
+
* reset throttle answers in hours, and "3600 s" is a number nobody reads), and "Wait a
|
|
11
|
+
* moment and try again." without one — or with a `0`.
|
|
12
|
+
*
|
|
13
|
+
* @internal The namespaces' English; not part of the barrel.
|
|
14
|
+
*/
|
|
15
|
+
export function englishRateLimited(seconds?: number): string {
|
|
16
|
+
if (!seconds || seconds <= 0) return "Too many attempts. Wait a moment and try again.";
|
|
17
|
+
return `Too many attempts. Try again in ${englishWait(seconds)}.`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** "30 s", "2 min" — a wait in English, rounded up. @internal */
|
|
21
|
+
export function englishWait(seconds: number): string {
|
|
22
|
+
return seconds < 60 ? `${Math.ceil(seconds)} s` : `${Math.ceil(seconds / 60)} min`;
|
|
23
|
+
}
|
package/src/auth/auth-errors.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { httpStatusOf } from "../lib/http-status";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* The coded refusals of sign-in and sign-up (docs/auth-harmonization.md §5.2): every
|
|
3
5
|
* refusal the auth routes answer carries a machine-readable `code`, and the pages
|
|
@@ -274,29 +276,13 @@ export function errorBodyWithCode(
|
|
|
274
276
|
return undefined;
|
|
275
277
|
}
|
|
276
278
|
|
|
277
|
-
/** An HTTP status as a number, or undefined. */
|
|
278
|
-
function statusOf(value: unknown): number | undefined {
|
|
279
|
-
return typeof value === "number" && Number.isInteger(value) ? value : undefined;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
279
|
/**
|
|
283
|
-
* The HTTP status a thrown error carries
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
* 2. `err.status` — ofetch's `FetchError`, the generated OpenAPI clients' `ApiError`, and
|
|
288
|
-
* a `Response` thrown as it came;
|
|
289
|
-
* 3. `err.statusCode` — ofetch's alias, and Node-style errors.
|
|
290
|
-
*
|
|
291
|
-
* `undefined` when none is a whole number. Package-private — not re-exported from the
|
|
292
|
-
* barrel; {@link isRateLimited} and the session refresh's classifier read it (DUP-11,
|
|
293
|
-
* refactor audit 2026-10: the refresh carried its own copy of this probe).
|
|
280
|
+
* The HTTP status a thrown error carries ({@link httpStatusOf}): axios'
|
|
281
|
+
* `response.status`, then `status`, then `statusCode`. Lives in `lib/http-status.ts`
|
|
282
|
+
* since 0.52 (refactor audit 2026-10-30, MOD-6); re-exported here for the modules that
|
|
283
|
+
* import it from auth. Package-private — not re-exported from the barrel.
|
|
294
284
|
*/
|
|
295
|
-
export
|
|
296
|
-
if (!isBag(err)) return undefined;
|
|
297
|
-
const response = err.response;
|
|
298
|
-
return (isBag(response) ? statusOf(response.status) : undefined) ?? statusOf(err.status) ?? statusOf(err.statusCode);
|
|
299
|
-
}
|
|
285
|
+
export { httpStatusOf };
|
|
300
286
|
|
|
301
287
|
/**
|
|
302
288
|
* Whether `err` is a throttled request — HTTP `429 Too Many Requests` (0.30.0, from the
|
|
@@ -378,20 +364,7 @@ export function retryAfterSeconds(err: unknown, now: number | Date = Date.now())
|
|
|
378
364
|
return value === undefined ? undefined : parseRetryAfter(value, at);
|
|
379
365
|
}
|
|
380
366
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
* moment and try again." without one — or with a `0`.
|
|
386
|
-
*
|
|
387
|
-
* @internal The namespaces' English; not part of the barrel.
|
|
388
|
-
*/
|
|
389
|
-
export function englishRateLimited(seconds?: number): string {
|
|
390
|
-
if (!seconds || seconds <= 0) return "Too many attempts. Wait a moment and try again.";
|
|
391
|
-
return `Too many attempts. Try again in ${englishWait(seconds)}.`;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/** "30 s", "2 min" — a wait in English, rounded up. @internal */
|
|
395
|
-
export function englishWait(seconds: number): string {
|
|
396
|
-
return seconds < 60 ? `${Math.ceil(seconds)} s` : `${Math.ceil(seconds / 60)} min`;
|
|
397
|
-
}
|
|
367
|
+
// The English of the `rateLimited` labels, in auth-errors-labels since 0.52: the English
|
|
368
|
+
// catalogue reached this module for them, and with it `lib/http-status` (refactor audit
|
|
369
|
+
// 2026-10-30, MOD-6). Re-exported for the modules that import them from here.
|
|
370
|
+
export { englishRateLimited, englishWait } from "./auth-errors-labels";
|
|
@@ -2,6 +2,7 @@ import { useContext, useEffect, useId, useRef, useState } from "react";
|
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
5
|
+
import { describeFailure } from "../lib/describe-failure";
|
|
5
6
|
import { usePromisePending } from "../components/danger-confirm";
|
|
6
7
|
import { DialogFrame } from "../components/dialog-frame";
|
|
7
8
|
import { ModalCloseContext } from "../components/modal";
|
|
@@ -153,7 +154,9 @@ export function CompleteNameDialog({
|
|
|
153
154
|
setFailed(false);
|
|
154
155
|
};
|
|
155
156
|
|
|
156
|
-
|
|
157
|
+
// An app's `failed && words` before it has words is `false`, which `??` kept (refactor
|
|
158
|
+
// audit 2026-10-30, DUP-14): the kit's sentence unless the app's says something.
|
|
159
|
+
const message = failed ? describeFailure(error, labels.failed) : undefined;
|
|
157
160
|
|
|
158
161
|
return (
|
|
159
162
|
<DialogFrame
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// loads as one chunk like the other languages (0.34, KS U8). ./forgot-password-form
|
|
4
4
|
// re-exports them.
|
|
5
5
|
|
|
6
|
-
import { englishRateLimited } from "./auth-errors";
|
|
6
|
+
import { englishRateLimited } from "./auth-errors-labels";
|
|
7
7
|
import type { ForgotPasswordLabels } from "./forgot-password-form";
|
|
8
8
|
|
|
9
9
|
/** `Required`: every key, the 0.30 one included, has its English here. */
|
|
@@ -2,13 +2,15 @@ import { useId, useRef, useState } from "react";
|
|
|
2
2
|
import type { ComponentPropsWithRef, FormEvent, ReactNode } from "react";
|
|
3
3
|
import { MailCheck } from "lucide-react";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
|
+
import { describeFailure } from "../lib/describe-failure";
|
|
5
6
|
import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
|
|
6
7
|
import { AlertBanner } from "../components/alert-banner";
|
|
7
8
|
import { TextLink } from "../components/text-link";
|
|
8
9
|
import { Button } from "../components/button";
|
|
9
10
|
import { Input } from "../components/input";
|
|
10
11
|
import { isRateLimited, retryAfterSeconds } from "./auth-errors";
|
|
11
|
-
import {
|
|
12
|
+
import { isThenable } from "../lib/thenable";
|
|
13
|
+
import { FORM_HEADING_CLASS, INTRO_CLASS, OutcomeMessage, useFocusWhen } from "./status-parts";
|
|
12
14
|
import type { AuthHeadingLevel } from "./status-parts";
|
|
13
15
|
import { DEFAULT_FORGOT_PASSWORD_LABELS } from "./forgot-password-form-labels";
|
|
14
16
|
|
|
@@ -146,12 +148,15 @@ export function ForgotPasswordForm({
|
|
|
146
148
|
);
|
|
147
149
|
}
|
|
148
150
|
|
|
149
|
-
// The app's words first, then the throttle's, then the kit's catch-all
|
|
151
|
+
// The app's words first, then the throttle's, then the kit's catch-all — an app's ""
|
|
152
|
+
// is no words (refactor audit 2026-10-30, DUP-14: `??` drew an empty alert).
|
|
150
153
|
const failureFor = (error: unknown): ReactNode =>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
describeFailure(
|
|
155
|
+
describeError?.(error),
|
|
156
|
+
isRateLimited(error)
|
|
157
|
+
? (labels.rateLimited ?? DEFAULT_FORGOT_PASSWORD_LABELS.rateLimited)(retryAfterSeconds(error))
|
|
158
|
+
: labels.error,
|
|
159
|
+
);
|
|
155
160
|
|
|
156
161
|
const submit = (e: FormEvent) => {
|
|
157
162
|
e.preventDefault();
|