@eifi1/ui-kit 0.53.0 → 0.55.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 +96 -82
- package/dist/account/delete-account-setting.d.ts +3 -2
- package/dist/account/delete-account-setting.js.map +1 -1
- package/dist/admin/plan-change.js +2 -2
- package/dist/admin/plan-change.js.map +1 -1
- package/dist/admin/user-roster.d.ts +6 -0
- package/dist/admin/user-roster.js +4 -0
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/auth-errors.d.ts +36 -0
- package/dist/auth/auth-errors.js +20 -0
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/billing/billing-labels.d.ts +26 -0
- package/dist/billing/billing-labels.js +9 -0
- package/dist/billing/billing-labels.js.map +1 -1
- package/dist/billing/subscription-standing.d.ts +61 -0
- package/dist/billing/subscription-standing.js +51 -0
- package/dist/billing/subscription-standing.js.map +1 -0
- package/dist/billing/usage-meter.d.ts +52 -0
- package/dist/billing/usage-meter.js +52 -0
- package/dist/billing/usage-meter.js.map +1 -0
- package/dist/chart.d.ts +1 -0
- package/dist/chart.js +4 -0
- package/dist/chart.js.map +1 -1
- package/dist/components/alert-banner.js +2 -3
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +2 -1
- package/dist/components/amount-input.js +3 -15
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.js +2 -2
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/bulk-action-bar.js +2 -1
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button.d.ts +35 -1
- package/dist/components/button.js +5 -9
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar-heatmap.js +6 -4
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/camera-button.d.ts +89 -0
- package/dist/components/camera-button.js +122 -0
- package/dist/components/camera-button.js.map +1 -0
- package/dist/components/camera-capture.d.ts +66 -0
- package/dist/components/camera-capture.js +190 -0
- package/dist/components/camera-capture.js.map +1 -0
- package/dist/components/camera-labels.d.ts +20 -0
- package/dist/components/camera-labels.js +15 -0
- package/dist/components/camera-labels.js.map +1 -0
- package/dist/components/chart-edge.d.ts +9 -0
- package/dist/components/chart-edge.js +14 -3
- package/dist/components/chart-edge.js.map +1 -1
- package/dist/components/chart-zoom-core.js +34 -29
- package/dist/components/chart-zoom-core.js.map +1 -1
- package/dist/components/checkbox-group.js +1 -1
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/combobox-core.js +3 -2
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +2 -2
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/consent-again-notice-labels.d.ts +25 -0
- package/dist/components/consent-again-notice-labels.js +15 -0
- package/dist/components/consent-again-notice-labels.js.map +1 -0
- package/dist/components/consent-again-notice.d.ts +85 -0
- package/dist/components/consent-again-notice.js +94 -0
- package/dist/components/consent-again-notice.js.map +1 -0
- package/dist/components/country-select.js +2 -7
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-option-list.d.ts +2 -1
- package/dist/components/currency-option-list.js +10 -3
- package/dist/components/currency-option-list.js.map +1 -1
- package/dist/components/currency-select.d.ts +3 -1
- package/dist/components/currency-select.js +2 -2
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +22 -1
- package/dist/components/danger-confirm.js +52 -30
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-column-settings.js +2 -2
- package/dist/components/data-table-column-settings.js.map +1 -1
- package/dist/components/data-table-filter-popover.d.ts +2 -1
- package/dist/components/data-table-filter-popover.js +3 -2
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +33 -3
- package/dist/components/data-table-filters.js +6 -4
- package/dist/components/data-table-filters.js.map +1 -1
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-virtual.js +13 -3
- package/dist/components/data-table-virtual.js.map +1 -1
- package/dist/components/date-field.js +2 -2
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.js +2 -2
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.js +2 -6
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +5 -1
- package/dist/components/dialog-frame.js +6 -2
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/dropdown.js +7 -3
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/entity-combobox.js +2 -2
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/field-parts.d.ts +108 -6
- package/dist/components/field-parts.js +59 -6
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-suggestion-labels.d.ts +2 -0
- package/dist/components/field-suggestion-labels.js +10 -0
- package/dist/components/field-suggestion-labels.js.map +1 -0
- package/dist/components/field.js +1 -1
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-button.d.ts +1 -1
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/floating-panel.d.ts +7 -6
- package/dist/components/floating-panel.js +3 -17
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form-actions.d.ts +3 -2
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/hover-menu.js +3 -2
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/icon-button.d.ts +23 -5
- package/dist/components/icon-button.js +6 -8
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/inline-confirm.js +2 -1
- package/dist/components/inline-confirm.js.map +1 -1
- package/dist/components/inline-entity-combobox.js +2 -2
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/input.js +2 -2
- package/dist/components/input.js.map +1 -1
- package/dist/components/jump-calendar.js +3 -3
- package/dist/components/jump-calendar.js.map +1 -1
- package/dist/components/legal.d.ts +13 -1
- package/dist/components/legal.js +12 -0
- package/dist/components/legal.js.map +1 -1
- package/dist/components/legended-series-chart.d.ts +80 -0
- package/dist/components/legended-series-chart.js +70 -0
- package/dist/components/legended-series-chart.js.map +1 -0
- package/dist/components/lightbox.js +2 -1
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/mini-calendar.js +16 -7
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.d.ts +48 -0
- package/dist/components/modal.js +26 -6
- package/dist/components/modal.js.map +1 -1
- package/dist/components/month-picker.d.ts +1 -1
- package/dist/components/month-picker.js +6 -6
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.js +2 -2
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.js +2 -6
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-input.js +2 -2
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/page-header-layout.d.ts +18 -0
- package/dist/components/page-header-layout.js +23 -0
- package/dist/components/page-header-layout.js.map +1 -0
- package/dist/components/page-header-skeleton.d.ts +41 -0
- package/dist/components/page-header-skeleton.js +52 -0
- package/dist/components/page-header-skeleton.js.map +1 -0
- package/dist/components/page-header.js +4 -17
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/popover.js +7 -2
- package/dist/components/popover.js.map +1 -1
- package/dist/components/release-notes-labels.d.ts +16 -0
- package/dist/components/release-notes-labels.js +18 -0
- package/dist/components/release-notes-labels.js.map +1 -0
- package/dist/components/release-notes.d.ts +65 -0
- package/dist/components/release-notes.js +65 -0
- package/dist/components/release-notes.js.map +1 -0
- package/dist/components/select.js +2 -2
- package/dist/components/select.js.map +1 -1
- package/dist/components/series-chart-labels.d.ts +9 -0
- package/dist/components/series-chart-labels.js +3 -1
- package/dist/components/series-chart-labels.js.map +1 -1
- package/dist/components/series-chart.d.ts +5 -0
- package/dist/components/series-chart.js +89 -36
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/stat-tile.d.ts +21 -2
- package/dist/components/stat-tile.js +4 -2
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/toggle-group.js +3 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/treemap-layout.js.map +1 -1
- package/dist/components/treemap.d.ts +17 -15
- package/dist/components/treemap.js +167 -85
- package/dist/components/treemap.js.map +1 -1
- package/dist/currencies.d.ts +16 -2
- package/dist/currencies.js +2 -1
- package/dist/currencies.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/eslint/role-utilities.d.ts +2 -2
- package/dist/eslint/role-utilities.js.map +1 -1
- package/dist/feedback/feedback-context-labels.js +2 -1
- package/dist/feedback/feedback-context-labels.js.map +1 -1
- package/dist/feedback/feedback-context.d.ts +19 -3
- package/dist/feedback/feedback-context.js +12 -1
- package/dist/feedback/feedback-context.js.map +1 -1
- package/dist/feedback/feedback-diagnostics.d.ts +17 -0
- package/dist/feedback/feedback-diagnostics.js +27 -0
- package/dist/feedback/feedback-diagnostics.js.map +1 -0
- package/dist/feedback/feedback-dialog.d.ts +10 -0
- package/dist/feedback/feedback-dialog.js +6 -4
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox-page.d.ts +260 -0
- package/dist/feedback/feedback-inbox-page.js +207 -0
- package/dist/feedback/feedback-inbox-page.js.map +1 -0
- package/dist/feedback/feedback-record.d.ts +5 -0
- package/dist/feedback/feedback-record.js.map +1 -1
- package/dist/feedback/feedback-row-detail-labels.js +1 -0
- package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
- package/dist/feedback/feedback-row-detail.d.ts +3 -0
- package/dist/feedback/feedback-row-detail.js +3 -0
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-submit-dialog.d.ts +5 -1
- package/dist/feedback/feedback-submit-dialog.js +15 -3
- package/dist/feedback/feedback-submit-dialog.js.map +1 -1
- package/dist/feedback/feedback-submit.d.ts +30 -2
- package/dist/feedback/feedback-submit.js +5 -2
- package/dist/feedback/feedback-submit.js.map +1 -1
- package/dist/feedback/feedback-vocabulary.js +2 -2
- package/dist/feedback/feedback-vocabulary.js.map +1 -1
- package/dist/feedback.d.ts +1 -0
- package/dist/feedback.js +6 -0
- package/dist/feedback.js.map +1 -1
- package/dist/hooks/use-debounce.d.ts +32 -5
- package/dist/hooks/use-debounce.js +6 -5
- package/dist/hooks/use-debounce.js.map +1 -1
- package/dist/hooks/use-file-picker.d.ts +3 -1
- package/dist/hooks/use-file-picker.js.map +1 -1
- package/dist/hooks/use-focus-trap.d.ts +19 -3
- package/dist/hooks/use-focus-trap.js +15 -5
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-has-camera.d.ts +36 -0
- package/dist/hooks/use-has-camera.js +53 -0
- package/dist/hooks/use-has-camera.js.map +1 -0
- package/dist/hooks/use-hotkey.js +2 -1
- package/dist/hooks/use-hotkey.js.map +1 -1
- package/dist/hooks/use-overlay-history.d.ts +6 -1
- package/dist/hooks/use-overlay-history.js +10 -2
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.js +11 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +78 -4
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +20 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +95 -5
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +74 -4
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +75 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +77 -4
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +77 -4
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +74 -4
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +22 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +27 -8
- package/dist/index.js +41 -2
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-labels.d.ts +8 -0
- package/dist/landing/landing-labels.js +2 -1
- package/dist/landing/landing-labels.js.map +1 -1
- package/dist/lib/changelog.d.ts +130 -0
- package/dist/lib/changelog.js +137 -0
- package/dist/lib/changelog.js.map +1 -0
- package/dist/lib/clipboard-minus.js +2 -2
- package/dist/lib/clipboard-minus.js.map +1 -1
- package/dist/lib/dates.d.ts +36 -4
- package/dist/lib/dates.js +49 -13
- package/dist/lib/dates.js.map +1 -1
- package/dist/lib/editable-content.d.ts +33 -0
- package/dist/lib/editable-content.js +15 -0
- package/dist/lib/editable-content.js.map +1 -0
- package/dist/lib/focus-left.d.ts +47 -1
- package/dist/lib/focus-left.js +11 -2
- package/dist/lib/focus-left.js.map +1 -1
- package/dist/lib/format.d.ts +37 -2
- package/dist/lib/format.js +25 -1
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/intl-cache.d.ts +4 -2
- package/dist/lib/intl-cache.js.map +1 -1
- package/dist/lib/server-wake.d.ts +49 -9
- package/dist/lib/server-wake.js +25 -14
- package/dist/lib/server-wake.js.map +1 -1
- package/dist/lib/session-refresh.d.ts +53 -0
- package/dist/lib/session-refresh.js +27 -1
- package/dist/lib/session-refresh.js.map +1 -1
- package/dist/lib/translation-review.d.ts +26 -0
- package/dist/lib/translation-review.js +14 -0
- package/dist/lib/translation-review.js.map +1 -1
- package/dist/rhf/fields.js +3 -3
- package/dist/rhf/fields.js.map +1 -1
- package/dist/shell/app-shell.d.ts +25 -1
- package/dist/shell/app-shell.js +3 -1
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/dev-menu.d.ts +3 -0
- package/dist/shell/dev-menu.js +4 -2
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/held-changes-banner-labels.d.ts +23 -0
- package/dist/shell/held-changes-banner-labels.js +14 -0
- package/dist/shell/held-changes-banner-labels.js.map +1 -0
- package/dist/shell/held-changes-banner.d.ts +75 -0
- package/dist/shell/held-changes-banner.js +106 -0
- package/dist/shell/held-changes-banner.js.map +1 -0
- package/dist/shell/sync-status-indicator.d.ts +27 -12
- package/dist/shell/sync-status-indicator.js +13 -4
- package/dist/shell/sync-status-indicator.js.map +1 -1
- package/dist/shell/top-bar-parts-labels.d.ts +5 -0
- package/dist/shell/top-bar-parts-labels.js +3 -1
- package/dist/shell/top-bar-parts-labels.js.map +1 -1
- package/dist/shell.d.ts +2 -0
- package/dist/shell.js +3 -0
- package/dist/shell.js.map +1 -1
- package/dist/sync/engine.d.ts +11 -2
- package/dist/sync/engine.js +13 -5
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/hooks.d.ts +3 -2
- package/dist/sync/hooks.js +4 -2
- package/dist/sync/hooks.js.map +1 -1
- package/dist/testing/css-variables.generated.d.ts +2 -2
- package/dist/testing/css-variables.generated.js +1 -1
- package/dist/testing/css-variables.generated.js.map +1 -1
- package/dist/theme/chart-palette.d.ts +18 -0
- package/dist/theme/chart-palette.js +17 -1
- package/dist/theme/chart-palette.js.map +1 -1
- package/dist/theme/contrast-tokens.d.ts +3 -3
- package/dist/theme/contrast-tokens.js.map +1 -1
- package/dist/theme/contrast.d.ts +4 -4
- package/dist/theme/contrast.js.map +1 -1
- package/dist/tour/tour-overlay.js +2 -1
- package/dist/tour/tour-overlay.js.map +1 -1
- package/package.json +5 -9
- package/tokens.css +19 -54
- package/src/account/account-parts.ts +0 -47
- package/src/account/account-settings-labels.ts +0 -240
- package/src/account/account-settings.tsx +0 -698
- package/src/account/data-export-setting-labels.ts +0 -20
- package/src/account/data-export-setting.tsx +0 -200
- package/src/account/delete-account-setting-labels.ts +0 -33
- package/src/account/delete-account-setting.tsx +0 -341
- package/src/account/email-change-setting-labels.ts +0 -31
- package/src/account/email-change-setting.tsx +0 -443
- package/src/account/passkeys-setting.tsx +0 -445
- package/src/account/sessions-setting-labels.ts +0 -24
- package/src/account/sessions-setting.tsx +0 -283
- package/src/admin/admin-action-confirm-labels.ts +0 -19
- package/src/admin/admin-action-confirm.tsx +0 -509
- package/src/admin/admin-action-log-labels.ts +0 -83
- package/src/admin/admin-action-log.tsx +0 -464
- package/src/admin/admin-area-labels.ts +0 -114
- package/src/admin/admin-forbidden.tsx +0 -75
- package/src/admin/admin-overview.tsx +0 -258
- package/src/admin/admin-parts.ts +0 -68
- package/src/admin/admin-sections.tsx +0 -208
- package/src/admin/admin-tool-links.tsx +0 -90
- package/src/admin/invitations-panel-labels.ts +0 -31
- package/src/admin/invitations-panel.tsx +0 -516
- package/src/admin/mail-test-card-labels.ts +0 -19
- package/src/admin/mail-test-card.tsx +0 -189
- package/src/admin/plan-change-labels.ts +0 -5
- package/src/admin/plan-change.tsx +0 -474
- package/src/admin/reviewer-scope-editor-labels.ts +0 -16
- package/src/admin/reviewer-scope-editor.tsx +0 -224
- package/src/admin/role-select-labels.ts +0 -16
- package/src/admin/role-select.tsx +0 -282
- package/src/admin/transfer-ownership-dialog-labels.ts +0 -20
- package/src/admin/transfer-ownership-dialog.tsx +0 -162
- package/src/admin/user-roster-labels.ts +0 -17
- package/src/admin/user-roster.tsx +0 -559
- package/src/auth/accept-invitation-labels.ts +0 -21
- package/src/auth/accept-invitation.tsx +0 -210
- package/src/auth/auth-errors-labels.ts +0 -23
- package/src/auth/auth-errors.ts +0 -370
- package/src/auth/complete-name-dialog-labels.ts +0 -16
- package/src/auth/complete-name-dialog.tsx +0 -253
- package/src/auth/email-tag.ts +0 -75
- package/src/auth/forgot-password-form-labels.ts +0 -20
- package/src/auth/forgot-password-form.tsx +0 -221
- package/src/auth/form-rules.ts +0 -40
- package/src/auth/new-password-fields.tsx +0 -85
- package/src/auth/not-found-page-labels.ts +0 -12
- package/src/auth/not-found-page.tsx +0 -95
- package/src/auth/register-form-labels.ts +0 -31
- package/src/auth/register-form.tsx +0 -456
- package/src/auth/reset-password-form-labels.ts +0 -27
- package/src/auth/reset-password-form.tsx +0 -341
- package/src/auth/sign-in-form-labels.ts +0 -44
- package/src/auth/sign-in-form.tsx +0 -858
- package/src/auth/status-parts.tsx +0 -132
- package/src/auth/verify-email-labels.ts +0 -26
- package/src/auth/verify-email.tsx +0 -445
- package/src/billing/billing-banner.tsx +0 -258
- package/src/billing/billing-labels.ts +0 -381
- package/src/billing/billing-lock.ts +0 -108
- package/src/billing/billing-overview.ts +0 -157
- package/src/billing/billing-standing.ts +0 -80
- package/src/billing/cancel-request.ts +0 -97
- package/src/billing/cancel-subscription.tsx +0 -98
- package/src/billing/checkout-processing.ts +0 -394
- package/src/billing/checkout-return.ts +0 -90
- package/src/billing/pay-page.ts +0 -330
- package/src/billing/plan-card.tsx +0 -562
- package/src/billing/plan-change-labels.ts +0 -66
- package/src/billing/plan-limit-notice.tsx +0 -148
- package/src/billing/plan-limit-toast.tsx +0 -90
- package/src/billing/plan-limit.ts +0 -52
- package/src/billing/plan-price.ts +0 -98
- package/src/billing/plan-switch.tsx +0 -216
- package/src/billing/provider-page.ts +0 -84
- package/src/billing/subscription-actions.tsx +0 -247
- package/src/billing/subscription-status-chip.tsx +0 -95
- package/src/chart.ts +0 -103
- package/src/components/account-chips-labels.ts +0 -16
- package/src/components/account-chips.tsx +0 -474
- package/src/components/alert-banner.tsx +0 -670
- package/src/components/amount-input.tsx +0 -815
- package/src/components/appearance-labels.ts +0 -63
- package/src/components/authed-image-labels.ts +0 -11
- package/src/components/authed-image.tsx +0 -209
- package/src/components/autocomplete.tsx +0 -645
- package/src/components/breadcrumbs-labels.ts +0 -10
- package/src/components/breadcrumbs.tsx +0 -205
- package/src/components/bulk-action-bar-labels.ts +0 -11
- package/src/components/bulk-action-bar.tsx +0 -443
- package/src/components/button-group.tsx +0 -223
- package/src/components/button-look.ts +0 -256
- package/src/components/button.tsx +0 -339
- package/src/components/calculator.tsx +0 -341
- package/src/components/calendar-heatmap-labels.ts +0 -15
- package/src/components/calendar-heatmap.tsx +0 -594
- package/src/components/card.tsx +0 -377
- package/src/components/chart-edge.ts +0 -106
- package/src/components/chart-figure.tsx +0 -35
- package/src/components/chart-height.ts +0 -30
- package/src/components/chart-zoom-core.tsx +0 -627
- package/src/components/chart-zoom.tsx +0 -22
- package/src/components/chart.tsx +0 -554
- package/src/components/checkbox-group.tsx +0 -247
- package/src/components/checkbox.tsx +0 -346
- package/src/components/chip-input.tsx +0 -370
- package/src/components/chip-labels.ts +0 -13
- package/src/components/chip.tsx +0 -843
- package/src/components/choice-card.tsx +0 -544
- package/src/components/column-mapper-labels.ts +0 -38
- package/src/components/column-mapper.tsx +0 -655
- package/src/components/combobox-core.tsx +0 -1321
- package/src/components/combobox-suggestions.tsx +0 -131
- package/src/components/combobox.tsx +0 -716
- package/src/components/confirm-context.ts +0 -7
- package/src/components/confirm-dialog-labels.ts +0 -13
- package/src/components/confirm-dialog.tsx +0 -341
- package/src/components/copy-button-labels.ts +0 -13
- package/src/components/copy-button.tsx +0 -192
- package/src/components/country-select-labels.ts +0 -11
- package/src/components/country-select.tsx +0 -539
- package/src/components/currency-option-list.tsx +0 -180
- package/src/components/currency-select.tsx +0 -341
- package/src/components/danger-confirm-labels.ts +0 -20
- package/src/components/danger-confirm.tsx +0 -934
- package/src/components/data-table-cells.tsx +0 -118
- package/src/components/data-table-column-settings.tsx +0 -198
- package/src/components/data-table-filter-popover.tsx +0 -281
- package/src/components/data-table-filters.ts +0 -287
- package/src/components/data-table-fit.ts +0 -301
- package/src/components/data-table-groups.tsx +0 -288
- package/src/components/data-table-head.tsx +0 -280
- package/src/components/data-table-labels.ts +0 -198
- package/src/components/data-table-leading-row.tsx +0 -58
- package/src/components/data-table-mobile.tsx +0 -1117
- package/src/components/data-table-pagination.tsx +0 -202
- package/src/components/data-table-resize.ts +0 -188
- package/src/components/data-table-row-actions.tsx +0 -302
- package/src/components/data-table-row.tsx +0 -496
- package/src/components/data-table-selection.ts +0 -71
- package/src/components/data-table-shared.tsx +0 -287
- package/src/components/data-table-sort.ts +0 -163
- package/src/components/data-table-virtual.ts +0 -576
- package/src/components/data-table.tsx +0 -2598
- package/src/components/date-field.tsx +0 -684
- package/src/components/date-format-setting.tsx +0 -64
- package/src/components/date-picker.tsx +0 -404
- package/src/components/date-range-picker.tsx +0 -518
- package/src/components/description-list-labels.ts +0 -9
- package/src/components/description-list.tsx +0 -386
- package/src/components/dialog-frame-labels.ts +0 -7
- package/src/components/dialog-frame.tsx +0 -276
- package/src/components/disclosure.tsx +0 -476
- package/src/components/dropdown.tsx +0 -461
- package/src/components/empty-state.tsx +0 -136
- package/src/components/entity-combobox.tsx +0 -422
- package/src/components/error-boundary-labels.ts +0 -20
- package/src/components/error-boundary.tsx +0 -675
- package/src/components/facing-pair.ts +0 -93
- package/src/components/field-base-labels.ts +0 -20
- package/src/components/field-base.tsx +0 -656
- package/src/components/field-parts.tsx +0 -825
- package/src/components/field-strip.tsx +0 -129
- package/src/components/field.tsx +0 -206
- package/src/components/file-button.tsx +0 -295
- package/src/components/file-dropzone.tsx +0 -559
- package/src/components/floating-panel-labels.ts +0 -10
- package/src/components/floating-panel.tsx +0 -828
- package/src/components/focus-ring.ts +0 -16
- package/src/components/form-actions-labels.ts +0 -11
- package/src/components/form-actions.tsx +0 -578
- package/src/components/full-bleed-dialog.tsx +0 -294
- package/src/components/grouped-picker.tsx +0 -184
- package/src/components/help-popover.tsx +0 -117
- package/src/components/hover-menu.tsx +0 -343
- package/src/components/iban-input-labels.ts +0 -14
- package/src/components/iban-input.tsx +0 -236
- package/src/components/icon-button.tsx +0 -959
- package/src/components/icon-picker-labels.ts +0 -13
- package/src/components/icon-picker.tsx +0 -232
- package/src/components/image-grid-labels.ts +0 -11
- package/src/components/image-grid.tsx +0 -202
- package/src/components/inline-confirm.tsx +0 -116
- package/src/components/inline-edit-field-labels.ts +0 -11
- package/src/components/inline-edit-field.tsx +0 -552
- package/src/components/inline-entity-combobox.tsx +0 -849
- package/src/components/input.tsx +0 -394
- package/src/components/jump-calendar.tsx +0 -265
- package/src/components/language-select.tsx +0 -93
- package/src/components/legal-labels.ts +0 -105
- package/src/components/legal-page.tsx +0 -711
- package/src/components/legal.tsx +0 -668
- package/src/components/lightbox-labels.ts +0 -18
- package/src/components/lightbox.tsx +0 -399
- package/src/components/line-items-labels.ts +0 -14
- package/src/components/line-items.tsx +0 -602
- package/src/components/list-labels.ts +0 -12
- package/src/components/list.tsx +0 -870
- package/src/components/loading-state.tsx +0 -78
- package/src/components/measured-grid-labels.ts +0 -25
- package/src/components/measured-grid.tsx +0 -837
- package/src/components/menu-item.tsx +0 -241
- package/src/components/mini-calendar-labels.ts +0 -17
- package/src/components/mini-calendar.tsx +0 -789
- package/src/components/modal.tsx +0 -505
- package/src/components/money-draft.ts +0 -83
- package/src/components/money-field.tsx +0 -76
- package/src/components/month-grid.tsx +0 -229
- package/src/components/month-picker-labels.ts +0 -22
- package/src/components/month-picker.tsx +0 -1087
- package/src/components/multi-entity-combobox.tsx +0 -369
- package/src/components/multi-select.tsx +0 -376
- package/src/components/nav-pills.tsx +0 -198
- package/src/components/number-field.tsx +0 -327
- package/src/components/number-input.tsx +0 -558
- package/src/components/numeric-field.ts +0 -169
- package/src/components/numpad-sheet.tsx +0 -285
- package/src/components/one-time-code-input.tsx +0 -270
- package/src/components/page-contents-labels.ts +0 -9
- package/src/components/page-contents.tsx +0 -282
- package/src/components/page-header-context.ts +0 -8
- package/src/components/page-header.tsx +0 -298
- package/src/components/password-strength-labels.ts +0 -22
- package/src/components/password-strength.tsx +0 -241
- package/src/components/phone-input-labels.ts +0 -10
- package/src/components/phone-input.tsx +0 -282
- package/src/components/picker-sheet.tsx +0 -330
- package/src/components/pie-chart-labels.ts +0 -40
- package/src/components/pie-chart.tsx +0 -480
- package/src/components/popover-labels.ts +0 -14
- package/src/components/popover.tsx +0 -268
- package/src/components/progress-bar-labels.ts +0 -10
- package/src/components/progress-bar.tsx +0 -479
- package/src/components/qr-code.tsx +0 -76
- package/src/components/reauth-dialog-labels.ts +0 -13
- package/src/components/reauth-dialog.tsx +0 -265
- package/src/components/row-actions-labels.ts +0 -12
- package/src/components/row-actions.tsx +0 -795
- package/src/components/scroll-area.tsx +0 -123
- package/src/components/search-field.tsx +0 -192
- package/src/components/select.tsx +0 -294
- package/src/components/separator.tsx +0 -33
- package/src/components/series-chart-axes.ts +0 -342
- package/src/components/series-chart-budget.ts +0 -150
- package/src/components/series-chart-labels.ts +0 -33
- package/src/components/series-chart-thin.ts +0 -180
- package/src/components/series-chart-ticks.ts +0 -194
- package/src/components/series-chart.tsx +0 -1906
- package/src/components/server-wake-labels.ts +0 -11
- package/src/components/server-wake.tsx +0 -129
- package/src/components/settings-fields.tsx +0 -237
- package/src/components/share-card-labels.ts +0 -30
- package/src/components/share-card.tsx +0 -675
- package/src/components/signature-pad-labels.ts +0 -24
- package/src/components/signature-pad.tsx +0 -747
- package/src/components/signed-amount-labels.ts +0 -10
- package/src/components/signed-amount.tsx +0 -336
- package/src/components/skeleton.tsx +0 -80
- package/src/components/slider.tsx +0 -338
- package/src/components/sparkline-labels.ts +0 -14
- package/src/components/sparkline.tsx +0 -322
- package/src/components/spinner.tsx +0 -81
- package/src/components/stat-tile-labels.ts +0 -15
- package/src/components/stat-tile.tsx +0 -725
- package/src/components/status-dot.tsx +0 -170
- package/src/components/swatch-picker-labels.ts +0 -10
- package/src/components/swatch-picker.tsx +0 -283
- package/src/components/swipeable-row.tsx +0 -386
- package/src/components/switch.tsx +0 -273
- package/src/components/table-skeleton.tsx +0 -136
- package/src/components/table.tsx +0 -647
- package/src/components/tabs-labels.ts +0 -13
- package/src/components/tabs.tsx +0 -693
- package/src/components/text-link.tsx +0 -359
- package/src/components/text.tsx +0 -150
- package/src/components/textarea.tsx +0 -330
- package/src/components/tile-radio.tsx +0 -332
- package/src/components/time-input.tsx +0 -121
- package/src/components/toast-labels.ts +0 -12
- package/src/components/toast.tsx +0 -519
- package/src/components/toggle-group.tsx +0 -752
- package/src/components/toggle-legend.tsx +0 -394
- package/src/components/tooltip.tsx +0 -1149
- package/src/components/translation-review-editor.tsx +0 -290
- package/src/components/translation-review-labels.ts +0 -181
- package/src/components/translation-review-parts.tsx +0 -272
- package/src/components/translation-review.tsx +0 -1240
- package/src/components/tree-view.tsx +0 -589
- package/src/components/treemap-labels.ts +0 -47
- package/src/components/treemap-layout.ts +0 -210
- package/src/components/treemap.tsx +0 -1184
- package/src/components/trigger-aria.ts +0 -44
- package/src/components/use-anchor-dir.ts +0 -20
- package/src/components/use-mobile-reveal.ts +0 -62
- package/src/components/use-table-state.ts +0 -753
- package/src/components/user-avatar.tsx +0 -116
- package/src/components/wizard-stepper.tsx +0 -42
- package/src/components/write-lock-labels.ts +0 -10
- package/src/components/write-lock.tsx +0 -253
- package/src/currencies.ts +0 -70
- package/src/data-table.ts +0 -42
- package/src/demo/demo-banner.tsx +0 -153
- package/src/demo/demo-countdown.ts +0 -136
- package/src/demo/demo-ended.tsx +0 -90
- package/src/demo/demo-labels.ts +0 -78
- package/src/demo/demo-session.ts +0 -32
- package/src/demo/demo-start.tsx +0 -156
- package/src/eslint/index.ts +0 -161
- package/src/eslint/role-utilities.generated.ts +0 -146
- package/src/eslint/role-utilities.ts +0 -233
- package/src/feedback/feedback-attachment-download.tsx +0 -77
- package/src/feedback/feedback-attachment-labels.ts +0 -37
- package/src/feedback/feedback-attachment.tsx +0 -1239
- package/src/feedback/feedback-capture.ts +0 -287
- package/src/feedback/feedback-comment-thread.tsx +0 -353
- package/src/feedback/feedback-context-labels.ts +0 -10
- package/src/feedback/feedback-context.tsx +0 -213
- package/src/feedback/feedback-crash.ts +0 -547
- package/src/feedback/feedback-dialog-labels.ts +0 -29
- package/src/feedback/feedback-dialog.tsx +0 -440
- package/src/feedback/feedback-entry-file.tsx +0 -150
- package/src/feedback/feedback-inbox.tsx +0 -552
- package/src/feedback/feedback-labels.ts +0 -144
- package/src/feedback/feedback-menu-labels.ts +0 -12
- package/src/feedback/feedback-menu.tsx +0 -177
- package/src/feedback/feedback-mutation.ts +0 -20
- package/src/feedback/feedback-page-link.ts +0 -90
- package/src/feedback/feedback-public-labels.ts +0 -81
- package/src/feedback/feedback-public-list.tsx +0 -524
- package/src/feedback/feedback-public-switch.tsx +0 -102
- package/src/feedback/feedback-public-types.ts +0 -101
- package/src/feedback/feedback-record.ts +0 -423
- package/src/feedback/feedback-replies-context.ts +0 -9
- package/src/feedback/feedback-replies.tsx +0 -343
- package/src/feedback/feedback-rework-entry-chip.tsx +0 -18
- package/src/feedback/feedback-row-detail-labels.ts +0 -30
- package/src/feedback/feedback-row-detail.tsx +0 -858
- package/src/feedback/feedback-status-undo.ts +0 -109
- package/src/feedback/feedback-submit-dialog.tsx +0 -118
- package/src/feedback/feedback-submit.tsx +0 -237
- package/src/feedback/feedback-swipe.tsx +0 -192
- package/src/feedback/feedback-table-labels.ts +0 -27
- package/src/feedback/feedback-table.tsx +0 -912
- package/src/feedback/feedback-thread-labels.ts +0 -22
- package/src/feedback/feedback-thread-parts-labels.ts +0 -41
- package/src/feedback/feedback-thread.tsx +0 -905
- package/src/feedback/feedback-vocabulary.ts +0 -263
- package/src/feedback/feedback-vote-button.tsx +0 -124
- package/src/feedback.ts +0 -116
- package/src/hooks/use-anchored-panel.ts +0 -396
- package/src/hooks/use-anchored-rect.ts +0 -77
- package/src/hooks/use-announce.ts +0 -85
- package/src/hooks/use-authed-src.ts +0 -167
- package/src/hooks/use-body-scroll-lock.ts +0 -119
- package/src/hooks/use-breakpoint.ts +0 -133
- package/src/hooks/use-close-transition.ts +0 -107
- package/src/hooks/use-copy-to-clipboard.ts +0 -122
- package/src/hooks/use-debounce.ts +0 -114
- package/src/hooks/use-dismiss.ts +0 -371
- package/src/hooks/use-document-title.ts +0 -33
- package/src/hooks/use-file-drop.ts +0 -121
- package/src/hooks/use-file-picker-labels.ts +0 -28
- package/src/hooks/use-file-picker.tsx +0 -359
- package/src/hooks/use-focus-trap.ts +0 -199
- package/src/hooks/use-hotkey.ts +0 -189
- package/src/hooks/use-large-text.ts +0 -41
- package/src/hooks/use-long-press.ts +0 -140
- package/src/hooks/use-media-query.ts +0 -39
- package/src/hooks/use-mounted.ts +0 -39
- package/src/hooks/use-noindex.ts +0 -37
- package/src/hooks/use-overlay-history.ts +0 -714
- package/src/hooks/use-row-swipe.ts +0 -207
- package/src/hooks/use-search-param-state.ts +0 -434
- package/src/hooks/use-windowed-rows.ts +0 -225
- package/src/i18n/defaults.ts +0 -267
- package/src/i18n/german.ts +0 -2057
- package/src/i18n/kit-labels.tsx +0 -1003
- package/src/i18n/languages.ts +0 -349
- package/src/i18n/locales/de-CH.ts +0 -24
- package/src/i18n/locales/en.ts +0 -267
- package/src/i18n/locales/es.ts +0 -1997
- package/src/i18n/locales/fr.ts +0 -2035
- package/src/i18n/locales/hu.ts +0 -2002
- package/src/i18n/locales/it.ts +0 -2012
- package/src/i18n/locales/zh.ts +0 -1910
- package/src/i18n/plurals.ts +0 -86
- package/src/i18n/review.ts +0 -475
- package/src/i18n/shared-labels.ts +0 -138
- package/src/i18n/swiss.ts +0 -29
- package/src/index.ts +0 -1179
- package/src/landing/access.ts +0 -93
- package/src/landing/landing-actions.tsx +0 -97
- package/src/landing/landing-labels.ts +0 -59
- package/src/landing/landing-sections.tsx +0 -341
- package/src/landing/page-seo.ts +0 -261
- package/src/landing/public-header.tsx +0 -121
- package/src/landing/public-page.tsx +0 -106
- package/src/landing/routing.tsx +0 -225
- package/src/lib/broadcast.ts +0 -52
- package/src/lib/calc.ts +0 -323
- package/src/lib/chip-edge-snap.ts +0 -212
- package/src/lib/clipboard-minus.ts +0 -107
- package/src/lib/clipping.ts +0 -34
- package/src/lib/cn.ts +0 -28
- package/src/lib/column-mapping.ts +0 -234
- package/src/lib/countries.ts +0 -91
- package/src/lib/data-attributes.ts +0 -14
- package/src/lib/date-format.ts +0 -227
- package/src/lib/dates.ts +0 -266
- package/src/lib/day-format.ts +0 -96
- package/src/lib/decimal-marks.ts +0 -108
- package/src/lib/describe-failure.ts +0 -18
- package/src/lib/device-settings.ts +0 -147
- package/src/lib/direction.ts +0 -74
- package/src/lib/document-navigation.ts +0 -17
- package/src/lib/document-title.ts +0 -41
- package/src/lib/download.ts +0 -172
- package/src/lib/float-clearance.ts +0 -70
- package/src/lib/floating-stack.ts +0 -70
- package/src/lib/focus-left.ts +0 -156
- package/src/lib/format.ts +0 -522
- package/src/lib/http-status.ts +0 -38
- package/src/lib/iban.ts +0 -251
- package/src/lib/ime.ts +0 -24
- package/src/lib/intl-cache.ts +0 -25
- package/src/lib/iso-day.ts +0 -13
- package/src/lib/lazy-with-fallback.ts +0 -82
- package/src/lib/logger.ts +0 -69
- package/src/lib/minus.ts +0 -50
- package/src/lib/path-pattern.ts +0 -55
- package/src/lib/person-name.ts +0 -155
- package/src/lib/phone.ts +0 -208
- package/src/lib/plain-text.ts +0 -22
- package/src/lib/presence.ts +0 -18
- package/src/lib/qr-encode.ts +0 -444
- package/src/lib/quiet-focus.ts +0 -32
- package/src/lib/reduced-motion.ts +0 -22
- package/src/lib/refs.ts +0 -22
- package/src/lib/round.ts +0 -43
- package/src/lib/safe-storage.ts +0 -119
- package/src/lib/server-wake.ts +0 -315
- package/src/lib/session-refresh.ts +0 -472
- package/src/lib/share-format.ts +0 -18
- package/src/lib/status-tone.ts +0 -43
- package/src/lib/strip-fade.ts +0 -287
- package/src/lib/table-text.ts +0 -554
- package/src/lib/text-case.ts +0 -19
- package/src/lib/text-match.ts +0 -169
- package/src/lib/thenable.ts +0 -19
- package/src/lib/translation-review.ts +0 -717
- package/src/notifications/device-zone-report.ts +0 -67
- package/src/notifications/feedback-notification-types-labels.ts +0 -33
- package/src/notifications/feedback-notification-types.ts +0 -71
- package/src/notifications/notification-bell.tsx +0 -119
- package/src/notifications/notification-inbox.tsx +0 -309
- package/src/notifications/notification-parts.tsx +0 -81
- package/src/notifications/notification-types-setting.tsx +0 -406
- package/src/notifications/notification-types.ts +0 -89
- package/src/notifications/notifications-labels.ts +0 -287
- package/src/notifications/push-device-setting.tsx +0 -230
- package/src/notifications/push-devices-setting.tsx +0 -374
- package/src/notifications/push-worker.ts +0 -168
- package/src/notifications/quiet-hours-setting.tsx +0 -238
- package/src/notifications/unsubscribe-panel.tsx +0 -200
- package/src/notifications/use-push-device.ts +0 -448
- package/src/offline/local-first.ts +0 -100
- package/src/offline/pwa-update-prompt-labels.ts +0 -9
- package/src/offline/pwa-update-prompt.tsx +0 -78
- package/src/offline/query-persistence.ts +0 -391
- package/src/offline/service-worker-updates.ts +0 -81
- package/src/offline/shared-computer-labels.ts +0 -8
- package/src/offline/shared-computer.tsx +0 -87
- package/src/offline/sign-out-pending-dialog-labels.ts +0 -21
- package/src/offline/sign-out-pending-dialog.tsx +0 -135
- package/src/offline.ts +0 -37
- package/src/push-worker.ts +0 -25
- package/src/rhf/fields.tsx +0 -2187
- package/src/rhf/form-core.tsx +0 -324
- package/src/rhf/form.tsx +0 -12
- package/src/rhf/line-items.tsx +0 -135
- package/src/rhf/use-rhf-wizard-step.ts +0 -104
- package/src/rhf.ts +0 -21
- package/src/search/command-palette-labels.ts +0 -16
- package/src/search/command-palette.tsx +0 -624
- package/src/search/global-search-labels.ts +0 -13
- package/src/search/global-search.tsx +0 -660
- package/src/search/search-index.ts +0 -283
- package/src/search/use-command-key.ts +0 -23
- package/src/search.ts +0 -14
- package/src/settings/device-reset-setting-labels.ts +0 -20
- package/src/settings/device-reset-setting.tsx +0 -116
- package/src/settings/settings-card-classes.ts +0 -11
- package/src/settings/settings-catalogue.ts +0 -150
- package/src/settings/settings-context.ts +0 -33
- package/src/settings/settings-heading.tsx +0 -67
- package/src/settings/settings-labels.ts +0 -87
- package/src/settings/settings-layout.tsx +0 -471
- package/src/settings/settings-section.tsx +0 -108
- package/src/settings/use-account-appearance.ts +0 -148
- package/src/settings/use-account-language.ts +0 -146
- package/src/settings/use-settings-focus.ts +0 -128
- package/src/settings/use-settings-route.ts +0 -258
- package/src/shell/account-menu-language.tsx +0 -130
- package/src/shell/account-menu-text-size.tsx +0 -80
- package/src/shell/admin-menu.tsx +0 -183
- package/src/shell/app-shell-labels.ts +0 -11
- package/src/shell/app-shell.tsx +0 -1560
- package/src/shell/auth-layout.tsx +0 -186
- package/src/shell/company-switcher-labels.ts +0 -13
- package/src/shell/company-switcher.tsx +0 -136
- package/src/shell/dev-menu.tsx +0 -257
- package/src/shell/fill-height.tsx +0 -45
- package/src/shell/language-code.ts +0 -5
- package/src/shell/option-switcher-menu.tsx +0 -84
- package/src/shell/sync-status-indicator.tsx +0 -303
- package/src/shell/top-bar-actions.tsx +0 -87
- package/src/shell/top-bar-brand.tsx +0 -78
- package/src/shell/top-bar-parts-labels.ts +0 -148
- package/src/shell/top-bar.tsx +0 -40
- package/src/shell/topbar-action-menu.tsx +0 -567
- package/src/shell/topbar-controls.tsx +0 -269
- package/src/shell/tour-menu.tsx +0 -187
- package/src/shell.ts +0 -108
- package/src/sync/db.ts +0 -129
- package/src/sync/engine.ts +0 -1011
- package/src/sync/hooks.ts +0 -98
- package/src/sync/testing.ts +0 -73
- package/src/sync/wire.ts +0 -61
- package/src/sync.ts +0 -37
- package/src/table-text.ts +0 -8
- package/src/testing/css-variables.generated.ts +0 -112
- package/src/testing/css-variables.ts +0 -189
- package/src/testing/index.ts +0 -29
- package/src/testing/react.ts +0 -58
- package/src/testing/tour.ts +0 -41
- package/src/testing/viewport.ts +0 -357
- package/src/theme/chart-palette.ts +0 -232
- package/src/theme/color.ts +0 -272
- package/src/theme/contrast-tokens.ts +0 -268
- package/src/theme/contrast.ts +0 -250
- package/src/theme/palette-derive.ts +0 -825
- package/src/theme/palette-presets.ts +0 -544
- package/src/theme/palette-store.ts +0 -108
- package/src/theme/text-size.ts +0 -289
- package/src/theme/theme-store.ts +0 -157
- package/src/tour/tour-catalogue-labels.ts +0 -75
- package/src/tour/tour-catalogue.tsx +0 -335
- package/src/tour/tour-dock.ts +0 -134
- package/src/tour/tour-engine.ts +0 -37
- package/src/tour/tour-gates.ts +0 -218
- package/src/tour/tour-guide-button.tsx +0 -64
- package/src/tour/tour-guide-labels.ts +0 -15
- package/src/tour/tour-info.ts +0 -144
- package/src/tour/tour-labels.ts +0 -23
- package/src/tour/tour-overlay.tsx +0 -1170
- package/src/tour/tour.tsx +0 -750
- package/src/tour/use-tour-progress.ts +0 -671
- package/src/tour/use-tour-url-sync.ts +0 -266
- package/src/tour.ts +0 -21
- package/src/vite-env.d.ts +0 -23
- package/src/wizard/stepper-nav.tsx +0 -360
- package/src/wizard/types.ts +0 -275
- package/src/wizard/use-wizard.ts +0 -560
- package/src/wizard/validation.ts +0 -39
- package/src/wizard/wizard-context.tsx +0 -74
- package/src/wizard/wizard-labels.ts +0 -29
- package/src/wizard/wizard-step.tsx +0 -76
- package/src/wizard/wizard-summary.tsx +0 -84
- package/src/wizard.ts +0 -15
package/src/landing/routing.tsx
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
import type { ReactNode } from "react";
|
|
3
|
-
import { Navigate, Outlet, useLocation } from "react-router";
|
|
4
|
-
|
|
5
|
-
import { matchesPathPattern, routerPathname } from "../lib/path-pattern";
|
|
6
|
-
import { readStored, removeStored, writeStored } from "../lib/safe-storage";
|
|
7
|
-
import type { LandingSession } from "./landing-actions";
|
|
8
|
-
import { LoadingState } from "../components/loading-state";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 0.31.1: a session that is still being restored — an app whose access token lives in
|
|
12
|
-
* memory reads it back from its refresh token first (kastlan's 0.31 adoption). Until
|
|
13
|
-
* then `/` neither shows the landing nor resumes, and a public page neither shows nor
|
|
14
|
-
* redirects: both render `loading` instead.
|
|
15
|
-
*/
|
|
16
|
-
export type RoutingSession = LandingSession | "loading";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The public routes' logic (docs/landing-demo-harmonization.md §3): what `/` shows,
|
|
20
|
-
* which pages a session skips, and the page a session resumes on — keksdose's
|
|
21
|
-
* `RootEntry`, `RedirectIfAuthed` and use-last-visited-page.ts, for every app.
|
|
22
|
-
* Router-aware (react-router), so they belong to the `./shell` entry.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/* ── ?next= ──────────────────────────────────────────────────────────────── */
|
|
26
|
-
|
|
27
|
-
/** The query parameter that carries "where I was actually trying to go" through the
|
|
28
|
-
* sign-in bounce (keksdose's `NEXT_PARAM`). */
|
|
29
|
-
export const NEXT_PARAM = "next";
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* A `?next=` value that is safe to navigate to, or null.
|
|
33
|
-
*
|
|
34
|
-
* Same-origin PATHS only, decided by the URL PARSER rather than by string prefix —
|
|
35
|
-
* this is the open-redirect check, and it is the reason this lives in one place
|
|
36
|
-
* instead of at each call site.
|
|
37
|
-
*
|
|
38
|
-
* The prefix version ("starts with `/`, does not start with `//`") let two shapes
|
|
39
|
-
* through that the browser resolves cross-origin, because the WHATWG parser does not
|
|
40
|
-
* read them as text: a backslash after the leading slash counts as a second slash for
|
|
41
|
-
* a special scheme, so `/\evil.example` resolves to `https://evil.example/`; and tab,
|
|
42
|
-
* LF and CR are STRIPPED anywhere in the input before parsing, so `/<TAB>/evil.example`
|
|
43
|
-
* becomes `//evil.example`. Asking the same parser the browser will use closes every
|
|
44
|
-
* such shape at once, including ones nobody has thought of yet, and it normalises what
|
|
45
|
-
* comes back instead of echoing the caller's spelling.
|
|
46
|
-
*
|
|
47
|
-
* keksdose's (shared/hooks/use-last-visited-page.ts), verbatim but for the fallback
|
|
48
|
-
* origin.
|
|
49
|
-
*/
|
|
50
|
-
export function safeNextPath(raw: string | null | undefined): string | null {
|
|
51
|
-
if (!raw) return null;
|
|
52
|
-
const base = typeof window !== "undefined" ? window.location.origin : "https://kit.invalid";
|
|
53
|
-
try {
|
|
54
|
-
const url = new URL(raw, base);
|
|
55
|
-
if (url.origin !== base) return null;
|
|
56
|
-
return `${url.pathname}${url.search}${url.hash}`;
|
|
57
|
-
} catch {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/* ── The last visited page (§3.2) ────────────────────────────────────────── */
|
|
63
|
-
|
|
64
|
-
/** A path to leave out: a string is the path and everything under it (`/demo` is
|
|
65
|
-
* `/demo` and `/demo/ended`; `/` is only `/`), a RegExp is tested on the pathname. Both
|
|
66
|
-
* as React Router matches a route: case-insensitive (a RegExp gets the `i` flag) and on
|
|
67
|
-
* the percent-decoded path (0.52). */
|
|
68
|
-
export type PathPattern = string | RegExp;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* The pages never recorded as a resume target (§3.2): the landing (`/`, `/welcome`), the
|
|
72
|
-
* auth pages, the demo's own (`/demo*`) and the legal pages. The 404 has no path of its
|
|
73
|
-
* own — call {@link useLastVisitedPage} inside the signed-in layout, as keksdose does,
|
|
74
|
-
* and it never sees one. The app adds its own one-shot routes (keksdose:
|
|
75
|
-
* `/banks/callback`, `/join`, `/share-target`) through `exclude`.
|
|
76
|
-
*/
|
|
77
|
-
export const DEFAULT_LAST_VISITED_EXCLUDES: readonly PathPattern[] = Object.freeze([
|
|
78
|
-
"/",
|
|
79
|
-
"/welcome",
|
|
80
|
-
"/login",
|
|
81
|
-
"/register",
|
|
82
|
-
"/forgot-password",
|
|
83
|
-
"/reset-password",
|
|
84
|
-
"/verify-email",
|
|
85
|
-
"/demo",
|
|
86
|
-
"/impressum",
|
|
87
|
-
"/privacy",
|
|
88
|
-
"/terms",
|
|
89
|
-
]);
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Whether `pathname` is one of the defaults or the app's `exclude` — read as the ROUTER
|
|
93
|
-
* reads it, decoded and case-insensitive (lib/path-pattern). This module's own copy of the
|
|
94
|
-
* rule compared the raw pathname case-sensitively after the feedback guard's copy had
|
|
95
|
-
* learnt both, and `exclude: ["/banks/callback"]` recorded `/Banks/Callback?code=…` as the
|
|
96
|
-
* page the next launch resumes on (0.52 code review, lib/path-pattern.ts). One rule now.
|
|
97
|
-
*/
|
|
98
|
-
function isExcluded(pathname: string, exclude: readonly PathPattern[]): boolean {
|
|
99
|
-
const path = routerPathname(pathname);
|
|
100
|
-
const named = (pattern: PathPattern) => matchesPathPattern(path, pattern);
|
|
101
|
-
return DEFAULT_LAST_VISITED_EXCLUDES.some(named) || exclude.some(named);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export interface LastVisitedPageOptions {
|
|
105
|
-
/** The device key: `<app>.lastVisitedPage` (§3.2), one per app on the origin. */
|
|
106
|
-
key: string;
|
|
107
|
-
/** The app's own paths to leave out, ON TOP of {@link DEFAULT_LAST_VISITED_EXCLUDES}. */
|
|
108
|
-
exclude?: readonly PathPattern[];
|
|
109
|
-
/** `false` records nothing — while the session is still being restored, say. */
|
|
110
|
-
enabled?: boolean;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Remember the page a session is on (path and query), on every navigation, so `/` — a
|
|
115
|
-
* revisit, a fresh sign-in, the installed PWA, whose `start_url` is `/` — resumes there
|
|
116
|
-
* (§3.2, keksdose feedback #59). Device-local, in `localStorage` under `key`; a blocked
|
|
117
|
-
* storage records nothing.
|
|
118
|
-
*
|
|
119
|
-
* Call it once in the signed-in layout. The excluded paths are never written, so a
|
|
120
|
-
* one-shot page (a bank callback, an invitation link) never becomes the place the next
|
|
121
|
-
* launch opens on.
|
|
122
|
-
*/
|
|
123
|
-
export function useLastVisitedPage({ key, exclude = [], enabled = true }: LastVisitedPageOptions): void {
|
|
124
|
-
const { pathname, search } = useLocation();
|
|
125
|
-
// Decided here, so the effect depends on the answer and not on an `exclude` array the
|
|
126
|
-
// caller likely builds inline.
|
|
127
|
-
const skip = !enabled || isExcluded(pathname, exclude);
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
if (skip) return;
|
|
130
|
-
writeStored(key, pathname + search);
|
|
131
|
-
}, [key, pathname, search, skip]);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* The page {@link useLastVisitedPage} remembered under `key` — checked by
|
|
136
|
-
* {@link safeNextPath}, so a value someone planted in storage cannot leave the origin —
|
|
137
|
-
* or `fallback` (default `null`) when there is none or storage is blocked. A string
|
|
138
|
-
* fallback narrows the answer to a string, for react-router's `to`.
|
|
139
|
-
*/
|
|
140
|
-
export function readLastVisitedPage(key: string, fallback: string): string;
|
|
141
|
-
export function readLastVisitedPage(key: string, fallback?: null): string | null;
|
|
142
|
-
export function readLastVisitedPage(key: string, fallback: string | null = null): string | null {
|
|
143
|
-
return safeNextPath(readStored(key)) ?? fallback;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/** Forget the remembered page — on an explicit sign-out, so the next account does not
|
|
147
|
-
* resume on the previous one's page. */
|
|
148
|
-
export function clearLastVisitedPage(key: string): void {
|
|
149
|
-
removeStored(key);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/* ── RootEntry ───────────────────────────────────────────────────────────── */
|
|
153
|
-
|
|
154
|
-
export interface RootEntryProps {
|
|
155
|
-
/** Without a session `/` is the landing; with one (real or demo) it resumes;
|
|
156
|
-
* `"loading"` while the app restores one. */
|
|
157
|
-
session: RoutingSession;
|
|
158
|
-
/** What shows while `session` is `"loading"`. Default: the kit's `LoadingState`. */
|
|
159
|
-
loading?: ReactNode;
|
|
160
|
-
/** The remembered page — `readLastVisitedPage(key)`. */
|
|
161
|
-
resumePath?: string | null;
|
|
162
|
-
/** The landing page element. */
|
|
163
|
-
landing: ReactNode;
|
|
164
|
-
/** The app's home: where a session goes with nothing to resume (keksdose `/budget`,
|
|
165
|
-
* kastlan and Kurvenschmiede `/dashboard`). */
|
|
166
|
-
home: string;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* The `/` route (§3.1): the landing for a visitor, and for a session — real or demo —
|
|
171
|
-
* the last visited page, else the app's home. Indexed and canonical `/` for the visitor;
|
|
172
|
-
* a crawler never has a session, so for it `/` is stable.
|
|
173
|
-
*
|
|
174
|
-
* keksdose showed a session with nothing remembered the landing; the contract sends it
|
|
175
|
-
* home instead, because a session at `/` came to use the app. The landing stays one tap
|
|
176
|
-
* away at `/welcome`, where the signed-in brand link points.
|
|
177
|
-
*/
|
|
178
|
-
export function RootEntry({ session, resumePath, landing, home, loading }: RootEntryProps) {
|
|
179
|
-
if (session === "loading") return <>{loading ?? <LoadingState />}</>;
|
|
180
|
-
if (session === "none") return <>{landing}</>;
|
|
181
|
-
const resume = safeNextPath(resumePath);
|
|
182
|
-
return <Navigate to={resume && resume !== "/" ? resume : home} replace />;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/* ── RedirectIfAuthed ────────────────────────────────────────────────────── */
|
|
186
|
-
|
|
187
|
-
export interface RedirectIfAuthedProps {
|
|
188
|
-
/** `"loading"` while the app restores a session: neither the page nor a redirect. */
|
|
189
|
-
session: RoutingSession;
|
|
190
|
-
/** What shows while `session` is `"loading"`. Default: the kit's `LoadingState`. */
|
|
191
|
-
loading?: ReactNode;
|
|
192
|
-
/**
|
|
193
|
-
* Let a DEMO session through (§5.6): on `/login`, `/register` and the app's invitation
|
|
194
|
-
* pages, so a demo visitor can sign in or accept an invitation — a successful one
|
|
195
|
-
* replaces the demo session. Default `false`: on `/demo` a live demo continues instead
|
|
196
|
-
* of starting a second one (§5.2), and on `/forgot-password` a demo has no password.
|
|
197
|
-
*/
|
|
198
|
-
allowDemo?: boolean;
|
|
199
|
-
/** Where a redirected session goes: the resume target —
|
|
200
|
-
* `readLastVisitedPage(key, home)`. A safe `?next=` goes first. */
|
|
201
|
-
fallback: string;
|
|
202
|
-
/** The page. Left out, an `<Outlet />`: the component is a layout route around the
|
|
203
|
-
* public pages, as in keksdose. */
|
|
204
|
-
children?: ReactNode;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Public pages a session skips (§3.1): a signed-in visitor at `/login` goes back into
|
|
209
|
-
* the app, to a safe `?next=` when the URL carries one (a share invitation or a push
|
|
210
|
-
* deep link opened with a live session in another tab — keksdose) and else to
|
|
211
|
-
* `fallback`.
|
|
212
|
-
*
|
|
213
|
-
* A demo session passes where `allowDemo` says so (§5.6). Mount one wrapper with
|
|
214
|
-
* `allowDemo` around `/login`, `/register` and the invitation pages, and one without
|
|
215
|
-
* around `/demo` (and `/forgot-password`).
|
|
216
|
-
*/
|
|
217
|
-
export function RedirectIfAuthed({ session, allowDemo = false, fallback, children, loading }: RedirectIfAuthedProps) {
|
|
218
|
-
const { search } = useLocation();
|
|
219
|
-
if (session === "loading") return <>{loading ?? <LoadingState />}</>;
|
|
220
|
-
if (session === "none" || (session === "demo" && allowDemo)) {
|
|
221
|
-
return children === undefined ? <Outlet /> : <>{children}</>;
|
|
222
|
-
}
|
|
223
|
-
const next = safeNextPath(new URLSearchParams(search).get(NEXT_PARAM));
|
|
224
|
-
return <Navigate to={next ?? fallback} replace />;
|
|
225
|
-
}
|
package/src/lib/broadcast.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* The cross-tab messages of the sync engine (the copy's new epoch after `forget()`) and of the
|
|
3
|
-
* query copy (`clear`), refactor audit 2026-10-30 FLW-1. 0.52 code review
|
|
4
|
-
* (src/sync/engine.ts, src/offline/query-persistence.ts): both wrote the open, the feature
|
|
5
|
-
* check, the try/catch and the close by hand, the listening side twice too — and the two
|
|
6
|
-
* listeners had drifted (only the query copy's let go of Node's worker).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Tell this origin's other tabs one thing over a `BroadcastChannel`, and let go of the
|
|
11
|
-
* channel at once.
|
|
12
|
-
*
|
|
13
|
-
* Best-effort by design: the message makes another tab stop sooner, and each caller has a
|
|
14
|
-
* fallback that holds without it (the epoch in `meta`, the key deleted from storage).
|
|
15
|
-
*
|
|
16
|
-
* The message goes out on a channel of its own, so a caller that listens on `name` itself
|
|
17
|
-
* hears it too, like every other channel of that name in this tab: it ignores its own.
|
|
18
|
-
*/
|
|
19
|
-
export function postOnce(name: string, message: unknown): void {
|
|
20
|
-
// Older browsers and some test environments have none: nothing is posted.
|
|
21
|
-
if (typeof BroadcastChannel === "undefined") return;
|
|
22
|
-
try {
|
|
23
|
-
const channel = new BroadcastChannel(name);
|
|
24
|
-
try {
|
|
25
|
-
channel.postMessage(message);
|
|
26
|
-
} finally {
|
|
27
|
-
channel.close();
|
|
28
|
-
}
|
|
29
|
-
} catch {
|
|
30
|
-
/* best-effort: a message that cannot be cloned, a channel refused (an opaque origin) */
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Hear what this origin's other tabs post on `name` until the returned function is called.
|
|
36
|
-
* Nothing is heard (and closing is a no-op) where there is no BroadcastChannel or none can be
|
|
37
|
-
* opened (an opaque origin): each caller has a fallback that holds without it.
|
|
38
|
-
*/
|
|
39
|
-
export function listenOn(name: string, onMessage: (data: unknown) => void): () => void {
|
|
40
|
-
if (typeof BroadcastChannel === "undefined") return () => undefined;
|
|
41
|
-
let channel: BroadcastChannel;
|
|
42
|
-
try {
|
|
43
|
-
channel = new BroadcastChannel(name);
|
|
44
|
-
} catch {
|
|
45
|
-
return () => undefined;
|
|
46
|
-
}
|
|
47
|
-
// Node's channel (an app's tests) holds its worker open while it listens, and a test that
|
|
48
|
-
// never stops the listener would keep it listening. Browsers have no `unref`.
|
|
49
|
-
(channel as BroadcastChannel & { unref?: () => void }).unref?.();
|
|
50
|
-
channel.onmessage = ({ data }: MessageEvent<unknown>) => onMessage(data);
|
|
51
|
-
return () => channel.close();
|
|
52
|
-
}
|
package/src/lib/calc.ts
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A tiny, dependency-free arithmetic evaluator for the numeric input fields.
|
|
3
|
-
* It lets users type a calculation (e.g. "12.50+3.20" or "100/3") straight into
|
|
4
|
-
* an amount field, or build one in the calculator popover, and have it resolve
|
|
5
|
-
* to a number. Deliberately NOT backed by `eval`/`Function` — it's a hand-rolled
|
|
6
|
-
* tokenizer + recursive-descent parser over a closed grammar (digits, decimals,
|
|
7
|
-
* `+ - * /`, unary minus, parentheses), so no arbitrary code can run.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
type Token =
|
|
11
|
-
| { kind: "num"; value: number }
|
|
12
|
-
| { kind: "op"; value: "+" | "-" | "*" | "/" }
|
|
13
|
-
| { kind: "lparen" }
|
|
14
|
-
| { kind: "rparen" };
|
|
15
|
-
|
|
16
|
-
function tokenize(input: string): Token[] | null {
|
|
17
|
-
const tokens: Token[] = [];
|
|
18
|
-
let i = 0;
|
|
19
|
-
while (i < input.length) {
|
|
20
|
-
const ch = input[i];
|
|
21
|
-
if (ch === " ") {
|
|
22
|
-
i++;
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
if (ch === "+" || ch === "-" || ch === "*" || ch === "/") {
|
|
26
|
-
tokens.push({ kind: "op", value: ch });
|
|
27
|
-
i++;
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
if (ch === "(") {
|
|
31
|
-
tokens.push({ kind: "lparen" });
|
|
32
|
-
i++;
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
if (ch === ")") {
|
|
36
|
-
tokens.push({ kind: "rparen" });
|
|
37
|
-
i++;
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if ((ch >= "0" && ch <= "9") || ch === ".") {
|
|
41
|
-
let j = i;
|
|
42
|
-
let dotSeen = false;
|
|
43
|
-
while (j < input.length && ((input[j] >= "0" && input[j] <= "9") || input[j] === ".")) {
|
|
44
|
-
if (input[j] === ".") {
|
|
45
|
-
if (dotSeen) return null; // two dots in one number → invalid
|
|
46
|
-
dotSeen = true;
|
|
47
|
-
}
|
|
48
|
-
j++;
|
|
49
|
-
}
|
|
50
|
-
const num = Number(input.slice(i, j));
|
|
51
|
-
if (!Number.isFinite(num)) return null;
|
|
52
|
-
tokens.push({ kind: "num", value: num });
|
|
53
|
-
i = j;
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
return null; // unknown character
|
|
57
|
-
}
|
|
58
|
-
return tokens;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Recursive-descent parse honouring `* /` over `+ -` and left-associativity.
|
|
63
|
-
* Returns `null` for any malformed input (the `null` sentinel is safe because a
|
|
64
|
-
* valid result of 0 is distinct from it). Division by zero is treated as invalid.
|
|
65
|
-
*
|
|
66
|
-
* expr := term (('+' | '-') term)*
|
|
67
|
-
* term := factor (('*' | '/') factor)*
|
|
68
|
-
* factor := ('+' | '-') factor | number | '(' expr ')'
|
|
69
|
-
*/
|
|
70
|
-
function parse(tokens: Token[]): number | null {
|
|
71
|
-
let pos = 0;
|
|
72
|
-
|
|
73
|
-
function parseExpr(): number | null {
|
|
74
|
-
let value = parseTerm();
|
|
75
|
-
if (value === null) return null;
|
|
76
|
-
while (pos < tokens.length) {
|
|
77
|
-
const tok = tokens[pos];
|
|
78
|
-
if (tok.kind === "op" && (tok.value === "+" || tok.value === "-")) {
|
|
79
|
-
pos++;
|
|
80
|
-
const rhs = parseTerm();
|
|
81
|
-
if (rhs === null) return null;
|
|
82
|
-
value = tok.value === "+" ? value + rhs : value - rhs;
|
|
83
|
-
} else break;
|
|
84
|
-
}
|
|
85
|
-
return value;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function parseTerm(): number | null {
|
|
89
|
-
let value = parseFactor();
|
|
90
|
-
if (value === null) return null;
|
|
91
|
-
while (pos < tokens.length) {
|
|
92
|
-
const tok = tokens[pos];
|
|
93
|
-
if (tok.kind === "op" && (tok.value === "*" || tok.value === "/")) {
|
|
94
|
-
pos++;
|
|
95
|
-
const rhs = parseFactor();
|
|
96
|
-
if (rhs === null) return null;
|
|
97
|
-
if (tok.value === "/") {
|
|
98
|
-
if (rhs === 0) return null;
|
|
99
|
-
value = value / rhs;
|
|
100
|
-
} else {
|
|
101
|
-
value = value * rhs;
|
|
102
|
-
}
|
|
103
|
-
} else break;
|
|
104
|
-
}
|
|
105
|
-
return value;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function parseFactor(): number | null {
|
|
109
|
-
const tok = tokens[pos];
|
|
110
|
-
if (!tok) return null;
|
|
111
|
-
if (tok.kind === "op" && (tok.value === "+" || tok.value === "-")) {
|
|
112
|
-
pos++;
|
|
113
|
-
const operand = parseFactor();
|
|
114
|
-
if (operand === null) return null;
|
|
115
|
-
return tok.value === "-" ? -operand : operand;
|
|
116
|
-
}
|
|
117
|
-
if (tok.kind === "lparen") {
|
|
118
|
-
pos++;
|
|
119
|
-
const inner = parseExpr();
|
|
120
|
-
if (inner === null) return null;
|
|
121
|
-
if (tokens[pos]?.kind !== "rparen") return null;
|
|
122
|
-
pos++;
|
|
123
|
-
return inner;
|
|
124
|
-
}
|
|
125
|
-
if (tok.kind === "num") {
|
|
126
|
-
pos++;
|
|
127
|
-
return tok.value;
|
|
128
|
-
}
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const result = parseExpr();
|
|
133
|
-
if (result === null) return null;
|
|
134
|
-
if (pos !== tokens.length) return null; // leftover tokens → invalid
|
|
135
|
-
return result;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/** Evaluate an arithmetic string, returning `null` if it isn't a valid sum.
|
|
139
|
-
* Accepts the on-screen operator glyphs (`× ÷ −`) and comma decimals too. */
|
|
140
|
-
export function evaluateExpression(expr: string): number | null {
|
|
141
|
-
const normalized = expr
|
|
142
|
-
.replace(/×/g, "*")
|
|
143
|
-
.replace(/÷/g, "/")
|
|
144
|
-
.replace(/[−–—]/g, "-") // unicode minus / en / em dash → ascii
|
|
145
|
-
.replace(/,/g, ".")
|
|
146
|
-
.trim();
|
|
147
|
-
if (normalized === "") return null;
|
|
148
|
-
const tokens = tokenize(normalized);
|
|
149
|
-
if (tokens === null || tokens.length === 0) return null;
|
|
150
|
-
const result = parse(tokens);
|
|
151
|
-
if (result === null || !Number.isFinite(result)) return null;
|
|
152
|
-
return result;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** True when `s` carries arithmetic beyond a single leading minus — i.e. a plain
|
|
156
|
-
* number (or a lone negative like "-5") is NOT an expression, but "12+5" is.
|
|
157
|
-
* Used to decide whether a field's text should be evaluated on commit.
|
|
158
|
-
*
|
|
159
|
-
* The operator set is the one {@link evaluateExpression} accepts, on-screen glyphs
|
|
160
|
-
* included: the calculator keypad inserts `× ÷ −`, and a `−` that this said was not
|
|
161
|
-
* arithmetic went on to be read as a plain number — where the digits-only fallback
|
|
162
|
-
* in {@link commitExpression} silently ate it, turning "-42−−50" (= 8) into a bare
|
|
163
|
-
* 8 with no record that a sum had happened at all. */
|
|
164
|
-
export function looksLikeExpression(s: string): boolean {
|
|
165
|
-
const t = s.trim();
|
|
166
|
-
if (t === "") return false;
|
|
167
|
-
if (/^-?\d*[.,]?\d*$/.test(t)) return false; // plain (optionally negative) decimal
|
|
168
|
-
return /[+\-*/×÷−–—()]/.test(t.replace(/^-/, ""));
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/** Render an evaluated number back to a field-friendly string, trimming binary
|
|
172
|
-
* float noise (so 0.1 + 0.2 reads "0.3", not "0.30000000000000004").
|
|
173
|
-
*
|
|
174
|
-
* FIXED notation, always, and that is the whole point of the function rather than a
|
|
175
|
-
* detail of it. This used to end in `parseFloat(n.toFixed(10)).toString()`, and
|
|
176
|
-
* `Number.prototype.toString` switches to EXPONENT notation below 1e-6 and at or
|
|
177
|
-
* above 1e21 — an alphabet containing `e`, `+` and `-`. Neither function that reads a
|
|
178
|
-
* field's text back accepts it: {@link tokenize} rejects `e` as an unknown character
|
|
179
|
-
* and {@link sanitizeLive} deletes it. So {@link commitExpression} fell through to
|
|
180
|
-
* its digits-only cleanup, which stripped the `e` and CONCATENATED the mantissa to
|
|
181
|
-
* the exponent. A field committed its own output as a different number:
|
|
182
|
-
*
|
|
183
|
-
* "1/10000000" -> "1e-7" -> "17" (AmountInput: "6")
|
|
184
|
-
* "999999999999*999999999999" -> "9.99999999998e+23" -> "9.9999999999823"
|
|
185
|
-
*
|
|
186
|
-
* Both controls commit on blur AND on Enter, so Enter-then-click-away was enough on
|
|
187
|
-
* its own, it was silent, and it was in a money field.
|
|
188
|
-
*
|
|
189
|
-
* The invariant, which the test asserts directly rather than by example:
|
|
190
|
-
* **`commitExpression(formatResult(n))` equals `formatResult(n)` for every finite
|
|
191
|
-
* `n`.** Anything rendered here has to survive being read back. */
|
|
192
|
-
export function formatResult(n: number): string {
|
|
193
|
-
if (!Number.isFinite(n)) return "";
|
|
194
|
-
// At or above 1e21 `toFixed` gives up and hands back `toString`'s exponent form —
|
|
195
|
-
// but every double that large is an integer, so BigInt renders it exactly.
|
|
196
|
-
if (Math.abs(n) >= 1e21) return BigInt(n).toString();
|
|
197
|
-
return trimTrailingZeros(n.toFixed(10));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/** "15.7000000000" -> "15.7", "0.0000000000" -> "0". The ten decimals are where the
|
|
201
|
-
* binary float noise gets rounded off; this is only about not showing the padding. */
|
|
202
|
-
function trimTrailingZeros(fixed: string): string {
|
|
203
|
-
if (!fixed.includes(".")) return fixed;
|
|
204
|
-
const trimmed = fixed.replace(/0+$/, "").replace(/\.$/, "");
|
|
205
|
-
// `toFixed` keeps the sign on a magnitude that rounded away to nothing
|
|
206
|
-
// ("-0.0000000000"); `toString` did not, and "-0" in an amount field is noise.
|
|
207
|
-
return trimmed === "-0" || trimmed === "" ? "0" : trimmed;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** The single "on blur / Enter" transform a numeric field applies: evaluate the
|
|
211
|
-
* text if it's an expression, otherwise normalise it to a bare number string
|
|
212
|
-
* (comma → dot, dropping stray characters, non-leading minuses and anything after
|
|
213
|
-
* a second decimal point).
|
|
214
|
-
*
|
|
215
|
-
* The last clause is the backstop for Keksdose live #201. A field the user typed in
|
|
216
|
-
* cannot reach here malformed any more — {@link sanitizeLive} runs on every change,
|
|
217
|
-
* including a paste — but a value handed in from elsewhere (a recurring rule, an
|
|
218
|
-
* import, a test) still can, and "1.2.3" is not an expression (no operator), so it
|
|
219
|
-
* used to fall straight through unchanged and be read as NaN. Here the text is CUT
|
|
220
|
-
* at the second dot ("1.2") rather than joined ("1.23"): with no keystroke to
|
|
221
|
-
* ignore there is nothing to say which reading was meant, and the shorter one
|
|
222
|
-
* cannot silently invent a bigger number. */
|
|
223
|
-
export function commitExpression(raw: string): string {
|
|
224
|
-
const s = raw.trim();
|
|
225
|
-
if (looksLikeExpression(s)) {
|
|
226
|
-
const n = evaluateExpression(s);
|
|
227
|
-
if (n !== null) return formatResult(n);
|
|
228
|
-
// Unparseable (e.g. a half-typed "12+"): fall through to a digits-only clean.
|
|
229
|
-
}
|
|
230
|
-
// Global, like sanitizeLive's: these two are the two halves of one rule and must
|
|
231
|
-
// not appear to state it differently. (The `[^0-9.-]` strip on the same line
|
|
232
|
-
// already ate whatever commas a non-global replace missed, so this changes no
|
|
233
|
-
// behaviour — it removes the need for the next reader to run it to find that out.)
|
|
234
|
-
const cleaned = s
|
|
235
|
-
.replace(/,/g, ".")
|
|
236
|
-
.replace(/[^0-9.-]/g, "")
|
|
237
|
-
.replace(/(?!^)-/g, "");
|
|
238
|
-
return cleaned.replace(/^(-?\d*\.?\d*).*$/, "$1");
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** The live, per-keystroke transform a numeric field applies: comma → dot and
|
|
242
|
-
* drop anything that isn't a digit, decimal point, arithmetic operator (incl.
|
|
243
|
-
* the on-screen `× ÷` glyphs) or paren — so a typed calculation survives
|
|
244
|
-
* keystroke-by-keystroke but stray characters can't be entered. A lone leading
|
|
245
|
-
* `-` is kept — in a plain field it is simply a negative amount; in a field whose
|
|
246
|
-
* caller owns the sign it is read off again by {@link splitLeadingSign}. The text
|
|
247
|
-
* is resolved to a plain number on blur/Enter via {@link commitExpression}.
|
|
248
|
-
*
|
|
249
|
-
* The typographic minus and the two dashes become "-" first, as in
|
|
250
|
-
* {@link evaluateExpression}: U+2212 is what the kit's own `formatMoney` and
|
|
251
|
-
* `formatNumber` print for every negative since 0.49, and stripping it with the
|
|
252
|
-
* stray characters turned a pasted "−1.234,50 €" into a positive amount (refactor
|
|
253
|
-
* audit 2026-10-30, INP-3). */
|
|
254
|
-
export function sanitizeLive(raw: string): string {
|
|
255
|
-
return dropExtraDots(
|
|
256
|
-
raw
|
|
257
|
-
.replace(/[−–—]/g, "-")
|
|
258
|
-
.replace(/,/g, ".")
|
|
259
|
-
.replace(/[^0-9.+\-*/×÷()]/g, ""),
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* At most ONE decimal point per number (Keksdose live #201).
|
|
265
|
-
*
|
|
266
|
-
* Per NUMBER, not per string: "1.5+2.5" is a legitimate calculation with two dots
|
|
267
|
-
* in two operands, so the counter resets at every operator and parenthesis.
|
|
268
|
-
*
|
|
269
|
-
* A second dot inside one operand is a **no-op keystroke** — the digits after it
|
|
270
|
-
* keep landing, so "1.2" + "." + "3" is "1.23". That is what every calculator does
|
|
271
|
-
* with a repeated decimal point, and it is the only option that does not make the
|
|
272
|
-
* field feel broken ("my 3 disappeared"). This runs on paste as well as on typing,
|
|
273
|
-
* so the malformed value never reaches the rest of the app: everything downstream
|
|
274
|
-
* reads the field with `Number()`, NaN became a silent 0, and on the create form
|
|
275
|
-
* that 0 was painted with the income green — a figure that was not a number at all
|
|
276
|
-
* asserting money was coming in.
|
|
277
|
-
*/
|
|
278
|
-
function dropExtraDots(s: string): string {
|
|
279
|
-
let out = "";
|
|
280
|
-
let dotInNumber = false;
|
|
281
|
-
for (const ch of s) {
|
|
282
|
-
if (ch === ".") {
|
|
283
|
-
if (dotInNumber) continue;
|
|
284
|
-
dotInNumber = true;
|
|
285
|
-
} else if (ch < "0" || ch > "9") {
|
|
286
|
-
// An operator or a paren ends the current operand.
|
|
287
|
-
dotInNumber = false;
|
|
288
|
-
}
|
|
289
|
-
out += ch;
|
|
290
|
-
}
|
|
291
|
-
return out;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/** A bare, unsigned amount: digits with at most one decimal separator and nothing
|
|
295
|
-
* else — "42", "42.", ".5", "0,5". NOT "" (an empty field has no figure to put a
|
|
296
|
-
* sign in front of), not "-42", not "12+5". It is the only shape a DISPLAYED sign
|
|
297
|
-
* prefix makes sense in front of; an expression carries its own arithmetic and has
|
|
298
|
-
* to survive keystroke-for-keystroke. */
|
|
299
|
-
export function isBareAmount(s: string): boolean {
|
|
300
|
-
const t = s.trim();
|
|
301
|
-
return t !== "" && /^\d*[.,]?\d*$/.test(t);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Split a LEADING sign off a plain signed number (Keksdose live #201 rework):
|
|
306
|
-
* `"-42"` → `{ sign: "-", rest: "42" }`, everything else → `{ sign: "", rest: text }`.
|
|
307
|
-
*
|
|
308
|
-
* Only in front of a bare amount, because a minus with arithmetic after it IS
|
|
309
|
-
* arithmetic: "12-30" is a subtraction, and "-12+5" is -7, not -(12+5). Those come
|
|
310
|
-
* back untouched and are resolved by {@link commitExpression} on blur — at which
|
|
311
|
-
* point the RESULT is a plain signed number and this function does get to speak.
|
|
312
|
-
*
|
|
313
|
-
* A lone "-" splits (rest ""): the sign is a statement about the direction the
|
|
314
|
-
* moment it is typed, before any digit exists.
|
|
315
|
-
*/
|
|
316
|
-
export function splitLeadingSign(text: string): { sign: "" | "-" | "+"; rest: string } {
|
|
317
|
-
const trimmed = text.trimStart();
|
|
318
|
-
const sign = trimmed.charAt(0);
|
|
319
|
-
if (sign !== "-" && sign !== "+") return { sign: "", rest: text };
|
|
320
|
-
const rest = trimmed.slice(1);
|
|
321
|
-
if (rest !== "" && !isBareAmount(rest)) return { sign: "", rest: text };
|
|
322
|
-
return { sign, rest };
|
|
323
|
-
}
|