@eifi1/ui-kit 0.31.1 → 0.32.1
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 +51 -28
- package/dist/account/delete-account-setting.d.ts +8 -3
- package/dist/admin/admin-action-confirm.d.ts +8 -3
- package/dist/admin/admin-action-log.d.ts +1 -1
- package/dist/admin/admin-action-log.js +4 -2
- package/dist/admin/admin-action-log.js.map +1 -1
- package/dist/admin/invitations-panel.d.ts +8 -3
- package/dist/admin/invitations-panel.js +29 -26
- package/dist/admin/invitations-panel.js.map +1 -1
- package/dist/admin/reviewer-scope-editor.d.ts +8 -3
- package/dist/admin/role-select.d.ts +10 -5
- package/dist/admin/transfer-ownership-dialog.d.ts +8 -3
- package/dist/admin/user-roster.d.ts +10 -5
- package/dist/admin/user-roster.js +8 -47
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/auth-errors.d.ts +43 -8
- package/dist/auth/auth-errors.js +24 -1
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/register-form.d.ts +8 -3
- package/dist/billing/billing-banner.d.ts +184 -0
- package/dist/billing/billing-banner.js +98 -0
- package/dist/billing/billing-banner.js.map +1 -0
- package/dist/billing/billing-labels.d.ts +100 -0
- package/dist/billing/billing-labels.js +76 -0
- package/dist/billing/billing-labels.js.map +1 -0
- package/dist/billing/billing-lock.d.ts +158 -0
- package/dist/billing/billing-lock.js +17 -0
- package/dist/billing/billing-lock.js.map +1 -0
- package/dist/billing/billing-standing.d.ts +149 -0
- package/dist/billing/billing-standing.js +28 -0
- package/dist/billing/billing-standing.js.map +1 -0
- package/dist/billing/plan-card.d.ts +248 -0
- package/dist/billing/plan-card.js +248 -0
- package/dist/billing/plan-card.js.map +1 -0
- package/dist/billing/plan-limit-notice.d.ts +156 -0
- package/dist/billing/plan-limit-notice.js +76 -0
- package/dist/billing/plan-limit-notice.js.map +1 -0
- package/dist/billing/plan-limit.d.ts +34 -0
- package/dist/billing/plan-limit.js +20 -0
- package/dist/billing/plan-limit.js.map +1 -0
- package/dist/billing/plan-price.d.ts +61 -0
- package/dist/billing/plan-price.js +45 -0
- package/dist/billing/plan-price.js.map +1 -0
- package/dist/billing/subscription-actions.d.ts +133 -0
- package/dist/billing/subscription-actions.js +28 -0
- package/dist/billing/subscription-actions.js.map +1 -0
- package/dist/billing/subscription-status-chip.d.ts +149 -0
- package/dist/billing/subscription-status-chip.js +48 -0
- package/dist/billing/subscription-status-chip.js.map +1 -0
- package/dist/chart.d.ts +9 -3
- package/dist/chart.js.map +1 -1
- package/dist/components/account-chips.d.ts +16 -4
- package/dist/components/account-chips.js +21 -3
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/alert-banner.d.ts +6 -1
- package/dist/components/alert-banner.js +5 -4
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +8 -3
- package/dist/components/amount-input.js +5 -5
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/appearance-labels.d.ts +38 -0
- package/dist/components/appearance-labels.js +19 -0
- package/dist/components/appearance-labels.js.map +1 -0
- package/dist/components/autocomplete.js +2 -2
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/breadcrumbs.js +3 -2
- package/dist/components/breadcrumbs.js.map +1 -1
- package/dist/components/bulk-action-bar.d.ts +2 -2
- package/dist/components/bulk-action-bar.js +7 -12
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button-group.d.ts +8 -3
- package/dist/components/button-group.js +7 -1
- package/dist/components/button-group.js.map +1 -1
- package/dist/components/calculator.d.ts +8 -3
- package/dist/components/calculator.js +4 -3
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/calendar-heatmap.js +5 -5
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/chart-height.d.ts +23 -0
- package/dist/components/chart-height.js +15 -0
- package/dist/components/chart-height.js.map +1 -0
- package/dist/components/chart-zoom.js +6 -1
- package/dist/components/chart-zoom.js.map +1 -1
- package/dist/components/checkbox-group.js +2 -2
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/checkbox.d.ts +10 -0
- package/dist/components/checkbox.js +25 -10
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +19 -3
- package/dist/components/chip.js +54 -23
- package/dist/components/chip.js.map +1 -1
- package/dist/components/choice-card.d.ts +1 -1
- package/dist/components/choice-card.js +9 -8
- package/dist/components/choice-card.js.map +1 -1
- package/dist/components/column-mapper.js +1 -1
- package/dist/components/column-mapper.js.map +1 -1
- package/dist/components/combobox-core.js +8 -7
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +8 -8
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +8 -3
- package/dist/components/copy-button.d.ts +10 -5
- package/dist/components/country-select.js +1 -1
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-select.js +3 -3
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +8 -3
- package/dist/components/data-table-cells.d.ts +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filter-popover.js +4 -1
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table-labels.d.ts +1 -1
- package/dist/components/data-table-pagination.d.ts +3 -2
- package/dist/components/data-table-pagination.js +15 -6
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +123 -52
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +1 -1
- package/dist/components/date-picker.js +18 -6
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/description-list.js +2 -2
- package/dist/components/description-list.js.map +1 -1
- package/dist/components/dialog-frame.js +2 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/disclosure.js +3 -2
- package/dist/components/disclosure.js.map +1 -1
- package/dist/components/dropdown.d.ts +1 -1
- package/dist/components/dropdown.js +7 -1
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/facing-pair.d.ts +19 -6
- package/dist/components/facing-pair.js +3 -2
- package/dist/components/facing-pair.js.map +1 -1
- package/dist/components/field-parts.d.ts +102 -6
- package/dist/components/field-parts.js +81 -6
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-sync.d.ts +4 -1
- package/dist/components/field-sync.js +12 -2
- package/dist/components/field-sync.js.map +1 -1
- package/dist/components/field.js +2 -2
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-button.d.ts +8 -3
- package/dist/components/file-dropzone.d.ts +8 -3
- package/dist/components/floating-panel.js +7 -4
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/focus-ring.d.ts +12 -0
- package/dist/components/focus-ring.js +8 -0
- package/dist/components/focus-ring.js.map +1 -0
- package/dist/components/form-actions.d.ts +8 -3
- package/dist/components/form-actions.js +33 -19
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/full-bleed-dialog.d.ts +11 -1
- package/dist/components/full-bleed-dialog.js +3 -1
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/iban-input.d.ts +8 -3
- package/dist/components/image-grid.js +1 -1
- package/dist/components/image-grid.js.map +1 -1
- package/dist/components/inline-edit-field.js +10 -4
- package/dist/components/inline-edit-field.js.map +1 -1
- package/dist/components/language-select.d.ts +8 -3
- package/dist/components/legal-page.d.ts +26 -5
- package/dist/components/legal-page.js +3 -1
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +8 -3
- package/dist/components/legal.js +2 -1
- package/dist/components/legal.js.map +1 -1
- package/dist/components/lightbox.js +24 -2
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/line-items.js +2 -1
- package/dist/components/line-items.js.map +1 -1
- package/dist/components/list.d.ts +5 -0
- package/dist/components/list.js +13 -9
- package/dist/components/list.js.map +1 -1
- package/dist/components/measured-grid.d.ts +3 -1
- package/dist/components/measured-grid.js +38 -20
- package/dist/components/measured-grid.js.map +1 -1
- package/dist/components/menu-item.js +2 -1
- package/dist/components/menu-item.js.map +1 -1
- package/dist/components/mini-calendar.js +8 -4
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/money-field.d.ts +8 -3
- package/dist/components/month-picker.js +50 -39
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/nav-pills.js +1 -1
- package/dist/components/nav-pills.js.map +1 -1
- package/dist/components/number-field.d.ts +8 -3
- package/dist/components/number-input.d.ts +11 -4
- package/dist/components/number-input.js +8 -6
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +8 -3
- package/dist/components/numpad-sheet.js +2 -1
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/one-time-code-input.js +2 -2
- package/dist/components/one-time-code-input.js.map +1 -1
- package/dist/components/page-contents.js +2 -2
- package/dist/components/page-contents.js.map +1 -1
- package/dist/components/phone-input.d.ts +8 -3
- package/dist/components/phone-input.js +4 -4
- package/dist/components/phone-input.js.map +1 -1
- package/dist/components/pie-chart.d.ts +8 -2
- package/dist/components/pie-chart.js +11 -7
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/popover.d.ts +9 -1
- package/dist/components/popover.js +8 -4
- package/dist/components/popover.js.map +1 -1
- package/dist/components/row-actions.d.ts +100 -0
- package/dist/components/row-actions.js +231 -0
- package/dist/components/row-actions.js.map +1 -0
- package/dist/components/scroll-area.js +1 -1
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/search-field.js +3 -2
- package/dist/components/search-field.js.map +1 -1
- package/dist/components/series-chart-budget.d.ts +30 -7
- package/dist/components/series-chart-budget.js +12 -4
- package/dist/components/series-chart-budget.js.map +1 -1
- package/dist/components/series-chart-ticks.d.ts +7 -1
- package/dist/components/series-chart-ticks.js +6 -0
- package/dist/components/series-chart-ticks.js.map +1 -1
- package/dist/components/series-chart.d.ts +58 -28
- package/dist/components/series-chart.js +42 -32
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/settings-fields.d.ts +57 -8
- package/dist/components/settings-fields.js +39 -1
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/share-card.d.ts +11 -6
- package/dist/components/share-card.js +8 -2
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/sign-chip.d.ts +4 -0
- package/dist/components/sign-chip.js +17 -4
- package/dist/components/sign-chip.js.map +1 -1
- package/dist/components/signature-pad.d.ts +3 -1
- package/dist/components/signature-pad.js +8 -5
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/slider.js +7 -6
- package/dist/components/slider.js.map +1 -1
- package/dist/components/sparkline.d.ts +5 -1
- package/dist/components/sparkline.js +4 -2
- package/dist/components/sparkline.js.map +1 -1
- package/dist/components/stat-tile.d.ts +17 -1
- package/dist/components/stat-tile.js +48 -20
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/status-dot.d.ts +4 -0
- package/dist/components/status-dot.js +9 -2
- package/dist/components/status-dot.js.map +1 -1
- package/dist/components/swipeable-row.js +10 -2
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/switch.d.ts +21 -7
- package/dist/components/switch.js +24 -11
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table.js +2 -2
- package/dist/components/table.js.map +1 -1
- package/dist/components/text-link.d.ts +8 -3
- package/dist/components/text-link.js +1 -1
- package/dist/components/text-link.js.map +1 -1
- package/dist/components/text.d.ts +7 -2
- package/dist/components/text.js +5 -5
- package/dist/components/text.js.map +1 -1
- package/dist/components/tile-radio.js +2 -1
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +8 -3
- package/dist/components/toast.d.ts +18 -2
- package/dist/components/toast.js +8 -5
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.d.ts +25 -3
- package/dist/components/toggle-group.js +40 -11
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle-legend.d.ts +10 -1
- package/dist/components/toggle-legend.js +21 -7
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/translation-review-editor.js +1 -1
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review-parts.d.ts +4 -0
- package/dist/components/translation-review.d.ts +4 -0
- package/dist/components/translation-review.js +3 -3
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/tree-view.js +3 -2
- package/dist/components/tree-view.js.map +1 -1
- package/dist/components/treemap.d.ts +5 -2
- package/dist/components/treemap.js +33 -16
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/ui.d.ts +8 -3
- package/dist/components/ui.js +207 -119
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/components/user-avatar.d.ts +5 -1
- package/dist/components/user-avatar.js +1 -1
- package/dist/components/user-avatar.js.map +1 -1
- package/dist/components/wizard-stepper.js +20 -14
- package/dist/components/wizard-stepper.js.map +1 -1
- package/dist/{data-table-labels-DUELeXpa.d.ts → data-table-labels-kpAAVi6g.d.ts} +26 -2
- package/dist/data-table.d.ts +1 -1
- package/dist/{delete-account-setting-CpIhzxxZ.d.ts → delete-account-setting-FLyJf-kZ.d.ts} +642 -60
- package/dist/demo/demo-banner.js +1 -0
- package/dist/demo/demo-banner.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +8 -3
- package/dist/feedback/feedback-context.d.ts +8 -3
- package/dist/feedback/feedback-crash.d.ts +8 -3
- package/dist/feedback/feedback-dialog.d.ts +8 -3
- package/dist/feedback/feedback-dialog.js +3 -3
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +8 -3
- package/dist/feedback/feedback-inbox.js +2 -2
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-labels.d.ts +8 -3
- package/dist/feedback/feedback-menu.d.ts +9 -4
- package/dist/feedback/feedback-record.d.ts +8 -3
- package/dist/feedback/feedback-row-detail.d.ts +8 -3
- package/dist/feedback/feedback-status-undo.d.ts +8 -3
- package/dist/feedback/feedback-submit.d.ts +8 -3
- package/dist/feedback/feedback-swipe.d.ts +8 -3
- package/dist/feedback/feedback-table.d.ts +8 -3
- package/dist/feedback/feedback-thread.d.ts +8 -3
- package/dist/feedback/feedback-thread.js +3 -3
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +8 -3
- package/dist/hooks/use-anchored-panel.d.ts +32 -3
- package/dist/hooks/use-anchored-panel.js +21 -3
- package/dist/hooks/use-anchored-panel.js.map +1 -1
- package/dist/hooks/use-breakpoint.d.ts +88 -0
- package/dist/hooks/use-breakpoint.js +50 -0
- package/dist/hooks/use-breakpoint.js.map +1 -0
- package/dist/hooks/use-file-drop.d.ts +8 -3
- package/dist/hooks/use-large-text.d.ts +29 -0
- package/dist/hooks/use-large-text.js +20 -0
- package/dist/hooks/use-large-text.js.map +1 -0
- package/dist/hooks/use-windowed-rows.d.ts +52 -8
- package/dist/hooks/use-windowed-rows.js +94 -5
- package/dist/hooks/use-windowed-rows.js.map +1 -1
- package/dist/i18n/defaults.d.ts +8 -3
- package/dist/i18n/defaults.js +8 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +8 -3
- package/dist/i18n/german.js +94 -3
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +8 -3
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +10 -5
- package/dist/i18n/locales/de-CH.d.ts +8 -3
- package/dist/i18n/locales/en.d.ts +8 -3
- package/dist/i18n/locales/es.d.ts +8 -3
- package/dist/i18n/locales/es.js +89 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +8 -3
- package/dist/i18n/locales/fr.js +91 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +8 -3
- package/dist/i18n/locales/hu.js +91 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +8 -3
- package/dist/i18n/locales/it.js +92 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +8 -3
- package/dist/i18n/locales/zh.js +89 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +8 -3
- package/dist/i18n/review.js +15 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +27 -11
- package/dist/index.js +77 -4
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-actions.d.ts +8 -3
- package/dist/landing/landing-sections.d.ts +8 -3
- package/dist/landing/landing-sections.js +7 -3
- package/dist/landing/landing-sections.js.map +1 -1
- package/dist/landing/public-header.d.ts +9 -4
- package/dist/landing/public-header.js +3 -3
- package/dist/landing/public-header.js.map +1 -1
- package/dist/landing/routing.d.ts +8 -3
- package/dist/lib/cn.js +3 -2
- package/dist/lib/cn.js.map +1 -1
- package/dist/rhf/fields.d.ts +8 -3
- package/dist/rhf/fields.js +1 -1
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +8 -3
- package/dist/rhf/form.js +2 -2
- package/dist/rhf/form.js.map +1 -1
- package/dist/rhf.d.ts +8 -3
- package/dist/search/command-palette.d.ts +1 -1
- package/dist/search/command-palette.js +9 -8
- package/dist/search/command-palette.js.map +1 -1
- package/dist/settings/settings-layout.js +2 -1
- package/dist/settings/settings-layout.js.map +1 -1
- package/dist/settings/settings-section.d.ts +8 -3
- package/dist/settings/use-account-appearance.d.ts +92 -0
- package/dist/settings/use-account-appearance.js +63 -0
- package/dist/settings/use-account-appearance.js.map +1 -0
- package/dist/settings/use-settings-route.d.ts +1 -1
- package/dist/settings/use-settings-route.js +2 -3
- package/dist/settings/use-settings-route.js.map +1 -1
- package/dist/shell/app-shell.d.ts +12 -171
- package/dist/shell/app-shell.js +144 -28
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/auth-layout.js +1 -1
- package/dist/shell/auth-layout.js.map +1 -1
- package/dist/shell/option-switcher-menu.js +1 -1
- package/dist/shell/option-switcher-menu.js.map +1 -1
- package/dist/shell/top-bar-brand.d.ts +8 -3
- package/dist/shell/top-bar-brand.js +3 -1
- package/dist/shell/top-bar-brand.js.map +1 -1
- package/dist/shell/topbar-action-menu.d.ts +4 -0
- package/dist/shell/topbar-action-menu.js +3 -3
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell/topbar-controls.js +4 -4
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/shell.d.ts +9 -5
- package/dist/theme/contrast-tokens.d.ts +41 -0
- package/dist/theme/contrast-tokens.js +59 -0
- package/dist/theme/contrast-tokens.js.map +1 -0
- package/dist/theme/contrast.d.ts +110 -0
- package/dist/theme/contrast.js +128 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/palette-presets.d.ts +12 -1
- package/dist/theme/palette-presets.js +9 -4
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/text-size.d.ts +173 -0
- package/dist/theme/text-size.js +121 -0
- package/dist/theme/text-size.js.map +1 -0
- package/dist/wizard/stepper-nav.d.ts +8 -3
- package/dist/wizard/wizard-summary.js +1 -1
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/dist/wizard.d.ts +8 -3
- package/package.json +1 -1
- package/src/admin/admin-action-log.tsx +6 -1
- package/src/admin/invitations-panel.tsx +36 -29
- package/src/admin/user-roster.tsx +17 -72
- package/src/auth/auth-errors.ts +68 -7
- package/src/billing/billing-banner.tsx +205 -0
- package/src/billing/billing-labels.ts +240 -0
- package/src/billing/billing-lock.ts +75 -0
- package/src/billing/billing-standing.ts +72 -0
- package/src/billing/plan-card.tsx +458 -0
- package/src/billing/plan-limit-notice.tsx +145 -0
- package/src/billing/plan-limit.ts +53 -0
- package/src/billing/plan-price.ts +101 -0
- package/src/billing/subscription-actions.tsx +76 -0
- package/src/billing/subscription-status-chip.tsx +95 -0
- package/src/chart.ts +2 -0
- package/src/components/account-chips.tsx +36 -10
- package/src/components/alert-banner.tsx +16 -7
- package/src/components/amount-input.tsx +5 -5
- package/src/components/appearance-labels.ts +47 -0
- package/src/components/autocomplete.tsx +2 -2
- package/src/components/breadcrumbs.tsx +3 -3
- package/src/components/bulk-action-bar.tsx +11 -14
- package/src/components/button-group.tsx +21 -0
- package/src/components/calculator.tsx +4 -3
- package/src/components/calendar-heatmap.tsx +5 -5
- package/src/components/chart-height.ts +30 -0
- package/src/components/chart-zoom.tsx +6 -1
- package/src/components/checkbox-group.tsx +2 -2
- package/src/components/checkbox.tsx +62 -20
- package/src/components/chip.tsx +139 -30
- package/src/components/choice-card.tsx +16 -11
- package/src/components/column-mapper.tsx +1 -1
- package/src/components/combobox-core.tsx +8 -7
- package/src/components/combobox.tsx +8 -8
- package/src/components/country-select.tsx +1 -1
- package/src/components/currency-select.tsx +3 -3
- package/src/components/data-table-filter-popover.tsx +7 -1
- package/src/components/data-table-pagination.tsx +60 -31
- package/src/components/data-table.tsx +164 -43
- package/src/components/date-picker.tsx +44 -10
- package/src/components/description-list.tsx +2 -2
- package/src/components/dialog-frame.tsx +2 -1
- package/src/components/disclosure.tsx +3 -2
- package/src/components/dropdown.tsx +10 -2
- package/src/components/facing-pair.ts +12 -5
- package/src/components/field-parts.tsx +190 -7
- package/src/components/field-sync.tsx +17 -3
- package/src/components/field.tsx +2 -2
- package/src/components/floating-panel.tsx +7 -4
- package/src/components/focus-ring.ts +12 -0
- package/src/components/form-actions.tsx +55 -18
- package/src/components/full-bleed-dialog.tsx +18 -4
- package/src/components/image-grid.tsx +1 -1
- package/src/components/inline-edit-field.tsx +26 -4
- package/src/components/legal-page.tsx +28 -2
- package/src/components/legal.tsx +19 -1
- package/src/components/lightbox.tsx +24 -2
- package/src/components/line-items.tsx +7 -1
- package/src/components/list.tsx +36 -10
- package/src/components/measured-grid.tsx +49 -24
- package/src/components/menu-item.tsx +2 -2
- package/src/components/mini-calendar.tsx +8 -4
- package/src/components/month-picker.tsx +15 -6
- package/src/components/nav-pills.tsx +1 -1
- package/src/components/number-input.tsx +14 -7
- package/src/components/numpad-sheet.tsx +2 -2
- package/src/components/one-time-code-input.tsx +2 -2
- package/src/components/page-contents.tsx +2 -2
- package/src/components/phone-input.tsx +9 -4
- package/src/components/pie-chart.tsx +19 -9
- package/src/components/popover.tsx +22 -5
- package/src/components/row-actions.tsx +450 -0
- package/src/components/scroll-area.tsx +1 -1
- package/src/components/search-field.tsx +4 -2
- package/src/components/series-chart-budget.ts +40 -8
- package/src/components/series-chart-ticks.ts +10 -0
- package/src/components/series-chart.tsx +123 -72
- package/src/components/settings-fields.tsx +89 -5
- package/src/components/share-card.tsx +31 -2
- package/src/components/sign-chip.tsx +28 -4
- package/src/components/signature-pad.tsx +13 -7
- package/src/components/slider.tsx +22 -9
- package/src/components/sparkline.tsx +11 -3
- package/src/components/stat-tile.tsx +70 -14
- package/src/components/status-dot.tsx +25 -2
- package/src/components/swipeable-row.tsx +10 -2
- package/src/components/switch.tsx +57 -23
- package/src/components/table.tsx +2 -2
- package/src/components/text-link.tsx +1 -1
- package/src/components/text.tsx +11 -6
- package/src/components/tile-radio.tsx +4 -1
- package/src/components/toast.tsx +27 -7
- package/src/components/toggle-group.tsx +115 -14
- package/src/components/toggle-legend.tsx +53 -8
- package/src/components/translation-review-editor.tsx +1 -1
- package/src/components/translation-review.tsx +11 -5
- package/src/components/tree-view.tsx +3 -2
- package/src/components/treemap.tsx +27 -10
- package/src/components/ui.tsx +353 -153
- package/src/components/user-avatar.tsx +1 -1
- package/src/components/wizard-stepper.tsx +5 -1
- package/src/demo/demo-banner.tsx +5 -0
- package/src/feedback/feedback-dialog.tsx +3 -3
- package/src/feedback/feedback-inbox.tsx +2 -2
- package/src/feedback/feedback-thread.tsx +3 -3
- package/src/hooks/use-anchored-panel.ts +67 -5
- package/src/hooks/use-breakpoint.ts +132 -0
- package/src/hooks/use-large-text.ts +41 -0
- package/src/hooks/use-windowed-rows.ts +168 -12
- package/src/i18n/defaults.ts +8 -0
- package/src/i18n/german.ts +107 -0
- package/src/i18n/kit-labels.tsx +12 -0
- package/src/i18n/locales/es.ts +98 -0
- package/src/i18n/locales/fr.ts +102 -0
- package/src/i18n/locales/hu.ts +100 -0
- package/src/i18n/locales/it.ts +103 -0
- package/src/i18n/locales/zh.ts +94 -0
- package/src/i18n/review.ts +14 -0
- package/src/index.ts +76 -6
- package/src/landing/landing-sections.tsx +7 -3
- package/src/landing/public-header.tsx +4 -4
- package/src/lib/cn.ts +13 -2
- package/src/rhf/fields.tsx +1 -1
- package/src/rhf/form.tsx +2 -2
- package/src/search/command-palette.tsx +10 -9
- package/src/settings/settings-layout.tsx +2 -1
- package/src/settings/use-account-appearance.ts +148 -0
- package/src/settings/use-settings-route.ts +3 -4
- package/src/shell/app-shell.tsx +278 -54
- package/src/shell/auth-layout.tsx +1 -1
- package/src/shell/option-switcher-menu.tsx +1 -1
- package/src/shell/top-bar-brand.tsx +3 -1
- package/src/shell/topbar-action-menu.tsx +3 -3
- package/src/shell/topbar-controls.tsx +4 -4
- package/src/theme/contrast-tokens.ts +112 -0
- package/src/theme/contrast.ts +225 -0
- package/src/theme/palette-presets.ts +24 -4
- package/src/theme/palette-store.ts +6 -1
- package/src/theme/text-size.ts +283 -0
- package/src/wizard/wizard-summary.tsx +4 -2
- package/tokens.css +158 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/theme/text-size.ts"],"sourcesContent":["import { useEffect, useMemo, useSyncExternalStore } from \"react\";\nimport { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport { logger } from \"../lib/logger\";\nimport { readStored } from \"../lib/safe-storage\";\n\n/**\n * The text size (docs/text-size-harmonization.md §2.1, §3.1, §10.3, §10.6).\n *\n * ONE scale on `<html>`: `data-text-size=\"normal|large|xlarge\"`, and `tokens.css` turns\n * it into `font-size: 100% / 125% / 150%` — percent, never px, so \"Normal\" keeps\n * whatever size the person set in the browser. Tailwind's spacing and type are rem, so\n * about 90 % of every screen grows with that one declaration; the breakpoints follow too\n * (tokens.css redefines `sm:` … `3xl:` per size, {@link useBreakpoint} answers the same\n * in JS).\n *\n * The names below are the mechanism's public vocabulary and are FROZEN: an app's\n * storage, its `/auth/me` column (server-kit's `TEXT_SIZES`) and the inline boot snippet\n * all spell them this way.\n */\n\n/** The three steps, in order (§2.1, §10.6): server-kit's `TEXT_SIZES`, value for value. */\nexport const TEXT_SIZES = [\"normal\", \"large\", \"xlarge\"] as const;\n\nexport type TextSize = (typeof TEXT_SIZES)[number];\n\n/** The root font size each step sets, as a factor of the browser's own (tokens.css). For\n * what CSS cannot reach: a canvas or SVG chart's px constants, a windowed list's row\n * estimate, a popover width in px (§3.2). */\nexport const TEXT_SCALE: Readonly<Record<TextSize, number>> = { normal: 1, large: 1.25, xlarge: 1.5 };\n\n/** The attribute on `<html>` that carries the size. */\nconst TEXT_SIZE_ATTRIBUTE = \"data-text-size\";\n\nexport function isTextSize(value: unknown): value is TextSize {\n return value === \"normal\" || value === \"large\" || value === \"xlarge\";\n}\n\n/**\n * The size in force: **this device's own choice → the account's → Normal** (§2.2, §2.6).\n * Each is taken only when it is one of {@link TEXT_SIZES}; anything else (a stale value,\n * `null` = never chosen) falls through to the next. The one order the pre-paint call, the\n * apply hook and `useAccountAppearance` all use, so the three can never disagree.\n */\nexport function resolveTextSize(device: unknown, account?: unknown): TextSize {\n if (isTextSize(device)) return device;\n if (isTextSize(account)) return account;\n return \"normal\";\n}\n\n/* ── <html data-text-size> and the subscribers that read it ─────────────── */\n\nconst listeners = new Set<() => void>();\nlet observer: MutationObserver | null = null;\n\nfunction notify(): void {\n for (const listener of listeners) listener();\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n // Also catches writers that are not this module — the inline boot snippet, an app\n // setting the attribute by hand, a test.\n if (!observer && typeof MutationObserver !== \"undefined\" && typeof document !== \"undefined\") {\n observer = new MutationObserver(notify);\n observer.observe(document.documentElement, { attributes: true, attributeFilter: [TEXT_SIZE_ATTRIBUTE] });\n }\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n observer?.disconnect();\n observer = null;\n }\n };\n}\n\n/** The size `<html>` carries now; Normal without one (or outside a browser). */\nexport function readTextSize(): TextSize {\n if (typeof document === \"undefined\") return \"normal\";\n const value = document.documentElement.getAttribute(TEXT_SIZE_ATTRIBUTE);\n return isTextSize(value) ? value : \"normal\";\n}\n\n/** Put `size` on `<html>`. Every {@link useTextSize} re-renders with it. */\nexport function applyTextSize(size: TextSize): void {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n if (root.getAttribute(TEXT_SIZE_ATTRIBUTE) === size) return;\n root.setAttribute(TEXT_SIZE_ATTRIBUTE, size);\n notify();\n}\n\nexport interface TextSizeInfo {\n size: TextSize;\n /** {@link TEXT_SCALE} for `size`: 1, 1.25 or 1.5. */\n scale: number;\n}\n\n/**\n * The size in force on this page, and its scale (§3.1) — read from `<html>`, so it needs\n * no store and works in every kit component: whoever applied the size (the app's store,\n * the pre-paint call, the inline snippet), this follows it.\n *\n * Only for what CSS cannot do. A class that should differ at Large is a `large:`\n * variant; a layout switch is a breakpoint, which already scales.\n */\nexport function useTextSize(): TextSizeInfo {\n const size = useSyncExternalStore(subscribe, readTextSize, () => \"normal\" as const);\n return useMemo(() => ({ size, scale: TEXT_SCALE[size] }), [size]);\n}\n\n/* ── Storage: the frozen format, the pre-paint call ─────────────────────── */\n\n/**\n * What a text-size store persists under its key — zustand's persist envelope, and FROZEN\n * (§10.3) because an app's inline `<head>` snippet reads it before any module loads:\n *\n * {\"state\":{\"size\":\"large\"},\"version\":1}\n *\n * `size` is one of {@link TEXT_SIZES}, or `null` / absent when this device never chose.\n * A future change adds a key; it never renames `state.size` or changes its values.\n *\n * A hand-written seed (a test, a screenshot script) must carry `\"version\":1`: the store\n * drops a stored state of another version as a migration it doesn't know, silently\n * (keksdose's 0.32 report). The inline snippet reads `state.size` whatever the version,\n * so the two would disagree. In the kit's showcase, `?text-size=` needs no seed.\n */\nexport interface PersistedTextSize {\n state?: { size?: TextSize | null };\n version?: number;\n}\n\n/** This device's own choice under `storageKey`, or `null` when it never chose (or the\n * storage is blocked, malformed, or holds a value that is not a size). */\nexport function readPersistedTextSize(storageKey: string): TextSize | null {\n try {\n const blob = JSON.parse(readStored(storageKey) ?? \"null\") as PersistedTextSize | null;\n const size = blob?.state?.size;\n return isTextSize(size) ? size : null;\n } catch {\n return null;\n }\n}\n\nexport interface PersistedAppearanceOptions {\n /**\n * The account's last known value, for a device without a choice of its own (§10.3):\n * what the app persisted with its user (keksdose keeps `/auth/me` in localStorage), so\n * a cold boot paints the account's size instead of Normal and then jumping — offline\n * too. Called once, guarded: a throw counts as \"no account value\".\n */\n account?: () => string | null | undefined;\n}\n\nfunction readAccount(account: PersistedAppearanceOptions[\"account\"]): unknown {\n if (!account) return undefined;\n try {\n return account();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Pre-paint (§3.1, §10.3): read this device's choice under `storageKey` — else the\n * account's last known value — and put it on `<html>` BEFORE `createRoot`, next to\n * `applyPersistedTheme`, so the first paint already has the right size. Returns the size\n * applied.\n *\n * ```ts\n * applyPersistedTextSize(\"keksdose-text-size\", {\n * account: () => readPersistedUser()?.text_size,\n * });\n * ```\n */\nexport function applyPersistedTextSize(storageKey: string, options: PersistedAppearanceOptions = {}): TextSize {\n const size = resolveTextSize(readPersistedTextSize(storageKey), readAccount(options.account));\n applyTextSize(size);\n return size;\n}\n\n/**\n * The same pre-paint as {@link applyPersistedTextSize}, as an inline `<head>` script for\n * a boot splash painted from `index.html` before any module runs (§10.3). A function\n * EXPRESSION: call it with the storage key and, optionally, a function returning the\n * account's last known value.\n *\n * ```html\n * <script>\n * (function(k,a){…})(\"keksdose-text-size\", function () {\n * return JSON.parse(localStorage.getItem(\"keksdose-auth\")).state.user.text_size;\n * });\n * </script>\n * ```\n *\n * Paste the constant's value in place of `(function(k,a){…})`. It reads the frozen\n * {@link PersistedTextSize} format, never throws, and sets only `data-text-size`.\n *\n * The splash sizes in rem, and needs the root rules inline beside it, since the app's\n * stylesheet is a separate request and arrives after the splash paints (0.32.1,\n * keksdose's 0.32 report: that is every app, not an edge case):\n *\n * ```html\n * <style>html[data-text-size=large]{font-size:125%}html[data-text-size=xlarge]{font-size:150%}</style>\n * ```\n *\n * Under a hash-based Content Security Policy (`script-src 'sha256-…'`) this is a second\n * inline script with its own hash: add it to the policy, and recompute it whenever the\n * storage key or the account function in the call changes (keksdose added it to both\n * its Caddyfiles, and its guard test hashes every inline script).\n */\nexport const TEXT_SIZE_INLINE_SCRIPT =\n \"(function(k,a){function ok(v){return v==='normal'||v==='large'||v==='xlarge'}\" +\n \"var v=null;try{var s=JSON.parse(localStorage.getItem(k)||'null');v=s&&s.state&&s.state.size}catch(e){}\" +\n \"if(!ok(v)){v=null;try{v=a?a():null}catch(e){}}\" +\n \"try{document.documentElement.setAttribute('data-text-size',ok(v)?v:'normal')}catch(e){}})\";\n\n/* ── The store ──────────────────────────────────────────────────────────── */\n\nexport interface TextSizeState {\n /** This device's own choice (persisted), or `null` when it never chose — then the\n * account's value applies (§2.2). */\n size: TextSize | null;\n /** Store this device's choice; `null` forgets it, so the account's applies again. */\n setSize: (size: TextSize | null) => void;\n}\n\nexport interface ApplyTextSizeOptions {\n /** The account's value (`/auth/me`'s `text_size`): it applies while this device has no\n * choice of its own. Leave it out where there is no account. */\n account?: string | null;\n}\n\n/**\n * Build a text-size store bound to a consumer-supplied localStorage key, shaped like\n * `createThemeStore` (§6). It holds the DEVICE's choice only; the account's value comes\n * in through `useApplyTextSize({ account })` and `useAccountAppearance`, and the size in\n * force is always {@link resolveTextSize} of the two.\n *\n * - `useTextSizeStore` — the zustand hook: `size` (device choice or null) and `setSize`.\n * - `useApplyTextSize({ account })` — the effect that puts the size in force on `<html>`.\n * Mount it once near the root, beside `useApplyTheme`.\n *\n * The persisted format is {@link PersistedTextSize}, and frozen.\n */\nexport function createTextSizeStore(storageKey: string) {\n const useTextSizeStore = create<TextSizeState>()(\n logger(\n persist(\n (set) => ({\n size: null,\n setSize: (size) => set({ size: isTextSize(size) ? size : null }),\n }),\n {\n name: storageKey,\n version: 1,\n partialize: (s) => ({ size: s.size }),\n // A hand-edited or future value must not reach <html> as an unknown size.\n merge: (persisted, current) => ({\n ...current,\n size: isTextSize((persisted as { size?: unknown } | null)?.size)\n ? ((persisted as { size: TextSize }).size)\n : null,\n }),\n },\n ),\n \"text-size\",\n ),\n );\n\n function useApplyTextSize({ account }: ApplyTextSizeOptions = {}): TextSize {\n const device = useTextSizeStore((s) => s.size);\n const size = resolveTextSize(device, account);\n useEffect(() => {\n applyTextSize(size);\n }, [size]);\n return size;\n }\n\n return { useTextSizeStore, useApplyTextSize };\n}\n\nexport type TextSizeStore = ReturnType<typeof createTextSizeStore>;\n"],"mappings":";AAAA,SAAS,WAAW,SAAS,4BAA4B;AACzD,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAkBpB,MAAM,aAAa,CAAC,UAAU,SAAS,QAAQ;AAO/C,MAAM,aAAiD,EAAE,QAAQ,GAAG,OAAO,MAAM,QAAQ,IAAI;AAGpG,MAAM,sBAAsB;AAErB,SAAS,WAAW,OAAmC;AAC5D,SAAO,UAAU,YAAY,UAAU,WAAW,UAAU;AAC9D;AAQO,SAAS,gBAAgB,QAAiB,SAA6B;AAC5E,MAAI,WAAW,MAAM,EAAG,QAAO;AAC/B,MAAI,WAAW,OAAO,EAAG,QAAO;AAChC,SAAO;AACT;AAIA,MAAM,YAAY,oBAAI,IAAgB;AACtC,IAAI,WAAoC;AAExC,SAAS,SAAe;AACtB,aAAW,YAAY,UAAW,UAAS;AAC7C;AAEA,SAAS,UAAU,UAAkC;AACnD,YAAU,IAAI,QAAQ;AAGtB,MAAI,CAAC,YAAY,OAAO,qBAAqB,eAAe,OAAO,aAAa,aAAa;AAC3F,eAAW,IAAI,iBAAiB,MAAM;AACtC,aAAS,QAAQ,SAAS,iBAAiB,EAAE,YAAY,MAAM,iBAAiB,CAAC,mBAAmB,EAAE,CAAC;AAAA,EACzG;AACA,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AACzB,QAAI,UAAU,SAAS,GAAG;AACxB,gBAAU,WAAW;AACrB,iBAAW;AAAA,IACb;AAAA,EACF;AACF;AAGO,SAAS,eAAyB;AACvC,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAM,QAAQ,SAAS,gBAAgB,aAAa,mBAAmB;AACvE,SAAO,WAAW,KAAK,IAAI,QAAQ;AACrC;AAGO,SAAS,cAAc,MAAsB;AAClD,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,OAAO,SAAS;AACtB,MAAI,KAAK,aAAa,mBAAmB,MAAM,KAAM;AACrD,OAAK,aAAa,qBAAqB,IAAI;AAC3C,SAAO;AACT;AAgBO,SAAS,cAA4B;AAC1C,QAAM,OAAO,qBAAqB,WAAW,cAAc,MAAM,QAAiB;AAClF,SAAO,QAAQ,OAAO,EAAE,MAAM,OAAO,WAAW,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;AAClE;AAyBO,SAAS,sBAAsB,YAAqC;AACzE,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,WAAW,UAAU,KAAK,MAAM;AACxD,UAAM,OAAO,MAAM,OAAO;AAC1B,WAAO,WAAW,IAAI,IAAI,OAAO;AAAA,EACnC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYA,SAAS,YAAY,SAAyD;AAC5E,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI;AACF,WAAO,QAAQ;AAAA,EACjB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAcO,SAAS,uBAAuB,YAAoB,UAAsC,CAAC,GAAa;AAC7G,QAAM,OAAO,gBAAgB,sBAAsB,UAAU,GAAG,YAAY,QAAQ,OAAO,CAAC;AAC5F,gBAAc,IAAI;AAClB,SAAO;AACT;AAgCO,MAAM,0BACX;AAiCK,SAAS,oBAAoB,YAAoB;AACtD,QAAM,mBAAmB,OAAsB;AAAA,IAC7C;AAAA,MACE;AAAA,QACE,CAAC,SAAS;AAAA,UACR,MAAM;AAAA,UACN,SAAS,CAAC,SAAS,IAAI,EAAE,MAAM,WAAW,IAAI,IAAI,OAAO,KAAK,CAAC;AAAA,QACjE;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,UACT,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK;AAAA;AAAA,UAEnC,OAAO,CAAC,WAAW,aAAa;AAAA,YAC9B,GAAG;AAAA,YACH,MAAM,WAAY,WAAyC,IAAI,IACzD,UAAiC,OACnC;AAAA,UACN;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,WAAS,iBAAiB,EAAE,QAAQ,IAA0B,CAAC,GAAa;AAC1E,UAAM,SAAS,iBAAiB,CAAC,MAAM,EAAE,IAAI;AAC7C,UAAM,OAAO,gBAAgB,QAAQ,OAAO;AAC5C,cAAU,MAAM;AACd,oBAAc,IAAI;AAAA,IACpB,GAAG,CAAC,IAAI,CAAC;AACT,WAAO;AAAA,EACT;AAEA,SAAO,EAAE,kBAAkB,iBAAiB;AAC9C;","names":[]}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ReactElement } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { bO as ButtonVariant } from '../delete-account-setting-FLyJf-kZ.js';
|
|
4
4
|
import { UseWizardReturn, WizardLabels } from './types.js';
|
|
5
5
|
import '../components/tooltip.js';
|
|
6
6
|
import '../hooks/use-anchored-rect.js';
|
|
7
7
|
import '../lib/clipping.js';
|
|
8
|
-
import '../data-table-labels-
|
|
8
|
+
import '../data-table-labels-kpAAVi6g.js';
|
|
9
9
|
import '../components/data-table-sort.js';
|
|
10
10
|
import '../components/swipeable-row.js';
|
|
11
11
|
import '../components/mini-calendar.js';
|
|
12
12
|
import '../components/calendar-heatmap.js';
|
|
13
13
|
import '../components/popover.js';
|
|
14
|
+
import '../hooks/use-breakpoint.js';
|
|
14
15
|
import '../components/chip.js';
|
|
15
16
|
import 'lucide-react';
|
|
17
|
+
import '../components/field-parts.js';
|
|
16
18
|
import '../components/field-sync.js';
|
|
17
19
|
import '../tour/tour.js';
|
|
18
20
|
import '../search/command-palette.js';
|
|
@@ -80,6 +82,9 @@ import '../admin/admin-parts.js';
|
|
|
80
82
|
import '../admin/admin-action-log.js';
|
|
81
83
|
import '../settings/settings-labels.js';
|
|
82
84
|
import '../demo/demo-labels.js';
|
|
85
|
+
import '../components/appearance-labels.js';
|
|
86
|
+
import '../theme/contrast.js';
|
|
87
|
+
import '../theme/text-size.js';
|
|
83
88
|
import '../components/reauth-dialog.js';
|
|
84
89
|
import '../components/server-wake.js';
|
|
85
90
|
import '../lib/server-wake.js';
|
|
@@ -93,7 +98,7 @@ import '../components/sign-chip.js';
|
|
|
93
98
|
import '../components/column-mapper.js';
|
|
94
99
|
import '../lib/column-mapping.js';
|
|
95
100
|
import '../lib/table-text.js';
|
|
96
|
-
import '../components/
|
|
101
|
+
import '../components/focus-ring.js';
|
|
97
102
|
|
|
98
103
|
/**
|
|
99
104
|
* The chrome around a wizard: the step indicator, the step content, and the
|
|
@@ -15,7 +15,7 @@ function WizardSummary({
|
|
|
15
15
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
16
16
|
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-[var(--text-primary)]", children: l.reviewTitle }),
|
|
17
17
|
sections.map((section, sIdx) => /* @__PURE__ */ jsxs(Card, { children: [
|
|
18
|
-
/* @__PURE__ */ jsxs(CardHeader, { className: "pb-2", children: [
|
|
18
|
+
/* @__PURE__ */ jsxs(CardHeader, { className: "pb-2", stackAction: false, children: [
|
|
19
19
|
/* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: section.label }),
|
|
20
20
|
section.stepIndex !== void 0 && onEditStep && /* @__PURE__ */ jsx(CardAction, { children: /* @__PURE__ */ jsx(Tooltip, { label: l.edit, children: /* @__PURE__ */ jsx(
|
|
21
21
|
IconButton,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/wizard/wizard-summary.tsx"],"sourcesContent":["import { Pencil } from \"lucide-react\";\nimport { Card, CardAction, CardContent, CardHeader, CardTitle, IconButton } from \"../components/ui\";\nimport { Tooltip } from \"../components/tooltip\";\nimport type { SummarySection, WizardLabels } from \"./types\";\nimport { DEFAULT_WIZARD_LABELS } from \"./types\";\nimport { useKitLabels } from \"../i18n/kit-labels\";\n\n/**\n * The review step: one card per section, each row a label/value pair, each card\n * carrying an edit button back to the step it came from.\n *\n * Sections are data, not children, because \"jump back to step N\" is the whole\n * point of the component and a caller assembling its own cards invariably drops\n * it. Labels and values are `ReactNode`, so a value can be a badge or a link.\n *\n * A section with no `stepIndex` (file-level counts, a total) is a card without an\n * edit button. `disabled` greys every edit button at once — while the commit runs,\n * when jumping back would show a step whose edits can no longer reach the request.\n */\nexport function WizardSummary({\n sections,\n onEditStep,\n disabled = false,\n labels,\n}: {\n sections: SummarySection[];\n /** Called with the section's `stepIndex`. Optional only for a summary whose\n * sections name no step at all. */\n onEditStep?: (stepIndex: number) => void;\n /** Disable every edit button (e.g. `wizard.isSubmitting`). */\n disabled?: boolean;\n labels?: Partial<WizardLabels>;\n}) {\n const l = useKitLabels(\"wizard\", DEFAULT_WIZARD_LABELS, labels);\n\n return (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">{l.reviewTitle}</h2>\n {sections.map((section, sIdx) => (\n <Card key={sIdx}>\n {/* CardHeader is a grid, and CardAction is the top-right column it\n reserves — the edit button has to go through it or it stacks under\n the title instead of sitting beside it. */}\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-base\">{section.label}</CardTitle>\n {section.stepIndex !== undefined && onEditStep && (\n <CardAction>\n {/* The kit Tooltip, not a native `title`: it shows on keyboard focus too,\n and an app with a one-tooltip rule (keksdose dev#523) sees one. */}\n <Tooltip label={l.edit}>\n <IconButton\n size=\"sm\"\n variant=\"ghost\"\n aria-label={l.edit}\n disabled={disabled}\n onClick={() => onEditStep(section.stepIndex as number)}\n >\n <Pencil />\n </IconButton>\n </Tooltip>\n </CardAction>\n )}\n </CardHeader>\n <CardContent>\n <dl className=\"grid gap-2 text-sm\">\n {section.items.map((item, iIdx) => (\n <div key={iIdx}>\n {iIdx > 0 && (\n <div className=\"mb-2 border-t border-[var(--border)]\" role=\"presentation\" />\n )}\n <div className=\"flex items-start justify-between gap-4\">\n <dt className=\"text-[var(--text-muted)]\">{item.label}</dt>\n <dd className=\"text-end font-medium text-[var(--text-primary)]\">\n {item.value}\n </dd>\n </div>\n </div>\n ))}\n </dl>\n </CardContent>\n </Card>\n ))}\n </div>\n );\n}\n"],"mappings":";AAqCM,
|
|
1
|
+
{"version":3,"sources":["../../src/wizard/wizard-summary.tsx"],"sourcesContent":["import { Pencil } from \"lucide-react\";\nimport { Card, CardAction, CardContent, CardHeader, CardTitle, IconButton } from \"../components/ui\";\nimport { Tooltip } from \"../components/tooltip\";\nimport type { SummarySection, WizardLabels } from \"./types\";\nimport { DEFAULT_WIZARD_LABELS } from \"./types\";\nimport { useKitLabels } from \"../i18n/kit-labels\";\n\n/**\n * The review step: one card per section, each row a label/value pair, each card\n * carrying an edit button back to the step it came from.\n *\n * Sections are data, not children, because \"jump back to step N\" is the whole\n * point of the component and a caller assembling its own cards invariably drops\n * it. Labels and values are `ReactNode`, so a value can be a badge or a link.\n *\n * A section with no `stepIndex` (file-level counts, a total) is a card without an\n * edit button. `disabled` greys every edit button at once — while the commit runs,\n * when jumping back would show a step whose edits can no longer reach the request.\n */\nexport function WizardSummary({\n sections,\n onEditStep,\n disabled = false,\n labels,\n}: {\n sections: SummarySection[];\n /** Called with the section's `stepIndex`. Optional only for a summary whose\n * sections name no step at all. */\n onEditStep?: (stepIndex: number) => void;\n /** Disable every edit button (e.g. `wizard.isSubmitting`). */\n disabled?: boolean;\n labels?: Partial<WizardLabels>;\n}) {\n const l = useKitLabels(\"wizard\", DEFAULT_WIZARD_LABELS, labels);\n\n return (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">{l.reviewTitle}</h2>\n {sections.map((section, sIdx) => (\n <Card key={sIdx}>\n {/* CardHeader is a grid, and CardAction is the top-right column it\n reserves — the edit button has to go through it or it stacks under\n the title instead of sitting beside it. `stackAction={false}`: the pencil\n is named by `aria-label` and stays an icon at Large, so it keeps its\n place beside the title there too (0.32.1). */}\n <CardHeader className=\"pb-2\" stackAction={false}>\n <CardTitle className=\"text-base\">{section.label}</CardTitle>\n {section.stepIndex !== undefined && onEditStep && (\n <CardAction>\n {/* The kit Tooltip, not a native `title`: it shows on keyboard focus too,\n and an app with a one-tooltip rule (keksdose dev#523) sees one. */}\n <Tooltip label={l.edit}>\n <IconButton\n size=\"sm\"\n variant=\"ghost\"\n aria-label={l.edit}\n disabled={disabled}\n onClick={() => onEditStep(section.stepIndex as number)}\n >\n <Pencil />\n </IconButton>\n </Tooltip>\n </CardAction>\n )}\n </CardHeader>\n <CardContent>\n <dl className=\"grid gap-2 text-sm\">\n {section.items.map((item, iIdx) => (\n <div key={iIdx}>\n {iIdx > 0 && (\n <div className=\"mb-2 border-t border-[var(--border)]\" role=\"presentation\" />\n )}\n <div className=\"flex items-start justify-between gap-4\">\n <dt className=\"text-[var(--text-muted)]\">{item.label}</dt>\n <dd className=\"text-end font-medium text-[var(--text-primary)]\">\n {item.value}\n </dd>\n </div>\n </div>\n ))}\n </dl>\n </CardContent>\n </Card>\n ))}\n </div>\n );\n}\n"],"mappings":";AAqCM,cAQI,YARJ;AArCN,SAAS,cAAc;AACvB,SAAS,MAAM,YAAY,aAAa,YAAY,WAAW,kBAAkB;AACjF,SAAS,eAAe;AAExB,SAAS,6BAA6B;AACtC,SAAS,oBAAoB;AActB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAQG;AACD,QAAM,IAAI,aAAa,UAAU,uBAAuB,MAAM;AAE9D,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,wBAAC,QAAG,WAAU,oDAAoD,YAAE,aAAY;AAAA,IAC/E,SAAS,IAAI,CAAC,SAAS,SACtB,qBAAC,QAMC;AAAA,2BAAC,cAAW,WAAU,QAAO,aAAa,OACxC;AAAA,4BAAC,aAAU,WAAU,aAAa,kBAAQ,OAAM;AAAA,QAC/C,QAAQ,cAAc,UAAa,cAClC,oBAAC,cAGC,8BAAC,WAAQ,OAAO,EAAE,MAChB;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,cAAY,EAAE;AAAA,YACd;AAAA,YACA,SAAS,MAAM,WAAW,QAAQ,SAAmB;AAAA,YAErD,8BAAC,UAAO;AAAA;AAAA,QACV,GACF,GACF;AAAA,SAEJ;AAAA,MACA,oBAAC,eACC,8BAAC,QAAG,WAAU,sBACX,kBAAQ,MAAM,IAAI,CAAC,MAAM,SACxB,qBAAC,SACE;AAAA,eAAO,KACN,oBAAC,SAAI,WAAU,wCAAuC,MAAK,gBAAe;AAAA,QAE5E,qBAAC,SAAI,WAAU,0CACb;AAAA,8BAAC,QAAG,WAAU,4BAA4B,eAAK,OAAM;AAAA,UACrD,oBAAC,QAAG,WAAU,mDACX,eAAK,OACR;AAAA,WACF;AAAA,WATQ,IAUV,CACD,GACH,GACF;AAAA,SA1CS,IA2CX,CACD;AAAA,KACH;AAEJ;","names":[]}
|
package/dist/wizard.d.ts
CHANGED
|
@@ -6,18 +6,20 @@ export { WizardStep, WizardStepProps } from './wizard/wizard-step.js';
|
|
|
6
6
|
export { WizardSummary } from './wizard/wizard-summary.js';
|
|
7
7
|
export { StepperNav } from './wizard/stepper-nav.js';
|
|
8
8
|
import 'react';
|
|
9
|
-
import './delete-account-setting-
|
|
9
|
+
import './delete-account-setting-FLyJf-kZ.js';
|
|
10
10
|
import './components/tooltip.js';
|
|
11
11
|
import './hooks/use-anchored-rect.js';
|
|
12
12
|
import './lib/clipping.js';
|
|
13
|
-
import './data-table-labels-
|
|
13
|
+
import './data-table-labels-kpAAVi6g.js';
|
|
14
14
|
import './components/data-table-sort.js';
|
|
15
15
|
import './components/swipeable-row.js';
|
|
16
16
|
import './components/mini-calendar.js';
|
|
17
17
|
import './components/calendar-heatmap.js';
|
|
18
18
|
import './components/popover.js';
|
|
19
|
+
import './hooks/use-breakpoint.js';
|
|
19
20
|
import './components/chip.js';
|
|
20
21
|
import 'lucide-react';
|
|
22
|
+
import './components/field-parts.js';
|
|
21
23
|
import './components/field-sync.js';
|
|
22
24
|
import './tour/tour.js';
|
|
23
25
|
import './search/command-palette.js';
|
|
@@ -85,6 +87,9 @@ import './admin/admin-parts.js';
|
|
|
85
87
|
import './admin/admin-action-log.js';
|
|
86
88
|
import './settings/settings-labels.js';
|
|
87
89
|
import './demo/demo-labels.js';
|
|
90
|
+
import './components/appearance-labels.js';
|
|
91
|
+
import './theme/contrast.js';
|
|
92
|
+
import './theme/text-size.js';
|
|
88
93
|
import './components/reauth-dialog.js';
|
|
89
94
|
import './components/server-wake.js';
|
|
90
95
|
import './lib/server-wake.js';
|
|
@@ -98,4 +103,4 @@ import './components/sign-chip.js';
|
|
|
98
103
|
import './components/column-mapper.js';
|
|
99
104
|
import './lib/column-mapping.js';
|
|
100
105
|
import './lib/table-text.js';
|
|
101
|
-
import './components/
|
|
106
|
+
import './components/focus-ring.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eifi1/ui-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "App-agnostic shared design system: domain-free React components, theme and tokens.",
|
|
6
6
|
"_sideEffects": "The barrel (src/index.ts) re-exports EVERY component, including components/chart, which statically imports recharts. Without this field a bundler must assume each of those modules has side effects, so it cannot drop the unused ones: importing a Button from '@eifi1/ui-kit' dragged all 433KB of recharts into the consumer's ENTRY chunk, and Keksdose was preloading it on every page load, login included. Nothing in src/ imports for side effects (no bare imports, no CSS imports from JS, no module-level global writes) — the token stylesheet is its own './tokens.css' export — so this is safe. CSS is still listed so any future stylesheet survives. Re-checked when `flag-icons` left `dependencies` and tsup started emitting a `\"use client\"` banner: neither touches this. The flag stylesheet was never imported from JS in the first place (that was the finding), and a directive prologue is a string literal every bundler lifts out before it decides whether a module is inert.",
|
|
@@ -47,7 +47,10 @@ export type AdminActionKind =
|
|
|
47
47
|
| "transfer"
|
|
48
48
|
| "deletion_request"
|
|
49
49
|
| "deletion_cancel"
|
|
50
|
-
| "erase"
|
|
50
|
+
| "erase"
|
|
51
|
+
// 0.32.1 (keksdose's 0.32 report): server-kit 0.6's `AdminAction.PLAN`, an operator's
|
|
52
|
+
// plan change or grant (docs/billing-harmonization.md §6).
|
|
53
|
+
| "plan";
|
|
51
54
|
|
|
52
55
|
/** Every {@link AdminActionKind}, in the contract's order. */
|
|
53
56
|
export const ADMIN_ACTION_KINDS: readonly AdminActionKind[] = [
|
|
@@ -67,6 +70,7 @@ export const ADMIN_ACTION_KINDS: readonly AdminActionKind[] = [
|
|
|
67
70
|
"deletion_request",
|
|
68
71
|
"deletion_cancel",
|
|
69
72
|
"erase",
|
|
73
|
+
"plan",
|
|
70
74
|
];
|
|
71
75
|
|
|
72
76
|
/** One logged action — the app's `admin_actions` row with the people joined in. */
|
|
@@ -142,6 +146,7 @@ export const DEFAULT_ADMIN_ACTION_LOG_LABELS: AdminActionLogLabels = {
|
|
|
142
146
|
deletion_request: "Deletion requested",
|
|
143
147
|
deletion_cancel: "Deletion cancelled",
|
|
144
148
|
erase: "Account erased",
|
|
149
|
+
plan: "Plan changed",
|
|
145
150
|
},
|
|
146
151
|
};
|
|
147
152
|
|
|
@@ -14,7 +14,8 @@ import type { ChipTone } from "../components/chip";
|
|
|
14
14
|
import { CopyButton } from "../components/copy-button";
|
|
15
15
|
import { LanguageSelect } from "../components/language-select";
|
|
16
16
|
import { SectionLabel, Caption } from "../components/text";
|
|
17
|
-
import {
|
|
17
|
+
import { RowActions } from "../components/row-actions";
|
|
18
|
+
import { Button, Input, Select, Spinner } from "../components/ui";
|
|
18
19
|
import { useWriteLock } from "../components/write-lock";
|
|
19
20
|
import { hasMessage, settle, useDayText, usePersonLabel } from "./admin-parts";
|
|
20
21
|
import type { AdminPerson, MaybePromise } from "./admin-parts";
|
|
@@ -480,35 +481,41 @@ export function InvitationsPanel<R extends string = string>({
|
|
|
480
481
|
</div>
|
|
481
482
|
{(link || resendable || revocable) && (
|
|
482
483
|
<div className="ms-auto flex shrink-0 items-center gap-1">
|
|
484
|
+
{/* The copy stays its own icon: it says "Copied" where it was
|
|
485
|
+
pressed, which a menu entry that closes cannot. */}
|
|
483
486
|
{link && open && <CopyButton size="xs" tone="muted" text={link} label={labels.copyLink} />}
|
|
484
|
-
{
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
487
|
+
{/* Resend and revoke are the row's actions (docs/text-size-
|
|
488
|
+
harmonization.md §10.8): two icons at Normal, one "⋯" menu at
|
|
489
|
+
Large, where both names as text ("Send … a new link") would
|
|
490
|
+
not fit a phone's row beside the copy icon. */}
|
|
491
|
+
<RowActions
|
|
492
|
+
name={invitation.email}
|
|
493
|
+
actions={[
|
|
494
|
+
resendable && {
|
|
495
|
+
key: "resend",
|
|
496
|
+
label: labels.resend(invitation.email),
|
|
497
|
+
icon: RefreshCw,
|
|
498
|
+
commit: true,
|
|
499
|
+
pending: busy === `resend:${key}`,
|
|
500
|
+
disabled: busy !== null,
|
|
501
|
+
onSelect: () =>
|
|
502
|
+
void (async () => {
|
|
503
|
+
const answer = await run(`resend:${key}`, () => onResend(invitation));
|
|
504
|
+
if (answer !== FAILED) took(answer, invitation.email, invitation.id);
|
|
505
|
+
})(),
|
|
506
|
+
},
|
|
507
|
+
revocable && {
|
|
508
|
+
key: "revoke",
|
|
509
|
+
label: labels.revoke(invitation.email),
|
|
510
|
+
icon: Trash2,
|
|
511
|
+
tone: "danger",
|
|
512
|
+
commit: true,
|
|
513
|
+
pending: busy === `revoke:${key}`,
|
|
514
|
+
disabled: busy !== null,
|
|
515
|
+
onSelect: () => void run(`revoke:${key}`, () => onRevoke(invitation)),
|
|
516
|
+
},
|
|
517
|
+
]}
|
|
518
|
+
/>
|
|
512
519
|
</div>
|
|
513
520
|
)}
|
|
514
521
|
</div>
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
|
-
import { MoreHorizontal } from "lucide-react";
|
|
4
|
-
import type { LucideIcon } from "lucide-react";
|
|
5
3
|
import { cn } from "../lib/cn";
|
|
6
4
|
import type { DateInput } from "../lib/format";
|
|
7
5
|
import type { PersonName } from "../lib/person-name";
|
|
@@ -12,8 +10,8 @@ import type { ChipTone } from "../components/chip";
|
|
|
12
10
|
import type { DataTableColumn } from "../components/data-table";
|
|
13
11
|
import { encodeSorts } from "../components/data-table-sort";
|
|
14
12
|
import type { SortState } from "../components/data-table-sort";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
13
|
+
import { RowActions } from "../components/row-actions";
|
|
14
|
+
import type { RowAction, RowActionList } from "../components/row-actions";
|
|
17
15
|
import { UserAvatar } from "../components/user-avatar";
|
|
18
16
|
import { personLabel } from "./admin-parts";
|
|
19
17
|
import { RoleSelect } from "./role-select";
|
|
@@ -213,27 +211,13 @@ export function UserIdentityCell({
|
|
|
213
211
|
|
|
214
212
|
/* ── The row's actions ──────────────────────────────────────────────────────── */
|
|
215
213
|
|
|
216
|
-
/** One entry of a row's action menu (§4).
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
key?: string;
|
|
220
|
-
label: string;
|
|
221
|
-
/** Runs it — usually opens `AdminActionConfirm` with the level the server states. */
|
|
222
|
-
onSelect: () => void;
|
|
223
|
-
icon?: LucideIcon;
|
|
224
|
-
/** `danger` for deactivate, transfer, erase. */
|
|
225
|
-
tone?: "default" | "danger";
|
|
226
|
-
/** Why it is not available for this row ("You can’t deactivate yourself"). The entry
|
|
227
|
-
* stays in the menu, focusable, and says so — an action that silently vanished
|
|
228
|
-
* would leave the admin looking for it. */
|
|
229
|
-
disabledReason?: ReactNode;
|
|
230
|
-
/** Leave it out for this row. */
|
|
231
|
-
hidden?: boolean;
|
|
232
|
-
}
|
|
214
|
+
/** One entry of a row's action menu (§4) — the kit's {@link RowAction} since 0.32,
|
|
215
|
+
* which generalised it for every dense row (docs/text-size-harmonization.md §10.8). */
|
|
216
|
+
export type UserRowAction = RowAction;
|
|
233
217
|
|
|
234
218
|
/** What `actions(row)` may return: entries, and `false` / `null` for the ones a
|
|
235
219
|
* condition left out (`row.is_active && {…}`). */
|
|
236
|
-
export type UserRowActionList =
|
|
220
|
+
export type UserRowActionList = RowActionList;
|
|
237
221
|
|
|
238
222
|
export interface UserRowActionsProps {
|
|
239
223
|
actions: UserRowActionList;
|
|
@@ -248,59 +232,19 @@ export interface UserRowActionsProps {
|
|
|
248
232
|
* a phone card, and both grow with every action §2.4 adds. The menu is portalled, so a
|
|
249
233
|
* table's scroller cannot clip it; Escape and an outside press close it, and focus goes
|
|
250
234
|
* back to the button, which is where a confirmation dialog then returns it.
|
|
235
|
+
*
|
|
236
|
+
* Since 0.32 this is {@link RowActions} with `collapse="menu"` — the menu at every size —
|
|
237
|
+
* named by the roster's own `actionsFor`.
|
|
251
238
|
*/
|
|
252
239
|
export function UserRowActions({ actions, name, labels: labelsProp }: UserRowActionsProps) {
|
|
253
240
|
const labels = useKitLabels("userRoster", DEFAULT_USER_ROSTER_LABELS, labelsProp);
|
|
254
|
-
const entries = actions.filter((a): a is UserRowAction => Boolean(a) && !(a as UserRowAction).hidden);
|
|
255
|
-
if (entries.length === 0) return null;
|
|
256
|
-
const title = labels.actionsFor(name);
|
|
257
241
|
return (
|
|
258
|
-
<
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
ref={ref}
|
|
265
|
-
size="xs"
|
|
266
|
-
label={title}
|
|
267
|
-
aria-haspopup="dialog"
|
|
268
|
-
aria-expanded={open}
|
|
269
|
-
stopPropagation
|
|
270
|
-
onClick={toggle}
|
|
271
|
-
>
|
|
272
|
-
<MoreHorizontal />
|
|
273
|
-
</IconButton>
|
|
274
|
-
)}
|
|
275
|
-
>
|
|
276
|
-
{(close) => (
|
|
277
|
-
<ul className="space-y-0.5">
|
|
278
|
-
{entries.map((action) => {
|
|
279
|
-
const Icon = action.icon;
|
|
280
|
-
return (
|
|
281
|
-
<li key={action.key ?? action.label}>
|
|
282
|
-
<Button
|
|
283
|
-
type="button"
|
|
284
|
-
variant="ghost"
|
|
285
|
-
size="sm"
|
|
286
|
-
stretch
|
|
287
|
-
tone={action.tone === "danger" ? "danger" : undefined}
|
|
288
|
-
disabledReason={action.disabledReason}
|
|
289
|
-
className="justify-start"
|
|
290
|
-
onClick={() => {
|
|
291
|
-
close();
|
|
292
|
-
action.onSelect();
|
|
293
|
-
}}
|
|
294
|
-
>
|
|
295
|
-
{Icon && <Icon className="size-4 shrink-0" aria-hidden />}
|
|
296
|
-
{action.label}
|
|
297
|
-
</Button>
|
|
298
|
-
</li>
|
|
299
|
-
);
|
|
300
|
-
})}
|
|
301
|
-
</ul>
|
|
302
|
-
)}
|
|
303
|
-
</Popover>
|
|
242
|
+
<RowActions
|
|
243
|
+
actions={actions}
|
|
244
|
+
name={name}
|
|
245
|
+
collapse="menu"
|
|
246
|
+
labels={{ actionsFor: labels.actionsFor }}
|
|
247
|
+
/>
|
|
304
248
|
);
|
|
305
249
|
}
|
|
306
250
|
|
|
@@ -507,7 +451,8 @@ export function userRosterColumns<T extends UserRosterRow, R extends string = st
|
|
|
507
451
|
column: { mobileHidden: true },
|
|
508
452
|
}),
|
|
509
453
|
// How long ago rather than a date — the question is "recently?" — with the exact
|
|
510
|
-
// time
|
|
454
|
+
// time beside it (keksdose's last-seen column, Kurvenschmiede's; 0.32 §4: never only
|
|
455
|
+
// in a tooltip).
|
|
511
456
|
dateColumn<T>({
|
|
512
457
|
key: "last_login",
|
|
513
458
|
header: labels.lastLogin,
|
package/src/auth/auth-errors.ts
CHANGED
|
@@ -86,9 +86,35 @@ export type DemoErrorCode =
|
|
|
86
86
|
| "demo_read_only"
|
|
87
87
|
| "demo_refused";
|
|
88
88
|
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
|
|
89
|
+
/**
|
|
90
|
+
* 0.32.0: billing's coded refusals (docs/billing-harmonization.md §3.3, §3.4, §4, §12.3) —
|
|
91
|
+
* server-kit 0.6's `BillingError` and `PlanLimitError`, value for value, answered as
|
|
92
|
+
* `{detail, code}` like the others and read by the same {@link authErrorCode}.
|
|
93
|
+
*
|
|
94
|
+
* - `billing_disabled` — `404`: the billing switch is off (§2.9), so every billing route
|
|
95
|
+
* but `GET /billing/status` is "not there", as a switched-off demo is.
|
|
96
|
+
* - `billing_read_only` — `402`: a write by (or into the data of) a payer out of good
|
|
97
|
+
* standing (§3.3, §12.1). Inside a sync reply it marks the changes that were refused
|
|
98
|
+
* and not applied (§12.5). The app's write lock and banner already say why, so — like
|
|
99
|
+
* `demo_read_only` — it needs no toast of its own.
|
|
100
|
+
* - `plan_limit` — `402`: a create past the plan's limit (§3.4), with the extra fields
|
|
101
|
+
* `dimension`, `plan`, `limit` and `used` — read them with `isPlanLimit`. A lapsed payer
|
|
102
|
+
* creating gets `billing_read_only` instead, never this (§12.3).
|
|
103
|
+
* - `billing_not_configured` — billing is switched on but the provider's settings are
|
|
104
|
+
* missing (the secrets, a price id): the operator's mistake, not the payer's.
|
|
105
|
+
*/
|
|
106
|
+
export type BillingErrorCode = "billing_disabled" | "billing_read_only" | "plan_limit" | "billing_not_configured";
|
|
107
|
+
|
|
108
|
+
/** Every code the kit reads: the sign-in refusals, the account ones (0.30.0), the demo's
|
|
109
|
+
* (0.31.0) and billing's (0.32.0). */
|
|
110
|
+
export type KitErrorCode = AuthErrorCode | AccountErrorCode | DemoErrorCode | BillingErrorCode;
|
|
111
|
+
|
|
112
|
+
const BILLING_CODES: ReadonlySet<BillingErrorCode> = new Set<BillingErrorCode>([
|
|
113
|
+
"billing_disabled",
|
|
114
|
+
"billing_read_only",
|
|
115
|
+
"plan_limit",
|
|
116
|
+
"billing_not_configured",
|
|
117
|
+
]);
|
|
92
118
|
|
|
93
119
|
const CODES: ReadonlySet<string> = new Set<KitErrorCode>([
|
|
94
120
|
"invalid_credentials",
|
|
@@ -112,6 +138,7 @@ const CODES: ReadonlySet<string> = new Set<KitErrorCode>([
|
|
|
112
138
|
"demo_not_ready",
|
|
113
139
|
"demo_read_only",
|
|
114
140
|
"demo_refused",
|
|
141
|
+
...BILLING_CODES,
|
|
115
142
|
]);
|
|
116
143
|
|
|
117
144
|
type Bag = Record<string, unknown>;
|
|
@@ -132,8 +159,8 @@ function codeOfBody(body: unknown): KitErrorCode | undefined {
|
|
|
132
159
|
|
|
133
160
|
/**
|
|
134
161
|
* The code an error carries — an {@link AuthErrorCode}, since 0.30.0 an
|
|
135
|
-
* {@link AccountErrorCode}, since 0.31.0 a {@link DemoErrorCode}
|
|
136
|
-
* carries none.
|
|
162
|
+
* {@link AccountErrorCode}, since 0.31.0 a {@link DemoErrorCode}, since 0.32.0 a
|
|
163
|
+
* {@link BillingErrorCode} — or `undefined` when it carries none.
|
|
137
164
|
*
|
|
138
165
|
* Reads the parsed response body wherever the apps' HTTP clients put it, without
|
|
139
166
|
* depending on any of them:
|
|
@@ -148,7 +175,7 @@ function codeOfBody(body: unknown): KitErrorCode | undefined {
|
|
|
148
175
|
* it is one of the codes above: axios writes its OWN codes there (`ERR_NETWORK`,
|
|
149
176
|
* `ECONNABORTED`, `ERR_BAD_REQUEST`), and so does Node, so an unknown value is never
|
|
150
177
|
* read as a refusal. The HTTP status is not checked: the code is the contract, and the
|
|
151
|
-
* status differs per refusal (401, 403, 409, 410).
|
|
178
|
+
* status differs per refusal (401, 402, 403, 404, 409, 410).
|
|
152
179
|
*/
|
|
153
180
|
export function authErrorCode(err: unknown): KitErrorCode | undefined {
|
|
154
181
|
if (!isBag(err)) return undefined;
|
|
@@ -173,13 +200,47 @@ export function authErrorCode(err: unknown): KitErrorCode | undefined {
|
|
|
173
200
|
* with, so an app's `onSubmit` can simply let its client's error through. See
|
|
174
201
|
* {@link authErrorCode} for the shapes it reads. Since 0.30.0 it knows the account codes
|
|
175
202
|
* too: `isAuthError(err, "last_admin")`; since 0.31.0 the demo's:
|
|
176
|
-
* `isAuthError(err, "demo_read_only")
|
|
203
|
+
* `isAuthError(err, "demo_read_only")`; since 0.32.0 billing's:
|
|
204
|
+
* `isAuthError(err, "billing_read_only")` (or {@link isBillingError}).
|
|
177
205
|
*/
|
|
178
206
|
export function isAuthError(err: unknown, code?: KitErrorCode): boolean {
|
|
179
207
|
const found = authErrorCode(err);
|
|
180
208
|
return found !== undefined && (code === undefined || found === code);
|
|
181
209
|
}
|
|
182
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Whether `err` is one of billing's coded refusals (0.32.0, docs/billing-harmonization.md
|
|
213
|
+
* §10) — any of the four, or the one named. {@link isAuthError} answers the same for a
|
|
214
|
+
* named code; this one also answers "is it billing's at all", which an app's error
|
|
215
|
+
* handler asks before it decides between the write lock, a `PlanLimitNotice` and a toast.
|
|
216
|
+
*/
|
|
217
|
+
export function isBillingError(err: unknown, code?: BillingErrorCode): boolean {
|
|
218
|
+
const found = authErrorCode(err);
|
|
219
|
+
return found !== undefined && BILLING_CODES.has(found as BillingErrorCode) && (code === undefined || found === code);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The parsed body that carries a code, wherever {@link authErrorCode} would find it (in
|
|
224
|
+
* the same order) — the object with the `code`, so FastAPI's nested `detail` when the code
|
|
225
|
+
* is there. For a reader of a refusal's EXTRA fields (`isPlanLimit`: `dimension`, `limit`,
|
|
226
|
+
* `used` sit beside the code). `accept` decides which codes count; default, the known ones.
|
|
227
|
+
*
|
|
228
|
+
* @internal Not part of the barrel.
|
|
229
|
+
*/
|
|
230
|
+
export function errorBodyWithCode(
|
|
231
|
+
err: unknown,
|
|
232
|
+
accept: (code: unknown) => boolean = (code) => known(code) !== undefined,
|
|
233
|
+
): Record<string, unknown> | undefined {
|
|
234
|
+
if (!isBag(err)) return undefined;
|
|
235
|
+
const response = err.response;
|
|
236
|
+
for (const body of [isBag(response) ? response.data : undefined, err.data, err.body, err]) {
|
|
237
|
+
if (!isBag(body)) continue;
|
|
238
|
+
if (accept(body.code)) return body;
|
|
239
|
+
if (isBag(body.detail) && accept(body.detail.code)) return body.detail;
|
|
240
|
+
}
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
|
|
183
244
|
/** An HTTP status as a number, or undefined. */
|
|
184
245
|
function statusOf(value: unknown): number | undefined {
|
|
185
246
|
return typeof value === "number" && Number.isInteger(value) ? value : undefined;
|