@eifi1/ui-kit 0.34.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -41
- package/dist/admin/role-select.d.ts +3 -2
- package/dist/admin/role-select.js +2 -0
- package/dist/admin/role-select.js.map +1 -1
- package/dist/billing/billing-banner.d.ts +5 -2
- package/dist/billing/billing-banner.js.map +1 -1
- package/dist/billing/plan-limit-notice.d.ts +5 -2
- package/dist/billing/plan-limit-notice.js.map +1 -1
- package/dist/chart.js.map +1 -1
- package/dist/components/amount-input.d.ts +2 -5
- package/dist/components/amount-input.js +2 -2
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.d.ts +2 -2
- package/dist/components/autocomplete.js +2 -1
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/button-look.d.ts +1 -1
- package/dist/components/button-look.js +9 -4
- package/dist/components/button-look.js.map +1 -1
- package/dist/components/calculator.d.ts +1 -4
- package/dist/components/calculator.js +1 -3
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/chart-zoom.d.ts +0 -37
- package/dist/components/chart-zoom.js +1 -28
- package/dist/components/chart-zoom.js.map +1 -1
- package/dist/components/checkbox-group.d.ts +5 -2
- package/dist/components/checkbox-group.js +15 -4
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/chip-input.d.ts +0 -4
- package/dist/components/chip-input.js +1 -5
- package/dist/components/chip-input.js.map +1 -1
- package/dist/components/column-mapper.d.ts +5 -3
- package/dist/components/column-mapper.js +2 -0
- package/dist/components/column-mapper.js.map +1 -1
- package/dist/components/combobox.d.ts +3 -3
- package/dist/components/combobox.js +2 -1
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/copy-button.d.ts +5 -1
- package/dist/components/copy-button.js.map +1 -1
- package/dist/components/country-select.d.ts +3 -3
- package/dist/components/country-select.js +3 -0
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-option-list.d.ts +3 -8
- package/dist/components/currency-option-list.js +1 -29
- package/dist/components/currency-option-list.js.map +1 -1
- package/dist/components/currency-select.d.ts +3 -2
- package/dist/components/currency-select.js +10 -1
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +3 -3
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filter-popover.js +1 -1
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-labels.d.ts +1 -42
- package/dist/components/data-table-labels.js +2 -31
- package/dist/components/data-table-labels.js.map +1 -1
- package/dist/components/data-table-shared.d.ts +17 -1
- package/dist/components/data-table-shared.js +22 -0
- package/dist/components/data-table-shared.js.map +1 -1
- package/dist/components/data-table.d.ts +12 -2
- package/dist/components/data-table.js +18 -14
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-field.d.ts +2 -1
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.js +3 -0
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.js +3 -0
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +3 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/dropdown.d.ts +18 -15
- package/dist/components/dropdown.js +11 -3
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +3 -3
- package/dist/components/entity-combobox.js +2 -1
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/field-base.d.ts +0 -5
- package/dist/components/field-base.js +0 -5
- package/dist/components/field-base.js.map +1 -1
- package/dist/components/field-parts.d.ts +69 -22
- package/dist/components/field-parts.js +33 -19
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-strip.d.ts +9 -23
- package/dist/components/field-strip.js +26 -23
- package/dist/components/field-strip.js.map +1 -1
- package/dist/components/field-sync.d.ts +0 -4
- package/dist/components/field-sync.js +0 -4
- package/dist/components/field-sync.js.map +1 -1
- package/dist/components/field.d.ts +7 -6
- package/dist/components/field.js +24 -15
- package/dist/components/field.js.map +1 -1
- package/dist/components/full-bleed-dialog.js +2 -2
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/help-popover.d.ts +9 -7
- package/dist/components/help-popover.js.map +1 -1
- package/dist/components/hover-menu.d.ts +6 -13
- package/dist/components/hover-menu.js +3 -3
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/icon-picker.d.ts +3 -2
- package/dist/components/icon-picker.js +3 -0
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-entity-combobox.d.ts +3 -3
- package/dist/components/inline-entity-combobox.js +2 -1
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/input.d.ts +2 -2
- package/dist/components/input.js +2 -1
- package/dist/components/input.js.map +1 -1
- package/dist/components/modal.d.ts +9 -1
- package/dist/components/modal.js +7 -4
- package/dist/components/modal.js.map +1 -1
- package/dist/components/month-picker.d.ts +2 -1
- package/dist/components/month-picker.js +8 -1
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.d.ts +2 -2
- package/dist/components/multi-entity-combobox.js +2 -1
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.d.ts +7 -18
- package/dist/components/multi-select.js +8 -10
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-input.d.ts +2 -5
- package/dist/components/number-input.js +2 -4
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numeric-field.d.ts +5 -2
- package/dist/components/numeric-field.js +4 -1
- package/dist/components/numeric-field.js.map +1 -1
- package/dist/components/one-time-code-input.d.ts +2 -1
- package/dist/components/one-time-code-input.js +2 -1
- package/dist/components/one-time-code-input.js.map +1 -1
- package/dist/components/phone-input.d.ts +1 -1
- package/dist/components/phone-input.js +4 -0
- package/dist/components/phone-input.js.map +1 -1
- package/dist/components/popover.js +3 -3
- package/dist/components/popover.js.map +1 -1
- package/dist/components/select.d.ts +4 -3
- package/dist/components/select.js +2 -1
- package/dist/components/select.js.map +1 -1
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/server-wake.d.ts +0 -6
- package/dist/components/server-wake.js.map +1 -1
- package/dist/components/settings-fields.d.ts +4 -2
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/slider.d.ts +3 -2
- package/dist/components/slider.js +7 -1
- package/dist/components/slider.js.map +1 -1
- package/dist/components/stat-tile.d.ts +8 -2
- package/dist/components/stat-tile.js +2 -11
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/swatch-picker.d.ts +3 -2
- package/dist/components/swatch-picker.js +3 -0
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/swipeable-row.d.ts +2 -17
- package/dist/components/swipeable-row.js +11 -16
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/text-link.js +3 -1
- package/dist/components/text-link.js.map +1 -1
- package/dist/components/textarea.d.ts +2 -1
- package/dist/components/textarea.js +9 -3
- package/dist/components/textarea.js.map +1 -1
- package/dist/components/toggle-group.d.ts +2 -2
- package/dist/components/toggle-group.js +7 -3
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/tooltip.d.ts +9 -1
- package/dist/components/tooltip.js +20 -5
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/translation-review.d.ts +10 -2
- package/dist/components/translation-review.js +11 -3
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/use-table-state.d.ts +31 -3
- package/dist/components/use-table-state.js +53 -8
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/components/user-avatar.d.ts +2 -2
- package/dist/components/user-avatar.js.map +1 -1
- package/dist/components/wizard-stepper.d.ts +1 -4
- package/dist/components/wizard-stepper.js +2 -3
- package/dist/components/wizard-stepper.js.map +1 -1
- package/dist/currencies.d.ts +23 -0
- package/dist/currencies.js +38 -0
- package/dist/currencies.js.map +1 -0
- package/dist/demo/demo-banner.d.ts +7 -2
- package/dist/demo/demo-banner.js.map +1 -1
- package/dist/eslint/index.d.ts +83 -0
- package/dist/eslint/index.js +69 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/role-utilities.d.ts +48 -0
- package/dist/eslint/role-utilities.generated.d.ts +2 -0
- package/dist/eslint/role-utilities.generated.js +143 -0
- package/dist/eslint/role-utilities.generated.js.map +1 -0
- package/dist/eslint/role-utilities.js +43 -0
- package/dist/eslint/role-utilities.js.map +1 -0
- package/dist/feedback/feedback-menu.d.ts +2 -2
- package/dist/feedback/feedback-menu.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +3 -8
- package/dist/feedback/feedback-thread.js +0 -2
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/hooks/use-dismiss.d.ts +16 -3
- package/dist/hooks/use-dismiss.js +14 -2
- package/dist/hooks/use-dismiss.js.map +1 -1
- package/dist/i18n/defaults.js +5 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +97 -1
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +29 -4
- package/dist/i18n/kit-labels.js +21 -1
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +104 -3
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +95 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +99 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +95 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +99 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +95 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +13 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/i18n/shared-labels.js +3 -1
- package/dist/i18n/shared-labels.js.map +1 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js +40 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/device-settings.d.ts +72 -0
- package/dist/lib/device-settings.js +64 -0
- package/dist/lib/device-settings.js.map +1 -0
- package/dist/lib/plain-text.d.ts +11 -0
- package/dist/lib/plain-text.js +16 -0
- package/dist/lib/plain-text.js.map +1 -0
- package/dist/lib/refs.d.ts +13 -0
- package/dist/lib/refs.js +15 -0
- package/dist/lib/refs.js.map +1 -0
- package/dist/lib/safe-storage.d.ts +6 -0
- package/dist/lib/safe-storage.js +11 -0
- package/dist/lib/safe-storage.js.map +1 -1
- package/dist/notifications/notification-parts.d.ts +39 -0
- package/dist/notifications/notification-parts.js +47 -0
- package/dist/notifications/notification-parts.js.map +1 -0
- package/dist/notifications/notification-types-setting.d.ts +62 -0
- package/dist/notifications/notification-types-setting.js +192 -0
- package/dist/notifications/notification-types-setting.js.map +1 -0
- package/dist/notifications/notification-types.d.ts +75 -0
- package/dist/notifications/notification-types.js +2 -0
- package/dist/notifications/notification-types.js.map +1 -0
- package/dist/notifications/notifications-labels.d.ts +131 -0
- package/dist/notifications/notifications-labels.js +83 -0
- package/dist/notifications/notifications-labels.js.map +1 -0
- package/dist/notifications/push-device-setting.d.ts +37 -0
- package/dist/notifications/push-device-setting.js +164 -0
- package/dist/notifications/push-device-setting.js.map +1 -0
- package/dist/notifications/push-devices-setting.d.ts +44 -0
- package/dist/notifications/push-devices-setting.js +203 -0
- package/dist/notifications/push-devices-setting.js.map +1 -0
- package/dist/notifications/quiet-hours-setting.d.ts +47 -0
- package/dist/notifications/quiet-hours-setting.js +131 -0
- package/dist/notifications/quiet-hours-setting.js.map +1 -0
- package/dist/notifications/time-zone-select.d.ts +50 -0
- package/dist/notifications/time-zone-select.js +76 -0
- package/dist/notifications/time-zone-select.js.map +1 -0
- package/dist/notifications/unsubscribe-panel.d.ts +53 -0
- package/dist/notifications/unsubscribe-panel.js +139 -0
- package/dist/notifications/unsubscribe-panel.js.map +1 -0
- package/dist/notifications/use-push-device.d.ts +122 -0
- package/dist/notifications/use-push-device.js +230 -0
- package/dist/notifications/use-push-device.js.map +1 -0
- package/dist/rhf/fields.d.ts +36 -29
- package/dist/rhf/fields.js +51 -22
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form-core.d.ts +5 -4
- package/dist/rhf/form-core.js.map +1 -1
- package/dist/rhf/form.d.ts +7 -36
- package/dist/rhf/form.js +1 -16
- package/dist/rhf/form.js.map +1 -1
- package/dist/rhf/line-items.d.ts +1 -1
- package/dist/rhf/line-items.js.map +1 -1
- package/dist/rhf/use-rhf-wizard-step.js.map +1 -1
- package/dist/rhf.js.map +1 -1
- package/dist/settings/device-reset-setting-labels.d.ts +3 -0
- package/dist/settings/device-reset-setting-labels.js +15 -0
- package/dist/settings/device-reset-setting-labels.js.map +1 -0
- package/dist/settings/device-reset-setting.d.ts +58 -0
- package/dist/settings/device-reset-setting.js +51 -0
- package/dist/settings/device-reset-setting.js.map +1 -0
- package/dist/shell/app-shell.js +5 -0
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/option-switcher-menu.d.ts +5 -17
- package/dist/shell/option-switcher-menu.js +1 -3
- package/dist/shell/option-switcher-menu.js.map +1 -1
- package/dist/shell/role-switcher.d.ts +1 -4
- package/dist/shell/role-switcher.js +2 -3
- package/dist/shell/role-switcher.js.map +1 -1
- package/dist/shell/topbar-action-menu.d.ts +7 -19
- package/dist/shell/topbar-action-menu.js +1 -3
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell/topbar-controls.d.ts +3 -12
- package/dist/shell/topbar-controls.js +6 -9
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/viewport.d.ts +25 -2
- package/dist/testing/viewport.js +61 -10
- package/dist/testing/viewport.js.map +1 -1
- package/dist/theme/contrast-tokens.d.ts +42 -4
- package/dist/theme/contrast-tokens.js +56 -9
- package/dist/theme/contrast-tokens.js.map +1 -1
- package/dist/theme/contrast.d.ts +4 -2
- package/dist/theme/contrast.js +13 -0
- package/dist/theme/contrast.js.map +1 -1
- package/dist/theme/palette-derive.d.ts +15 -1
- package/dist/theme/palette-derive.js +37 -8
- package/dist/theme/palette-derive.js.map +1 -1
- package/dist/theme/palette-presets.d.ts +2 -8
- package/dist/theme/palette-presets.js +5 -284
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/theme/palette-store.js +6 -0
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/text-size.js +6 -0
- package/dist/theme/text-size.js.map +1 -1
- package/dist/theme/theme-store.js +6 -0
- package/dist/theme/theme-store.js.map +1 -1
- package/dist/wizard/types.d.ts +0 -5
- package/dist/wizard/types.js +1 -5
- package/dist/wizard/types.js.map +1 -1
- package/package.json +9 -1
- package/src/admin/role-select.tsx +4 -1
- package/src/billing/billing-banner.tsx +5 -2
- package/src/billing/plan-limit-notice.tsx +5 -2
- package/src/chart.ts +5 -3
- package/src/components/amount-input.tsx +4 -7
- package/src/components/autocomplete.tsx +5 -2
- package/src/components/button-look.ts +15 -5
- package/src/components/calculator.tsx +2 -7
- package/src/components/chart-zoom.tsx +4 -47
- package/src/components/checkbox-group.tsx +22 -4
- package/src/components/chip-input.tsx +0 -7
- package/src/components/column-mapper.tsx +6 -2
- package/src/components/combobox.tsx +6 -3
- package/src/components/copy-button.tsx +5 -1
- package/src/components/country-select.tsx +6 -1
- package/src/components/currency-option-list.tsx +8 -42
- package/src/components/currency-select.tsx +12 -3
- package/src/components/danger-confirm.tsx +3 -3
- package/src/components/data-table-filter-popover.tsx +2 -1
- package/src/components/data-table-labels.ts +2 -84
- package/src/components/data-table-shared.tsx +55 -2
- package/src/components/data-table.tsx +29 -17
- package/src/components/date-field.tsx +2 -2
- package/src/components/date-picker.tsx +3 -0
- package/src/components/date-range-picker.tsx +3 -0
- package/src/components/dialog-frame.tsx +3 -1
- package/src/components/dropdown.tsx +42 -18
- package/src/components/entity-combobox.tsx +6 -3
- package/src/components/field-base.tsx +0 -11
- package/src/components/field-parts.tsx +112 -38
- package/src/components/field-strip.tsx +12 -27
- package/src/components/field-sync.tsx +0 -7
- package/src/components/field.tsx +32 -19
- package/src/components/full-bleed-dialog.tsx +4 -3
- package/src/components/help-popover.tsx +9 -7
- package/src/components/hover-menu.tsx +12 -16
- package/src/components/icon-picker.tsx +8 -3
- package/src/components/inline-entity-combobox.tsx +6 -3
- package/src/components/input.tsx +4 -2
- package/src/components/modal.tsx +20 -4
- package/src/components/month-picker.tsx +10 -3
- package/src/components/multi-entity-combobox.tsx +5 -2
- package/src/components/multi-select.tsx +19 -31
- package/src/components/number-input.tsx +5 -10
- package/src/components/numeric-field.ts +10 -2
- package/src/components/one-time-code-input.tsx +5 -3
- package/src/components/phone-input.tsx +4 -0
- package/src/components/popover.tsx +8 -4
- package/src/components/select.tsx +6 -3
- package/src/components/series-chart.tsx +1 -1
- package/src/components/server-wake.tsx +0 -6
- package/src/components/settings-fields.tsx +4 -2
- package/src/components/slider.tsx +10 -3
- package/src/components/stat-tile.tsx +11 -20
- package/src/components/swatch-picker.tsx +9 -4
- package/src/components/swipeable-row.tsx +15 -37
- package/src/components/text-link.tsx +3 -1
- package/src/components/textarea.tsx +11 -4
- package/src/components/toggle-group.tsx +21 -5
- package/src/components/tooltip.tsx +37 -6
- package/src/components/translation-review.tsx +25 -7
- package/src/components/use-table-state.ts +91 -10
- package/src/components/user-avatar.tsx +2 -2
- package/src/components/wizard-stepper.tsx +2 -6
- package/src/currencies.ts +70 -0
- package/src/demo/demo-banner.tsx +7 -2
- package/src/eslint/index.ts +161 -0
- package/src/eslint/role-utilities.generated.ts +146 -0
- package/src/eslint/role-utilities.ts +99 -0
- package/src/feedback/feedback-menu.tsx +2 -2
- package/src/feedback/feedback-thread.tsx +3 -8
- package/src/hooks/use-dismiss.ts +39 -4
- package/src/i18n/defaults.ts +4 -0
- package/src/i18n/german.ts +113 -0
- package/src/i18n/kit-labels.tsx +66 -6
- package/src/i18n/locales/en.ts +6 -0
- package/src/i18n/locales/es.ts +106 -0
- package/src/i18n/locales/fr.ts +109 -2
- package/src/i18n/locales/hu.ts +104 -0
- package/src/i18n/locales/it.ts +108 -2
- package/src/i18n/locales/zh.ts +96 -0
- package/src/i18n/review.ts +13 -0
- package/src/i18n/shared-labels.ts +2 -0
- package/src/index.ts +53 -1
- package/src/lib/device-settings.ts +146 -0
- package/src/lib/plain-text.ts +22 -0
- package/src/lib/refs.ts +22 -0
- package/src/lib/safe-storage.ts +16 -0
- package/src/notifications/notification-parts.tsx +83 -0
- package/src/notifications/notification-types-setting.tsx +309 -0
- package/src/notifications/notification-types.ts +80 -0
- package/src/notifications/notifications-labels.ts +238 -0
- package/src/notifications/push-device-setting.tsx +224 -0
- package/src/notifications/push-devices-setting.tsx +306 -0
- package/src/notifications/quiet-hours-setting.tsx +185 -0
- package/src/notifications/time-zone-select.tsx +126 -0
- package/src/notifications/unsubscribe-panel.tsx +203 -0
- package/src/notifications/use-push-device.ts +392 -0
- package/src/rhf/fields.tsx +87 -39
- package/src/rhf/form-core.tsx +5 -4
- package/src/rhf/form.tsx +7 -43
- package/src/rhf/line-items.tsx +1 -1
- package/src/rhf/use-rhf-wizard-step.ts +4 -4
- package/src/rhf.ts +3 -2
- package/src/settings/device-reset-setting-labels.ts +20 -0
- package/src/settings/device-reset-setting.tsx +119 -0
- package/src/shell/app-shell.tsx +8 -0
- package/src/shell/option-switcher-menu.tsx +5 -22
- package/src/shell/role-switcher.tsx +2 -6
- package/src/shell/topbar-action-menu.tsx +7 -24
- package/src/shell/topbar-controls.tsx +6 -18
- package/src/testing/index.ts +3 -1
- package/src/testing/viewport.ts +125 -19
- package/src/theme/contrast-tokens.ts +106 -12
- package/src/theme/contrast.ts +30 -4
- package/src/theme/palette-derive.ts +68 -7
- package/src/theme/palette-presets.ts +16 -299
- package/src/theme/palette-store.ts +12 -0
- package/src/theme/text-size.ts +8 -0
- package/src/theme/theme-store.ts +10 -0
- package/src/wizard/types.ts +0 -8
- package/tokens.css +38 -4
package/README.md
CHANGED
|
@@ -94,6 +94,12 @@ currency picker and the language menu. It was a 5.6 MB hard dependency through 0
|
|
|
94
94
|
installed into every consumer and imported by nothing — so it may still be in your tree
|
|
95
95
|
transitively after upgrading. Depend on it explicitly if you render any of the three.
|
|
96
96
|
|
|
97
|
+
**Shipping only the flags you render.** `@eifi1/ui-kit/currencies` (0.34.1) is the
|
|
98
|
+
currency list as plain data — `CURRENCIES`, and `CURRENCY_COUNTRIES` (code → the lowercase
|
|
99
|
+
country flag-icons names the flag by: `CHF` → `"ch"`, `EUR` → `"eu"`). It imports nothing,
|
|
100
|
+
so a build script or a Vite plugin can import it in Node to generate a flag subset. Read
|
|
101
|
+
it there, never out of a file under `dist/`: those move between versions.
|
|
102
|
+
|
|
97
103
|
## Wiring
|
|
98
104
|
|
|
99
105
|
### 1. Vite — dedupe shared singletons
|
|
@@ -169,6 +175,16 @@ module runs needs the text size even earlier: see "Before the first paint" under
|
|
|
169
175
|
[Styling](#styling). Worked example:
|
|
170
176
|
[`showcase/src/main.tsx`](https://github.com/Eifi1/ui-kit/blob/main/showcase/src/main.tsx).
|
|
171
177
|
|
|
178
|
+
**Reset this device's settings** (0.36, `docs/settings-harmonization.md` §11): the four
|
|
179
|
+
stores, `AppShell`'s sidebar key and `UiKitProvider`'s table prefix join a registry by
|
|
180
|
+
themselves; `DeviceResetSetting` (the last card of the appearance group) clears them all and
|
|
181
|
+
puts each back live. An app adds its own device keys, each with a reset that goes through its
|
|
182
|
+
own store:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
registerDeviceSetting({ key: "myapp-lang", kind: "appearance", reset: () => setDeviceLanguage(null) });
|
|
186
|
+
```
|
|
187
|
+
|
|
172
188
|
### 4. Labels — one provider, the shipped catalogues
|
|
173
189
|
|
|
174
190
|
Load the kit's words with `await loadUiKitLabels(code)` before the first render and hand
|
|
@@ -182,9 +198,9 @@ re-skins the kit by changing values rather than by forking components. The famil
|
|
|
182
198
|
|
|
183
199
|
| Family | Tokens | Set by |
|
|
184
200
|
|---|---|---|
|
|
185
|
-
| **Palette** | `--bg-page` `--bg-surface` `--bg-surface-2` `--border` `--text-primary` `--text-secondary` `--text-muted` `--brand` `--brand-hover` `--brand-contrast` `--money-income` `--money-expense` `--money-net` `--money-neutral` `--chart-1…9` | `applyTokenSet()`, written inline on `<html>` from the active `PalettePreset` (More contrast steps four of them) |
|
|
201
|
+
| **Palette** | `--bg-page` `--bg-surface` `--bg-surface-2` `--border` `--text-primary` `--text-secondary` `--text-muted` `--brand` `--brand-hover` `--brand-contrast` `--money-income` `--money-expense` `--money-net` `--money-neutral` `--chart-1…9` | `applyTokenSet()`, written inline on `<html>` from the active `PalettePreset` (More contrast steps four of them; in light also the well and the four money colours) |
|
|
186
202
|
| **Derived** | `--text-placeholder` `--bg-hover` `--bg-active` `--bg-inverse` `--text-inverse` `--border-strong` `--brand-bg` `--brand-bg-hover` `--brand-muted`, and `--neutral` (`--text-muted` as a fill) | `color-mix()` or `var()` in `tokens.css`, from the layer above — so they follow the preset with no preset having to list them |
|
|
187
|
-
| **Semantic** | `--danger*` `--warning*` `--info*` `--success*` — each the colour, `-contrast`, `-border` and `-bg`; danger and warning also `-border-strong`, danger `-hover` — and `--status-synced/-pending/-edited/-error` | literals in `tokens.css`, per theme |
|
|
203
|
+
| **Semantic** | `--danger*` `--warning*` `--info*` `--success*` — each the colour, `-contrast`, `-border` and `-bg`; danger and warning also `-border-strong`, danger `-hover` — and `--status-synced/-pending/-edited/-error` | literals in `tokens.css`, per theme; in light under More contrast the four colours and `--status-edited` deepen for the darker well |
|
|
188
204
|
| **Categorical hues** | `--hue-blue` `--hue-indigo` `--hue-purple` `--hue-teal` `--hue-orange`, each with `-contrast`, `-border` and `-bg` | literals in `tokens.css`, per theme — values that mean only "a different value" (a status enum), at the semantic family's weight |
|
|
189
205
|
| **Fill foregrounds** | `<fill>-contrast`: the text ON a fill — `--brand-contrast`, `--money-income-contrast` … `--money-neutral-contrast`, `--neutral-contrast`, and each tone's and hue's `-contrast` | with their family; money is white in light and the page in dark |
|
|
190
206
|
| **Media** | `--media-ink` `--media-scrim` `--media-scrim-hover` | literals, the SAME in both themes: controls drawn on a photo or a camera picture, whose background is the picture, not the page |
|
|
@@ -226,8 +242,10 @@ name with the property's own prefix dropped (`--bg-surface` → `bg-surface`,
|
|
|
226
242
|
The names are **property-scoped**: a text role makes a `text-*` utility and nothing else,
|
|
227
243
|
so `bg-muted` does not exist and a role cannot land on the wrong property by accident. An
|
|
228
244
|
app's own `--color-*` names (shadcn-style) do not collide with them. Keep `[var(--…)]` for a
|
|
229
|
-
role with no utility: the chart colours
|
|
230
|
-
|
|
245
|
+
role with no utility: the chart colours and `--status-*`. The ring offsets
|
|
246
|
+
(`ring-offset-surface`, `ring-offset-page`) and the money colours (`text-money-income`,
|
|
247
|
+
`bg-money-expense` …, the table below) are utilities since 0.34 and take variants, unlike
|
|
248
|
+
the plain money classes further down. The kit's own
|
|
231
249
|
markup follows this rule with no exceptions: `check:tokens` allows no `[var(--role)]` where
|
|
232
250
|
a utility exists.
|
|
233
251
|
|
|
@@ -329,13 +347,46 @@ Theme values: `text-micro` (font size 0.625rem), `text-caption` (font size 0.687
|
|
|
329
347
|
|
|
330
348
|
<!-- END GENERATED: styling -->
|
|
331
349
|
|
|
350
|
+
### Lint: the role utilities in an app
|
|
351
|
+
|
|
352
|
+
`@eifi1/ui-kit/eslint` (0.35) is `check:tokens`' role rule for an app's own markup: an ESLint
|
|
353
|
+
flat-config plugin whose `role-utilities` rule reports a `[var(--role)]` class wherever that
|
|
354
|
+
property has a utility for the role, and names it. It reads every string literal and
|
|
355
|
+
template-literal part, so a JSX `className`, a `cn()` / `clsx()` argument and a class constant
|
|
356
|
+
alike. Where one utility fits, `eslint --fix` writes it and keeps the variants and the opacity:
|
|
357
|
+
`hover:text-[var(--text-muted)]/70` → `hover:text-muted/70`. A token with no utility on that
|
|
358
|
+
property is left alone (`text-[var(--chart-1)]`, `--status-*`, `bg-[var(--border)]` as a
|
|
359
|
+
divider), and so are comments. The rule reads the table above, so a role that gains a utility is
|
|
360
|
+
flagged from the release that adds it.
|
|
361
|
+
|
|
362
|
+
```js
|
|
363
|
+
// eslint.config.js
|
|
364
|
+
import uiKit from "@eifi1/ui-kit/eslint";
|
|
365
|
+
|
|
366
|
+
export default defineConfig([ // or tseslint.config(…): either takes it
|
|
367
|
+
// … the app's own entries, which say which files are linted …
|
|
368
|
+
uiKit.configs.recommended,
|
|
369
|
+
]);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
`configs.recommended` registers the plugin as `@eifi1/ui-kit` and turns
|
|
373
|
+
`@eifi1/ui-kit/role-utilities` on as an error for every linted file except tests
|
|
374
|
+
(`**/__tests__/**`, `*.test.*`, `*.spec.*`), which may name an old class to assert it is gone.
|
|
375
|
+
To scope it yourself, register the plugin and set the rule:
|
|
376
|
+
`{ files: ["src/**/*.tsx"], plugins: { "@eifi1/ui-kit": uiKit }, rules: { "@eifi1/ui-kit/role-utilities": "error" } }`.
|
|
377
|
+
It runs on ESLint 9 and 10 and imports no package of its own.
|
|
378
|
+
|
|
332
379
|
### Text size and More contrast
|
|
333
380
|
|
|
334
381
|
ONE scale on `<html>`: `data-text-size="normal" | "large" | "xlarge"` is 100 / 125 / 150 %
|
|
335
382
|
of the browser's own font size, so Normal keeps whatever the reader set in the browser,
|
|
336
383
|
and everything sized in rem (Tailwind's spacing and type) grows with it.
|
|
337
384
|
`data-contrast="more"` is More contrast, from the setting or from `prefers-contrast: more`
|
|
338
|
-
on "System"; it steps the colour tokens in JavaScript and widens `--focus-ring-width`.
|
|
385
|
+
on "System"; it steps the colour tokens in JavaScript and widens `--focus-ring-width`. In
|
|
386
|
+
light it also darkens the well (`--bg-surface-2`, 10 % ink into the card) and deepens the
|
|
387
|
+
money, status, teal, orange and `--status-edited` colours and `--bg-active` so they keep
|
|
388
|
+
their contrast on it; dark keeps its well. A link button's and TextLink's brand reads
|
|
389
|
+
`--brand-muted` (the brand as text) under it, in both modes. The
|
|
339
390
|
stores in [Wiring](#wiring) put both attributes there; the attribute names are frozen.
|
|
340
391
|
|
|
341
392
|
- **`large:`** applies at Large AND Extra large, **`xlarge:`** only at Extra large, and
|
|
@@ -505,25 +556,27 @@ columns, strings and permissions (see the note at the top of `src/feedback/feedb
|
|
|
505
556
|
|
|
506
557
|
<!-- BEGIN GENERATED: exports — node scripts/gen-export-inventory.mjs -->
|
|
507
558
|
|
|
508
|
-
**
|
|
559
|
+
**1925 names from 313 modules** — 890 values and 1035 types. _Italic_ is a type-only export.
|
|
509
560
|
|
|
510
561
|
Generated from `dist/index.d.ts` by `node scripts/gen-export-inventory.mjs`; the count
|
|
511
562
|
is pinned by `src/__tests__/public-surface.test.ts`. Do not edit between the markers.
|
|
512
563
|
|
|
513
564
|
| Entry point | Names |
|
|
514
565
|
|---|---|
|
|
515
|
-
| `@eifi1/ui-kit` |
|
|
516
|
-
| `@eifi1/ui-kit/chart` |
|
|
566
|
+
| `@eifi1/ui-kit` | 1925 |
|
|
567
|
+
| `@eifi1/ui-kit/chart` | 92 |
|
|
517
568
|
| `@eifi1/ui-kit/shell` | 77 |
|
|
518
|
-
| `@eifi1/ui-kit/data-table` |
|
|
519
|
-
| `@eifi1/ui-kit/wizard` |
|
|
569
|
+
| `@eifi1/ui-kit/data-table` | 51 |
|
|
570
|
+
| `@eifi1/ui-kit/wizard` | 24 |
|
|
520
571
|
| `@eifi1/ui-kit/tour` | 7 |
|
|
521
|
-
| `@eifi1/ui-kit/feedback` |
|
|
572
|
+
| `@eifi1/ui-kit/feedback` | 164 |
|
|
522
573
|
| `@eifi1/ui-kit/search` | 23 |
|
|
523
574
|
| `@eifi1/ui-kit/dates` | 22 |
|
|
524
575
|
| `@eifi1/ui-kit/table-text` | 14 |
|
|
525
|
-
| `@eifi1/ui-kit/
|
|
526
|
-
| `@eifi1/ui-kit/
|
|
576
|
+
| `@eifi1/ui-kit/currencies` | 3 |
|
|
577
|
+
| `@eifi1/ui-kit/eslint` | 1 |
|
|
578
|
+
| `@eifi1/ui-kit/testing` | 11 |
|
|
579
|
+
| `@eifi1/ui-kit/rhf` | 48 |
|
|
527
580
|
|
|
528
581
|
Everything below is reachable from the main `@eifi1/ui-kit` barrel. The subpaths are a
|
|
529
582
|
re-slicing of it, never a second API.
|
|
@@ -549,6 +602,7 @@ re-slicing of it, never a second API.
|
|
|
549
602
|
| `lib/isin` | `formatIsin`, `isinCheckDigit`, `isValidIsin` |
|
|
550
603
|
| `lib/phone` | `formatNationalPhone`, `formatPhone`, `isE164`, `parsePhone`, `PHONE_COUNTRIES`, `PHONE_DIAL_CODES`, _`ParsedPhone`_, _`PhoneCountry`_, _`PhoneCountryCode`_ |
|
|
551
604
|
| `lib/column-mapping` | `assignColumnRole`, `guessMapping`, `missingRoles`, `readMappedTable`, `readTextFile`, `roleOfColumn`, _`ColumnMapperResult`_, _`ColumnMapping`_, _`ColumnRole`_ |
|
|
605
|
+
| `lib/device-settings` | `deviceSettings`, `registerDeviceSetting`, `resetDeviceSettings`, _`DeviceSetting`_, _`DeviceSettingKind`_ |
|
|
552
606
|
| `lib/clipping` | `CLIPS_ATTRIBUTE` |
|
|
553
607
|
| `lib/chip-edge-snap` | `refreshChipEdges` |
|
|
554
608
|
|
|
@@ -584,7 +638,7 @@ re-slicing of it, never a second API.
|
|
|
584
638
|
|---|---|
|
|
585
639
|
| `theme/color` | `contrast`, `deltaE`, `hexToOklch`, `luminance`, `oklchToHex`, `oklchToRgb`, `parseHex`, `rgbToOklch`, `simulateCvd`, `solveLightness`, `toHex`, _`CvdType`_, _`Oklch`_, _`Rgb`_ |
|
|
586
640
|
| `theme/palette-derive` | `auditChartRamp`, `auditPalette`, `deriveChartRamp`, `derivePalette`, `describe`, _`AnchorRole`_, _`ChartRampReport`_, _`ContrastCheck`_, _`ContrastReport`_, _`DerivedPalette`_, _`DeriveOptions`_, _`PaletteAnchors`_, _`SemanticTokens`_ |
|
|
587
|
-
| `theme/palette-presets` | `
|
|
641
|
+
| `theme/palette-presets` | `applyTokenSet`, `DEFAULT_PRESET`, `DERIVED_PRESETS`, `IMPRINT_PRESET`, `PALETTES`, `presetById`, _`PalettePreset`_, _`TokenSet`_ |
|
|
588
642
|
| `theme/theme-store` | `applyPersistedTheme`, `createThemeStore`, _`ThemeMode`_, _`ThemePreference`_, _`ThemeState`_, _`ThemeStore`_ |
|
|
589
643
|
| `theme/palette-store` | `applyPersistedPalette`, `createPaletteStore`, _`PaletteStore`_ |
|
|
590
644
|
| `theme/text-size` | `applyPersistedTextSize`, `applyTextSize`, `createTextSizeStore`, `isTextSize`, `readPersistedTextSize`, `readTextSize`, `resolveTextSize`, `TEXT_SCALE`, `TEXT_SIZE_INLINE_SCRIPT`, `TEXT_SIZES`, `useTextSize`, _`ApplyTextSizeOptions`_, _`PersistedAppearanceOptions`_, _`PersistedTextSize`_, _`TextSize`_, _`TextSizeInfo`_, _`TextSizeState`_, _`TextSizeStore`_ |
|
|
@@ -608,7 +662,7 @@ re-slicing of it, never a second API.
|
|
|
608
662
|
| `components/button` | `Button`, _`ButtonLinkProps`_, _`ButtonProps`_ |
|
|
609
663
|
| `components/button-look` | `buttonClasses`, `TOUCH_TARGET_LARGE`, _`ButtonClassesOptions`_, _`ButtonSize`_, _`ButtonTone`_, _`ButtonVariant`_ |
|
|
610
664
|
| `components/icon-button` | `IconButton`, _`IconButtonGlyphSize`_, _`IconButtonLinkProps`_, _`IconButtonProps`_, _`IconButtonSize`_, _`IconButtonTone`_, _`IconButtonToneColor`_, _`IconButtonVariant`_ |
|
|
611
|
-
| `components/field-base` | `DEFAULT_CHARACTER_COUNT_LABELS`, `DEFAULT_PASSWORD_REVEAL_LABELS`, `FIELD_BASE`, `FIELD_DISPLAY`, `FIELD_FLOATING_PAD`, `FIELD_INVALID`, `FIELD_TOUCH_TEXT`, `FIELD_TRIGGER`, `FIELD_WRITABLE_LOOK`, `FieldChevron`, `FLOATING_INPUT_CLASS`, `FLOATING_LABEL_CLASS`, `FloatingField`, `Label`,
|
|
665
|
+
| `components/field-base` | `DEFAULT_CHARACTER_COUNT_LABELS`, `DEFAULT_PASSWORD_REVEAL_LABELS`, `FIELD_BASE`, `FIELD_DISPLAY`, `FIELD_FLOATING_PAD`, `FIELD_INVALID`, `FIELD_TOUCH_TEXT`, `FIELD_TRIGGER`, `FIELD_WRITABLE_LOOK`, `FieldChevron`, `FLOATING_INPUT_CLASS`, `FLOATING_LABEL_CLASS`, `FloatingField`, `Label`, _`CharacterCountLabels`_, _`FieldChevronProps`_, _`FloatingFieldProps`_, _`LabelProps`_, _`PasswordRevealLabels`_ |
|
|
612
666
|
| `components/input` | `Input`, _`InputProps`_ |
|
|
613
667
|
| `components/select` | `Select`, _`SelectProps`_ |
|
|
614
668
|
| `components/textarea` | `Textarea`, _`TextareaProps`_ |
|
|
@@ -638,7 +692,7 @@ re-slicing of it, never a second API.
|
|
|
638
692
|
| `components/tooltip` | `placeTooltip`, `Tooltip`, _`TooltipPlacement`_, _`TooltipProps`_, _`TooltipSide`_, _`TooltipSize`_, _`TooltipTap`_, _`TooltipViewport`_ |
|
|
639
693
|
| `components/user-avatar` | `avatarInitials`, `UserAvatar`, _`UserAvatarBadge`_, _`UserAvatarProps`_ |
|
|
640
694
|
| `components/settings-fields` | `ContrastSetting`, `LanguageSetting`, `TextSizeSetting`, `ThemeSetting`, _`ContrastSettingProps`_, _`LanguageSettingProps`_, _`TextSizeSettingProps`_, _`ThemeSettingProps`_, _`ThemeSettingSelectProps`_, _`ThemeSettingToggleProps`_ |
|
|
641
|
-
| `components/field-sync` | `DEFAULT_FIELD_SYNC_LABELS`, `FIELD_SYNC_FRAME`, `FIELD_SYNC_SAVED_MS`, `FieldSyncIndicator`, `FieldSyncRow`, `
|
|
695
|
+
| `components/field-sync` | `DEFAULT_FIELD_SYNC_LABELS`, `FIELD_SYNC_FRAME`, `FIELD_SYNC_SAVED_MS`, `FieldSyncIndicator`, `FieldSyncRow`, `useFieldSync`, _`FieldSyncIndicatorProps`_, _`FieldSyncLabels`_, _`FieldSyncRowProps`_, _`FieldSyncState`_, _`UseFieldSyncOptions`_, _`UseFieldSyncReturn`_ |
|
|
642
696
|
| `components/month-picker` | `DEFAULT_MONTH_PICKER_LABELS`, `MonthPicker`, _`MonthPickerLabels`_, _`MonthPickerProps`_ |
|
|
643
697
|
| `components/checkbox` | `Checkbox`, _`CheckboxProps`_ |
|
|
644
698
|
| `components/switch` | `Switch`, _`SwitchProps`_, _`SwitchSize`_ |
|
|
@@ -667,7 +721,6 @@ re-slicing of it, never a second API.
|
|
|
667
721
|
| `components/treemap` | `fitLabel`, `Treemap`, `TreemapCell`, _`TreemapCellProps`_, _`TreemapNode`_, _`TreemapProps`_ |
|
|
668
722
|
| `components/series-chart` | `resolveTooltipPlacement`, `SeriesChart`, `seriesLegendEntries`, `StaticSeriesChart`, _`SeriesChartAxis`_, _`SeriesChartHit`_, _`SeriesChartMarker`_, _`SeriesChartPoint`_, _`SeriesChartProps`_, _`SeriesChartReference`_, _`SeriesChartRow`_, _`SeriesChartSeries`_, _`SeriesChartSpan`_, _`SeriesChartTickValues`_, _`SeriesChartTone`_, _`SeriesChartTooltip`_, _`SeriesChartTooltipPlacement`_, _`SeriesChartType`_, _`SeriesChartX`_, _`SeriesChartXTick`_, _`SeriesChartXValue`_, _`SeriesLegendAxes`_ |
|
|
669
723
|
| `components/chart-height` | _`ChartHeight`_ |
|
|
670
|
-
| `components/chart-zoom` | `axisExtent`, `DEFAULT_Y_AXIS`, `defaultZoomAxes`, `fitXToY`, `fitYToX`, `NO_ZOOM`, `selectionFromDrag`, `withChartZoom`, `ZOOM_MIN_DRAG`, `ZOOM_SQUARE_ENOUGH`, `zoomAfter`, `zoomAxesFor`, `zoomDomains` |
|
|
671
724
|
| `components/chart-zoom-core` | `SharedXZoom`, _`ZoomAxes`_, _`ZoomAxesSetting`_, _`ZoomBinding`_, _`ZoomDrag`_, _`ZoomFitSeries`_, _`ZoomFitSource`_, _`ZoomRow`_, _`ZoomSelection`_, _`ZoomState`_, _`ZoomTarget`_ |
|
|
672
725
|
| `components/toggle-legend` | `LegendColumn`, `LegendGroup`, `StaticLegend`, `STEP_DASH`, `STROKE_PATTERNS`, `strokeDash`, `toggleHidden`, `ToggleLegend`, _`LegendEntry`_, _`StaticLegendProps`_, _`ToggleLegendProps`_ |
|
|
673
726
|
| `components/facing-pair` | `FACING_SIDES`, `facingAxes`, `facingBand`, `facingHeadingPad`, _`FacingSide`_ |
|
|
@@ -679,7 +732,7 @@ re-slicing of it, never a second API.
|
|
|
679
732
|
| `components/toggle-group` | `ToggleGroup`, _`ToggleGroupBaseProps`_, _`ToggleGroupClearableProps`_, _`ToggleGroupProps`_, _`ToggleGroupRequiredProps`_, _`ToggleOption`_ |
|
|
680
733
|
| `components/nav-pills` | `NavPills`, _`NavPillItem`_, _`NavPillLinkProps`_, _`NavPillsCurrent`_, _`NavPillsProps`_ |
|
|
681
734
|
| `components/chip` | `Chip`, _`ChipHue`_, _`ChipLinkProps`_, _`ChipProps`_, _`ChipShape`_, _`ChipSize`_, _`ChipTone`_, _`ChipVariant`_ |
|
|
682
|
-
| `components/chip-input` | `ChipInput`, `DEFAULT_CHIP_INPUT_LABELS`,
|
|
735
|
+
| `components/chip-input` | `ChipInput`, `DEFAULT_CHIP_INPUT_LABELS`, _`ChipInputLabels`_, _`ChipInputProps`_ |
|
|
683
736
|
| `components/wizard-stepper` | `WizardStepper` |
|
|
684
737
|
| `components/hover-menu` | `HoverMenu`, _`HoverMenuProps`_ |
|
|
685
738
|
| `components/modal` | `Modal`, `ModalCloseContext`, `useBackdropClose`, _`ModalProps`_ |
|
|
@@ -732,9 +785,9 @@ re-slicing of it, never a second API.
|
|
|
732
785
|
| `components/country-select` | `CountrySelect`, `DEFAULT_COUNTRY_SELECT_LABELS`, _`CountrySelectLabels`_, _`CountrySelectProps`_ |
|
|
733
786
|
| `components/iban-input` | `DEFAULT_IBAN_INPUT_LABELS`, `IbanInput`, _`IbanInputLabels`_, _`IbanInputProps`_ |
|
|
734
787
|
| `components/phone-input` | `DEFAULT_PHONE_INPUT_LABELS`, `PhoneInput`, _`PhoneInputLabels`_, _`PhoneInputProps`_ |
|
|
735
|
-
| `components/field-strip` | `FieldStrip`, _`FieldStripIds`_, _`
|
|
788
|
+
| `components/field-strip` | `FieldStrip`, _`FieldStripIds`_, _`FieldStripProps`_ |
|
|
736
789
|
| `components/column-mapper` | `ColumnMapper`, `ColumnRoleTable`, `DEFAULT_COLUMN_MAPPER_LABELS`, _`ColumnMapperLabels`_, _`ColumnMapperProps`_, _`ColumnRoleTableBodyProps`_, _`ColumnRoleTableProps`_, _`ColumnRoleTableRowProps`_ |
|
|
737
|
-
| `components/data-table-labels` | `DEFAULT_DATA_TABLE_LABELS`,
|
|
790
|
+
| `components/data-table-labels` | `DEFAULT_DATA_TABLE_LABELS`, _`DataTableLabels`_ |
|
|
738
791
|
| `components/data-table-sort` | `decodeSorts`, `encodeSorts`, `nextSorts`, `normalizeSorts`, _`SortCycle`_, _`SortDir`_, _`SortState`_, _`SortStepOptions`_ |
|
|
739
792
|
| `components/data-table-filters` | `dateFilter`, `decodeFilterValue`, `decodeFilterValueOfType`, `defaultFilterState`, `encodeFilterValue`, `filterHref`, `isFilterActive`, `numberFilter`, `resolveFilter`, `rowMatches`, `selectFilter`, `textFilter`, _`ColumnFilter`_, _`FilterValue`_ |
|
|
740
793
|
| `components/data-table-pagination` | `PAGE_SIZE_OPTIONS`, `Pagination` |
|
|
@@ -779,6 +832,7 @@ re-slicing of it, never a second API.
|
|
|
779
832
|
| `settings/settings-heading` | `SettingsHeadingLevel`, `useSettingsHeadingLevel`, _`SettingsHeadingLevelProps`_, _`SettingsHeadingTag`_ |
|
|
780
833
|
| `settings/settings-catalogue` | `settingsHref`, `settingsSearchEntries`, `visibleSettingsEntries`, `visibleSettingsGroups`, _`SettingsEntry`_, _`SettingsGroup`_, _`SettingsSearchEntriesOptions`_ |
|
|
781
834
|
| `settings/settings-labels` | `DEFAULT_SETTINGS_LABELS`, `useSettingsLabels`, _`SettingsCoreGroup`_, _`SettingsGroupLabels`_, _`SettingsLabels`_ |
|
|
835
|
+
| `settings/device-reset-setting` | `DEFAULT_DEVICE_RESET_LABELS`, `DEVICE_RESET_ANCHOR`, `DeviceResetSetting`, _`DeviceResetLabels`_, _`DeviceResetSettingProps`_ |
|
|
782
836
|
| `settings/use-account-language` | `matchOfferedLanguage`, `resolveAccountLanguage`, `useAccountLanguage`, _`AccountLanguage`_, _`AccountLanguageSource`_, _`ResolveAccountLanguageInput`_, _`ResolvedAccountLanguage`_, _`UseAccountLanguageOptions`_ |
|
|
783
837
|
| `settings/use-account-appearance` | `resolveAccountAppearance`, `useAccountAppearance`, _`AccountAppearance`_, _`AccountAppearanceFields`_, _`AccountAppearancePatch`_, _`AppearanceSource`_, _`DeviceAppearance`_, _`ResolvedAccountAppearance`_, _`UseAccountAppearanceOptions`_ |
|
|
784
838
|
|
|
@@ -801,7 +855,7 @@ re-slicing of it, never a second API.
|
|
|
801
855
|
| `feedback/feedback-attachment` | `DEFAULT_ATTACHMENT_ACCEPT`, `DEFAULT_FEEDBACK_ATTACHMENT_LABELS`, `DEFAULT_MAX_ATTACHMENT_BYTES`, `DEFAULT_MAX_ATTACHMENTS`, `FeedbackAttachmentField`, `pastedName`, _`FeedbackAttachmentError`_, _`FeedbackAttachmentErrorInfo`_, _`FeedbackAttachmentFieldLabels`_, _`FeedbackAttachmentFieldMultipleProps`_, _`FeedbackAttachmentFieldProps`_, _`FeedbackAttachmentFieldRefsProps`_, _`FeedbackAttachmentFieldSingleProps`_, _`FeedbackAttachmentRef`_, _`FeedbackAttachmentRefsError`_ |
|
|
802
856
|
| `feedback/feedback-dialog` | `DEFAULT_FEEDBACK_DIALOG_LABELS`, `FeedbackDialog`, _`FeedbackAttachmentLabels`_, _`FeedbackCategoryOption`_, _`FeedbackDialogLabels`_, _`FeedbackDialogMultipleProps`_, _`FeedbackDialogProps`_, _`FeedbackDialogSingleProps`_, _`FeedbackDialogTextLabels`_, _`FeedbackMultipleSubmission`_, _`FeedbackSubmission`_, _`FeedbackSubmitHint`_ |
|
|
803
857
|
| `feedback/feedback-inbox` | `FeedbackCategoryBadge`, `FeedbackDetail`, `FeedbackDetailSection`, `FeedbackNoteEditor`, `FeedbackProse`, `FeedbackStatusBadge`, `FeedbackStatusTransitions`, _`FeedbackNoteAttachment`_ |
|
|
804
|
-
| `feedback/feedback-thread` | `ChatComposer`, `DEFAULT_FEEDBACK_COMPOSER_LABELS`, `DEFAULT_FEEDBACK_THREAD_LABELS`, `
|
|
858
|
+
| `feedback/feedback-thread` | `ChatComposer`, `DEFAULT_FEEDBACK_COMPOSER_LABELS`, `DEFAULT_FEEDBACK_THREAD_LABELS`, `FeedbackThread`, _`ChatComposerHandle`_, _`ChatComposerLabels`_, _`ChatComposerProps`_, _`ChatComposerSlotContext`_, _`FeedbackComposerAttachment`_, _`FeedbackComposerHandle`_, _`FeedbackComposerLabels`_, _`FeedbackComposerProps`_, _`FeedbackComposerSlotContext`_, _`FeedbackThreadAttachment`_, _`FeedbackThreadEvent`_, _`FeedbackThreadItem`_, _`FeedbackThreadLabels`_, _`FeedbackThreadMessage`_, _`FeedbackThreadProps`_ |
|
|
805
859
|
| `feedback/feedback-record` | `appendRework`, `attachmentName`, `FEEDBACK_ATTACHMENT_ACCEPT`, `FEEDBACK_AUTHOR_EDITABLE_STATUSES`, `FEEDBACK_AWAITING_STATUSES`, `FEEDBACK_PICKABLE_CATEGORIES`, `FEEDBACK_REWORKABLE_STATUSES`, `feedbackAttachmentLine`, `isImageAttachment`, `replaceDescription`, `reworkCount`, `splitBodyAttachments`, `splitDescription`, _`FeedbackContext`_, _`FeedbackEnvironment`_, _`FeedbackRecord`_ |
|
|
806
860
|
| `feedback/feedback-labels` | `DEFAULT_FEEDBACK_CATEGORY_LABELS`, `DEFAULT_FEEDBACK_STATUS_LABELS`, `DEFAULT_FEEDBACK_TOAST_LABELS`, `useFeedbackCategoryLabels`, `useFeedbackStatusLabels`, `useFeedbackToastLabels`, _`FeedbackCategoryLabels`_, _`FeedbackStatusLabels`_, _`FeedbackToastLabels`_ |
|
|
807
861
|
| `feedback/feedback-status-undo` | `FEEDBACK_UNDO_DURATION`, `useFeedbackStatusUndo`, _`FeedbackStatusChange`_, _`FeedbackStatusMutate`_, _`FeedbackStatusPatch`_, _`FeedbackStatusRow`_, _`FeedbackStatusUndoOptions`_ |
|
|
@@ -819,7 +873,7 @@ re-slicing of it, never a second API.
|
|
|
819
873
|
|
|
820
874
|
| Module | Exports |
|
|
821
875
|
|---|---|
|
|
822
|
-
| `wizard/types` | `DEFAULT_WIZARD_LABELS`,
|
|
876
|
+
| `wizard/types` | `DEFAULT_WIZARD_LABELS`, _`FieldErrors`_, _`StepStatus`_, _`SummaryItem`_, _`SummarySection`_, _`UseWizardOptions`_, _`UseWizardReturn`_, _`ValidateResult`_, _`WizardLabels`_, _`WizardStepConfig`_, _`WizardUrlSync`_ |
|
|
823
877
|
| `wizard/use-wizard` | `useWizard` |
|
|
824
878
|
| `wizard/wizard-context` | `useOptionalWizardContext`, `useWizardContext`, `useWizardNextGate`, `useWizardStepValidate`, `WizardContextProvider`, _`WizardContextValue`_ |
|
|
825
879
|
| `wizard/validation` | `requiredFieldsValidator`, _`RequiredFieldSpec`_ |
|
|
@@ -904,6 +958,20 @@ re-slicing of it, never a second API.
|
|
|
904
958
|
| `billing/billing-overview` | _`BillingOverview`_, _`PortalRequest`_, _`PortalTarget`_, _`SubscriptionSource`_ |
|
|
905
959
|
| `billing/plan-limit-toast` | `usePlanLimitToast`, _`PlanLimitToastOptions`_ |
|
|
906
960
|
|
|
961
|
+
### notifications
|
|
962
|
+
|
|
963
|
+
| Module | Exports |
|
|
964
|
+
|---|---|
|
|
965
|
+
| `notifications/notifications-labels` | `DEFAULT_NOTIFICATIONS_LABELS`, _`NotificationRegionLabels`_, _`NotificationsLabels`_ |
|
|
966
|
+
| `notifications/notification-types` | _`DigestCadence`_, _`NotificationSettingsPatch`_, _`NotificationSwitches`_, _`NotificationTypeEntry`_, _`NotificationTypeGroup`_, _`NotificationTypesValue`_, _`PushDeviceItem`_ |
|
|
967
|
+
| `notifications/notification-types-setting` | `NotificationTypesSetting`, _`NotificationTypesSettingProps`_ |
|
|
968
|
+
| `notifications/quiet-hours-setting` | `QuietHoursSetting`, _`QuietHoursSettingProps`_ |
|
|
969
|
+
| `notifications/time-zone-select` | `deviceTimeZone`, `timeZoneOptions`, `TimeZoneSelect`, _`TimeZoneSelectProps`_ |
|
|
970
|
+
| `notifications/use-push-device` | `notifyPushSubscriptionChanged`, `PUSH_SUBSCRIPTION_CHANGED`, `PushDeviceError`, `pushSupported`, `usePushDevice`, _`PushDevice`_, _`PushDeviceErrorCode`_, _`PushPermission`_, _`PushSubscriptionInput`_, _`UsePushDeviceOptions`_ |
|
|
971
|
+
| `notifications/push-device-setting` | `PushDeviceSetting`, _`PushDeviceAction`_, _`PushDeviceSettingProps`_ |
|
|
972
|
+
| `notifications/push-devices-setting` | `describeUserAgent`, `PushDevicesSetting`, _`PushDevicesSettingProps`_ |
|
|
973
|
+
| `notifications/unsubscribe-panel` | `UnsubscribePanel`, `unsubscribeTokenType`, _`UnsubscribePanelProps`_ |
|
|
974
|
+
|
|
907
975
|
### demo
|
|
908
976
|
|
|
909
977
|
| Module | Exports |
|
|
@@ -915,6 +983,12 @@ re-slicing of it, never a second API.
|
|
|
915
983
|
| `demo/demo-banner` | `DemoBanner`, _`DemoBannerProps`_ |
|
|
916
984
|
| `demo/demo-ended` | `DemoEnded`, _`DemoEndedProps`_ |
|
|
917
985
|
|
|
986
|
+
### root
|
|
987
|
+
|
|
988
|
+
| Module | Exports |
|
|
989
|
+
|---|---|
|
|
990
|
+
| `currencies` | `CURRENCY_COUNTRIES` |
|
|
991
|
+
|
|
918
992
|
<!-- END GENERATED: exports -->
|
|
919
993
|
|
|
920
994
|
## Forms / refs
|
|
@@ -926,36 +1000,36 @@ element that takes focus: the `<input>` of `Input`, `NumberField`, `AmountInput`
|
|
|
926
1000
|
on its checked option. So they work directly with react-hook-form:
|
|
927
1001
|
`<Input {...field} />` (from `Controller`/`register`) attaches RHF's ref, giving
|
|
928
1002
|
focus-and-scroll-to-error for free. A component that spreads its props onto an element
|
|
929
|
-
(`Card`, `EmptyState`, `PageHeader`, …) takes that element's `ref` too. For
|
|
930
|
-
|
|
1003
|
+
(`Card`, `EmptyState`, `PageHeader`, …) takes that element's `ref` too. For fields bound
|
|
1004
|
+
to a react-hook-form form in one line each, see `@eifi1/ui-kit/rhf` below.
|
|
931
1005
|
|
|
932
1006
|
### react-hook-form — `@eifi1/ui-kit/rhf` (optional)
|
|
933
1007
|
|
|
934
|
-
|
|
935
|
-
`
|
|
936
|
-
|
|
1008
|
+
The react-hook-form adapter: `Form`, the bound fields (`RhfTextField`, `RhfNumberField`,
|
|
1009
|
+
`RhfMoneyField`, `RhfDateField`, `RhfSelect`, `RhfCombobox`, `RhfCheckbox`, …) and
|
|
1010
|
+
`RhfField` for a control of your own, and the only entry that needs `react-hook-form` (an
|
|
1011
|
+
**optional** peer, `^7.55.0`). The main barrel does not import it, so apps without a form
|
|
1012
|
+
library install nothing.
|
|
937
1013
|
|
|
938
1014
|
```tsx
|
|
939
|
-
import { Form,
|
|
1015
|
+
import { Form, RhfField, RhfNumberField, RhfTextField } from "@eifi1/ui-kit/rhf";
|
|
940
1016
|
|
|
941
1017
|
<Form {...form}>
|
|
942
|
-
<
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
<NumberField value={field.value} onCommit={field.onChange} />
|
|
947
|
-
</FormControl>
|
|
948
|
-
<FormMessage />
|
|
949
|
-
</FormItem>
|
|
1018
|
+
<RhfTextField name="title" label="Title" required rules={{ required: "Give it a title." }} />
|
|
1019
|
+
<RhfNumberField name="amount" label="Amount" unit="EUR" hint="Net of VAT." />
|
|
1020
|
+
<RhfField name="street" label="Street" render={({ field, invalid }) => (
|
|
1021
|
+
<AddressAutocomplete {...field} invalid={invalid} />
|
|
950
1022
|
)} />
|
|
951
1023
|
</Form>
|
|
952
1024
|
```
|
|
953
1025
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1026
|
+
Each bound field is a label, the control, a hint and the form's message wired to each
|
|
1027
|
+
other: the control's `aria-describedby` names only the hint and message actually rendered
|
|
1028
|
+
(merged after the control's own), `aria-invalid` and `invalid` come from the field state,
|
|
1029
|
+
and `field.ref` reaches the focusable element, so a failed submit focuses the first field
|
|
1030
|
+
in error. The message is the form's own; the kit adds no text. The shadcn scaffold the
|
|
1031
|
+
adapter started as (`FormField`, `FormItem`, `FormLabel`, `FormControl`,
|
|
1032
|
+
`FormDescription`, `FormMessage`, `useFormField`) left the public surface in 0.35.
|
|
959
1033
|
|
|
960
1034
|
### Pasted and imported tables — `@eifi1/ui-kit/table-text`
|
|
961
1035
|
|
|
@@ -3,6 +3,7 @@ import { type LabelOverride } from "../i18n/kit-labels.js";
|
|
|
3
3
|
import type { RoleVocabulary } from "../components/account-chips.js";
|
|
4
4
|
import type { SelectProps } from "../components/select.js";
|
|
5
5
|
import type { CommitScope } from "../components/write-lock.js";
|
|
6
|
+
import type { FieldHelpProps } from "../components/field-parts.js";
|
|
6
7
|
import { DEFAULT_ROLE_SELECT_LABELS } from "./role-select-labels.js";
|
|
7
8
|
/**
|
|
8
9
|
* The role of an account, chosen by an admin (docs/user-admin-harmonization.md §3.3,
|
|
@@ -94,7 +95,7 @@ export interface RoleSelectProps<R extends string = string> extends Omit<SelectP
|
|
|
94
95
|
* (`size`, `commit`, `hint`, `error`, `data-*`).
|
|
95
96
|
*/
|
|
96
97
|
export declare function RoleSelect<R extends string = string>({ value, roles, onChange, offered, disabledReason, optionDisabledReason, name, labels: labelsProp, label, ...rest }: RoleSelectProps<R>): import("react").JSX.Element;
|
|
97
|
-
export interface RolesEditorProps<R extends string = string> {
|
|
98
|
+
export interface RolesEditorProps<R extends string = string> extends FieldHelpProps {
|
|
98
99
|
/** The roles ticked — the draft the app holds while its dialog is open. */
|
|
99
100
|
value: readonly R[];
|
|
100
101
|
roles: RoleVocabulary<R>;
|
|
@@ -133,4 +134,4 @@ export interface RolesEditorProps<R extends string = string> {
|
|
|
133
134
|
* `AdminActionConfirm` (`acknowledge`, §4.2) — which can draw this editor as its
|
|
134
135
|
* `children`, so the roles and the tick are one dialog.
|
|
135
136
|
*/
|
|
136
|
-
export declare function RolesEditor<R extends string = string>({ value, roles, onChange, offered, disabledReason, optionDisabledReason, legend, legendVisibility, required, hint, error, columns, commit, className, labels: labelsProp, }: RolesEditorProps<R>): import("react").JSX.Element;
|
|
137
|
+
export declare function RolesEditor<R extends string = string>({ value, roles, onChange, offered, disabledReason, optionDisabledReason, legend, legendVisibility, required, hint, help, error, columns, commit, className, labels: labelsProp, }: RolesEditorProps<R>): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/admin/role-select.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { hasContent } from \"../lib/presence\";\nimport type { RoleVocabulary } from \"../components/account-chips\";\nimport { CheckboxGroup } from \"../components/checkbox-group\";\nimport type { CheckboxGroupOption } from \"../components/checkbox-group\";\nimport { Select } from \"../components/select\";\nimport type { SelectProps } from \"../components/select\";\nimport type { CommitScope } from \"../components/write-lock\";\nimport { DEFAULT_ROLE_SELECT_LABELS } from \"./role-select-labels\";\n\n/**\n * The role of an account, chosen by an admin (docs/user-admin-harmonization.md §3.3,\n * §4.1, §7): {@link RoleSelect} for the apps where an account has ONE role (keksdose,\n * Kurvenschmiede) and {@link RolesEditor} for kastlan, where an account has several per\n * company.\n *\n * Both take the app's {@link RoleVocabulary} — the one `RoleChip` reads — so a role is\n * called the same in the chip, the select and the editor. Neither sends a request: a role\n * change is an `acknowledge` action (§4.2), so the app opens `AdminActionConfirm` from\n * `onChange` and the value stays where the server has it until the server says otherwise.\n *\n * WHY THE REASONS. The server refuses the last active admin's demotion (`last_admin`),\n * your own admin role (`self`), Kurvenschmiede's CUSTOMER for an account that owns work,\n * kastlan's TENANT until a tenant portal exists (§4.1, §9.6). A choice the server will\n * refuse is shown as unavailable, with why, rather than offered and answered with an\n * error after a confirmation dialog — the 0.18 write-lock rule: a control that cannot\n * act says so where it is. `\"last_admin\"` and `\"self\"` are the kit's words in every\n * language; anything else is the app's own sentence.\n */\n\n/** A reason the kit words itself. `self_action` is the server's code for `self` (the\n * account error codes), so a refusal's code can be handed on as it came. */\nexport type RoleLockCode = \"last_admin\" | \"self\" | \"self_action\";\n\n/**\n * Why a role (or the whole control) cannot be changed: one of the kit's\n * {@link RoleLockCode}s, or the app's own words.\n */\nexport type RoleLock = RoleLockCode | (string & {}) | ReactNode;\n\n/** The `roleSelect` namespace — RoleSelect's and RolesEditor's words. */\nexport interface RoleSelectLabels {\n /** The select's name where no `label` is drawn, and RolesEditor's legend. \"Role\". */\n label: string;\n /** RolesEditor's legend. \"Roles\". */\n rolesLegend: string;\n /** The select's accessible name in a roster row — \"Role of Ada Example\". */\n roleOf: (name: string) => string;\n /** The whole control is locked: the account is the last active administrator. */\n lockedLastAdmin: string;\n /** The whole control is locked: it is the admin's own account. */\n lockedSelf: string;\n /** One option is unavailable for the last active administrator — said after the\n * role's name, inside the option. */\n notForLastAdmin: string;\n /** One option is unavailable on the admin's own account. */\n notForSelf: string;\n /** An unavailable option's text: the role's name and why. */\n unavailable: (role: string, reason: string) => string;\n}\n\n// Defined in ./role-select-labels, which holds no component code (0.34, KS U8).\nexport { DEFAULT_ROLE_SELECT_LABELS };\n\n/** The whole-control reason, the kit's codes in the kit's words. */\nfunction lockText(reason: RoleLock, labels: RoleSelectLabels): ReactNode {\n if (reason === \"last_admin\") return labels.lockedLastAdmin;\n if (reason === \"self\" || reason === \"self_action\") return labels.lockedSelf;\n return reason;\n}\n\n/** An option's reason as the text a native `<option>` can hold. */\nfunction optionReasonText(reason: string, labels: RoleSelectLabels): string {\n if (reason === \"last_admin\") return labels.notForLastAdmin;\n if (reason === \"self\" || reason === \"self_action\") return labels.notForSelf;\n return reason;\n}\n\n/** The vocabulary's keys, in its own order. */\nfunction keysOf<R extends string>(roles: RoleVocabulary<R>): R[] {\n return Object.keys(roles) as R[];\n}\n\n/* ── RoleSelect ─────────────────────────────────────────────────────────────── */\n\nexport interface RoleSelectProps<R extends string = string>\n extends Omit<SelectProps, \"value\" | \"defaultValue\" | \"onChange\" | \"children\" | \"multiple\" | \"disabledReason\"> {\n /** The role the server has. Controlled: a pick does not move the select until the\n * app's request lands and the row comes back with the new role. */\n value: R | null | undefined;\n /** The app's roles — what `RoleChip` reads. Their order is the list's. */\n roles: RoleVocabulary<R>;\n /** A role other than `value` was picked. The app asks `AdminActionConfirm` (an\n * `acknowledge` action, §4.2) and sends the change. */\n onChange: (role: R) => void;\n /**\n * The roles that may be CHOSEN here, in the vocabulary's order whatever order this is\n * in. Default: all of them. A role the account holds that is not offered (Kurvenschmiede's\n * REVIEWER, given only through the reviewer scope, §9.6) is still shown, unavailable:\n * a select that dropped it would show the account as something it is not.\n */\n offered?: readonly R[];\n /**\n * Why the whole choice is locked for this account: `\"last_admin\"`, `\"self\"`, or the\n * app's own words. The select stays focusable and says so (Select's `disabledReason`).\n */\n disabledReason?: RoleLock;\n /**\n * Why ONE role cannot be chosen for this account: `\"last_admin\"`, `\"self\"`, or the\n * app's own words (Kurvenschmiede: \"owns work\", for CUSTOMER) — a STRING, because a\n * native option holds text only. The option is disabled and reads \"Member (not for the\n * last administrator)\". `undefined` for an available role.\n */\n optionDisabledReason?: (role: R) => string | undefined;\n /** The account's name, for the select's accessible name in a roster row (\"Role of\n * Ada Example\") where no `label` is drawn. */\n name?: string;\n labels?: LabelOverride<RoleSelectLabels>;\n}\n\n/**\n * One role, picked from the app's vocabulary — Kurvenschmiede's roster `Select`\n * (users-panel.tsx), with the reasons it left to the server's toast drawn in place.\n *\n * Unlabelled by default, for a table cell: named \"Role of Ada Example\" (`name`) or\n * \"Role\". Pass `label` for a form field. Every {@link Select} prop passes through\n * (`size`, `commit`, `hint`, `error`, `data-*`).\n */\nexport function RoleSelect<R extends string = string>({\n value,\n roles,\n onChange,\n offered,\n disabledReason,\n optionDisabledReason,\n name,\n labels: labelsProp,\n label,\n ...rest\n}: RoleSelectProps<R>) {\n const labels = useKitLabels(\"roleSelect\", DEFAULT_ROLE_SELECT_LABELS, labelsProp);\n const all = keysOf(roles);\n const choosable = new Set<R>(offered ?? all);\n const held = value ?? null;\n // A cell has no room for a visible label: the select is named for the account it\n // belongs to, so fifty of them in a roster are not fifty \"Role\"s.\n const ariaLabel =\n label === undefined ? (rest[\"aria-label\"] ?? (name ? labels.roleOf(name) : labels.label)) : rest[\"aria-label\"];\n return (\n <Select\n {...rest}\n label={label}\n aria-label={ariaLabel}\n value={held ?? \"\"}\n disabledReason={hasContent(disabledReason) ? lockText(disabledReason, labels) : undefined}\n onChange={(event) => {\n const next = event.target.value as R;\n if (next && next !== held) onChange(next);\n }}\n >\n {held === null && <option value=\"\" disabled />}\n {all\n .filter((role) => choosable.has(role) || role === held)\n .map((role) => {\n const word = roles[role].label;\n const reason = role === held ? undefined : optionDisabledReason?.(role);\n const unavailable = !choosable.has(role) || hasContent(reason);\n return (\n <option key={role} value={role} disabled={unavailable && role !== held}>\n {reason ? labels.unavailable(word, optionReasonText(reason, labels)) : word}\n </option>\n );\n })}\n {/* A role the vocabulary does not know (an older client against a newer API) is\n still the account's role: shown as its key, as RoleChip shows it. */}\n {held !== null && !all.includes(held) && (\n <option value={held} disabled>\n {held}\n </option>\n )}\n </Select>\n );\n}\n\n/* ── RolesEditor ────────────────────────────────────────────────────────────── */\n\nexport interface RolesEditorProps<R extends string = string> {\n /** The roles ticked — the draft the app holds while its dialog is open. */\n value: readonly R[];\n roles: RoleVocabulary<R>;\n /** The new set, in the vocabulary's order (a role the editor does not offer, but the\n * account holds, is kept after the rest — CheckboxGroup's rule). */\n onChange: (roles: R[]) => void;\n /** The roles that may be ticked or unticked here. Default: all. kastlan leaves TENANT\n * out until a tenant portal exists (§4.1). */\n offered?: readonly R[];\n /** Why nothing can be changed: `\"last_admin\"`, `\"self\"` or the app's words. */\n disabledReason?: RoleLock;\n /** Why one role cannot be changed — shown under it, and the box keeps its state:\n * `\"last_admin\"` on the last administrator's ADMIN, say. */\n optionDisabledReason?: (role: R) => RoleLock | undefined;\n /** Default `roleSelect.rolesLegend` — \"Roles\". kastlan names the company: \"Roles in\n * Example Ltd\". */\n legend?: ReactNode;\n legendVisibility?: \"visible\" | \"sr-only\";\n /** At least one role (kastlan's dialog saves none). Draws the required star. */\n required?: boolean;\n hint?: ReactNode;\n error?: ReactNode;\n columns?: 1 | 2 | 3 | 4;\n /** The editor SAVES on change — the write lock's opt-in (CheckboxGroup's `commit`). */\n commit?: CommitScope;\n className?: string;\n labels?: LabelOverride<RoleSelectLabels>;\n}\n\n/**\n * Several roles at once — kastlan's manage-roles dialog (`ChoiceCardGroup multiple`),\n * which holds an account's roles in the CURRENT company (§4.1: `PUT /admin/users/{id}/roles`).\n * A kit {@link CheckboxGroup} of the vocabulary, with the reasons of {@link RoleSelect}:\n * a role that cannot change keeps its box as it is and says why under it.\n *\n * A field, not a form: the app's dialog holds the draft, and its Save goes through\n * `AdminActionConfirm` (`acknowledge`, §4.2) — which can draw this editor as its\n * `children`, so the roles and the tick are one dialog.\n */\nexport function RolesEditor<R extends string = string>({\n value,\n roles,\n onChange,\n offered,\n disabledReason,\n optionDisabledReason,\n legend,\n legendVisibility,\n required,\n hint,\n error,\n columns,\n commit,\n className,\n labels: labelsProp,\n}: RolesEditorProps<R>) {\n const labels = useKitLabels(\"roleSelect\", DEFAULT_ROLE_SELECT_LABELS, labelsProp);\n const all = keysOf(roles);\n const choosable = new Set<R>(offered ?? all);\n const held = new Set<R>(value);\n const options: CheckboxGroupOption<R>[] = all\n .filter((role) => choosable.has(role) || held.has(role))\n .map((role) => {\n const reason = optionDisabledReason?.(role);\n const locked = hasContent(reason);\n return {\n value: role,\n label: roles[role].label,\n hint: locked ? lockText(reason, labels) : undefined,\n disabled: locked || !choosable.has(role),\n };\n });\n return (\n <CheckboxGroup<R>\n legend={legend ?? labels.rolesLegend}\n legendVisibility={legendVisibility}\n options={options}\n value={[...value]}\n onChange={onChange}\n required={required}\n hint={hint}\n error={error}\n columns={columns}\n commit={commit}\n disabledReason={hasContent(disabledReason) ? lockText(disabledReason, labels) : undefined}\n className={className}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/admin/role-select.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { hasContent } from \"../lib/presence\";\nimport type { RoleVocabulary } from \"../components/account-chips\";\nimport { CheckboxGroup } from \"../components/checkbox-group\";\nimport type { CheckboxGroupOption } from \"../components/checkbox-group\";\nimport { Select } from \"../components/select\";\nimport type { SelectProps } from \"../components/select\";\nimport type { CommitScope } from \"../components/write-lock\";\nimport type { FieldHelpProps } from \"../components/field-parts\";\nimport { DEFAULT_ROLE_SELECT_LABELS } from \"./role-select-labels\";\n\n/**\n * The role of an account, chosen by an admin (docs/user-admin-harmonization.md §3.3,\n * §4.1, §7): {@link RoleSelect} for the apps where an account has ONE role (keksdose,\n * Kurvenschmiede) and {@link RolesEditor} for kastlan, where an account has several per\n * company.\n *\n * Both take the app's {@link RoleVocabulary} — the one `RoleChip` reads — so a role is\n * called the same in the chip, the select and the editor. Neither sends a request: a role\n * change is an `acknowledge` action (§4.2), so the app opens `AdminActionConfirm` from\n * `onChange` and the value stays where the server has it until the server says otherwise.\n *\n * WHY THE REASONS. The server refuses the last active admin's demotion (`last_admin`),\n * your own admin role (`self`), Kurvenschmiede's CUSTOMER for an account that owns work,\n * kastlan's TENANT until a tenant portal exists (§4.1, §9.6). A choice the server will\n * refuse is shown as unavailable, with why, rather than offered and answered with an\n * error after a confirmation dialog — the 0.18 write-lock rule: a control that cannot\n * act says so where it is. `\"last_admin\"` and `\"self\"` are the kit's words in every\n * language; anything else is the app's own sentence.\n */\n\n/** A reason the kit words itself. `self_action` is the server's code for `self` (the\n * account error codes), so a refusal's code can be handed on as it came. */\nexport type RoleLockCode = \"last_admin\" | \"self\" | \"self_action\";\n\n/**\n * Why a role (or the whole control) cannot be changed: one of the kit's\n * {@link RoleLockCode}s, or the app's own words.\n */\nexport type RoleLock = RoleLockCode | (string & {}) | ReactNode;\n\n/** The `roleSelect` namespace — RoleSelect's and RolesEditor's words. */\nexport interface RoleSelectLabels {\n /** The select's name where no `label` is drawn, and RolesEditor's legend. \"Role\". */\n label: string;\n /** RolesEditor's legend. \"Roles\". */\n rolesLegend: string;\n /** The select's accessible name in a roster row — \"Role of Ada Example\". */\n roleOf: (name: string) => string;\n /** The whole control is locked: the account is the last active administrator. */\n lockedLastAdmin: string;\n /** The whole control is locked: it is the admin's own account. */\n lockedSelf: string;\n /** One option is unavailable for the last active administrator — said after the\n * role's name, inside the option. */\n notForLastAdmin: string;\n /** One option is unavailable on the admin's own account. */\n notForSelf: string;\n /** An unavailable option's text: the role's name and why. */\n unavailable: (role: string, reason: string) => string;\n}\n\n// Defined in ./role-select-labels, which holds no component code (0.34, KS U8).\nexport { DEFAULT_ROLE_SELECT_LABELS };\n\n/** The whole-control reason, the kit's codes in the kit's words. */\nfunction lockText(reason: RoleLock, labels: RoleSelectLabels): ReactNode {\n if (reason === \"last_admin\") return labels.lockedLastAdmin;\n if (reason === \"self\" || reason === \"self_action\") return labels.lockedSelf;\n return reason;\n}\n\n/** An option's reason as the text a native `<option>` can hold. */\nfunction optionReasonText(reason: string, labels: RoleSelectLabels): string {\n if (reason === \"last_admin\") return labels.notForLastAdmin;\n if (reason === \"self\" || reason === \"self_action\") return labels.notForSelf;\n return reason;\n}\n\n/** The vocabulary's keys, in its own order. */\nfunction keysOf<R extends string>(roles: RoleVocabulary<R>): R[] {\n return Object.keys(roles) as R[];\n}\n\n/* ── RoleSelect ─────────────────────────────────────────────────────────────── */\n\nexport interface RoleSelectProps<R extends string = string>\n extends Omit<SelectProps, \"value\" | \"defaultValue\" | \"onChange\" | \"children\" | \"multiple\" | \"disabledReason\"> {\n /** The role the server has. Controlled: a pick does not move the select until the\n * app's request lands and the row comes back with the new role. */\n value: R | null | undefined;\n /** The app's roles — what `RoleChip` reads. Their order is the list's. */\n roles: RoleVocabulary<R>;\n /** A role other than `value` was picked. The app asks `AdminActionConfirm` (an\n * `acknowledge` action, §4.2) and sends the change. */\n onChange: (role: R) => void;\n /**\n * The roles that may be CHOSEN here, in the vocabulary's order whatever order this is\n * in. Default: all of them. A role the account holds that is not offered (Kurvenschmiede's\n * REVIEWER, given only through the reviewer scope, §9.6) is still shown, unavailable:\n * a select that dropped it would show the account as something it is not.\n */\n offered?: readonly R[];\n /**\n * Why the whole choice is locked for this account: `\"last_admin\"`, `\"self\"`, or the\n * app's own words. The select stays focusable and says so (Select's `disabledReason`).\n */\n disabledReason?: RoleLock;\n /**\n * Why ONE role cannot be chosen for this account: `\"last_admin\"`, `\"self\"`, or the\n * app's own words (Kurvenschmiede: \"owns work\", for CUSTOMER) — a STRING, because a\n * native option holds text only. The option is disabled and reads \"Member (not for the\n * last administrator)\". `undefined` for an available role.\n */\n optionDisabledReason?: (role: R) => string | undefined;\n /** The account's name, for the select's accessible name in a roster row (\"Role of\n * Ada Example\") where no `label` is drawn. */\n name?: string;\n labels?: LabelOverride<RoleSelectLabels>;\n}\n\n/**\n * One role, picked from the app's vocabulary — Kurvenschmiede's roster `Select`\n * (users-panel.tsx), with the reasons it left to the server's toast drawn in place.\n *\n * Unlabelled by default, for a table cell: named \"Role of Ada Example\" (`name`) or\n * \"Role\". Pass `label` for a form field. Every {@link Select} prop passes through\n * (`size`, `commit`, `hint`, `error`, `data-*`).\n */\nexport function RoleSelect<R extends string = string>({\n value,\n roles,\n onChange,\n offered,\n disabledReason,\n optionDisabledReason,\n name,\n labels: labelsProp,\n label,\n ...rest\n}: RoleSelectProps<R>) {\n const labels = useKitLabels(\"roleSelect\", DEFAULT_ROLE_SELECT_LABELS, labelsProp);\n const all = keysOf(roles);\n const choosable = new Set<R>(offered ?? all);\n const held = value ?? null;\n // A cell has no room for a visible label: the select is named for the account it\n // belongs to, so fifty of them in a roster are not fifty \"Role\"s.\n const ariaLabel =\n label === undefined ? (rest[\"aria-label\"] ?? (name ? labels.roleOf(name) : labels.label)) : rest[\"aria-label\"];\n return (\n <Select\n {...rest}\n label={label}\n aria-label={ariaLabel}\n value={held ?? \"\"}\n disabledReason={hasContent(disabledReason) ? lockText(disabledReason, labels) : undefined}\n onChange={(event) => {\n const next = event.target.value as R;\n if (next && next !== held) onChange(next);\n }}\n >\n {held === null && <option value=\"\" disabled />}\n {all\n .filter((role) => choosable.has(role) || role === held)\n .map((role) => {\n const word = roles[role].label;\n const reason = role === held ? undefined : optionDisabledReason?.(role);\n const unavailable = !choosable.has(role) || hasContent(reason);\n return (\n <option key={role} value={role} disabled={unavailable && role !== held}>\n {reason ? labels.unavailable(word, optionReasonText(reason, labels)) : word}\n </option>\n );\n })}\n {/* A role the vocabulary does not know (an older client against a newer API) is\n still the account's role: shown as its key, as RoleChip shows it. */}\n {held !== null && !all.includes(held) && (\n <option value={held} disabled>\n {held}\n </option>\n )}\n </Select>\n );\n}\n\n/* ── RolesEditor ────────────────────────────────────────────────────────────── */\n\nexport interface RolesEditorProps<R extends string = string> extends FieldHelpProps {\n /** The roles ticked — the draft the app holds while its dialog is open. */\n value: readonly R[];\n roles: RoleVocabulary<R>;\n /** The new set, in the vocabulary's order (a role the editor does not offer, but the\n * account holds, is kept after the rest — CheckboxGroup's rule). */\n onChange: (roles: R[]) => void;\n /** The roles that may be ticked or unticked here. Default: all. kastlan leaves TENANT\n * out until a tenant portal exists (§4.1). */\n offered?: readonly R[];\n /** Why nothing can be changed: `\"last_admin\"`, `\"self\"` or the app's words. */\n disabledReason?: RoleLock;\n /** Why one role cannot be changed — shown under it, and the box keeps its state:\n * `\"last_admin\"` on the last administrator's ADMIN, say. */\n optionDisabledReason?: (role: R) => RoleLock | undefined;\n /** Default `roleSelect.rolesLegend` — \"Roles\". kastlan names the company: \"Roles in\n * Example Ltd\". */\n legend?: ReactNode;\n legendVisibility?: \"visible\" | \"sr-only\";\n /** At least one role (kastlan's dialog saves none). Draws the required star. */\n required?: boolean;\n hint?: ReactNode;\n error?: ReactNode;\n columns?: 1 | 2 | 3 | 4;\n /** The editor SAVES on change — the write lock's opt-in (CheckboxGroup's `commit`). */\n commit?: CommitScope;\n className?: string;\n labels?: LabelOverride<RoleSelectLabels>;\n}\n\n/**\n * Several roles at once — kastlan's manage-roles dialog (`ChoiceCardGroup multiple`),\n * which holds an account's roles in the CURRENT company (§4.1: `PUT /admin/users/{id}/roles`).\n * A kit {@link CheckboxGroup} of the vocabulary, with the reasons of {@link RoleSelect}:\n * a role that cannot change keeps its box as it is and says why under it.\n *\n * A field, not a form: the app's dialog holds the draft, and its Save goes through\n * `AdminActionConfirm` (`acknowledge`, §4.2) — which can draw this editor as its\n * `children`, so the roles and the tick are one dialog.\n */\nexport function RolesEditor<R extends string = string>({\n value,\n roles,\n onChange,\n offered,\n disabledReason,\n optionDisabledReason,\n legend,\n legendVisibility,\n required,\n hint,\n help,\n error,\n columns,\n commit,\n className,\n labels: labelsProp,\n}: RolesEditorProps<R>) {\n const labels = useKitLabels(\"roleSelect\", DEFAULT_ROLE_SELECT_LABELS, labelsProp);\n const all = keysOf(roles);\n const choosable = new Set<R>(offered ?? all);\n const held = new Set<R>(value);\n const options: CheckboxGroupOption<R>[] = all\n .filter((role) => choosable.has(role) || held.has(role))\n .map((role) => {\n const reason = optionDisabledReason?.(role);\n const locked = hasContent(reason);\n return {\n value: role,\n label: roles[role].label,\n hint: locked ? lockText(reason, labels) : undefined,\n disabled: locked || !choosable.has(role),\n };\n });\n return (\n <CheckboxGroup<R>\n legend={legend ?? labels.rolesLegend}\n legendVisibility={legendVisibility}\n options={options}\n value={[...value]}\n onChange={onChange}\n required={required}\n hint={hint}\n help={help}\n error={error}\n columns={columns}\n commit={commit}\n disabledReason={hasContent(disabledReason) ? lockText(disabledReason, labels) : undefined}\n className={className}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ComponentPropsWithRef } from "react";
|
|
2
2
|
import type { LabelOverride } from "../i18n/kit-labels.js";
|
|
3
3
|
import type { AlertSize, AlertTone } from "../components/alert-banner.js";
|
|
4
4
|
import type { BillingLabels } from "./billing-labels.js";
|
|
@@ -15,7 +15,10 @@ import type { BillingLabels } from "./billing-labels.js";
|
|
|
15
15
|
* - `processing` — back from checkout before the webhook landed (§12.21).
|
|
16
16
|
*/
|
|
17
17
|
export type BillingBannerKind = "trial-ending" | "grant-ending" | "payment-failed" | "plan-ended" | "guest" | "processing";
|
|
18
|
-
|
|
18
|
+
/** A `div`'s props, `ref` included since 0.35 (round 0.35 R4, the follow-up to API-2): they
|
|
19
|
+
* go on to the {@link AlertBanner}, so the ref is the banner's `<div>` — with an × too,
|
|
20
|
+
* since the banner has no `href` or `onClick` that would make its row a link or a button. */
|
|
21
|
+
interface BillingBannerBaseProps extends Omit<ComponentPropsWithRef<"div">, "children" | "onClick"> {
|
|
19
22
|
/**
|
|
20
23
|
* Over the kind's tone: `trial-ending` and `grant-ending` are `info` until the last
|
|
21
24
|
* three days and `warning` in them; `payment-failed` is `danger` (money did not
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/billing/billing-banner.tsx"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../src/billing/billing-banner.tsx"],"sourcesContent":["import type { ComponentPropsWithRef, ReactNode } from \"react\";\nimport { CreditCard, Hourglass, PencilOff } from \"lucide-react\";\n\nimport type { LabelOverride } from \"../i18n/kit-labels\";\nimport { AlertBanner } from \"../components/alert-banner\";\nimport type { AlertSize, AlertTone } from \"../components/alert-banner\";\nimport { Button } from \"../components/button\";\nimport { Spinner } from \"../components/spinner\";\nimport { useBillingLabels } from \"./billing-labels\";\nimport type { BillingLabels } from \"./billing-labels\";\n\n/**\n * The billing banners (docs/billing-harmonization.md §3.3, §7, §12.6, §12.21):\n *\n * - `trial-ending` — from 7 days before `trial_ends_at` (§3.3);\n * - `grant-ending` — from 7 days before `comped_until`: a beta user's 12 months, an\n * operator's grant;\n * - `payment-failed` — from the first failed payment (`past_due`), while the provider\n * retries;\n * - `plan-ended` — out of good standing: read-only, never locked (§2.3);\n * - `guest` — a guest in someone else's read-only item (§12.6);\n * - `processing` — back from checkout before the webhook landed (§12.21).\n */\nexport type BillingBannerKind =\n | \"trial-ending\"\n | \"grant-ending\"\n | \"payment-failed\"\n | \"plan-ended\"\n | \"guest\"\n | \"processing\";\n\n/** A `div`'s props, `ref` included since 0.35 (round 0.35 R4, the follow-up to API-2): they\n * go on to the {@link AlertBanner}, so the ref is the banner's `<div>` — with an × too,\n * since the banner has no `href` or `onClick` that would make its row a link or a button. */\ninterface BillingBannerBaseProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\" | \"onClick\"> {\n /**\n * Over the kind's tone: `trial-ending` and `grant-ending` are `info` until the last\n * three days and `warning` in them; `payment-failed` is `danger` (money did not\n * arrive — kastlan's past-due strip was red); `plan-ended` is `warning`, a state with\n * everything still there rather than an error; `guest` and `processing` are `info`.\n */\n tone?: AlertTone;\n /** `strip` (default): the band under the top bar, on every page. `box`: the same\n * message on the subscription page itself. */\n variant?: \"strip\" | \"box\";\n /** Default `sm` for a strip (the demo's banner), `md` for a box. */\n size?: AlertSize;\n /**\n * Where the action goes — the subscription page, say. The app's action, as an `href`\n * or as {@link onAction}; without either there is no button. Never a write-locked\n * commit: billing itself always works (§3.3).\n */\n actionHref?: string;\n /** What the action does — the app's portal call (`POST /billing/portal`, then off to\n * its `url`): for `payment-failed` with `{target: \"payment_method\"}`, the portal's\n * page for the card (§14.5); for `processing`, `useCheckoutProcessing`'s\n * `checkAgain`. The kit sends no request. */\n onAction?: () => void;\n /**\n * Over the kind's action words: \"Choose a plan\" (trial, grant, plan ended), \"Update\n * payment method\" (payment failed), \"Check again\" (processing). The guest banner has\n * none of its own: an action there needs this.\n */\n actionLabel?: string;\n /** The action is under way: the button's spinner, no second press. */\n actionPending?: boolean;\n /** An × that calls this; the app removes the banner and remembers that it did. */\n onDismiss?: () => void;\n dismissLabel?: string;\n /** Prop > `<UiKitProvider labels={{ billing }}>` > English. */\n labels?: LabelOverride<BillingLabels>;\n}\n\nexport type BillingBannerProps = BillingBannerBaseProps &\n (\n | {\n kind: \"trial-ending\" | \"grant-ending\";\n /** Calendar days left — `billingDaysLeft(trial_ends_at)`. 0 is today. */\n daysLeft: number;\n item?: never;\n }\n | {\n kind: \"guest\";\n /** The item's own name (\"Household 2026\"), or nothing. NEVER the owner's status:\n * the banner says \"for now\" and nothing more (§12.6). */\n item?: string;\n daysLeft?: never;\n }\n | {\n kind: \"payment-failed\" | \"plan-ended\" | \"processing\";\n daysLeft?: never;\n item?: never;\n }\n );\n\n/** The last days, in which an ending trial or grant turns from news into a warning. */\nconst LAST_DAYS = 3;\n\nfunction defaultTone(kind: BillingBannerKind, daysLeft: number | undefined): AlertTone {\n switch (kind) {\n case \"trial-ending\":\n case \"grant-ending\":\n return (daysLeft ?? 0) > LAST_DAYS ? \"info\" : \"warning\";\n case \"payment-failed\":\n return \"danger\";\n case \"plan-ended\":\n return \"warning\";\n default:\n return \"info\";\n }\n}\n\n/**\n * One of the billing banners, as a kit `AlertBanner` strip (§7): the kind's sentence, its\n * glyph and tone, and the app's action. Carries `data-billing-banner` with the kind.\n *\n * The app decides WHICH banner shows, from `GET /billing/overview` (and hides all of them\n * while billing is off, §4); the kit only says it. A guest's banner takes no status at\n * all — the type does not let one in — so the owner's payment state cannot leak into it\n * by a wrong prop (§12.6).\n *\n * `processing` is a live region (`role=\"status\"`): it appears when the person comes back\n * from checkout and goes when the overview catches up (§12.21), and a screen reader\n * should hear both. The others are page furniture, role-less as the strip is.\n */\nexport function BillingBanner(props: BillingBannerProps) {\n const {\n kind,\n daysLeft,\n item,\n tone,\n variant = \"strip\",\n size,\n actionHref,\n onAction,\n actionLabel,\n actionPending,\n onDismiss,\n dismissLabel,\n labels: labelsProp,\n role,\n ...rest\n } = props;\n const labels = useBillingLabels(labelsProp);\n const days = Math.max(0, Math.floor(daysLeft ?? 0));\n\n let text: string;\n let icon: ReactNode;\n let ownAction: string | undefined;\n switch (kind) {\n case \"trial-ending\":\n text = labels.trialEnding(days);\n icon = <Hourglass />;\n ownAction = labels.choosePlan;\n break;\n case \"grant-ending\":\n text = labels.grantEnding(days);\n icon = <Hourglass />;\n ownAction = labels.choosePlan;\n break;\n case \"payment-failed\":\n text = labels.paymentFailed;\n icon = <CreditCard />;\n ownAction = labels.updatePayment;\n break;\n case \"plan-ended\":\n text = labels.planEnded;\n icon = <PencilOff />;\n ownAction = labels.choosePlan;\n break;\n case \"guest\":\n text = labels.guestReadOnly(item);\n icon = <PencilOff />;\n ownAction = undefined;\n break;\n case \"processing\":\n text = labels.processing;\n icon = <Spinner label={null} />;\n ownAction = labels.checkAgain;\n break;\n }\n\n const words = actionLabel ?? ownAction;\n const action =\n words === undefined || (actionHref === undefined && onAction === undefined) ? undefined : actionHref !== undefined ? (\n <Button href={actionHref} variant=\"secondary\" size=\"sm\">\n {words}\n </Button>\n ) : (\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={onAction} pending={actionPending}>\n {words}\n </Button>\n );\n\n return (\n <AlertBanner\n {...rest}\n role={role ?? (kind === \"processing\" ? \"status\" : undefined)}\n variant={variant}\n size={size ?? (variant === \"strip\" ? \"sm\" : \"md\")}\n tone={tone ?? defaultTone(kind, days)}\n icon={icon}\n action={action}\n onDismiss={onDismiss}\n dismissLabel={dismissLabel}\n data-billing-banner={kind}\n >\n {text}\n </AlertBanner>\n );\n}\n"],"mappings":";AAwJa;AAvJb,SAAS,YAAY,WAAW,iBAAiB;AAGjD,SAAS,mBAAmB;AAE5B,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,wBAAwB;AAwFjC,MAAM,YAAY;AAElB,SAAS,YAAY,MAAyB,UAAyC;AACrF,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACH,cAAQ,YAAY,KAAK,YAAY,SAAS;AAAA,IAChD,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAeO,SAAS,cAAc,OAA2B;AACvD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AACJ,QAAM,SAAS,iBAAiB,UAAU;AAC1C,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,CAAC,CAAC;AAElD,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,OAAO,YAAY,IAAI;AAC9B,aAAO,oBAAC,aAAU;AAClB,kBAAY,OAAO;AACnB;AAAA,IACF,KAAK;AACH,aAAO,OAAO,YAAY,IAAI;AAC9B,aAAO,oBAAC,aAAU;AAClB,kBAAY,OAAO;AACnB;AAAA,IACF,KAAK;AACH,aAAO,OAAO;AACd,aAAO,oBAAC,cAAW;AACnB,kBAAY,OAAO;AACnB;AAAA,IACF,KAAK;AACH,aAAO,OAAO;AACd,aAAO,oBAAC,aAAU;AAClB,kBAAY,OAAO;AACnB;AAAA,IACF,KAAK;AACH,aAAO,OAAO,cAAc,IAAI;AAChC,aAAO,oBAAC,aAAU;AAClB,kBAAY;AACZ;AAAA,IACF,KAAK;AACH,aAAO,OAAO;AACd,aAAO,oBAAC,WAAQ,OAAO,MAAM;AAC7B,kBAAY,OAAO;AACnB;AAAA,EACJ;AAEA,QAAM,QAAQ,eAAe;AAC7B,QAAM,SACJ,UAAU,UAAc,eAAe,UAAa,aAAa,SAAa,SAAY,eAAe,SACvG,oBAAC,UAAO,MAAM,YAAY,SAAQ,aAAY,MAAK,MAChD,iBACH,IAEA,oBAAC,UAAO,MAAK,UAAS,SAAQ,aAAY,MAAK,MAAK,SAAS,UAAU,SAAS,eAC7E,iBACH;AAGJ,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,MAAM,SAAS,SAAS,eAAe,WAAW;AAAA,MAClD;AAAA,MACA,MAAM,SAAS,YAAY,UAAU,OAAO;AAAA,MAC5C,MAAM,QAAQ,YAAY,MAAM,IAAI;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,uBAAqB;AAAA,MAEpB;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ComponentPropsWithRef } from "react";
|
|
2
2
|
import type { LabelOverride } from "../i18n/kit-labels.js";
|
|
3
3
|
import type { AlertTone } from "../components/alert-banner.js";
|
|
4
4
|
import type { BillingLabels } from "./billing-labels.js";
|
|
5
5
|
/** The `contact` mode's mail: to support, its subject naming the dimension. */
|
|
6
6
|
export declare function planLimitMailto(email: string, subject: string): string;
|
|
7
|
-
|
|
7
|
+
/** A `div`'s props, `ref` included since 0.35 (round 0.35 R4, the follow-up to API-2): they
|
|
8
|
+
* go on to the {@link AlertBanner}, so the ref is the notice's `<div>` — its `href` is the
|
|
9
|
+
* action button's, never the banner's, so the frame is never a link. */
|
|
10
|
+
interface PlanLimitNoticeBaseProps extends Omit<ComponentPropsWithRef<"div">, "children" | "onClick"> {
|
|
8
11
|
/** The dimension as the refusal names it (`"budgets"`, `"seats"`) — `isPlanLimit(err)`'s
|
|
9
12
|
* `dimension`. Carried as `data-dimension`. */
|
|
10
13
|
dimension: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/billing/plan-limit-notice.tsx"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../src/billing/plan-limit-notice.tsx"],"sourcesContent":["import type { ComponentPropsWithRef } from \"react\";\n\nimport { useKitLocale } from \"../i18n/kit-labels\";\nimport type { LabelOverride } from \"../i18n/kit-labels\";\nimport { formatNumber } from \"../lib/format\";\nimport { AlertBanner } from \"../components/alert-banner\";\nimport type { AlertTone } from \"../components/alert-banner\";\nimport { ProgressBar } from \"../components/progress-bar\";\nimport { Button } from \"../components/button\";\nimport { useBillingLabels } from \"./billing-labels\";\nimport type { BillingLabels } from \"./billing-labels\";\n\n/** RFC 3986 percent-encoding, `!'()*` too — a mail client that splits on `'` is the one\n * that breaks \"Plan limit: Ada's plots\" (landing/access.ts keeps the same rule). */\nfunction encodeStrict(value: string): string {\n return encodeURIComponent(value).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);\n}\n\n/** The `contact` mode's mail: to support, its subject naming the dimension. */\nexport function planLimitMailto(email: string, subject: string): string {\n const to = encodeStrict(email).replace(/%40/g, \"@\");\n return `mailto:${to}?subject=${encodeStrict(subject)}`;\n}\n\n/** A `div`'s props, `ref` included since 0.35 (round 0.35 R4, the follow-up to API-2): they\n * go on to the {@link AlertBanner}, so the ref is the notice's `<div>` — its `href` is the\n * action button's, never the banner's, so the frame is never a link. */\ninterface PlanLimitNoticeBaseProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\" | \"onClick\"> {\n /** The dimension as the refusal names it (`\"budgets\"`, `\"seats\"`) — `isPlanLimit(err)`'s\n * `dimension`. Carried as `data-dimension`. */\n dimension: string;\n /** The app's name for it, in the reader's language: \"Budgets\". Default: the key. */\n dimensionLabel?: string;\n /** How many there are. Left out (keksdose's legacy `plan_budget_limit` body has no\n * `used`), it is read as `limit`: the create was refused for being at it. */\n used?: number;\n /** The plan's limit for the dimension. Left out — a body without one — the notice says\n * its words and draws no meter. */\n limit?: number;\n /** The payer's plan code, as `isPlanLimit` reads it — carried as `data-plan`, so the\n * refusal can be spread in whole: `<PlanLimitNotice {...isPlanLimit(err)} …/>`. */\n plan?: string;\n /** How a figure is written — kastlan's storage limit is bytes (`formatFileSize`).\n * Default: a number in the kit's locale. */\n formatValue?: (value: number) => string;\n /** Over the provider's locale, for the default figures. */\n locale?: string;\n /** Default `warning`. */\n tone?: AlertTone;\n /** Prop > `<UiKitProvider labels={{ billing }}>` > English. */\n labels?: LabelOverride<BillingLabels>;\n}\n\nexport type PlanLimitNoticeProps = PlanLimitNoticeBaseProps &\n (\n | {\n /** Plans are bought: \"Choose a plan\" → the app's subscription page. */\n mode: \"upgrade\";\n /** The subscription page. */\n href: string;\n email?: never;\n }\n | {\n /** The operator grants plans by hand (keksdose's today): \"Ask for more\" → a mail. */\n mode: \"contact\";\n /** The support address: `support@` the app's domain. */\n email: string;\n href?: never;\n }\n );\n\n/**\n * A create refused at the plan's limit (docs/billing-harmonization.md §3.4): \"Plan limit\n * reached\", what to do, the dimension's meter (\"Budgets — 3 of 3\") and the app's way to\n * more — `upgrade`, a link to the subscription page, or `contact`, a mail to support.\n *\n * A limit gates CREATION only: a downgrade never deletes or hides what is over the new\n * limit (§3.4), so `used` may be past `limit`; the meter then fills and turns red. Feed it\n * the refusal: `const hit = isPlanLimit(err); hit && <PlanLimitNotice {...hit} …/>`. The\n * kit sends nothing — the mail opens the reader's own client.\n */\nexport function PlanLimitNotice(props: PlanLimitNoticeProps) {\n const {\n dimension,\n dimensionLabel,\n used: usedProp,\n limit,\n plan,\n formatValue,\n locale: localeProp,\n tone = \"warning\",\n labels: labelsProp,\n mode,\n href,\n email,\n className,\n ...rest\n } = props;\n const labels = useBillingLabels(labelsProp);\n const locale = useKitLocale(localeProp);\n const used = usedProp ?? limit ?? 0;\n const name = dimensionLabel ?? dimension;\n const figure = (value: number) => (formatValue ? formatValue(value) : formatNumber(value, { locale }));\n\n const action =\n mode === \"upgrade\" ? (\n <Button href={href} variant=\"secondary\" size=\"sm\">\n {labels.choosePlan}\n </Button>\n ) : (\n <Button href={planLimitMailto(email, labels.contactSubject(name))} variant=\"secondary\" size=\"sm\">\n {labels.askForMore}\n </Button>\n );\n\n return (\n <AlertBanner\n {...rest}\n tone={tone}\n action={action}\n data-plan-limit-mode={mode}\n data-dimension={dimension}\n data-plan={plan}\n className={className}\n >\n <span className=\"block font-medium\">{labels.limitReached}</span>\n <span className=\"block\">{mode === \"upgrade\" ? labels.limitUpgrade : labels.limitContact}</span>\n {limit !== undefined && (\n <ProgressBar\n as=\"span\"\n variant=\"meter\"\n size=\"slim\"\n value={used}\n max={limit}\n label={name}\n showValue\n // The bar is clamped at `max` and hands its formatter the clamped value; the\n // figures are the real ones, so \"5 of 3\" after a downgrade says what the bar\n // cannot draw.\n formatValue={() => labels.usage(figure(used), figure(limit))}\n tone={used > limit ? \"danger\" : \"warning\"}\n className=\"mt-2\"\n locale={locale}\n />\n )}\n </AlertBanner>\n );\n}\n"],"mappings":";AA0GM,cAUF,YAVE;AAxGN,SAAS,oBAAoB;AAE7B,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAC5B,SAAS,cAAc;AACvB,SAAS,wBAAwB;AAKjC,SAAS,aAAa,OAAuB;AAC3C,SAAO,mBAAmB,KAAK,EAAE,QAAQ,YAAY,CAAC,MAAM,IAAI,EAAE,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,YAAY,CAAC,EAAE;AAC9G;AAGO,SAAS,gBAAgB,OAAe,SAAyB;AACtE,QAAM,KAAK,aAAa,KAAK,EAAE,QAAQ,QAAQ,GAAG;AAClD,SAAO,UAAU,EAAE,YAAY,aAAa,OAAO,CAAC;AACtD;AA2DO,SAAS,gBAAgB,OAA6B;AAC3D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AACJ,QAAM,SAAS,iBAAiB,UAAU;AAC1C,QAAM,SAAS,aAAa,UAAU;AACtC,QAAM,OAAO,YAAY,SAAS;AAClC,QAAM,OAAO,kBAAkB;AAC/B,QAAM,SAAS,CAAC,UAAmB,cAAc,YAAY,KAAK,IAAI,aAAa,OAAO,EAAE,OAAO,CAAC;AAEpG,QAAM,SACJ,SAAS,YACP,oBAAC,UAAO,MAAY,SAAQ,aAAY,MAAK,MAC1C,iBAAO,YACV,IAEA,oBAAC,UAAO,MAAM,gBAAgB,OAAO,OAAO,eAAe,IAAI,CAAC,GAAG,SAAQ,aAAY,MAAK,MACzF,iBAAO,YACV;AAGJ,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA;AAAA,MACA,wBAAsB;AAAA,MACtB,kBAAgB;AAAA,MAChB,aAAW;AAAA,MACX;AAAA,MAEA;AAAA,4BAAC,UAAK,WAAU,qBAAqB,iBAAO,cAAa;AAAA,QACzD,oBAAC,UAAK,WAAU,SAAS,mBAAS,YAAY,OAAO,eAAe,OAAO,cAAa;AAAA,QACvF,UAAU,UACT;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,OAAO;AAAA,YACP,KAAK;AAAA,YACL,OAAO;AAAA,YACP,WAAS;AAAA,YAIT,aAAa,MAAM,OAAO,MAAM,OAAO,IAAI,GAAG,OAAO,KAAK,CAAC;AAAA,YAC3D,MAAM,OAAO,QAAQ,WAAW;AAAA,YAChC,WAAU;AAAA,YACV;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":[]}
|
package/dist/chart.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/chart.ts"],"sourcesContent":["// `@eifi1/ui-kit/chart` — the chart shell and its colour system.\n//\n// A re-slicing of what the main barrel already exports, not a new API. It exists so a\n// consumer can reach the chart kit WITHOUT the barrel: `import(\"@eifi1/ui-kit/chart\")`\n// is a 31KB chunk, where the same lazy import through the barrel pulls 221KB, because\n// a dynamic import of the barrel cannot be tree-shaken down to one of its members.\n//\n// It is about chunk size, not about the peer: `recharts` is a REQUIRED peer (since 0.5.0),\n// because the main barrel re-exports everything here too, so `import { Button } from\n// \"@eifi1/ui-kit\"` reaches recharts as well (packaging-contract.test.ts asserts it).\nexport * from \"./components/chart\";\nexport * from \"./theme/chart-palette\";\n\n// The tile chart (treemap) the apps share — moved here from keksdose so every consumer\n// derives it from the package rather than from a copy.\nexport * from \"./components/treemap\";\n\n// lenkbank's zoomable series chart, its synced x-zoom, the toggle legend and the\n// mirrored-pair axis geometry — moved here so the apps derive them from the package.\nexport * from \"./components/series-chart\";\n// 0.32.1 (keksdose's 0.32 report): the height every chart takes, for an app's wrappers.\nexport type { ChartHeight } from \"./components/chart-height\";\nexport * from \"./components/chart-zoom\";\n// The
|
|
1
|
+
{"version":3,"sources":["../src/chart.ts"],"sourcesContent":["// `@eifi1/ui-kit/chart` — the chart shell and its colour system.\n//\n// A re-slicing of what the main barrel already exports, not a new API. It exists so a\n// consumer can reach the chart kit WITHOUT the barrel: `import(\"@eifi1/ui-kit/chart\")`\n// is a 31KB chunk, where the same lazy import through the barrel pulls 221KB, because\n// a dynamic import of the barrel cannot be tree-shaken down to one of its members.\n//\n// It is about chunk size, not about the peer: `recharts` is a REQUIRED peer (since 0.5.0),\n// because the main barrel re-exports everything here too, so `import { Button } from\n// \"@eifi1/ui-kit\"` reaches recharts as well (packaging-contract.test.ts asserts it).\nexport * from \"./components/chart\";\nexport * from \"./theme/chart-palette\";\n\n// The tile chart (treemap) the apps share — moved here from keksdose so every consumer\n// derives it from the package rather than from a copy.\nexport * from \"./components/treemap\";\n\n// lenkbank's zoomable series chart, its synced x-zoom, the toggle legend and the\n// mirrored-pair axis geometry — moved here so the apps derive them from the package.\nexport * from \"./components/series-chart\";\n// 0.32.1 (keksdose's 0.32 report): the height every chart takes, for an app's wrappers.\nexport type { ChartHeight } from \"./components/chart-height\";\n// SharedXZoom and the zoom's types: the public face of ./chart-zoom-core, whose arithmetic\n// stays the kit's (refactor audit 2026-10, API-6b; off the surface in 0.35).\nexport * from \"./components/chart-zoom\";\n// The same binding, named from the module that holds it and the drag layer (recharts): the\n// packaging contract reads this entry's own imports to know which modules may import\n// recharts, so chart-zoom-core has to be one of them (MOD-6).\nexport { SharedXZoom } from \"./components/chart-zoom-core\";\nexport * from \"./components/toggle-legend\";\nexport * from \"./components/facing-pair\";\nexport * from \"./components/series-chart-labels\";\n\n// The part-to-whole chart (donut / pie) — moved here from kastlan's dashboard and reports.\nexport * from \"./components/pie-chart\";\nexport * from \"./components/pie-chart-labels\";\n"],"mappings":";AAUA,cAAc;AACd,cAAc;AAId,cAAc;AAId,cAAc;AAKd,cAAc;AAId,SAAS,mBAAmB;AAC5B,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;","names":[]}
|