basalt-ui 1.30.2 → 1.32.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/AGENTS.md +1 -1
- package/CHANGELOG.md +54 -0
- package/MIGRATING.md +256 -12
- package/agent/rules/basalt-controls.md +19 -19
- package/agent/rules/basalt-mantine.md +5 -5
- package/configs/oxlint-plugin.js +371 -4
- package/configs/oxlint-plugin.test.ts +327 -2
- package/configs/oxlint.json +2 -1
- package/dist/agent-chat/composer.d.ts.map +1 -1
- package/dist/agent-chat/composer.js +41 -43
- package/dist/agent-chat/thread-workspace.d.ts +2 -2
- package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
- package/dist/agent-chat/thread-workspace.js +3 -4
- package/dist/agent-chat/use-keyboard-inset.d.ts +2 -0
- package/dist/agent-chat/use-keyboard-inset.d.ts.map +1 -0
- package/dist/agent-chat/use-keyboard-inset.js +34 -0
- package/dist/charts/cursor/touch-pin.d.ts +45 -0
- package/dist/charts/cursor/touch-pin.d.ts.map +1 -0
- package/dist/charts/cursor/touch-pin.js +79 -0
- package/dist/charts/hooks/use-discrete-cursor.d.ts +66 -0
- package/dist/charts/hooks/use-discrete-cursor.d.ts.map +1 -0
- package/dist/charts/hooks/use-discrete-cursor.js +198 -0
- package/dist/charts/hooks/use-hysteresis.d.ts +18 -0
- package/dist/charts/hooks/use-hysteresis.d.ts.map +1 -0
- package/dist/charts/hooks/use-hysteresis.js +12 -0
- package/dist/charts/hooks/useBandPlot.d.ts +7 -0
- package/dist/charts/hooks/useBandPlot.d.ts.map +1 -1
- package/dist/charts/hooks/useBandPlot.js +62 -18
- package/dist/charts/hooks/useChartCursor.d.ts +40 -11
- package/dist/charts/hooks/useChartCursor.d.ts.map +1 -1
- package/dist/charts/hooks/useChartCursor.js +102 -11
- package/dist/charts/index.d.ts +0 -1
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +0 -10
- package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
- package/dist/charts/kinds/BandStrip.js +47 -82
- package/dist/charts/kinds/Donut.d.ts +9 -3
- package/dist/charts/kinds/Donut.d.ts.map +1 -1
- package/dist/charts/kinds/Donut.js +110 -48
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.js +138 -145
- package/dist/charts/kinds/Heatmap.d.ts +7 -0
- package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
- package/dist/charts/kinds/Heatmap.js +37 -16
- package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
- package/dist/charts/kinds/MirroredBars.js +68 -111
- package/dist/charts/kinds/band-chrome.d.ts +31 -0
- package/dist/charts/kinds/band-chrome.d.ts.map +1 -0
- package/dist/charts/kinds/band-chrome.js +71 -0
- package/dist/charts/kinds/donut-layout.d.ts +47 -0
- package/dist/charts/kinds/donut-layout.d.ts.map +1 -0
- package/dist/charts/kinds/donut-layout.js +52 -0
- package/dist/charts/layout/auto-margin.d.ts +7 -2
- package/dist/charts/layout/auto-margin.d.ts.map +1 -1
- package/dist/charts/layout/auto-margin.js +12 -3
- package/dist/charts/layout/end-labels.d.ts +64 -0
- package/dist/charts/layout/end-labels.d.ts.map +1 -0
- package/dist/charts/layout/end-labels.js +76 -0
- package/dist/charts/primitives/Axes.d.ts +32 -4
- package/dist/charts/primitives/Axes.d.ts.map +1 -1
- package/dist/charts/primitives/Axes.js +62 -16
- package/dist/charts/primitives/CartesianChart.d.ts +7 -6
- package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
- package/dist/charts/primitives/CartesianChart.js +264 -145
- package/dist/charts/primitives/ChartCard.d.ts +0 -14
- package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.js +56 -21
- package/dist/charts/primitives/ChartFrame.d.ts +28 -22
- package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
- package/dist/charts/primitives/ChartFrame.js +116 -34
- package/dist/charts/primitives/ChartLegend.d.ts +19 -15
- package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
- package/dist/charts/primitives/ChartLegend.js +86 -73
- package/dist/charts/primitives/ChartTooltip.d.ts +5 -0
- package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
- package/dist/charts/primitives/ChartTooltip.js +20 -4
- package/dist/charts/primitives/Crosshair.js +2 -2
- package/dist/charts/primitives/HoverOverlay.d.ts +29 -9
- package/dist/charts/primitives/HoverOverlay.d.ts.map +1 -1
- package/dist/charts/primitives/HoverOverlay.js +54 -27
- package/dist/charts/primitives/HoverOverlay.module.css +13 -0
- package/dist/charts/primitives/HoverOverlay.module.css.d.ts +8 -0
- package/dist/charts/primitives/chart-card-context.d.ts +33 -0
- package/dist/charts/primitives/chart-card-context.d.ts.map +1 -0
- package/dist/charts/primitives/chart-card-context.js +18 -0
- package/dist/charts/primitives/chart-frame-layout.d.ts +93 -113
- package/dist/charts/primitives/chart-frame-layout.d.ts.map +1 -1
- package/dist/charts/primitives/chart-frame-layout.js +75 -34
- package/dist/charts/primitives/chart-layout.d.ts +112 -0
- package/dist/charts/primitives/chart-layout.d.ts.map +1 -0
- package/dist/charts/primitives/chart-layout.js +175 -0
- package/dist/charts/primitives/chart-tier.d.ts +13 -11
- package/dist/charts/primitives/chart-tier.d.ts.map +1 -1
- package/dist/charts/primitives/chart-tier.js +42 -13
- package/dist/charts/primitives/legend-disclosure.d.ts +27 -0
- package/dist/charts/primitives/legend-disclosure.d.ts.map +1 -0
- package/dist/charts/primitives/legend-disclosure.js +153 -0
- package/dist/charts/series.d.ts +4 -1
- package/dist/charts/series.d.ts.map +1 -1
- package/dist/charts/utils/ticks.d.ts +27 -8
- package/dist/charts/utils/ticks.d.ts.map +1 -1
- package/dist/charts/utils/ticks.js +35 -11
- package/dist/common/errors.d.ts +11 -1
- package/dist/common/errors.d.ts.map +1 -1
- package/dist/common/errors.js +16 -2
- package/dist/common/hit-floor.d.ts +10 -0
- package/dist/common/hit-floor.d.ts.map +1 -0
- package/dist/common/hit-floor.js +6 -0
- package/dist/{shell → common}/isomorphic-layout-effect.d.ts +4 -3
- package/dist/common/isomorphic-layout-effect.d.ts.map +1 -0
- package/dist/common/use-measured-widths.d.ts +37 -0
- package/dist/common/use-measured-widths.d.ts.map +1 -0
- package/dist/common/use-measured-widths.js +51 -0
- package/dist/common/use-media-query.d.ts +6 -0
- package/dist/common/use-media-query.d.ts.map +1 -0
- package/dist/common/use-media-query.js +40 -0
- package/dist/common/validate.d.ts +9 -0
- package/dist/common/validate.d.ts.map +1 -1
- package/dist/common/validate.js +9 -4
- package/dist/content/article-layout.d.ts +4 -2
- package/dist/content/article-layout.d.ts.map +1 -1
- package/dist/content/article-layout.js +43 -3
- package/dist/content/article-layout.module.css +45 -4
- package/dist/content/article-layout.module.css.d.ts +3 -0
- package/dist/content/code-block.d.ts.map +1 -1
- package/dist/content/code-block.js +40 -2
- package/dist/content/code-block.module.css +32 -2
- package/dist/content/prose.module.css +13 -8
- package/dist/controls/actions.d.ts +29 -6
- package/dist/controls/actions.d.ts.map +1 -1
- package/dist/controls/actions.js +158 -27
- package/dist/controls/actions.module.css +14 -1
- package/dist/controls/actions.module.css.d.ts +1 -0
- package/dist/controls/controls.module.css +13 -31
- package/dist/controls/enum-filter.js +2 -2
- package/dist/controls/filter-context.d.ts +10 -0
- package/dist/controls/filter-context.d.ts.map +1 -1
- package/dist/controls/filter-context.js +2 -0
- package/dist/controls/filter-pill.d.ts.map +1 -1
- package/dist/controls/filter-pill.js +1 -0
- package/dist/controls/index.d.ts +1 -1
- package/dist/controls/index.d.ts.map +1 -1
- package/dist/controls/index.js +0 -2
- package/dist/controls/multi-select-filter.js +2 -2
- package/dist/controls/sync-button.module.css +2 -1
- package/dist/dashboard/section.d.ts.map +1 -1
- package/dist/dashboard/section.js +1 -0
- package/dist/dashboard/section.module.css +1 -26
- package/dist/dashboard/stat-card.d.ts +1 -1
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +4 -1
- package/dist/dashboard/stat-card.module.css +6 -9
- package/dist/dashboard/stat-group.module.css +33 -66
- package/dist/dashboard/widget-grid.d.ts.map +1 -1
- package/dist/dashboard/widget-grid.module.css +11 -38
- package/dist/dashboard/widget-header.d.ts +14 -4
- package/dist/dashboard/widget-header.d.ts.map +1 -1
- package/dist/dashboard/widget-header.js +23 -6
- package/dist/dashboard/widget-header.module.css +145 -133
- package/dist/dashboard/widget-header.module.css.d.ts +2 -0
- package/dist/data/data-table-state.d.ts +83 -0
- package/dist/data/data-table-state.d.ts.map +1 -0
- package/dist/data/data-table-state.js +139 -0
- package/dist/data/data-table.d.ts +56 -2
- package/dist/data/data-table.d.ts.map +1 -1
- package/dist/data/data-table.js +436 -336
- package/dist/data/data-table.module.css +94 -0
- package/dist/data/data-table.module.css.d.ts +11 -0
- package/dist/data/virtual-list.d.ts.map +1 -1
- package/dist/data/virtual-list.js +10 -0
- package/dist/forms/form-layout.d.ts.map +1 -1
- package/dist/forms/form-layout.js +3 -3
- package/dist/forms/form-layout.module.css +20 -5
- package/dist/forms/form-layout.module.css.d.ts +1 -0
- package/dist/guard/index.d.ts +8 -2
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +68 -2
- package/dist/guard/types.d.ts +3 -3
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/notifications/center.d.ts.map +1 -1
- package/dist/provider/index.d.ts +20 -1
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +30 -8
- package/dist/shell/app-brand.d.ts.map +1 -1
- package/dist/shell/app-brand.js +1 -0
- package/dist/shell/app-brand.module.css +2 -2
- package/dist/shell/app-header.module.css +18 -8
- package/dist/shell/app-main.module.css +54 -3
- package/dist/shell/app-main.module.css.d.ts +1 -0
- package/dist/shell/app-mobile-nav.module.css +16 -4
- package/dist/shell/app-sidebar.module.css +4 -6
- package/dist/shell/aside-docking.d.ts +31 -0
- package/dist/shell/aside-docking.d.ts.map +1 -0
- package/dist/shell/aside-docking.js +19 -0
- package/dist/shell/index.d.ts +1 -0
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +56 -16
- package/dist/shell/mobile-nav-model.d.ts +1 -1
- package/dist/shell/page-aside.d.ts +22 -3
- package/dist/shell/page-aside.d.ts.map +1 -1
- package/dist/shell/page-aside.js +27 -13
- package/dist/shell/page-bar.d.ts.map +1 -1
- package/dist/shell/page-bar.js +10 -5
- package/dist/shell/page-bar.module.css +10 -34
- package/dist/shell/use-breakpoint.d.ts +3 -4
- package/dist/shell/use-breakpoint.d.ts.map +1 -1
- package/dist/shell/use-breakpoint.js +3 -25
- package/dist/shell/use-size-class.d.ts +6 -0
- package/dist/shell/use-size-class.d.ts.map +1 -0
- package/dist/shell/use-size-class.js +19 -0
- package/dist/state/persisted-or-local.d.ts +4 -1
- package/dist/state/persisted-or-local.d.ts.map +1 -1
- package/dist/state/persisted-or-local.js +4 -3
- package/dist/state/persisted.d.ts +10 -0
- package/dist/state/persisted.d.ts.map +1 -1
- package/dist/state/persisted.js +44 -14
- package/dist/styles.css +41 -0
- package/dist/surfaces.d.ts +4 -4
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +11 -3
- package/dist/theme/controls.module.css +7 -0
- package/dist/theme/ctl-theme.d.ts +1 -0
- package/dist/theme/ctl-theme.d.ts.map +1 -1
- package/dist/theme/ctl-theme.js +12 -4
- package/dist/theme/floating.module.css +37 -0
- package/dist/theme/floating.module.css.d.ts +3 -0
- package/dist/theme/index.d.ts +2 -2
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +34 -5
- package/dist/theme/nav-link.module.css +7 -0
- package/dist/theme-lab/derive-controls.d.ts.map +1 -1
- package/dist/tokens/index.d.ts +7 -16
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +23 -28
- package/dist/tokens/palette.d.ts +5 -27
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +8 -30
- package/dist/tokens/size-classes.d.ts +40 -0
- package/dist/tokens/size-classes.d.ts.map +1 -0
- package/dist/tokens/size-classes.js +29 -0
- package/dist/tokens.css +8 -4
- package/llms.txt +3 -3
- package/package.json +18 -17
- package/src/agent-chat/composer.tsx +74 -47
- package/src/agent-chat/thread-workspace.tsx +8 -11
- package/src/agent-chat/use-keyboard-inset.ts +68 -0
- package/src/charts/cursor/touch-pin.ts +138 -0
- package/src/charts/hooks/use-discrete-cursor.ts +335 -0
- package/src/charts/hooks/use-hysteresis.ts +26 -0
- package/src/charts/hooks/useBandPlot.ts +90 -27
- package/src/charts/hooks/useChartCursor.ts +211 -26
- package/src/charts/index.ts +0 -8
- package/src/charts/kinds/BandStrip.tsx +25 -61
- package/src/charts/kinds/Donut.tsx +153 -62
- package/src/charts/kinds/DualPanel.tsx +21 -26
- package/src/charts/kinds/Heatmap.tsx +61 -22
- package/src/charts/kinds/MirroredBars.tsx +23 -65
- package/src/charts/kinds/band-chrome.tsx +91 -0
- package/src/charts/kinds/donut-layout.ts +82 -0
- package/src/charts/layout/auto-margin.ts +24 -5
- package/src/charts/layout/end-labels.ts +135 -0
- package/src/charts/primitives/Axes.tsx +112 -21
- package/src/charts/primitives/CartesianChart.tsx +282 -111
- package/src/charts/primitives/ChartCard.tsx +119 -48
- package/src/charts/primitives/ChartFrame.tsx +204 -60
- package/src/charts/primitives/ChartLegend.tsx +115 -78
- package/src/charts/primitives/ChartTooltip.tsx +24 -3
- package/src/charts/primitives/Crosshair.tsx +2 -2
- package/src/charts/primitives/HoverOverlay.module.css +13 -0
- package/src/charts/primitives/HoverOverlay.module.css.d.ts +8 -0
- package/src/charts/primitives/HoverOverlay.tsx +62 -20
- package/src/charts/primitives/chart-card-context.ts +46 -0
- package/src/charts/primitives/chart-frame-layout.ts +207 -182
- package/src/charts/primitives/chart-layout.ts +318 -0
- package/src/charts/primitives/chart-tier.tsx +66 -21
- package/src/charts/primitives/legend-disclosure.tsx +177 -0
- package/src/charts/series.ts +4 -1
- package/src/charts/utils/ticks.ts +95 -19
- package/src/common/errors.ts +25 -1
- package/src/common/hit-floor.ts +9 -0
- package/src/{shell → common}/isomorphic-layout-effect.ts +4 -3
- package/src/common/use-measured-widths.ts +88 -0
- package/src/common/use-media-query.ts +56 -0
- package/src/common/validate.ts +17 -4
- package/src/content/article-layout.module.css +45 -4
- package/src/content/article-layout.module.css.d.ts +3 -0
- package/src/content/article-layout.tsx +60 -5
- package/src/content/code-block.module.css +32 -2
- package/src/content/code-block.tsx +47 -3
- package/src/content/prose.module.css +13 -8
- package/src/controls/actions.module.css +14 -1
- package/src/controls/actions.module.css.d.ts +1 -0
- package/src/controls/actions.tsx +223 -75
- package/src/controls/controls.module.css +13 -31
- package/src/controls/enum-filter.tsx +2 -2
- package/src/controls/filter-context.tsx +11 -0
- package/src/controls/filter-pill.tsx +1 -0
- package/src/controls/index.ts +0 -1
- package/src/controls/multi-select-filter.tsx +2 -2
- package/src/controls/sync-button.module.css +2 -1
- package/src/dashboard/section.module.css +1 -26
- package/src/dashboard/section.tsx +1 -0
- package/src/dashboard/stat-card.module.css +6 -9
- package/src/dashboard/stat-card.tsx +6 -3
- package/src/dashboard/stat-group.module.css +33 -66
- package/src/dashboard/widget-grid.module.css +11 -38
- package/src/dashboard/widget-grid.tsx +7 -6
- package/src/dashboard/widget-header.module.css +145 -133
- package/src/dashboard/widget-header.module.css.d.ts +2 -0
- package/src/dashboard/widget-header.tsx +45 -11
- package/src/data/data-table-state.ts +218 -0
- package/src/data/data-table.module.css +94 -0
- package/src/data/data-table.module.css.d.ts +11 -0
- package/src/data/data-table.tsx +547 -299
- package/src/data/virtual-list.tsx +31 -0
- package/src/forms/form-layout.module.css +20 -5
- package/src/forms/form-layout.module.css.d.ts +1 -0
- package/src/forms/form-layout.tsx +12 -10
- package/src/guard/index.ts +188 -3
- package/src/guard/types.ts +3 -2
- package/src/index.ts +2 -0
- package/src/notifications/center.tsx +3 -0
- package/src/provider/index.tsx +60 -7
- package/src/shell/app-brand.module.css +2 -2
- package/src/shell/app-brand.tsx +1 -0
- package/src/shell/app-header.module.css +18 -8
- package/src/shell/app-main.module.css +54 -3
- package/src/shell/app-main.module.css.d.ts +1 -0
- package/src/shell/app-mobile-nav.module.css +16 -4
- package/src/shell/app-sidebar.module.css +4 -6
- package/src/shell/aside-docking.ts +54 -0
- package/src/shell/index.tsx +178 -129
- package/src/shell/mobile-nav-model.ts +1 -1
- package/src/shell/page-aside.tsx +70 -21
- package/src/shell/page-bar.module.css +10 -34
- package/src/shell/page-bar.tsx +10 -5
- package/src/shell/use-breakpoint.ts +9 -45
- package/src/shell/use-size-class.ts +31 -0
- package/src/state/persisted-or-local.ts +10 -4
- package/src/state/persisted.ts +76 -17
- package/src/styles.css +41 -0
- package/src/surfaces.ts +9 -1
- package/src/theme/controls.module.css +7 -0
- package/src/theme/ctl-theme.tsx +15 -3
- package/src/theme/floating.module.css +37 -0
- package/src/theme/floating.module.css.d.ts +3 -0
- package/src/theme/index.ts +46 -8
- package/src/theme/nav-link.module.css +7 -0
- package/src/theme-lab/derive-controls.tsx +2 -0
- package/src/tokens/index.ts +20 -30
- package/src/tokens/palette.ts +6 -28
- package/src/tokens/size-classes.ts +46 -0
- package/dist/shell/isomorphic-layout-effect.d.ts.map +0 -1
- /package/dist/{shell → common}/isomorphic-layout-effect.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touch-pin.d.ts","sourceRoot":"","sources":["../../../src/charts/cursor/touch-pin.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,QAAQ,EACR,SAAS,EACT,eAAuB,EACvB,kBAA0B,GAC3B,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB;sDACkD;IAClD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,KAAK,OAAO,CAAA;IACpC,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB;8FAC0F;IAC1F,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;oGACgG;IAChG,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,GAAG,IAAI,CA2BP;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB;gGAC4F;IAC5F,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,kGAAkG;IAClG,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAA;IACtC;;sGAEkG;IAClG,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAA;IACtC;qFACiF;IACjF,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAC7B,YAAY,EACZ,YAAY,GACb,EAAE;IACD,0FAA0F;IAC1F,YAAY,EAAE,MAAM,CAAC,CAAA;IACrB,YAAY,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;CACjC,GAAG,QAAQ,CAiDX"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
function useDismissOnOutside({
|
|
3
|
+
enabled,
|
|
4
|
+
isInside,
|
|
5
|
+
onDismiss,
|
|
6
|
+
dismissOnResize = false,
|
|
7
|
+
scrollExemptInside = false
|
|
8
|
+
}) {
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (!enabled) return;
|
|
11
|
+
const onPointerDown = (event) => {
|
|
12
|
+
if (event.target instanceof Node && isInside?.(event.target) === true) return;
|
|
13
|
+
onDismiss();
|
|
14
|
+
};
|
|
15
|
+
const onKeyDown = (event) => {
|
|
16
|
+
if (event.key === "Escape") onDismiss();
|
|
17
|
+
};
|
|
18
|
+
const onScroll = (event) => {
|
|
19
|
+
if (scrollExemptInside && event.target instanceof Node && isInside?.(event.target) === true) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
onDismiss();
|
|
23
|
+
};
|
|
24
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
25
|
+
document.addEventListener("keydown", onKeyDown);
|
|
26
|
+
document.addEventListener("scroll", onScroll, true);
|
|
27
|
+
if (dismissOnResize) window.addEventListener("resize", onDismiss);
|
|
28
|
+
return () => {
|
|
29
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
30
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
31
|
+
document.removeEventListener("scroll", onScroll, true);
|
|
32
|
+
if (dismissOnResize) window.removeEventListener("resize", onDismiss);
|
|
33
|
+
};
|
|
34
|
+
}, [enabled, isInside, onDismiss, dismissOnResize, scrollExemptInside]);
|
|
35
|
+
}
|
|
36
|
+
function useTouchPin({
|
|
37
|
+
getCommitted,
|
|
38
|
+
setCommitted
|
|
39
|
+
}) {
|
|
40
|
+
const pressRef = useRef(null);
|
|
41
|
+
const backupRef = useRef(void 0);
|
|
42
|
+
const hasBackupRef = useRef(false);
|
|
43
|
+
const getCommittedRef = useRef(getCommitted);
|
|
44
|
+
getCommittedRef.current = getCommitted;
|
|
45
|
+
const setCommittedRef = useRef(setCommitted);
|
|
46
|
+
setCommittedRef.current = setCommitted;
|
|
47
|
+
const begin = useCallback((pointerId) => {
|
|
48
|
+
backupRef.current = getCommittedRef.current();
|
|
49
|
+
hasBackupRef.current = true;
|
|
50
|
+
pressRef.current = pointerId;
|
|
51
|
+
}, []);
|
|
52
|
+
const commit = useCallback((pointerId) => {
|
|
53
|
+
if (pressRef.current !== pointerId) return false;
|
|
54
|
+
pressRef.current = null;
|
|
55
|
+
backupRef.current = void 0;
|
|
56
|
+
hasBackupRef.current = false;
|
|
57
|
+
return true;
|
|
58
|
+
}, []);
|
|
59
|
+
const cancel = useCallback((pointerId) => {
|
|
60
|
+
if (pressRef.current !== pointerId) return false;
|
|
61
|
+
pressRef.current = null;
|
|
62
|
+
const backup = backupRef.current;
|
|
63
|
+
const hasBackup = hasBackupRef.current;
|
|
64
|
+
backupRef.current = void 0;
|
|
65
|
+
hasBackupRef.current = false;
|
|
66
|
+
if (hasBackup) setCommittedRef.current(backup);
|
|
67
|
+
return true;
|
|
68
|
+
}, []);
|
|
69
|
+
const reset = useCallback(() => {
|
|
70
|
+
pressRef.current = null;
|
|
71
|
+
backupRef.current = void 0;
|
|
72
|
+
hasBackupRef.current = false;
|
|
73
|
+
}, []);
|
|
74
|
+
return useMemo(() => ({ begin, commit, cancel, reset }), [begin, commit, cancel, reset]);
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
useDismissOnOutside,
|
|
78
|
+
useTouchPin
|
|
79
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { KeyboardEventHandler, PointerEventHandler } from 'react';
|
|
2
|
+
/** A discrete target plus the viewport-space point its tooltip anchors to. */
|
|
3
|
+
export type DiscreteCursorTip<T> = {
|
|
4
|
+
target: T;
|
|
5
|
+
anchor: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export type UseDiscreteCursorResult<T> = {
|
|
11
|
+
/** The target whose tooltip should render, resolved from whichever mode last set it (hover, a
|
|
12
|
+
* touch pin, or keyboard focus). `null` when nothing is active. */
|
|
13
|
+
tip: DiscreteCursorTip<T> | null;
|
|
14
|
+
/** True once a coarse-pointer tap has PINNED `tip` open (survives pointer lift). */
|
|
15
|
+
isPinned: boolean;
|
|
16
|
+
/** Pointer handlers for one target's shape — spread onto its `<g>`/`<rect>`. Fine pointers
|
|
17
|
+
* (mouse/pen) hover; a coarse pointer (touch) pins on `pointerdown` instead. */
|
|
18
|
+
pointerProps: (t: T) => {
|
|
19
|
+
onPointerEnter: PointerEventHandler<Element>;
|
|
20
|
+
onPointerMove: PointerEventHandler<Element>;
|
|
21
|
+
onPointerDown: PointerEventHandler<Element>;
|
|
22
|
+
onPointerUp: PointerEventHandler<Element>;
|
|
23
|
+
onPointerLeave: PointerEventHandler<Element>;
|
|
24
|
+
onPointerCancel: PointerEventHandler<Element>;
|
|
25
|
+
};
|
|
26
|
+
/** DOM id for a target's `role="option"` element — also `aria-activedescendant`'s value while
|
|
27
|
+
* that target is active. Spread `id={optionId(t)}` on the same node that gets `pointerProps`. */
|
|
28
|
+
optionId: (t: T) => string;
|
|
29
|
+
/** Dismisses a pin and clears keyboard focus. Already wired to Escape and an outside tap while
|
|
30
|
+
* pinned; call it directly for anything else that should close the tooltip (e.g. data changing
|
|
31
|
+
* out from under the focused key). */
|
|
32
|
+
clear: () => void;
|
|
33
|
+
/** Spread on the ONE shared, focusable host (the chart's `<svg>`). */
|
|
34
|
+
hostProps: {
|
|
35
|
+
ref: (node: Element | null) => void;
|
|
36
|
+
tabIndex: 0;
|
|
37
|
+
role: 'listbox';
|
|
38
|
+
'aria-label': string;
|
|
39
|
+
'aria-activedescendant': string | undefined;
|
|
40
|
+
onKeyDown: KeyboardEventHandler<Element>;
|
|
41
|
+
onBlur: () => void;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Keyboard + focus + tap parity for a DISCRETE set of targets (donut slices, heatmap cells) — the
|
|
46
|
+
* counterpart `HoverOverlay` gives a continuous cartesian domain (`docs/CHARTS-SPEC.md` §4).
|
|
47
|
+
*
|
|
48
|
+
* **Role choice**: `listbox`/`option` (WAI-ARIA APG "Listbox"), not `slider`. A cartesian domain is
|
|
49
|
+
* one continuous value; a donut slice or heatmap cell is a named choice among discrete siblings.
|
|
50
|
+
* `aria-activedescendant` announces the focused option's id while DOM focus stays on the one host.
|
|
51
|
+
*
|
|
52
|
+
* Three input modes converge on one `tip`: hover (fine pointer, ephemeral), a provisional tap that
|
|
53
|
+
* `pointerup` commits into a pin (a `pointercancel` first — a scroll — clears it), and keyboard
|
|
54
|
+
* stepping on the one focusable host (`columns` maps Up/Down to a full-row jump for a 2D grid;
|
|
55
|
+
* Left/Right always step by one). Keyboard focus anchors the tooltip to the host's center — an
|
|
56
|
+
* accepted simplification; the value still reaches a screen reader via the option's text.
|
|
57
|
+
*/
|
|
58
|
+
export declare function useDiscreteCursor<T>({ targets, getKey, columns, ariaLabel, }: {
|
|
59
|
+
targets: readonly T[];
|
|
60
|
+
getKey: (t: T) => string;
|
|
61
|
+
/** Row width for a 2D grid — see the Up/Down mapping above. Omit for a 1D ring. */
|
|
62
|
+
columns?: number;
|
|
63
|
+
/** Accessible name for the shared listbox host. */
|
|
64
|
+
ariaLabel?: string;
|
|
65
|
+
}): UseDiscreteCursorResult<T>;
|
|
66
|
+
//# sourceMappingURL=use-discrete-cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-discrete-cursor.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/use-discrete-cursor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EAEpB,mBAAmB,EACpB,MAAM,OAAO,CAAA;AAGd,8EAA8E;AAC9E,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAA;AAIlF,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI;IACvC;uEACmE;IACnE,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAChC,oFAAoF;IACpF,QAAQ,EAAE,OAAO,CAAA;IACjB;oFACgF;IAChF,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK;QACtB,cAAc,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAA;QAC5C,aAAa,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAA;QAC3C,aAAa,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAA;QAC3C,WAAW,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAA;QACzC,cAAc,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAA;QAC5C,eAAe,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAA;KAC9C,CAAA;IACD;qGACiG;IACjG,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IAC1B;;0CAEsC;IACtC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,sEAAsE;IACtE,SAAS,EAAE;QACT,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAA;QACnC,QAAQ,EAAE,CAAC,CAAA;QACX,IAAI,EAAE,SAAS,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAA;QAC3C,SAAS,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;QACxC,MAAM,EAAE,MAAM,IAAI,CAAA;KACnB,CAAA;CACF,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,EACnC,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAwE,GACzE,EAAE;IACD,OAAO,EAAE,SAAS,CAAC,EAAE,CAAA;IACrB,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,uBAAuB,CAAC,CAAC,CAAC,CAoQ7B"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { useDismissOnOutside, useTouchPin } from "../cursor/touch-pin.js";
|
|
3
|
+
function useDiscreteCursor({
|
|
4
|
+
targets,
|
|
5
|
+
getKey,
|
|
6
|
+
columns,
|
|
7
|
+
ariaLabel = "Chart data \u2014 use arrow keys to navigate, Escape to dismiss"
|
|
8
|
+
}) {
|
|
9
|
+
const [active, setActive] = useState(null);
|
|
10
|
+
const [pinned, setPinned] = useState(false);
|
|
11
|
+
const hostElRef = useRef(null);
|
|
12
|
+
const idPrefix = useId();
|
|
13
|
+
const activeRef = useRef(active);
|
|
14
|
+
activeRef.current = active;
|
|
15
|
+
const pinnedRef = useRef(pinned);
|
|
16
|
+
pinnedRef.current = pinned;
|
|
17
|
+
const targetsRef = useRef(targets);
|
|
18
|
+
targetsRef.current = targets;
|
|
19
|
+
const getKeyRef = useRef(getKey);
|
|
20
|
+
getKeyRef.current = getKey;
|
|
21
|
+
const columnsRef = useRef(columns);
|
|
22
|
+
columnsRef.current = columns;
|
|
23
|
+
const moveFrameRef = useRef(null);
|
|
24
|
+
const pendingActiveRef = useRef(null);
|
|
25
|
+
useEffect(
|
|
26
|
+
() => () => {
|
|
27
|
+
if (moveFrameRef.current !== null) cancelAnimationFrame(moveFrameRef.current);
|
|
28
|
+
},
|
|
29
|
+
[]
|
|
30
|
+
);
|
|
31
|
+
const scheduleActive = useCallback((next) => {
|
|
32
|
+
pendingActiveRef.current = next;
|
|
33
|
+
if (moveFrameRef.current !== null) return;
|
|
34
|
+
moveFrameRef.current = requestAnimationFrame(() => {
|
|
35
|
+
moveFrameRef.current = null;
|
|
36
|
+
setActive(pendingActiveRef.current);
|
|
37
|
+
});
|
|
38
|
+
}, []);
|
|
39
|
+
const cancelPendingFrame = useCallback(() => {
|
|
40
|
+
if (moveFrameRef.current !== null) {
|
|
41
|
+
cancelAnimationFrame(moveFrameRef.current);
|
|
42
|
+
moveFrameRef.current = null;
|
|
43
|
+
}
|
|
44
|
+
pendingActiveRef.current = null;
|
|
45
|
+
}, []);
|
|
46
|
+
const touchPin = useTouchPin({
|
|
47
|
+
getCommitted: () => pinnedRef.current ? activeRef.current : null,
|
|
48
|
+
setCommitted: (value) => {
|
|
49
|
+
setActive(value);
|
|
50
|
+
setPinned(value !== null);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const clear = useCallback(() => {
|
|
54
|
+
cancelPendingFrame();
|
|
55
|
+
touchPin.reset();
|
|
56
|
+
setActive(null);
|
|
57
|
+
setPinned(false);
|
|
58
|
+
}, [touchPin, cancelPendingFrame]);
|
|
59
|
+
const isInsideHost = useCallback(
|
|
60
|
+
(target) => hostElRef.current?.contains(target) === true,
|
|
61
|
+
[]
|
|
62
|
+
);
|
|
63
|
+
useDismissOnOutside({ enabled: pinned, isInside: isInsideHost, onDismiss: clear });
|
|
64
|
+
const indexByKey = useMemo(() => {
|
|
65
|
+
const map = /* @__PURE__ */ new Map();
|
|
66
|
+
targets.forEach((t, i) => map.set(getKeyRef.current(t), i));
|
|
67
|
+
return map;
|
|
68
|
+
}, [targets]);
|
|
69
|
+
const optionId = useCallback(
|
|
70
|
+
(t) => `${idPrefix}-${indexByKey.get(getKeyRef.current(t)) ?? -1}`,
|
|
71
|
+
[idPrefix, indexByKey]
|
|
72
|
+
);
|
|
73
|
+
const findTarget = (key) => {
|
|
74
|
+
const index = indexByKey.get(key);
|
|
75
|
+
return index === void 0 ? void 0 : targetsRef.current[index];
|
|
76
|
+
};
|
|
77
|
+
const pointerProps = (t) => {
|
|
78
|
+
const key = getKeyRef.current(t);
|
|
79
|
+
const showAt = (event) => {
|
|
80
|
+
scheduleActive({ key, anchor: { x: event.clientX, y: event.clientY } });
|
|
81
|
+
};
|
|
82
|
+
const cancelIfUncommitted = (event) => touchPin.cancel(event.pointerId);
|
|
83
|
+
return {
|
|
84
|
+
onPointerEnter: (event) => {
|
|
85
|
+
if (event.pointerType !== "mouse" || pinned) return;
|
|
86
|
+
showAt(event);
|
|
87
|
+
},
|
|
88
|
+
onPointerMove: (event) => {
|
|
89
|
+
if (event.pointerType !== "mouse" || pinned) return;
|
|
90
|
+
showAt(event);
|
|
91
|
+
},
|
|
92
|
+
// Only a coarse pointer presses — a fine pointer's `down` is a no-op, it already shows via
|
|
93
|
+
// enter/move above. The press is PROVISIONAL: it snapshots whatever is committed now (so a
|
|
94
|
+
// cancel can restore it) BEFORE showing the readout, which only `onPointerUp` commits. On
|
|
95
|
+
// touch the readout anchors to the HOST's top edge rather than the finger, which would cover
|
|
96
|
+
// it; a missing host falls back to the pointer.
|
|
97
|
+
onPointerDown: (event) => {
|
|
98
|
+
if (event.pointerType === "mouse") return;
|
|
99
|
+
touchPin.begin(event.pointerId);
|
|
100
|
+
cancelPendingFrame();
|
|
101
|
+
const rect = hostElRef.current?.getBoundingClientRect();
|
|
102
|
+
setActive({
|
|
103
|
+
key,
|
|
104
|
+
anchor: rect === void 0 ? { x: event.clientX, y: event.clientY } : { x: rect.left + rect.width / 2, y: rect.top }
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
// A completed tap commits the pin. Only the tracked pointer commits — and only a coarse one:
|
|
108
|
+
// some browsers assign a touch's `pointerId` the same value (1) mouse pointers use, so a
|
|
109
|
+
// `pointerType` check keeps an unrelated mouse `pointerup` reusing that id from committing an
|
|
110
|
+
// abandoned touch press.
|
|
111
|
+
onPointerUp: (event) => {
|
|
112
|
+
if (event.pointerType === "mouse") return;
|
|
113
|
+
if (!touchPin.commit(event.pointerId)) return;
|
|
114
|
+
setPinned(true);
|
|
115
|
+
},
|
|
116
|
+
// A still-uncommitted press ending here is the browser taking the gesture (a scroll); clear it
|
|
117
|
+
// regardless of `pinned`. Otherwise keep the fine-pointer/pinned guard. Routes through the
|
|
118
|
+
// same `clear()` the outside-tap/Escape dismissal uses (mirrors `useChartCursor`'s own
|
|
119
|
+
// `onPointerLeave`) rather than a bare `setActive(null)` — a `pointermove` scheduled just
|
|
120
|
+
// before this event fires is still in flight (coalesced onto `moveFrameRef`/
|
|
121
|
+
// `pendingActiveRef`), and only `clear()` cancels it. A bare `setActive(null)` left that frame
|
|
122
|
+
// free to land a tick later and resurrect the tooltip this leave/cancel was meant to dismiss.
|
|
123
|
+
onPointerLeave: (event) => {
|
|
124
|
+
if (cancelIfUncommitted(event)) return;
|
|
125
|
+
if (event.pointerType !== "mouse" || pinned) return;
|
|
126
|
+
clear();
|
|
127
|
+
},
|
|
128
|
+
onPointerCancel: (event) => {
|
|
129
|
+
if (cancelIfUncommitted(event)) return;
|
|
130
|
+
if (event.pointerType !== "mouse" || pinned) return;
|
|
131
|
+
clear();
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
const onKeyDown = (event) => {
|
|
136
|
+
const list = targetsRef.current;
|
|
137
|
+
if (list.length === 0) return;
|
|
138
|
+
if (event.key === "Escape") {
|
|
139
|
+
clear();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const cols = columnsRef.current;
|
|
143
|
+
let delta = 0;
|
|
144
|
+
switch (event.key) {
|
|
145
|
+
case "ArrowRight":
|
|
146
|
+
delta = 1;
|
|
147
|
+
break;
|
|
148
|
+
case "ArrowLeft":
|
|
149
|
+
delta = -1;
|
|
150
|
+
break;
|
|
151
|
+
case "ArrowDown":
|
|
152
|
+
delta = cols ?? 1;
|
|
153
|
+
break;
|
|
154
|
+
case "ArrowUp":
|
|
155
|
+
delta = -(cols ?? 1);
|
|
156
|
+
break;
|
|
157
|
+
default:
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
const currentIndex = active === null ? -1 : list.findIndex((t) => getKeyRef.current(t) === active.key);
|
|
162
|
+
const base = currentIndex === -1 ? delta > 0 ? -1 : list.length : currentIndex;
|
|
163
|
+
const nextIndex = Math.min(Math.max(base + delta, 0), list.length - 1);
|
|
164
|
+
const next = list[nextIndex];
|
|
165
|
+
const rect = hostElRef.current?.getBoundingClientRect();
|
|
166
|
+
const anchor = rect === void 0 ? { x: 0, y: 0 } : { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
|
|
167
|
+
cancelPendingFrame();
|
|
168
|
+
setActive({ key: getKeyRef.current(next), anchor });
|
|
169
|
+
};
|
|
170
|
+
const tip = (() => {
|
|
171
|
+
if (active === null) return null;
|
|
172
|
+
const target = findTarget(active.key);
|
|
173
|
+
return target === void 0 ? null : { target, anchor: active.anchor };
|
|
174
|
+
})();
|
|
175
|
+
return {
|
|
176
|
+
tip,
|
|
177
|
+
isPinned: pinned,
|
|
178
|
+
pointerProps,
|
|
179
|
+
optionId,
|
|
180
|
+
clear,
|
|
181
|
+
hostProps: {
|
|
182
|
+
ref: (node) => {
|
|
183
|
+
hostElRef.current = node;
|
|
184
|
+
},
|
|
185
|
+
tabIndex: 0,
|
|
186
|
+
role: "listbox",
|
|
187
|
+
"aria-label": ariaLabel,
|
|
188
|
+
"aria-activedescendant": tip === null ? void 0 : optionId(tip.target),
|
|
189
|
+
onKeyDown,
|
|
190
|
+
onBlur: () => {
|
|
191
|
+
if (!pinned) clear();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
export {
|
|
197
|
+
useDiscreteCursor
|
|
198
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A derived value that feeds back into its own next computation — hysteresis, "was X last frame" —
|
|
3
|
+
* without the anti-pattern of mutating a ref during render (`ChartCard`'s short-card flag, P0-1;
|
|
4
|
+
* `Donut`'s side/stacked layout, P2-10, both hit the SAME bug independently: a render a concurrent
|
|
5
|
+
* commit discards must not still poison the next real one's input).
|
|
6
|
+
*
|
|
7
|
+
* `compute` is called with the PREVIOUS committed value (never mutated here) and returns this
|
|
8
|
+
* render's value; the ref only updates in a `useLayoutEffect`, after the value has actually
|
|
9
|
+
* committed. Internal only — not on any public barrel.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const short = useHysteresis(
|
|
13
|
+
* (wasShort) => measuredHeight > 0 && measuredHeight < (wasShort ? EXIT : ENTER),
|
|
14
|
+
* false,
|
|
15
|
+
* )
|
|
16
|
+
*/
|
|
17
|
+
export declare function useHysteresis<T>(compute: (previous: T) => T, initial: T): T;
|
|
18
|
+
//# sourceMappingURL=use-hysteresis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-hysteresis.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/use-hysteresis.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAO3E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useLayoutEffect, useRef } from "react";
|
|
2
|
+
function useHysteresis(compute, initial) {
|
|
3
|
+
const ref = useRef(initial);
|
|
4
|
+
const value = compute(ref.current);
|
|
5
|
+
useLayoutEffect(() => {
|
|
6
|
+
ref.current = value;
|
|
7
|
+
}, [value]);
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
useHysteresis
|
|
12
|
+
};
|
|
@@ -122,6 +122,13 @@ export type BandPlot<T> = {
|
|
|
122
122
|
/** Drawn width of one band — the pitch minus a 1px separator, floored at 1. */
|
|
123
123
|
bandWidth: number;
|
|
124
124
|
tickValues: string[];
|
|
125
|
+
/** Where the left axis paints: inside the plot (compact), not at all (micro), else outside. An
|
|
126
|
+
* explicit `margin.left` keeps it outside. Same law as `CartesianChart`. */
|
|
127
|
+
yPlacement: 'outside' | 'inside' | 'none';
|
|
128
|
+
/** Terminal x labels anchor inward (compact/micro). */
|
|
129
|
+
xAnchorTerminals: boolean;
|
|
130
|
+
/** Width to wrap x labels to; undefined when they do not wrap. */
|
|
131
|
+
xWrapWidth: number | undefined;
|
|
125
132
|
svgRef: RefObject<SVGSVGElement | null>;
|
|
126
133
|
tooltipAnchor: CursorAnchor | null;
|
|
127
134
|
showTooltip: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBandPlot.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useBandPlot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"useBandPlot.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useBandPlot.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { scaleBand } from "@visx/scale";
|
|
2
2
|
import { useCallback, useMemo, useRef } from "react";
|
|
3
3
|
import { autoMargin } from "../layout/auto-margin.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
isTightClass,
|
|
6
|
+
planXLabels,
|
|
7
|
+
resolveMarginFloor,
|
|
8
|
+
resolveYPlacement
|
|
9
|
+
} from "../primitives/chart-layout.js";
|
|
10
|
+
import { useChartContainerClass, useChartMetrics } from "../primitives/chart-tier.js";
|
|
5
11
|
import { maxTextWidth } from "../utils/measure-text.js";
|
|
6
12
|
import { smartTicks, xLabelPxFor } from "../utils/ticks.js";
|
|
7
13
|
import { useChartCursor } from "./useChartCursor.js";
|
|
@@ -29,27 +35,47 @@ function useBandPlot(input) {
|
|
|
29
35
|
margin: marginOverride,
|
|
30
36
|
tooltip
|
|
31
37
|
} = input;
|
|
32
|
-
const tier =
|
|
38
|
+
const tier = useChartMetrics();
|
|
39
|
+
const containerClass = useChartContainerClass();
|
|
40
|
+
const tight = isTightClass(containerClass);
|
|
33
41
|
const hasLeftAxis = leftLabels !== void 0 && leftLabels.length > 0;
|
|
42
|
+
const yPlacement = resolveYPlacement(containerClass, {
|
|
43
|
+
hasLeftAxis,
|
|
44
|
+
marginOverrideLeft: marginOverride?.left
|
|
45
|
+
});
|
|
34
46
|
const xLabelsAll = useMemo(() => data.map((d) => formatX(getX(d))), [data, getX, formatX]);
|
|
47
|
+
const xPlan = useMemo(
|
|
48
|
+
() => planXLabels({
|
|
49
|
+
labels: xLabelsAll,
|
|
50
|
+
plotWidth: width - tier.margin.left - tier.margin.right,
|
|
51
|
+
fontPx: tier.axisFont,
|
|
52
|
+
categorical: tight
|
|
53
|
+
}),
|
|
54
|
+
[xLabelsAll, width, tier.margin, tier.axisFont, tight]
|
|
55
|
+
);
|
|
56
|
+
const xWrapWidth = xPlan.wrap ? xPlan.wrapPx : void 0;
|
|
35
57
|
const margin = useMemo(() => {
|
|
36
58
|
const measured = autoMargin({
|
|
37
|
-
...leftLabels !== void 0 && { left: leftLabels },
|
|
59
|
+
...leftLabels !== void 0 && { left: yPlacement === "outside" ? leftLabels : [] },
|
|
38
60
|
bottom: xLabelsAll,
|
|
39
61
|
fontPx: tier.axisFont,
|
|
40
|
-
floor
|
|
62
|
+
// An inside-placed left axis paints IN the plot, so the outside label-width floor is dead
|
|
63
|
+
// space there — same law as `CartesianChart`'s `marginInput.floor`.
|
|
64
|
+
floor: resolveMarginFloor(yPlacement, tier.margin),
|
|
65
|
+
anchorTerminals: tight,
|
|
66
|
+
bottomLines: xPlan.lines,
|
|
41
67
|
...marginOverride !== void 0 && { override: marginOverride }
|
|
42
68
|
});
|
|
43
69
|
if (marginOverride?.left !== void 0 && marginOverride.right !== void 0) return measured;
|
|
44
70
|
const halfXLabel = Math.ceil(maxTextWidth(xLabelsAll, tier.axisFont) / 2);
|
|
45
|
-
const left = hasLeftAxis ? measured.left : Math.max(measured.left, halfXLabel);
|
|
71
|
+
const left = hasLeftAxis || tight ? measured.left : Math.max(measured.left, halfXLabel);
|
|
46
72
|
return {
|
|
47
73
|
...measured,
|
|
48
74
|
...marginOverride?.left === void 0 && {
|
|
49
|
-
left: hasLeftAxis ? left : capTerminalGutter(left, width, TERMINAL_GUTTER_MAX_FRACTION.left, tier.margin.left)
|
|
75
|
+
left: hasLeftAxis || tight ? left : capTerminalGutter(left, width, TERMINAL_GUTTER_MAX_FRACTION.left, tier.margin.left)
|
|
50
76
|
},
|
|
51
77
|
...marginOverride?.right === void 0 && {
|
|
52
|
-
right: capTerminalGutter(
|
|
78
|
+
right: tight ? measured.right : capTerminalGutter(
|
|
53
79
|
measured.right,
|
|
54
80
|
width,
|
|
55
81
|
TERMINAL_GUTTER_MAX_FRACTION.right,
|
|
@@ -57,7 +83,18 @@ function useBandPlot(input) {
|
|
|
57
83
|
)
|
|
58
84
|
}
|
|
59
85
|
};
|
|
60
|
-
}, [
|
|
86
|
+
}, [
|
|
87
|
+
leftLabels,
|
|
88
|
+
xLabelsAll,
|
|
89
|
+
marginOverride,
|
|
90
|
+
hasLeftAxis,
|
|
91
|
+
width,
|
|
92
|
+
tier.axisFont,
|
|
93
|
+
tier.margin,
|
|
94
|
+
tight,
|
|
95
|
+
yPlacement,
|
|
96
|
+
xPlan.lines
|
|
97
|
+
]);
|
|
61
98
|
const plotWidth = Math.max(width - margin.left - margin.right, 0);
|
|
62
99
|
const minBandPx = fold?.minBandPx ?? DEFAULT_MIN_BAND_PX;
|
|
63
100
|
const merge = fold?.merge;
|
|
@@ -77,31 +114,35 @@ function useBandPlot(input) {
|
|
|
77
114
|
},
|
|
78
115
|
[scale]
|
|
79
116
|
);
|
|
117
|
+
const svgRef = useRef(null);
|
|
80
118
|
const cursor = useChartCursor({
|
|
81
119
|
data: bands,
|
|
82
120
|
chartId,
|
|
83
121
|
getKey: getX,
|
|
84
122
|
xScale: bandCenter,
|
|
85
123
|
marginLeft: margin.left,
|
|
124
|
+
// Both callers (`BandStrip`, `MirroredBars`) mount exactly one `<svg ref={band.svgRef}>`, so
|
|
125
|
+
// it doubles as the tap-outside boundary (`docs/CHARTS-SPEC.md` §4, Tooltip) with no separate
|
|
126
|
+
// passthrough option — reusing the ref this hook already returns, not a new one.
|
|
127
|
+
boundaryRef: svgRef,
|
|
86
128
|
...cursorResolution !== void 0 && { resolution: cursorResolution }
|
|
87
129
|
});
|
|
88
130
|
const xLabelPx = useMemo(
|
|
89
|
-
() => xLabelPxFor(keys.map(formatX), tier.axisFont),
|
|
90
|
-
[keys, formatX, tier.axisFont]
|
|
131
|
+
() => xWrapWidth === void 0 ? xLabelPxFor(keys.map(formatX), tier.axisFont) : xPlan.labelPx,
|
|
132
|
+
[keys, formatX, tier.axisFont, xWrapWidth, xPlan.labelPx]
|
|
91
133
|
);
|
|
92
|
-
const tickValues = useMemo(
|
|
93
|
-
()
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
[keys, plotWidth,
|
|
97
|
-
);
|
|
98
|
-
const svgRef = useRef(null);
|
|
134
|
+
const tickValues = useMemo(() => {
|
|
135
|
+
if (xTickValues !== void 0) return [...xTickValues(keys, plotWidth)];
|
|
136
|
+
if (containerClass === "micro")
|
|
137
|
+
return keys.length > 1 ? [keys[0], keys[keys.length - 1]] : [...keys];
|
|
138
|
+
return [...smartTicks(keys, plotWidth, xLabelPx, tight)];
|
|
139
|
+
}, [keys, plotWidth, xTickValues, xLabelPx, containerClass, tight]);
|
|
99
140
|
const point = cursor.point;
|
|
100
141
|
const crosshairX = point === null ? null : bandCenter(getX(point)) ?? null;
|
|
101
142
|
const cfg = tooltip === false ? void 0 : tooltip;
|
|
102
143
|
const isFollowerRender = !cursor.isSource && cfg?.onFollow === true;
|
|
103
144
|
const showTooltip = tooltip !== false && point !== null && (cursor.isSource || isFollowerRender);
|
|
104
|
-
const useAnchored = cfg?.follow === false || isFollowerRender;
|
|
145
|
+
const useAnchored = cfg?.follow === false || cfg?.follow === void 0 && cursor.isTouch || isFollowerRender;
|
|
105
146
|
const anchorX = useAnchored ? crosshairX : null;
|
|
106
147
|
const svgRect = anchorX === null ? void 0 : svgRef.current?.getBoundingClientRect();
|
|
107
148
|
const tooltipAnchor = svgRect === void 0 || anchorX === null ? cursor.anchor : { x: svgRect.left + margin.left + anchorX, y: svgRect.top + margin.top };
|
|
@@ -119,6 +160,9 @@ function useBandPlot(input) {
|
|
|
119
160
|
step,
|
|
120
161
|
bandWidth,
|
|
121
162
|
tickValues,
|
|
163
|
+
yPlacement,
|
|
164
|
+
xAnchorTerminals: tight,
|
|
165
|
+
xWrapWidth,
|
|
122
166
|
svgRef,
|
|
123
167
|
tooltipAnchor,
|
|
124
168
|
showTooltip,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { KeyboardEvent, PointerEvent } from 'react';
|
|
1
|
+
import type { KeyboardEvent, PointerEvent, RefObject } from 'react';
|
|
2
2
|
import type { CursorResolution } from '../cursor/resolve.js';
|
|
3
3
|
/** Viewport-space pointer anchor the tooltip positions against. */
|
|
4
4
|
export type CursorAnchor = {
|
|
@@ -12,24 +12,46 @@ export type ChartCursor<T> = {
|
|
|
12
12
|
isSource: boolean;
|
|
13
13
|
/** Latest pointer position in viewport coords, or null when not hovered. */
|
|
14
14
|
anchor: CursorAnchor | null;
|
|
15
|
+
/**
|
|
16
|
+
* True when the interaction that most recently placed THIS chart's cursor had
|
|
17
|
+
* `event.pointerType !== 'mouse'` (touch or pen). Callers fold it into the anchored-tooltip
|
|
18
|
+
* condition (`tooltip.follow` defaulting to `false` on touch, docs/CHARTS-SPEC.md §4) — a follower's own
|
|
19
|
+
* anchoring is unaffected, since a follower is never the one whose pointer set this flag.
|
|
20
|
+
*/
|
|
21
|
+
isTouch: boolean;
|
|
15
22
|
onPointerMove: (event: PointerEvent<SVGRectElement>) => void;
|
|
16
|
-
|
|
23
|
+
/** Coarse-pointer equivalent of hover: resolves the nearest point and shows the tooltip
|
|
24
|
+
* immediately, with no preceding `pointermove` — a plain tap otherwise fires only
|
|
25
|
+
* `pointerdown`/`pointerup`. The press is PROVISIONAL: it shows the tooltip but does not commit a
|
|
26
|
+
* pin, which only `onPointerUp` does. Also what MOVES an existing touch pin to a new tap elsewhere
|
|
27
|
+
* in the same chart (fine pointers ignore it; `onPointerMove` already covers hover for them). */
|
|
28
|
+
onPointerDown: (event: PointerEvent<SVGRectElement>) => void;
|
|
29
|
+
/** Commits the provisional touch press — the same `pointerId` as the matching `onPointerDown` —
|
|
30
|
+
* so the pin survives the lift. A `pointerup` for any other pointer is ignored. */
|
|
31
|
+
onPointerUp: (event: PointerEvent<SVGRectElement>) => void;
|
|
32
|
+
/** `pointerleave`/`pointercancel`, sharing one handler. A still-UNCOMMITTED touch press cancelled
|
|
33
|
+
* here is the browser taking the gesture (a scroll) and clears; once committed, touch no-ops so a
|
|
34
|
+
* stray `pointercancel` cannot undo the pin. A fine pointer always clears. */
|
|
35
|
+
onPointerLeave: (event: PointerEvent<SVGRectElement>) => void;
|
|
17
36
|
onKeyDown: (event: KeyboardEvent<SVGRectElement>) => void;
|
|
18
37
|
onBlur: () => void;
|
|
19
38
|
};
|
|
20
39
|
/**
|
|
21
40
|
* Wires a chart into the ambient cursor store: snaps the pointer to the nearest own point,
|
|
22
|
-
* broadcasts it, and reads back a sibling's broadcast through domain-aware resolution
|
|
23
|
-
*
|
|
24
|
-
*
|
|
41
|
+
* broadcasts it, and reads back a sibling's broadcast through domain-aware resolution — automatic,
|
|
42
|
+
* no `resolveKey` escape hatch.
|
|
43
|
+
*
|
|
44
|
+
* The tooltip anchor is coalesced through `requestAnimationFrame` (one local write per frame on a
|
|
45
|
+
* fast scrub); the BROADCAST is deduped instead, so a within-bucket scrub costs nothing and a real
|
|
46
|
+
* bucket change reaches siblings on the same tick.
|
|
25
47
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
48
|
+
* Touch model (`docs/CHARTS-SPEC.md` §4): a fine pointer keeps hovering. A coarse pointer
|
|
49
|
+
* (`onPointerDown`) resolves and shows the tooltip immediately, drag-scrubs via `onPointerMove`,
|
|
50
|
+
* and COMMITS a pin on `onPointerUp` — `onPointerLeave` (also wired to `pointercancel`) no-ops once
|
|
51
|
+
* committed. A press the browser turns into a scroll clears instead. The pin moves on a fresh tap,
|
|
52
|
+
* clears on a `document` tap outside `boundaryRef`, on any scroll, or on Escape.
|
|
31
53
|
*/
|
|
32
|
-
export declare function useChartCursor<T>({ data, chartId, getKey, xScale, marginLeft, resolution, }: {
|
|
54
|
+
export declare function useChartCursor<T>({ data, chartId, getKey, xScale, marginLeft, resolution, boundaryRef, }: {
|
|
33
55
|
data: readonly T[];
|
|
34
56
|
chartId: string;
|
|
35
57
|
getKey: (d: T) => string;
|
|
@@ -42,5 +64,12 @@ export declare function useChartCursor<T>({ data, chartId, getKey, xScale, margi
|
|
|
42
64
|
* series keyed by its Monday, a monthly series keyed by its 1st) — see {@link CursorResolution}.
|
|
43
65
|
*/
|
|
44
66
|
resolution?: CursorResolution;
|
|
67
|
+
/**
|
|
68
|
+
* Element a touch tap OUTSIDE dismisses the pin against (`docs/CHARTS-SPEC.md` §4). One
|
|
69
|
+
* capture-phase `document` `pointerdown` listener clears the pin when the target falls outside
|
|
70
|
+
* this ref — added on pinning, removed on unpin/unmount. Omit to skip outside-dismiss (a tap
|
|
71
|
+
* elsewhere in the chart and Escape still work); never throws for a missing ref.
|
|
72
|
+
*/
|
|
73
|
+
boundaryRef?: RefObject<Element | null>;
|
|
45
74
|
}): ChartCursor<T>;
|
|
46
75
|
//# sourceMappingURL=useChartCursor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChartCursor.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useChartCursor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"useChartCursor.d.ts","sourceRoot":"","sources":["../../../src/charts/hooks/useChartCursor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAMzD,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,kGAAkG;IAClG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;IACf,kGAAkG;IAClG,QAAQ,EAAE,OAAO,CAAA;IACjB,4EAA4E;IAC5E,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B;;;;;OAKG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IAC5D;;;;qGAIiG;IACjG,aAAa,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IAC5D;uFACmF;IACnF,WAAW,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IAC1D;;kFAE8E;IAC9E,cAAc,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IAC7D,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,KAAK,IAAI,CAAA;IACzD,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAChC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,UAAU,EACV,UAAsB,EACtB,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,gEAAgE;IAChE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;CACxC,GAAG,WAAW,CAAC,CAAC,CAAC,CAuRjB"}
|