@eifi1/ui-kit 0.51.6 → 0.52.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 +146 -26
- package/dist/account/account-parts.d.ts +10 -8
- package/dist/account/account-parts.js +1 -18
- package/dist/account/account-parts.js.map +1 -1
- package/dist/account/data-export-setting-labels.js +1 -1
- package/dist/account/data-export-setting-labels.js.map +1 -1
- package/dist/account/delete-account-setting-labels.js +1 -1
- package/dist/account/delete-account-setting-labels.js.map +1 -1
- package/dist/account/email-change-setting-labels.js +1 -1
- package/dist/account/email-change-setting-labels.js.map +1 -1
- package/dist/account/passkeys-setting.d.ts +9 -2
- package/dist/account/passkeys-setting.js +41 -29
- package/dist/account/passkeys-setting.js.map +1 -1
- package/dist/account/sessions-setting.d.ts +3 -2
- package/dist/account/sessions-setting.js +10 -8
- package/dist/account/sessions-setting.js.map +1 -1
- package/dist/admin/admin-action-confirm.js +3 -7
- package/dist/admin/admin-action-confirm.js.map +1 -1
- package/dist/admin/admin-parts.d.ts +6 -3
- package/dist/admin/admin-parts.js +6 -21
- package/dist/admin/admin-parts.js.map +1 -1
- package/dist/admin/mail-test-card-labels.js +1 -1
- package/dist/admin/mail-test-card-labels.js.map +1 -1
- package/dist/admin/plan-change-labels.d.ts +2 -2
- package/dist/admin/plan-change-labels.js +1 -17
- package/dist/admin/plan-change-labels.js.map +1 -1
- package/dist/admin/plan-change.d.ts +3 -42
- package/dist/admin/plan-change.js +1 -1
- package/dist/admin/plan-change.js.map +1 -1
- package/dist/admin/reviewer-scope-editor.js +3 -3
- package/dist/admin/reviewer-scope-editor.js.map +1 -1
- package/dist/auth/auth-errors-labels.d.ts +11 -0
- package/dist/auth/auth-errors-labels.js +13 -0
- package/dist/auth/auth-errors-labels.js.map +1 -0
- package/dist/auth/auth-errors.d.ts +7 -23
- package/dist/auth/auth-errors.js +2 -15
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/complete-name-dialog.d.ts +3 -2
- package/dist/auth/complete-name-dialog.js +3 -5
- package/dist/auth/complete-name-dialog.js.map +1 -1
- package/dist/auth/forgot-password-form-labels.js +1 -1
- package/dist/auth/forgot-password-form-labels.js.map +1 -1
- package/dist/auth/forgot-password-form.js +7 -2
- package/dist/auth/forgot-password-form.js.map +1 -1
- package/dist/auth/register-form-labels.js +1 -1
- package/dist/auth/register-form-labels.js.map +1 -1
- package/dist/auth/reset-password-form-labels.js +1 -1
- package/dist/auth/reset-password-form-labels.js.map +1 -1
- package/dist/auth/reset-password-form.js +5 -1
- package/dist/auth/reset-password-form.js.map +1 -1
- package/dist/auth/sign-in-form-labels.js +1 -1
- package/dist/auth/sign-in-form-labels.js.map +1 -1
- package/dist/auth/status-parts.d.ts +0 -3
- package/dist/auth/status-parts.js +0 -4
- package/dist/auth/status-parts.js.map +1 -1
- package/dist/auth/verify-email-labels.js +1 -1
- package/dist/auth/verify-email-labels.js.map +1 -1
- package/dist/auth/verify-email.js +7 -2
- package/dist/auth/verify-email.js.map +1 -1
- package/dist/billing/cancel-request.d.ts +11 -2
- package/dist/billing/cancel-request.js +15 -3
- package/dist/billing/cancel-request.js.map +1 -1
- package/dist/billing/cancel-subscription.d.ts +22 -10
- package/dist/billing/cancel-subscription.js +8 -11
- package/dist/billing/cancel-subscription.js.map +1 -1
- package/dist/billing/dialog-close.d.ts +29 -0
- package/dist/billing/dialog-close.js +8 -0
- package/dist/billing/dialog-close.js.map +1 -0
- package/dist/billing/plan-card.d.ts +14 -4
- package/dist/billing/plan-card.js +15 -8
- package/dist/billing/plan-card.js.map +1 -1
- package/dist/billing/plan-change-labels.d.ts +42 -0
- package/dist/billing/plan-change-labels.js +22 -0
- package/dist/billing/plan-change-labels.js.map +1 -0
- package/dist/billing/plan-switch.d.ts +21 -9
- package/dist/billing/plan-switch.js +10 -8
- package/dist/billing/plan-switch.js.map +1 -1
- package/dist/chart.d.ts +12 -0
- package/dist/chart.js +16 -1
- package/dist/chart.js.map +1 -1
- package/dist/components/account-chips.d.ts +5 -5
- package/dist/components/account-chips.js +11 -13
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/alert-banner.d.ts +16 -5
- package/dist/components/alert-banner.js +46 -1
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +22 -4
- package/dist/components/amount-input.js +3 -3
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.js +57 -65
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/bulk-action-bar.d.ts +12 -2
- package/dist/components/bulk-action-bar.js +65 -21
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button-look.d.ts +5 -5
- package/dist/components/button-look.js.map +1 -1
- package/dist/components/button.d.ts +2 -2
- package/dist/components/button.js.map +1 -1
- package/dist/components/calculator.d.ts +21 -2
- package/dist/components/calculator.js +53 -14
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/chart-edge.d.ts +16 -0
- package/dist/components/chart-edge.js +14 -1
- package/dist/components/chart-edge.js.map +1 -1
- package/dist/components/chart-figure.d.ts +13 -0
- package/dist/components/chart-figure.js +15 -0
- package/dist/components/chart-figure.js.map +1 -0
- package/dist/components/chart-zoom-core.js +1 -4
- package/dist/components/chart-zoom-core.js.map +1 -1
- package/dist/components/chart.d.ts +8 -1
- package/dist/components/chart.js +19 -10
- package/dist/components/chart.js.map +1 -1
- package/dist/components/combobox-core.d.ts +119 -7
- package/dist/components/combobox-core.js +151 -46
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +1 -1
- package/dist/components/combobox.js +142 -131
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/copy-button.d.ts +6 -5
- package/dist/components/copy-button.js +5 -3
- package/dist/components/copy-button.js.map +1 -1
- package/dist/components/country-select.js +2 -2
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/data-table-column-settings.d.ts +1 -1
- package/dist/components/data-table-column-settings.js +33 -7
- package/dist/components/data-table-column-settings.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +4 -2
- package/dist/components/data-table-filters.js +2 -2
- package/dist/components/data-table-filters.js.map +1 -1
- package/dist/components/data-table-fit.d.ts +6 -4
- package/dist/components/data-table-fit.js +4 -1
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-groups.d.ts +1 -1
- package/dist/components/data-table-groups.js.map +1 -1
- package/dist/components/data-table-head.d.ts +1 -1
- package/dist/components/data-table-head.js +15 -12
- package/dist/components/data-table-head.js.map +1 -1
- package/dist/components/data-table-mobile.d.ts +36 -7
- package/dist/components/data-table-mobile.js +63 -31
- package/dist/components/data-table-mobile.js.map +1 -1
- package/dist/components/data-table-pagination.js +11 -6
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table-resize.d.ts +1 -1
- package/dist/components/data-table-resize.js.map +1 -1
- package/dist/components/data-table-row-actions.d.ts +2 -2
- package/dist/components/data-table-row-actions.js.map +1 -1
- package/dist/components/data-table-row.d.ts +6 -2
- package/dist/components/data-table-row.js +17 -10
- package/dist/components/data-table-row.js.map +1 -1
- package/dist/components/data-table-selection.d.ts +1 -1
- package/dist/components/data-table-selection.js.map +1 -1
- package/dist/components/data-table-shared.d.ts +10 -2
- package/dist/components/data-table-shared.js +18 -0
- package/dist/components/data-table-shared.js.map +1 -1
- package/dist/components/data-table-sort.d.ts +21 -2
- package/dist/components/data-table-sort.js +24 -0
- package/dist/components/data-table-sort.js.map +1 -1
- package/dist/components/data-table-virtual.d.ts +1 -1
- package/dist/components/data-table-virtual.js +18 -6
- package/dist/components/data-table-virtual.js.map +1 -1
- package/dist/components/data-table.d.ts +25 -8
- package/dist/components/data-table.js +154 -25
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-field.d.ts +24 -2
- package/dist/components/date-field.js +33 -8
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.d.ts +15 -2
- package/dist/components/date-picker.js +55 -26
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.d.ts +47 -20
- package/dist/components/date-range-picker.js +23 -7
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +2 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/entity-combobox.js +4 -2
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/error-boundary.js +37 -30
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/{ui-labels.d.ts → field-base-labels.d.ts} +0 -2
- package/dist/components/{ui-labels.js → field-base-labels.js} +2 -9
- package/dist/components/field-base-labels.js.map +1 -0
- package/dist/components/field-base.d.ts +4 -3
- package/dist/components/field-base.js +3 -3
- package/dist/components/field-base.js.map +1 -1
- package/dist/components/field-sync-labels.d.ts +1 -0
- package/dist/components/field-sync-labels.js.map +1 -1
- package/dist/components/field-sync.d.ts +23 -1
- package/dist/components/field-sync.js.map +1 -1
- package/dist/components/form-actions.js +11 -5
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/hover-menu.d.ts +3 -0
- package/dist/components/hover-menu.js +5 -3
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/icon-button.js +14 -9
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/inline-confirm.d.ts +43 -0
- package/dist/components/inline-confirm.js +67 -0
- package/dist/components/inline-confirm.js.map +1 -0
- package/dist/components/inline-entity-combobox.d.ts +4 -3
- package/dist/components/inline-entity-combobox.js +150 -141
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/input.js +1 -1
- package/dist/components/input.js.map +1 -1
- package/dist/components/jump-calendar.js +28 -112
- package/dist/components/jump-calendar.js.map +1 -1
- package/dist/components/legal-page.d.ts +3 -1
- package/dist/components/legal-page.js +3 -2
- package/dist/components/legal-page.js.map +1 -1
- package/dist/components/legal.d.ts +4 -2
- package/dist/components/legal.js.map +1 -1
- package/dist/components/lightbox.d.ts +2 -2
- package/dist/components/lightbox.js +17 -6
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/list.d.ts +6 -2
- package/dist/components/list.js +4 -3
- package/dist/components/list.js.map +1 -1
- package/dist/components/measured-grid.d.ts +1 -1
- package/dist/components/measured-grid.js +2 -1
- package/dist/components/measured-grid.js.map +1 -1
- package/dist/components/mini-calendar.js +3 -5
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.d.ts +24 -0
- package/dist/components/modal.js +12 -4
- package/dist/components/modal.js.map +1 -1
- package/dist/components/money-draft.js +7 -5
- package/dist/components/money-draft.js.map +1 -1
- package/dist/components/money-field.d.ts +2 -2
- package/dist/components/money-field.js.map +1 -1
- package/dist/components/month-grid.d.ts +55 -0
- package/dist/components/month-grid.js +148 -0
- package/dist/components/month-grid.js.map +1 -0
- package/dist/components/month-picker.d.ts +36 -4
- package/dist/components/month-picker.js +123 -146
- package/dist/components/month-picker.js.map +1 -1
- 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 +2 -2
- package/dist/components/multi-select.js +11 -6
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-field.d.ts +6 -4
- package/dist/components/number-field.js +3 -2
- package/dist/components/number-field.js.map +1 -1
- package/dist/components/number-input.d.ts +4 -1
- package/dist/components/number-input.js +3 -2
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/picker-sheet.js +2 -1
- package/dist/components/picker-sheet.js.map +1 -1
- package/dist/components/pie-chart-labels.d.ts +7 -0
- package/dist/components/pie-chart-labels.js +1 -0
- package/dist/components/pie-chart-labels.js.map +1 -1
- package/dist/components/pie-chart.d.ts +5 -3
- package/dist/components/pie-chart.js +7 -22
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/popover.d.ts +3 -0
- package/dist/components/popover.js +7 -1
- package/dist/components/popover.js.map +1 -1
- package/dist/components/reauth-dialog.d.ts +4 -5
- package/dist/components/reauth-dialog.js +1 -4
- package/dist/components/reauth-dialog.js.map +1 -1
- package/dist/components/row-actions.js +2 -1
- package/dist/components/row-actions.js.map +1 -1
- package/dist/components/section-nav.d.ts +7 -0
- package/dist/components/section-nav.js.map +1 -1
- package/dist/components/series-chart-axes.d.ts +10 -3
- package/dist/components/series-chart-axes.js +1 -0
- package/dist/components/series-chart-axes.js.map +1 -1
- package/dist/components/series-chart-labels.d.ts +7 -4
- package/dist/components/series-chart-labels.js.map +1 -1
- package/dist/components/series-chart.d.ts +31 -7
- package/dist/components/series-chart.js +72 -29
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/share-card.js +3 -3
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/sign-chip-labels.d.ts +1 -0
- package/dist/components/sign-chip-labels.js.map +1 -1
- package/dist/components/sign-chip.d.ts +10 -1
- package/dist/components/sign-chip.js.map +1 -1
- package/dist/components/tabs-labels.d.ts +2 -0
- package/dist/components/tabs-labels.js +11 -0
- package/dist/components/tabs-labels.js.map +1 -0
- package/dist/components/tabs.d.ts +1 -1
- package/dist/components/tabs.js +13 -11
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/toggle-legend.d.ts +2 -2
- package/dist/components/toggle-legend.js +6 -6
- package/dist/components/toggle-legend.js.map +1 -1
- package/dist/components/translation-review-editor.d.ts +4 -2
- package/dist/components/translation-review-editor.js +2 -3
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review.d.ts +2 -1
- package/dist/components/translation-review.js +2 -2
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/treemap-labels.d.ts +26 -0
- package/dist/components/treemap-labels.js +10 -0
- package/dist/components/treemap-labels.js.map +1 -0
- package/dist/components/treemap-layout.d.ts +62 -0
- package/dist/components/treemap-layout.js +126 -0
- package/dist/components/treemap-layout.js.map +1 -0
- package/dist/components/treemap.d.ts +140 -17
- package/dist/components/treemap.js +324 -97
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/use-table-state.d.ts +5 -5
- package/dist/components/use-table-state.js +4 -1
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/data-table.d.ts +6 -2
- package/dist/data-table.js +7 -2
- package/dist/data-table.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/eslint/role-utilities.d.ts +36 -7
- package/dist/eslint/role-utilities.js +42 -9
- package/dist/eslint/role-utilities.js.map +1 -1
- package/dist/feedback/feedback-dialog.d.ts +25 -16
- package/dist/feedback/feedback-dialog.js +6 -2
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-mutation.d.ts +30 -0
- package/dist/feedback/feedback-mutation.js +16 -0
- package/dist/feedback/feedback-mutation.js.map +1 -0
- package/dist/feedback/feedback-page-link.d.ts +53 -0
- package/dist/feedback/feedback-page-link.js +37 -0
- package/dist/feedback/feedback-page-link.js.map +1 -0
- package/dist/feedback/feedback-public-list.d.ts +12 -3
- package/dist/feedback/feedback-public-list.js +2 -1
- package/dist/feedback/feedback-public-list.js.map +1 -1
- package/dist/feedback/feedback-replies.d.ts +3 -1
- package/dist/feedback/feedback-replies.js +5 -4
- package/dist/feedback/feedback-replies.js.map +1 -1
- package/dist/feedback/feedback-row-detail-labels.js +5 -0
- package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
- package/dist/feedback/feedback-row-detail.d.ts +64 -28
- package/dist/feedback/feedback-row-detail.js +30 -28
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-status-undo.d.ts +30 -11
- package/dist/feedback/feedback-status-undo.js +10 -15
- package/dist/feedback/feedback-status-undo.js.map +1 -1
- package/dist/feedback/feedback-submit-dialog.d.ts +1 -1
- package/dist/feedback/feedback-submit-dialog.js +1 -1
- package/dist/feedback/feedback-submit-dialog.js.map +1 -1
- package/dist/feedback/feedback-submit.js +9 -3
- package/dist/feedback/feedback-submit.js.map +1 -1
- package/dist/feedback/feedback-swipe.d.ts +1 -1
- package/dist/feedback/feedback-swipe.js.map +1 -1
- package/dist/feedback/feedback-table.d.ts +21 -9
- package/dist/feedback/feedback-table.js +45 -25
- package/dist/feedback/feedback-table.js.map +1 -1
- package/dist/feedback/feedback-thread-labels.d.ts +2 -2
- package/dist/feedback/feedback-thread-labels.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +24 -23
- package/dist/feedback/feedback-thread.js +2 -1
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +34 -0
- package/dist/feedback.js +42 -0
- package/dist/feedback.js.map +1 -1
- package/dist/hooks/use-dismiss.js.map +1 -1
- package/dist/hooks/use-focus-trap.d.ts +35 -0
- package/dist/hooks/use-focus-trap.js +6 -4
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-hotkey.d.ts +5 -2
- package/dist/hooks/use-hotkey.js +5 -4
- package/dist/hooks/use-hotkey.js.map +1 -1
- package/dist/hooks/use-long-press.d.ts +7 -4
- package/dist/hooks/use-long-press.js +3 -0
- package/dist/hooks/use-long-press.js.map +1 -1
- package/dist/hooks/use-media-query.js +12 -4
- package/dist/hooks/use-media-query.js.map +1 -1
- package/dist/hooks/use-mounted.d.ts +22 -0
- package/dist/hooks/use-mounted.js +24 -0
- package/dist/hooks/use-mounted.js.map +1 -0
- package/dist/hooks/use-overlay-history.d.ts +7 -1
- package/dist/hooks/use-overlay-history.js +35 -5
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.js +4 -5
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +7 -1
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +9 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +20 -41
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +7 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +20 -10
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +9 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +7 -1
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +8 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +5 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +64 -17
- package/dist/index.js +77 -12
- package/dist/index.js.map +1 -1
- package/dist/landing/routing.d.ts +3 -1
- package/dist/landing/routing.js +4 -7
- package/dist/landing/routing.js.map +1 -1
- package/dist/lib/broadcast.d.ts +17 -0
- package/dist/lib/broadcast.js +30 -0
- package/dist/lib/broadcast.js.map +1 -0
- package/dist/lib/calc.d.ts +7 -1
- package/dist/lib/calc.js +3 -1
- package/dist/lib/calc.js.map +1 -1
- package/dist/lib/clipboard-minus.d.ts +2 -2
- package/dist/lib/clipboard-minus.js +1 -1
- package/dist/lib/clipboard-minus.js.map +1 -1
- package/dist/lib/date-format.d.ts +37 -2
- package/dist/lib/date-format.js +34 -8
- package/dist/lib/date-format.js.map +1 -1
- package/dist/lib/day-format.d.ts +46 -0
- package/dist/lib/day-format.js +46 -0
- package/dist/lib/day-format.js.map +1 -0
- package/dist/lib/decimal-marks.d.ts +7 -1
- package/dist/lib/decimal-marks.js +5 -2
- package/dist/lib/decimal-marks.js.map +1 -1
- package/dist/lib/describe-failure.d.ts +14 -0
- package/dist/lib/describe-failure.js +9 -0
- package/dist/lib/describe-failure.js.map +1 -0
- package/dist/lib/direction.d.ts +16 -0
- package/dist/lib/direction.js +9 -1
- package/dist/lib/direction.js.map +1 -1
- package/dist/lib/focus-left.d.ts +63 -0
- package/dist/lib/focus-left.js +67 -0
- package/dist/lib/focus-left.js.map +1 -0
- package/dist/lib/format.d.ts +5 -3
- package/dist/lib/format.js +16 -13
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/http-status.d.ts +24 -0
- package/dist/lib/http-status.js +14 -0
- package/dist/lib/http-status.js.map +1 -0
- package/dist/lib/intl-cache.d.ts +14 -0
- package/dist/lib/intl-cache.js +15 -0
- package/dist/lib/intl-cache.js.map +1 -0
- package/dist/lib/isin.d.ts +10 -0
- package/dist/lib/isin.js.map +1 -1
- package/dist/lib/iso-day.d.ts +11 -0
- package/dist/lib/iso-day.js +8 -0
- package/dist/lib/iso-day.js.map +1 -0
- package/dist/lib/lazy-with-fallback.d.ts +31 -0
- package/dist/lib/lazy-with-fallback.js +40 -0
- package/dist/lib/lazy-with-fallback.js.map +1 -0
- package/dist/lib/path-pattern.d.ts +34 -0
- package/dist/lib/path-pattern.js +24 -0
- package/dist/lib/path-pattern.js.map +1 -0
- package/dist/lib/reduced-motion.d.ts +2 -1
- package/dist/lib/reduced-motion.js.map +1 -1
- package/dist/lib/round.d.ts +2 -1
- package/dist/lib/round.js +2 -1
- package/dist/lib/round.js.map +1 -1
- package/dist/lib/safe-storage.d.ts +24 -5
- package/dist/lib/safe-storage.js +27 -2
- package/dist/lib/safe-storage.js.map +1 -1
- package/dist/lib/session-refresh.js +1 -1
- package/dist/lib/session-refresh.js.map +1 -1
- package/dist/lib/share-format.d.ts +13 -0
- package/dist/lib/share-format.js +10 -0
- package/dist/lib/share-format.js.map +1 -0
- package/dist/lib/text-case.d.ts +17 -0
- package/dist/lib/text-case.js +8 -0
- package/dist/lib/text-case.js.map +1 -0
- package/dist/lib/text-match.d.ts +38 -0
- package/dist/lib/text-match.js +24 -2
- package/dist/lib/text-match.js.map +1 -1
- package/dist/lib/thenable.d.ts +13 -0
- package/dist/lib/thenable.js +8 -0
- package/dist/lib/thenable.js.map +1 -0
- package/dist/lib/translation-review.d.ts +7 -2
- package/dist/lib/translation-review.js +4 -4
- package/dist/lib/translation-review.js.map +1 -1
- package/dist/notifications/device-zone-report.js +1 -1
- package/dist/notifications/device-zone-report.js.map +1 -1
- package/dist/notifications/notification-bell.d.ts +2 -1
- package/dist/notifications/notification-bell.js +3 -3
- package/dist/notifications/notification-bell.js.map +1 -1
- package/dist/notifications/notification-inbox.d.ts +10 -6
- package/dist/notifications/notification-inbox.js +26 -48
- package/dist/notifications/notification-inbox.js.map +1 -1
- package/dist/notifications/notification-parts.d.ts +3 -2
- package/dist/notifications/notification-parts.js +1 -3
- package/dist/notifications/notification-parts.js.map +1 -1
- package/dist/notifications/notification-types-setting.js +1 -1
- package/dist/notifications/notification-types-setting.js.map +1 -1
- package/dist/notifications/notifications-labels.d.ts +6 -0
- package/dist/notifications/notifications-labels.js +1 -0
- package/dist/notifications/notifications-labels.js.map +1 -1
- package/dist/notifications/push-device-setting.js +1 -1
- package/dist/notifications/push-device-setting.js.map +1 -1
- package/dist/notifications/push-devices-setting.d.ts +2 -1
- package/dist/notifications/push-devices-setting.js +27 -49
- package/dist/notifications/push-devices-setting.js.map +1 -1
- package/dist/notifications/quiet-hours-setting.d.ts +10 -3
- package/dist/notifications/quiet-hours-setting.js +65 -26
- package/dist/notifications/quiet-hours-setting.js.map +1 -1
- package/dist/notifications/unsubscribe-panel.js +4 -7
- package/dist/notifications/unsubscribe-panel.js.map +1 -1
- package/dist/notifications/use-push-device.d.ts +39 -1
- package/dist/notifications/use-push-device.js +28 -7
- package/dist/notifications/use-push-device.js.map +1 -1
- package/dist/offline/query-persistence.d.ts +3 -1
- package/dist/offline/query-persistence.js +19 -2
- package/dist/offline/query-persistence.js.map +1 -1
- package/dist/rhf/fields.d.ts +11 -4
- package/dist/rhf/fields.js.map +1 -1
- package/dist/search/command-palette.js +1 -1
- package/dist/search/command-palette.js.map +1 -1
- package/dist/search/global-search.js +19 -9
- package/dist/search/global-search.js.map +1 -1
- package/dist/search/use-command-key.d.ts +12 -1
- package/dist/search/use-command-key.js +3 -12
- package/dist/search/use-command-key.js.map +1 -1
- package/dist/search.d.ts +7 -0
- package/dist/search.js +10 -0
- package/dist/search.js.map +1 -1
- package/dist/settings/use-settings-focus.js +1 -0
- package/dist/settings/use-settings-focus.js.map +1 -1
- package/dist/shell/account-menu-language.d.ts +21 -5
- package/dist/shell/account-menu-language.js +3 -1
- package/dist/shell/account-menu-language.js.map +1 -1
- package/dist/shell/account-menu-text-size.d.ts +26 -9
- package/dist/shell/account-menu-text-size.js +3 -2
- package/dist/shell/account-menu-text-size.js.map +1 -1
- package/dist/shell/dev-menu.js +5 -18
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/role-switcher.d.ts +7 -0
- package/dist/shell/role-switcher.js.map +1 -1
- package/dist/shell/top-bar-actions.d.ts +1 -1
- package/dist/shell/top-bar-actions.js.map +1 -1
- package/dist/shell/top-bar-parts-labels.d.ts +0 -2
- package/dist/shell/top-bar-parts-labels.js +0 -1
- package/dist/shell/top-bar-parts-labels.js.map +1 -1
- package/dist/shell.d.ts +27 -8
- package/dist/shell.js +28 -7
- package/dist/shell.js.map +1 -1
- package/dist/sync/engine.d.ts +30 -4
- package/dist/sync/engine.js +172 -52
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync.d.ts +6 -2
- package/dist/sync.js +6 -1
- package/dist/sync.js.map +1 -1
- package/dist/testing/css-variables.js +3 -8
- package/dist/testing/css-variables.js.map +1 -1
- package/dist/theme/contrast.d.ts +2 -1
- package/dist/theme/contrast.js +3 -8
- package/dist/theme/contrast.js.map +1 -1
- package/dist/theme/palette-store.js +6 -6
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/text-size.js +3 -8
- package/dist/theme/text-size.js.map +1 -1
- package/dist/theme/theme-store.js +3 -6
- package/dist/theme/theme-store.js.map +1 -1
- package/dist/tour/tour-catalogue.d.ts +7 -4
- package/dist/tour/tour-catalogue.js +12 -10
- package/dist/tour/tour-catalogue.js.map +1 -1
- package/dist/tour/tour-dock.d.ts +0 -2
- package/dist/tour/tour-dock.js +0 -2
- package/dist/tour/tour-dock.js.map +1 -1
- package/dist/tour/tour-gates.d.ts +4 -0
- package/dist/tour/tour-gates.js +14 -0
- package/dist/tour/tour-gates.js.map +1 -1
- package/dist/tour/tour-overlay.d.ts +27 -0
- package/dist/tour/tour-overlay.js +741 -0
- package/dist/tour/tour-overlay.js.map +1 -0
- package/dist/tour/tour.d.ts +16 -4
- package/dist/tour/tour.js +62 -778
- package/dist/tour/tour.js.map +1 -1
- package/dist/tour/use-tour-progress.js +1 -1
- package/dist/tour/use-tour-progress.js.map +1 -1
- package/dist/tour/use-tour-url-sync.js +2 -2
- package/dist/tour/use-tour-url-sync.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +5 -1
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard/types.d.ts +6 -2
- package/dist/wizard/types.js.map +1 -1
- package/dist/wizard/use-wizard.d.ts +3 -1
- package/dist/wizard/use-wizard.js.map +1 -1
- package/dist/wizard/validation.d.ts +3 -1
- package/dist/wizard/validation.js.map +1 -1
- package/package.json +12 -8
- package/src/account/account-parts.ts +5 -25
- package/src/account/data-export-setting-labels.ts +1 -1
- package/src/account/delete-account-setting-labels.ts +1 -1
- package/src/account/email-change-setting-labels.ts +1 -1
- package/src/account/passkeys-setting.tsx +60 -38
- package/src/account/sessions-setting.tsx +18 -12
- package/src/admin/admin-action-confirm.tsx +5 -10
- package/src/admin/admin-parts.ts +11 -25
- package/src/admin/mail-test-card-labels.ts +1 -1
- package/src/admin/plan-change-labels.ts +5 -23
- package/src/admin/plan-change.tsx +7 -44
- package/src/admin/reviewer-scope-editor.tsx +3 -3
- package/src/auth/auth-errors-labels.ts +23 -0
- package/src/auth/auth-errors.ts +11 -38
- package/src/auth/complete-name-dialog.tsx +9 -8
- package/src/auth/forgot-password-form-labels.ts +1 -1
- package/src/auth/forgot-password-form.tsx +11 -6
- package/src/auth/register-form-labels.ts +1 -1
- package/src/auth/reset-password-form-labels.ts +1 -1
- package/src/auth/reset-password-form.tsx +8 -4
- package/src/auth/sign-in-form-labels.ts +1 -1
- package/src/auth/status-parts.tsx +0 -6
- package/src/auth/verify-email-labels.ts +1 -1
- package/src/auth/verify-email.tsx +11 -6
- package/src/billing/cancel-request.ts +28 -6
- package/src/billing/cancel-subscription.tsx +29 -22
- package/src/billing/dialog-close.ts +34 -0
- package/src/billing/plan-card.tsx +36 -11
- package/src/billing/plan-change-labels.ts +66 -0
- package/src/billing/plan-switch.tsx +31 -20
- package/src/chart.ts +21 -3
- package/src/components/account-chips.tsx +20 -23
- package/src/components/alert-banner.tsx +82 -5
- package/src/components/amount-input.tsx +32 -14
- package/src/components/autocomplete.tsx +64 -70
- package/src/components/bulk-action-bar.tsx +70 -2
- package/src/components/button-look.ts +5 -5
- package/src/components/button.tsx +2 -2
- package/src/components/calculator.tsx +98 -17
- package/src/components/chart-edge.ts +34 -1
- package/src/components/chart-figure.tsx +35 -0
- package/src/components/chart-zoom-core.tsx +6 -5
- package/src/components/chart.tsx +26 -5
- package/src/components/combobox-core.tsx +303 -69
- package/src/components/combobox.tsx +184 -155
- package/src/components/copy-button.tsx +34 -23
- package/src/components/country-select.tsx +16 -11
- package/src/components/data-table-column-settings.tsx +52 -10
- package/src/components/data-table-filters.ts +6 -4
- package/src/components/data-table-fit.ts +19 -5
- package/src/components/data-table-groups.tsx +1 -1
- package/src/components/data-table-head.tsx +32 -22
- package/src/components/data-table-mobile.tsx +110 -27
- package/src/components/data-table-pagination.tsx +21 -6
- package/src/components/data-table-resize.ts +1 -1
- package/src/components/data-table-row-actions.tsx +3 -3
- package/src/components/data-table-row.tsx +25 -14
- package/src/components/data-table-selection.ts +1 -1
- package/src/components/data-table-shared.tsx +33 -1
- package/src/components/data-table-sort.ts +57 -2
- package/src/components/data-table-virtual.ts +32 -8
- package/src/components/data-table.tsx +267 -41
- package/src/components/date-field.tsx +65 -8
- package/src/components/date-picker.tsx +125 -48
- package/src/components/date-range-picker.tsx +82 -31
- package/src/components/dialog-frame.tsx +2 -1
- package/src/components/entity-combobox.tsx +4 -1
- package/src/components/error-boundary.tsx +53 -39
- package/src/components/field-base-labels.ts +20 -0
- package/src/components/field-base.tsx +13 -7
- package/src/components/field-sync-labels.ts +1 -0
- package/src/components/field-sync.tsx +23 -1
- package/src/components/form-actions.tsx +20 -5
- package/src/components/hover-menu.tsx +18 -8
- package/src/components/icon-button.tsx +14 -9
- package/src/components/inline-confirm.tsx +116 -0
- package/src/components/inline-entity-combobox.tsx +198 -152
- package/src/components/input.tsx +1 -1
- package/src/components/jump-calendar.tsx +30 -146
- package/src/components/legal-page.tsx +10 -7
- package/src/components/legal.tsx +4 -2
- package/src/components/lightbox.tsx +21 -8
- package/src/components/list.tsx +14 -5
- package/src/components/measured-grid.tsx +8 -4
- package/src/components/mini-calendar.tsx +6 -5
- package/src/components/modal.tsx +45 -4
- package/src/components/money-draft.ts +16 -5
- package/src/components/money-field.tsx +2 -2
- package/src/components/month-grid.tsx +229 -0
- package/src/components/month-picker.tsx +192 -200
- package/src/components/multi-entity-combobox.tsx +1 -0
- package/src/components/multi-select.tsx +21 -9
- package/src/components/number-field.tsx +14 -7
- package/src/components/number-input.tsx +9 -3
- package/src/components/numpad-sheet.tsx +4 -3
- package/src/components/picker-sheet.tsx +12 -9
- package/src/components/pie-chart-labels.ts +8 -0
- package/src/components/pie-chart.tsx +22 -28
- package/src/components/popover.tsx +18 -1
- package/src/components/reauth-dialog.tsx +6 -10
- package/src/components/row-actions.tsx +2 -1
- package/src/components/section-nav.tsx +7 -0
- package/src/components/series-chart-axes.ts +11 -3
- package/src/components/series-chart-labels.ts +7 -4
- package/src/components/series-chart.tsx +178 -69
- package/src/components/share-card.tsx +6 -6
- package/src/components/sign-chip-labels.ts +1 -0
- package/src/components/sign-chip.tsx +10 -1
- package/src/components/tabs-labels.ts +13 -0
- package/src/components/tabs.tsx +35 -19
- package/src/components/toggle-legend.tsx +16 -11
- package/src/components/translation-review-editor.tsx +6 -5
- package/src/components/translation-review.tsx +4 -3
- package/src/components/treemap-labels.ts +39 -0
- package/src/components/treemap-layout.ts +210 -0
- package/src/components/treemap.tsx +722 -133
- package/src/components/use-table-state.ts +12 -9
- package/src/data-table.ts +9 -2
- package/src/eslint/role-utilities.ts +97 -19
- package/src/feedback/feedback-dialog.tsx +30 -19
- package/src/feedback/feedback-mutation.ts +41 -0
- package/src/feedback/feedback-page-link.ts +90 -0
- package/src/feedback/feedback-public-list.tsx +17 -5
- package/src/feedback/feedback-replies.tsx +13 -6
- package/src/feedback/feedback-row-detail-labels.ts +5 -0
- package/src/feedback/feedback-row-detail.tsx +103 -67
- package/src/feedback/feedback-status-undo.ts +41 -27
- package/src/feedback/feedback-submit-dialog.tsx +2 -2
- package/src/feedback/feedback-submit.tsx +21 -7
- package/src/feedback/feedback-swipe.tsx +1 -1
- package/src/feedback/feedback-table.tsx +86 -38
- package/src/feedback/feedback-thread-labels.ts +2 -2
- package/src/feedback/feedback-thread.tsx +27 -25
- package/src/feedback.ts +42 -0
- package/src/hooks/use-dismiss.ts +3 -2
- package/src/hooks/use-focus-trap.ts +8 -24
- package/src/hooks/use-hotkey.ts +24 -7
- package/src/hooks/use-long-press.ts +16 -2
- package/src/hooks/use-media-query.ts +20 -4
- package/src/hooks/use-mounted.ts +39 -0
- package/src/hooks/use-overlay-history.ts +70 -5
- package/src/i18n/defaults.ts +4 -5
- package/src/i18n/german.ts +8 -2
- package/src/i18n/kit-labels.tsx +9 -2
- package/src/i18n/locales/es.ts +8 -2
- package/src/i18n/locales/fr.ts +21 -13
- package/src/i18n/locales/hu.ts +10 -2
- package/src/i18n/locales/it.ts +8 -2
- package/src/i18n/locales/zh.ts +9 -2
- package/src/i18n/review.ts +5 -0
- package/src/index.ts +103 -13
- package/src/landing/routing.tsx +14 -10
- package/src/lib/broadcast.ts +52 -0
- package/src/lib/calc.ts +13 -2
- package/src/lib/clipboard-minus.ts +14 -4
- package/src/lib/date-format.ts +89 -13
- package/src/lib/day-format.ts +96 -0
- package/src/lib/decimal-marks.ts +12 -3
- package/src/lib/describe-failure.ts +18 -0
- package/src/lib/direction.ts +39 -0
- package/src/lib/focus-left.ts +156 -0
- package/src/lib/format.ts +34 -19
- package/src/lib/http-status.ts +38 -0
- package/src/lib/intl-cache.ts +25 -0
- package/src/lib/isin.ts +10 -0
- package/src/lib/iso-day.ts +13 -0
- package/src/lib/lazy-with-fallback.ts +82 -0
- package/src/lib/path-pattern.ts +55 -0
- package/src/lib/reduced-motion.ts +2 -1
- package/src/lib/round.ts +7 -2
- package/src/lib/safe-storage.ts +48 -6
- package/src/lib/session-refresh.ts +1 -1
- package/src/lib/share-format.ts +18 -0
- package/src/lib/text-case.ts +19 -0
- package/src/lib/text-match.ts +69 -2
- package/src/lib/thenable.ts +19 -0
- package/src/lib/translation-review.ts +13 -5
- package/src/notifications/device-zone-report.ts +1 -1
- package/src/notifications/notification-bell.tsx +7 -4
- package/src/notifications/notification-inbox.tsx +40 -58
- package/src/notifications/notification-parts.tsx +3 -4
- package/src/notifications/notification-types-setting.tsx +1 -1
- package/src/notifications/notifications-labels.ts +7 -0
- package/src/notifications/push-device-setting.tsx +1 -1
- package/src/notifications/push-devices-setting.tsx +30 -55
- package/src/notifications/quiet-hours-setting.tsx +93 -31
- package/src/notifications/unsubscribe-panel.tsx +4 -7
- package/src/notifications/use-push-device.ts +76 -10
- package/src/offline/query-persistence.ts +35 -3
- package/src/rhf/fields.tsx +11 -4
- package/src/search/command-palette.tsx +2 -4
- package/src/search/global-search.tsx +36 -15
- package/src/search/use-command-key.ts +13 -12
- package/src/search.ts +9 -0
- package/src/settings/use-settings-focus.ts +3 -0
- package/src/shell/account-menu-language.tsx +27 -5
- package/src/shell/account-menu-text-size.tsx +32 -10
- package/src/shell/dev-menu.tsx +7 -21
- package/src/shell/role-switcher.tsx +7 -0
- package/src/shell/top-bar-actions.tsx +1 -1
- package/src/shell/top-bar-parts-labels.ts +0 -3
- package/src/shell.ts +40 -9
- package/src/sync/engine.ts +339 -61
- package/src/sync.ts +8 -1
- package/src/testing/css-variables.ts +8 -9
- package/src/theme/contrast.ts +8 -9
- package/src/theme/palette-store.ts +9 -9
- package/src/theme/text-size.ts +6 -8
- package/src/theme/theme-store.ts +7 -9
- package/src/tour/tour-catalogue.tsx +26 -15
- package/src/tour/tour-dock.ts +0 -2
- package/src/tour/tour-gates.ts +23 -0
- package/src/tour/tour-overlay.tsx +1170 -0
- package/src/tour/tour.tsx +116 -1193
- package/src/tour/use-tour-progress.ts +1 -1
- package/src/tour/use-tour-url-sync.ts +7 -3
- package/src/wizard/stepper-nav.tsx +3 -1
- package/src/wizard/types.ts +11 -2
- package/src/wizard/use-wizard.ts +2 -1
- package/src/wizard/validation.ts +8 -2
- package/tokens.css +2 -1
- package/dist/components/ui-labels.js.map +0 -1
- package/dist/shell/dev-switchers.d.ts +0 -6
- package/dist/shell/dev-switchers.js +0 -12
- package/dist/shell/dev-switchers.js.map +0 -1
- package/src/components/ui-labels.ts +0 -24
- package/src/shell/dev-switchers.tsx +0 -18
|
@@ -8,6 +8,7 @@ import { useRangeSelection } from "./data-table-selection";
|
|
|
8
8
|
import { columnLabel, logicalAlign, resolveDataTableLabels } from "./data-table-shared";
|
|
9
9
|
import {
|
|
10
10
|
MobileFilters,
|
|
11
|
+
MobileLeadingRow,
|
|
11
12
|
MobileSelectBar,
|
|
12
13
|
MobileSort,
|
|
13
14
|
StackedFields,
|
|
@@ -41,8 +42,9 @@ import { ColumnSettingsPanel } from "./data-table-column-settings";
|
|
|
41
42
|
import { useLargeText } from "../hooks/use-large-text";
|
|
42
43
|
import { cn } from "../lib/cn";
|
|
43
44
|
import { isFilterActive, resolveFilter, rowMatches } from "./data-table-filters";
|
|
45
|
+
import { matchesSearch, searchWords } from "../lib/text-match";
|
|
44
46
|
import type { ColumnFilter, FilterValue } from "./data-table-filters";
|
|
45
|
-
import { nextSorts } from "./data-table-sort";
|
|
47
|
+
import { compareSortValues, nextSorts } from "./data-table-sort";
|
|
46
48
|
import type { SortCycle, SortDir, SortState } from "./data-table-sort";
|
|
47
49
|
import { Pagination } from "./data-table-pagination";
|
|
48
50
|
import type { SwipeAction } from "./swipeable-row";
|
|
@@ -60,6 +62,7 @@ import {
|
|
|
60
62
|
} from "../i18n/kit-labels";
|
|
61
63
|
import { useEdgeFade } from "../lib/strip-fade";
|
|
62
64
|
import { dirOf, type Direction } from "../lib/direction";
|
|
65
|
+
import { focusContainer, focusFirst, focusIsLost, tabStops, whenFocusLeftForNothing } from "../lib/focus-left";
|
|
63
66
|
|
|
64
67
|
// ---------- Types ----------
|
|
65
68
|
|
|
@@ -67,6 +70,11 @@ export interface DataTableColumn<T> {
|
|
|
67
70
|
key: string;
|
|
68
71
|
header: ReactNode;
|
|
69
72
|
cell: (row: T) => ReactNode;
|
|
73
|
+
/** What a client sort orders the column by. Strings collate in the table's `locale`
|
|
74
|
+
* (digits as numbers, case and accents left out; 0.51.7, audit 2026-10-30 DSP-3),
|
|
75
|
+
* numbers compare as numbers and sort before strings, `null` and `undefined` sort
|
|
76
|
+
* last in either direction. The order is `compareSortValues`, exported for an app's
|
|
77
|
+
* own list beside the table (0.52). */
|
|
70
78
|
sortBy?: (row: T) => string | number | null | undefined;
|
|
71
79
|
filter?: ColumnFilter<T>;
|
|
72
80
|
filterBy?: (row: T) => string;
|
|
@@ -261,8 +269,11 @@ export interface ServerPagination {
|
|
|
261
269
|
}
|
|
262
270
|
|
|
263
271
|
export interface DataTableProps<T> {
|
|
264
|
-
|
|
265
|
-
|
|
272
|
+
/** `readonly` since 0.52 (refactor audit 2026-10-30, API-7): the table never changes the
|
|
273
|
+
* arrays it is handed, so a caller's `as const` list or a query's frozen result needs no
|
|
274
|
+
* copy. Only widens: a mutable array is still one. The same for `columns` and `sorts`. */
|
|
275
|
+
rows: readonly T[];
|
|
276
|
+
columns: readonly DataTableColumn<T>[];
|
|
266
277
|
rowKey: (row: T) => string | number;
|
|
267
278
|
defaultPageSize?: number;
|
|
268
279
|
onRowClick?: (row: T) => void;
|
|
@@ -284,6 +295,11 @@ export interface DataTableProps<T> {
|
|
|
284
295
|
* not wrap table cells, and the absolutely-positioned row overlay that is the
|
|
285
296
|
* usual workaround would sit on top of the per-cell controls these rows carry
|
|
286
297
|
* (status toggles, the selection checkbox, nested links) and swallow them.
|
|
298
|
+
*
|
|
299
|
+
* With `onRowClick` a plain click opens the row through it, in place. Without one
|
|
300
|
+
* (0.52, refactor audit 2026-10-30, DSP-23 b) the click follows the link — through the
|
|
301
|
+
* provider's `linkComponent` for an in-app path, as every kit link — and the phone
|
|
302
|
+
* card is that link too; before, the click was cancelled and opened nothing.
|
|
287
303
|
*/
|
|
288
304
|
rowHref?: (row: T) => string | undefined;
|
|
289
305
|
expandedRow?: (row: T) => ReactNode | null;
|
|
@@ -437,7 +453,7 @@ export interface DataTableProps<T> {
|
|
|
437
453
|
*/
|
|
438
454
|
filters?: FilterState;
|
|
439
455
|
onFiltersChange?: (next: FilterState) => void;
|
|
440
|
-
sorts?: SortState[];
|
|
456
|
+
sorts?: readonly SortState[];
|
|
441
457
|
onSortsChange?: (next: SortState[]) => void;
|
|
442
458
|
/**
|
|
443
459
|
* Controlled page size, as `sorts` above: the table pages by it and hands its pager's
|
|
@@ -618,8 +634,10 @@ export interface DataTableProps<T> {
|
|
|
618
634
|
*/
|
|
619
635
|
desktopSwipeActions?: boolean | DataTableDesktopSwipeActions<T>;
|
|
620
636
|
/**
|
|
621
|
-
* Renders as a full-width row above the data rows in the desktop table
|
|
622
|
-
*
|
|
637
|
+
* Renders as a full-width row above the data rows in the desktop table, and since
|
|
638
|
+
* 0.51.7 as the first item of the phone's card list (audit 2026-10-30 DSP-2: the card
|
|
639
|
+
* list dropped it, and kastlan's inline "Add meter" editor never appeared on a phone).
|
|
640
|
+
* On the phone it is no card: no row link, swipe or selection toggle. For a
|
|
623
641
|
* toggle that shows/hides a slice of rows, style it as an expand/collapse
|
|
624
642
|
* disclosure (chevron + label) so it reads as part of the table rather
|
|
625
643
|
* than a floating control above it. See feedback #10/#11 (transactions'
|
|
@@ -629,9 +647,11 @@ export interface DataTableProps<T> {
|
|
|
629
647
|
/**
|
|
630
648
|
* 0.48 (keksdose dev #603: "it should rather be sticky, so the user can show hide them
|
|
631
649
|
* everywhere on click"): pin the {@link leadingRow} under the sticky header while the
|
|
632
|
-
* rows scroll beneath both — its `top` is the header's measured height.
|
|
633
|
-
*
|
|
634
|
-
*
|
|
650
|
+
* rows scroll beneath both — its `top` is the header's measured height. It sticks
|
|
651
|
+
* within the table's own scroller (a bounded body: `fillHeight` or `maxBodyHeight`).
|
|
652
|
+
* On a phone (0.51.7) it is pinned at the top of the card list's scroller (the list
|
|
653
|
+
* under a bounded `fillHeight`, else the page), with `mobileGroupBy`'s section headers
|
|
654
|
+
* under it. Default: it scrolls with the rows.
|
|
635
655
|
*/
|
|
636
656
|
leadingRowSticky?: boolean;
|
|
637
657
|
/**
|
|
@@ -922,6 +942,28 @@ export interface DataTableDesktopSwipeActions<T> {
|
|
|
922
942
|
*/
|
|
923
943
|
const FOOTER_CELL = "sticky bottom-0 z-10 bg-surface-2 shadow-[inset_0_2px_0_var(--border-strong)]";
|
|
924
944
|
|
|
945
|
+
/** Where focus that leaves a row is still the row's (DSP-4): an overlay — a confirm, a
|
|
946
|
+
* menu, a sheet — hands it back or closes with the row it was about. The kit marks its
|
|
947
|
+
* own (`data-kit-layer`); an app's dialog says what it is. */
|
|
948
|
+
const OVERLAY_SELECTOR = '[data-kit-layer],[role="dialog"],[role="alertdialog"],[aria-modal="true"],[role="menu"]';
|
|
949
|
+
|
|
950
|
+
/** `rows`' places by `rowKey`, the first row of a key winning as a `findIndex`'s did; the
|
|
951
|
+
* map built at the first lookup (0.52 code review, data-table.tsx). */
|
|
952
|
+
function keyIndex<T>(rows: readonly T[], rowKey: (row: T) => string | number): (key: string | number) => number {
|
|
953
|
+
let at: Map<string | number, number> | null = null;
|
|
954
|
+
return (key) => {
|
|
955
|
+
if (!at) {
|
|
956
|
+
at = new Map();
|
|
957
|
+
for (let i = rows.length - 1; i >= 0; i--) at.set(rowKey(rows[i]), i);
|
|
958
|
+
}
|
|
959
|
+
return at.get(key) ?? -1;
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/** How long a filter's "n of m rows" waits for the typing to pause (DSP-23 d): longer than
|
|
964
|
+
* the gap between two keystrokes, short enough to answer the word just typed. */
|
|
965
|
+
const FILTER_ANNOUNCE_DELAY_MS = 500;
|
|
966
|
+
|
|
925
967
|
// ---------- Phone sort control (keksdose K10) ----------
|
|
926
968
|
|
|
927
969
|
/**
|
|
@@ -968,6 +1010,21 @@ import { DEFAULT_PERSIST_PREFIX, useTableState, type TableUrlSync } from "./use-
|
|
|
968
1010
|
import { useMobileReveal } from "./use-mobile-reveal";
|
|
969
1011
|
import { GROW_CELL_CLASS, GROW_PEER_CELL_CLASS, useColumnFit } from "./data-table-fit";
|
|
970
1012
|
|
|
1013
|
+
/**
|
|
1014
|
+
* rowMatches for one column's filter state, the text filter's query folded once (0.52
|
|
1015
|
+
* code review, data-table-filters.ts): folded again for every row it tested, a 5000-row
|
|
1016
|
+
* table folded the same query 5000 times per keystroke. Module-private: data-table-filters
|
|
1017
|
+
* is re-exported whole by @eifi1/ui-kit/data-table, and this is no public API.
|
|
1018
|
+
*/
|
|
1019
|
+
function rowMatcher<T>(col: DataTableColumn<T>, state: FilterValue, locale?: string): (row: T) => boolean {
|
|
1020
|
+
const filter = resolveFilter(col);
|
|
1021
|
+
if (filter?.type === "text" && state.type === "text" && state.q.trim()) {
|
|
1022
|
+
const words = searchWords(state.q, locale);
|
|
1023
|
+
return (row) => matchesSearch(words, [filter.getValue(row)], locale);
|
|
1024
|
+
}
|
|
1025
|
+
return (row) => rowMatches(col, row, state, locale);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
971
1028
|
export function DataTable<T>({
|
|
972
1029
|
rows,
|
|
973
1030
|
columns: columnsProp,
|
|
@@ -1108,13 +1165,15 @@ export function DataTable<T>({
|
|
|
1108
1165
|
// (a drag or "Auto-size columns" before it grew, KS N2) is ignored, and it has no
|
|
1109
1166
|
// handle, so it can never pin it again. Ignored rather than deleted from storage, as
|
|
1110
1167
|
// the widths above; the next resize or auto-size writes a blob without it.
|
|
1168
|
+
// Keyed on the `grow` column's key, not the columns array: an inline `columns={…}`
|
|
1169
|
+
// gave every render new widths, and the fit measured the table for it (DSP-19).
|
|
1170
|
+
const growKey = columns.find((c) => c.grow)?.key;
|
|
1111
1171
|
const widths = useMemo(() => {
|
|
1112
1172
|
if (!resizable) return {};
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
const { [grow]: _ignored, ...rest } = storedWidths;
|
|
1173
|
+
if (!growKey || !(growKey in storedWidths)) return storedWidths;
|
|
1174
|
+
const { [growKey]: _ignored, ...rest } = storedWidths;
|
|
1116
1175
|
return rest;
|
|
1117
|
-
}, [resizable, storedWidths,
|
|
1176
|
+
}, [resizable, storedWidths, growKey]);
|
|
1118
1177
|
const hiddenCols = useMemo(
|
|
1119
1178
|
() => (columnSettings ? storedHiddenCols : new Set<string>()),
|
|
1120
1179
|
[columnSettings, storedHiddenCols],
|
|
@@ -1159,13 +1218,13 @@ export function DataTable<T>({
|
|
|
1159
1218
|
if (v && !seen.has(v)) seen.add(v);
|
|
1160
1219
|
}
|
|
1161
1220
|
map[col.key] = Array.from(seen)
|
|
1162
|
-
.sort()
|
|
1221
|
+
.sort((a, b) => compareSortValues(a, b, locale))
|
|
1163
1222
|
.map((v) => ({ value: v, label: v }));
|
|
1164
1223
|
}
|
|
1165
1224
|
return map;
|
|
1166
1225
|
// `columns` by signature — see the note above the signatures.
|
|
1167
1226
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1168
|
-
}, [columnSig, selectOptionsSig, rows]);
|
|
1227
|
+
}, [columnSig, selectOptionsSig, rows, locale]);
|
|
1169
1228
|
|
|
1170
1229
|
const filtered = useMemo(() => {
|
|
1171
1230
|
if (serverRows) return rows;
|
|
@@ -1173,7 +1232,8 @@ export function DataTable<T>({
|
|
|
1173
1232
|
for (const col of columns) {
|
|
1174
1233
|
const state = filters[col.key];
|
|
1175
1234
|
if (!state || !isFilterActive(state)) continue;
|
|
1176
|
-
|
|
1235
|
+
// One matcher per filter, its query folded once (0.52 code review, data-table-filters.ts).
|
|
1236
|
+
result = result.filter(rowMatcher(col, state, locale));
|
|
1177
1237
|
}
|
|
1178
1238
|
return result;
|
|
1179
1239
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -1198,14 +1258,16 @@ export function DataTable<T>({
|
|
|
1198
1258
|
if (av == null && bv == null) continue;
|
|
1199
1259
|
if (av == null) return 1;
|
|
1200
1260
|
if (bv == null) return -1;
|
|
1201
|
-
|
|
1202
|
-
|
|
1261
|
+
// The order `compareSortValues` exports (0.52): one rule, here and in an app's
|
|
1262
|
+
// own list beside the table. Nulls are last above, in either direction.
|
|
1263
|
+
const order = compareSortValues(av, bv, locale);
|
|
1264
|
+
if (order !== 0) return dir === "asc" ? order : -order;
|
|
1203
1265
|
}
|
|
1204
1266
|
return 0;
|
|
1205
1267
|
});
|
|
1206
1268
|
return copy;
|
|
1207
1269
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1208
|
-
}, [filtered, sorts, columnSig, serverRows]);
|
|
1270
|
+
}, [filtered, sorts, columnSig, serverRows, locale]);
|
|
1209
1271
|
|
|
1210
1272
|
// `paginated={false}` is expressed as "page size = everything" rather than as a
|
|
1211
1273
|
// second code path, so slicing, the page clamp and the range summary all keep
|
|
@@ -1224,10 +1286,16 @@ export function DataTable<T>({
|
|
|
1224
1286
|
const safePage = isServer
|
|
1225
1287
|
? Math.min(Math.max(0, serverPagination!.page), totalPages - 1)
|
|
1226
1288
|
: Math.min(page, totalPages - 1);
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1289
|
+
// Memoised (refactor audit 2026-10-30, DSP-19): the fit, the rows' window and the
|
|
1290
|
+
// range selection compare the page's rows by identity, and a fresh `slice(…)` on every
|
|
1291
|
+
// render of a paginated table — the default — had the fit lay the whole table out on a
|
|
1292
|
+
// ticked box, a keystroke, any parent render.
|
|
1293
|
+
const wholeList = isServer || unpaged || pageSize === Infinity;
|
|
1294
|
+
const slice = useMemo(
|
|
1295
|
+
() =>
|
|
1296
|
+
wholeList ? sorted : sorted.slice(safePage * effectivePageSize, safePage * effectivePageSize + effectivePageSize),
|
|
1297
|
+
[wholeList, sorted, safePage, effectivePageSize],
|
|
1298
|
+
);
|
|
1231
1299
|
|
|
1232
1300
|
const toggleSort = (key: string, shiftKey: boolean) => {
|
|
1233
1301
|
const col = columns.find((c) => c.key === key);
|
|
@@ -1320,6 +1388,16 @@ export function DataTable<T>({
|
|
|
1320
1388
|
// Seeded with the mount value: a live region that speaks on first paint talks over
|
|
1321
1389
|
// the page the user has just opened, and every table on that page does it at once.
|
|
1322
1390
|
const announcedFilterKey = useRef(filterKey);
|
|
1391
|
+
// Spoken once the typing pauses (refactor audit 2026-10-30, DSP-23 d): every keystroke
|
|
1392
|
+
// in a text filter is a new filter, and "12 of 137 rows" on each one — through the live
|
|
1393
|
+
// region's 50 ms reset — talked over the very letters being typed. The count is read
|
|
1394
|
+
// when the sentence goes out, so it is the rows the pause left on screen.
|
|
1395
|
+
const filterSpeech = useRef({ shown: filtered.length, total: rows.length, labels });
|
|
1396
|
+
useLayoutEffect(() => {
|
|
1397
|
+
filterSpeech.current = { shown: filtered.length, total: rows.length, labels };
|
|
1398
|
+
});
|
|
1399
|
+
const filterTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
|
1400
|
+
useEffect(() => () => clearTimeout(filterTimer.current), []);
|
|
1323
1401
|
useEffect(() => {
|
|
1324
1402
|
if (announcedFilterKey.current === filterKey) return;
|
|
1325
1403
|
announcedFilterKey.current = filterKey;
|
|
@@ -1328,8 +1406,12 @@ export function DataTable<T>({
|
|
|
1328
1406
|
// filtered total — so the "n of m" sentence has no second number to give here.
|
|
1329
1407
|
// Saying nothing is better than announcing the page size as a result count.
|
|
1330
1408
|
if (serverRows) return;
|
|
1331
|
-
|
|
1332
|
-
|
|
1409
|
+
clearTimeout(filterTimer.current);
|
|
1410
|
+
filterTimer.current = setTimeout(() => {
|
|
1411
|
+
const { shown, total, labels: words } = filterSpeech.current;
|
|
1412
|
+
announce(words.filterResults(shown, total));
|
|
1413
|
+
}, FILTER_ANNOUNCE_DELAY_MS);
|
|
1414
|
+
}, [filterKey, serverRows, announce]);
|
|
1333
1415
|
|
|
1334
1416
|
// 1-based, because that is what the page strip shows and what a person says.
|
|
1335
1417
|
const goToPage = (p: number) => {
|
|
@@ -1348,8 +1430,11 @@ export function DataTable<T>({
|
|
|
1348
1430
|
headRefs,
|
|
1349
1431
|
scroller: () => desktopScroller.current,
|
|
1350
1432
|
enabled: !usePhoneLayout(),
|
|
1351
|
-
// Measured only when one of these changed (0.48.2): not on a ticked box.
|
|
1352
|
-
|
|
1433
|
+
// Measured only when one of these changed (0.48.2): not on a ticked box. The columns
|
|
1434
|
+
// by their keys (DSP-19): an inline `columns={…}` is a new array every render. The
|
|
1435
|
+
// locale (0.52 code review, data-table.tsx): the cells' dates, numbers and the kit's
|
|
1436
|
+
// words follow it under the same rows and keys; the fit adds the headers' drawn text.
|
|
1437
|
+
content: [slice, columnSig, hiddenCols, widths, density, large, locale],
|
|
1353
1438
|
});
|
|
1354
1439
|
const visibleColumns = useMemo(
|
|
1355
1440
|
() => columns.filter((c) => !hiddenCols.has(c.key) && !autoHidden.has(c.key)),
|
|
@@ -1404,7 +1489,10 @@ export function DataTable<T>({
|
|
|
1404
1489
|
const footerLabelCol = showFooter
|
|
1405
1490
|
? (visibleColumns.find((c) => !c.footer && !isTableOwnColumn(c.key)) ?? visibleColumns[0])
|
|
1406
1491
|
: undefined;
|
|
1407
|
-
|
|
1492
|
+
// `footer` keeps its `T[]` parameters: narrowed to `readonly`, a caller's footer typed
|
|
1493
|
+
// `(rows: Row[]) => …` would no longer fit (API-7 only widens). The table hands over the
|
|
1494
|
+
// arrays it holds, as before, and changes neither.
|
|
1495
|
+
const footerValue = (col: DataTableColumn<T>) => col.footer?.(sorted as T[], slice as T[]);
|
|
1408
1496
|
const footerHeadingId = useId();
|
|
1409
1497
|
// Each open row's detail row, for its disclosure button's `aria-controls`.
|
|
1410
1498
|
const detailIdBase = useId();
|
|
@@ -1541,10 +1629,14 @@ export function DataTable<T>({
|
|
|
1541
1629
|
if (el.parentElement) ro.observe(el.parentElement);
|
|
1542
1630
|
return () => ro.disconnect();
|
|
1543
1631
|
}, [phoneFill]);
|
|
1632
|
+
// A sticky `leadingRow`'s height on a phone (audit 2026-10-30 DSP-2): the section
|
|
1633
|
+
// headers stick under it, as the desktop's group bands stick under the desktop row.
|
|
1634
|
+
const [phoneLeadHeight, setPhoneLeadHeight] = useState(0);
|
|
1544
1635
|
|
|
1545
1636
|
const { mobileSlice, canRevealMoreMobile, loadMoreRef } = useMobileReveal({
|
|
1546
|
-
|
|
1547
|
-
|
|
1637
|
+
// Read only there; its `T[]` widens to `readonly T[]` with its owner (API-7).
|
|
1638
|
+
rows: sorted as T[],
|
|
1639
|
+
slice: slice as T[],
|
|
1548
1640
|
isServer,
|
|
1549
1641
|
isMdUp,
|
|
1550
1642
|
unpaged,
|
|
@@ -1594,12 +1686,18 @@ export function DataTable<T>({
|
|
|
1594
1686
|
// the pager.
|
|
1595
1687
|
const rowsFocusable = !!onRowClick;
|
|
1596
1688
|
const [focusRowKey, setFocusRowKey] = useState<string | number | null>(null);
|
|
1689
|
+
// The rows' places by key (0.52 code review, data-table.tsx): the tab stop's check
|
|
1690
|
+
// below, the focus note and its recovery each walked the rows calling `rowKey` — on
|
|
1691
|
+
// every render, at each focus, in every commit while a row was noted: under
|
|
1692
|
+
// `virtualize`, 3000 rows, ~15000 calls per arrow step at the table's end. Built at the
|
|
1693
|
+
// first lookup, once per array, so a table nobody focuses builds none. Keyed on the
|
|
1694
|
+
// rows alone: `rowKey` is a pure function of its row, and a call site writes it inline.
|
|
1695
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1696
|
+
const sliceIndex = useMemo(() => keyIndex(slice, rowKey), [slice]);
|
|
1697
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1698
|
+
const mobileIndex = useMemo(() => keyIndex(mobileSlice, rowKey), [mobileSlice]);
|
|
1597
1699
|
const tabRowKey =
|
|
1598
|
-
focusRowKey !== null &&
|
|
1599
|
-
? focusRowKey
|
|
1600
|
-
: slice.length
|
|
1601
|
-
? rowKey(slice[0])
|
|
1602
|
-
: null;
|
|
1700
|
+
focusRowKey !== null && sliceIndex(focusRowKey) !== -1 ? focusRowKey : slice.length ? rowKey(slice[0]) : null;
|
|
1603
1701
|
|
|
1604
1702
|
// What the memoised rows' handlers read at event time (0.48.2, K-052-2): the latest
|
|
1605
1703
|
// props, refreshed every commit, so a row that bailed out of a render still toggles
|
|
@@ -1608,7 +1706,38 @@ export function DataTable<T>({
|
|
|
1608
1706
|
// move over every row, rendered or not: the target is rendered, then focused.
|
|
1609
1707
|
const virtualOn = !!virtualize && isMdUp && slice.length > 0;
|
|
1610
1708
|
const focusRowRef = useRef<((index: number) => void) | undefined>(undefined);
|
|
1709
|
+
// ---- When the focused row leaves (refactor audit 2026-10-30, DSP-4) ----
|
|
1710
|
+
// The row holding the focus — its key, and where it stood — noted as the focus comes
|
|
1711
|
+
// into it (the rows report it, through React, so a menu or a dialog a row opened in a
|
|
1712
|
+
// portal is the row's too). A delete, a status change that filters the row out, an
|
|
1713
|
+
// approval: the row's DOM goes, the focus with it to <body>, and the commit that took it
|
|
1714
|
+
// puts the focus on the row now in its place (below).
|
|
1715
|
+
const heldRow = useRef<{ key: string | number; index: number } | null>(null);
|
|
1716
|
+
const noteRowFocus = (key: string | number) => {
|
|
1717
|
+
heldRow.current = { key, index: (isMdUp ? sliceIndex : mobileIndex)(key) };
|
|
1718
|
+
};
|
|
1719
|
+
// A gone row's note waiting for the overlay that holds the focus (below): watched as
|
|
1720
|
+
// a node until it leaves the page, since its close need not render the table.
|
|
1721
|
+
const overlayWatch = useRef<{ layer: Element; stop: () => void } | null>(null);
|
|
1722
|
+
const settleRef = useRef<() => void>(() => {});
|
|
1723
|
+
const watchOverlay = (layer: Element) => {
|
|
1724
|
+
if (overlayWatch.current?.layer === layer) return;
|
|
1725
|
+
overlayWatch.current?.stop();
|
|
1726
|
+
const observer = new MutationObserver(() => {
|
|
1727
|
+
if (layer.isConnected) return;
|
|
1728
|
+
stop();
|
|
1729
|
+
settleRef.current();
|
|
1730
|
+
});
|
|
1731
|
+
const stop = () => {
|
|
1732
|
+
observer.disconnect();
|
|
1733
|
+
if (overlayWatch.current?.layer === layer) overlayWatch.current = null;
|
|
1734
|
+
};
|
|
1735
|
+
observer.observe(layer.ownerDocument.body, { childList: true, subtree: true });
|
|
1736
|
+
overlayWatch.current = { layer, stop };
|
|
1737
|
+
};
|
|
1738
|
+
useEffect(() => () => overlayWatch.current?.stop(), []);
|
|
1611
1739
|
const latestRowCtx: DataTableRowCtx<T> = {
|
|
1740
|
+
noteFocus: noteRowFocus,
|
|
1612
1741
|
moveFocus: virtualOn
|
|
1613
1742
|
? (from, key) => {
|
|
1614
1743
|
const target = rowNavTarget(from, key, slice.length);
|
|
@@ -1653,7 +1782,7 @@ export function DataTable<T>({
|
|
|
1653
1782
|
|
|
1654
1783
|
// One mobile card (`MobileRow`, data-table-mobile.tsx). A function so the flat list
|
|
1655
1784
|
// and the grouped list (below) share identical row markup.
|
|
1656
|
-
const renderMobileRow = (row: T) => {
|
|
1785
|
+
const renderMobileRow = (row: T, index: number) => {
|
|
1657
1786
|
const key = rowKey(row);
|
|
1658
1787
|
const expanded = isExpanded?.(row) ?? false;
|
|
1659
1788
|
return (
|
|
@@ -1661,6 +1790,7 @@ export function DataTable<T>({
|
|
|
1661
1790
|
key={key}
|
|
1662
1791
|
ctx={rowCtx}
|
|
1663
1792
|
rowKey={key}
|
|
1793
|
+
rowIndex={index}
|
|
1664
1794
|
row={row}
|
|
1665
1795
|
expanded={expanded}
|
|
1666
1796
|
expansion={expanded ? openedRowContent(row) : null}
|
|
@@ -1756,15 +1886,72 @@ export function DataTable<T>({
|
|
|
1756
1886
|
focusRowRef.current = focusRowAt;
|
|
1757
1887
|
}, [focusRowAt]);
|
|
1758
1888
|
|
|
1889
|
+
// The commit that took the focused row (DSP-4): if the focus fell with it — to <body>,
|
|
1890
|
+
// not into a dialog or a field the app chose — it goes to the row now at that index,
|
|
1891
|
+
// else the last row, else the table itself (`tabIndex=-1` while empty, named by
|
|
1892
|
+
// `labels.table`); the card on a phone. A focusable row (`onRowClick`) takes it itself,
|
|
1893
|
+
// any other its first control. The remaining count is said, as a filter's is: the
|
|
1894
|
+
// focus moved without the user moving it. translation-review's `keepFocusAt` is the
|
|
1895
|
+
// kit's earlier copy of the rule, for its groups.
|
|
1896
|
+
//
|
|
1897
|
+
// Every commit while a row is noted, a lookup by its key. A focus the user took
|
|
1898
|
+
// elsewhere drops the note (`onBlur` on the root, below), and since the 0.52 code review
|
|
1899
|
+
// so does one that went to nothing — a click on the page's background: kept, it was the
|
|
1900
|
+
// one case where a later removal (a refetch, a sync) pulled the focus back in.
|
|
1901
|
+
const settleFocus = () => {
|
|
1902
|
+
const held = heldRow.current;
|
|
1903
|
+
if (!held) return;
|
|
1904
|
+
const now = (isMdUp ? sliceIndex : mobileIndex)(held.key);
|
|
1905
|
+
if (now !== -1) {
|
|
1906
|
+
held.index = now;
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
const list = isMdUp ? tableRef.current : phoneListRef.current;
|
|
1910
|
+
// In an overlay — a confirm, an edit drawer — the focus is not lost yet: the overlay
|
|
1911
|
+
// hands it back to its opener as it closes, and the opener was in the row (0.52 code
|
|
1912
|
+
// review, data-table.tsx: an optimistic delete with its confirm still open dropped the
|
|
1913
|
+
// note, and the confirm's close dropped the focus to <body>). The note waits for the
|
|
1914
|
+
// overlay to leave the page, watched as a node: the table need not render when it does
|
|
1915
|
+
// (`useConfirm`'s provider, a Modal's exit). Not an overlay the table itself is in.
|
|
1916
|
+
const layer = focusIsLost() ? null : document.activeElement?.closest(OVERLAY_SELECTOR);
|
|
1917
|
+
if (layer && !(list && layer.contains(list))) {
|
|
1918
|
+
watchOverlay(layer);
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1921
|
+
heldRow.current = null;
|
|
1922
|
+
overlayWatch.current?.stop();
|
|
1923
|
+
if (!list || !focusIsLost()) return;
|
|
1924
|
+
const shown = isMdUp ? slice : mobileSlice;
|
|
1925
|
+
const at = shown.length === 0 ? -1 : Math.min(Math.max(held.index, 0), shown.length - 1);
|
|
1926
|
+
if (at === -1) list.focus();
|
|
1927
|
+
else if (isMdUp && virtualOn && rowsFocusable) focusRowRef.current?.(at);
|
|
1928
|
+
else {
|
|
1929
|
+
const row = list.querySelector<HTMLElement>(
|
|
1930
|
+
isMdUp ? `:scope > tbody > tr[data-row-index="${at}"]` : `:scope > li[data-row-index="${at}"]`,
|
|
1931
|
+
);
|
|
1932
|
+
// Each of the row's stops in turn, then the table (0.52 code review): `focus()` on
|
|
1933
|
+
// one that cannot hold it — `display: none`, in a closed <details>, a hidden input —
|
|
1934
|
+
// does nothing, and the focus stayed on <body>.
|
|
1935
|
+
const stops = !row ? [] : isMdUp && rowsFocusable ? [row] : tabStops(row, { includeSelf: false });
|
|
1936
|
+
if (!focusFirst(stops)) focusContainer(list);
|
|
1937
|
+
}
|
|
1938
|
+
announce(labels.filterResults(paginationTotal, isServer ? paginationTotal : rows.length));
|
|
1939
|
+
};
|
|
1940
|
+
useLayoutEffect(() => {
|
|
1941
|
+
settleRef.current = settleFocus;
|
|
1942
|
+
settleFocus();
|
|
1943
|
+
});
|
|
1944
|
+
|
|
1759
1945
|
// `mobileGroupBy` may be a desktop `groupBy` level (0.48), its label and end slot too.
|
|
1760
1946
|
const mobileLevel = typeof mobileGroupBy === "function" ? null : (mobileGroupBy ?? null);
|
|
1761
1947
|
const mobileKey = typeof mobileGroupBy === "function" ? mobileGroupBy : mobileGroupBy?.key;
|
|
1762
|
-
|
|
1763
|
-
|
|
1948
|
+
// `start`: the section's first card's place in the list (its `data-row-index`, DSP-4).
|
|
1949
|
+
const mobileGroups: { key: string; rows: T[]; start: number }[] | null = mobileKey
|
|
1950
|
+
? mobileSlice.reduce<{ key: string; rows: T[]; start: number }[]>((acc, row, i) => {
|
|
1764
1951
|
const key = mobileKey(row);
|
|
1765
1952
|
const last = acc[acc.length - 1];
|
|
1766
1953
|
if (last && last.key === key) last.rows.push(row);
|
|
1767
|
-
else acc.push({ key, rows: [row] });
|
|
1954
|
+
else acc.push({ key, rows: [row], start: i });
|
|
1768
1955
|
return acc;
|
|
1769
1956
|
}, [])
|
|
1770
1957
|
: null;
|
|
@@ -1788,6 +1975,24 @@ export function DataTable<T>({
|
|
|
1788
1975
|
// `<main>` and every `FillHeight` between it and this table key off it with
|
|
1789
1976
|
// `has-[[data-fill-height]]`, so a page asks for the fill by passing the prop.
|
|
1790
1977
|
data-fill-height={fillHeight ? "" : undefined}
|
|
1978
|
+
// The focused row's note (DSP-4): cleared on the way down to whatever takes the
|
|
1979
|
+
// focus, and set again on the way up by the row that holds it. Focus leaving for
|
|
1980
|
+
// something real outside the table drops it — unless that is an overlay (a confirm,
|
|
1981
|
+
// a menu), which hands the focus back, or closes with the row it asked about.
|
|
1982
|
+
onFocusCapture={() => {
|
|
1983
|
+
heldRow.current = null;
|
|
1984
|
+
overlayWatch.current?.stop();
|
|
1985
|
+
}}
|
|
1986
|
+
onBlur={(e) => {
|
|
1987
|
+
const to = e.relatedTarget;
|
|
1988
|
+
if (to instanceof Element && !to.closest(OVERLAY_SELECTOR)) heldRow.current = null;
|
|
1989
|
+
// Focus that left for nothing — a click on the page (0.52 code review): no
|
|
1990
|
+
// element to say where, and a later removal of the row is no longer the user's.
|
|
1991
|
+
const held = heldRow.current;
|
|
1992
|
+
whenFocusLeftForNothing(e, () => {
|
|
1993
|
+
if (heldRow.current === held) heldRow.current = null;
|
|
1994
|
+
});
|
|
1995
|
+
}}
|
|
1791
1996
|
className={cn(
|
|
1792
1997
|
"group/table",
|
|
1793
1998
|
frame ? "overflow-clip" : "min-w-0",
|
|
@@ -1879,6 +2084,10 @@ export function DataTable<T>({
|
|
|
1879
2084
|
)}
|
|
1880
2085
|
<ul
|
|
1881
2086
|
ref={phoneListRef}
|
|
2087
|
+
// Named as the table is, and focusable while empty: where the focus goes when
|
|
2088
|
+
// the last card leaves (DSP-4).
|
|
2089
|
+
aria-label={labels.table}
|
|
2090
|
+
tabIndex={mobileSlice.length === 0 ? -1 : undefined}
|
|
1882
2091
|
className={cn(
|
|
1883
2092
|
"divide-y divide-subtle",
|
|
1884
2093
|
// Under `fillHeight` the list takes the room its parent gives it, and in a
|
|
@@ -1894,10 +2103,20 @@ export function DataTable<T>({
|
|
|
1894
2103
|
)}
|
|
1895
2104
|
aria-busy={isLoading || undefined}
|
|
1896
2105
|
>
|
|
2106
|
+
{/* The desktop's leading row, as the list's first item (0.51.7, audit
|
|
2107
|
+
2026-10-30 DSP-2; MobileLeadingRow says what it is and is not). */}
|
|
2108
|
+
{leadingRow ? (
|
|
2109
|
+
<MobileLeadingRow sticky={leadingRowSticky} onHeight={setPhoneLeadHeight}>
|
|
2110
|
+
{leadingRow}
|
|
2111
|
+
</MobileLeadingRow>
|
|
2112
|
+
) : null}
|
|
1897
2113
|
{mobileGroups
|
|
1898
2114
|
? mobileGroups.map((g) => (
|
|
1899
2115
|
<Fragment key={`hb-group:${g.key}`}>
|
|
1900
|
-
<li
|
|
2116
|
+
<li
|
|
2117
|
+
className="sticky top-0 z-10 flex flex-wrap items-baseline justify-between gap-x-3 bg-surface-2 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-muted backdrop-blur"
|
|
2118
|
+
style={leadingRow && leadingRowSticky ? { top: phoneLeadHeight } : undefined}
|
|
2119
|
+
>
|
|
1901
2120
|
<span className="min-w-0">
|
|
1902
2121
|
{mobileGroupLabel
|
|
1903
2122
|
? mobileGroupLabel(g.key)
|
|
@@ -1909,7 +2128,7 @@ export function DataTable<T>({
|
|
|
1909
2128
|
<span className="ms-auto tabular-nums">{mobileLevel.end(g.key, g.rows)}</span>
|
|
1910
2129
|
)}
|
|
1911
2130
|
</li>
|
|
1912
|
-
{g.rows.map(renderMobileRow)}
|
|
2131
|
+
{g.rows.map((r, i) => renderMobileRow(r, g.start + i))}
|
|
1913
2132
|
</Fragment>
|
|
1914
2133
|
))
|
|
1915
2134
|
: mobileSlice.map(renderMobileRow)}
|
|
@@ -1992,6 +2211,11 @@ export function DataTable<T>({
|
|
|
1992
2211
|
behind it shows, so the panel names the row it opened from. */}
|
|
1993
2212
|
<FullBleedDialog
|
|
1994
2213
|
open={dialogOpen}
|
|
2214
|
+
// The open row's editor is the row's focus too: a Delete in it takes the row,
|
|
2215
|
+
// and the dialog with it (DSP-4).
|
|
2216
|
+
onFocus={() => {
|
|
2217
|
+
if (mobileDialogRow) noteRowFocus(rowKey(mobileDialogRow));
|
|
2218
|
+
}}
|
|
1995
2219
|
onClose={closeDialog}
|
|
1996
2220
|
closeLabel={labels.close}
|
|
1997
2221
|
header={mobileDialogRow ? mobilePrimaryCol?.cell(mobileDialogRow) : null}
|
|
@@ -2036,6 +2260,8 @@ export function DataTable<T>({
|
|
|
2036
2260
|
className={cn("w-full", compact ? "text-xs" : "text-sm")}
|
|
2037
2261
|
data-fit-grow={growDrawn ? "" : undefined}
|
|
2038
2262
|
aria-label={labels.table}
|
|
2263
|
+
// Focusable while empty: where the focus goes when the last row leaves (DSP-4).
|
|
2264
|
+
tabIndex={slice.length === 0 ? -1 : undefined}
|
|
2039
2265
|
aria-busy={isLoading || undefined}
|
|
2040
2266
|
// `virtualize` (0.48.2): every row counted, rendered or not.
|
|
2041
2267
|
aria-rowcount={rowWindow?.rowCount}
|