@eifi1/ui-kit 0.51.3 → 0.51.5
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 +6 -6
- package/dist/account/account-settings-labels.js.map +1 -1
- package/dist/account/account-settings.js +11 -9
- package/dist/account/account-settings.js.map +1 -1
- package/dist/account/delete-account-setting.js +56 -65
- package/dist/account/delete-account-setting.js.map +1 -1
- package/dist/account/email-change-setting-labels.js.map +1 -1
- package/dist/account/email-change-setting.js.map +1 -1
- package/dist/account/passkeys-setting.js.map +1 -1
- package/dist/account/sessions-setting.js.map +1 -1
- package/dist/admin/admin-action-confirm.js +1 -3
- package/dist/admin/admin-action-confirm.js.map +1 -1
- package/dist/admin/admin-action-log.js.map +1 -1
- package/dist/admin/admin-area-labels.js +4 -1
- package/dist/admin/admin-area-labels.js.map +1 -1
- package/dist/admin/admin-overview.js +19 -11
- package/dist/admin/admin-overview.js.map +1 -1
- package/dist/admin/admin-sections.js.map +1 -1
- package/dist/admin/admin-tool-links.d.ts +1 -1
- package/dist/admin/admin-tool-links.js +7 -1
- package/dist/admin/admin-tool-links.js.map +1 -1
- package/dist/admin/invitations-panel.js +2 -13
- package/dist/admin/invitations-panel.js.map +1 -1
- package/dist/admin/mail-test-card.js.map +1 -1
- package/dist/admin/reviewer-scope-editor.js +4 -11
- package/dist/admin/reviewer-scope-editor.js.map +1 -1
- package/dist/admin/role-select.js.map +1 -1
- package/dist/admin/user-roster.js +1 -9
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/accept-invitation.js.map +1 -1
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/forgot-password-form.js +23 -31
- package/dist/auth/forgot-password-form.js.map +1 -1
- package/dist/auth/register-form.js.map +1 -1
- package/dist/auth/reset-password-form.js.map +1 -1
- package/dist/auth/sign-in-form.js +13 -5
- package/dist/auth/sign-in-form.js.map +1 -1
- package/dist/auth/verify-email.js +1 -8
- package/dist/auth/verify-email.js.map +1 -1
- package/dist/billing/billing-banner.js.map +1 -1
- package/dist/billing/billing-labels.js.map +1 -1
- package/dist/billing/checkout-processing.js.map +1 -1
- package/dist/billing/plan-card.js +91 -85
- package/dist/billing/plan-card.js.map +1 -1
- package/dist/billing/plan-limit-toast.js.map +1 -1
- package/dist/billing/plan-limit.js.map +1 -1
- package/dist/billing/plan-price.js.map +1 -1
- package/dist/billing/plan-switch.js.map +1 -1
- package/dist/billing/subscription-actions.js.map +1 -1
- package/dist/bin/eifi1-pay-page.mjs +6 -1
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/alert-banner.js +1 -5
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.js +29 -12
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/authed-image.js.map +1 -1
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/bulk-action-bar.js +1 -4
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button-group.js.map +1 -1
- package/dist/components/button-look.js.map +1 -1
- package/dist/components/button.js +1 -7
- package/dist/components/button.js.map +1 -1
- package/dist/components/calculator.js +5 -5
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/calendar-heatmap.js +4 -10
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/card.js +1 -8
- package/dist/components/card.js.map +1 -1
- package/dist/components/chart-zoom-core.js +3 -17
- package/dist/components/chart-zoom-core.js.map +1 -1
- package/dist/components/chart.d.ts +1 -1
- package/dist/components/chart.js +4 -22
- package/dist/components/chart.js.map +1 -1
- package/dist/components/checkbox-group.js +1 -4
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/chip-input.js +4 -1
- package/dist/components/chip-input.js.map +1 -1
- package/dist/components/chip.js +10 -5
- package/dist/components/chip.js.map +1 -1
- package/dist/components/choice-card.js +58 -74
- package/dist/components/choice-card.js.map +1 -1
- package/dist/components/column-mapper-labels.js.map +1 -1
- package/dist/components/column-mapper.js +167 -227
- package/dist/components/column-mapper.js.map +1 -1
- package/dist/components/combobox-core.js +5 -9
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +1 -4
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-button.js.map +1 -1
- package/dist/components/country-select.d.ts +5 -4
- package/dist/components/country-select.js +3 -19
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-option-list.js +13 -11
- package/dist/components/currency-option-list.js.map +1 -1
- package/dist/components/currency-select.js +1 -6
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-cells.js.map +1 -1
- package/dist/components/data-table-column-settings.js.map +1 -1
- package/dist/components/data-table-filter-popover.js +2 -18
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-filters.js.map +1 -1
- package/dist/components/data-table-fit.js +7 -5
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-groups.js +3 -1
- package/dist/components/data-table-groups.js.map +1 -1
- package/dist/components/data-table-head.js +49 -57
- package/dist/components/data-table-head.js.map +1 -1
- package/dist/components/data-table-mobile.js +31 -44
- package/dist/components/data-table-mobile.js.map +1 -1
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table-row-actions.js +19 -16
- package/dist/components/data-table-row-actions.js.map +1 -1
- package/dist/components/data-table-row.js.map +1 -1
- package/dist/components/data-table-shared.js.map +1 -1
- package/dist/components/data-table-sort.js.map +1 -1
- package/dist/components/data-table-virtual.js +4 -1
- package/dist/components/data-table-virtual.js.map +1 -1
- package/dist/components/data-table.d.ts +8 -0
- package/dist/components/data-table.js +30 -39
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.js +1 -6
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/description-list.js +10 -10
- package/dist/components/description-list.js.map +1 -1
- package/dist/components/dialog-frame.js +9 -2
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/disclosure.js +17 -27
- package/dist/components/disclosure.js.map +1 -1
- package/dist/components/dropdown.js +25 -35
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/empty-state.js.map +1 -1
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/field-base.js +5 -5
- package/dist/components/field-base.js.map +1 -1
- package/dist/components/field-parts.d.ts +1 -1
- package/dist/components/field-parts.js +10 -14
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-sync.js +8 -10
- package/dist/components/field-sync.js.map +1 -1
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/floating-panel.js +4 -1
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/focus-ring.js.map +1 -1
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/grouped-picker.js +11 -12
- package/dist/components/grouped-picker.js.map +1 -1
- package/dist/components/hover-menu.js +1 -4
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/iban-input-labels.js.map +1 -1
- package/dist/components/icon-button.js +4 -1
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/icon-picker.js +6 -10
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/image-grid.js +41 -50
- package/dist/components/image-grid.js.map +1 -1
- package/dist/components/inline-edit-field.js.map +1 -1
- package/dist/components/inline-entity-combobox.js +6 -12
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/input.js +14 -2
- package/dist/components/input.js.map +1 -1
- package/dist/components/jump-calendar.js +1 -7
- package/dist/components/jump-calendar.js.map +1 -1
- package/dist/components/legal-labels.js +8 -2
- package/dist/components/legal-labels.js.map +1 -1
- package/dist/components/legal-page.d.ts +18 -1
- package/dist/components/legal-page.js +27 -2
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +40 -5
- package/dist/components/legal.js +41 -5
- package/dist/components/legal.js.map +1 -1
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/line-items.js +26 -36
- package/dist/components/line-items.js.map +1 -1
- package/dist/components/list-labels.js +3 -1
- package/dist/components/list-labels.js.map +1 -1
- package/dist/components/list.d.ts +18 -1
- package/dist/components/list.js +54 -13
- package/dist/components/list.js.map +1 -1
- package/dist/components/measured-grid.js +29 -53
- package/dist/components/measured-grid.js.map +1 -1
- package/dist/components/menu-item.js.map +1 -1
- package/dist/components/mini-calendar.js +13 -31
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/money-field.js.map +1 -1
- package/dist/components/month-picker.js +10 -21
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.js +3 -16
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/nav-pills.js +10 -1
- package/dist/components/nav-pills.js.map +1 -1
- package/dist/components/number-field.js.map +1 -1
- package/dist/components/number-input.js +1 -7
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.js +1 -4
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/one-time-code-input.js +1 -7
- package/dist/components/one-time-code-input.js.map +1 -1
- package/dist/components/page-contents.js +13 -22
- package/dist/components/page-contents.js.map +1 -1
- package/dist/components/page-header.js +1 -11
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/password-strength-labels.js.map +1 -1
- package/dist/components/password-strength.js +2 -8
- package/dist/components/password-strength.js.map +1 -1
- package/dist/components/phone-input.js +42 -57
- package/dist/components/phone-input.js.map +1 -1
- package/dist/components/picker-sheet.js.map +1 -1
- package/dist/components/pie-chart.js +1 -8
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/popover.js.map +1 -1
- package/dist/components/progress-bar.js +16 -9
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/qr-code.js +1 -8
- package/dist/components/qr-code.js.map +1 -1
- package/dist/components/row-actions.js +5 -1
- package/dist/components/row-actions.js.map +1 -1
- package/dist/components/search-field.js.map +1 -1
- package/dist/components/select.js +28 -38
- package/dist/components/select.js.map +1 -1
- package/dist/components/separator.js +1 -5
- package/dist/components/separator.js.map +1 -1
- package/dist/components/series-chart-axes.js +4 -1
- package/dist/components/series-chart-axes.js.map +1 -1
- package/dist/components/series-chart-budget.js.map +1 -1
- package/dist/components/series-chart-ticks.js.map +1 -1
- package/dist/components/series-chart.js +29 -45
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/settings-fields.js +21 -17
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/share-card.js +4 -9
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/sign-chip.js.map +1 -1
- package/dist/components/signature-pad.js +4 -13
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/signed-amount.js +12 -5
- package/dist/components/signed-amount.js.map +1 -1
- package/dist/components/skeleton.js +2 -17
- package/dist/components/skeleton.js.map +1 -1
- package/dist/components/slider.js +13 -36
- package/dist/components/slider.js.map +1 -1
- package/dist/components/sparkline.js.map +1 -1
- package/dist/components/stat-tile.js +14 -10
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/swatch-picker.js +14 -4
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/swipeable-row.d.ts +1 -1
- package/dist/components/swipeable-row.js +1 -8
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/table-skeleton.js +4 -1
- package/dist/components/table-skeleton.js.map +1 -1
- package/dist/components/table.js +12 -9
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.js +5 -24
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/text-link.js.map +1 -1
- package/dist/components/text.js.map +1 -1
- package/dist/components/tile-radio.js +1 -7
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.js.map +1 -1
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.js +6 -1
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle-legend.js +2 -11
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/tooltip.js +2 -22
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/translation-review-editor.js +1 -4
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review-parts.d.ts +1 -1
- package/dist/components/translation-review-parts.js +7 -1
- package/dist/components/translation-review-parts.js.map +1 -1
- package/dist/components/translation-review.js +18 -7
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/tree-view.js +14 -10
- package/dist/components/tree-view.js.map +1 -1
- package/dist/components/treemap.js +1 -13
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/trigger-aria.js.map +1 -1
- package/dist/components/use-table-state.js +14 -11
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/components/user-avatar.js +3 -26
- package/dist/components/user-avatar.js.map +1 -1
- package/dist/demo/demo-start.js +8 -4
- package/dist/demo/demo-start.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/feedback/feedback-attachment-labels.js.map +1 -1
- package/dist/feedback/feedback-attachment.js +1 -8
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-capture.d.ts +1 -1
- package/dist/feedback/feedback-capture.js +3 -1
- package/dist/feedback/feedback-capture.js.map +1 -1
- package/dist/feedback/feedback-comment-thread.js +27 -13
- package/dist/feedback/feedback-comment-thread.js.map +1 -1
- package/dist/feedback/feedback-context.js +1 -4
- package/dist/feedback/feedback-context.js.map +1 -1
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-public-list.js +7 -1
- package/dist/feedback/feedback-public-list.js.map +1 -1
- package/dist/feedback/feedback-record.js +1 -5
- package/dist/feedback/feedback-record.js.map +1 -1
- package/dist/feedback/feedback-replies.js +25 -10
- package/dist/feedback/feedback-replies.js.map +1 -1
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-status-undo.js.map +1 -1
- package/dist/feedback/feedback-submit-dialog.js.map +1 -1
- package/dist/feedback/feedback-table.d.ts +3 -1
- package/dist/feedback/feedback-table.js +22 -5
- package/dist/feedback/feedback-table.js.map +1 -1
- package/dist/feedback/feedback-thread.js +2 -13
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback/feedback-vocabulary.js.map +1 -1
- package/dist/feedback/feedback-vote-button.js.map +1 -1
- package/dist/hooks/use-anchored-rect.js.map +1 -1
- package/dist/hooks/use-document-title.js.map +1 -1
- package/dist/hooks/use-file-drop.js.map +1 -1
- package/dist/hooks/use-file-picker-labels.js.map +1 -1
- package/dist/hooks/use-file-picker.js.map +1 -1
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-overlay-history.js +10 -5
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/hooks/use-row-swipe.d.ts +1 -1
- package/dist/hooks/use-row-swipe.js +1 -6
- package/dist/hooks/use-row-swipe.js.map +1 -1
- package/dist/i18n/defaults.js +1 -4
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +15 -4
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.js +2 -8
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.js.map +1 -1
- package/dist/i18n/locales/en.js +19 -4
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/es.js +15 -4
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +15 -4
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +15 -4
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +15 -4
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +11 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/plurals.js.map +1 -1
- package/dist/i18n/review.js +15 -7
- package/dist/i18n/review.js.map +1 -1
- package/dist/i18n/shared-labels.js.map +1 -1
- package/dist/index.d.ts +17 -17
- package/dist/index.js +40 -23
- package/dist/index.js.map +1 -1
- package/dist/landing/access.js +1 -4
- package/dist/landing/access.js.map +1 -1
- package/dist/landing/landing-sections.js +35 -38
- package/dist/landing/landing-sections.js.map +1 -1
- package/dist/landing/page-seo.js.map +1 -1
- package/dist/lib/calc.js.map +1 -1
- package/dist/lib/clipboard-minus.js.map +1 -1
- package/dist/lib/dates.js.map +1 -1
- package/dist/lib/decimal-marks.js.map +1 -1
- package/dist/lib/device-settings.js +2 -1
- package/dist/lib/device-settings.js.map +1 -1
- package/dist/lib/direction.js.map +1 -1
- package/dist/lib/iban.js.map +1 -1
- package/dist/lib/logger.js +1 -5
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/person-name.js.map +1 -1
- package/dist/lib/phone.js.map +1 -1
- package/dist/lib/qr-encode.js +344 -8
- package/dist/lib/qr-encode.js.map +1 -1
- package/dist/lib/session-refresh.js.map +1 -1
- package/dist/lib/table-text.js +15 -3
- package/dist/lib/table-text.js.map +1 -1
- package/dist/lib/text-match.d.ts +20 -0
- package/dist/lib/text-match.js +11 -1
- package/dist/lib/text-match.js.map +1 -1
- package/dist/lib/translation-review.js.map +1 -1
- package/dist/notifications/notification-inbox.js +63 -44
- package/dist/notifications/notification-inbox.js.map +1 -1
- package/dist/notifications/notification-parts.js.map +1 -1
- package/dist/notifications/notification-types-setting.js.map +1 -1
- package/dist/notifications/notifications-labels.js.map +1 -1
- package/dist/notifications/push-device-setting.js +6 -1
- package/dist/notifications/push-device-setting.js.map +1 -1
- package/dist/notifications/push-devices-setting.js.map +1 -1
- package/dist/notifications/push-worker.js.map +1 -1
- package/dist/notifications/quiet-hours-setting.js.map +1 -1
- package/dist/notifications/use-push-device.js +4 -1
- package/dist/notifications/use-push-device.js.map +1 -1
- package/dist/offline/pwa-update-prompt.d.ts +1 -1
- package/dist/offline/pwa-update-prompt.js +7 -1
- package/dist/offline/pwa-update-prompt.js.map +1 -1
- package/dist/offline/query-persistence.js.map +1 -1
- package/dist/offline.d.ts +1 -1
- package/dist/offline.js +6 -1
- package/dist/offline.js.map +1 -1
- package/dist/pay/pay.css +8 -1
- package/dist/rhf/fields.d.ts +1 -2
- package/dist/rhf/fields.js +1 -10
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form-core.js +1 -4
- package/dist/rhf/form-core.js.map +1 -1
- package/dist/rhf/line-items.js.map +1 -1
- package/dist/rhf/use-rhf-wizard-step.js.map +1 -1
- package/dist/search/command-palette.js +71 -62
- package/dist/search/command-palette.js.map +1 -1
- package/dist/search/global-search.js +34 -5
- package/dist/search/global-search.js.map +1 -1
- package/dist/search/search-index.js.map +1 -1
- package/dist/settings/device-reset-setting.js +1 -6
- package/dist/settings/device-reset-setting.js.map +1 -1
- package/dist/settings/settings-heading.js.map +1 -1
- package/dist/settings/settings-layout.js +9 -20
- package/dist/settings/settings-layout.js.map +1 -1
- package/dist/settings/use-settings-focus.d.ts +7 -0
- package/dist/settings/use-settings-focus.js +2 -0
- package/dist/settings/use-settings-focus.js.map +1 -1
- package/dist/settings/use-settings-route.js.map +1 -1
- package/dist/shell/app-shell.js +62 -31
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/auth-layout.js +1 -10
- package/dist/shell/auth-layout.js.map +1 -1
- package/dist/shell/dev-menu.d.ts +5 -0
- package/dist/shell/dev-menu.js +14 -7
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/option-switcher-menu.js.map +1 -1
- package/dist/shell/sync-status-indicator.js +7 -6
- package/dist/shell/sync-status-indicator.js.map +1 -1
- package/dist/shell/top-bar-parts-labels.js.map +1 -1
- package/dist/shell/topbar-action-menu.d.ts +14 -1
- package/dist/shell/topbar-action-menu.js +85 -34
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell/topbar-controls.js +1 -10
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/shell/tour-menu.js +9 -1
- package/dist/shell/tour-menu.js.map +1 -1
- package/dist/shell.d.ts +1 -1
- package/dist/shell.js +2 -1
- package/dist/shell.js.map +1 -1
- package/dist/sync/db.js.map +1 -1
- package/dist/sync/engine.js +24 -6
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync.d.ts +2 -2
- package/dist/sync.js +7 -1
- package/dist/sync.js.map +1 -1
- package/dist/testing/css-variables.js.map +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +1 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/react.js.map +1 -1
- package/dist/testing/viewport.js +7 -4
- package/dist/testing/viewport.js.map +1 -1
- package/dist/theme/contrast-tokens.js +13 -2
- package/dist/theme/contrast-tokens.js.map +1 -1
- package/dist/theme/palette-derive.d.ts +1 -1
- package/dist/theme/palette-derive.js +18 -29
- package/dist/theme/palette-derive.js.map +1 -1
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/text-size.js.map +1 -1
- package/dist/theme/theme-store.js +1 -3
- package/dist/theme/theme-store.js.map +1 -1
- package/dist/tour/tour-catalogue.js.map +1 -1
- package/dist/tour/tour-dock.js +5 -1
- package/dist/tour/tour-dock.js.map +1 -1
- package/dist/tour/tour-engine.js +1 -4
- package/dist/tour/tour-engine.js.map +1 -1
- package/dist/tour/tour.js +21 -12
- package/dist/tour/tour.js.map +1 -1
- package/dist/tour/use-tour-progress.js.map +1 -1
- package/dist/tour/use-tour-url-sync.js.map +1 -1
- package/dist/wizard/stepper-nav.js +3 -24
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard/types.js.map +1 -1
- package/dist/wizard/use-wizard.js +24 -28
- package/dist/wizard/use-wizard.js.map +1 -1
- package/dist/wizard/validation.js.map +1 -1
- package/dist/wizard/wizard-context.js.map +1 -1
- package/dist/wizard/wizard-step.d.ts +1 -1
- package/dist/wizard/wizard-step.js +1 -8
- package/dist/wizard/wizard-step.js.map +1 -1
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/package.json +5 -2
- package/src/account/account-settings-labels.ts +1 -2
- package/src/account/account-settings.tsx +11 -17
- package/src/account/delete-account-setting.tsx +1 -6
- package/src/account/email-change-setting-labels.ts +1 -2
- package/src/account/email-change-setting.tsx +3 -1
- package/src/account/passkeys-setting.tsx +1 -3
- package/src/account/sessions-setting.tsx +4 -2
- package/src/admin/admin-action-confirm.tsx +4 -7
- package/src/admin/admin-action-log.tsx +29 -29
- package/src/admin/admin-area-labels.ts +4 -1
- package/src/admin/admin-overview.tsx +8 -2
- package/src/admin/admin-sections.tsx +3 -1
- package/src/admin/admin-tool-links.tsx +7 -1
- package/src/admin/invitations-panel.tsx +5 -11
- package/src/admin/mail-test-card.tsx +1 -2
- package/src/admin/reviewer-scope-editor.tsx +4 -9
- package/src/admin/role-select.tsx +4 -2
- package/src/admin/user-roster.tsx +2 -11
- package/src/auth/accept-invitation.tsx +1 -7
- package/src/auth/auth-errors.ts +1 -6
- package/src/auth/forgot-password-form.tsx +2 -7
- package/src/auth/register-form.tsx +7 -8
- package/src/auth/reset-password-form.tsx +2 -5
- package/src/auth/sign-in-form.tsx +15 -14
- package/src/auth/verify-email.tsx +2 -7
- package/src/billing/billing-banner.tsx +3 -7
- package/src/billing/billing-labels.ts +6 -4
- package/src/billing/checkout-processing.ts +0 -1
- package/src/billing/plan-card.tsx +9 -8
- package/src/billing/plan-limit-toast.tsx +1 -2
- package/src/billing/plan-limit.ts +1 -2
- package/src/billing/plan-price.ts +1 -4
- package/src/billing/plan-switch.tsx +1 -2
- package/src/billing/subscription-actions.tsx +5 -2
- package/src/components/account-chips.tsx +1 -7
- package/src/components/alert-banner.tsx +2 -8
- package/src/components/amount-input.tsx +206 -178
- package/src/components/authed-image.tsx +7 -4
- package/src/components/autocomplete.tsx +7 -9
- package/src/components/bulk-action-bar.tsx +2 -7
- package/src/components/button-group.tsx +1 -2
- package/src/components/button-look.ts +6 -17
- package/src/components/button.tsx +1 -4
- package/src/components/calculator.tsx +6 -9
- package/src/components/calendar-heatmap.tsx +5 -10
- package/src/components/card.tsx +9 -13
- package/src/components/chart-zoom-core.tsx +6 -33
- package/src/components/chart.tsx +8 -31
- package/src/components/checkbox-group.tsx +1 -4
- package/src/components/chip-input.tsx +6 -6
- package/src/components/chip.tsx +14 -26
- package/src/components/choice-card.tsx +4 -18
- package/src/components/column-mapper-labels.ts +3 -10
- package/src/components/column-mapper.tsx +33 -122
- package/src/components/combobox-core.tsx +17 -47
- package/src/components/combobox.tsx +2 -6
- package/src/components/confirm-dialog.tsx +1 -3
- package/src/components/copy-button.tsx +2 -4
- package/src/components/country-select.tsx +9 -21
- package/src/components/currency-option-list.tsx +16 -18
- package/src/components/currency-select.tsx +2 -7
- package/src/components/danger-confirm.tsx +8 -9
- package/src/components/data-table-cells.tsx +1 -2
- package/src/components/data-table-column-settings.tsx +1 -3
- package/src/components/data-table-filter-popover.tsx +5 -19
- package/src/components/data-table-filters.ts +1 -6
- package/src/components/data-table-fit.ts +7 -7
- package/src/components/data-table-groups.tsx +3 -1
- package/src/components/data-table-head.tsx +32 -46
- package/src/components/data-table-mobile.tsx +99 -108
- package/src/components/data-table-pagination.tsx +2 -6
- package/src/components/data-table-row-actions.tsx +25 -24
- package/src/components/data-table-row.tsx +16 -17
- package/src/components/data-table-shared.tsx +10 -16
- package/src/components/data-table-sort.ts +1 -2
- package/src/components/data-table-virtual.ts +9 -4
- package/src/components/data-table.tsx +497 -501
- package/src/components/date-picker.tsx +1 -7
- package/src/components/date-range-picker.tsx +3 -13
- package/src/components/description-list.tsx +7 -13
- package/src/components/dialog-frame.tsx +12 -3
- package/src/components/disclosure.tsx +8 -12
- package/src/components/dropdown.tsx +3 -11
- package/src/components/empty-state.tsx +1 -3
- package/src/components/entity-combobox.tsx +2 -6
- package/src/components/error-boundary.tsx +7 -7
- package/src/components/field-base.tsx +8 -14
- package/src/components/field-parts.tsx +12 -23
- package/src/components/field-sync.tsx +7 -11
- package/src/components/file-button.tsx +7 -3
- package/src/components/file-dropzone.tsx +7 -12
- package/src/components/floating-panel.tsx +44 -51
- package/src/components/focus-ring.ts +1 -2
- package/src/components/form-actions.tsx +1 -4
- package/src/components/grouped-picker.tsx +21 -16
- package/src/components/hover-menu.tsx +1 -4
- package/src/components/iban-input-labels.ts +1 -2
- package/src/components/icon-button.tsx +46 -48
- package/src/components/icon-picker.tsx +9 -20
- package/src/components/image-grid.tsx +1 -6
- package/src/components/inline-edit-field.tsx +1 -5
- package/src/components/inline-entity-combobox.tsx +11 -25
- package/src/components/input.tsx +14 -2
- package/src/components/jump-calendar.tsx +2 -6
- package/src/components/legal-labels.ts +8 -3
- package/src/components/legal-page.tsx +56 -6
- package/src/components/legal.tsx +83 -10
- package/src/components/lightbox.tsx +1 -3
- package/src/components/line-items.tsx +7 -15
- package/src/components/list-labels.ts +2 -0
- package/src/components/list.tsx +81 -27
- package/src/components/measured-grid.tsx +8 -30
- package/src/components/menu-item.tsx +1 -3
- package/src/components/mini-calendar.tsx +129 -159
- package/src/components/money-field.tsx +4 -2
- package/src/components/month-picker.tsx +14 -21
- package/src/components/multi-entity-combobox.tsx +6 -26
- package/src/components/multi-select.tsx +5 -9
- package/src/components/nav-pills.tsx +10 -2
- package/src/components/number-field.tsx +18 -15
- package/src/components/number-input.tsx +3 -19
- package/src/components/numpad-sheet.tsx +9 -13
- package/src/components/one-time-code-input.tsx +6 -11
- package/src/components/page-contents.tsx +2 -9
- package/src/components/page-header.tsx +5 -10
- package/src/components/password-strength-labels.ts +1 -2
- package/src/components/password-strength.tsx +6 -9
- package/src/components/phone-input.tsx +2 -13
- package/src/components/picker-sheet.tsx +2 -5
- package/src/components/pie-chart.tsx +6 -12
- package/src/components/popover.tsx +2 -1
- package/src/components/progress-bar.tsx +16 -25
- package/src/components/qr-code.tsx +2 -9
- package/src/components/row-actions.tsx +9 -1
- package/src/components/search-field.tsx +4 -5
- package/src/components/select.tsx +2 -10
- package/src/components/separator.tsx +1 -5
- package/src/components/series-chart-axes.ts +5 -5
- package/src/components/series-chart-budget.ts +1 -4
- package/src/components/series-chart-ticks.ts +1 -4
- package/src/components/series-chart.tsx +43 -83
- package/src/components/settings-fields.tsx +20 -15
- package/src/components/share-card.tsx +6 -14
- package/src/components/sign-chip.tsx +16 -16
- package/src/components/signature-pad.tsx +21 -13
- package/src/components/signed-amount.tsx +6 -14
- package/src/components/skeleton.tsx +2 -13
- package/src/components/slider.tsx +9 -20
- package/src/components/sparkline.tsx +2 -13
- package/src/components/stat-tile.tsx +13 -24
- package/src/components/swatch-picker.tsx +8 -3
- package/src/components/swipeable-row.tsx +2 -11
- package/src/components/table-skeleton.tsx +4 -1
- package/src/components/table.tsx +12 -8
- package/src/components/tabs.tsx +24 -39
- package/src/components/text-link.tsx +6 -6
- package/src/components/text.tsx +1 -2
- package/src/components/tile-radio.tsx +6 -19
- package/src/components/time-input.tsx +4 -5
- package/src/components/toast.tsx +3 -12
- package/src/components/toggle-group.tsx +9 -9
- package/src/components/toggle-legend.tsx +4 -16
- package/src/components/tooltip.tsx +9 -48
- package/src/components/translation-review-editor.tsx +4 -4
- package/src/components/translation-review-parts.tsx +7 -1
- package/src/components/translation-review.tsx +15 -16
- package/src/components/tree-view.tsx +17 -20
- package/src/components/treemap.tsx +3 -15
- package/src/components/trigger-aria.ts +1 -4
- package/src/components/use-table-state.ts +16 -17
- package/src/components/user-avatar.tsx +4 -21
- package/src/demo/demo-start.tsx +8 -4
- package/src/feedback/feedback-attachment-labels.ts +2 -1
- package/src/feedback/feedback-attachment.tsx +16 -29
- package/src/feedback/feedback-capture.ts +3 -1
- package/src/feedback/feedback-comment-thread.tsx +9 -6
- package/src/feedback/feedback-context.tsx +1 -4
- package/src/feedback/feedback-dialog.tsx +3 -4
- package/src/feedback/feedback-inbox.tsx +3 -9
- package/src/feedback/feedback-public-list.tsx +7 -1
- package/src/feedback/feedback-record.ts +6 -14
- package/src/feedback/feedback-replies.tsx +10 -5
- package/src/feedback/feedback-row-detail.tsx +2 -5
- package/src/feedback/feedback-status-undo.ts +1 -4
- package/src/feedback/feedback-submit-dialog.tsx +4 -4
- package/src/feedback/feedback-table.tsx +29 -9
- package/src/feedback/feedback-thread.tsx +4 -16
- package/src/feedback/feedback-vocabulary.ts +72 -82
- package/src/feedback/feedback-vote-button.tsx +9 -8
- package/src/hooks/use-anchored-rect.ts +1 -4
- package/src/hooks/use-document-title.ts +3 -1
- package/src/hooks/use-file-drop.ts +1 -3
- package/src/hooks/use-file-picker-labels.ts +1 -2
- package/src/hooks/use-file-picker.tsx +1 -5
- package/src/hooks/use-focus-trap.ts +1 -2
- package/src/hooks/use-overlay-history.ts +10 -5
- package/src/hooks/use-row-swipe.ts +1 -6
- package/src/i18n/defaults.ts +1 -4
- package/src/i18n/german.ts +42 -50
- package/src/i18n/kit-labels.tsx +5 -20
- package/src/i18n/languages.ts +2 -8
- package/src/i18n/locales/en.ts +15 -31
- package/src/i18n/locales/es.ts +44 -50
- package/src/i18n/locales/fr.ts +43 -52
- package/src/i18n/locales/hu.ts +35 -38
- package/src/i18n/locales/it.ts +44 -53
- package/src/i18n/locales/zh.ts +23 -33
- package/src/i18n/plurals.ts +4 -1
- package/src/i18n/review.ts +20 -7
- package/src/i18n/shared-labels.ts +1 -2
- package/src/index.ts +107 -32
- package/src/landing/access.ts +2 -7
- package/src/landing/landing-sections.tsx +14 -15
- package/src/landing/page-seo.ts +1 -3
- package/src/lib/calc.ts +4 -1
- package/src/lib/clipboard-minus.ts +4 -1
- package/src/lib/dates.ts +2 -10
- package/src/lib/decimal-marks.ts +1 -3
- package/src/lib/device-settings.ts +2 -1
- package/src/lib/direction.ts +1 -3
- package/src/lib/iban.ts +89 -9
- package/src/lib/logger.ts +1 -5
- package/src/lib/person-name.ts +1 -3
- package/src/lib/phone.ts +5 -8
- package/src/lib/qr-encode.ts +32 -8
- package/src/lib/session-refresh.ts +5 -6
- package/src/lib/table-text.ts +24 -6
- package/src/lib/text-match.ts +43 -1
- package/src/lib/translation-review.ts +1 -3
- package/src/notifications/notification-inbox.tsx +17 -4
- package/src/notifications/notification-parts.tsx +1 -2
- package/src/notifications/notification-types-setting.tsx +19 -18
- package/src/notifications/notifications-labels.ts +1 -2
- package/src/notifications/push-device-setting.tsx +7 -1
- package/src/notifications/push-devices-setting.tsx +7 -3
- package/src/notifications/push-worker.ts +10 -2
- package/src/notifications/quiet-hours-setting.tsx +4 -1
- package/src/notifications/use-push-device.ts +4 -1
- package/src/offline/pwa-update-prompt.tsx +7 -1
- package/src/offline/query-persistence.ts +9 -6
- package/src/offline.ts +6 -1
- package/src/rhf/fields.tsx +50 -19
- package/src/rhf/form-core.tsx +2 -6
- package/src/rhf/line-items.tsx +5 -7
- package/src/rhf/use-rhf-wizard-step.ts +3 -12
- package/src/search/command-palette.tsx +15 -23
- package/src/search/global-search.tsx +38 -8
- package/src/search/search-index.ts +5 -1
- package/src/settings/device-reset-setting.tsx +5 -8
- package/src/settings/settings-heading.tsx +3 -1
- package/src/settings/settings-layout.tsx +6 -13
- package/src/settings/use-settings-focus.ts +8 -0
- package/src/settings/use-settings-route.ts +4 -3
- package/src/shell/app-shell.tsx +48 -24
- package/src/shell/auth-layout.tsx +1 -6
- package/src/shell/dev-menu.tsx +18 -6
- package/src/shell/option-switcher-menu.tsx +1 -3
- package/src/shell/sync-status-indicator.tsx +14 -12
- package/src/shell/top-bar-parts-labels.ts +1 -3
- package/src/shell/topbar-action-menu.tsx +130 -45
- package/src/shell/topbar-controls.tsx +5 -19
- package/src/shell/tour-menu.tsx +9 -1
- package/src/shell.ts +1 -1
- package/src/sync/db.ts +5 -1
- package/src/sync/engine.ts +44 -12
- package/src/sync.ts +16 -2
- package/src/testing/css-variables.ts +1 -2
- package/src/testing/index.ts +1 -6
- package/src/testing/react.ts +1 -2
- package/src/testing/viewport.ts +9 -9
- package/src/theme/contrast-tokens.ts +13 -2
- package/src/theme/palette-derive.ts +24 -50
- package/src/theme/palette-presets.ts +0 -1
- package/src/theme/palette-store.ts +1 -4
- package/src/theme/text-size.ts +1 -1
- package/src/theme/theme-store.ts +2 -6
- package/src/tour/tour-catalogue.tsx +4 -2
- package/src/tour/tour-dock.ts +5 -1
- package/src/tour/tour-engine.ts +2 -6
- package/src/tour/tour.tsx +28 -12
- package/src/tour/use-tour-progress.ts +8 -2
- package/src/tour/use-tour-url-sync.ts +3 -1
- package/src/vite-env.d.ts +1 -4
- package/src/wizard/stepper-nav.tsx +10 -35
- package/src/wizard/types.ts +1 -4
- package/src/wizard/use-wizard.ts +28 -43
- package/src/wizard/validation.ts +1 -5
- package/src/wizard/wizard-context.tsx +2 -6
- package/src/wizard/wizard-step.tsx +1 -8
- package/src/wizard/wizard-summary.tsx +2 -6
- package/tokens.css +393 -152
package/src/shell/dev-menu.tsx
CHANGED
|
@@ -126,6 +126,11 @@ const isRow = (entry: TopBarMenuEntry) => entry.kind !== "heading" && entry.kind
|
|
|
126
126
|
*
|
|
127
127
|
* Nothing renders unless `enabled`, and nothing with no row to show. The panel scrolls
|
|
128
128
|
* (`TopBarActionMenu`'s `scrollable`): some 25 rows ran off a 390×844 phone.
|
|
129
|
+
*
|
|
130
|
+
* From `md` up the groups stand side by side, one column each, in that order (0.51.4,
|
|
131
|
+
* `TopBarActionMenu`'s `columns`; keksdose dev #640, Marcel: "Each group gets a column").
|
|
132
|
+
* "Back to {role}" stays under the roles. A desktop too narrow for all of them wraps
|
|
133
|
+
* the columns onto a second row; a phone keeps the one scrolling column.
|
|
129
134
|
*/
|
|
130
135
|
export function DevMenu<R extends string, P extends string>({
|
|
131
136
|
enabled,
|
|
@@ -177,9 +182,12 @@ export function DevMenu<R extends string, P extends string>({
|
|
|
177
182
|
roles && roles.length > 0 && role !== undefined && onRole
|
|
178
183
|
? [
|
|
179
184
|
{ kind: "heading", key: "head-role", label: words.roleHeading },
|
|
180
|
-
...roles.map(
|
|
181
|
-
|
|
182
|
-
|
|
185
|
+
...roles.map((r): TopBarMenuEntry => ({
|
|
186
|
+
key: `role-${r}`,
|
|
187
|
+
label: roleLabel(r),
|
|
188
|
+
checked: r === role,
|
|
189
|
+
onSelect: () => pickRole(r),
|
|
190
|
+
})),
|
|
183
191
|
// Behind a rule, which ends the role group: "Back to" is a way out, not a role.
|
|
184
192
|
...(original !== undefined && original !== role
|
|
185
193
|
? ([
|
|
@@ -220,9 +228,12 @@ export function DevMenu<R extends string, P extends string>({
|
|
|
220
228
|
words.planHeading
|
|
221
229
|
),
|
|
222
230
|
},
|
|
223
|
-
...plans.map(
|
|
224
|
-
|
|
225
|
-
|
|
231
|
+
...plans.map((p): TopBarMenuEntry => ({
|
|
232
|
+
key: `plan-${p}`,
|
|
233
|
+
label: planLabel(p),
|
|
234
|
+
checked: p === plan,
|
|
235
|
+
onSelect: () => onPlan(p),
|
|
236
|
+
})),
|
|
226
237
|
]
|
|
227
238
|
: [];
|
|
228
239
|
|
|
@@ -254,6 +265,7 @@ export function DevMenu<R extends string, P extends string>({
|
|
|
254
265
|
aria-label={name}
|
|
255
266
|
entries={entries}
|
|
256
267
|
scrollable
|
|
268
|
+
columns
|
|
257
269
|
/>
|
|
258
270
|
);
|
|
259
271
|
}
|
|
@@ -60,9 +60,7 @@ export function OptionSwitcherMenu<T extends string>({
|
|
|
60
60
|
{(close) => (
|
|
61
61
|
<ul className="py-1">
|
|
62
62
|
{heading && (
|
|
63
|
-
<li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">
|
|
64
|
-
{heading}
|
|
65
|
-
</li>
|
|
63
|
+
<li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">{heading}</li>
|
|
66
64
|
)}
|
|
67
65
|
{options.map((opt) => (
|
|
68
66
|
<li key={opt.value}>
|
|
@@ -160,10 +160,7 @@ export function SyncStatusIndicator({
|
|
|
160
160
|
|
|
161
161
|
const onlineOnly = storage === "none";
|
|
162
162
|
// Online-only: nothing waits on the device, so only offline, error, saving and settled.
|
|
163
|
-
const state = syncState(
|
|
164
|
-
onlineOnly ? { ...status, pending: 0, blocked: 0, waitingForPlan: 0 } : status,
|
|
165
|
-
refreshing,
|
|
166
|
-
);
|
|
163
|
+
const state = syncState(onlineOnly ? { ...status, pending: 0, blocked: 0, waitingForPlan: 0 } : status, refreshing);
|
|
167
164
|
const data = dataAttributes(rest);
|
|
168
165
|
if (hideWhenIdle && state === "synced") return null;
|
|
169
166
|
|
|
@@ -190,12 +187,13 @@ export function SyncStatusIndicator({
|
|
|
190
187
|
text = words.pending(status.pending);
|
|
191
188
|
break;
|
|
192
189
|
default:
|
|
193
|
-
text =
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
190
|
+
text =
|
|
191
|
+
!onlineOnly && status.lastSyncedAt
|
|
192
|
+
? words.syncedAt(
|
|
193
|
+
// A clock time in the UI's language, never the browser's (keksdose live #246).
|
|
194
|
+
new Date(status.lastSyncedAt).toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" }),
|
|
195
|
+
)
|
|
196
|
+
: words.idle;
|
|
199
197
|
}
|
|
200
198
|
if (scope) {
|
|
201
199
|
text = state === "offline" && scope.offline ? scope.offline : words.scoped(scope.name, text);
|
|
@@ -272,7 +270,10 @@ export function SyncStatusIndicator({
|
|
|
272
270
|
{...data}
|
|
273
271
|
role="status"
|
|
274
272
|
data-sync-state={state}
|
|
275
|
-
className={cn(
|
|
273
|
+
className={cn(
|
|
274
|
+
"relative inline-flex size-9 shrink-0 items-center justify-center [&>svg]:size-5",
|
|
275
|
+
TEXT_TONE[tone],
|
|
276
|
+
)}
|
|
276
277
|
>
|
|
277
278
|
{glyph}
|
|
278
279
|
<span className="sr-only">{name}</span>
|
|
@@ -288,7 +289,8 @@ export function SyncStatusIndicator({
|
|
|
288
289
|
</Tooltip>
|
|
289
290
|
);
|
|
290
291
|
|
|
291
|
-
if (!showLabel || !short)
|
|
292
|
+
if (!showLabel || !short)
|
|
293
|
+
return className ? <span className={cn("inline-flex", className)}>{control}</span> : control;
|
|
292
294
|
return (
|
|
293
295
|
<span className={cn("inline-flex items-center gap-1", className)}>
|
|
294
296
|
{control}
|
|
@@ -115,9 +115,7 @@ export const DEFAULT_TOP_BAR_PARTS_LABELS: TopBarPartsLabels = {
|
|
|
115
115
|
},
|
|
116
116
|
sync: {
|
|
117
117
|
blocked: (count) =>
|
|
118
|
-
count === 1
|
|
119
|
-
? "1 change cannot be sent from this device"
|
|
120
|
-
: `${count} changes cannot be sent from this device`,
|
|
118
|
+
count === 1 ? "1 change cannot be sent from this device" : `${count} changes cannot be sent from this device`,
|
|
121
119
|
offline: "Offline — changes are saved on this device and will sync when you reconnect",
|
|
122
120
|
refused: "The server refused the last sync",
|
|
123
121
|
syncing: "Syncing…",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useId, useLayoutEffect, useRef } from "react";
|
|
2
|
-
import type { KeyboardEvent as ReactKeyboardEvent, ReactNode } from "react";
|
|
2
|
+
import type { CSSProperties, KeyboardEvent as ReactKeyboardEvent, ReactNode } from "react";
|
|
3
3
|
import { Link } from "react-router";
|
|
4
4
|
import { cn } from "../lib/cn";
|
|
5
5
|
import { HoverMenu, type HoverMenuProps } from "../components/hover-menu";
|
|
@@ -83,7 +83,8 @@ type DividerEntry = Extract<TopBarMenuEntry, { kind: "divider" }>;
|
|
|
83
83
|
type RowEntry = Exclude<TopBarMenuEntry, HeadingEntry | DividerEntry>;
|
|
84
84
|
|
|
85
85
|
/** What the panel draws from `entries`: loose rows and rules, and headed groups. */
|
|
86
|
-
type Block =
|
|
86
|
+
type Block =
|
|
87
|
+
{ kind: "loose"; entry: RowEntry | DividerEntry } | { kind: "group"; heading: HeadingEntry; rows: RowEntry[] };
|
|
87
88
|
|
|
88
89
|
/**
|
|
89
90
|
* Cut `entries` into blocks: a heading opens a group that takes the rows after it until
|
|
@@ -109,6 +110,40 @@ function toBlocks(entries: readonly TopBarMenuEntry[]): Block[] {
|
|
|
109
110
|
return blocks.filter((block) => block.kind === "loose" || block.rows.length > 0);
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
/** One column of `columns` (0.51.4): a group and the loose entries after it, up to the
|
|
114
|
+
* next group — so a group's own way out behind a rule (DevMenu's "Back to {role}") stays
|
|
115
|
+
* under it instead of running across the panel. */
|
|
116
|
+
type LooseBlock = Extract<Block, { kind: "loose" }>;
|
|
117
|
+
type Column = { group: Extract<Block, { kind: "group" }>; after: Array<RowEntry | DividerEntry>; index: number };
|
|
118
|
+
|
|
119
|
+
/** `blocks` as the columns layout draws them: what comes before the first group, then a
|
|
120
|
+
* column per group. A rule that would end a column is dropped: the column's edge is the
|
|
121
|
+
* separation there. */
|
|
122
|
+
function toColumns(blocks: readonly Block[]): { lead: LooseBlock[]; columns: Column[] } {
|
|
123
|
+
const lead: LooseBlock[] = [];
|
|
124
|
+
const columns: Column[] = [];
|
|
125
|
+
blocks.forEach((block, index) => {
|
|
126
|
+
if (block.kind === "group") columns.push({ group: block, after: [], index });
|
|
127
|
+
else if (columns.length === 0) lead.push(block);
|
|
128
|
+
else columns[columns.length - 1]!.after.push(block.entry);
|
|
129
|
+
});
|
|
130
|
+
for (const column of columns) {
|
|
131
|
+
while (column.after.at(-1)?.kind === "divider") column.after.pop();
|
|
132
|
+
}
|
|
133
|
+
return { lead, columns };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* `columns`' panel: each column 14rem, the panel as wide as its columns (a CSS variable
|
|
138
|
+
* the list sets) but never wider than the glass, and from `md` up only. The grid places
|
|
139
|
+
* as many 14rem columns as that width holds, so a narrow desktop wraps the groups onto a
|
|
140
|
+
* second row instead of scrolling sideways. The header, the title and the footer span
|
|
141
|
+
* the row.
|
|
142
|
+
*/
|
|
143
|
+
const COLUMNS_PANEL =
|
|
144
|
+
"md:grid md:grid-cols-[repeat(auto-fill,minmax(14rem,1fr))] md:items-start md:gap-y-2 md:w-[min(calc(100vw-2rem),var(--menu-columns-width))]";
|
|
145
|
+
const SPAN_ALL = "md:col-span-full";
|
|
146
|
+
|
|
112
147
|
/**
|
|
113
148
|
* The non-interactive identity block at the top of an account menu — kastlan's name +
|
|
114
149
|
* role, keksdose's display name + email + role chip. It is text, not a `menuitem`: the
|
|
@@ -133,7 +168,8 @@ export interface TopBarMenuHeader {
|
|
|
133
168
|
/** What a control is, as far as `HoverMenu` is concerned, when it lives in the header
|
|
134
169
|
* or the footer: not a menu row. */
|
|
135
170
|
const SECTION_CONTROLS = "a[href]:not([role]),button:not([role])";
|
|
136
|
-
const TABBABLE =
|
|
171
|
+
const TABBABLE =
|
|
172
|
+
"a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]";
|
|
137
173
|
|
|
138
174
|
/**
|
|
139
175
|
* `scrollable`'s cap (0.51, DevMenu): the glass under the bar. Under `TopBar` the panel
|
|
@@ -225,6 +261,7 @@ export function TopBarActionMenu({
|
|
|
225
261
|
align,
|
|
226
262
|
panelClassName,
|
|
227
263
|
scrollable = false,
|
|
264
|
+
columns = false,
|
|
228
265
|
triggerAttributes,
|
|
229
266
|
}: {
|
|
230
267
|
/** The trigger's face for the usual icon button. Ignored when `trigger` is given. */
|
|
@@ -308,6 +345,19 @@ export function TopBarActionMenu({
|
|
|
308
345
|
* header and the footer are inside the list and scroll with the rows.
|
|
309
346
|
*/
|
|
310
347
|
scrollable?: boolean;
|
|
348
|
+
/**
|
|
349
|
+
* From `md` up, lay the heading groups side by side, one column per group (0.51.4,
|
|
350
|
+
* `DevMenu`; keksdose dev #640, Marcel: "Each group gets a column. That way it would be
|
|
351
|
+
* much better visible for desktop users"). Below `md`, the one column as before.
|
|
352
|
+
*
|
|
353
|
+
* A column is a group and the loose rows after it up to the next heading, so a row
|
|
354
|
+
* behind a rule at the end of a group (DevMenu's "Back to {role}") stays in that
|
|
355
|
+
* group's column. Loose rows before the first heading, the header, the menu-wide
|
|
356
|
+
* `heading` and the footer span the panel. The DOM order is unchanged, so ↓/↑ walk the
|
|
357
|
+
* rows down one column and on into the next, as a reader reads them. `leading` and
|
|
358
|
+
* `children` rows take a cell each; add `md:col-span-full` to one that should span.
|
|
359
|
+
*/
|
|
360
|
+
columns?: boolean;
|
|
311
361
|
/** `data-*` attributes for the trigger itself — a tour's anchor (`data-tour`), a test
|
|
312
362
|
* hook. The parts built on this menu (`TourMenu`) pass theirs through here. */
|
|
313
363
|
triggerAttributes?: { [key: `data-${string}`]: string | number | boolean | undefined };
|
|
@@ -316,6 +366,10 @@ export function TopBarActionMenu({
|
|
|
316
366
|
// entry's `key`, which is the caller's text and may hold a space — and a space in
|
|
317
367
|
// `aria-labelledby` is a list separator.
|
|
318
368
|
const uid = useId();
|
|
369
|
+
const blocks = toBlocks(entries);
|
|
370
|
+
const grouped = columns ? toColumns(blocks) : null;
|
|
371
|
+
// A menu with no group has nothing to put side by side: the list as always.
|
|
372
|
+
const laidOut = grouped && grouped.columns.length > 0 ? grouped : null;
|
|
319
373
|
return (
|
|
320
374
|
<HoverMenu
|
|
321
375
|
aria-label={ariaLabel}
|
|
@@ -350,8 +404,7 @@ export function TopBarActionMenu({
|
|
|
350
404
|
<>
|
|
351
405
|
<span className="sr-only">{ariaLabel}</span>
|
|
352
406
|
{/* The space keeps the name from running into the face's text ("Account
|
|
353
|
-
menu3 unread"); as a flex item it takes no room. */}
|
|
354
|
-
{" "}
|
|
407
|
+
menu3 unread"); as a flex item it takes no room. */}{" "}
|
|
355
408
|
{trigger({ open })}
|
|
356
409
|
</>,
|
|
357
410
|
);
|
|
@@ -380,8 +433,8 @@ export function TopBarActionMenu({
|
|
|
380
433
|
const footerClass =
|
|
381
434
|
"flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted [&_a:hover]:text-primary [&_a]:rounded-sm [&_a:focus-visible]:outline-none [&_a:focus-visible]:ring-focus [&_a:focus-visible]:ring-brand";
|
|
382
435
|
/** One action or link row — loose, or inside a heading's group. */
|
|
383
|
-
const row = (entry: RowEntry) => (
|
|
384
|
-
<li key={entry.key}>
|
|
436
|
+
const row = (entry: RowEntry, className?: string) => (
|
|
437
|
+
<li key={entry.key} className={className}>
|
|
385
438
|
{entry.kind === "link" ? (
|
|
386
439
|
<MenuItem
|
|
387
440
|
href={entry.to}
|
|
@@ -413,58 +466,90 @@ export function TopBarActionMenu({
|
|
|
413
466
|
)}
|
|
414
467
|
</li>
|
|
415
468
|
);
|
|
469
|
+
/** A rule or a row outside any group; `span` stretches it across the columns. */
|
|
470
|
+
const loose = (block: LooseBlock, span: boolean) => {
|
|
471
|
+
const entry = block.entry;
|
|
472
|
+
if (entry.kind === "divider") {
|
|
473
|
+
return <li key={entry.key} className={cn("my-1 border-t border-subtle", span && SPAN_ALL)} />;
|
|
474
|
+
}
|
|
475
|
+
return row(entry, span ? SPAN_ALL : undefined);
|
|
476
|
+
};
|
|
477
|
+
/** A heading's group: its name, then its rows in a named `role="group"`. */
|
|
478
|
+
const group = (block: Extract<Block, { kind: "group" }>, i: number, tight: boolean, inColumn = false) => {
|
|
479
|
+
const headingId = `${uid}-group-${i}`;
|
|
480
|
+
return (
|
|
481
|
+
<li key={block.heading.key} role="none">
|
|
482
|
+
<div
|
|
483
|
+
id={headingId}
|
|
484
|
+
role="presentation"
|
|
485
|
+
className={cn(
|
|
486
|
+
"px-3 pb-0.5 text-caption font-semibold uppercase tracking-wide text-muted [overflow-wrap:anywhere]",
|
|
487
|
+
// A column's heading lines up with its neighbours' at the top of the
|
|
488
|
+
// grid row; under `md` the columns stack, and it spaces like the list's.
|
|
489
|
+
tight ? "pt-1" : cn("pt-2.5", inColumn && "md:pt-1"),
|
|
490
|
+
)}
|
|
491
|
+
>
|
|
492
|
+
{block.heading.label}
|
|
493
|
+
</div>
|
|
494
|
+
<ul role="group" aria-labelledby={headingId}>
|
|
495
|
+
{block.rows.map((entry) => row(entry))}
|
|
496
|
+
</ul>
|
|
497
|
+
</li>
|
|
498
|
+
);
|
|
499
|
+
};
|
|
416
500
|
return (
|
|
417
501
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- a Tab bubbling up from a row or footer link, see keepTabInsidePanel
|
|
418
|
-
<ul
|
|
502
|
+
<ul
|
|
503
|
+
className={cn("py-1", scrollable && SCROLLABLE_PANEL, laidOut && COLUMNS_PANEL, panelClassName)}
|
|
504
|
+
style={
|
|
505
|
+
laidOut ? ({ "--menu-columns-width": `${laidOut.columns.length * 14}rem` } as CSSProperties) : undefined
|
|
506
|
+
}
|
|
507
|
+
onKeyDown={keepTabInsidePanel}
|
|
508
|
+
>
|
|
419
509
|
{header && (
|
|
420
|
-
<MenuSection className="mb-1 border-b border-subtle px-3 py-2">
|
|
510
|
+
<MenuSection className={cn("mb-1 border-b border-subtle px-3 py-2", laidOut && SPAN_ALL)}>
|
|
421
511
|
<div className="truncate text-sm font-medium text-primary">{header.title}</div>
|
|
422
|
-
{header.subtitle != null &&
|
|
423
|
-
<div className="truncate text-xs text-muted">{header.subtitle}</div>
|
|
424
|
-
)}
|
|
512
|
+
{header.subtitle != null && <div className="truncate text-xs text-muted">{header.subtitle}</div>}
|
|
425
513
|
{headerExtra != null && headerExtra !== false && <div className="mt-1">{headerExtra}</div>}
|
|
426
514
|
</MenuSection>
|
|
427
515
|
)}
|
|
428
516
|
{heading && (
|
|
429
|
-
<li
|
|
517
|
+
<li
|
|
518
|
+
className={cn(
|
|
519
|
+
"px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder",
|
|
520
|
+
laidOut && SPAN_ALL,
|
|
521
|
+
)}
|
|
522
|
+
>
|
|
430
523
|
{heading}
|
|
431
524
|
</li>
|
|
432
525
|
)}
|
|
433
526
|
{leading?.(close)}
|
|
434
|
-
{
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
{block.heading.label}
|
|
458
|
-
</div>
|
|
459
|
-
<ul role="group" aria-labelledby={headingId}>
|
|
460
|
-
{block.rows.map(row)}
|
|
461
|
-
</ul>
|
|
462
|
-
</li>
|
|
463
|
-
);
|
|
464
|
-
})}
|
|
527
|
+
{laidOut ? (
|
|
528
|
+
<>
|
|
529
|
+
{laidOut.lead.map((block) => loose(block, true))}
|
|
530
|
+
{laidOut.columns.map((column, c) => (
|
|
531
|
+
// A column of the grid; under `md` a group as in the list, its rows
|
|
532
|
+
// following.
|
|
533
|
+
<li key={column.group.heading.key} role="none" data-menu-column="" className="min-w-0">
|
|
534
|
+
<ul role="none">
|
|
535
|
+
{group(column.group, column.index, c === 0 && laidOut.lead.length === 0, true)}
|
|
536
|
+
{column.after.map((entry) => loose({ kind: "loose", entry }, false))}
|
|
537
|
+
</ul>
|
|
538
|
+
</li>
|
|
539
|
+
))}
|
|
540
|
+
</>
|
|
541
|
+
) : (
|
|
542
|
+
blocks.map((block, i) => {
|
|
543
|
+
if (block.kind === "loose") return loose(block, false);
|
|
544
|
+
const before = blocks[i - 1];
|
|
545
|
+
// Under a rule (or at the top of the rows) the rule's margin is the gap;
|
|
546
|
+
// straight under another group's last row the heading makes its own.
|
|
547
|
+
return group(block, i, !before || (before.kind === "loose" && before.entry.kind === "divider"));
|
|
548
|
+
})
|
|
549
|
+
)}
|
|
465
550
|
{children?.(close)}
|
|
466
551
|
{footerBody != null && footerBody !== false && (
|
|
467
|
-
<MenuSection className="mt-1 border-t border-subtle px-3 py-2">
|
|
552
|
+
<MenuSection className={cn("mt-1 border-t border-subtle px-3 py-2", laidOut && SPAN_ALL)}>
|
|
468
553
|
{footerLabel ? (
|
|
469
554
|
<nav aria-label={footerLabel} className={footerClass}>
|
|
470
555
|
{footerBody}
|
|
@@ -19,11 +19,7 @@ export const TOPBAR_MENU_ITEM_CLASS =
|
|
|
19
19
|
|
|
20
20
|
/** The small uppercase heading row the top-bar menus share (`heading`). */
|
|
21
21
|
function MenuHeading({ children }: { children: string }) {
|
|
22
|
-
return
|
|
23
|
-
<li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">
|
|
24
|
-
{children}
|
|
25
|
-
</li>
|
|
26
|
-
);
|
|
22
|
+
return <li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">{children}</li>;
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
/**
|
|
@@ -108,12 +104,7 @@ export function PaletteMenu({
|
|
|
108
104
|
aria-label={labels.palette}
|
|
109
105
|
trigger={({ toggle }) => (
|
|
110
106
|
<Tooltip label={activeName} portal>
|
|
111
|
-
<button
|
|
112
|
-
type="button"
|
|
113
|
-
onClick={toggle}
|
|
114
|
-
aria-label={labels.palette}
|
|
115
|
-
className={TOPBAR_TRIGGER_CLASS}
|
|
116
|
-
>
|
|
107
|
+
<button type="button" onClick={toggle} aria-label={labels.palette} className={TOPBAR_TRIGGER_CLASS}>
|
|
117
108
|
{/* A DATA colour, not a semantic one: the palette mark is the
|
|
118
109
|
"colour" control, so it carries a colour, and which hue is
|
|
119
110
|
arbitrary. `--chart-1` is the violet end of the CVD-safe
|
|
@@ -155,14 +146,10 @@ export function PaletteMenu({
|
|
|
155
146
|
</span>
|
|
156
147
|
<span className="flex min-w-0 flex-col text-start">
|
|
157
148
|
<span className="truncate">{p.name}</span>
|
|
158
|
-
<span className="truncate text-caption text-placeholder">
|
|
159
|
-
{p.blurb}
|
|
160
|
-
</span>
|
|
149
|
+
<span className="truncate text-caption text-placeholder">{p.blurb}</span>
|
|
161
150
|
</span>
|
|
162
151
|
</span>
|
|
163
|
-
{activeId === p.id &&
|
|
164
|
-
<Check className="size-4 shrink-0 text-secondary" />
|
|
165
|
-
)}
|
|
152
|
+
{activeId === p.id && <Check className="size-4 shrink-0 text-secondary" />}
|
|
166
153
|
</button>
|
|
167
154
|
</li>
|
|
168
155
|
);
|
|
@@ -186,8 +173,7 @@ export type LanguageMenuTrigger = "flag+code" | "code" | "flag";
|
|
|
186
173
|
/** The trigger with a code: as tall as the others, as wide as flag and code need. */
|
|
187
174
|
const LANGUAGE_TRIGGER_WIDE_CLASS = TOPBAR_TRIGGER_CLASS.replace("size-9", "h-9 min-w-9 gap-1.5 px-2");
|
|
188
175
|
|
|
189
|
-
const FLAG_CLASS =
|
|
190
|
-
"inline-block h-[0.9375rem] w-5 shrink-0 rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)]";
|
|
176
|
+
const FLAG_CLASS = "inline-block h-[0.9375rem] w-5 shrink-0 rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)]";
|
|
191
177
|
|
|
192
178
|
/** Language switcher: a hover menu of options with flags and a check on the
|
|
193
179
|
* active one. Controlled — the app owns the current code and change handler.
|
package/src/shell/tour-menu.tsx
CHANGED
|
@@ -148,7 +148,15 @@ export function TourMenu({
|
|
|
148
148
|
const tail: TopBarMenuEntry[] = [
|
|
149
149
|
...rest.map(entryFor),
|
|
150
150
|
...(href
|
|
151
|
-
? [
|
|
151
|
+
? [
|
|
152
|
+
{
|
|
153
|
+
kind: "link" as const,
|
|
154
|
+
key: "all-tours",
|
|
155
|
+
icon: <Compass className="size-4" />,
|
|
156
|
+
label: words.allTours,
|
|
157
|
+
to: href,
|
|
158
|
+
},
|
|
159
|
+
]
|
|
152
160
|
: []),
|
|
153
161
|
];
|
|
154
162
|
|
package/src/shell.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type {
|
|
|
41
41
|
SettingsLocationRules,
|
|
42
42
|
SettingsLocationResult,
|
|
43
43
|
} from "./settings/use-settings-route";
|
|
44
|
-
export { useSettingsFocus, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus";
|
|
44
|
+
export { useSettingsFocus, useFocusParam, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus";
|
|
45
45
|
export { SettingsSection } from "./settings/settings-section";
|
|
46
46
|
export type { SettingsSectionProps } from "./settings/settings-section";
|
|
47
47
|
export { useSettingsLayout } from "./settings/settings-context";
|
package/src/sync/db.ts
CHANGED
|
@@ -98,7 +98,11 @@ export const SYNC_DB_PK_INDEX = {
|
|
|
98
98
|
*/
|
|
99
99
|
export async function rowByPk(db: SyncDb, entity: string, pk: number): Promise<SyncedRow | undefined> {
|
|
100
100
|
if (db.rows.schema.idxByName["[entity+pk]"]) return db.rows.where("[entity+pk]").equals([entity, pk]).first();
|
|
101
|
-
return db.rows
|
|
101
|
+
return db.rows
|
|
102
|
+
.where("entity")
|
|
103
|
+
.equals(entity)
|
|
104
|
+
.filter((row) => row.pk === pk)
|
|
105
|
+
.first();
|
|
102
106
|
}
|
|
103
107
|
|
|
104
108
|
/**
|
package/src/sync/engine.ts
CHANGED
|
@@ -103,7 +103,13 @@ export interface SyncEngine {
|
|
|
103
103
|
/** Into the copy at once and into the queue, in the scope the caller names (D11). An edit
|
|
104
104
|
* merges into the row's last `pending` upsert; deleting a row that never reached the
|
|
105
105
|
* server forgets its queue; stamped with `stampAfter`. */
|
|
106
|
-
write(
|
|
106
|
+
write(
|
|
107
|
+
scope: string,
|
|
108
|
+
entity: string,
|
|
109
|
+
id: string,
|
|
110
|
+
op: "upsert" | "delete",
|
|
111
|
+
data?: Record<string, unknown>,
|
|
112
|
+
): Promise<void>;
|
|
107
113
|
start(): void;
|
|
108
114
|
/** Stops the poll and the timers, aborts the round in flight and drops its answer (the
|
|
109
115
|
* queue is laid back). A new engine's round on the same database waits for it. */
|
|
@@ -164,9 +170,9 @@ function defaultPlanCode(err: unknown): string | null {
|
|
|
164
170
|
* `{detail: {code, detail}}`. */
|
|
165
171
|
function refusalOf(err: unknown): { code?: string; detail?: string } {
|
|
166
172
|
const body = (err as { response?: { data?: unknown } }).response?.data as
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
173
|
+
{ code?: unknown; detail?: unknown } | undefined;
|
|
174
|
+
const inner =
|
|
175
|
+
body?.detail && typeof body.detail === "object" ? (body.detail as { code?: unknown; detail?: unknown }) : body;
|
|
170
176
|
const text = (v: unknown) => (typeof v === "string" && v ? v : undefined);
|
|
171
177
|
return { code: text(inner?.code), detail: text(inner?.detail) };
|
|
172
178
|
}
|
|
@@ -200,7 +206,13 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
200
206
|
const sharedComputer = options.sharedComputer ?? isSharedComputer;
|
|
201
207
|
|
|
202
208
|
let generation = 0;
|
|
203
|
-
let state: SyncEngineState = {
|
|
209
|
+
let state: SyncEngineState = {
|
|
210
|
+
phase: "idle",
|
|
211
|
+
online: browserOnline(),
|
|
212
|
+
counts: ZERO,
|
|
213
|
+
lastSyncedAt: null,
|
|
214
|
+
nextRetryAt: null,
|
|
215
|
+
};
|
|
204
216
|
const listeners = new Set<() => void>();
|
|
205
217
|
let started = false;
|
|
206
218
|
let poll: ReturnType<typeof setInterval> | null = null;
|
|
@@ -281,7 +293,8 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
281
293
|
const rejected = sent.filter((c) => !refusedIds.has(c.id) && rejections.has(c.id));
|
|
282
294
|
await db.outbox.bulkDelete(sent.filter((c) => !refusedIds.has(c.id) && !rejections.has(c.id)).map((c) => c.seq!));
|
|
283
295
|
const hold = refused != null && holdCodes.has(refused.code);
|
|
284
|
-
if (refused)
|
|
296
|
+
if (refused)
|
|
297
|
+
await mark(kept, { status: hold ? "waiting" : "blocked", code: refused.code, reason: refused.detail });
|
|
285
298
|
for (const change of rejected) {
|
|
286
299
|
const why = rejections.get(change.id)!;
|
|
287
300
|
await db.outbox.update(change.seq!, { status: "rejected", code: why.code, reason: why.detail });
|
|
@@ -313,7 +326,13 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
313
326
|
continue;
|
|
314
327
|
}
|
|
315
328
|
const row = (await db.rows.get([change.entity, change.id])) as CopyRow | undefined;
|
|
316
|
-
await db.rows.put({
|
|
329
|
+
await db.rows.put({
|
|
330
|
+
...row,
|
|
331
|
+
entity: change.entity,
|
|
332
|
+
id: change.id,
|
|
333
|
+
pk: row?.pk ?? null,
|
|
334
|
+
data: { ...row?.data, ...change.data },
|
|
335
|
+
});
|
|
317
336
|
}
|
|
318
337
|
if (lastPage) {
|
|
319
338
|
await db.meta.put({ key: lastKnowledgeKey(scope), value: answer.server_knowledge });
|
|
@@ -345,7 +364,12 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
345
364
|
|
|
346
365
|
type ScopeResult = { offline: true } | { offline: false; waiting: number; blocked: number; rejected: number };
|
|
347
366
|
|
|
348
|
-
async function syncScope(
|
|
367
|
+
async function syncScope(
|
|
368
|
+
scope: string,
|
|
369
|
+
gen: number,
|
|
370
|
+
signal: AbortSignal,
|
|
371
|
+
withBlocked: boolean,
|
|
372
|
+
): Promise<ScopeResult> {
|
|
349
373
|
const sent = await takeQueue(scope, withBlocked);
|
|
350
374
|
const last = Number((await db.meta.get(lastKnowledgeKey(scope)))?.value ?? 0) || 0;
|
|
351
375
|
const body = (changes: SyncWireChange[], page_cursor: SyncRequestBody["page_cursor"]): SyncRequestBody => ({
|
|
@@ -369,7 +393,8 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
369
393
|
await mark(sent, { status: "waiting", code: plan, reason: plan });
|
|
370
394
|
return { offline: false, waiting: sent.length, blocked: 0, rejected: 0 };
|
|
371
395
|
}
|
|
372
|
-
if (httpStatusOf(err) === 403)
|
|
396
|
+
if (httpStatusOf(err) === 403)
|
|
397
|
+
return { offline: false, waiting: 0, blocked: 0, rejected: await loseScope(scope, err) };
|
|
373
398
|
throw err;
|
|
374
399
|
}
|
|
375
400
|
let cursor = options.paged ? (answer.page_cursor ?? null) : null;
|
|
@@ -545,7 +570,9 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
545
570
|
const row = (await db.rows.get([entity, id])) as CopyRow | undefined;
|
|
546
571
|
const ofRow = await db.outbox.where("[entity+id]").equals([entity, id]).toArray();
|
|
547
572
|
ofRow.sort((a, b) => a.seq! - b.seq!);
|
|
548
|
-
const updated_at = stampAfter(
|
|
573
|
+
const updated_at = stampAfter(
|
|
574
|
+
latest([row?.updated_at, row?.data.updated_at, ...ofRow.map((c) => c.updated_at)]),
|
|
575
|
+
);
|
|
549
576
|
// A new edit to the row moves a rejected change out of the way (D13).
|
|
550
577
|
const rejected = ofRow.filter((c) => c.scope === scope && c.status === "rejected");
|
|
551
578
|
if (op === "delete") {
|
|
@@ -564,7 +591,10 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
564
591
|
const next: CopyRow = { ...row, entity, id, pk: row?.pk ?? null, data: { ...row?.data, ...data } };
|
|
565
592
|
if (!row) next.local = true;
|
|
566
593
|
await db.rows.put(next);
|
|
567
|
-
const carried = Object.assign({}, ...rejected.filter((c) => c.op === "upsert").map((c) => c.data)) as Record<
|
|
594
|
+
const carried = Object.assign({}, ...rejected.filter((c) => c.op === "upsert").map((c) => c.data)) as Record<
|
|
595
|
+
string,
|
|
596
|
+
unknown
|
|
597
|
+
>;
|
|
568
598
|
await db.outbox.bulkDelete(rejected.map((c) => c.seq!));
|
|
569
599
|
const last = ofRow.filter((c) => c.scope === scope && c.status === "pending").at(-1);
|
|
570
600
|
if (last && last.op === "upsert") {
|
|
@@ -628,7 +658,9 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
|
|
|
628
658
|
},
|
|
629
659
|
|
|
630
660
|
async discardRejected(scope) {
|
|
631
|
-
const gone = (await db.outbox.where("status").equals("rejected").toArray()).filter(
|
|
661
|
+
const gone = (await db.outbox.where("status").equals("rejected").toArray()).filter(
|
|
662
|
+
(c) => !scope || c.scope === scope,
|
|
663
|
+
);
|
|
632
664
|
if (gone.length === 0) return;
|
|
633
665
|
await db.transaction("rw", db.rows, db.outbox, db.meta, async () => {
|
|
634
666
|
await db.outbox.bulkDelete(gone.map((c) => c.seq!));
|
package/src/sync.ts
CHANGED
|
@@ -5,8 +5,22 @@
|
|
|
5
5
|
// `/offline`'s TanStack and idb-keyval peers: the leaf utilities both entries export live in
|
|
6
6
|
// one module of their own (src/offline/local-first.ts). NOT re-exported from the main barrel.
|
|
7
7
|
export { createSyncDb, rowByPk, SYNC_DB_PK_INDEX, SYNC_DB_STORES } from "./sync/db";
|
|
8
|
-
export type {
|
|
9
|
-
|
|
8
|
+
export type {
|
|
9
|
+
CreateSyncDbOptions,
|
|
10
|
+
OutboxChange,
|
|
11
|
+
OutboxStatus,
|
|
12
|
+
SyncDb,
|
|
13
|
+
SyncDbUpgrade,
|
|
14
|
+
SyncedRow,
|
|
15
|
+
SyncMetaEntry,
|
|
16
|
+
} from "./sync/db";
|
|
17
|
+
export {
|
|
18
|
+
createSyncEngine,
|
|
19
|
+
DEFAULT_HOLD_CODES,
|
|
20
|
+
DEFAULT_SYNC_BACKOFF_MS,
|
|
21
|
+
releaseSyncEngine,
|
|
22
|
+
syncEngineFor,
|
|
23
|
+
} from "./sync/engine";
|
|
10
24
|
export type {
|
|
11
25
|
SyncCounts,
|
|
12
26
|
SyncEngine,
|
|
@@ -158,8 +158,7 @@ export function undeclaredCssVariables(
|
|
|
158
158
|
if (isCssPath(path)) for (const name of declaredCustomProperties(text)) declared.add(name);
|
|
159
159
|
for (const name of runtimeWrites(text)) declared.add(name);
|
|
160
160
|
}
|
|
161
|
-
const listed = (name: string) =>
|
|
162
|
-
runtime.some((r) => (typeof r === "string" ? r === name : r.test(name)));
|
|
161
|
+
const listed = (name: string) => runtime.some((r) => (typeof r === "string" ? r === name : r.test(name)));
|
|
163
162
|
|
|
164
163
|
const out: string[] = [];
|
|
165
164
|
for (const [path, text] of code) {
|
package/src/testing/index.ts
CHANGED
|
@@ -26,9 +26,4 @@ export {
|
|
|
26
26
|
} from "./viewport";
|
|
27
27
|
// 0.50.1 (keksdose N4): a valid `TourStepContext` for a test that calls a step's
|
|
28
28
|
// `beforeStep` or `when` itself — `beforeStep!(tourStepContext())`.
|
|
29
|
-
export {
|
|
30
|
-
tourStepContext,
|
|
31
|
-
type TestTourStepContext,
|
|
32
|
-
type TourStepContextOptions,
|
|
33
|
-
type TourStepVia,
|
|
34
|
-
} from "./tour";
|
|
29
|
+
export { tourStepContext, type TestTourStepContext, type TourStepContextOptions, type TourStepVia } from "./tour";
|