@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
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
// A type-only import: erased at build time, so this module stays free of the table
|
|
7
7
|
// itself (and of react-router), which `i18n/defaults` relies on.
|
|
8
8
|
import type { DataTableSortLabels } from "./data-table";
|
|
9
|
-
import type { LabelOverride } from "../i18n/kit-labels";
|
|
10
9
|
|
|
11
10
|
/** The phone sort control's four keys (`sortBy`, `sortDefault`, `sortAscending`,
|
|
12
11
|
* `sortDescending`, 0.22.0) are {@link DataTableSortLabels}', declared beside the
|
|
@@ -89,7 +88,7 @@ export interface DataTableLabels extends DataTableSortLabels {
|
|
|
89
88
|
* A column's filter button and panel: "Filter Amount", and "Filter Amount (active)"
|
|
90
89
|
* while the column is filtered (round 0.34 Wave 2, BUG-7c). Every column's used to be
|
|
91
90
|
* "Filter" alike, and "filtered" was a colour. An app that translated only `filter`
|
|
92
|
-
* gets `"<filter>: <column>"` from it
|
|
91
|
+
* gets `"<filter>: <column>"` from it: DataTable derives the one from the other.
|
|
93
92
|
*/
|
|
94
93
|
filterColumn: (column: string, active: boolean) => string;
|
|
95
94
|
|
|
@@ -171,90 +170,9 @@ export const DEFAULT_DATA_TABLE_LABELS: DataTableLabels = {
|
|
|
171
170
|
// The phone sort control (0.22.0). The same words as `DEFAULT_DATA_TABLE_SORT_LABELS`
|
|
172
171
|
// in data-table.tsx, written out rather than spread in: importing that VALUE here
|
|
173
172
|
// would make data-table.tsx and this module import each other (data-table.tsx reads
|
|
174
|
-
//
|
|
173
|
+
// these defaults from here), and would pull the whole table into `i18n/defaults`.
|
|
175
174
|
sortBy: "Sort by",
|
|
176
175
|
sortDefault: "Default order",
|
|
177
176
|
sortAscending: "Ascending",
|
|
178
177
|
sortDescending: "Descending",
|
|
179
178
|
};
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Merge caller overrides onto the English defaults (presets merged too, key by key, as
|
|
183
|
-
* the provider merges them — so the parameter is a {@link LabelOverride}).
|
|
184
|
-
*
|
|
185
|
-
* The parameter is lenient on purpose — a table with no labels at all still
|
|
186
|
-
* renders — but that is also how a translated app ends up half English and never
|
|
187
|
-
* hears about it: lenkbank ships nineteen of these keys in English in a German UI
|
|
188
|
-
* today, because every one of them is backfilled silently. The kit will not start
|
|
189
|
-
* throwing over it (three apps depend on the lenient merge), so
|
|
190
|
-
* {@link missingDataTableLabels} is the other half: it answers which keys fell back,
|
|
191
|
-
* and an app asserts on that in its OWN test, where the answer is actionable.
|
|
192
|
-
*
|
|
193
|
-
* @deprecated 0.34 — pass `labels` to DataTable, or the provider's `dataTable`, which this
|
|
194
|
-
* merge serves; removed in 0.35 from the public surface, where DataTable keeps it as its
|
|
195
|
-
* own (refactor audit 2026-10, API-6a). One app test calls it.
|
|
196
|
-
*/
|
|
197
|
-
export function resolveDataTableLabels(partial?: LabelOverride<DataTableLabels>): DataTableLabels {
|
|
198
|
-
if (!partial) return DEFAULT_DATA_TABLE_LABELS;
|
|
199
|
-
// An `undefined` preset is skipped, as the provider skips it, rather than blanking one.
|
|
200
|
-
const presets = { ...DEFAULT_DATA_TABLE_LABELS.presets };
|
|
201
|
-
for (const [key, text] of Object.entries(partial.presets ?? {})) if (text !== undefined) presets[key] = text;
|
|
202
|
-
const merged: DataTableLabels = { ...DEFAULT_DATA_TABLE_LABELS, ...partial, presets };
|
|
203
|
-
// `columnsCount` was split out of `columns` + a template literal. Consumers have
|
|
204
|
-
// been translating `columns` since 0.1, and backfilling the English default over
|
|
205
|
-
// that would hand them "Columns (4/9)" back for having translated the key that
|
|
206
|
-
// existed at the time — the same silent-English failure the audit records against
|
|
207
|
-
// this file. So the count is derived from the RESOLVED `columns` unless the caller
|
|
208
|
-
// states the whole sentence, which is the escape hatch for a language where the
|
|
209
|
-
// parenthetical does not fit.
|
|
210
|
-
if (partial.columns !== undefined && partial.columnsCount === undefined) {
|
|
211
|
-
merged.columnsCount = (visible, total) => `${merged.columns} (${visible}/${total})`;
|
|
212
|
-
}
|
|
213
|
-
// The same for `filterColumn` (0.34), from a translated `filter`: the app's own word
|
|
214
|
-
// with the column, rather than English for having translated the key that existed.
|
|
215
|
-
if (partial.filter !== undefined && partial.filterColumn === undefined) {
|
|
216
|
-
merged.filterColumn = (column) => `${merged.filter}: ${column}`;
|
|
217
|
-
}
|
|
218
|
-
return merged;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* The label keys `labels` does not supply, and which therefore come back English
|
|
223
|
-
* from {@link resolveDataTableLabels}.
|
|
224
|
-
*
|
|
225
|
-
* For a consumer's own test:
|
|
226
|
-
*
|
|
227
|
-
* ```ts
|
|
228
|
-
* expect(missingDataTableLabels(de.dataTable)).toEqual([]);
|
|
229
|
-
* ```
|
|
230
|
-
*
|
|
231
|
-
* which fails the day the kit adds a key — which is the point. Adding a label is
|
|
232
|
-
* additive here and a silent regression in a translated app, and nothing else in
|
|
233
|
-
* either repository can tell the two apart.
|
|
234
|
-
*
|
|
235
|
-
* Preset labels are reported one at a time (`presets.yesterday`), because `presets`
|
|
236
|
-
* is a `Record` merged key by key: answering `"presets"` would say nothing about
|
|
237
|
-
* which of the eleven are still English.
|
|
238
|
-
*
|
|
239
|
-
* @deprecated 0.34 — `missingKitLabels(labels, DEFAULT_UI_KIT_LABELS)`, which checks every
|
|
240
|
-
* namespace, the table's among them, and which all three apps' tests already call;
|
|
241
|
-
* removed in 0.35 (refactor audit 2026-10, API-6a).
|
|
242
|
-
*/
|
|
243
|
-
export function missingDataTableLabels(labels?: Partial<DataTableLabels>): string[] {
|
|
244
|
-
const missing: string[] = [];
|
|
245
|
-
for (const key of Object.keys(DEFAULT_DATA_TABLE_LABELS) as Array<keyof DataTableLabels>) {
|
|
246
|
-
if (key === "presets") continue;
|
|
247
|
-
if (labels?.[key] !== undefined) continue;
|
|
248
|
-
// `columnsCount` is DERIVED from a translated `columns` by the resolver above,
|
|
249
|
-
// so a caller who set that one is not leaking English here. Reporting it would
|
|
250
|
-
// send them to translate a key they have already covered, and an `toEqual([])`
|
|
251
|
-
// assertion built on this would never go green.
|
|
252
|
-
if (key === "columnsCount" && labels?.columns !== undefined) continue;
|
|
253
|
-
if (key === "filterColumn" && labels?.filter !== undefined) continue;
|
|
254
|
-
missing.push(key);
|
|
255
|
-
}
|
|
256
|
-
for (const preset of Object.keys(DEFAULT_DATA_TABLE_LABELS.presets)) {
|
|
257
|
-
if (labels?.presets?.[preset] === undefined) missing.push(`presets.${preset}`);
|
|
258
|
-
}
|
|
259
|
-
return missing;
|
|
260
|
-
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import { ROW_ACTIONS_KEY } from "./data-table-row-actions";
|
|
3
|
-
import type
|
|
3
|
+
import { DEFAULT_DATA_TABLE_LABELS, type DataTableLabels } from "./data-table-labels";
|
|
4
4
|
import type { DataTableCellProps, DataTableColumn, DataTableHeadProps } from "./data-table";
|
|
5
|
+
import type { LabelOverride } from "../i18n/kit-labels";
|
|
5
6
|
|
|
6
7
|
// What DataTable shares with its header (data-table-head.tsx), its column panel and its
|
|
7
8
|
// phone layout (data-table-mobile.tsx): the cell-attribute and alignment rules, a
|
|
8
9
|
// column's plain-text name, and the row link. Moved out of data-table.tsx unchanged
|
|
9
10
|
// (refactor audit 2026-10, MOD-3), into a module of their own so none of those has to
|
|
10
|
-
// import data-table.tsx at run time — which imports them.
|
|
11
|
+
// import data-table.tsx at run time — which imports them. Since 0.35 also the table's
|
|
12
|
+
// label resolver, which DataTable and its FilterPopover share and the barrel no longer
|
|
13
|
+
// exports (round 0.35 R1).
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
16
|
* Split a caller's cell attributes into what may reach the element and what the kit
|
|
@@ -80,6 +83,56 @@ export function columnLabel<T>(col: DataTableColumn<T>, labels?: DataTableLabels
|
|
|
80
83
|
return col.headerText ?? (typeof col.header === "string" ? col.header : col.key);
|
|
81
84
|
}
|
|
82
85
|
|
|
86
|
+
/**
|
|
87
|
+
* The table's labels: caller overrides merged onto the English defaults (presets merged
|
|
88
|
+
* too, key by key, as the provider merges them — so the parameter is a
|
|
89
|
+
* {@link LabelOverride}).
|
|
90
|
+
*
|
|
91
|
+
* DataTable's own, and FilterPopover's: public until 0.35, when it left the barrel for
|
|
92
|
+
* DataTable's `labels` and the provider's `dataTable`, which it serves (round 0.35 R1,
|
|
93
|
+
* refactor audit 2026-10 API-6a). It stays a resolver rather than `useKitLabels` for the
|
|
94
|
+
* two keys it derives (`columnsCount`, `filterColumn`), which a plain merge would not.
|
|
95
|
+
*
|
|
96
|
+
* Lenient on purpose — a table with no labels at all still renders — so a translated app
|
|
97
|
+
* finds out what fell back to English from `missingKitLabels(labels,
|
|
98
|
+
* DEFAULT_UI_KIT_LABELS)` in its own test, where the answer is actionable.
|
|
99
|
+
*/
|
|
100
|
+
export function resolveDataTableLabels(
|
|
101
|
+
...layers: (LabelOverride<DataTableLabels> | undefined)[]
|
|
102
|
+
): DataTableLabels {
|
|
103
|
+
if (!layers.some(Boolean)) return DEFAULT_DATA_TABLE_LABELS;
|
|
104
|
+
// The layers in order, the provider's then the prop's, later winning key by key. An
|
|
105
|
+
// `undefined` key is skipped, as `useKitLabels` skips it, rather than blanking the word
|
|
106
|
+
// under it: DataTable spread `{ ...provider, ...prop }`, so `labels={{ autoSize:
|
|
107
|
+
// undefined }}` blanked the provider's word and the English one (round 0.35). `presets`
|
|
108
|
+
// is a record and is merged the same way, so renaming one keeps the other ten.
|
|
109
|
+
const partial: Partial<Omit<DataTableLabels, "presets">> = {};
|
|
110
|
+
const presets = { ...DEFAULT_DATA_TABLE_LABELS.presets };
|
|
111
|
+
for (const layer of layers) {
|
|
112
|
+
for (const [key, value] of Object.entries(layer ?? {})) {
|
|
113
|
+
if (value === undefined) continue;
|
|
114
|
+
if (key !== "presets") Object.assign(partial, { [key]: value });
|
|
115
|
+
else for (const [preset, text] of Object.entries(value)) if (text !== undefined) presets[preset] = text;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const merged: DataTableLabels = { ...DEFAULT_DATA_TABLE_LABELS, ...partial, presets };
|
|
119
|
+
// `columnsCount` was split out of `columns` + a template literal. Consumers have
|
|
120
|
+
// been translating `columns` since 0.1, and backfilling the English default over
|
|
121
|
+
// that would hand them "Columns (4/9)" back for having translated the key that
|
|
122
|
+
// existed at the time. So the count is derived from the RESOLVED `columns` unless the
|
|
123
|
+
// caller states the whole sentence, which is the escape hatch for a language where
|
|
124
|
+
// the parenthetical does not fit.
|
|
125
|
+
if (partial.columns !== undefined && partial.columnsCount === undefined) {
|
|
126
|
+
merged.columnsCount = (visible, total) => `${merged.columns} (${visible}/${total})`;
|
|
127
|
+
}
|
|
128
|
+
// The same for `filterColumn` (0.34), from a translated `filter`: the app's own word
|
|
129
|
+
// with the column, rather than English for having translated the key that existed.
|
|
130
|
+
if (partial.filter !== undefined && partial.filterColumn === undefined) {
|
|
131
|
+
merged.filterColumn = (column) => `${merged.filter}: ${column}`;
|
|
132
|
+
}
|
|
133
|
+
return merged;
|
|
134
|
+
}
|
|
135
|
+
|
|
83
136
|
/**
|
|
84
137
|
* Whether a click that reached `row`'s handler did not start in the row's own DOM.
|
|
85
138
|
*
|
|
@@ -5,7 +5,15 @@ import { Spinner } from "./spinner";
|
|
|
5
5
|
import { ROW_ACTIONS_KEY, useRowActionColumn } from "./data-table-row-actions";
|
|
6
6
|
import { useColumnResize } from "./data-table-resize";
|
|
7
7
|
import { useRangeSelection } from "./data-table-selection";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
RowLink,
|
|
10
|
+
cleanAttrs,
|
|
11
|
+
columnLabel,
|
|
12
|
+
fromOutside,
|
|
13
|
+
logicalAlign,
|
|
14
|
+
resolveDataTableLabels,
|
|
15
|
+
splitCellProps,
|
|
16
|
+
} from "./data-table-shared";
|
|
9
17
|
import { MobileFilters, MobileRow, MobileSort, StackedFields } from "./data-table-mobile";
|
|
10
18
|
import { DataTableHead } from "./data-table-head";
|
|
11
19
|
import { ColumnSettingsPanel } from "./data-table-column-settings";
|
|
@@ -20,7 +28,7 @@ import type { SwipeAction } from "./swipeable-row";
|
|
|
20
28
|
import { FullBleedDialog } from "./full-bleed-dialog";
|
|
21
29
|
import { usePhoneLayout } from "../hooks/use-breakpoint";
|
|
22
30
|
import { useAnnounce } from "../hooks/use-announce";
|
|
23
|
-
import { DEFAULT_DATA_TABLE_LABELS,
|
|
31
|
+
import { DEFAULT_DATA_TABLE_LABELS, type DataTableLabels } from "./data-table-labels";
|
|
24
32
|
import { useKitLabelOverrides, useKitLocale, useKitTableStorageKeyPrefix, type LabelOverride } from "../i18n/kit-labels";
|
|
25
33
|
import { useEdgeFade } from "../lib/strip-fade";
|
|
26
34
|
import { dirOf, type Direction } from "../lib/direction";
|
|
@@ -294,6 +302,16 @@ export interface DataTableProps<T> {
|
|
|
294
302
|
onFiltersChange?: (next: FilterState) => void;
|
|
295
303
|
sorts?: SortState[];
|
|
296
304
|
onSortsChange?: (next: SortState[]) => void;
|
|
305
|
+
/**
|
|
306
|
+
* Controlled page size, as `sorts` above: the table pages by it and hands its pager's
|
|
307
|
+
* choice to `onPageSizeChange` (`Infinity` is "All"). For tables that page ALIKE —
|
|
308
|
+
* `TranslationReviewPanel`'s groups share one page size as they share one sort
|
|
309
|
+
* (0.35). Left out, the table keeps its own, from `defaultPageSize`, the URL and
|
|
310
|
+
* `storageKey`. A change of value sends a client-side table back to page 1. In
|
|
311
|
+
* `serverPagination` mode the page size is `serverPagination.pageSize`.
|
|
312
|
+
*/
|
|
313
|
+
pageSize?: number;
|
|
314
|
+
onPageSizeChange?: (pageSize: number) => void;
|
|
297
315
|
/**
|
|
298
316
|
* Opt-in multi-row selection (desktop table only). When provided, a leading
|
|
299
317
|
* checkbox column is rendered with a select-all box in the header; the owner
|
|
@@ -556,7 +574,7 @@ export interface DataTableProps<T> {
|
|
|
556
574
|
* On a phone it heads the summary card, which is also named by it.
|
|
557
575
|
*
|
|
558
576
|
* There is no built-in default word: a new kit label key is a silent English string
|
|
559
|
-
* in every translated app (see `
|
|
577
|
+
* in every translated app (see `missingKitLabels`), and the caller has the
|
|
560
578
|
* word in its own catalogue already. Without it the row is unlabelled on screen —
|
|
561
579
|
* pass one.
|
|
562
580
|
*/
|
|
@@ -728,6 +746,8 @@ export function DataTable<T>({
|
|
|
728
746
|
onFiltersChange,
|
|
729
747
|
sorts: sortsProp,
|
|
730
748
|
onSortsChange,
|
|
749
|
+
pageSize: pageSizeProp,
|
|
750
|
+
onPageSizeChange,
|
|
731
751
|
selection,
|
|
732
752
|
labels: labelsProp,
|
|
733
753
|
locale: localeProp,
|
|
@@ -775,19 +795,7 @@ export function DataTable<T>({
|
|
|
775
795
|
// prop to, `TranslationReviewPanel`'s among them.
|
|
776
796
|
const providerStorageKeyPrefix = useKitTableStorageKeyPrefix();
|
|
777
797
|
const storageKeyPrefix = storageKeyPrefixProp ?? providerStorageKeyPrefix ?? DEFAULT_PERSIST_PREFIX;
|
|
778
|
-
const labels = useMemo(
|
|
779
|
-
() =>
|
|
780
|
-
resolveDataTableLabels(
|
|
781
|
-
labelOverrides || labelsProp
|
|
782
|
-
? {
|
|
783
|
-
...labelOverrides,
|
|
784
|
-
...labelsProp,
|
|
785
|
-
presets: { ...labelOverrides?.presets, ...labelsProp?.presets },
|
|
786
|
-
}
|
|
787
|
-
: undefined,
|
|
788
|
-
),
|
|
789
|
-
[labelOverrides, labelsProp],
|
|
790
|
-
);
|
|
798
|
+
const labels = useMemo(() => resolveDataTableLabels(labelOverrides, labelsProp), [labelOverrides, labelsProp]);
|
|
791
799
|
const locale = useKitLocale(localeProp);
|
|
792
800
|
|
|
793
801
|
// ---- Row actions ---- (data-table-row-actions.tsx)
|
|
@@ -830,6 +838,8 @@ export function DataTable<T>({
|
|
|
830
838
|
defaultPageSize,
|
|
831
839
|
sortsProp,
|
|
832
840
|
filtersProp,
|
|
841
|
+
// Ignored in `serverPagination` mode, where the owner's is the page size.
|
|
842
|
+
pageSizeProp: isServer ? undefined : pageSizeProp,
|
|
833
843
|
});
|
|
834
844
|
|
|
835
845
|
// With the controls that change them switched off, persisted widths and hidden
|
|
@@ -1841,7 +1851,9 @@ export function DataTable<T>({
|
|
|
1841
1851
|
isServer
|
|
1842
1852
|
? serverPagination!.onPageSizeChange
|
|
1843
1853
|
: (n) => {
|
|
1844
|
-
|
|
1854
|
+
// To the owner when it holds the page size, as `commitSorts` does.
|
|
1855
|
+
if (onPageSizeChange) onPageSizeChange(n);
|
|
1856
|
+
else setPageSize(n);
|
|
1845
1857
|
setPage(0);
|
|
1846
1858
|
}
|
|
1847
1859
|
}
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import { splitTriggerAria } from "./trigger-aria";
|
|
20
20
|
import type { TriggerAria } from "./trigger-aria";
|
|
21
21
|
import { FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID } from "./field-base";
|
|
22
|
-
import { assignRef, FieldLabelLine, LABEL_ABOVE_BOX } from "./field-parts";
|
|
22
|
+
import { assignRef, FieldLabelLine, LABEL_ABOVE_BOX, type FieldHelpProps } from "./field-parts";
|
|
23
23
|
import { FullBleedDialog } from "./full-bleed-dialog";
|
|
24
24
|
import type { RemLength } from "../hooks/use-breakpoint";
|
|
25
25
|
import type { MiniCalendarProps } from "./mini-calendar";
|
|
@@ -34,7 +34,7 @@ import { Popover } from "./popover";
|
|
|
34
34
|
* `FormEvent`, while both pickers answer with ISO date strings. Each declares its own
|
|
35
35
|
* (date-picker.tsx, date-range-picker.tsx).
|
|
36
36
|
*/
|
|
37
|
-
export interface DatePickerBaseProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange"
|
|
37
|
+
export interface DatePickerBaseProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange">, FieldHelpProps {
|
|
38
38
|
/** BCP 47 tag for the trigger's date and the calendar. Falls back to
|
|
39
39
|
* `<UiKitProvider locale>`, then to the runtime's default. */
|
|
40
40
|
locale?: string;
|
|
@@ -170,6 +170,7 @@ export function DatePicker(props: DatePickerProps) {
|
|
|
170
170
|
disabled,
|
|
171
171
|
invalid,
|
|
172
172
|
hint,
|
|
173
|
+
help,
|
|
173
174
|
error,
|
|
174
175
|
// Named so it reaches the field (and so its trigger) when a step/today row is the
|
|
175
176
|
// root and takes the rest of the caller's props.
|
|
@@ -185,6 +186,8 @@ export function DatePicker(props: DatePickerProps) {
|
|
|
185
186
|
// (the element a screen reader is on) after any description of the caller's own.
|
|
186
187
|
const messages = useFieldMessages({
|
|
187
188
|
hint,
|
|
189
|
+
help,
|
|
190
|
+
name: label ?? rest["aria-label"],
|
|
188
191
|
error,
|
|
189
192
|
invalid,
|
|
190
193
|
describedBy: rest["aria-describedby"],
|
|
@@ -394,6 +394,7 @@ export function DateRangePicker(props: DateRangePickerProps) {
|
|
|
394
394
|
disabled,
|
|
395
395
|
invalid,
|
|
396
396
|
hint,
|
|
397
|
+
help,
|
|
397
398
|
error,
|
|
398
399
|
// The trigger's (API-3).
|
|
399
400
|
ref,
|
|
@@ -404,6 +405,8 @@ export function DateRangePicker(props: DateRangePickerProps) {
|
|
|
404
405
|
const render = useTriggerFormat("dateRangePicker", locale, formatOptions, formatValue);
|
|
405
406
|
const messages = useFieldMessages({
|
|
406
407
|
hint,
|
|
408
|
+
help,
|
|
409
|
+
name: label ?? rest["aria-label"],
|
|
407
410
|
error,
|
|
408
411
|
invalid,
|
|
409
412
|
describedBy: rest["aria-describedby"],
|
|
@@ -23,7 +23,9 @@ export { DEFAULT_DIALOG_FRAME_LABELS };
|
|
|
23
23
|
* (`children` is the body here, not the whole panel) and `title`, which is the dialog's
|
|
24
24
|
* HEADING and a ReactNode rather than the browser's tooltip string — the collision
|
|
25
25
|
* `PickerSheet` met first. Everything else, `size`, `draggable`, `fullBleed`,
|
|
26
|
-
* `onKeyDown`, a `data-tour` anchor, still reaches the `Modal
|
|
26
|
+
* `onKeyDown`, a `data-tour` anchor, still reaches the `Modal` — and since 0.35 `ref`
|
|
27
|
+
* (round 0.35 R4): the panel, the `role="dialog"` element the frame's header, body and
|
|
28
|
+
* actions sit in.
|
|
27
29
|
*/
|
|
28
30
|
export interface DialogFrameProps extends Omit<ModalProps, "labelledBy" | "children" | "title"> {
|
|
29
31
|
/** The heading, and therefore the dialog's accessible name (`aria-labelledby`). */
|
|
@@ -11,6 +11,7 @@ import { createPortal } from "react-dom";
|
|
|
11
11
|
import { Search } from "lucide-react";
|
|
12
12
|
import { anchoredInline, useAnchoredPanel } from "../hooks/use-anchored-panel";
|
|
13
13
|
import { runOwnKeyDown, takeEscape, useDismissLayer, useOutsideClick } from "../hooks/use-dismiss";
|
|
14
|
+
import type { DismissLayer } from "../hooks/use-dismiss";
|
|
14
15
|
import { useOverlayHistory } from "../hooks/use-overlay-history";
|
|
15
16
|
import { cn } from "../lib/cn";
|
|
16
17
|
import { FIELD_TOUCH_TEXT } from "./field-base";
|
|
@@ -18,6 +19,12 @@ import { mergeRefs } from "./field-parts";
|
|
|
18
19
|
import { FOCUS_RING } from "./focus-ring";
|
|
19
20
|
import { useAnchorDir } from "./use-anchor-dir";
|
|
20
21
|
|
|
22
|
+
/** Each list's Escape layer, filed under the refs {@link useDropdown} and
|
|
23
|
+
* {@link useDropdownSearch} hand out (`panelRef`, `inputRef`), for the panel and the
|
|
24
|
+
* search box those refs are passed to — see "The caller's own handler" on
|
|
25
|
+
* {@link useDropdown} (round 0.35 R2). Weak: a list's refs go with its component. */
|
|
26
|
+
const listLayers = new WeakMap<object, DismissLayer>();
|
|
27
|
+
|
|
21
28
|
/**
|
|
22
29
|
* Open state + close-on-outside-click for a custom dropdown — the two input-shaped
|
|
23
30
|
* comboboxes, and an app's own panel. (MultiSelect, CurrencySelect, GroupedPicker and
|
|
@@ -88,6 +95,16 @@ import { useAnchorDir } from "./use-anchor-dir";
|
|
|
88
95
|
* and stop it there — so a caller passes nothing new, AmountInput's currency chip
|
|
89
96
|
* included.
|
|
90
97
|
*
|
|
98
|
+
* ## The caller's own handler (round 0.35 R2)
|
|
99
|
+
*
|
|
100
|
+
* A caller's `onKeyDown` on {@link DropdownPanel} or {@link DropdownSearchHeader} hears
|
|
101
|
+
* Escape only while this list is the layer on top — the rule the dialogs got first. A
|
|
102
|
+
* tooltip over a row takes that press first, and the next one is the handler's, whose
|
|
103
|
+
* `preventDefault()` still keeps the list. The two find the list's layer through the
|
|
104
|
+
* refs this hook hands out — the panel through `panelRef`, the search box through
|
|
105
|
+
* {@link useDropdownSearch}'s `inputRef` — so a caller passes nothing new. One handed
|
|
106
|
+
* neither (an un-anchored panel may leave `panelRef` off) hears every key, as before.
|
|
107
|
+
*
|
|
91
108
|
* `escapeLayer: false` is for a caller that registers its own layer: the editable
|
|
92
109
|
* comboboxes, whose list can be "open" with nothing in it to show — an Escape there
|
|
93
110
|
* belongs to the dialog.
|
|
@@ -129,7 +146,11 @@ export function useDropdown<T extends HTMLElement = HTMLDivElement>({
|
|
|
129
146
|
}, []);
|
|
130
147
|
useOutsideClick([wrapperRef, panelRef], close, open && !panelIsSheet);
|
|
131
148
|
// See "Escape inside a dialog" above.
|
|
132
|
-
useDismissLayer(open && escapeLayer, closeToTrigger);
|
|
149
|
+
const layer = useDismissLayer(open && escapeLayer, closeToTrigger);
|
|
150
|
+
// Filed under `panelRef` for the panel's own handler — "The caller's own handler" above.
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
listLayers.set(panelRef, layer);
|
|
153
|
+
}, [panelRef, layer]);
|
|
133
154
|
// Same close path Escape and an outside click take, so a list dismissed by Back
|
|
134
155
|
// cannot end up in a different state from one dismissed any other way.
|
|
135
156
|
useOverlayHistory(open && backCloses, close);
|
|
@@ -145,6 +166,12 @@ export function useDropdownSearch<T extends HTMLElement = HTMLDivElement>() {
|
|
|
145
166
|
useDropdown<T>();
|
|
146
167
|
const [query, setQuery] = useState("");
|
|
147
168
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
169
|
+
// The list's layer again, under `inputRef` for the search box's handler (round 0.35
|
|
170
|
+
// R2). `useDropdown`'s effect, which runs first, has filed it under `panelRef`.
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
const layer = listLayers.get(panelRef);
|
|
173
|
+
if (layer) listLayers.set(inputRef, layer);
|
|
174
|
+
}, [panelRef]);
|
|
148
175
|
useEffect(() => {
|
|
149
176
|
if (open) {
|
|
150
177
|
// eslint-disable-next-line react-hooks/set-state-in-effect -- reset the query on open
|
|
@@ -237,7 +264,9 @@ export function DropdownSearchHeader({
|
|
|
237
264
|
value={query}
|
|
238
265
|
onChange={(e) => onQueryChange(e.target.value)}
|
|
239
266
|
onKeyDown={(e) => {
|
|
240
|
-
|
|
267
|
+
// The caller's handler hears Escape only while the list is on top (round 0.35
|
|
268
|
+
// R2) — the layer filed under `inputRef`, when {@link useDropdownSearch} made it.
|
|
269
|
+
runOwnKeyDown(e, onKeyDown, listLayers.get(inputRef));
|
|
241
270
|
// Focus is in this box while the list is up, so this is where Escape lands
|
|
242
271
|
// first — see "Escape inside a dialog" on {@link useDropdown}.
|
|
243
272
|
takeEscape(e);
|
|
@@ -271,30 +300,23 @@ export interface DropdownPanelProps extends ComponentPropsWithoutRef<"div"> {
|
|
|
271
300
|
anchorRef?: RefObject<HTMLElement | null>;
|
|
272
301
|
/** {@link useDropdown}'s `panelRef`, so an outside-click sees this as inside. Escape
|
|
273
302
|
* anywhere in the panel, on a row as in the search box, closes the list rather than
|
|
274
|
-
* a dialog around it.
|
|
303
|
+
* a dialog around it. It is also how the panel finds the list's Escape layer, for
|
|
304
|
+
* its `onKeyDown` (round 0.35 R2: see "The caller's own handler" there). */
|
|
275
305
|
panelRef?: RefObject<HTMLDivElement | null>;
|
|
276
306
|
/** Panel width in px, for the anchored form (the CSS `w-*` cannot be measured). */
|
|
277
307
|
width?: number;
|
|
278
|
-
/** Which of the panel's edges lines up with the trigger's, room permitting
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
|
|
284
|
-
align?: "start" | "end" | PhysicalAlign;
|
|
308
|
+
/** Which of the panel's edges lines up with the trigger's, room permitting, by the
|
|
309
|
+
* trigger's reading direction — `end` is the right edge in a left-to-right form and
|
|
310
|
+
* the left one in a right-to-left form. Default `end`. The physical `left` / `right`
|
|
311
|
+
* went in 0.35 (round 0.35 R1, refactor audit 2026-10, API-6e): `right` is `end` in a
|
|
312
|
+
* left-to-right page, `left` is `start`. */
|
|
313
|
+
align?: "start" | "end";
|
|
285
314
|
children: ReactNode;
|
|
286
315
|
/** The panel, where the rest of the props go (0.34, API-2, refactor audit 2026-10) —
|
|
287
316
|
* merged with `panelRef`, so the outside-click still sees it. */
|
|
288
317
|
ref?: Ref<HTMLDivElement>;
|
|
289
318
|
}
|
|
290
319
|
|
|
291
|
-
/**
|
|
292
|
-
* @deprecated 0.34 — `"start"` / `"end"`, which follow the reading direction: `"right"`
|
|
293
|
-
* is `"end"` in a left-to-right page, the default; removed in 0.35 (refactor audit
|
|
294
|
-
* 2026-10, API-6e). The physical edges DropdownPanel's `align` still takes.
|
|
295
|
-
*/
|
|
296
|
-
type PhysicalAlign = "left" | "right";
|
|
297
|
-
|
|
298
320
|
/**
|
|
299
321
|
* The floating popover surface for the searchable dropdowns: bordered/shadowed
|
|
300
322
|
* panel, an optional `header` slot (search box, plus any actions), and a
|
|
@@ -344,7 +366,9 @@ export function DropdownPanel({
|
|
|
344
366
|
// A row the keyboard reached by Tab holds focus too, and its Escape has to close the
|
|
345
367
|
// list as the search box's does (BUG-1). The caller's handler first, as everywhere.
|
|
346
368
|
const handleKeyDown = (e: ReactKeyboardEvent<HTMLDivElement>) => {
|
|
347
|
-
|
|
369
|
+
// It hears Escape only while the list is on top, a tooltip over a row taking the
|
|
370
|
+
// press first (round 0.35 R2) — the layer filed under `panelRef`, when handed one.
|
|
371
|
+
runOwnKeyDown(e, onKeyDown, panelRef && listLayers.get(panelRef));
|
|
348
372
|
takeEscape(e);
|
|
349
373
|
};
|
|
350
374
|
const body = (
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
useFieldHint,
|
|
26
26
|
useLockReason,
|
|
27
27
|
type DisabledReasonDisplay,
|
|
28
|
+
type FieldHelpProps,
|
|
28
29
|
} from "./field-parts";
|
|
29
30
|
import { useCommitReason, type CommitScope } from "./write-lock";
|
|
30
31
|
|
|
@@ -33,7 +34,8 @@ export type { ComboClearValue, ComboOption } from "./combobox-core";
|
|
|
33
34
|
/** `onChange` is the kit's — "a selection was made", carrying values — rather
|
|
34
35
|
* than the div's form event, so the DOM's spelling of it is omitted. */
|
|
35
36
|
export interface EntityComboboxProps<V extends string | number, C extends ComboClearValue = null>
|
|
36
|
-
extends Omit<ComponentPropsWithoutRef<"div">, "onChange"
|
|
37
|
+
extends Omit<ComponentPropsWithoutRef<"div">, "onChange">,
|
|
38
|
+
FieldHelpProps {
|
|
37
39
|
/** Selected id; `null`, `undefined` or `clearValue` when nothing is selected. */
|
|
38
40
|
value: V | C | null | undefined;
|
|
39
41
|
/** Selecting an option emits its value; the clear button emits `clearValue`. */
|
|
@@ -73,7 +75,7 @@ export interface EntityComboboxProps<V extends string | number, C extends ComboC
|
|
|
73
75
|
* so it is the one control here that MUST be in the reader's language. */
|
|
74
76
|
closeLabel?: string;
|
|
75
77
|
/** The phone sheet's heading (and, as a string, its accessible name) for a picker
|
|
76
|
-
* whose label is drawn by someone else — a
|
|
78
|
+
* whose label is drawn by someone else — a bound field's label; `RhfCombobox`
|
|
77
79
|
* hands its label over here (0.24). Default: `label`, then `placeholder`. */
|
|
78
80
|
sheetTitle?: ReactNode;
|
|
79
81
|
disabled?: boolean;
|
|
@@ -182,6 +184,7 @@ export function EntityCombobox<V extends string | number, C extends ComboClearVa
|
|
|
182
184
|
invalid,
|
|
183
185
|
error,
|
|
184
186
|
hint,
|
|
187
|
+
help,
|
|
185
188
|
filter,
|
|
186
189
|
minChars,
|
|
187
190
|
debounceMs,
|
|
@@ -206,7 +209,7 @@ export function EntityCombobox<V extends string | number, C extends ComboClearVa
|
|
|
206
209
|
minChars,
|
|
207
210
|
debounceMs,
|
|
208
211
|
});
|
|
209
|
-
const hintParts = useFieldHint(hint, ariaDescribedBy);
|
|
212
|
+
const hintParts = useFieldHint(hint, ariaDescribedBy, { help, name: label ?? ariaLabel });
|
|
210
213
|
const field = useFieldError(error, invalid, hintParts.describedBy, ariaInvalid);
|
|
211
214
|
// The props are the per-instance overrides, the provider the app-wide ones; a
|
|
212
215
|
// prop left `undefined` falls through to the provider rather than masking it.
|
|
@@ -457,17 +457,6 @@ export interface PasswordRevealLabels {
|
|
|
457
457
|
// Defined in ./ui-labels, which holds no component code (0.34, KS U8).
|
|
458
458
|
export { DEFAULT_PASSWORD_REVEAL_LABELS };
|
|
459
459
|
|
|
460
|
-
/** @deprecated 0.34 — `useKitLabels("passwordReveal", DEFAULT_PASSWORD_REVEAL_LABELS, labels)`,
|
|
461
|
-
* which the provider reaches too, or Input's own `passwordLabels`; removed in 0.35
|
|
462
|
-
* (refactor audit 2026-10, API-6a). A merge from before the provider, which no kit
|
|
463
|
-
* component calls. */
|
|
464
|
-
export function resolvePasswordRevealLabels(
|
|
465
|
-
partial?: Partial<PasswordRevealLabels>,
|
|
466
|
-
): PasswordRevealLabels {
|
|
467
|
-
if (!partial) return DEFAULT_PASSWORD_REVEAL_LABELS;
|
|
468
|
-
return { ...DEFAULT_PASSWORD_REVEAL_LABELS, ...partial };
|
|
469
|
-
}
|
|
470
|
-
|
|
471
460
|
/**
|
|
472
461
|
* What the character counter of {@link Input} and {@link Textarea} (`showCount`) says.
|
|
473
462
|
* The visible "12/80" is digits and a slash and is not translated; these are the words
|