@eifi1/ui-kit 0.31.1 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -28
- package/dist/account/delete-account-setting.d.ts +8 -3
- package/dist/admin/admin-action-confirm.d.ts +8 -3
- package/dist/admin/admin-action-log.d.ts +1 -1
- package/dist/admin/admin-action-log.js +4 -2
- package/dist/admin/admin-action-log.js.map +1 -1
- package/dist/admin/invitations-panel.d.ts +8 -3
- package/dist/admin/invitations-panel.js +29 -26
- package/dist/admin/invitations-panel.js.map +1 -1
- package/dist/admin/reviewer-scope-editor.d.ts +8 -3
- package/dist/admin/role-select.d.ts +10 -5
- package/dist/admin/transfer-ownership-dialog.d.ts +8 -3
- package/dist/admin/user-roster.d.ts +10 -5
- package/dist/admin/user-roster.js +8 -47
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/auth-errors.d.ts +43 -8
- package/dist/auth/auth-errors.js +24 -1
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/register-form.d.ts +8 -3
- package/dist/billing/billing-banner.d.ts +184 -0
- package/dist/billing/billing-banner.js +98 -0
- package/dist/billing/billing-banner.js.map +1 -0
- package/dist/billing/billing-labels.d.ts +100 -0
- package/dist/billing/billing-labels.js +76 -0
- package/dist/billing/billing-labels.js.map +1 -0
- package/dist/billing/billing-lock.d.ts +158 -0
- package/dist/billing/billing-lock.js +17 -0
- package/dist/billing/billing-lock.js.map +1 -0
- package/dist/billing/billing-standing.d.ts +149 -0
- package/dist/billing/billing-standing.js +28 -0
- package/dist/billing/billing-standing.js.map +1 -0
- package/dist/billing/plan-card.d.ts +248 -0
- package/dist/billing/plan-card.js +248 -0
- package/dist/billing/plan-card.js.map +1 -0
- package/dist/billing/plan-limit-notice.d.ts +156 -0
- package/dist/billing/plan-limit-notice.js +76 -0
- package/dist/billing/plan-limit-notice.js.map +1 -0
- package/dist/billing/plan-limit.d.ts +34 -0
- package/dist/billing/plan-limit.js +20 -0
- package/dist/billing/plan-limit.js.map +1 -0
- package/dist/billing/plan-price.d.ts +61 -0
- package/dist/billing/plan-price.js +45 -0
- package/dist/billing/plan-price.js.map +1 -0
- package/dist/billing/subscription-actions.d.ts +133 -0
- package/dist/billing/subscription-actions.js +28 -0
- package/dist/billing/subscription-actions.js.map +1 -0
- package/dist/billing/subscription-status-chip.d.ts +149 -0
- package/dist/billing/subscription-status-chip.js +48 -0
- package/dist/billing/subscription-status-chip.js.map +1 -0
- package/dist/chart.d.ts +9 -3
- package/dist/chart.js.map +1 -1
- package/dist/components/account-chips.d.ts +16 -4
- package/dist/components/account-chips.js +21 -3
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/alert-banner.d.ts +6 -1
- package/dist/components/alert-banner.js +5 -4
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +8 -3
- package/dist/components/amount-input.js +5 -5
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/appearance-labels.d.ts +38 -0
- package/dist/components/appearance-labels.js +19 -0
- package/dist/components/appearance-labels.js.map +1 -0
- package/dist/components/autocomplete.js +2 -2
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/breadcrumbs.js +3 -2
- package/dist/components/breadcrumbs.js.map +1 -1
- package/dist/components/bulk-action-bar.d.ts +2 -2
- package/dist/components/bulk-action-bar.js +7 -12
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button-group.d.ts +8 -3
- package/dist/components/button-group.js +7 -1
- package/dist/components/button-group.js.map +1 -1
- package/dist/components/calculator.d.ts +8 -3
- package/dist/components/calculator.js +4 -3
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/calendar-heatmap.js +5 -5
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/chart-height.d.ts +23 -0
- package/dist/components/chart-height.js +15 -0
- package/dist/components/chart-height.js.map +1 -0
- package/dist/components/chart-zoom.js +6 -1
- package/dist/components/chart-zoom.js.map +1 -1
- package/dist/components/checkbox-group.js +2 -2
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/checkbox.d.ts +10 -0
- package/dist/components/checkbox.js +25 -10
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +19 -3
- package/dist/components/chip.js +54 -23
- package/dist/components/chip.js.map +1 -1
- package/dist/components/choice-card.d.ts +1 -1
- package/dist/components/choice-card.js +9 -8
- package/dist/components/choice-card.js.map +1 -1
- package/dist/components/column-mapper.js +1 -1
- package/dist/components/column-mapper.js.map +1 -1
- package/dist/components/combobox-core.js +8 -7
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +8 -8
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +8 -3
- package/dist/components/copy-button.d.ts +10 -5
- package/dist/components/country-select.js +1 -1
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-select.js +3 -3
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +8 -3
- package/dist/components/data-table-cells.d.ts +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filter-popover.js +4 -1
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table-labels.d.ts +1 -1
- package/dist/components/data-table-pagination.d.ts +3 -2
- package/dist/components/data-table-pagination.js +15 -6
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +123 -52
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +1 -1
- package/dist/components/date-picker.js +18 -6
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/description-list.js +2 -2
- package/dist/components/description-list.js.map +1 -1
- package/dist/components/dialog-frame.js +2 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/disclosure.js +3 -2
- package/dist/components/disclosure.js.map +1 -1
- package/dist/components/dropdown.d.ts +1 -1
- package/dist/components/dropdown.js +7 -1
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/facing-pair.d.ts +19 -6
- package/dist/components/facing-pair.js +3 -2
- package/dist/components/facing-pair.js.map +1 -1
- package/dist/components/field-parts.d.ts +102 -6
- package/dist/components/field-parts.js +81 -6
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-sync.d.ts +4 -1
- package/dist/components/field-sync.js +12 -2
- package/dist/components/field-sync.js.map +1 -1
- package/dist/components/field.js +2 -2
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-button.d.ts +8 -3
- package/dist/components/file-dropzone.d.ts +8 -3
- package/dist/components/floating-panel.js +7 -4
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/focus-ring.d.ts +12 -0
- package/dist/components/focus-ring.js +8 -0
- package/dist/components/focus-ring.js.map +1 -0
- package/dist/components/form-actions.d.ts +8 -3
- package/dist/components/form-actions.js +33 -19
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/full-bleed-dialog.d.ts +11 -1
- package/dist/components/full-bleed-dialog.js +3 -1
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/iban-input.d.ts +8 -3
- package/dist/components/image-grid.js +1 -1
- package/dist/components/image-grid.js.map +1 -1
- package/dist/components/inline-edit-field.js +10 -4
- package/dist/components/inline-edit-field.js.map +1 -1
- package/dist/components/language-select.d.ts +8 -3
- package/dist/components/legal-page.d.ts +26 -5
- package/dist/components/legal-page.js +3 -1
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +8 -3
- package/dist/components/legal.js +2 -1
- package/dist/components/legal.js.map +1 -1
- package/dist/components/lightbox.js +24 -2
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/line-items.js +2 -1
- package/dist/components/line-items.js.map +1 -1
- package/dist/components/list.d.ts +5 -0
- package/dist/components/list.js +13 -9
- package/dist/components/list.js.map +1 -1
- package/dist/components/measured-grid.d.ts +3 -1
- package/dist/components/measured-grid.js +38 -20
- package/dist/components/measured-grid.js.map +1 -1
- package/dist/components/menu-item.js +2 -1
- package/dist/components/menu-item.js.map +1 -1
- package/dist/components/mini-calendar.js +8 -4
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/money-field.d.ts +8 -3
- package/dist/components/month-picker.js +50 -39
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/nav-pills.js +1 -1
- package/dist/components/nav-pills.js.map +1 -1
- package/dist/components/number-field.d.ts +8 -3
- package/dist/components/number-input.d.ts +11 -4
- package/dist/components/number-input.js +8 -6
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +8 -3
- package/dist/components/numpad-sheet.js +2 -1
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/one-time-code-input.js +2 -2
- package/dist/components/one-time-code-input.js.map +1 -1
- package/dist/components/page-contents.js +2 -2
- package/dist/components/page-contents.js.map +1 -1
- package/dist/components/phone-input.d.ts +8 -3
- package/dist/components/phone-input.js +4 -4
- package/dist/components/phone-input.js.map +1 -1
- package/dist/components/pie-chart.d.ts +8 -2
- package/dist/components/pie-chart.js +11 -7
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/popover.d.ts +9 -1
- package/dist/components/popover.js +8 -4
- package/dist/components/popover.js.map +1 -1
- package/dist/components/row-actions.d.ts +100 -0
- package/dist/components/row-actions.js +231 -0
- package/dist/components/row-actions.js.map +1 -0
- package/dist/components/scroll-area.js +1 -1
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/search-field.js +3 -2
- package/dist/components/search-field.js.map +1 -1
- package/dist/components/series-chart-budget.d.ts +30 -7
- package/dist/components/series-chart-budget.js +12 -4
- package/dist/components/series-chart-budget.js.map +1 -1
- package/dist/components/series-chart-ticks.d.ts +7 -1
- package/dist/components/series-chart-ticks.js +6 -0
- package/dist/components/series-chart-ticks.js.map +1 -1
- package/dist/components/series-chart.d.ts +58 -28
- package/dist/components/series-chart.js +42 -32
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/settings-fields.d.ts +57 -8
- package/dist/components/settings-fields.js +39 -1
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/share-card.d.ts +11 -6
- package/dist/components/share-card.js +8 -2
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/sign-chip.d.ts +4 -0
- package/dist/components/sign-chip.js +17 -4
- package/dist/components/sign-chip.js.map +1 -1
- package/dist/components/signature-pad.d.ts +3 -1
- package/dist/components/signature-pad.js +8 -5
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/slider.js +7 -6
- package/dist/components/slider.js.map +1 -1
- package/dist/components/sparkline.d.ts +5 -1
- package/dist/components/sparkline.js +4 -2
- package/dist/components/sparkline.js.map +1 -1
- package/dist/components/stat-tile.d.ts +17 -1
- package/dist/components/stat-tile.js +48 -20
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/status-dot.d.ts +4 -0
- package/dist/components/status-dot.js +9 -2
- package/dist/components/status-dot.js.map +1 -1
- package/dist/components/swipeable-row.js +10 -2
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/switch.d.ts +21 -7
- package/dist/components/switch.js +24 -11
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table.js +2 -2
- package/dist/components/table.js.map +1 -1
- package/dist/components/text-link.d.ts +8 -3
- package/dist/components/text-link.js +1 -1
- package/dist/components/text-link.js.map +1 -1
- package/dist/components/text.d.ts +7 -2
- package/dist/components/text.js +5 -5
- package/dist/components/text.js.map +1 -1
- package/dist/components/tile-radio.js +2 -1
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +8 -3
- package/dist/components/toast.d.ts +18 -2
- package/dist/components/toast.js +8 -5
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.d.ts +25 -3
- package/dist/components/toggle-group.js +40 -11
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle-legend.d.ts +10 -1
- package/dist/components/toggle-legend.js +21 -7
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/translation-review-editor.js +1 -1
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review-parts.d.ts +4 -0
- package/dist/components/translation-review.d.ts +4 -0
- package/dist/components/translation-review.js +3 -3
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/tree-view.js +3 -2
- package/dist/components/tree-view.js.map +1 -1
- package/dist/components/treemap.d.ts +5 -2
- package/dist/components/treemap.js +33 -16
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/ui.d.ts +8 -3
- package/dist/components/ui.js +207 -119
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/components/user-avatar.d.ts +5 -1
- package/dist/components/user-avatar.js +1 -1
- package/dist/components/user-avatar.js.map +1 -1
- package/dist/components/wizard-stepper.js +20 -14
- package/dist/components/wizard-stepper.js.map +1 -1
- package/dist/{data-table-labels-DUELeXpa.d.ts → data-table-labels-kpAAVi6g.d.ts} +26 -2
- package/dist/data-table.d.ts +1 -1
- package/dist/{delete-account-setting-CpIhzxxZ.d.ts → delete-account-setting-FLyJf-kZ.d.ts} +642 -60
- package/dist/demo/demo-banner.js +1 -0
- package/dist/demo/demo-banner.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +8 -3
- package/dist/feedback/feedback-context.d.ts +8 -3
- package/dist/feedback/feedback-crash.d.ts +8 -3
- package/dist/feedback/feedback-dialog.d.ts +8 -3
- package/dist/feedback/feedback-dialog.js +3 -3
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +8 -3
- package/dist/feedback/feedback-inbox.js +2 -2
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-labels.d.ts +8 -3
- package/dist/feedback/feedback-menu.d.ts +9 -4
- package/dist/feedback/feedback-record.d.ts +8 -3
- package/dist/feedback/feedback-row-detail.d.ts +8 -3
- package/dist/feedback/feedback-status-undo.d.ts +8 -3
- package/dist/feedback/feedback-submit.d.ts +8 -3
- package/dist/feedback/feedback-swipe.d.ts +8 -3
- package/dist/feedback/feedback-table.d.ts +8 -3
- package/dist/feedback/feedback-thread.d.ts +8 -3
- package/dist/feedback/feedback-thread.js +3 -3
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +8 -3
- package/dist/hooks/use-anchored-panel.d.ts +32 -3
- package/dist/hooks/use-anchored-panel.js +21 -3
- package/dist/hooks/use-anchored-panel.js.map +1 -1
- package/dist/hooks/use-breakpoint.d.ts +88 -0
- package/dist/hooks/use-breakpoint.js +50 -0
- package/dist/hooks/use-breakpoint.js.map +1 -0
- package/dist/hooks/use-file-drop.d.ts +8 -3
- package/dist/hooks/use-large-text.d.ts +29 -0
- package/dist/hooks/use-large-text.js +20 -0
- package/dist/hooks/use-large-text.js.map +1 -0
- package/dist/hooks/use-windowed-rows.d.ts +52 -8
- package/dist/hooks/use-windowed-rows.js +94 -5
- package/dist/hooks/use-windowed-rows.js.map +1 -1
- package/dist/i18n/defaults.d.ts +8 -3
- package/dist/i18n/defaults.js +8 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +8 -3
- package/dist/i18n/german.js +94 -3
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +8 -3
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +10 -5
- package/dist/i18n/locales/de-CH.d.ts +8 -3
- package/dist/i18n/locales/en.d.ts +8 -3
- package/dist/i18n/locales/es.d.ts +8 -3
- package/dist/i18n/locales/es.js +89 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +8 -3
- package/dist/i18n/locales/fr.js +91 -3
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +8 -3
- package/dist/i18n/locales/hu.js +91 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +8 -3
- package/dist/i18n/locales/it.js +92 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +8 -3
- package/dist/i18n/locales/zh.js +89 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +8 -3
- package/dist/i18n/review.js +15 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +27 -11
- package/dist/index.js +77 -4
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-actions.d.ts +8 -3
- package/dist/landing/landing-sections.d.ts +8 -3
- package/dist/landing/landing-sections.js +7 -3
- package/dist/landing/landing-sections.js.map +1 -1
- package/dist/landing/public-header.d.ts +9 -4
- package/dist/landing/public-header.js +3 -3
- package/dist/landing/public-header.js.map +1 -1
- package/dist/landing/routing.d.ts +8 -3
- package/dist/lib/cn.js +3 -2
- package/dist/lib/cn.js.map +1 -1
- package/dist/rhf/fields.d.ts +8 -3
- package/dist/rhf/fields.js +1 -1
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +8 -3
- package/dist/rhf/form.js +2 -2
- package/dist/rhf/form.js.map +1 -1
- package/dist/rhf.d.ts +8 -3
- package/dist/search/command-palette.d.ts +1 -1
- package/dist/search/command-palette.js +9 -8
- package/dist/search/command-palette.js.map +1 -1
- package/dist/settings/settings-layout.js +2 -1
- package/dist/settings/settings-layout.js.map +1 -1
- package/dist/settings/settings-section.d.ts +8 -3
- package/dist/settings/use-account-appearance.d.ts +92 -0
- package/dist/settings/use-account-appearance.js +63 -0
- package/dist/settings/use-account-appearance.js.map +1 -0
- package/dist/settings/use-settings-route.d.ts +1 -1
- package/dist/settings/use-settings-route.js +2 -3
- package/dist/settings/use-settings-route.js.map +1 -1
- package/dist/shell/app-shell.d.ts +12 -171
- package/dist/shell/app-shell.js +144 -28
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/auth-layout.js +1 -1
- package/dist/shell/auth-layout.js.map +1 -1
- package/dist/shell/option-switcher-menu.js +1 -1
- package/dist/shell/option-switcher-menu.js.map +1 -1
- package/dist/shell/top-bar-brand.d.ts +8 -3
- package/dist/shell/top-bar-brand.js +3 -1
- package/dist/shell/top-bar-brand.js.map +1 -1
- package/dist/shell/topbar-action-menu.d.ts +4 -0
- package/dist/shell/topbar-action-menu.js +3 -3
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell/topbar-controls.js +4 -4
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/shell.d.ts +9 -5
- package/dist/theme/contrast-tokens.d.ts +41 -0
- package/dist/theme/contrast-tokens.js +59 -0
- package/dist/theme/contrast-tokens.js.map +1 -0
- package/dist/theme/contrast.d.ts +110 -0
- package/dist/theme/contrast.js +128 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/palette-presets.d.ts +12 -1
- package/dist/theme/palette-presets.js +9 -4
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/text-size.d.ts +173 -0
- package/dist/theme/text-size.js +121 -0
- package/dist/theme/text-size.js.map +1 -0
- package/dist/wizard/stepper-nav.d.ts +8 -3
- package/dist/wizard/wizard-summary.js +1 -1
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/dist/wizard.d.ts +8 -3
- package/package.json +1 -1
- package/src/admin/admin-action-log.tsx +6 -1
- package/src/admin/invitations-panel.tsx +36 -29
- package/src/admin/user-roster.tsx +17 -72
- package/src/auth/auth-errors.ts +68 -7
- package/src/billing/billing-banner.tsx +205 -0
- package/src/billing/billing-labels.ts +240 -0
- package/src/billing/billing-lock.ts +75 -0
- package/src/billing/billing-standing.ts +72 -0
- package/src/billing/plan-card.tsx +458 -0
- package/src/billing/plan-limit-notice.tsx +145 -0
- package/src/billing/plan-limit.ts +53 -0
- package/src/billing/plan-price.ts +101 -0
- package/src/billing/subscription-actions.tsx +76 -0
- package/src/billing/subscription-status-chip.tsx +95 -0
- package/src/chart.ts +2 -0
- package/src/components/account-chips.tsx +36 -10
- package/src/components/alert-banner.tsx +16 -7
- package/src/components/amount-input.tsx +5 -5
- package/src/components/appearance-labels.ts +47 -0
- package/src/components/autocomplete.tsx +2 -2
- package/src/components/breadcrumbs.tsx +3 -3
- package/src/components/bulk-action-bar.tsx +11 -14
- package/src/components/button-group.tsx +21 -0
- package/src/components/calculator.tsx +4 -3
- package/src/components/calendar-heatmap.tsx +5 -5
- package/src/components/chart-height.ts +30 -0
- package/src/components/chart-zoom.tsx +6 -1
- package/src/components/checkbox-group.tsx +2 -2
- package/src/components/checkbox.tsx +62 -20
- package/src/components/chip.tsx +139 -30
- package/src/components/choice-card.tsx +16 -11
- package/src/components/column-mapper.tsx +1 -1
- package/src/components/combobox-core.tsx +8 -7
- package/src/components/combobox.tsx +8 -8
- package/src/components/country-select.tsx +1 -1
- package/src/components/currency-select.tsx +3 -3
- package/src/components/data-table-filter-popover.tsx +7 -1
- package/src/components/data-table-pagination.tsx +60 -31
- package/src/components/data-table.tsx +164 -43
- package/src/components/date-picker.tsx +44 -10
- package/src/components/description-list.tsx +2 -2
- package/src/components/dialog-frame.tsx +2 -1
- package/src/components/disclosure.tsx +3 -2
- package/src/components/dropdown.tsx +10 -2
- package/src/components/facing-pair.ts +12 -5
- package/src/components/field-parts.tsx +190 -7
- package/src/components/field-sync.tsx +17 -3
- package/src/components/field.tsx +2 -2
- package/src/components/floating-panel.tsx +7 -4
- package/src/components/focus-ring.ts +12 -0
- package/src/components/form-actions.tsx +55 -18
- package/src/components/full-bleed-dialog.tsx +18 -4
- package/src/components/image-grid.tsx +1 -1
- package/src/components/inline-edit-field.tsx +26 -4
- package/src/components/legal-page.tsx +28 -2
- package/src/components/legal.tsx +19 -1
- package/src/components/lightbox.tsx +24 -2
- package/src/components/line-items.tsx +7 -1
- package/src/components/list.tsx +36 -10
- package/src/components/measured-grid.tsx +49 -24
- package/src/components/menu-item.tsx +2 -2
- package/src/components/mini-calendar.tsx +8 -4
- package/src/components/month-picker.tsx +15 -6
- package/src/components/nav-pills.tsx +1 -1
- package/src/components/number-input.tsx +14 -7
- package/src/components/numpad-sheet.tsx +2 -2
- package/src/components/one-time-code-input.tsx +2 -2
- package/src/components/page-contents.tsx +2 -2
- package/src/components/phone-input.tsx +9 -4
- package/src/components/pie-chart.tsx +19 -9
- package/src/components/popover.tsx +22 -5
- package/src/components/row-actions.tsx +450 -0
- package/src/components/scroll-area.tsx +1 -1
- package/src/components/search-field.tsx +4 -2
- package/src/components/series-chart-budget.ts +40 -8
- package/src/components/series-chart-ticks.ts +10 -0
- package/src/components/series-chart.tsx +123 -72
- package/src/components/settings-fields.tsx +89 -5
- package/src/components/share-card.tsx +31 -2
- package/src/components/sign-chip.tsx +28 -4
- package/src/components/signature-pad.tsx +13 -7
- package/src/components/slider.tsx +22 -9
- package/src/components/sparkline.tsx +11 -3
- package/src/components/stat-tile.tsx +70 -14
- package/src/components/status-dot.tsx +25 -2
- package/src/components/swipeable-row.tsx +10 -2
- package/src/components/switch.tsx +57 -23
- package/src/components/table.tsx +2 -2
- package/src/components/text-link.tsx +1 -1
- package/src/components/text.tsx +11 -6
- package/src/components/tile-radio.tsx +4 -1
- package/src/components/toast.tsx +27 -7
- package/src/components/toggle-group.tsx +115 -14
- package/src/components/toggle-legend.tsx +53 -8
- package/src/components/translation-review-editor.tsx +1 -1
- package/src/components/translation-review.tsx +11 -5
- package/src/components/tree-view.tsx +3 -2
- package/src/components/treemap.tsx +27 -10
- package/src/components/ui.tsx +353 -153
- package/src/components/user-avatar.tsx +1 -1
- package/src/components/wizard-stepper.tsx +5 -1
- package/src/demo/demo-banner.tsx +5 -0
- package/src/feedback/feedback-dialog.tsx +3 -3
- package/src/feedback/feedback-inbox.tsx +2 -2
- package/src/feedback/feedback-thread.tsx +3 -3
- package/src/hooks/use-anchored-panel.ts +67 -5
- package/src/hooks/use-breakpoint.ts +132 -0
- package/src/hooks/use-large-text.ts +41 -0
- package/src/hooks/use-windowed-rows.ts +168 -12
- package/src/i18n/defaults.ts +8 -0
- package/src/i18n/german.ts +107 -0
- package/src/i18n/kit-labels.tsx +12 -0
- package/src/i18n/locales/es.ts +98 -0
- package/src/i18n/locales/fr.ts +102 -0
- package/src/i18n/locales/hu.ts +100 -0
- package/src/i18n/locales/it.ts +103 -0
- package/src/i18n/locales/zh.ts +94 -0
- package/src/i18n/review.ts +14 -0
- package/src/index.ts +76 -6
- package/src/landing/landing-sections.tsx +7 -3
- package/src/landing/public-header.tsx +4 -4
- package/src/lib/cn.ts +13 -2
- package/src/rhf/fields.tsx +1 -1
- package/src/rhf/form.tsx +2 -2
- package/src/search/command-palette.tsx +10 -9
- package/src/settings/settings-layout.tsx +2 -1
- package/src/settings/use-account-appearance.ts +148 -0
- package/src/settings/use-settings-route.ts +3 -4
- package/src/shell/app-shell.tsx +278 -54
- package/src/shell/auth-layout.tsx +1 -1
- package/src/shell/option-switcher-menu.tsx +1 -1
- package/src/shell/top-bar-brand.tsx +3 -1
- package/src/shell/topbar-action-menu.tsx +3 -3
- package/src/shell/topbar-controls.tsx +4 -4
- package/src/theme/contrast-tokens.ts +112 -0
- package/src/theme/contrast.ts +225 -0
- package/src/theme/palette-presets.ts +24 -4
- package/src/theme/palette-store.ts +6 -1
- package/src/theme/text-size.ts +283 -0
- package/src/wizard/wizard-summary.tsx +4 -2
- package/tokens.css +158 -8
|
@@ -13,7 +13,11 @@ export function WizardStepper({
|
|
|
13
13
|
}) {
|
|
14
14
|
const currentIndex = steps.findIndex((s) => s.key === current);
|
|
15
15
|
return (
|
|
16
|
-
|
|
16
|
+
// `flex-wrap`: the steps flow onto a second line rather than past the screen
|
|
17
|
+
// (0.32.1, the 360 px Extra-large sweep; docs/text-size-harmonization.md §4).
|
|
18
|
+
// "Upload — Map columns — Confirm" ran 22 px past a 360 px phone at Extra large.
|
|
19
|
+
// Where the steps fit, they stay one row.
|
|
20
|
+
<ol className="flex flex-wrap items-center gap-1 text-xs" aria-label={ariaLabel}>
|
|
17
21
|
{steps.map((step, i) => (
|
|
18
22
|
<li key={step.key} className="flex items-center gap-1">
|
|
19
23
|
{i > 0 && <span className="w-4 border-t border-[var(--border)]" />}
|
package/src/demo/demo-banner.tsx
CHANGED
|
@@ -139,6 +139,11 @@ export function DemoBanner({
|
|
|
139
139
|
size="2xs"
|
|
140
140
|
variant="ghost"
|
|
141
141
|
label={labels.details}
|
|
142
|
+
// The icon alone at every text size (docs/text-size-harmonization.md §10.8):
|
|
143
|
+
// a strip's one disclosure chevron beside its two links, whose state the
|
|
144
|
+
// chevron and `aria-expanded` say; "Details" as text at Large would push the
|
|
145
|
+
// links onto another line of a strip that is meant to stay one.
|
|
146
|
+
labelVisible={false}
|
|
142
147
|
aria-expanded={!collapsed}
|
|
143
148
|
onClick={toggle}
|
|
144
149
|
>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
|
-
import { Button, Input,
|
|
3
|
+
import { Button, Input, Select, Textarea } from "../components/ui";
|
|
4
4
|
import type { ButtonSize, ButtonVariant } from "../components/ui";
|
|
5
5
|
import { Modal } from "../components/modal";
|
|
6
6
|
import { isApplePlatform } from "../hooks/use-hotkey";
|
|
7
|
-
import {
|
|
7
|
+
import { usePhoneLayout } from "../hooks/use-breakpoint";
|
|
8
8
|
import { useKitLabels } from "../i18n/kit-labels";
|
|
9
9
|
import {
|
|
10
10
|
DEFAULT_ATTACHMENT_ACCEPT,
|
|
@@ -262,7 +262,7 @@ export function FeedbackDialog(props: FeedbackDialogProps) {
|
|
|
262
262
|
// `attachments="multiple"` only: the capture, apart from the picked/pasted files.
|
|
263
263
|
const [screenshot, setScreenshot] = useState<File | null>(null);
|
|
264
264
|
const [files, setFiles] = useState<File[]>([]);
|
|
265
|
-
const isMobile =
|
|
265
|
+
const isMobile = usePhoneLayout();
|
|
266
266
|
const labels = useKitLabels("feedbackDialog", DEFAULT_FEEDBACK_DIALOG_LABELS, labelsProp);
|
|
267
267
|
const attachmentText = useKitLabels("feedbackAttachment", DEFAULT_FEEDBACK_ATTACHMENT_LABELS, labelsProp);
|
|
268
268
|
// Under `multiple` the heading is `attachmentList` — a screenshot AND photos — which
|
|
@@ -313,7 +313,7 @@ export function FeedbackCategoryBadge({
|
|
|
313
313
|
<span
|
|
314
314
|
className={cn(
|
|
315
315
|
"inline-flex items-center gap-1 rounded font-medium",
|
|
316
|
-
compact ? "px-1.5 py-0.5 text-
|
|
316
|
+
compact ? "px-1.5 py-0.5 text-caption" : "px-2 py-0.5 text-xs",
|
|
317
317
|
meta.badgeBg,
|
|
318
318
|
meta.badgeText,
|
|
319
319
|
className,
|
|
@@ -346,7 +346,7 @@ export function FeedbackStatusBadge({
|
|
|
346
346
|
return (
|
|
347
347
|
<span
|
|
348
348
|
className={cn(
|
|
349
|
-
"inline-flex items-center gap-1 whitespace-nowrap rounded px-1.5 py-0.5 text-
|
|
349
|
+
"inline-flex items-center gap-1 whitespace-nowrap rounded px-1.5 py-0.5 text-caption font-medium",
|
|
350
350
|
meta.activeBg,
|
|
351
351
|
meta.activeText,
|
|
352
352
|
className,
|
|
@@ -265,7 +265,7 @@ export function FeedbackThread({
|
|
|
265
265
|
className="flex flex-wrap items-baseline justify-center gap-x-2 px-4 text-center text-xs text-[var(--text-muted)]"
|
|
266
266
|
>
|
|
267
267
|
<span>{message.body}</span>
|
|
268
|
-
{time && <span className="text-
|
|
268
|
+
{time && <span className="text-caption">{time}</span>}
|
|
269
269
|
</li>,
|
|
270
270
|
);
|
|
271
271
|
return rows;
|
|
@@ -286,14 +286,14 @@ export function FeedbackThread({
|
|
|
286
286
|
: "rounded-es-sm bg-[var(--bg-surface-2)]",
|
|
287
287
|
)}
|
|
288
288
|
>
|
|
289
|
-
<header className="mb-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-
|
|
289
|
+
<header className="mb-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-caption text-[var(--text-muted)]">
|
|
290
290
|
{author != null && (
|
|
291
291
|
<span data-private={priv} className="font-medium text-[var(--text-secondary)]">
|
|
292
292
|
{author}
|
|
293
293
|
</span>
|
|
294
294
|
)}
|
|
295
295
|
{message.staff && (
|
|
296
|
-
<span className="rounded border border-[var(--border)] bg-[var(--bg-surface)] px-1 text-
|
|
296
|
+
<span className="rounded border border-[var(--border)] bg-[var(--bg-surface)] px-1 text-micro font-medium uppercase tracking-wide text-[var(--text-secondary)]">
|
|
297
297
|
{labels.staff}
|
|
298
298
|
</span>
|
|
299
299
|
)}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useLayoutEffect, useState } from "react";
|
|
2
2
|
import type { RefObject } from "react";
|
|
3
3
|
import { useAnchoredRect, type AnchorRect } from "./use-anchored-rect";
|
|
4
|
+
import { useTextSize } from "../theme/text-size";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Vertical placement for a portalled, `position: fixed` panel anchored to a trigger.
|
|
@@ -22,6 +23,51 @@ export interface ViewportBox {
|
|
|
22
23
|
height: number;
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Whether the page is pinch-zoomed (docs/text-size-harmonization.md §10.2). A zoom
|
|
28
|
+
* shrinks `visualViewport.height` exactly like an on-screen keyboard does, so every
|
|
29
|
+
* reader below must tell the two apart — and while zoomed, the answer is "no keyboard":
|
|
30
|
+
* following a zoomed viewport would drag a pinned row on every pan, magnified, and the
|
|
31
|
+
* browser already scrolls a focused field into view. The epsilon absorbs a scale of
|
|
32
|
+
* 1.0000001 that some engines report at rest.
|
|
33
|
+
*/
|
|
34
|
+
function isZoomed(vv: VisualViewport): boolean {
|
|
35
|
+
return vv.scale > 1.001;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Below this the "keyboard" is rounding noise or a browser UI strip — `innerHeight` and
|
|
39
|
+
* `visualViewport.height` routinely disagree by a pixel or two — and nothing should move
|
|
40
|
+
* (keksdose's `MIN_KEYBOARD_PX`). */
|
|
41
|
+
const MIN_KEYBOARD_PX = 100;
|
|
42
|
+
|
|
43
|
+
export interface KeyboardInsetOptions {
|
|
44
|
+
/** The smallest inset that counts as a keyboard. Default 100 px. */
|
|
45
|
+
minimum?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* How many CSS px at the bottom of the LAYOUT viewport the on-screen keyboard covers, now
|
|
50
|
+
* — the one guarded reader (§10.2), so the apps' copies go (keksdose's
|
|
51
|
+
* `use-keyboard-inset.ts`):
|
|
52
|
+
*
|
|
53
|
+
* - 0 while the page is pinch-zoomed (`visualViewport.scale > 1`), where a smaller visual
|
|
54
|
+
* viewport is the zoom, not a keyboard;
|
|
55
|
+
* - 0 below `minimum` (100 px), which is noise;
|
|
56
|
+
* - 0 without `visualViewport` (SSR, jsdom, an old browser) and under
|
|
57
|
+
* `interactive-widget=resizes-content`, where `bottom: 0` already lands above the
|
|
58
|
+
* keyboard.
|
|
59
|
+
*
|
|
60
|
+
* Read it on `visualViewport`'s `resize` and `scroll` events (window `resize` as the
|
|
61
|
+
* fallback); a bottom-anchored control lifts itself by the result.
|
|
62
|
+
*/
|
|
63
|
+
export function readKeyboardInset({ minimum = MIN_KEYBOARD_PX }: KeyboardInsetOptions = {}): number {
|
|
64
|
+
if (typeof window === "undefined") return 0;
|
|
65
|
+
const vv = window.visualViewport;
|
|
66
|
+
if (!vv || isZoomed(vv)) return 0;
|
|
67
|
+
const inset = Math.round(window.innerHeight - vv.height - vv.offsetTop);
|
|
68
|
+
return inset >= minimum ? inset : 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
25
71
|
function readViewport(): ViewportBox {
|
|
26
72
|
if (typeof window === "undefined") return { top: 0, height: 0 };
|
|
27
73
|
const vv = window.visualViewport;
|
|
@@ -35,9 +81,12 @@ export interface AnchoredPanelOptions {
|
|
|
35
81
|
gap?: number;
|
|
36
82
|
/** Space kept clear at the viewport edges. */
|
|
37
83
|
margin?: number;
|
|
38
|
-
/** The height the panel would like, when there is room.
|
|
84
|
+
/** The height the panel would like, when there is room. In px at Normal text size:
|
|
85
|
+
* {@link useAnchoredPanel} multiplies it by the size's scale, since what a panel
|
|
86
|
+
* holds is rows of text (0.32, docs/text-size-harmonization.md §3.2). */
|
|
39
87
|
preferredHeight?: number;
|
|
40
|
-
/** Below this, the space under the trigger counts as unusable and a flip is considered.
|
|
88
|
+
/** Below this, the space under the trigger counts as unusable and a flip is considered.
|
|
89
|
+
* In px at Normal, scaled likewise. */
|
|
41
90
|
minHeight?: number;
|
|
42
91
|
}
|
|
43
92
|
|
|
@@ -118,6 +167,12 @@ export function anchoredPanelPlacement(
|
|
|
118
167
|
* older browsers) or no keyboard taking a bite out of it. A caller then keeps its
|
|
119
168
|
* static layout, which is right at every width where this does not apply — and is why
|
|
120
169
|
* the desktop and the test suite see exactly the markup they saw before.
|
|
170
|
+
*
|
|
171
|
+
* Also `null` while the page is pinch-zoomed (0.32, §10.2), with the guard
|
|
172
|
+
* {@link readKeyboardInset} uses. A zoom shrinks the visual viewport like a keyboard,
|
|
173
|
+
* and following it gave PickerSheet the zoomed region's top and height but the page's
|
|
174
|
+
* full width — its close button sat off screen (kastlan, Kurvenschmiede). Zoomed, the
|
|
175
|
+
* sheet keeps its static full-screen box, which the reader can pan to like the page.
|
|
121
176
|
*/
|
|
122
177
|
export function useVisualViewport(active: boolean): ViewportBox | null {
|
|
123
178
|
const [box, setBox] = useState<ViewportBox | null>(null);
|
|
@@ -130,7 +185,9 @@ export function useVisualViewport(active: boolean): ViewportBox | null {
|
|
|
130
185
|
// device-pixel-ratio that is not an integer (his phone reports 1.25), so a
|
|
131
186
|
// strict comparison would report a "keyboard" of 0.4px on every phone and pin
|
|
132
187
|
// a height where none was needed.
|
|
133
|
-
setBox(
|
|
188
|
+
setBox(
|
|
189
|
+
vv && !isZoomed(vv) && vv.height < window.innerHeight - 1 ? { top: vv.offsetTop, height: vv.height } : null,
|
|
190
|
+
);
|
|
134
191
|
};
|
|
135
192
|
update();
|
|
136
193
|
const vv = window.visualViewport;
|
|
@@ -154,6 +211,11 @@ export function useAnchoredPanel<T extends HTMLElement>(
|
|
|
154
211
|
): AnchoredPanel {
|
|
155
212
|
const rect = useAnchoredRect(ref, open);
|
|
156
213
|
const [viewport, setViewport] = useState<ViewportBox>(readViewport);
|
|
214
|
+
// A panel of rows wants room for the same number of rows at every text size; the gap
|
|
215
|
+
// and the edge margin are not text and stay px.
|
|
216
|
+
const { scale } = useTextSize();
|
|
217
|
+
const preferredHeight = (options.preferredHeight ?? 320) * scale;
|
|
218
|
+
const minHeight = (options.minHeight ?? 160) * scale;
|
|
157
219
|
|
|
158
220
|
useLayoutEffect(() => {
|
|
159
221
|
if (!open) return;
|
|
@@ -174,7 +236,7 @@ export function useAnchoredPanel<T extends HTMLElement>(
|
|
|
174
236
|
}, [open]);
|
|
175
237
|
|
|
176
238
|
if (!rect) {
|
|
177
|
-
return { rect: null, top: 0, maxHeight:
|
|
239
|
+
return { rect: null, top: 0, maxHeight: preferredHeight, above: false };
|
|
178
240
|
}
|
|
179
|
-
return { rect, ...anchoredPanelPlacement(rect, viewport, options) };
|
|
241
|
+
return { rect, ...anchoredPanelPlacement(rect, viewport, { ...options, preferredHeight, minHeight }) };
|
|
180
242
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { useMediaQuery } from "./use-media-query";
|
|
2
|
+
import { useTextSize } from "../theme/text-size";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Breakpoints that follow the text size, in JS (docs/text-size-harmonization.md §3.3,
|
|
6
|
+
* §10.4).
|
|
7
|
+
*
|
|
8
|
+
* A media query's rem resolves against the browser's default font size, not `<html>`'s,
|
|
9
|
+
* so Tailwind's `md:` would stay at 48rem when the root grows. tokens.css therefore
|
|
10
|
+
* redefines every breakpoint variant per text size — `md:` is 48rem at Normal, 60rem at
|
|
11
|
+
* Large, 72rem at Extra large — and these hooks ask the same question with the same
|
|
12
|
+
* numbers, so the CSS and the JS answer always agree: AppShell's `md:hidden` and its
|
|
13
|
+
* `isMdUp`, DataTable's cards and its full-screen dialog, an app's sticky footer
|
|
14
|
+
* (keksdose's must be the SAME `usePhoneLayout()` the dialog uses, §10.4).
|
|
15
|
+
*
|
|
16
|
+
* Width queries only. Pointer and display-mode queries stay `useMediaQuery` (§10.4).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** The breakpoints at Normal, in rem: Tailwind's five, and `3xl` (keksdose's
|
|
20
|
+
* `min-[2400px]`, §10.4). tokens.css multiplies each by the text size. */
|
|
21
|
+
export const BREAKPOINT_REM = { sm: 40, md: 48, lg: 64, xl: 80, "2xl": 96, "3xl": 150 } as const;
|
|
22
|
+
|
|
23
|
+
export type Breakpoint = keyof typeof BREAKPOINT_REM;
|
|
24
|
+
|
|
25
|
+
/** A breakpoint variant, spelled as in a class: `"md"` is `md:` (at least md), `"max-md"`
|
|
26
|
+
* is `max-md:` (below md). */
|
|
27
|
+
export type BreakpointVariant = Breakpoint | `max-${Breakpoint}`;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The browser's own default font size in px — what a media query's rem means (the
|
|
31
|
+
* initial `font-size: medium`, never `<html>`'s). 16 unless the person changed it, and 16
|
|
32
|
+
* outside a browser. Read once: changing it takes a browser setting, after which the
|
|
33
|
+
* page is reloaded in practice.
|
|
34
|
+
*/
|
|
35
|
+
let browserRemPx: number | null = null;
|
|
36
|
+
function readBrowserRemPx(): number {
|
|
37
|
+
if (browserRemPx !== null) return browserRemPx;
|
|
38
|
+
// Outside a browser (SSR): 16, uncached, so the client's first real read still counts.
|
|
39
|
+
if (typeof document === "undefined" || !document.body) return 16;
|
|
40
|
+
const probe = document.createElement("div");
|
|
41
|
+
probe.style.cssText = "position:absolute;visibility:hidden;font-size:medium";
|
|
42
|
+
document.body.appendChild(probe);
|
|
43
|
+
const px = Number.parseFloat(getComputedStyle(probe).fontSize);
|
|
44
|
+
probe.remove();
|
|
45
|
+
// jsdom computes no font size ("medium" or nothing): the default it stands for.
|
|
46
|
+
browserRemPx = px > 0 ? px : 16;
|
|
47
|
+
return browserRemPx;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* How many CSS px one `rem` is at `scale` (`TEXT_SCALE` of the size in force): the
|
|
52
|
+
* browser's own default font size times the text size — what `<html>`'s computed font
|
|
53
|
+
* size is, by tokens.css. For the few lengths JS has to do arithmetic with: a popover's
|
|
54
|
+
* width against the viewport edge, a chart constant (§3.1, §3.2). 16 × `scale` outside a
|
|
55
|
+
* browser and in jsdom, which computes no default font size.
|
|
56
|
+
*/
|
|
57
|
+
export function remPx(scale = 1): number {
|
|
58
|
+
return readBrowserRemPx() * scale;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** {@link remPx} at the text size in force, re-rendering when it changes. */
|
|
62
|
+
export function useRemPx(): number {
|
|
63
|
+
const { scale } = useTextSize();
|
|
64
|
+
return remPx(scale);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** A length in rem as the kit spells one in JS — `"18rem"` — where a prop also takes px
|
|
68
|
+
* as a plain number. */
|
|
69
|
+
export type RemLength = `${number}rem`;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A `number | RemLength` in CSS px now: a number is px as given, `"18rem"` is 18 ×
|
|
73
|
+
* `rootRemPx` (see {@link remPx}). `undefined` stays `undefined`.
|
|
74
|
+
*/
|
|
75
|
+
export function lengthPx(length: number | RemLength, rootRemPx: number): number;
|
|
76
|
+
export function lengthPx(length: number | RemLength | undefined, rootRemPx: number): number | undefined;
|
|
77
|
+
export function lengthPx(length: number | RemLength | undefined, rootRemPx: number): number | undefined {
|
|
78
|
+
if (length === undefined) return undefined;
|
|
79
|
+
return typeof length === "number" ? length : Number.parseFloat(length) * rootRemPx;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The media query a breakpoint variant means at `scale` (`TEXT_SCALE` of the size in
|
|
84
|
+
* force). `"md"` → `(min-width: 768px)` at Normal, `(min-width: 960px)` at Large;
|
|
85
|
+
* `"max-md"` → `(width < 768px)` at Normal. In px, scaled by the browser's own default
|
|
86
|
+
* font size as well, so a person who set 20 px in the browser gets 960 px for `md` at
|
|
87
|
+
* Normal — as the CSS does.
|
|
88
|
+
*
|
|
89
|
+
* `max-*` is written in range syntax, `(width < N)`, against the same `N` its `min-*`
|
|
90
|
+
* twin starts at, so the two are exact complements at EVERY width: exactly one of
|
|
91
|
+
* `md` and `max-md` matches, as with tokens.css's `width >= 48rem` / `width < 48rem`
|
|
92
|
+
* (and Tailwind's own `max-*`). Until 0.32.1 it was `(max-width: 767px)`, which left a
|
|
93
|
+
* gap: on a fractional viewport width (767.5 px under zoom or at some Android
|
|
94
|
+
* device-pixel ratios) neither query matched, so DataTable, asking `!md`, said phone
|
|
95
|
+
* while `usePhoneLayout()`, asking `max-md`, said not (0.32.1, keksdose's 0.32 report;
|
|
96
|
+
* docs/text-size-harmonization.md §3.3: "the CSS and JS answers always agree").
|
|
97
|
+
*
|
|
98
|
+
* Range syntax in media queries is Chrome / Edge 104, Firefox 63, Safari 16.4. That is
|
|
99
|
+
* inside the floor the kit already sets: tokens.css's breakpoint variants are written in
|
|
100
|
+
* it, and Tailwind v4 itself needs Safari 16.4, Chrome 111 and Firefox 128.
|
|
101
|
+
*
|
|
102
|
+
* A test's `matchMedia` stub that keyed on the old string (`"max-width: 767px"`, the
|
|
103
|
+
* deprecated `PHONE_QUERY`) has to answer `(width < 768px)` now. `min-*` is unchanged,
|
|
104
|
+
* character for character.
|
|
105
|
+
*/
|
|
106
|
+
export function breakpointQuery(variant: BreakpointVariant, scale = 1, remPx: number = readBrowserRemPx()): string {
|
|
107
|
+
const max = variant.startsWith("max-");
|
|
108
|
+
const name = (max ? variant.slice(4) : variant) as Breakpoint;
|
|
109
|
+
const px = Math.round(BREAKPOINT_REM[name] * remPx * scale);
|
|
110
|
+
return max ? `(width < ${px}px)` : `(min-width: ${px}px)`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Whether the viewport matches a breakpoint variant at the text size in force — the JS
|
|
115
|
+
* twin of the class: `useBreakpoint("md")` is true exactly where `md:` applies,
|
|
116
|
+
* `useBreakpoint("max-sm")` where `max-sm:` does. `fallback` answers where there is no
|
|
117
|
+
* `matchMedia` (SSR, jsdom).
|
|
118
|
+
*/
|
|
119
|
+
export function useBreakpoint(variant: BreakpointVariant, fallback = false): boolean {
|
|
120
|
+
const { scale } = useTextSize();
|
|
121
|
+
return useMediaQuery(breakpointQuery(variant, scale), fallback);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The phone layout: below `md` at the text size in force — `max-md:` in CSS. The single
|
|
126
|
+
* answer for "is this the phone layout" (§10.4): the kit's own sheets and cards use it,
|
|
127
|
+
* and an app's phone checks must too, so a tablet at 150 % gets every phone treatment
|
|
128
|
+
* at once or none of them. Replaces `useMediaQuery(PHONE_QUERY)`.
|
|
129
|
+
*/
|
|
130
|
+
export function usePhoneLayout(fallback = false): boolean {
|
|
131
|
+
return useBreakpoint("max-md", fallback);
|
|
132
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useTextSize } from "../theme/text-size";
|
|
2
|
+
import { useMediaQuery } from "./use-media-query";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The two questions the kit's 0.32 behaviours ask (docs/text-size-harmonization.md §4,
|
|
6
|
+
* §10.7–10.9), answered in one place so every part draws the line where the others do.
|
|
7
|
+
*
|
|
8
|
+
* Prefer CSS where it can: a class that differs at Large is a `large:` variant
|
|
9
|
+
* (tokens.css), and a layout switch is a breakpoint, which already scales. These hooks
|
|
10
|
+
* are for what CSS cannot decide — whether a tooltip is rendered at all, whether a label
|
|
11
|
+
* becomes text, whether a row's actions collapse into a menu.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Large or Extra large is in force (`<html data-text-size>`) — the JS twin of the
|
|
15
|
+
* `large:` variant. */
|
|
16
|
+
export function useLargeText(): boolean {
|
|
17
|
+
return useTextSize().size !== "normal";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The primary pointer is a finger (`pointer: coarse`): a hover never happens, so a
|
|
22
|
+
* tooltip opens only on the taps that do nothing else. A pointer query, so it stays
|
|
23
|
+
* `useMediaQuery` (§10.4). `false` without `matchMedia` (SSR, jsdom).
|
|
24
|
+
*/
|
|
25
|
+
export function useCoarsePointer(): boolean {
|
|
26
|
+
return useMediaQuery("(pointer: coarse)", false);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Whether a fact may NOT live only in a tooltip here (§4 "No fact only in a tooltip"):
|
|
31
|
+
* at Large and Extra large, where the reader is the one who asked for bigger type, and
|
|
32
|
+
* on a touch screen at every size, where a tooltip cannot be hovered open. Where this
|
|
33
|
+
* is true the kit draws the fact in the layout — a `disabledReason` as a line under its
|
|
34
|
+
* control, a FieldHint as the field's caption, a StatTile hint as text — and keeps the
|
|
35
|
+
* bubble only where there is no room (a top bar, a dense row's inline actions).
|
|
36
|
+
*/
|
|
37
|
+
export function useInlineFacts(): boolean {
|
|
38
|
+
const large = useLargeText();
|
|
39
|
+
const coarse = useCoarsePointer();
|
|
40
|
+
return large || coarse;
|
|
41
|
+
}
|
|
@@ -1,27 +1,104 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
1
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import type { RefObject } from "react";
|
|
3
|
+
import { useTextSize } from "../theme/text-size";
|
|
3
4
|
|
|
4
5
|
/** Rows kept mounted beyond each edge, so a flick-scroll has something to show
|
|
5
6
|
* before the next render lands. */
|
|
6
7
|
const OVERSCAN = 6;
|
|
7
8
|
|
|
9
|
+
/** The attribute a measured row carries so {@link WindowedRows.measureRef} knows which
|
|
10
|
+
* row it is looking at: `data-row-index={index}`. */
|
|
11
|
+
export const WINDOWED_ROW_INDEX = "data-row-index";
|
|
12
|
+
|
|
8
13
|
/** What {@link useWindowedRows} answers: render rows `first` up to (not including)
|
|
9
14
|
* `last`, inside a scroll body `totalHeight` pixels tall. */
|
|
10
15
|
export interface WindowedRows {
|
|
11
16
|
first: number;
|
|
12
17
|
last: number;
|
|
13
18
|
totalHeight: number;
|
|
19
|
+
/**
|
|
20
|
+
* The top of row `index`, in px from the top of the list: the rows above it at their
|
|
21
|
+
* MEASURED heights where they have been rendered, at {@link estimate} where not.
|
|
22
|
+
* Position each row at this (`style={{ top: offsetOf(index) }}`) rather than at
|
|
23
|
+
* `index × rowHeight`, which is right only while every row is the estimate.
|
|
24
|
+
*/
|
|
25
|
+
offsetOf: (index: number) => number;
|
|
26
|
+
/** The height of row `index`: measured, else {@link estimate}. */
|
|
27
|
+
heightOf: (index: number) => number;
|
|
28
|
+
/**
|
|
29
|
+
* The height assumed for a row not measured yet: `rowHeight × scale`, the text
|
|
30
|
+
* size's factor (`useTextSize`). Give a row this as its `minHeight`, not its
|
|
31
|
+
* `height`: a row that wraps must be allowed to grow, and is then measured.
|
|
32
|
+
*/
|
|
33
|
+
estimate: number;
|
|
34
|
+
/**
|
|
35
|
+
* Put on every rendered row, with `data-row-index={index}` beside it: the row is
|
|
36
|
+
* observed while it is mounted, and its height replaces the estimate. Stable for the
|
|
37
|
+
* life of the list. A row without it keeps the estimate, which is the pre-0.32
|
|
38
|
+
* fixed-height list exactly.
|
|
39
|
+
*/
|
|
40
|
+
measureRef: (element: HTMLElement | null) => (() => void) | undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type Heights = ReadonlyMap<number, number>;
|
|
44
|
+
const NO_HEIGHTS: Heights = new Map();
|
|
45
|
+
|
|
46
|
+
/** The box height of an observed row: the border box where the browser reports one,
|
|
47
|
+
* else its laid-out rectangle. `0` means "not laid out" (hidden, jsdom) and is ignored. */
|
|
48
|
+
function rowHeightOf(entry: ResizeObserverEntry): number {
|
|
49
|
+
const box = entry.borderBoxSize?.[0];
|
|
50
|
+
if (box && box.blockSize > 0) return box.blockSize;
|
|
51
|
+
return entry.target.getBoundingClientRect().height;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The row index an element was given with {@link WINDOWED_ROW_INDEX}, or `null`. */
|
|
55
|
+
function indexOf(element: Element): number | null {
|
|
56
|
+
const raw = element.getAttribute(WINDOWED_ROW_INDEX);
|
|
57
|
+
if (raw === null) return null;
|
|
58
|
+
const index = Number(raw);
|
|
59
|
+
return Number.isInteger(index) && index >= 0 ? index : null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The last index `i` with `offsets[i] <= y` (0 when none): the row whose box holds `y`. */
|
|
63
|
+
function rowAt(offsets: Float64Array, count: number, y: number): number {
|
|
64
|
+
let lo = 0;
|
|
65
|
+
let hi = count;
|
|
66
|
+
while (lo < hi) {
|
|
67
|
+
const mid = (lo + hi + 1) >> 1;
|
|
68
|
+
if (offsets[mid] <= y) lo = mid;
|
|
69
|
+
else hi = mid - 1;
|
|
70
|
+
}
|
|
71
|
+
return Math.min(lo, Math.max(0, count - 1));
|
|
14
72
|
}
|
|
15
73
|
|
|
16
74
|
/**
|
|
17
|
-
* Which rows of a
|
|
75
|
+
* Which rows of a long list are worth rendering — and, since 0.32, where each one goes.
|
|
18
76
|
*
|
|
19
|
-
* Hand-rolled rather than pulled from a virtualization library
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
77
|
+
* Hand-rolled rather than pulled from a virtualization library: the obvious one
|
|
78
|
+
* (`@tanstack/react-virtual`) returns functions that cannot be memoized safely, so the
|
|
79
|
+
* React Compiler skips optimising any component that calls it — a list that exists to
|
|
80
|
+
* stay fast would opt out of the consumer's main source of speed.
|
|
81
|
+
*
|
|
82
|
+
* **Measured rows (docs/text-size-harmonization.md §10.9).** Until 0.32 every row was
|
|
83
|
+
* `rowHeight` px and the window was two divisions. "Nothing truncates" at Large and
|
|
84
|
+
* Extra large needs rows that grow with their text — Kurvenschmiede's segment list
|
|
85
|
+
* wraps a long name at 150 %, and a fixed 68 px row cut it off. So the rows are
|
|
86
|
+
* measured: put {@link WindowedRows.measureRef} and `data-row-index` on each rendered
|
|
87
|
+
* row, and one `ResizeObserver` watches every row while it is mounted (one observer for
|
|
88
|
+
* all of them, which the browser batches into one callback per frame). A measured
|
|
89
|
+
* height replaces the estimate; a row never rendered keeps `rowHeight × scale`, the
|
|
90
|
+
* text size's factor, so the scroll body is about right before anything is measured
|
|
91
|
+
* and exactly right for everything that has been. Offsets are a prefix sum over both,
|
|
92
|
+
* rebuilt only when a height changes — scrolling is a binary search.
|
|
93
|
+
*
|
|
94
|
+
* Measurements are dropped when the text size changes (every row is a different height
|
|
95
|
+
* then, and the rendered ones measure again at once) and ignored past `count` (a row
|
|
96
|
+
* removed at the end). Removing a row in the MIDDLE shifts the indices below it; they
|
|
97
|
+
* keep the old row's height until they are rendered again, which costs a few pixels of
|
|
98
|
+
* scrollbar, never a row out of place on screen.
|
|
99
|
+
*
|
|
100
|
+
* Without a `ResizeObserver` (jsdom, an old webview) the estimate holds for every row,
|
|
101
|
+
* which is the fixed-height list of before.
|
|
25
102
|
*
|
|
26
103
|
* `scrollRef` is the element that scrolls. The rows are assumed to start at its top;
|
|
27
104
|
* a sticky header above them costs a row or two of the overscan, not correctness.
|
|
@@ -35,8 +112,21 @@ export function useWindowedRows(
|
|
|
35
112
|
rowHeight: number,
|
|
36
113
|
scrollRef: RefObject<HTMLElement | null>,
|
|
37
114
|
): WindowedRows {
|
|
115
|
+
const { scale } = useTextSize();
|
|
116
|
+
const estimate = rowHeight * scale;
|
|
38
117
|
const [scrollTop, setScrollTop] = useState(0);
|
|
39
118
|
const [viewport, setViewport] = useState(0);
|
|
119
|
+
// The heights are keyed to the scale they were measured at: a text size switch makes
|
|
120
|
+
// every one of them stale at once, and the derivation below drops them on read.
|
|
121
|
+
const [measured, setMeasured] = useState<{ scale: number; heights: Heights }>({ scale, heights: NO_HEIGHTS });
|
|
122
|
+
const heights = measured.scale === scale ? measured.heights : NO_HEIGHTS;
|
|
123
|
+
// The observer's callback runs outside render and needs the scale in force then. A
|
|
124
|
+
// LAYOUT effect: the rows' new heights after a size switch are reported before the
|
|
125
|
+
// browser paints, which can be before a passive effect has run.
|
|
126
|
+
const scaleRef = useRef(scale);
|
|
127
|
+
useLayoutEffect(() => {
|
|
128
|
+
scaleRef.current = scale;
|
|
129
|
+
}, [scale]);
|
|
40
130
|
|
|
41
131
|
useEffect(() => {
|
|
42
132
|
const element = scrollRef.current;
|
|
@@ -59,11 +149,77 @@ export function useWindowedRows(
|
|
|
59
149
|
};
|
|
60
150
|
}, [scrollRef]);
|
|
61
151
|
|
|
62
|
-
|
|
152
|
+
// ONE observer for every row, made on the first row that asks for it.
|
|
153
|
+
const rowObserver = useRef<ResizeObserver | null>(null);
|
|
154
|
+
useEffect(
|
|
155
|
+
() => () => {
|
|
156
|
+
rowObserver.current?.disconnect();
|
|
157
|
+
rowObserver.current = null;
|
|
158
|
+
},
|
|
159
|
+
[],
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const measureRef = useCallback((element: HTMLElement | null) => {
|
|
163
|
+
if (!element || typeof ResizeObserver === "undefined") return undefined;
|
|
164
|
+
if (!rowObserver.current) {
|
|
165
|
+
rowObserver.current = new ResizeObserver((entries) => {
|
|
166
|
+
const updates: [number, number][] = [];
|
|
167
|
+
for (const entry of entries) {
|
|
168
|
+
const index = indexOf(entry.target);
|
|
169
|
+
const height = rowHeightOf(entry);
|
|
170
|
+
if (index !== null && height > 0) updates.push([index, height]);
|
|
171
|
+
}
|
|
172
|
+
if (!updates.length) return;
|
|
173
|
+
const at = scaleRef.current;
|
|
174
|
+
setMeasured((previous) => {
|
|
175
|
+
const base = previous.scale === at ? previous.heights : NO_HEIGHTS;
|
|
176
|
+
// Unchanged heights are the common case (a row re-observed after a re-render):
|
|
177
|
+
// the same map back means no render.
|
|
178
|
+
if (updates.every(([index, height]) => base.get(index) === height)) {
|
|
179
|
+
return previous.scale === at ? previous : { scale: at, heights: base };
|
|
180
|
+
}
|
|
181
|
+
const next = new Map(base);
|
|
182
|
+
for (const [index, height] of updates) next.set(index, height);
|
|
183
|
+
return { scale: at, heights: next };
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const observer = rowObserver.current;
|
|
188
|
+
observer.observe(element);
|
|
189
|
+
// React 19 calls this when the row unmounts (or the ref moves to another element).
|
|
190
|
+
return () => observer.unobserve(element);
|
|
191
|
+
}, []);
|
|
192
|
+
|
|
193
|
+
// The prefix sum: offsets[i] is the top of row i, offsets[count] the whole height.
|
|
194
|
+
// Skipped while nothing is measured, when the arithmetic is exact without it.
|
|
195
|
+
const offsets = useMemo(() => {
|
|
196
|
+
if (heights.size === 0) return null;
|
|
197
|
+
const table = new Float64Array(count + 1);
|
|
198
|
+
for (let index = 0; index < count; index += 1) {
|
|
199
|
+
table[index + 1] = table[index] + (heights.get(index) ?? estimate);
|
|
200
|
+
}
|
|
201
|
+
return table;
|
|
202
|
+
}, [count, estimate, heights]);
|
|
203
|
+
|
|
204
|
+
const offsetOf = useCallback(
|
|
205
|
+
(index: number) => (offsets ? offsets[Math.max(0, Math.min(index, count))] : index * estimate),
|
|
206
|
+
[offsets, count, estimate],
|
|
207
|
+
);
|
|
208
|
+
const heightOf = useCallback((index: number) => heights.get(index) ?? estimate, [heights, estimate]);
|
|
209
|
+
|
|
63
210
|
// A viewport of 0 is the first render, before the pane has been laid out (and every
|
|
64
211
|
// render under jsdom). Rendering nothing then would leave the list blank until
|
|
65
212
|
// something scrolled it, so fall back to a screenful.
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
213
|
+
const room = viewport || 600;
|
|
214
|
+
let first: number;
|
|
215
|
+
let last: number;
|
|
216
|
+
if (offsets) {
|
|
217
|
+
first = Math.max(0, rowAt(offsets, count, scrollTop) - OVERSCAN);
|
|
218
|
+
last = Math.min(count, rowAt(offsets, count, scrollTop + room) + 1 + OVERSCAN);
|
|
219
|
+
} else {
|
|
220
|
+
first = Math.max(0, Math.floor(scrollTop / estimate) - OVERSCAN);
|
|
221
|
+
last = Math.min(count, first + Math.ceil(room / estimate) + OVERSCAN * 2);
|
|
222
|
+
}
|
|
223
|
+
const totalHeight = offsets ? offsets[count] : count * estimate;
|
|
224
|
+
return { first, last, totalHeight, offsetOf, heightOf, estimate, measureRef };
|
|
69
225
|
}
|
package/src/i18n/defaults.ts
CHANGED
|
@@ -84,6 +84,10 @@ import { DEFAULT_INVITATIONS_LABELS } from "../admin/invitations-panel";
|
|
|
84
84
|
import { DEFAULT_SETTINGS_LABELS } from "../settings/settings-labels";
|
|
85
85
|
import { DEFAULT_LANDING_LABELS } from "../landing/landing-labels";
|
|
86
86
|
import { DEFAULT_DEMO_LABELS } from "../demo/demo-labels";
|
|
87
|
+
import { DEFAULT_BILLING_LABELS } from "../billing/billing-labels";
|
|
88
|
+
import { DEFAULT_APPEARANCE_LABELS } from "../components/appearance-labels";
|
|
89
|
+
import { DEFAULT_ROW_ACTIONS_LABELS } from "../components/row-actions";
|
|
90
|
+
import { DEFAULT_APP_SHELL_MORE_LABELS } from "../shell/app-shell";
|
|
87
91
|
import { DEFAULT_ACCOUNT_STATE_LABELS } from "../components/account-chips";
|
|
88
92
|
import { DEFAULT_SHARE_CARD_LABELS } from "../components/share-card";
|
|
89
93
|
import { DEFAULT_REAUTH_DIALOG_LABELS } from "../components/reauth-dialog";
|
|
@@ -214,6 +218,10 @@ export const DEFAULT_UI_KIT_LABELS: UiKitLabels = {
|
|
|
214
218
|
settings: DEFAULT_SETTINGS_LABELS,
|
|
215
219
|
landing: DEFAULT_LANDING_LABELS,
|
|
216
220
|
demo: DEFAULT_DEMO_LABELS,
|
|
221
|
+
billing: DEFAULT_BILLING_LABELS,
|
|
222
|
+
appearance: DEFAULT_APPEARANCE_LABELS,
|
|
223
|
+
rowActions: DEFAULT_ROW_ACTIONS_LABELS,
|
|
224
|
+
appShellMore: DEFAULT_APP_SHELL_MORE_LABELS,
|
|
217
225
|
characterCount: DEFAULT_CHARACTER_COUNT_LABELS,
|
|
218
226
|
countrySelect: DEFAULT_COUNTRY_SELECT_LABELS,
|
|
219
227
|
inlineEdit: DEFAULT_INLINE_EDIT_LABELS,
|