@eifi1/ui-kit 0.54.0 → 0.55.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 +90 -76
- package/dist/admin/plan-change.js +2 -2
- package/dist/admin/plan-change.js.map +1 -1
- package/dist/admin/user-roster.d.ts +6 -0
- package/dist/admin/user-roster.js +4 -0
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/billing/billing-labels.d.ts +26 -0
- package/dist/billing/billing-labels.js +9 -0
- package/dist/billing/billing-labels.js.map +1 -1
- package/dist/billing/subscription-standing.d.ts +61 -0
- package/dist/billing/subscription-standing.js +51 -0
- package/dist/billing/subscription-standing.js.map +1 -0
- package/dist/billing/usage-meter.d.ts +52 -0
- package/dist/billing/usage-meter.js +52 -0
- package/dist/billing/usage-meter.js.map +1 -0
- package/dist/chart.d.ts +1 -0
- package/dist/chart.js +4 -0
- package/dist/chart.js.map +1 -1
- package/dist/components/alert-banner.js +2 -3
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.js +3 -15
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.js +2 -2
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/bulk-action-bar.js +2 -1
- package/dist/components/bulk-action-bar.js.map +1 -1
- package/dist/components/button.d.ts +35 -1
- package/dist/components/button.js +5 -9
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar-heatmap.js +2 -2
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/camera-button.d.ts +89 -0
- package/dist/components/camera-button.js +122 -0
- package/dist/components/camera-button.js.map +1 -0
- package/dist/components/camera-capture.d.ts +66 -0
- package/dist/components/camera-capture.js +190 -0
- package/dist/components/camera-capture.js.map +1 -0
- package/dist/components/camera-labels.d.ts +20 -0
- package/dist/components/camera-labels.js +15 -0
- package/dist/components/camera-labels.js.map +1 -0
- package/dist/components/chart-edge.d.ts +9 -0
- package/dist/components/chart-edge.js +14 -3
- package/dist/components/chart-edge.js.map +1 -1
- package/dist/components/chart-zoom-core.js +34 -29
- package/dist/components/chart-zoom-core.js.map +1 -1
- package/dist/components/checkbox-group.js +1 -1
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/combobox-core.js +3 -2
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +2 -2
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/consent-again-notice-labels.d.ts +25 -0
- package/dist/components/consent-again-notice-labels.js +15 -0
- package/dist/components/consent-again-notice-labels.js.map +1 -0
- package/dist/components/consent-again-notice.d.ts +85 -0
- package/dist/components/consent-again-notice.js +94 -0
- package/dist/components/consent-again-notice.js.map +1 -0
- package/dist/components/country-select.js +2 -7
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/currency-select.js +2 -2
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.js +2 -2
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-column-settings.js +2 -2
- package/dist/components/data-table-column-settings.js.map +1 -1
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-virtual.js +13 -3
- package/dist/components/data-table-virtual.js.map +1 -1
- package/dist/components/date-field.js +2 -2
- package/dist/components/date-field.js.map +1 -1
- package/dist/components/date-picker.js +2 -2
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/date-range-picker.js +2 -6
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +3 -1
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/dropdown.js +7 -3
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/entity-combobox.js +2 -2
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/field-parts.d.ts +108 -6
- package/dist/components/field-parts.js +59 -6
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-suggestion-labels.d.ts +2 -0
- package/dist/components/field-suggestion-labels.js +10 -0
- package/dist/components/field-suggestion-labels.js.map +1 -0
- package/dist/components/field.js +1 -1
- package/dist/components/field.js.map +1 -1
- package/dist/components/file-button.d.ts +1 -1
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/floating-panel.d.ts +7 -6
- package/dist/components/floating-panel.js +3 -17
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form-actions.d.ts +3 -2
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/hover-menu.js +3 -2
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/icon-button.d.ts +23 -5
- package/dist/components/icon-button.js +6 -8
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/inline-confirm.js +2 -1
- package/dist/components/inline-confirm.js.map +1 -1
- package/dist/components/inline-entity-combobox.js +2 -2
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/input.js +2 -2
- package/dist/components/input.js.map +1 -1
- package/dist/components/jump-calendar.js +3 -3
- package/dist/components/jump-calendar.js.map +1 -1
- package/dist/components/legal.d.ts +13 -1
- package/dist/components/legal.js +12 -0
- package/dist/components/legal.js.map +1 -1
- package/dist/components/legended-series-chart.d.ts +80 -0
- package/dist/components/legended-series-chart.js +70 -0
- package/dist/components/legended-series-chart.js.map +1 -0
- package/dist/components/lightbox.js +2 -1
- package/dist/components/lightbox.js.map +1 -1
- package/dist/components/mini-calendar.js +13 -5
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.d.ts +23 -2
- package/dist/components/modal.js +24 -6
- package/dist/components/modal.js.map +1 -1
- package/dist/components/month-picker.d.ts +1 -1
- package/dist/components/month-picker.js +6 -6
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.js +2 -2
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.js +2 -6
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-input.js +2 -2
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/page-header-layout.d.ts +18 -0
- package/dist/components/page-header-layout.js +23 -0
- package/dist/components/page-header-layout.js.map +1 -0
- package/dist/components/page-header-skeleton.d.ts +41 -0
- package/dist/components/page-header-skeleton.js +52 -0
- package/dist/components/page-header-skeleton.js.map +1 -0
- package/dist/components/page-header.js +4 -17
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/popover.js +7 -2
- package/dist/components/popover.js.map +1 -1
- package/dist/components/release-notes-labels.d.ts +16 -0
- package/dist/components/release-notes-labels.js +18 -0
- package/dist/components/release-notes-labels.js.map +1 -0
- package/dist/components/release-notes.d.ts +65 -0
- package/dist/components/release-notes.js +65 -0
- package/dist/components/release-notes.js.map +1 -0
- package/dist/components/select.js +2 -2
- package/dist/components/select.js.map +1 -1
- package/dist/components/series-chart-labels.d.ts +9 -0
- package/dist/components/series-chart-labels.js +3 -1
- package/dist/components/series-chart-labels.js.map +1 -1
- package/dist/components/series-chart.d.ts +5 -0
- package/dist/components/series-chart.js +89 -36
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/toggle-group.js +3 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/treemap-layout.js.map +1 -1
- package/dist/components/treemap.d.ts +17 -15
- package/dist/components/treemap.js +167 -85
- package/dist/components/treemap.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/eslint/role-utilities.d.ts +2 -2
- package/dist/eslint/role-utilities.js.map +1 -1
- package/dist/feedback/feedback-inbox-page.d.ts +260 -0
- package/dist/feedback/feedback-inbox-page.js +207 -0
- package/dist/feedback/feedback-inbox-page.js.map +1 -0
- package/dist/feedback/feedback-vocabulary.js +2 -2
- package/dist/feedback/feedback-vocabulary.js.map +1 -1
- package/dist/feedback.d.ts +1 -0
- package/dist/feedback.js +6 -0
- package/dist/feedback.js.map +1 -1
- package/dist/hooks/use-debounce.d.ts +32 -5
- package/dist/hooks/use-debounce.js +6 -5
- package/dist/hooks/use-debounce.js.map +1 -1
- package/dist/hooks/use-file-picker.d.ts +3 -1
- package/dist/hooks/use-file-picker.js.map +1 -1
- package/dist/hooks/use-focus-trap.d.ts +19 -3
- package/dist/hooks/use-focus-trap.js +15 -5
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-has-camera.d.ts +36 -0
- package/dist/hooks/use-has-camera.js +53 -0
- package/dist/hooks/use-has-camera.js.map +1 -0
- package/dist/hooks/use-hotkey.js +1 -10
- package/dist/hooks/use-hotkey.js.map +1 -1
- package/dist/hooks/use-overlay-history.d.ts +6 -1
- package/dist/hooks/use-overlay-history.js +10 -2
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.js +11 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.js +75 -3
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +20 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +92 -4
- package/dist/i18n/locales/en.js.map +3 -3
- package/dist/i18n/locales/es.js +71 -3
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +72 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +74 -3
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +74 -3
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +71 -3
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +22 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +24 -5
- package/dist/index.js +35 -1
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-labels.d.ts +8 -0
- package/dist/landing/landing-labels.js +2 -1
- package/dist/landing/landing-labels.js.map +1 -1
- package/dist/lib/changelog.d.ts +130 -0
- package/dist/lib/changelog.js +137 -0
- package/dist/lib/changelog.js.map +1 -0
- package/dist/lib/clipboard-minus.js +2 -2
- package/dist/lib/clipboard-minus.js.map +1 -1
- package/dist/lib/dates.d.ts +29 -3
- package/dist/lib/dates.js +41 -12
- package/dist/lib/dates.js.map +1 -1
- package/dist/lib/editable-content.d.ts +33 -0
- package/dist/lib/editable-content.js +15 -0
- package/dist/lib/editable-content.js.map +1 -0
- package/dist/lib/focus-left.d.ts +47 -1
- package/dist/lib/focus-left.js +11 -2
- package/dist/lib/focus-left.js.map +1 -1
- package/dist/lib/server-wake.d.ts +49 -9
- package/dist/lib/server-wake.js +25 -14
- package/dist/lib/server-wake.js.map +1 -1
- package/dist/lib/session-refresh.d.ts +53 -0
- package/dist/lib/session-refresh.js +27 -1
- package/dist/lib/session-refresh.js.map +1 -1
- package/dist/rhf/fields.js +3 -3
- package/dist/rhf/fields.js.map +1 -1
- package/dist/shell/app-shell.d.ts +25 -1
- package/dist/shell/app-shell.js +3 -1
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/dev-menu.d.ts +3 -0
- package/dist/shell/dev-menu.js +4 -2
- package/dist/shell/dev-menu.js.map +1 -1
- package/dist/shell/held-changes-banner-labels.d.ts +23 -0
- package/dist/shell/held-changes-banner-labels.js +14 -0
- package/dist/shell/held-changes-banner-labels.js.map +1 -0
- package/dist/shell/held-changes-banner.d.ts +75 -0
- package/dist/shell/held-changes-banner.js +106 -0
- package/dist/shell/held-changes-banner.js.map +1 -0
- package/dist/shell/sync-status-indicator.d.ts +27 -12
- package/dist/shell/sync-status-indicator.js +13 -4
- package/dist/shell/sync-status-indicator.js.map +1 -1
- package/dist/shell/top-bar-parts-labels.d.ts +5 -0
- package/dist/shell/top-bar-parts-labels.js +3 -1
- package/dist/shell/top-bar-parts-labels.js.map +1 -1
- package/dist/shell.d.ts +2 -0
- package/dist/shell.js +3 -0
- package/dist/shell.js.map +1 -1
- package/dist/sync/engine.d.ts +11 -2
- package/dist/sync/engine.js +13 -5
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/hooks.d.ts +3 -2
- package/dist/sync/hooks.js +4 -2
- package/dist/sync/hooks.js.map +1 -1
- package/dist/testing/css-variables.generated.d.ts +2 -2
- package/dist/testing/css-variables.generated.js +1 -1
- package/dist/testing/css-variables.generated.js.map +1 -1
- package/dist/theme/chart-palette.d.ts +18 -0
- package/dist/theme/chart-palette.js +17 -1
- package/dist/theme/chart-palette.js.map +1 -1
- package/dist/theme/contrast-tokens.d.ts +3 -3
- package/dist/theme/contrast-tokens.js.map +1 -1
- package/dist/theme/contrast.d.ts +4 -4
- package/dist/theme/contrast.js.map +1 -1
- package/dist/tour/tour-overlay.js +2 -1
- package/dist/tour/tour-overlay.js.map +1 -1
- package/package.json +5 -9
- package/tokens.css +19 -54
- package/src/account/account-parts.ts +0 -47
- package/src/account/account-settings-labels.ts +0 -240
- package/src/account/account-settings.tsx +0 -698
- package/src/account/data-export-setting-labels.ts +0 -20
- package/src/account/data-export-setting.tsx +0 -200
- package/src/account/delete-account-setting-labels.ts +0 -33
- package/src/account/delete-account-setting.tsx +0 -342
- package/src/account/email-change-setting-labels.ts +0 -31
- package/src/account/email-change-setting.tsx +0 -443
- package/src/account/passkeys-setting.tsx +0 -445
- package/src/account/sessions-setting-labels.ts +0 -24
- package/src/account/sessions-setting.tsx +0 -283
- package/src/admin/admin-action-confirm-labels.ts +0 -19
- package/src/admin/admin-action-confirm.tsx +0 -509
- package/src/admin/admin-action-log-labels.ts +0 -83
- package/src/admin/admin-action-log.tsx +0 -464
- package/src/admin/admin-area-labels.ts +0 -114
- package/src/admin/admin-forbidden.tsx +0 -75
- package/src/admin/admin-overview.tsx +0 -258
- package/src/admin/admin-parts.ts +0 -68
- package/src/admin/admin-sections.tsx +0 -208
- package/src/admin/admin-tool-links.tsx +0 -90
- package/src/admin/invitations-panel-labels.ts +0 -31
- package/src/admin/invitations-panel.tsx +0 -516
- package/src/admin/mail-test-card-labels.ts +0 -19
- package/src/admin/mail-test-card.tsx +0 -189
- package/src/admin/plan-change-labels.ts +0 -5
- package/src/admin/plan-change.tsx +0 -474
- package/src/admin/reviewer-scope-editor-labels.ts +0 -16
- package/src/admin/reviewer-scope-editor.tsx +0 -224
- package/src/admin/role-select-labels.ts +0 -16
- package/src/admin/role-select.tsx +0 -282
- package/src/admin/transfer-ownership-dialog-labels.ts +0 -20
- package/src/admin/transfer-ownership-dialog.tsx +0 -162
- package/src/admin/user-roster-labels.ts +0 -17
- package/src/admin/user-roster.tsx +0 -559
- package/src/auth/accept-invitation-labels.ts +0 -21
- package/src/auth/accept-invitation.tsx +0 -210
- package/src/auth/auth-errors-labels.ts +0 -23
- package/src/auth/auth-errors.ts +0 -439
- package/src/auth/complete-name-dialog-labels.ts +0 -16
- package/src/auth/complete-name-dialog.tsx +0 -253
- package/src/auth/email-tag.ts +0 -75
- package/src/auth/forgot-password-form-labels.ts +0 -20
- package/src/auth/forgot-password-form.tsx +0 -221
- package/src/auth/form-rules.ts +0 -40
- package/src/auth/new-password-fields.tsx +0 -85
- package/src/auth/not-found-page-labels.ts +0 -12
- package/src/auth/not-found-page.tsx +0 -95
- package/src/auth/register-form-labels.ts +0 -31
- package/src/auth/register-form.tsx +0 -456
- package/src/auth/reset-password-form-labels.ts +0 -27
- package/src/auth/reset-password-form.tsx +0 -341
- package/src/auth/sign-in-form-labels.ts +0 -44
- package/src/auth/sign-in-form.tsx +0 -858
- package/src/auth/status-parts.tsx +0 -132
- package/src/auth/verify-email-labels.ts +0 -26
- package/src/auth/verify-email.tsx +0 -445
- package/src/billing/billing-banner.tsx +0 -258
- package/src/billing/billing-labels.ts +0 -381
- package/src/billing/billing-lock.ts +0 -108
- package/src/billing/billing-overview.ts +0 -157
- package/src/billing/billing-standing.ts +0 -80
- package/src/billing/cancel-request.ts +0 -97
- package/src/billing/cancel-subscription.tsx +0 -98
- package/src/billing/checkout-processing.ts +0 -394
- package/src/billing/checkout-return.ts +0 -90
- package/src/billing/pay-page.ts +0 -330
- package/src/billing/plan-card.tsx +0 -562
- package/src/billing/plan-change-labels.ts +0 -66
- package/src/billing/plan-limit-notice.tsx +0 -148
- package/src/billing/plan-limit-toast.tsx +0 -90
- package/src/billing/plan-limit.ts +0 -52
- package/src/billing/plan-price.ts +0 -98
- package/src/billing/plan-switch.tsx +0 -216
- package/src/billing/provider-page.ts +0 -84
- package/src/billing/subscription-actions.tsx +0 -247
- package/src/billing/subscription-status-chip.tsx +0 -95
- package/src/chart.ts +0 -103
- package/src/components/account-chips-labels.ts +0 -16
- package/src/components/account-chips.tsx +0 -474
- package/src/components/alert-banner.tsx +0 -670
- package/src/components/amount-input.tsx +0 -816
- package/src/components/appearance-labels.ts +0 -63
- package/src/components/authed-image-labels.ts +0 -11
- package/src/components/authed-image.tsx +0 -209
- package/src/components/autocomplete.tsx +0 -645
- package/src/components/breadcrumbs-labels.ts +0 -10
- package/src/components/breadcrumbs.tsx +0 -205
- package/src/components/bulk-action-bar-labels.ts +0 -11
- package/src/components/bulk-action-bar.tsx +0 -443
- package/src/components/button-group.tsx +0 -223
- package/src/components/button-look.ts +0 -256
- package/src/components/button.tsx +0 -339
- package/src/components/calculator.tsx +0 -341
- package/src/components/calendar-heatmap-labels.ts +0 -15
- package/src/components/calendar-heatmap.tsx +0 -600
- package/src/components/card.tsx +0 -377
- package/src/components/chart-edge.ts +0 -106
- package/src/components/chart-figure.tsx +0 -35
- package/src/components/chart-height.ts +0 -30
- package/src/components/chart-zoom-core.tsx +0 -627
- package/src/components/chart-zoom.tsx +0 -22
- package/src/components/chart.tsx +0 -554
- package/src/components/checkbox-group.tsx +0 -247
- package/src/components/checkbox.tsx +0 -346
- package/src/components/chip-input.tsx +0 -370
- package/src/components/chip-labels.ts +0 -13
- package/src/components/chip.tsx +0 -843
- package/src/components/choice-card.tsx +0 -544
- package/src/components/column-mapper-labels.ts +0 -38
- package/src/components/column-mapper.tsx +0 -655
- package/src/components/combobox-core.tsx +0 -1321
- package/src/components/combobox-suggestions.tsx +0 -131
- package/src/components/combobox.tsx +0 -716
- package/src/components/confirm-context.ts +0 -7
- package/src/components/confirm-dialog-labels.ts +0 -13
- package/src/components/confirm-dialog.tsx +0 -341
- package/src/components/copy-button-labels.ts +0 -13
- package/src/components/copy-button.tsx +0 -192
- package/src/components/country-select-labels.ts +0 -11
- package/src/components/country-select.tsx +0 -539
- package/src/components/currency-option-list.tsx +0 -188
- package/src/components/currency-select.tsx +0 -343
- package/src/components/danger-confirm-labels.ts +0 -20
- package/src/components/danger-confirm.tsx +0 -987
- package/src/components/data-table-cells.tsx +0 -118
- package/src/components/data-table-column-settings.tsx +0 -198
- package/src/components/data-table-filter-popover.tsx +0 -289
- package/src/components/data-table-filters.ts +0 -315
- package/src/components/data-table-fit.ts +0 -301
- package/src/components/data-table-groups.tsx +0 -288
- package/src/components/data-table-head.tsx +0 -280
- package/src/components/data-table-labels.ts +0 -198
- package/src/components/data-table-leading-row.tsx +0 -58
- package/src/components/data-table-mobile.tsx +0 -1117
- package/src/components/data-table-pagination.tsx +0 -202
- package/src/components/data-table-resize.ts +0 -188
- package/src/components/data-table-row-actions.tsx +0 -302
- package/src/components/data-table-row.tsx +0 -496
- package/src/components/data-table-selection.ts +0 -71
- package/src/components/data-table-shared.tsx +0 -287
- package/src/components/data-table-sort.ts +0 -163
- package/src/components/data-table-virtual.ts +0 -576
- package/src/components/data-table.tsx +0 -2598
- package/src/components/date-field.tsx +0 -684
- package/src/components/date-format-setting.tsx +0 -64
- package/src/components/date-picker.tsx +0 -404
- package/src/components/date-range-picker.tsx +0 -518
- package/src/components/description-list-labels.ts +0 -9
- package/src/components/description-list.tsx +0 -386
- package/src/components/dialog-frame-labels.ts +0 -7
- package/src/components/dialog-frame.tsx +0 -284
- package/src/components/disclosure.tsx +0 -476
- package/src/components/dropdown.tsx +0 -461
- package/src/components/empty-state.tsx +0 -136
- package/src/components/entity-combobox.tsx +0 -422
- package/src/components/error-boundary-labels.ts +0 -20
- package/src/components/error-boundary.tsx +0 -675
- package/src/components/facing-pair.ts +0 -93
- package/src/components/field-base-labels.ts +0 -20
- package/src/components/field-base.tsx +0 -656
- package/src/components/field-parts.tsx +0 -825
- package/src/components/field-strip.tsx +0 -129
- package/src/components/field.tsx +0 -206
- package/src/components/file-button.tsx +0 -295
- package/src/components/file-dropzone.tsx +0 -559
- package/src/components/floating-panel-labels.ts +0 -10
- package/src/components/floating-panel.tsx +0 -828
- package/src/components/focus-ring.ts +0 -16
- package/src/components/form-actions-labels.ts +0 -11
- package/src/components/form-actions.tsx +0 -578
- package/src/components/full-bleed-dialog.tsx +0 -294
- package/src/components/grouped-picker.tsx +0 -184
- package/src/components/help-popover.tsx +0 -117
- package/src/components/hover-menu.tsx +0 -343
- package/src/components/iban-input-labels.ts +0 -14
- package/src/components/iban-input.tsx +0 -236
- package/src/components/icon-button.tsx +0 -959
- package/src/components/icon-picker-labels.ts +0 -13
- package/src/components/icon-picker.tsx +0 -232
- package/src/components/image-grid-labels.ts +0 -11
- package/src/components/image-grid.tsx +0 -202
- package/src/components/inline-confirm.tsx +0 -116
- package/src/components/inline-edit-field-labels.ts +0 -11
- package/src/components/inline-edit-field.tsx +0 -552
- package/src/components/inline-entity-combobox.tsx +0 -849
- package/src/components/input.tsx +0 -394
- package/src/components/jump-calendar.tsx +0 -265
- package/src/components/language-select.tsx +0 -93
- package/src/components/legal-labels.ts +0 -105
- package/src/components/legal-page.tsx +0 -711
- package/src/components/legal.tsx +0 -668
- package/src/components/lightbox-labels.ts +0 -18
- package/src/components/lightbox.tsx +0 -399
- package/src/components/line-items-labels.ts +0 -14
- package/src/components/line-items.tsx +0 -602
- package/src/components/list-labels.ts +0 -12
- package/src/components/list.tsx +0 -870
- package/src/components/loading-state.tsx +0 -78
- package/src/components/measured-grid-labels.ts +0 -25
- package/src/components/measured-grid.tsx +0 -837
- package/src/components/menu-item.tsx +0 -241
- package/src/components/mini-calendar-labels.ts +0 -17
- package/src/components/mini-calendar.tsx +0 -792
- package/src/components/modal.tsx +0 -534
- package/src/components/money-draft.ts +0 -83
- package/src/components/money-field.tsx +0 -76
- package/src/components/month-grid.tsx +0 -229
- package/src/components/month-picker-labels.ts +0 -22
- package/src/components/month-picker.tsx +0 -1087
- package/src/components/multi-entity-combobox.tsx +0 -369
- package/src/components/multi-select.tsx +0 -376
- package/src/components/nav-pills.tsx +0 -198
- package/src/components/number-field.tsx +0 -327
- package/src/components/number-input.tsx +0 -559
- package/src/components/numeric-field.ts +0 -169
- package/src/components/numpad-sheet.tsx +0 -285
- package/src/components/one-time-code-input.tsx +0 -270
- package/src/components/page-contents-labels.ts +0 -9
- package/src/components/page-contents.tsx +0 -282
- package/src/components/page-header-context.ts +0 -8
- package/src/components/page-header.tsx +0 -298
- package/src/components/password-strength-labels.ts +0 -22
- package/src/components/password-strength.tsx +0 -241
- package/src/components/phone-input-labels.ts +0 -10
- package/src/components/phone-input.tsx +0 -282
- package/src/components/picker-sheet.tsx +0 -330
- package/src/components/pie-chart-labels.ts +0 -40
- package/src/components/pie-chart.tsx +0 -480
- package/src/components/popover-labels.ts +0 -14
- package/src/components/popover.tsx +0 -268
- package/src/components/progress-bar-labels.ts +0 -10
- package/src/components/progress-bar.tsx +0 -479
- package/src/components/qr-code.tsx +0 -76
- package/src/components/reauth-dialog-labels.ts +0 -13
- package/src/components/reauth-dialog.tsx +0 -265
- package/src/components/row-actions-labels.ts +0 -12
- package/src/components/row-actions.tsx +0 -795
- package/src/components/scroll-area.tsx +0 -123
- package/src/components/search-field.tsx +0 -192
- package/src/components/select.tsx +0 -294
- package/src/components/separator.tsx +0 -33
- package/src/components/series-chart-axes.ts +0 -342
- package/src/components/series-chart-budget.ts +0 -150
- package/src/components/series-chart-labels.ts +0 -33
- package/src/components/series-chart-thin.ts +0 -180
- package/src/components/series-chart-ticks.ts +0 -194
- package/src/components/series-chart.tsx +0 -1906
- package/src/components/server-wake-labels.ts +0 -11
- package/src/components/server-wake.tsx +0 -129
- package/src/components/settings-fields.tsx +0 -237
- package/src/components/share-card-labels.ts +0 -30
- package/src/components/share-card.tsx +0 -675
- package/src/components/signature-pad-labels.ts +0 -24
- package/src/components/signature-pad.tsx +0 -747
- package/src/components/signed-amount-labels.ts +0 -10
- package/src/components/signed-amount.tsx +0 -336
- package/src/components/skeleton.tsx +0 -80
- package/src/components/slider.tsx +0 -338
- package/src/components/sparkline-labels.ts +0 -14
- package/src/components/sparkline.tsx +0 -322
- package/src/components/spinner.tsx +0 -81
- package/src/components/stat-tile-labels.ts +0 -15
- package/src/components/stat-tile.tsx +0 -754
- package/src/components/status-dot.tsx +0 -170
- package/src/components/swatch-picker-labels.ts +0 -10
- package/src/components/swatch-picker.tsx +0 -283
- package/src/components/swipeable-row.tsx +0 -386
- package/src/components/switch.tsx +0 -273
- package/src/components/table-skeleton.tsx +0 -136
- package/src/components/table.tsx +0 -647
- package/src/components/tabs-labels.ts +0 -13
- package/src/components/tabs.tsx +0 -693
- package/src/components/text-link.tsx +0 -359
- package/src/components/text.tsx +0 -150
- package/src/components/textarea.tsx +0 -330
- package/src/components/tile-radio.tsx +0 -332
- package/src/components/time-input.tsx +0 -121
- package/src/components/toast-labels.ts +0 -12
- package/src/components/toast.tsx +0 -519
- package/src/components/toggle-group.tsx +0 -752
- package/src/components/toggle-legend.tsx +0 -394
- package/src/components/tooltip.tsx +0 -1149
- package/src/components/translation-review-editor.tsx +0 -290
- package/src/components/translation-review-labels.ts +0 -181
- package/src/components/translation-review-parts.tsx +0 -272
- package/src/components/translation-review.tsx +0 -1240
- package/src/components/tree-view.tsx +0 -589
- package/src/components/treemap-labels.ts +0 -47
- package/src/components/treemap-layout.ts +0 -210
- package/src/components/treemap.tsx +0 -1184
- package/src/components/trigger-aria.ts +0 -44
- package/src/components/use-anchor-dir.ts +0 -20
- package/src/components/use-mobile-reveal.ts +0 -62
- package/src/components/use-table-state.ts +0 -753
- package/src/components/user-avatar.tsx +0 -116
- package/src/components/wizard-stepper.tsx +0 -42
- package/src/components/write-lock-labels.ts +0 -10
- package/src/components/write-lock.tsx +0 -253
- package/src/currencies.ts +0 -90
- package/src/data-table.ts +0 -42
- package/src/demo/demo-banner.tsx +0 -153
- package/src/demo/demo-countdown.ts +0 -136
- package/src/demo/demo-ended.tsx +0 -90
- package/src/demo/demo-labels.ts +0 -78
- package/src/demo/demo-session.ts +0 -32
- package/src/demo/demo-start.tsx +0 -156
- package/src/eslint/index.ts +0 -161
- package/src/eslint/role-utilities.generated.ts +0 -146
- package/src/eslint/role-utilities.ts +0 -233
- package/src/feedback/feedback-attachment-download.tsx +0 -77
- package/src/feedback/feedback-attachment-labels.ts +0 -37
- package/src/feedback/feedback-attachment.tsx +0 -1239
- package/src/feedback/feedback-capture.ts +0 -287
- package/src/feedback/feedback-comment-thread.tsx +0 -353
- package/src/feedback/feedback-context-labels.ts +0 -11
- package/src/feedback/feedback-context.tsx +0 -245
- package/src/feedback/feedback-crash.ts +0 -547
- package/src/feedback/feedback-diagnostics.tsx +0 -41
- package/src/feedback/feedback-dialog-labels.ts +0 -29
- package/src/feedback/feedback-dialog.tsx +0 -452
- package/src/feedback/feedback-entry-file.tsx +0 -150
- package/src/feedback/feedback-inbox.tsx +0 -552
- package/src/feedback/feedback-labels.ts +0 -144
- package/src/feedback/feedback-menu-labels.ts +0 -12
- package/src/feedback/feedback-menu.tsx +0 -177
- package/src/feedback/feedback-mutation.ts +0 -20
- package/src/feedback/feedback-page-link.ts +0 -90
- package/src/feedback/feedback-public-labels.ts +0 -81
- package/src/feedback/feedback-public-list.tsx +0 -524
- package/src/feedback/feedback-public-switch.tsx +0 -102
- package/src/feedback/feedback-public-types.ts +0 -101
- package/src/feedback/feedback-record.ts +0 -428
- package/src/feedback/feedback-replies-context.ts +0 -9
- package/src/feedback/feedback-replies.tsx +0 -343
- package/src/feedback/feedback-rework-entry-chip.tsx +0 -18
- package/src/feedback/feedback-row-detail-labels.ts +0 -31
- package/src/feedback/feedback-row-detail.tsx +0 -871
- package/src/feedback/feedback-status-undo.ts +0 -109
- package/src/feedback/feedback-submit-dialog.tsx +0 -131
- package/src/feedback/feedback-submit.tsx +0 -270
- package/src/feedback/feedback-swipe.tsx +0 -192
- package/src/feedback/feedback-table-labels.ts +0 -27
- package/src/feedback/feedback-table.tsx +0 -912
- package/src/feedback/feedback-thread-labels.ts +0 -22
- package/src/feedback/feedback-thread-parts-labels.ts +0 -41
- package/src/feedback/feedback-thread.tsx +0 -905
- package/src/feedback/feedback-vocabulary.ts +0 -263
- package/src/feedback/feedback-vote-button.tsx +0 -124
- package/src/feedback.ts +0 -116
- package/src/hooks/use-anchored-panel.ts +0 -396
- package/src/hooks/use-anchored-rect.ts +0 -77
- package/src/hooks/use-announce.ts +0 -85
- package/src/hooks/use-authed-src.ts +0 -167
- package/src/hooks/use-body-scroll-lock.ts +0 -119
- package/src/hooks/use-breakpoint.ts +0 -133
- package/src/hooks/use-close-transition.ts +0 -107
- package/src/hooks/use-copy-to-clipboard.ts +0 -122
- package/src/hooks/use-debounce.ts +0 -114
- package/src/hooks/use-dismiss.ts +0 -371
- package/src/hooks/use-document-title.ts +0 -33
- package/src/hooks/use-file-drop.ts +0 -121
- package/src/hooks/use-file-picker-labels.ts +0 -28
- package/src/hooks/use-file-picker.tsx +0 -359
- package/src/hooks/use-focus-trap.ts +0 -199
- package/src/hooks/use-hotkey.ts +0 -212
- package/src/hooks/use-large-text.ts +0 -41
- package/src/hooks/use-long-press.ts +0 -140
- package/src/hooks/use-media-query.ts +0 -39
- package/src/hooks/use-mounted.ts +0 -39
- package/src/hooks/use-noindex.ts +0 -37
- package/src/hooks/use-overlay-history.ts +0 -714
- package/src/hooks/use-row-swipe.ts +0 -207
- package/src/hooks/use-search-param-state.ts +0 -434
- package/src/hooks/use-windowed-rows.ts +0 -225
- package/src/i18n/defaults.ts +0 -267
- package/src/i18n/german.ts +0 -2059
- package/src/i18n/kit-labels.tsx +0 -1003
- package/src/i18n/languages.ts +0 -349
- package/src/i18n/locales/de-CH.ts +0 -24
- package/src/i18n/locales/en.ts +0 -267
- package/src/i18n/locales/es.ts +0 -1999
- package/src/i18n/locales/fr.ts +0 -2037
- package/src/i18n/locales/hu.ts +0 -2004
- package/src/i18n/locales/it.ts +0 -2014
- package/src/i18n/locales/zh.ts +0 -1912
- package/src/i18n/plurals.ts +0 -86
- package/src/i18n/review.ts +0 -475
- package/src/i18n/shared-labels.ts +0 -138
- package/src/i18n/swiss.ts +0 -29
- package/src/index.ts +0 -1191
- package/src/landing/access.ts +0 -93
- package/src/landing/landing-actions.tsx +0 -97
- package/src/landing/landing-labels.ts +0 -59
- package/src/landing/landing-sections.tsx +0 -341
- package/src/landing/page-seo.ts +0 -261
- package/src/landing/public-header.tsx +0 -121
- package/src/landing/public-page.tsx +0 -106
- package/src/landing/routing.tsx +0 -225
- package/src/lib/broadcast.ts +0 -52
- package/src/lib/calc.ts +0 -323
- package/src/lib/chip-edge-snap.ts +0 -212
- package/src/lib/clipboard-minus.ts +0 -107
- package/src/lib/clipping.ts +0 -34
- package/src/lib/cn.ts +0 -28
- package/src/lib/column-mapping.ts +0 -234
- package/src/lib/countries.ts +0 -91
- package/src/lib/data-attributes.ts +0 -14
- package/src/lib/date-format.ts +0 -227
- package/src/lib/dates.ts +0 -288
- package/src/lib/day-format.ts +0 -96
- package/src/lib/decimal-marks.ts +0 -108
- package/src/lib/describe-failure.ts +0 -18
- package/src/lib/device-settings.ts +0 -147
- package/src/lib/direction.ts +0 -74
- package/src/lib/document-navigation.ts +0 -17
- package/src/lib/document-title.ts +0 -41
- package/src/lib/download.ts +0 -172
- package/src/lib/float-clearance.ts +0 -70
- package/src/lib/floating-stack.ts +0 -70
- package/src/lib/focus-left.ts +0 -156
- package/src/lib/format.ts +0 -585
- package/src/lib/http-status.ts +0 -38
- package/src/lib/iban.ts +0 -251
- package/src/lib/ime.ts +0 -24
- package/src/lib/intl-cache.ts +0 -27
- package/src/lib/iso-day.ts +0 -13
- package/src/lib/lazy-with-fallback.ts +0 -82
- package/src/lib/logger.ts +0 -69
- package/src/lib/minus.ts +0 -50
- package/src/lib/path-pattern.ts +0 -55
- package/src/lib/person-name.ts +0 -155
- package/src/lib/phone.ts +0 -208
- package/src/lib/plain-text.ts +0 -22
- package/src/lib/presence.ts +0 -18
- package/src/lib/qr-encode.ts +0 -444
- package/src/lib/quiet-focus.ts +0 -32
- package/src/lib/reduced-motion.ts +0 -22
- package/src/lib/refs.ts +0 -22
- package/src/lib/round.ts +0 -43
- package/src/lib/safe-storage.ts +0 -119
- package/src/lib/server-wake.ts +0 -315
- package/src/lib/session-refresh.ts +0 -472
- package/src/lib/share-format.ts +0 -18
- package/src/lib/status-tone.ts +0 -43
- package/src/lib/strip-fade.ts +0 -287
- package/src/lib/table-text.ts +0 -554
- package/src/lib/text-case.ts +0 -19
- package/src/lib/text-match.ts +0 -169
- package/src/lib/thenable.ts +0 -19
- package/src/lib/translation-review.ts +0 -769
- package/src/notifications/device-zone-report.ts +0 -67
- package/src/notifications/feedback-notification-types-labels.ts +0 -33
- package/src/notifications/feedback-notification-types.ts +0 -71
- package/src/notifications/notification-bell.tsx +0 -119
- package/src/notifications/notification-inbox.tsx +0 -309
- package/src/notifications/notification-parts.tsx +0 -81
- package/src/notifications/notification-types-setting.tsx +0 -406
- package/src/notifications/notification-types.ts +0 -89
- package/src/notifications/notifications-labels.ts +0 -287
- package/src/notifications/push-device-setting.tsx +0 -230
- package/src/notifications/push-devices-setting.tsx +0 -374
- package/src/notifications/push-worker.ts +0 -168
- package/src/notifications/quiet-hours-setting.tsx +0 -238
- package/src/notifications/unsubscribe-panel.tsx +0 -200
- package/src/notifications/use-push-device.ts +0 -448
- package/src/offline/local-first.ts +0 -100
- package/src/offline/pwa-update-prompt-labels.ts +0 -9
- package/src/offline/pwa-update-prompt.tsx +0 -78
- package/src/offline/query-persistence.ts +0 -391
- package/src/offline/service-worker-updates.ts +0 -81
- package/src/offline/shared-computer-labels.ts +0 -8
- package/src/offline/shared-computer.tsx +0 -87
- package/src/offline/sign-out-pending-dialog-labels.ts +0 -21
- package/src/offline/sign-out-pending-dialog.tsx +0 -135
- package/src/offline.ts +0 -37
- package/src/push-worker.ts +0 -25
- package/src/rhf/fields.tsx +0 -2187
- package/src/rhf/form-core.tsx +0 -324
- package/src/rhf/form.tsx +0 -12
- package/src/rhf/line-items.tsx +0 -135
- package/src/rhf/use-rhf-wizard-step.ts +0 -104
- package/src/rhf.ts +0 -21
- package/src/search/command-palette-labels.ts +0 -16
- package/src/search/command-palette.tsx +0 -624
- package/src/search/global-search-labels.ts +0 -13
- package/src/search/global-search.tsx +0 -660
- package/src/search/search-index.ts +0 -283
- package/src/search/use-command-key.ts +0 -23
- package/src/search.ts +0 -14
- package/src/settings/device-reset-setting-labels.ts +0 -20
- package/src/settings/device-reset-setting.tsx +0 -116
- package/src/settings/settings-card-classes.ts +0 -11
- package/src/settings/settings-catalogue.ts +0 -150
- package/src/settings/settings-context.ts +0 -33
- package/src/settings/settings-heading.tsx +0 -67
- package/src/settings/settings-labels.ts +0 -87
- package/src/settings/settings-layout.tsx +0 -471
- package/src/settings/settings-section.tsx +0 -108
- package/src/settings/use-account-appearance.ts +0 -148
- package/src/settings/use-account-language.ts +0 -146
- package/src/settings/use-settings-focus.ts +0 -128
- package/src/settings/use-settings-route.ts +0 -258
- package/src/shell/account-menu-language.tsx +0 -130
- package/src/shell/account-menu-text-size.tsx +0 -80
- package/src/shell/admin-menu.tsx +0 -183
- package/src/shell/app-shell-labels.ts +0 -11
- package/src/shell/app-shell.tsx +0 -1560
- package/src/shell/auth-layout.tsx +0 -186
- package/src/shell/company-switcher-labels.ts +0 -13
- package/src/shell/company-switcher.tsx +0 -136
- package/src/shell/dev-menu.tsx +0 -257
- package/src/shell/fill-height.tsx +0 -45
- package/src/shell/language-code.ts +0 -5
- package/src/shell/option-switcher-menu.tsx +0 -84
- package/src/shell/sync-status-indicator.tsx +0 -303
- package/src/shell/top-bar-actions.tsx +0 -87
- package/src/shell/top-bar-brand.tsx +0 -78
- package/src/shell/top-bar-parts-labels.ts +0 -148
- package/src/shell/top-bar.tsx +0 -40
- package/src/shell/topbar-action-menu.tsx +0 -567
- package/src/shell/topbar-controls.tsx +0 -269
- package/src/shell/tour-menu.tsx +0 -187
- package/src/shell.ts +0 -108
- package/src/sync/db.ts +0 -129
- package/src/sync/engine.ts +0 -1011
- package/src/sync/hooks.ts +0 -98
- package/src/sync/testing.ts +0 -73
- package/src/sync/wire.ts +0 -61
- package/src/sync.ts +0 -37
- package/src/table-text.ts +0 -8
- package/src/testing/css-variables.generated.ts +0 -112
- package/src/testing/css-variables.ts +0 -189
- package/src/testing/index.ts +0 -29
- package/src/testing/react.ts +0 -58
- package/src/testing/tour.ts +0 -41
- package/src/testing/viewport.ts +0 -357
- package/src/theme/chart-palette.ts +0 -232
- package/src/theme/color.ts +0 -272
- package/src/theme/contrast-tokens.ts +0 -268
- package/src/theme/contrast.ts +0 -250
- package/src/theme/palette-derive.ts +0 -825
- package/src/theme/palette-presets.ts +0 -544
- package/src/theme/palette-store.ts +0 -108
- package/src/theme/text-size.ts +0 -289
- package/src/theme/theme-store.ts +0 -157
- package/src/tour/tour-catalogue-labels.ts +0 -75
- package/src/tour/tour-catalogue.tsx +0 -335
- package/src/tour/tour-dock.ts +0 -134
- package/src/tour/tour-engine.ts +0 -37
- package/src/tour/tour-gates.ts +0 -218
- package/src/tour/tour-guide-button.tsx +0 -64
- package/src/tour/tour-guide-labels.ts +0 -15
- package/src/tour/tour-info.ts +0 -144
- package/src/tour/tour-labels.ts +0 -23
- package/src/tour/tour-overlay.tsx +0 -1170
- package/src/tour/tour.tsx +0 -750
- package/src/tour/use-tour-progress.ts +0 -671
- package/src/tour/use-tour-url-sync.ts +0 -266
- package/src/tour.ts +0 -21
- package/src/vite-env.d.ts +0 -23
- package/src/wizard/stepper-nav.tsx +0 -360
- package/src/wizard/types.ts +0 -275
- package/src/wizard/use-wizard.ts +0 -560
- package/src/wizard/validation.ts +0 -39
- package/src/wizard/wizard-context.tsx +0 -74
- package/src/wizard/wizard-labels.ts +0 -29
- package/src/wizard/wizard-step.tsx +0 -76
- package/src/wizard/wizard-summary.tsx +0 -84
- package/src/wizard.ts +0 -15
package/src/components/chart.tsx
DELETED
|
@@ -1,554 +0,0 @@
|
|
|
1
|
-
// shadcn/ui chart kit — vendored (MIT) and adapted for this app:
|
|
2
|
-
// - Recharts 3 instead of 2
|
|
3
|
-
// - the original keys its styling off shadcn theme tokens (--muted-foreground,
|
|
4
|
-
// --border, bg-background …). This app has no shadcn token layer, so those
|
|
5
|
-
// are mapped onto this kit's own tokens (--text-muted, --border, --bg-surface
|
|
6
|
-
// …), which follow the active palette preset and flip with the theme by
|
|
7
|
-
// themselves — hence no `dark:` variants anywhere below.
|
|
8
|
-
// The value on show is the *structure*: config-driven colors injected as CSS
|
|
9
|
-
// vars, muted axis/grid styling, and a polished tooltip/legend — the things
|
|
10
|
-
// that make shadcn charts read as "designed" rather than "default Recharts".
|
|
11
|
-
import { createContext, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
12
|
-
import type { ComponentProps, CSSProperties, ReactNode, RefObject } from "react";
|
|
13
|
-
import { Legend as RechartsLegend, ResponsiveContainer, Tooltip as RechartsTooltip } from "recharts";
|
|
14
|
-
import { cn } from "../lib/cn";
|
|
15
|
-
import { isRtl } from "../lib/direction";
|
|
16
|
-
import { useFigureDescription } from "./chart-figure";
|
|
17
|
-
import { TYPOGRAPHIC_MINUS } from "../lib/minus";
|
|
18
|
-
|
|
19
|
-
export interface ChartSeriesConfig {
|
|
20
|
-
label: ReactNode;
|
|
21
|
-
color: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type ChartConfig = Record<string, ChartSeriesConfig>;
|
|
25
|
-
|
|
26
|
-
const ChartContext = createContext<ChartConfig | null>(null);
|
|
27
|
-
|
|
28
|
-
export function useChart(): ChartConfig {
|
|
29
|
-
const ctx = useContext(ChartContext);
|
|
30
|
-
if (!ctx) throw new Error("useChart must be used within a <ChartContainer />");
|
|
31
|
-
return ctx;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface ChartContainerProps extends ComponentProps<"div"> {
|
|
35
|
-
config: ChartConfig;
|
|
36
|
-
children: ComponentProps<typeof ResponsiveContainer>["children"];
|
|
37
|
-
/**
|
|
38
|
-
* What the chart SHOWS, in a sentence, as its accessible description (0.52): read through
|
|
39
|
-
* `aria-describedby`, after a caller's own ids, and drawn nowhere. Inside the root, so
|
|
40
|
-
* the chart stays the one element its parent lays out. Pair it with `role="figure"` and
|
|
41
|
-
* an `aria-label`, as `Treemap` and `SeriesChart` do.
|
|
42
|
-
*/
|
|
43
|
-
description?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* The shell every chart in the kit is drawn inside.
|
|
48
|
-
*
|
|
49
|
-
* **The plot is not mirrored in RTL.** An x axis is a number line or a timeline, and
|
|
50
|
-
* both run left-to-right in Hebrew and Arabic charts as much as in English ones; a
|
|
51
|
-
* time axis flipped to run right-to-left is the surprise, not the courtesy. So no
|
|
52
|
-
* `reversed` on any axis, and the SVG is pinned to `direction: ltr` — without that it
|
|
53
|
-
* inherits the page's `rtl`, which flips what `text-anchor: end` means, and the tick
|
|
54
|
-
* labels of a left-hand y axis are drawn INTO the plot instead of beside it. Text
|
|
55
|
-
* inside the SVG still shapes by its own script; only the anchoring is physical.
|
|
56
|
-
* The HTML around the plot — legend, tooltip, the zoom reset button — follows the
|
|
57
|
-
* page's direction like any other markup. A consumer who does want a mirrored
|
|
58
|
-
* category axis passes `reversed` on its own `XAxis`.
|
|
59
|
-
*/
|
|
60
|
-
export function ChartContainer({ id, className, children, config, description, ...props }: ChartContainerProps) {
|
|
61
|
-
const uid = useId();
|
|
62
|
-
const about = useFigureDescription(description, props["aria-describedby"]);
|
|
63
|
-
// The id is pasted into an UNQUOTED `[data-chart=…]` selector below, so it has to be
|
|
64
|
-
// a CSS identifier: one stray space or `#` and the browser discards the whole rule,
|
|
65
|
-
// taking every series colour with it — silently, because an invalid rule is not an
|
|
66
|
-
// error anywhere. `useId()` gives `:r0:`, and a consumer-supplied id gives whatever
|
|
67
|
-
// they typed, so both are filtered rather than just the colons.
|
|
68
|
-
const chartId = `chart-${(id ?? uid).replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
69
|
-
return (
|
|
70
|
-
<ChartContext.Provider value={config}>
|
|
71
|
-
<div
|
|
72
|
-
data-chart={chartId}
|
|
73
|
-
className={cn(
|
|
74
|
-
// touch-pan-y lets a vertical finger drag still scroll the page while
|
|
75
|
-
// a horizontal drag is handed to recharts for tooltip scrubbing,
|
|
76
|
-
// instead of the page scrolling underneath the gesture (feedback #292).
|
|
77
|
-
"flex w-full touch-pan-y justify-center text-xs",
|
|
78
|
-
// physical anchoring for the unmirrored plot (see the doc comment above)
|
|
79
|
-
"[&_.recharts-surface]:[direction:ltr]",
|
|
80
|
-
// muted axis labels + gridlines; one class each, since the tokens
|
|
81
|
-
// already carry the light/dark values
|
|
82
|
-
"[&_.recharts-cartesian-axis-tick_text]:fill-muted",
|
|
83
|
-
"[&_.recharts-cartesian-grid_line]:stroke-subtle/70",
|
|
84
|
-
// hairline hover cursor instead of the heavy default
|
|
85
|
-
"[&_.recharts-curve.recharts-tooltip-cursor]:stroke-strong",
|
|
86
|
-
"[&_.recharts-rectangle.recharts-tooltip-cursor]:fill-[var(--bg-hover)]",
|
|
87
|
-
// kill the focus outlines & white sector strokes Recharts adds
|
|
88
|
-
"[&_.recharts-sector]:outline-none [&_.recharts-sector[stroke='#fff']]:stroke-transparent",
|
|
89
|
-
"[&_.recharts-layer]:outline-none [&_.recharts-surface]:outline-none [&_.recharts-dot[stroke='#fff']]:stroke-transparent",
|
|
90
|
-
className,
|
|
91
|
-
)}
|
|
92
|
-
{...props}
|
|
93
|
-
aria-describedby={about.describedBy}
|
|
94
|
-
>
|
|
95
|
-
<ChartStyle id={chartId} config={config} />
|
|
96
|
-
<ResponsiveContainer width="100%" height="100%">
|
|
97
|
-
{children}
|
|
98
|
-
</ResponsiveContainer>
|
|
99
|
-
{about.node}
|
|
100
|
-
</div>
|
|
101
|
-
</ChartContext.Provider>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* A config key, which becomes the tail of a custom-property NAME.
|
|
107
|
-
*
|
|
108
|
-
* `dangerouslySetInnerHTML` means what it says: nothing below is escaped by React, and
|
|
109
|
-
* a `ChartConfig` is not necessarily written by hand — kastlan builds one from category
|
|
110
|
-
* rows in its database, so these keys are user data. A key containing `}` closes this
|
|
111
|
-
* rule, and whatever follows it in that key becomes a NEW rule — one that applies to
|
|
112
|
-
* the whole document rather than to this one chart.
|
|
113
|
-
*/
|
|
114
|
-
const CSS_IDENT = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* A config colour, which becomes a declaration VALUE.
|
|
118
|
-
*
|
|
119
|
-
* Every form a palette actually produces: both hex spellings, the functional notations
|
|
120
|
-
* — with the argument list restricted to the characters those functions can legally
|
|
121
|
-
* contain, so no `;`, no `}` and no nested `url(` — and `var(--token)`, which is what
|
|
122
|
-
* this kit's own `paletteFor`/`CHART_COLORS` return. `var()`'s optional FALLBACK is
|
|
123
|
-
* deliberately not accepted: its second argument is an arbitrary value, i.e. the same
|
|
124
|
-
* hole in a shape that looks safe.
|
|
125
|
-
*/
|
|
126
|
-
const CSS_COLOR = /^(?:#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6}|(?:rgba?|hsla?)\([0-9A-Za-z.,%/ -]*\)|var\(--[A-Za-z0-9_-]+\))$/;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* The colour an entry is painted with, or `undefined` when the style block refuses it.
|
|
130
|
-
*
|
|
131
|
-
* The one gate both sides go through: {@link ChartStyle} emits exactly these, and the
|
|
132
|
-
* legend and tooltip swatches show exactly these. They used to read `config[key].color`
|
|
133
|
-
* directly, so an entry the style block had skipped still showed its configured colour
|
|
134
|
-
* in the key — a swatch promising a colour the series was never painted in.
|
|
135
|
-
*/
|
|
136
|
-
function paintedColor(key: string, entry: ChartSeriesConfig | undefined): string | undefined {
|
|
137
|
-
if (!entry?.color) return undefined;
|
|
138
|
-
return CSS_IDENT.test(key) && CSS_COLOR.test(entry.color) ? entry.color : undefined;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Inject each series colour as a `--color-<key>` custom property scoped to this
|
|
142
|
-
// chart, so chart JSX can refer to `var(--color-total)` and the legend/tooltip
|
|
143
|
-
// stay in sync from one source of truth.
|
|
144
|
-
function ChartStyle({ id, config }: { id: string; config: ChartConfig }) {
|
|
145
|
-
const entries = Object.entries(config).filter(([key, c]) => {
|
|
146
|
-
if (!c.color) return false;
|
|
147
|
-
// Skipping the entry costs that one series its `var(--color-…)` and leaves the rest
|
|
148
|
-
// of the chart painted; emitting it unchecked costs the page. The warning is so the
|
|
149
|
-
// consumer finds out from their console rather than from a colourless bar.
|
|
150
|
-
if (!CSS_IDENT.test(key)) {
|
|
151
|
-
console.warn(`[ui-kit] chart config key is not a CSS identifier, skipped: ${key}`);
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
if (!CSS_COLOR.test(c.color)) {
|
|
155
|
-
console.warn(`[ui-kit] chart config colour for "${key}" is not a colour, skipped: ${c.color}`);
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
return true;
|
|
159
|
-
});
|
|
160
|
-
if (!entries.length) return null;
|
|
161
|
-
const css = `[data-chart=${id}] {\n${entries.map(([key, c]) => ` --color-${key}: ${c.color};`).join("\n")}\n}`;
|
|
162
|
-
return <style dangerouslySetInnerHTML={{ __html: css }} />;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* recharts' `Tooltip`, with `filterNull` defaulting to **false**.
|
|
167
|
-
*
|
|
168
|
-
* recharts drops every payload entry whose value is `null`/`undefined` before the
|
|
169
|
-
* content sees it, so the missing-value path {@link ChartTooltipContent} documents —
|
|
170
|
-
* the em dash, `formatValue(undefined)` — never ran under the default: a series with a
|
|
171
|
-
* gap at the cursor simply vanished from the tooltip, which reads as "this series does
|
|
172
|
-
* not exist here" rather than "it has no value here". Kept, the entry prints "—".
|
|
173
|
-
*
|
|
174
|
-
* The other half of that filter — dropping series drawn with `hide` — is redone by
|
|
175
|
-
* `ChartTooltipContent` itself (honouring `includeHidden`), so a legend toggle still
|
|
176
|
-
* takes a series out of the tooltip. Pass `filterNull` to get recharts' behaviour back.
|
|
177
|
-
*/
|
|
178
|
-
export function ChartTooltip(props: ComponentProps<typeof RechartsTooltip>) {
|
|
179
|
-
return <RechartsTooltip filterNull={false} {...props} />;
|
|
180
|
-
}
|
|
181
|
-
export const ChartLegend = RechartsLegend;
|
|
182
|
-
|
|
183
|
-
interface TooltipPayloadItem {
|
|
184
|
-
dataKey?: string | number;
|
|
185
|
-
name?: string | number;
|
|
186
|
-
value?: number | string;
|
|
187
|
-
color?: string;
|
|
188
|
-
/** A series drawn with `hide` — dropped here, see {@link ChartTooltip}. */
|
|
189
|
-
hide?: boolean;
|
|
190
|
-
payload?: Record<string, unknown>;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* What a series has no value for at this point: a gap in a history, a projection that
|
|
195
|
-
* has not happened yet, a field that did not exist at an earlier capture.
|
|
196
|
-
*
|
|
197
|
-
* An em dash rather than an empty cell, so the row still lines up with its siblings and
|
|
198
|
-
* the reader can see that the series WAS asked and had nothing, rather than wondering
|
|
199
|
-
* whether it was dropped. It is a mark, not a word, so there is nothing here to
|
|
200
|
-
* translate and no label prop to resolve; a caller who wants words passes
|
|
201
|
-
* `formatValue`, which is handed the `undefined` and decides.
|
|
202
|
-
*/
|
|
203
|
-
const NO_VALUE = "—";
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* The number this payload item carries, or `undefined` when it carries none.
|
|
207
|
-
*
|
|
208
|
-
* This was `item.value ?? 0`, so every one of the absences above printed a confident
|
|
209
|
-
* "0" that appears nowhere in the data — a fabricated figure in a tooltip, which is the
|
|
210
|
-
* one place a reader goes to check an exact number. keksdose found it and wrapped the
|
|
211
|
-
* component rather than trust it. `""` and a non-numeric string are the same absence
|
|
212
|
-
* spelled differently (recharts hands a string value straight through from the data),
|
|
213
|
-
* and are answered the same way.
|
|
214
|
-
*/
|
|
215
|
-
function tooltipValue(value: number | string | undefined): number | undefined {
|
|
216
|
-
if (value == null || value === "") return undefined;
|
|
217
|
-
const n = typeof value === "string" ? Number(value) : value;
|
|
218
|
-
return Number.isFinite(n) ? n : undefined;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
interface ChartTooltipContentProps {
|
|
222
|
-
active?: boolean;
|
|
223
|
-
payload?: TooltipPayloadItem[];
|
|
224
|
-
label?: string | number;
|
|
225
|
-
indicator?: "dot" | "line";
|
|
226
|
-
hideLabel?: boolean;
|
|
227
|
-
labelFormatter?: (label: string | number) => ReactNode;
|
|
228
|
-
/** Formats one series' value for display. NOT called when the series has no value at
|
|
229
|
-
* this point — {@link ChartTooltipContentProps.formatValue} is the one that is. */
|
|
230
|
-
valueFormatter?: (value: number) => ReactNode;
|
|
231
|
-
/** Formats one series' value INCLUDING its absence: handed `undefined` for a gap, a
|
|
232
|
-
* projection that has not happened yet, or a field that did not exist at an earlier
|
|
233
|
-
* capture, and whatever it returns is rendered as-is. Only the caller knows whether
|
|
234
|
-
* that absence reads as a dash, a "not yet" or a genuine zero, so this is how it
|
|
235
|
-
* says. Supplying it wins over `valueFormatter` for every value.
|
|
236
|
-
*
|
|
237
|
-
* It sits NEXT to `valueFormatter` rather than widening it because that prop's
|
|
238
|
-
* parameter is contextually typed at every call site there is — `(v) => money(v)` —
|
|
239
|
-
* so widening it to `number | undefined` is a compile error in all three consuming
|
|
240
|
-
* apps, which is a breaking change this module does not get to make by itself. */
|
|
241
|
-
formatValue?: (value: number | undefined) => ReactNode;
|
|
242
|
-
/** Cursor position within the chart, injected by recharts. Used with
|
|
243
|
-
* {@link boundaryRef} to decide whether to flip the tooltip. */
|
|
244
|
-
coordinate?: { x?: number; y?: number };
|
|
245
|
-
/** When set, the tooltip flips to the LEFT of the cursor if it would otherwise
|
|
246
|
-
* spill past the right edge of this (usually horizontally-scrolling) container
|
|
247
|
-
* — e.g. a wide chart whose rightmost bars sat off-screen (feedback #77). */
|
|
248
|
-
boundaryRef?: RefObject<HTMLElement | null>;
|
|
249
|
-
/** Injected by recharts: keep series drawn with `hide` in the tooltip. */
|
|
250
|
-
includeHidden?: boolean;
|
|
251
|
-
/**
|
|
252
|
-
* `"floating"` (the default): the box recharts moves with the cursor. `"readout"`: the
|
|
253
|
-
* same heading and values as a flat row for a FIXED place outside the plot — a
|
|
254
|
-
* `SeriesChart` whose `tooltip.placement` is `"above"`/`"below"` portals it there, so
|
|
255
|
-
* a finger on a phone no longer sits on the box it is trying to read (keksdose #359).
|
|
256
|
-
* No border, shadow, width cap or viewport nudge; the values flow in a grid whose
|
|
257
|
-
* column count depends on the row's width alone, so the row is the same height
|
|
258
|
-
* whatever is being pointed at — and, idle, it shows {@link idleKeys} with "—".
|
|
259
|
-
*/
|
|
260
|
-
variant?: "floating" | "readout";
|
|
261
|
-
/** Readout only: the series to list while nothing is active, so the row keeps the
|
|
262
|
-
* height it will have once something is. */
|
|
263
|
-
idleKeys?: readonly string[];
|
|
264
|
-
/** Readout only: the heading while nothing is active. Default "—". */
|
|
265
|
-
idleLabel?: ReactNode;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
export function ChartTooltipContent({
|
|
269
|
-
active,
|
|
270
|
-
payload,
|
|
271
|
-
label,
|
|
272
|
-
indicator = "dot",
|
|
273
|
-
hideLabel = false,
|
|
274
|
-
labelFormatter,
|
|
275
|
-
valueFormatter,
|
|
276
|
-
formatValue,
|
|
277
|
-
coordinate,
|
|
278
|
-
boundaryRef,
|
|
279
|
-
includeHidden = false,
|
|
280
|
-
variant = "floating",
|
|
281
|
-
idleKeys,
|
|
282
|
-
idleLabel,
|
|
283
|
-
}: ChartTooltipContentProps) {
|
|
284
|
-
const config = useChart();
|
|
285
|
-
const tipRef = useRef<HTMLDivElement>(null);
|
|
286
|
-
const readout = variant === "readout";
|
|
287
|
-
// `ChartTooltip` keeps null values (so they can print "—"), which also keeps the
|
|
288
|
-
// series a legend toggle switched off with `hide`; those go here instead.
|
|
289
|
-
const items = includeHidden ? payload : payload?.filter((item) => item.hide !== true);
|
|
290
|
-
const shown = Boolean(active && items?.length);
|
|
291
|
-
// Everything below that measures and moves the box is about a FLOATING one.
|
|
292
|
-
const visible = shown && !readout;
|
|
293
|
-
// Recharts anchors the tooltip at coordinate.x inside the full (scrolled) chart
|
|
294
|
-
// width; subtract the container's scrollLeft to get its on-screen x, then flip
|
|
295
|
-
// left if the tooltip's own width would run past the visible right edge.
|
|
296
|
-
//
|
|
297
|
-
// Both the cursor and the flip are PHYSICAL (the plot is never mirrored, see
|
|
298
|
-
// `ChartContainer`), but an RTL scroller counts `scrollLeft` from its right edge —
|
|
299
|
-
// 0 at the start, negative going left — so there the content's left edge sits
|
|
300
|
-
// `scrollWidth - clientWidth + scrollLeft` px to the left of the visible one.
|
|
301
|
-
//
|
|
302
|
-
// Measured in a layout effect (the DOM is not readable during render), so it commits
|
|
303
|
-
// before paint. `payload` and `label` are deps because they change the tooltip's own
|
|
304
|
-
// width, and recharts hands a fresh `payload` on every tooltip render, so a scroll
|
|
305
|
-
// followed by any re-render is re-measured just as it was when this ran in render.
|
|
306
|
-
const [flip, setFlip] = useState(false);
|
|
307
|
-
const x = coordinate?.x;
|
|
308
|
-
useLayoutEffect(() => {
|
|
309
|
-
const boundary = boundaryRef?.current;
|
|
310
|
-
if (!visible || !boundary || x == null) {
|
|
311
|
-
setFlip(false);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
const offset = isRtl(boundary)
|
|
315
|
-
? boundary.scrollWidth - boundary.clientWidth + boundary.scrollLeft
|
|
316
|
-
: boundary.scrollLeft;
|
|
317
|
-
const visibleX = x - offset;
|
|
318
|
-
const tipWidth = tipRef.current?.offsetWidth ?? 160;
|
|
319
|
-
setFlip(visibleX + tipWidth + 12 > boundary.clientWidth);
|
|
320
|
-
}, [visible, x, boundaryRef, payload, label]);
|
|
321
|
-
|
|
322
|
-
// Whatever placed it — recharts' own rule or the boundary flip above — the box then
|
|
323
|
-
// clamps itself into the viewport, 8px off each edge. The width cap alone did not
|
|
324
|
-
// keep it on screen: on a 390px phone recharts opened a near-full-width tooltip to
|
|
325
|
-
// the RIGHT of a pointer 35% into the plot, and the values ran off the edge
|
|
326
|
-
// (lenkbank, on 0.15.2). Measured after placement, minus the shift it already has,
|
|
327
|
-
// so a re-measure never compounds; an unmeasured box (no layout) is left alone.
|
|
328
|
-
const [nudge, setNudge] = useState(0);
|
|
329
|
-
const nudgeRef = useRef(0);
|
|
330
|
-
// recharts slides its wrapper to each new position with a CSS transition, so the box
|
|
331
|
-
// measured on commit is still where it WAS; measure again once the slide ends.
|
|
332
|
-
const [settled, setSettled] = useState(0);
|
|
333
|
-
useEffect(() => {
|
|
334
|
-
const wrapper = tipRef.current?.closest<HTMLElement>(".recharts-tooltip-wrapper");
|
|
335
|
-
if (!visible || !wrapper) return;
|
|
336
|
-
const onEnd = () => setSettled((n) => n + 1);
|
|
337
|
-
wrapper.addEventListener("transitionend", onEnd);
|
|
338
|
-
return () => wrapper.removeEventListener("transitionend", onEnd);
|
|
339
|
-
}, [visible]);
|
|
340
|
-
useLayoutEffect(() => {
|
|
341
|
-
const el = tipRef.current;
|
|
342
|
-
if (!visible || !el) {
|
|
343
|
-
nudgeRef.current = 0;
|
|
344
|
-
setNudge(0);
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
const rect = el.getBoundingClientRect();
|
|
348
|
-
if (rect.width === 0) return;
|
|
349
|
-
const margin = 8;
|
|
350
|
-
const viewport = document.documentElement.clientWidth || window.innerWidth;
|
|
351
|
-
const left = rect.left - nudgeRef.current;
|
|
352
|
-
const right = left + rect.width;
|
|
353
|
-
let next = 0;
|
|
354
|
-
if (right > viewport - margin) next = viewport - margin - right;
|
|
355
|
-
if (left + next < margin) next = margin - left;
|
|
356
|
-
if (next !== nudgeRef.current) {
|
|
357
|
-
nudgeRef.current = next;
|
|
358
|
-
setNudge(next);
|
|
359
|
-
}
|
|
360
|
-
}, [visible, x, payload, label, flip, settled]);
|
|
361
|
-
// One series' line — the floating box stacks them; the readout lays them in a grid,
|
|
362
|
-
// where a long name is cut rather than wrapped so every cell stays one line high.
|
|
363
|
-
const tooltipRow = (item: TooltipPayloadItem, i: number, inRow: boolean) => {
|
|
364
|
-
// Bars/lines/areas identify a series by dataKey; pies/treemaps key off
|
|
365
|
-
// `name` (the nameKey value). Prefer whichever the config knows.
|
|
366
|
-
const dk = item.dataKey != null ? String(item.dataKey) : undefined;
|
|
367
|
-
const nm = item.name != null ? String(item.name) : undefined;
|
|
368
|
-
const cfgKey = dk && config[dk] ? dk : nm && config[nm] ? nm : (dk ?? nm ?? String(i));
|
|
369
|
-
const series = config[cfgKey];
|
|
370
|
-
const fill = typeof item.payload?.fill === "string" ? item.payload.fill : undefined;
|
|
371
|
-
// The data point's own `fill` before recharts' `item.color`: a treemap tile,
|
|
372
|
-
// or a bar with a per-cell colour, IS the colour the reader is pointing at,
|
|
373
|
-
// while `item.color` is the series-wide one — every tile's swatch came out
|
|
374
|
-
// `--chart-1` whatever colour the tile was.
|
|
375
|
-
const color = paintedColor(cfgKey, series) ?? fill ?? item.color ?? "var(--text-muted)";
|
|
376
|
-
const name = series?.label ?? nm ?? cfgKey;
|
|
377
|
-
const raw = tooltipValue(item.value);
|
|
378
|
-
let text: ReactNode;
|
|
379
|
-
// An idle readout cell has asked nothing yet, so there is no absence for
|
|
380
|
-
// `formatValue` to word — it is the bare mark.
|
|
381
|
-
if (inRow && !shown) text = NO_VALUE;
|
|
382
|
-
else if (formatValue) text = formatValue(raw);
|
|
383
|
-
else if (raw == null) text = NO_VALUE;
|
|
384
|
-
// The bare number's minus is U+2212, as every kit figure's (0.49, KIT-1).
|
|
385
|
-
else text = valueFormatter ? valueFormatter(raw) : String(raw).replace(/-/g, TYPOGRAPHIC_MINUS);
|
|
386
|
-
return (
|
|
387
|
-
<div
|
|
388
|
-
key={`${cfgKey}-${i}`}
|
|
389
|
-
// A readout cell is capped so a wide row does not push its value a column away
|
|
390
|
-
// from its name.
|
|
391
|
-
className={cn("flex items-center", inRow ? "min-w-0 max-w-[12rem] gap-1.5" : "gap-2")}
|
|
392
|
-
>
|
|
393
|
-
<span
|
|
394
|
-
className={cn("shrink-0 rounded-[2px]", indicator === "dot" ? "h-2.5 w-2.5 rounded-full" : "h-2.5 w-1")}
|
|
395
|
-
style={{ backgroundColor: color }}
|
|
396
|
-
/>
|
|
397
|
-
<span className={cn("min-w-0 text-muted", inRow ? "truncate" : "break-words")}>{name}</span>
|
|
398
|
-
<span
|
|
399
|
-
data-private
|
|
400
|
-
// Isolated, so an RTL page does not turn "-26.6" into "26.6-": a figure has no
|
|
401
|
-
// strong direction of its own, and one formatted with an RTL mark keeps it.
|
|
402
|
-
dir="auto"
|
|
403
|
-
className="ms-auto shrink-0 whitespace-nowrap font-mono font-medium tabular-nums text-primary"
|
|
404
|
-
>
|
|
405
|
-
{text}
|
|
406
|
-
</span>
|
|
407
|
-
</div>
|
|
408
|
-
);
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
if (readout) {
|
|
412
|
-
// Idle, the row lists every series with no value — the same cells it will have, so
|
|
413
|
-
// nothing under it moves on the first tap.
|
|
414
|
-
const rows: TooltipPayloadItem[] = shown
|
|
415
|
-
? items!
|
|
416
|
-
: (idleKeys ?? Object.keys(config)).map((key) => ({ dataKey: key }));
|
|
417
|
-
return (
|
|
418
|
-
<div className="text-xs" data-chart-readout={shown ? "active" : "idle"}>
|
|
419
|
-
{/* A full 24 px line: the zoom's reset button sits at the top corner of a chart
|
|
420
|
-
whose row is above it, and has to fit beside the heading, not over a value. */}
|
|
421
|
-
<div data-readout-heading className="truncate font-medium leading-6 text-primary">
|
|
422
|
-
{shown && !hideLabel && label != null
|
|
423
|
-
? labelFormatter
|
|
424
|
-
? labelFormatter(label)
|
|
425
|
-
: label
|
|
426
|
-
: (idleLabel ?? NO_VALUE)}
|
|
427
|
-
</div>
|
|
428
|
-
<div className="grid grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] gap-x-4 gap-y-1">
|
|
429
|
-
{rows.map((item, i) => tooltipRow(item, i, true))}
|
|
430
|
-
</div>
|
|
431
|
-
</div>
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
if (!visible || !items) return null;
|
|
435
|
-
return (
|
|
436
|
-
<div
|
|
437
|
-
ref={tipRef}
|
|
438
|
-
style={
|
|
439
|
-
boundaryRef || nudge
|
|
440
|
-
? {
|
|
441
|
-
transform: [
|
|
442
|
-
boundaryRef ? (flip ? "translateX(calc(-100% - 12px))" : "translateX(12px)") : "",
|
|
443
|
-
nudge ? `translateX(${nudge}px)` : "",
|
|
444
|
-
]
|
|
445
|
-
.filter(Boolean)
|
|
446
|
-
.join(" "),
|
|
447
|
-
}
|
|
448
|
-
: undefined
|
|
449
|
-
}
|
|
450
|
-
// Capped at the viewport: six long series names (lenkbank's German motion
|
|
451
|
-
// labels) made the box wider than a 390px chart, and recharts, which keeps a box
|
|
452
|
-
// inside the plot only when it fits, let it run off the edge with the values cut.
|
|
453
|
-
// Names wrap inside the cap; the values never do.
|
|
454
|
-
className="min-w-[9rem] max-w-[min(20rem,calc(100vw-2rem))] rounded-lg border border-subtle bg-surface px-2.5 py-2 text-xs shadow-xl"
|
|
455
|
-
>
|
|
456
|
-
{!hideLabel && label != null && (
|
|
457
|
-
<div className="mb-1.5 font-medium text-primary">{labelFormatter ? labelFormatter(label) : label}</div>
|
|
458
|
-
)}
|
|
459
|
-
<div className="grid gap-1.5">{items.map((item, i) => tooltipRow(item, i, false))}</div>
|
|
460
|
-
</div>
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
interface LegendPayloadItem {
|
|
465
|
-
value?: string;
|
|
466
|
-
dataKey?: string | number;
|
|
467
|
-
color?: string;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
interface ChartLegendContentProps {
|
|
471
|
-
payload?: LegendPayloadItem[];
|
|
472
|
-
onItemClick?: (key: string) => void;
|
|
473
|
-
/**
|
|
474
|
-
* TOGGLE mode (recommended): the series currently switched off. Each entry is a
|
|
475
|
-
* toggle button — pressed while its series is shown — and a hidden one is drawn
|
|
476
|
-
* faded with its label struck through. Several can be off at once; pair with
|
|
477
|
-
* `toggleHidden(hidden, key)` in `onItemClick` and `hide` on the chart's series.
|
|
478
|
-
*/
|
|
479
|
-
hiddenKeys?: ReadonlySet<string> | readonly string[];
|
|
480
|
-
/**
|
|
481
|
-
* ISOLATE mode: the one series shown in full, every other entry dimmed. Kept for
|
|
482
|
-
* the charts built on it; a legend where each entry switches its own series is
|
|
483
|
-
* what readers expect from a legend, so prefer `hiddenKeys`.
|
|
484
|
-
*/
|
|
485
|
-
activeKey?: string | null;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
export function ChartLegendContent({ payload, onItemClick, hiddenKeys, activeKey }: ChartLegendContentProps) {
|
|
489
|
-
const hidden = hiddenKeys ? new Set(hiddenKeys) : null;
|
|
490
|
-
const config = useChart();
|
|
491
|
-
if (!payload?.length) return null;
|
|
492
|
-
return (
|
|
493
|
-
<div className="flex flex-wrap items-center justify-center gap-x-4 gap-y-1 pt-3">
|
|
494
|
-
{payload.map((item, i) => {
|
|
495
|
-
const dk = item.dataKey != null ? String(item.dataKey) : undefined;
|
|
496
|
-
const vv = item.value != null ? String(item.value) : undefined;
|
|
497
|
-
const cfgKey = dk && config[dk] ? dk : vv && config[vv] ? vv : (dk ?? vv ?? String(i));
|
|
498
|
-
const series = config[cfgKey];
|
|
499
|
-
const color = paintedColor(cfgKey, series) ?? item.color ?? "var(--text-muted)";
|
|
500
|
-
const label = series?.label ?? vv ?? cfgKey;
|
|
501
|
-
const off = hidden?.has(cfgKey) ?? false;
|
|
502
|
-
const dimmed = off || (activeKey != null && activeKey !== cfgKey);
|
|
503
|
-
// The label's cue, in a key and on a button alike: a hidden series struck through,
|
|
504
|
-
// and an entry an isolate legend dims in the muted ink — drawn still, so not struck.
|
|
505
|
-
// Only a toggle button had one, and a key or an isolate legend told an entry off by
|
|
506
|
-
// its 10px swatch at 40 % alone (0.52 code review, deep, charts, finding 9).
|
|
507
|
-
const cue = off ? "line-through" : dimmed ? "text-muted" : undefined;
|
|
508
|
-
const className = cn(
|
|
509
|
-
"flex items-center gap-1.5 text-secondary transition-opacity",
|
|
510
|
-
onItemClick ? "cursor-pointer hover:opacity-80" : "cursor-default",
|
|
511
|
-
);
|
|
512
|
-
// Only the swatch fades; the label keeps an ink of AA contrast (0.52, refactor audit
|
|
513
|
-
// 2026-10-30, DSP-9). The whole entry at 40 % put a switched-off label under 2:1,
|
|
514
|
-
// on a button that brings its series back and is named by nothing else.
|
|
515
|
-
const swatch = (
|
|
516
|
-
<span
|
|
517
|
-
aria-hidden
|
|
518
|
-
className={cn("h-2.5 w-2.5 shrink-0 rounded-[3px]", dimmed && "opacity-40")}
|
|
519
|
-
style={{ backgroundColor: color } as CSSProperties}
|
|
520
|
-
/>
|
|
521
|
-
);
|
|
522
|
-
// A legend with no `onItemClick` is a KEY, not a control — and that is every
|
|
523
|
-
// legend in kastlan, where this rendered N focusable buttons per chart that did
|
|
524
|
-
// nothing when activated. A keyboard user paid the tab stops for all of them,
|
|
525
|
-
// and a screen reader announced each one as a button, promising an action there
|
|
526
|
-
// was none of. The interactive branch is unchanged.
|
|
527
|
-
return onItemClick ? (
|
|
528
|
-
<button
|
|
529
|
-
key={`${cfgKey}-${i}`}
|
|
530
|
-
type="button"
|
|
531
|
-
onClick={() => onItemClick(cfgKey)}
|
|
532
|
-
// Toggles report their state: in toggle mode pressed = the series is shown;
|
|
533
|
-
// in isolate mode pressed = the isolated one. With neither supplied the
|
|
534
|
-
// legend knows nothing about state, and a pressed="false" it cannot vouch
|
|
535
|
-
// for would lie — so it says nothing.
|
|
536
|
-
aria-pressed={hidden ? !off : activeKey === undefined ? undefined : activeKey === cfgKey}
|
|
537
|
-
className={className}
|
|
538
|
-
>
|
|
539
|
-
{swatch}
|
|
540
|
-
<span className={cue}>{label}</span>
|
|
541
|
-
</button>
|
|
542
|
-
) : (
|
|
543
|
-
// On the entry, not round the label: the text is its own, so the key's DOM is the
|
|
544
|
-
// same with a cue as without. A line-through reaches the text only (the swatch
|
|
545
|
-
// holds none), and the ink colours no swatch.
|
|
546
|
-
<span key={`${cfgKey}-${i}`} className={cn(className, cue)}>
|
|
547
|
-
{swatch}
|
|
548
|
-
{label}
|
|
549
|
-
</span>
|
|
550
|
-
);
|
|
551
|
-
})}
|
|
552
|
-
</div>
|
|
553
|
-
);
|
|
554
|
-
}
|