@eifi1/ui-kit 0.54.0 → 0.56.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 +90 -76
- 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/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.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 +6 -9
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar-heatmap.js +2 -2
- 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-select.js +2 -2
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.js +2 -2
- 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-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 +3 -1
- 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 +7 -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 +83 -0
- package/dist/components/legended-series-chart.js +77 -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 +13 -5
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.d.ts +23 -2
- package/dist/components/modal.js +24 -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/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/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-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-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 +1 -10
- 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 +75 -3
- 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 +92 -4
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +71 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +72 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +74 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +74 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +71 -3
- 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 +24 -5
- package/dist/index.js +35 -1
- 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 +29 -3
- package/dist/lib/dates.js +41 -12
- 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/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/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 +9 -12
- 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 -342
- 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 -439
- 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 -816
- 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 -600
- 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 -188
- package/src/components/currency-select.tsx +0 -343
- package/src/components/danger-confirm-labels.ts +0 -20
- package/src/components/danger-confirm.tsx +0 -987
- 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 -289
- package/src/components/data-table-filters.ts +0 -315
- 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 -284
- 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 -792
- package/src/components/modal.tsx +0 -534
- 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 -559
- 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 -754
- 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 -90
- 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 -11
- package/src/feedback/feedback-context.tsx +0 -245
- package/src/feedback/feedback-crash.ts +0 -547
- package/src/feedback/feedback-diagnostics.tsx +0 -41
- package/src/feedback/feedback-dialog-labels.ts +0 -29
- package/src/feedback/feedback-dialog.tsx +0 -452
- 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 -428
- 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 -31
- package/src/feedback/feedback-row-detail.tsx +0 -871
- package/src/feedback/feedback-status-undo.ts +0 -109
- package/src/feedback/feedback-submit-dialog.tsx +0 -131
- package/src/feedback/feedback-submit.tsx +0 -270
- 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 -212
- 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 -2059
- 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 -1999
- package/src/i18n/locales/fr.ts +0 -2037
- package/src/i18n/locales/hu.ts +0 -2004
- package/src/i18n/locales/it.ts +0 -2014
- package/src/i18n/locales/zh.ts +0 -1912
- 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 -1191
- 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 -288
- 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 -585
- 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 -27
- 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 -769
- 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/lib/download.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Saving a file the page fetched itself, and reading the name the server gave it
|
|
3
|
-
* (round 0.34 C6, KS U5).
|
|
4
|
-
*
|
|
5
|
-
* Every app behind a token downloads this way: an `<a href>` to an API route carries no
|
|
6
|
-
* `Authorization` header, so the app fetches the bytes and hands them to the browser
|
|
7
|
-
* through an object URL and a link with a `download` name. The kit had written that
|
|
8
|
-
* three times (the translation corrections export, a feedback attachment, the account
|
|
9
|
-
* data export) in three spellings, and Kurvenschmiede had a fourth beside them, each
|
|
10
|
-
* with its own answer to the two questions that matter — whether the link is in the
|
|
11
|
-
* document when it is clicked, and when the URL is revoked. One answer, here:
|
|
12
|
-
*
|
|
13
|
-
* - **The link is attached** (hidden, `rel="noopener"`), clicked once and taken out
|
|
14
|
-
* again. A detached link downloads in today's Chromium, but Firefox long ignored a
|
|
15
|
-
* click on a link outside the document, and attaching it costs nothing.
|
|
16
|
-
* - **The URL is revoked a minute later**, not at once. The click only STARTS the
|
|
17
|
-
* download; the browser reads the URL after this function has returned, and a URL
|
|
18
|
-
* revoked before that is a download that fails without a word. A minute holds one
|
|
19
|
-
* reference to a blob the page already had; Kastlan's `openAuthenticatedFile` waits
|
|
20
|
-
* the same minute for the tab it opens.
|
|
21
|
-
*
|
|
22
|
-
* And the name: server-kit's `content_disposition` writes the ORIGINAL name only in the
|
|
23
|
-
* RFC 6266 / RFC 8187 `filename*=UTF-8''…`, and an ASCII stand-in in the plain
|
|
24
|
-
* `filename=` (accents folded from 0.8). A reader that takes `filename=` alone saves
|
|
25
|
-
* "Grun.pdf" for "Grün.pdf" and "____.pdf" for a name in Chinese, so
|
|
26
|
-
* {@link filenameFromDisposition} reads `filename*` first.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/** How long an object URL handed to a download stays valid. See the module note. */
|
|
30
|
-
export const SAVE_BLOB_REVOKE_MS = 60_000;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Hand `href` to the browser as a download named `filename`: a hidden link with a
|
|
34
|
-
* `download` name, attached, clicked once and taken out again. The one way a page saves
|
|
35
|
-
* a file without opening a tab that shows it instead.
|
|
36
|
-
*
|
|
37
|
-
* For a URL the caller keeps alive itself — `DataExportSetting` keeps its object URL for
|
|
38
|
-
* the "Didn't start? Save the file" link under the button. Everything else wants
|
|
39
|
-
* {@link saveBlob}.
|
|
40
|
-
*/
|
|
41
|
-
export function clickDownload(href: string, filename: string): void {
|
|
42
|
-
const link = document.createElement("a");
|
|
43
|
-
link.href = href;
|
|
44
|
-
link.download = filename;
|
|
45
|
-
link.rel = "noopener";
|
|
46
|
-
link.hidden = true;
|
|
47
|
-
document.body.appendChild(link);
|
|
48
|
-
link.click();
|
|
49
|
-
link.remove();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Save `blob` as a file named `filename` — the browser's own download, as if the person
|
|
54
|
-
* had clicked a link to it.
|
|
55
|
-
*
|
|
56
|
-
* Call it from the handler of the click that asked for the file. After an `await` (the
|
|
57
|
-
* fetch) most browsers still count the click as the person's; a browser that does not
|
|
58
|
-
* holds the download back, and a page that must not lose it keeps a link of its own
|
|
59
|
-
* under the button, as `DataExportSetting` does.
|
|
60
|
-
*
|
|
61
|
-
* ```ts
|
|
62
|
-
* const res = await api.get(path, { responseType: "blob" });
|
|
63
|
-
* saveBlob(res.data, filenameFromDisposition(res.headers["content-disposition"], "report.pdf"));
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
export function saveBlob(blob: Blob, filename: string): void {
|
|
67
|
-
const href = URL.createObjectURL(blob);
|
|
68
|
-
clickDownload(href, filename);
|
|
69
|
-
setTimeout(() => URL.revokeObjectURL(href), SAVE_BLOB_REVOKE_MS);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/* ── Content-Disposition ─────────────────────────────────────────────────── */
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* The parameters of a `Content-Disposition` value, names lower-cased. `;` separates
|
|
76
|
-
* them except inside a quoted string, whose backslash escapes are undone; a bare token
|
|
77
|
-
* (the disposition type, `attachment`) is skipped. The first of a repeated name wins.
|
|
78
|
-
*/
|
|
79
|
-
function dispositionParams(header: string): Map<string, string> {
|
|
80
|
-
const params = new Map<string, string>();
|
|
81
|
-
const n = header.length;
|
|
82
|
-
let i = 0;
|
|
83
|
-
while (i < n) {
|
|
84
|
-
let j = i;
|
|
85
|
-
while (j < n && header[j] !== "=" && header[j] !== ";") j++;
|
|
86
|
-
const name = header.slice(i, j).trim().toLowerCase();
|
|
87
|
-
if (j >= n || header[j] === ";") {
|
|
88
|
-
i = j + 1;
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
j++; // past "="
|
|
92
|
-
while (j < n && (header[j] === " " || header[j] === "\t")) j++;
|
|
93
|
-
let value = "";
|
|
94
|
-
if (header[j] === '"') {
|
|
95
|
-
j++;
|
|
96
|
-
while (j < n && header[j] !== '"') {
|
|
97
|
-
if (header[j] === "\\" && j + 1 < n) j++;
|
|
98
|
-
value += header[j];
|
|
99
|
-
j++;
|
|
100
|
-
}
|
|
101
|
-
// Past the closing quote and whatever stray text follows it up to the next ";".
|
|
102
|
-
while (j < n && header[j] !== ";") j++;
|
|
103
|
-
} else {
|
|
104
|
-
const end = header.indexOf(";", j);
|
|
105
|
-
value = header.slice(j, end === -1 ? n : end).trim();
|
|
106
|
-
j = end === -1 ? n : end;
|
|
107
|
-
}
|
|
108
|
-
if (name && !params.has(name)) params.set(name, value);
|
|
109
|
-
i = j + 1;
|
|
110
|
-
}
|
|
111
|
-
return params;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** An RFC 8187 ext-value — `charset'language'percent-encoded` — decoded, or undefined
|
|
115
|
-
* for a charset it cannot read or an encoding that is broken. */
|
|
116
|
-
function decodeExtValue(value: string): string | undefined {
|
|
117
|
-
const match = /^([^']*)'[^']*'(.*)$/.exec(value);
|
|
118
|
-
if (!match) return undefined;
|
|
119
|
-
const charset = match[1].trim().toLowerCase();
|
|
120
|
-
const encoded = match[2];
|
|
121
|
-
if (charset === "utf-8" || charset === "utf8") {
|
|
122
|
-
try {
|
|
123
|
-
return decodeURIComponent(encoded);
|
|
124
|
-
} catch {
|
|
125
|
-
return undefined; // a stray "%" or a cut-off sequence
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
if (charset === "iso-8859-1") {
|
|
129
|
-
return encoded.replace(/%([0-9a-f]{2})/gi, (_, hex: string) => String.fromCharCode(parseInt(hex, 16)));
|
|
130
|
-
}
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** A name safe to put in a `download` attribute or on screen: the last path segment
|
|
135
|
-
* (RFC 6266 §4.3 — a recipient strips directory information), without control
|
|
136
|
-
* characters, trimmed; undefined when nothing is left. */
|
|
137
|
-
function cleanFilename(name: string | undefined): string | undefined {
|
|
138
|
-
if (name === undefined) return undefined;
|
|
139
|
-
const base = name.slice(Math.max(name.lastIndexOf("/"), name.lastIndexOf("\\")) + 1);
|
|
140
|
-
const clean = Array.from(base)
|
|
141
|
-
.filter((c) => {
|
|
142
|
-
const code = c.charCodeAt(0);
|
|
143
|
-
return code >= 0x20 && code !== 0x7f;
|
|
144
|
-
})
|
|
145
|
-
.join("")
|
|
146
|
-
.trim();
|
|
147
|
-
return clean && !/^\.+$/.test(clean) ? clean : undefined;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* The file name a `Content-Disposition` header asks for: the RFC 8187 `filename*`
|
|
152
|
-
* (`UTF-8''Gr%C3%BCn.pdf`, the one that carries a name in any script) first, then the
|
|
153
|
-
* plain `filename=`, quoted or not. Directory parts are dropped. Never throws: a missing
|
|
154
|
-
* header, a header with no name, a broken encoding all come back as `fallback` —
|
|
155
|
-
* `undefined` when none is given.
|
|
156
|
-
*
|
|
157
|
-
* Reads exactly what server-kit's `content_disposition` writes. With axios the header is
|
|
158
|
-
* `res.headers["content-disposition"]`, with `fetch` `res.headers.get("Content-Disposition")`
|
|
159
|
-
* — and across origins only when the server lists it in `Access-Control-Expose-Headers`.
|
|
160
|
-
*/
|
|
161
|
-
export function filenameFromDisposition(header: string | null | undefined): string | undefined;
|
|
162
|
-
export function filenameFromDisposition(header: string | null | undefined, fallback: string): string;
|
|
163
|
-
export function filenameFromDisposition(header: string | null | undefined, fallback?: string): string | undefined {
|
|
164
|
-
if (typeof header !== "string" || header === "") return fallback;
|
|
165
|
-
const params = dispositionParams(header);
|
|
166
|
-
const extended = params.get("filename*");
|
|
167
|
-
return (
|
|
168
|
-
cleanFilename(extended === undefined ? undefined : decodeExtValue(extended)) ??
|
|
169
|
-
cleanFilename(params.get("filename")) ??
|
|
170
|
-
fallback
|
|
171
|
-
);
|
|
172
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The room the floating launchers take above the bottom nav, published as
|
|
5
|
-
* `--app-float-clearance` on `<html>` so `AppShell` can pad `<main>` past them, and with
|
|
6
|
-
* the nav included as `--kit-floating-inset` (0.49 KIT-11, below).
|
|
7
|
-
*
|
|
8
|
-
* keksdose dev#612 (UX-1.3, "the help button covers content"): the shell padded `<main>`
|
|
9
|
-
* for the nav plus 1.5rem, so on a phone the last row of every page ended under the help
|
|
10
|
-
* launcher — and on /transactions under the action group below it, exactly where the
|
|
11
|
-
* row's amount is. keksdose patched it with its own `--help-launcher-clearance` and an
|
|
12
|
-
* unlayered app.css rule. Here every kit launcher (`FloatingActionButton`, so
|
|
13
|
-
* `FloatingPanel`'s too, and `FloatingActionGroup`) declares its own room while it is
|
|
14
|
-
* mounted and shown, and the shell takes the largest.
|
|
15
|
-
*
|
|
16
|
-
* Declared, not measured: a launcher knows its `offset` and its 3rem height exactly, as
|
|
17
|
-
* CSS lengths, and the variable then follows the nav and the text size by itself. A
|
|
18
|
-
* `hidden` launcher keeps its claim: the room is its own while it is mounted, so the page
|
|
19
|
-
* does not change length as it hides and shows (keksdose's launcher steps aside while an
|
|
20
|
-
* editor covers its corner). Unmount it to give the room back.
|
|
21
|
-
*
|
|
22
|
-
* Internal: not exported from the barrel.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
const claims = new Map<symbol, string>();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 0.49 KIT-11: `--kit-floating-inset` is the same room measured from the screen's bottom
|
|
29
|
-
* edge — the phone's bottom nav (`--app-nav-h`, 0px from `md` up) or the home indicator,
|
|
30
|
-
* whichever is taller, plus `--app-float-clearance` — so a page's own fixed or sticky
|
|
31
|
-
* footer, or its last row, can clear the launchers with one length at every width.
|
|
32
|
-
* Unset while no launcher is mounted, like `--app-float-clearance`: write
|
|
33
|
-
* `var(--kit-floating-inset, var(--app-nav-h, 0px))`.
|
|
34
|
-
*/
|
|
35
|
-
const NAV_OR_HOME_INDICATOR = "max(var(--app-nav-h, 0px), env(safe-area-inset-bottom, 0px))";
|
|
36
|
-
|
|
37
|
-
function publish() {
|
|
38
|
-
if (typeof document === "undefined") return;
|
|
39
|
-
const root = document.documentElement;
|
|
40
|
-
const values = [...claims.values()];
|
|
41
|
-
if (values.length === 0) {
|
|
42
|
-
root.style.removeProperty("--app-float-clearance");
|
|
43
|
-
root.style.removeProperty("--kit-floating-inset");
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
root.style.setProperty("--app-float-clearance", values.length === 1 ? values[0] : `max(${values.join(", ")})`);
|
|
47
|
-
root.style.setProperty("--kit-floating-inset", `calc(${NAV_OR_HOME_INDICATOR} + var(--app-float-clearance))`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/** Claim `value` (a CSS length: the launcher's top edge above the nav, plus a gap) until
|
|
51
|
-
* the returned function is called. */
|
|
52
|
-
export function claimFloatClearance(value: string): () => void {
|
|
53
|
-
const key = Symbol("float-clearance");
|
|
54
|
-
claims.set(key, value);
|
|
55
|
-
publish();
|
|
56
|
-
return () => {
|
|
57
|
-
claims.delete(key);
|
|
58
|
-
publish();
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* A launcher at `offset` above the nav claims its 3rem height plus a 0.5rem gap while
|
|
64
|
-
* mounted (`extra`: what its frame adds, the group's 1px borders).
|
|
65
|
-
*/
|
|
66
|
-
export function useFloatClearance(offset: string, extra?: string): void {
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
return claimFloatClearance(`calc(${offset} + 3.5rem${extra ? ` + ${extra}` : ""})`);
|
|
69
|
-
}, [offset, extra]);
|
|
70
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What floats over the bottom of the screen right now, so a notice that comes and goes
|
|
3
|
-
* can sit above it instead of on it.
|
|
4
|
-
*
|
|
5
|
-
* kastlan 0.18: its offline pill is a `bottom-start` FloatingActionButton, and
|
|
6
|
-
* `ServerWakeNotice` sat in the same corner — right after a break both show at once
|
|
7
|
-
* (the photo outbox syncs while the first reads wake the server), one over the other.
|
|
8
|
-
* The FAB's `offset` cannot help: the notice comes and goes, and on a phone it is
|
|
9
|
-
* nearly as wide as the screen, so a FAB in EITHER corner can be under it.
|
|
10
|
-
*
|
|
11
|
-
* Measured, not declared: a FloatingActionButton registers its fixed element while it
|
|
12
|
-
* is mounted, and a notice asks {@link clearanceAbove} for the height it has to clear —
|
|
13
|
-
* whatever offset, `extended` label or `hidden` state the controls are in. A control
|
|
14
|
-
* that is `hidden` measures 0 × 0 and is skipped, so kastlan's pill, which stays
|
|
15
|
-
* mounted and hidden while there is nothing to report, costs the notice nothing.
|
|
16
|
-
*
|
|
17
|
-
* NO READER since 0.34: `ServerWakeNotice` moved to the top of the screen (keksdose
|
|
18
|
-
* live #399), out of every FAB's corner. FloatingActionButton still registers; the
|
|
19
|
-
* next notice that has to sit above the bottom's floating controls reads this.
|
|
20
|
-
*
|
|
21
|
-
* Internal: not exported from the barrel.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
const occupants = new Set<HTMLElement>();
|
|
25
|
-
const listeners = new Set<() => void>();
|
|
26
|
-
let observer: ResizeObserver | null = null;
|
|
27
|
-
|
|
28
|
-
function notify() {
|
|
29
|
-
for (const listener of listeners) listener();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Track `element` until the returned function is called. Size changes — a label that
|
|
33
|
-
* grows, `hidden` toggling — notify the subscribers too. */
|
|
34
|
-
export function registerFloating(element: HTMLElement): () => void {
|
|
35
|
-
occupants.add(element);
|
|
36
|
-
if (observer === null && typeof ResizeObserver !== "undefined") observer = new ResizeObserver(notify);
|
|
37
|
-
observer?.observe(element);
|
|
38
|
-
notify();
|
|
39
|
-
return () => {
|
|
40
|
-
occupants.delete(element);
|
|
41
|
-
observer?.unobserve(element);
|
|
42
|
-
notify();
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Hear every registration, removal and size change. */
|
|
47
|
-
export function subscribeFloating(listener: () => void): () => void {
|
|
48
|
-
listeners.add(listener);
|
|
49
|
-
return () => {
|
|
50
|
-
listeners.delete(listener);
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* The distance from the viewport's bottom edge to the top of the highest visible
|
|
56
|
-
* floating control that shares a column with `element` — what `element` has to clear —
|
|
57
|
-
* or `null` when nothing is under it.
|
|
58
|
-
*/
|
|
59
|
-
export function clearanceAbove(element: HTMLElement | null): number | null {
|
|
60
|
-
if (!element) return null;
|
|
61
|
-
const own = element.getBoundingClientRect();
|
|
62
|
-
let top = Infinity;
|
|
63
|
-
for (const other of occupants) {
|
|
64
|
-
const box = other.getBoundingClientRect();
|
|
65
|
-
if (box.width === 0 || box.height === 0) continue;
|
|
66
|
-
if (box.right <= own.left || box.left >= own.right) continue;
|
|
67
|
-
top = Math.min(top, box.top);
|
|
68
|
-
}
|
|
69
|
-
return top === Infinity ? null : Math.max(0, window.innerHeight - top);
|
|
70
|
-
}
|
package/src/lib/focus-left.ts
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
// "The focused node left" (refactor audit 2026-10-30, Wave 1: DSP-4, DSP-15). When the
|
|
2
|
-
// element holding the keyboard's focus is removed — a table row deleted, filtered out or
|
|
3
|
-
// approved; a bulk bar gone with its Clear; a banner its × took away — the browser puts
|
|
4
|
-
// focus on <body> and says nothing: no blur in Chromium, none in jsdom. A keyboard or
|
|
5
|
-
// screen-reader user then starts again from the top of the page. The overlays give focus
|
|
6
|
-
// back to their opener (use-focus-trap); these helpers are for the controls that leave
|
|
7
|
-
// the page while the focus is IN them, and decide where it goes instead.
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Candidate tab stops, in DOM order — narrowed by {@link isTabStop} to the ones a Tab
|
|
11
|
-
* really reaches. The kit's one copy of the rule (0.52 code review, lib/focus-left.ts):
|
|
12
|
-
* this file and use-focus-trap each had it, with an exported `firstTabStop` apiece that
|
|
13
|
-
* disagreed about the element itself, and a combobox panel's toolbar had a third
|
|
14
|
-
* selector. The trap, the focus a removed node drops (below), the tour's field ring and
|
|
15
|
-
* the toolbar all read it here, so "the next stop" is the same stop everywhere.
|
|
16
|
-
*
|
|
17
|
-
* The selector is the one `Modal` used. On its own it was not enough (round 0.34
|
|
18
|
-
* BUG-4): only the bare `[tabindex]` clause excluded `-1`, so a `button`, an `input` or
|
|
19
|
-
* a link taken out of the tab order still counted. A panel that ends in a roving grid —
|
|
20
|
-
* the calendar's days, the month grid, the picker sheet's rows, every one of them `-1`
|
|
21
|
-
* but the active cell — then had a "last" stop no Tab ever reaches: Tab from the real
|
|
22
|
-
* last stop was not wrapped and walked out of the open panel, and Shift+Tab from the
|
|
23
|
-
* first landed on a cell that is not a stop at all.
|
|
24
|
-
*/
|
|
25
|
-
// `input[type=hidden]` is no stop: a Tab never lands on it and focus() on it does nothing,
|
|
26
|
-
// but its tabIndex reads 0, so a trap could take a form's hidden field for its first or last
|
|
27
|
-
// stop and Shift+Tab left the dialog (0.52 code review).
|
|
28
|
-
const TAB_STOP =
|
|
29
|
-
'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]):not([type="hidden"]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* A stop the browser's own Tab would land on: in the tab order (`tabIndex` ≥ 0) and not
|
|
33
|
-
* inside something `hidden` or `inert`. Removes only elements a native Tab never
|
|
34
|
-
* reaches, so no correct order changes. `visibility: hidden` and closed `<details>` are
|
|
35
|
-
* still not walked — they need layout, which this rule has never read.
|
|
36
|
-
*/
|
|
37
|
-
function isTabStop(el: HTMLElement): boolean {
|
|
38
|
-
return el.tabIndex >= 0 && !el.closest("[hidden],[inert]");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface TabStopOptions {
|
|
42
|
-
/** Whether `el` itself counts, first, when it is a stop. Default true: the tour's
|
|
43
|
-
* target may BE the field (refactor audit 2026-10-30, DUP-9). False for "a control
|
|
44
|
-
* inside it" — a row, a drawer, a trap's container, a toolbar. */
|
|
45
|
-
includeSelf?: boolean;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** The tab stops in `el`, in DOM order — `el` itself first when it is one, unless
|
|
49
|
-
* `includeSelf: false`. */
|
|
50
|
-
export function tabStops(el: Element, { includeSelf = true }: TabStopOptions = {}): HTMLElement[] {
|
|
51
|
-
const inside = Array.from(el.querySelectorAll<HTMLElement>(TAB_STOP)).filter(isTabStop);
|
|
52
|
-
const own = includeSelf && el instanceof HTMLElement && el.matches(TAB_STOP) && isTabStop(el);
|
|
53
|
-
return own ? [el, ...inside] : inside;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** The first of {@link tabStops} — the control a person types into or presses — or null. */
|
|
57
|
-
export function firstTabStop(el: Element, options?: TabStopOptions): HTMLElement | null {
|
|
58
|
-
return tabStops(el, options)[0] ?? null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Whether the focus has fallen out of the page: onto `<body>`, onto nothing, or onto a
|
|
63
|
-
* node no longer in the document. False on the server, where nothing has focus to lose.
|
|
64
|
-
* A recovery asks this first: focus that went somewhere real (a dialog, the next field,
|
|
65
|
-
* an app's own `focus()`) is the user's or the app's, and is left where it is.
|
|
66
|
-
*/
|
|
67
|
-
export function focusIsLost(): boolean {
|
|
68
|
-
if (typeof document === "undefined") return false;
|
|
69
|
-
const el = document.activeElement;
|
|
70
|
-
return !el || el === document.body || !el.isConnected;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Calls `then` when a `blur`/`focusout` was the user's own move to nothing — a click on
|
|
75
|
-
* the page's background, or a click Safari answers by focusing nothing (it focuses no
|
|
76
|
-
* button or link on a click, and blurs what had the focus) — after which a note of where
|
|
77
|
-
* the focus was is stale (0.52 code review: DataTable's row, BulkActionBar's and
|
|
78
|
-
* AlertBanner's notes outlived it, and a removal much later pulled the focus, and the
|
|
79
|
-
* scroll, back to them).
|
|
80
|
-
*
|
|
81
|
-
* No element took the focus, the document holds none, and the node that lost it could
|
|
82
|
-
* still hold it. Not when it was removed, hidden, made inert or disabled: that is the page
|
|
83
|
-
* taking the focus away — the very case those notes are kept for. Not a window losing the
|
|
84
|
-
* focus either, which leaves the node the document's active element. Decided a microtask
|
|
85
|
-
* later, once the event's own work is done: a browser that blurs a node it is removing
|
|
86
|
-
* (or hiding) may do it while the node is still in place, and only after it is gone is
|
|
87
|
-
* that told apart from a click.
|
|
88
|
-
*/
|
|
89
|
-
export function whenFocusLeftForNothing(
|
|
90
|
-
e: { target: EventTarget | null; relatedTarget: EventTarget | null },
|
|
91
|
-
then: () => void,
|
|
92
|
-
): void {
|
|
93
|
-
const el = e.target;
|
|
94
|
-
if (e.relatedTarget !== null || !(el instanceof Element)) return;
|
|
95
|
-
queueMicrotask(() => {
|
|
96
|
-
if (!el.isConnected || el.matches(":disabled") || el.closest("[hidden],[inert]")) return;
|
|
97
|
-
// `display: none`, where the browser can say (jsdom cannot).
|
|
98
|
-
if (typeof el.checkVisibility === "function" && !el.checkVisibility()) return;
|
|
99
|
-
if (focusIsLost()) then();
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* The tab stops around `frame`, outside it, nearest first on each side — where focus
|
|
105
|
-
* goes once `frame` is gone. Read BEFORE it goes: a removed node has no place in the
|
|
106
|
-
* document to measure from. `limit` per side keeps a long page's stops out of memory.
|
|
107
|
-
*
|
|
108
|
-
* Walked outwards from the frame, `limit` stops each way (0.52 code review,
|
|
109
|
-
* lib/focus-left.ts): read from every stop in the page, a banner under a 2000-row table
|
|
110
|
-
* read all 2000 to keep the nearest five before it.
|
|
111
|
-
*/
|
|
112
|
-
export function tabStopsAround(frame: Element, limit = 5): { after: HTMLElement[]; before: HTMLElement[] } {
|
|
113
|
-
const doc = frame.ownerDocument;
|
|
114
|
-
const walker = doc.createTreeWalker(doc.documentElement, NodeFilter.SHOW_ELEMENT);
|
|
115
|
-
const isStop = (node: Node): node is HTMLElement =>
|
|
116
|
-
node instanceof HTMLElement && node.matches(TAB_STOP) && isTabStop(node);
|
|
117
|
-
// After: from the first element past the frame's own subtree, in document order.
|
|
118
|
-
const after: HTMLElement[] = [];
|
|
119
|
-
walker.currentNode = frame;
|
|
120
|
-
let node: Node | null = walker.nextSibling();
|
|
121
|
-
while (!node && walker.parentNode()) node = walker.nextSibling();
|
|
122
|
-
for (; node && after.length < limit; node = walker.nextNode()) if (isStop(node)) after.push(node);
|
|
123
|
-
// Before: back from the frame, nearest first (its ancestors among them, as before).
|
|
124
|
-
const before: HTMLElement[] = [];
|
|
125
|
-
walker.currentNode = frame;
|
|
126
|
-
for (node = walker.previousNode(); node && before.length < limit; node = walker.previousNode())
|
|
127
|
-
if (isStop(node)) before.push(node);
|
|
128
|
-
return { after, before };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Focus the first of `candidates` that is still in the page and takes the focus; true
|
|
133
|
-
* when one did. Each is tried and checked, since `focus()` on a node that cannot hold it
|
|
134
|
-
* (detached, `display: none`, disabled since) fails without a word.
|
|
135
|
-
*/
|
|
136
|
-
export function focusFirst(candidates: Iterable<Element | null | undefined>): boolean {
|
|
137
|
-
for (const el of candidates) {
|
|
138
|
-
if (!(el instanceof HTMLElement) || !el.isConnected) continue;
|
|
139
|
-
el.focus();
|
|
140
|
-
if (document.activeElement === el) return true;
|
|
141
|
-
}
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Focus a container that is not a tab stop of its own — a table, a list — as the place
|
|
147
|
-
* the user is in, without making it one: `tabindex="-1"` for as long as it holds the
|
|
148
|
-
* focus, unless it already carries a `tabindex` of its own.
|
|
149
|
-
*/
|
|
150
|
-
export function focusContainer(el: HTMLElement): void {
|
|
151
|
-
if (!el.hasAttribute("tabindex")) {
|
|
152
|
-
el.setAttribute("tabindex", "-1");
|
|
153
|
-
el.addEventListener("blur", () => el.removeAttribute("tabindex"), { once: true });
|
|
154
|
-
}
|
|
155
|
-
el.focus();
|
|
156
|
-
}
|