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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Group } from "@visx/group";
|
|
3
|
-
import { memo, useMemo
|
|
3
|
+
import { memo, useMemo } from "react";
|
|
4
4
|
import { assertRequiredProps } from "../../common/validate.js";
|
|
5
5
|
import {
|
|
6
6
|
ChartTooltipFloat,
|
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
TooltipRow
|
|
10
10
|
} from "../primitives/ChartTooltip.js";
|
|
11
11
|
import { ChartFrame } from "../primitives/ChartFrame.js";
|
|
12
|
-
import {
|
|
12
|
+
import { useChartMetrics } from "../primitives/chart-tier.js";
|
|
13
|
+
import { useDiscreteCursor } from "../hooks/use-discrete-cursor.js";
|
|
13
14
|
import { maxTextWidth } from "../utils/measure-text.js";
|
|
14
15
|
import { thinLabels, xLabelPxFor } from "../utils/ticks.js";
|
|
15
16
|
import { VX, alpha } from "../../tokens/index.js";
|
|
@@ -75,8 +76,7 @@ function HeatmapPlot(props) {
|
|
|
75
76
|
legend
|
|
76
77
|
} = props;
|
|
77
78
|
const { width, height } = plot;
|
|
78
|
-
const { axisFont } =
|
|
79
|
-
const [tip, setTip] = useState(null);
|
|
79
|
+
const { axisFont } = useChartMetrics();
|
|
80
80
|
const rows = useMemo(() => rowsProp ?? firstSeen(data, getRow), [rowsProp, data, getRow]);
|
|
81
81
|
const cols = useMemo(() => colsProp ?? firstSeen(data, getCol), [colsProp, data, getCol]);
|
|
82
82
|
const { lookup, max } = useMemo(() => {
|
|
@@ -89,6 +89,27 @@ function HeatmapPlot(props) {
|
|
|
89
89
|
}
|
|
90
90
|
return { lookup: map, max: m };
|
|
91
91
|
}, [data, getRow, getCol, getValue]);
|
|
92
|
+
const cellTargets = useMemo(() => {
|
|
93
|
+
const out = [];
|
|
94
|
+
for (const row of rows) {
|
|
95
|
+
for (const col of cols) out.push({ row, col, value: lookup.get(cellKey(row, col)) });
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}, [rows, cols, lookup]);
|
|
99
|
+
const cursor = useDiscreteCursor({
|
|
100
|
+
targets: cellTargets,
|
|
101
|
+
getKey: (c) => cellKey(c.row, c.col),
|
|
102
|
+
columns: cols.length,
|
|
103
|
+
ariaLabel: "Heatmap cells \u2014 use arrow keys to navigate, Escape to dismiss"
|
|
104
|
+
});
|
|
105
|
+
const activeTip = cursor.tip !== null && cursor.tip.target.value !== void 0 ? {
|
|
106
|
+
anchor: cursor.tip.anchor,
|
|
107
|
+
cell: {
|
|
108
|
+
row: cursor.tip.target.row,
|
|
109
|
+
col: cursor.tip.target.col,
|
|
110
|
+
value: cursor.tip.target.value
|
|
111
|
+
}
|
|
112
|
+
} : null;
|
|
92
113
|
const rowLabels = useMemo(() => rows.map(rowLabel), [rows, rowLabel]);
|
|
93
114
|
const colLabels = useMemo(() => cols.map(colLabel), [cols, colLabel]);
|
|
94
115
|
const legendH = legend ? LEGEND_H + LEGEND_LABEL_H : 0;
|
|
@@ -106,20 +127,22 @@ function HeatmapPlot(props) {
|
|
|
106
127
|
() => thinLabels(rowLabels, cellH, labelLineHeight(axisFont)),
|
|
107
128
|
[rowLabels, cellH, axisFont]
|
|
108
129
|
);
|
|
109
|
-
const show = (row, col, value, event) => {
|
|
110
|
-
setTip({ row, col, value, anchor: { x: event.clientX, y: event.clientY } });
|
|
111
|
-
};
|
|
112
|
-
const hide = () => setTip(null);
|
|
113
130
|
return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
114
|
-
/* @__PURE__ */ jsxs("svg", { width, height, children: [
|
|
131
|
+
/* @__PURE__ */ jsxs("svg", { width, height, ...cursor.hostProps, children: [
|
|
115
132
|
/* @__PURE__ */ jsx(Group, { left: PAD_LEFT, top: PAD_TOP, children: rows.flatMap(
|
|
116
133
|
(row, ri) => cols.map((col, ci) => {
|
|
117
134
|
const value = lookup.get(cellKey(row, col));
|
|
118
135
|
const has = value !== void 0;
|
|
119
136
|
const cellFill = has ? alpha(color, intensity(value, max)) : alpha(VX.neutral, 0.04);
|
|
137
|
+
const target = { row, col, value };
|
|
138
|
+
const isActive = cursor.tip?.target.row === row && cursor.tip?.target.col === col;
|
|
120
139
|
return /* @__PURE__ */ jsx(
|
|
121
140
|
"rect",
|
|
122
141
|
{
|
|
142
|
+
id: cursor.optionId(target),
|
|
143
|
+
role: "option",
|
|
144
|
+
"aria-selected": isActive,
|
|
145
|
+
"aria-label": `${rowLabels[ri]}: ${colLabels[ci]}: ${value !== void 0 ? formatValue(value) : "no data"}`,
|
|
123
146
|
x: ci * cellW + cellGap / 2,
|
|
124
147
|
y: ri * cellH + cellGap / 2,
|
|
125
148
|
width: Math.max(0, cellW - cellGap),
|
|
@@ -127,9 +150,7 @@ function HeatmapPlot(props) {
|
|
|
127
150
|
rx: cellRadius,
|
|
128
151
|
fill: cellFill,
|
|
129
152
|
style: { cursor: has ? "pointer" : "default" },
|
|
130
|
-
|
|
131
|
-
onPointerLeave: hide,
|
|
132
|
-
onPointerCancel: hide
|
|
153
|
+
...has ? cursor.pointerProps(target) : {}
|
|
133
154
|
},
|
|
134
155
|
cellKey(row, col)
|
|
135
156
|
);
|
|
@@ -197,8 +218,8 @@ function HeatmapPlot(props) {
|
|
|
197
218
|
)
|
|
198
219
|
] })
|
|
199
220
|
] }),
|
|
200
|
-
|
|
201
|
-
/* @__PURE__ */ jsx(TooltipHeader, { date: rowLabel(
|
|
221
|
+
activeTip !== null && /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: activeTip.anchor, children: [
|
|
222
|
+
/* @__PURE__ */ jsx(TooltipHeader, { date: rowLabel(activeTip.cell.row), label: colLabel(activeTip.cell.col) }),
|
|
202
223
|
/* @__PURE__ */ jsxs(TooltipBody, { children: [
|
|
203
224
|
/* @__PURE__ */ jsx(
|
|
204
225
|
TooltipRow,
|
|
@@ -206,10 +227,10 @@ function HeatmapPlot(props) {
|
|
|
206
227
|
color: alpha(color, 0.9),
|
|
207
228
|
shape: "bar",
|
|
208
229
|
label: "Value",
|
|
209
|
-
value: formatValue(
|
|
230
|
+
value: formatValue(activeTip.cell.value)
|
|
210
231
|
}
|
|
211
232
|
),
|
|
212
|
-
renderTooltip?.(
|
|
233
|
+
renderTooltip?.(activeTip.cell)
|
|
213
234
|
] })
|
|
214
235
|
] })
|
|
215
236
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MirroredBars.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MirroredBars.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAIvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"MirroredBars.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MirroredBars.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAIvE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAIrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAI/D,gGAAgG;AAChG,MAAM,MAAM,eAAe,GAAG;IAC5B;mEAC+D;IAC/D,GAAG,EAAE,MAAM,CAAA;IACX;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB;sBACkB;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;oFACgF;IAChF,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI,WAAW,GAAG;IAC/C,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,sFAAsF;IACtF,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;;;;;OAKG;IACH,MAAM,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACjC,yCAAyC;IACzC,EAAE,EAAE,eAAe,CAAA;IACnB,yCAAyC;IACzC,IAAI,EAAE,eAAe,CAAA;IACrB;8FAC0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACpC;kCAC8B;IAC9B,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IAChC;kGAC8F;IAC9F,MAAM,CAAC,EAAE,MAAM,GAAG,qBAAqB,CAAA;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,CAAA;IAC/E,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IAClB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,OAAO,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IACtC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC;gFAC4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;4FACwF;IACxF,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB,CAAA;AA8BD;;;;;;;;;;;;;GAaG;AACH,iBAAS,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,+BAwBxD;AA+SD,eAAO,MAAM,YAAY,EAAuB,OAAO,iBAAiB,CAAA"}
|
|
@@ -6,19 +6,14 @@ import { assertRequiredProps } from "../../common/validate.js";
|
|
|
6
6
|
import { VX, alpha } from "../../tokens/index.js";
|
|
7
7
|
import { useBandPlot } from "../hooks/useBandPlot.js";
|
|
8
8
|
import { probeAxisLabels } from "../layout/auto-margin.js";
|
|
9
|
-
import {
|
|
9
|
+
import { AxisLeftNumeric } from "../primitives/Axes.js";
|
|
10
10
|
import { ChartFrame, resolveLegend } from "../primitives/ChartFrame.js";
|
|
11
|
-
import {
|
|
12
|
-
ChartTooltipFloat,
|
|
13
|
-
TooltipBody,
|
|
14
|
-
TooltipHeader,
|
|
15
|
-
TooltipRow
|
|
16
|
-
} from "../primitives/ChartTooltip.js";
|
|
11
|
+
import { TooltipRows } from "../primitives/ChartTooltip.js";
|
|
17
12
|
import { Crosshair } from "../primitives/Crosshair.js";
|
|
18
13
|
import { HatchPattern, hatchFill, hatchSizeFor } from "../primitives/HatchPattern.js";
|
|
19
|
-
import { HoverOverlay } from "../primitives/HoverOverlay.js";
|
|
20
14
|
import { deriveTooltipRows } from "../series.js";
|
|
21
15
|
import { fmtAxisDate } from "../utils/format.js";
|
|
16
|
+
import { BandAxisOverlay, BandTooltip, clampFraction } from "./band-chrome.js";
|
|
22
17
|
const DEFAULT_UP_FRACTION = 0.35;
|
|
23
18
|
const DEFAULT_PANE_TICKS = 3;
|
|
24
19
|
function assertPaneKey(side, key, resolved, series) {
|
|
@@ -107,7 +102,7 @@ function MirroredBarsPlot(props) {
|
|
|
107
102
|
...marginOverride !== void 0 && { margin: marginOverride },
|
|
108
103
|
...tooltip !== void 0 && { tooltip }
|
|
109
104
|
});
|
|
110
|
-
const { bands, margin, plotWidth,
|
|
105
|
+
const { bands, margin, plotWidth, point, crosshairX, step, bandWidth } = band;
|
|
111
106
|
const barBand = Math.max(plot.height - margin.top - margin.bottom, 2);
|
|
112
107
|
const upHeight = Math.max(Math.round(barBand * upFraction), 1);
|
|
113
108
|
const downHeight = Math.max(barBand - upHeight, 1);
|
|
@@ -198,8 +193,6 @@ function MirroredBarsPlot(props) {
|
|
|
198
193
|
hatchId
|
|
199
194
|
]);
|
|
200
195
|
if (plotWidth <= 0 || bands.length === 0) return null;
|
|
201
|
-
const cfg = tooltip === false ? void 0 : tooltip;
|
|
202
|
-
const badge = cfg?.label === void 0 || point === null ? null : cfg.label(point);
|
|
203
196
|
const visibleSeries = series.filter((s) => !hidden.has(s.key)).map((s) => {
|
|
204
197
|
if (s.formatValue !== void 0) return s;
|
|
205
198
|
if (s.key === up.key) return { ...s, formatValue: (v) => up.format(v) };
|
|
@@ -208,108 +201,72 @@ function MirroredBarsPlot(props) {
|
|
|
208
201
|
});
|
|
209
202
|
const rows = point === null ? [] : deriveTooltipRows(visibleSeries, point, down.format);
|
|
210
203
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
211
|
-
/* @__PURE__ */ jsxs(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
)
|
|
277
|
-
] })
|
|
278
|
-
] }),
|
|
279
|
-
band.showTooltip && point !== null && /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: band.tooltipAnchor, ariaLive: band.ariaLive, children: [
|
|
280
|
-
/* @__PURE__ */ jsx(
|
|
281
|
-
TooltipHeader,
|
|
282
|
-
{
|
|
283
|
-
date: getX(point),
|
|
284
|
-
...cfg?.formatHeader !== void 0 && {
|
|
285
|
-
format: (key) => cfg.formatHeader?.(key, point) ?? key
|
|
286
|
-
},
|
|
287
|
-
...badge !== null && { label: badge.text, labelColor: badge.color }
|
|
288
|
-
}
|
|
289
|
-
),
|
|
290
|
-
/* @__PURE__ */ jsxs(TooltipBody, { children: [
|
|
291
|
-
cfg?.prependRows?.(point, { hidden }),
|
|
292
|
-
rows.map((row) => /* @__PURE__ */ jsx(
|
|
293
|
-
TooltipRow,
|
|
294
|
-
{
|
|
295
|
-
color: row.color,
|
|
296
|
-
label: row.label,
|
|
297
|
-
value: row.value,
|
|
298
|
-
shape: row.shape,
|
|
299
|
-
dashed: row.dashed,
|
|
300
|
-
...row.strokeWidth !== void 0 && { strokeWidth: row.strokeWidth }
|
|
301
|
-
},
|
|
302
|
-
row.key
|
|
303
|
-
)),
|
|
304
|
-
cfg?.extraRows?.(point, { hidden })
|
|
305
|
-
] })
|
|
306
|
-
] })
|
|
204
|
+
/* @__PURE__ */ jsxs(
|
|
205
|
+
"svg",
|
|
206
|
+
{
|
|
207
|
+
ref: band.svgRef,
|
|
208
|
+
width: plot.width,
|
|
209
|
+
height: plot.height,
|
|
210
|
+
style: { touchAction: "pan-y" },
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
|
|
213
|
+
HatchPattern,
|
|
214
|
+
{
|
|
215
|
+
id: hatchId,
|
|
216
|
+
color: absentColor,
|
|
217
|
+
opacity: 0.7,
|
|
218
|
+
size: hatchSizeFor(bandWidth)
|
|
219
|
+
}
|
|
220
|
+
) }),
|
|
221
|
+
/* @__PURE__ */ jsxs(Group, { left: margin.left, top: margin.top, children: [
|
|
222
|
+
bars,
|
|
223
|
+
upVisible && band.yPlacement !== "none" && /* @__PURE__ */ jsx(
|
|
224
|
+
AxisLeftNumeric,
|
|
225
|
+
{
|
|
226
|
+
scale: upAxisScale,
|
|
227
|
+
numTicks: upTicks,
|
|
228
|
+
tickFormat: (v) => up.format(Number(v)),
|
|
229
|
+
inside: band.yPlacement === "inside"
|
|
230
|
+
}
|
|
231
|
+
),
|
|
232
|
+
downVisible && band.yPlacement !== "none" && /* @__PURE__ */ jsx(Group, { top: baseline, children: /* @__PURE__ */ jsx(
|
|
233
|
+
AxisLeftNumeric,
|
|
234
|
+
{
|
|
235
|
+
scale: downScale,
|
|
236
|
+
numTicks: downTicks,
|
|
237
|
+
tickFormat: (v) => down.format(Number(v)),
|
|
238
|
+
inside: band.yPlacement === "inside"
|
|
239
|
+
}
|
|
240
|
+
) }),
|
|
241
|
+
/* @__PURE__ */ jsx(
|
|
242
|
+
"line",
|
|
243
|
+
{
|
|
244
|
+
x1: 0,
|
|
245
|
+
x2: plotWidth,
|
|
246
|
+
y1: baseline,
|
|
247
|
+
y2: baseline,
|
|
248
|
+
stroke: VX.axisStroke,
|
|
249
|
+
strokeWidth: 1
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
crosshairX !== null && /* @__PURE__ */ jsx(Crosshair, { x: crosshairX, top: 0, bottom: barBand }),
|
|
253
|
+
/* @__PURE__ */ jsx(
|
|
254
|
+
BandAxisOverlay,
|
|
255
|
+
{
|
|
256
|
+
band,
|
|
257
|
+
height: barBand,
|
|
258
|
+
getX,
|
|
259
|
+
formatX,
|
|
260
|
+
ariaLabel
|
|
261
|
+
}
|
|
262
|
+
)
|
|
263
|
+
] })
|
|
264
|
+
]
|
|
265
|
+
}
|
|
266
|
+
),
|
|
267
|
+
/* @__PURE__ */ jsx(BandTooltip, { band, tooltip, getX, hidden, children: /* @__PURE__ */ jsx(TooltipRows, { rows }) })
|
|
307
268
|
] });
|
|
308
269
|
}
|
|
309
|
-
function clampFraction(value) {
|
|
310
|
-
if (value === void 0 || !Number.isFinite(value)) return 0;
|
|
311
|
-
return Math.min(Math.max(value, 0), 1);
|
|
312
|
-
}
|
|
313
270
|
function finiteOrNull(v) {
|
|
314
271
|
return v === null || v === void 0 || Number.isNaN(v) ? null : v;
|
|
315
272
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { BandPlot, BandTooltipConfig } from '../hooks/useBandPlot.js';
|
|
3
|
+
/**
|
|
4
|
+
* The chrome `BandStrip` and `MirroredBars` share around their own marks — the slot axis, the
|
|
5
|
+
* keyboard/pointer overlay and the tooltip shell — so the two `useBandPlot` kinds cannot drift in
|
|
6
|
+
* any of them. Internal; neither is exported from a barrel.
|
|
7
|
+
*
|
|
8
|
+
* theme-allow-file hand-rolled-plot — the slot axis and overlay of the two declared banded
|
|
9
|
+
* exceptions (`BandStrip`, `MirroredBars`), which carry the same waiver for the same reason.
|
|
10
|
+
*/
|
|
11
|
+
/** A 0..1 share. Non-finite (a 0/0 fold count) reads as "nothing is absent" — the conservative
|
|
12
|
+
* end, since the alternative is a band that does not render at all. */
|
|
13
|
+
export declare function clampFraction(value: number | undefined): number;
|
|
14
|
+
/** The slot axis under a `height`-tall band row, plus the hover/keyboard overlay over it. */
|
|
15
|
+
export declare function BandAxisOverlay<T>({ band, height, getX, formatX, ariaLabel, }: {
|
|
16
|
+
band: BandPlot<T>;
|
|
17
|
+
height: number;
|
|
18
|
+
getX: (d: T) => string;
|
|
19
|
+
formatX: (key: string) => string;
|
|
20
|
+
ariaLabel: string | undefined;
|
|
21
|
+
}): import("react").JSX.Element;
|
|
22
|
+
/** The tooltip shell: header (+ badge), the consumer's prepended rows, the kind's own derived
|
|
23
|
+
* `children` rows, the consumer's extra rows. Renders nothing off-hover or with `tooltip: false`. */
|
|
24
|
+
export declare function BandTooltip<T>({ band, tooltip, getX, hidden, children, }: {
|
|
25
|
+
band: BandPlot<T>;
|
|
26
|
+
tooltip: BandTooltipConfig<T> | false | undefined;
|
|
27
|
+
getX: (d: T) => string;
|
|
28
|
+
hidden: ReadonlySet<string>;
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
}): import("react").JSX.Element | null;
|
|
31
|
+
//# sourceMappingURL=band-chrome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"band-chrome.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/band-chrome.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAKvE;;;;;;;GAOG;AAEH;uEACuE;AACvE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG/D;AAED,6FAA6F;AAC7F,wBAAgB,eAAe,CAAC,CAAC,EAAE,EACjC,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,OAAO,EACP,SAAS,GACV,EAAE;IACD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAChC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B,+BAkBA;AAED;qGACqG;AACrG,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAC7B,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,MAAM,EACN,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IACjB,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,SAAS,CAAA;IACjD,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3B,QAAQ,EAAE,SAAS,CAAA;CACpB,sCAqBA"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { AxisBottomDate } from "../primitives/Axes.js";
|
|
3
|
+
import { ChartTooltipFloat, TooltipBody, TooltipHeader } from "../primitives/ChartTooltip.js";
|
|
4
|
+
import { cursorSliderProps, HoverOverlay } from "../primitives/HoverOverlay.js";
|
|
5
|
+
function clampFraction(value) {
|
|
6
|
+
if (value === void 0 || !Number.isFinite(value)) return 0;
|
|
7
|
+
return Math.min(Math.max(value, 0), 1);
|
|
8
|
+
}
|
|
9
|
+
function BandAxisOverlay({
|
|
10
|
+
band,
|
|
11
|
+
height,
|
|
12
|
+
getX,
|
|
13
|
+
formatX,
|
|
14
|
+
ariaLabel
|
|
15
|
+
}) {
|
|
16
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17
|
+
/* @__PURE__ */ jsx(
|
|
18
|
+
AxisBottomDate,
|
|
19
|
+
{
|
|
20
|
+
top: height,
|
|
21
|
+
scale: band.scale,
|
|
22
|
+
tickValues: band.tickValues,
|
|
23
|
+
tickFormat: (v) => formatX(String(v)),
|
|
24
|
+
anchorTerminals: band.xAnchorTerminals,
|
|
25
|
+
...band.xWrapWidth !== void 0 && { wrapWidth: band.xWrapWidth }
|
|
26
|
+
}
|
|
27
|
+
),
|
|
28
|
+
/* @__PURE__ */ jsx(
|
|
29
|
+
HoverOverlay,
|
|
30
|
+
{
|
|
31
|
+
width: band.plotWidth,
|
|
32
|
+
height,
|
|
33
|
+
...cursorSliderProps({ cursor: band.cursor, data: band.bands, getX, formatX, ariaLabel })
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
38
|
+
function BandTooltip({
|
|
39
|
+
band,
|
|
40
|
+
tooltip,
|
|
41
|
+
getX,
|
|
42
|
+
hidden,
|
|
43
|
+
children
|
|
44
|
+
}) {
|
|
45
|
+
const { point } = band;
|
|
46
|
+
if (!band.showTooltip || point === null) return null;
|
|
47
|
+
const cfg = tooltip === false ? void 0 : tooltip;
|
|
48
|
+
const badge = cfg?.label === void 0 ? null : cfg.label(point);
|
|
49
|
+
return /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: band.tooltipAnchor, ariaLive: band.ariaLive, children: [
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
TooltipHeader,
|
|
52
|
+
{
|
|
53
|
+
date: getX(point),
|
|
54
|
+
...cfg?.formatHeader !== void 0 && {
|
|
55
|
+
format: (key) => cfg.formatHeader?.(key, point) ?? key
|
|
56
|
+
},
|
|
57
|
+
...badge !== null && { label: badge.text, labelColor: badge.color }
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
/* @__PURE__ */ jsxs(TooltipBody, { children: [
|
|
61
|
+
cfg?.prependRows?.(point, { hidden }),
|
|
62
|
+
children,
|
|
63
|
+
cfg?.extraRows?.(point, { hidden })
|
|
64
|
+
] })
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
BandAxisOverlay,
|
|
69
|
+
BandTooltip,
|
|
70
|
+
clampFraction
|
|
71
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ContainerClass } from '../../tokens/size-classes.js';
|
|
2
|
+
/** Aspect (frame W/H) above which the legend moves beside the ring. */
|
|
3
|
+
export declare const SIDE_LEGEND_ASPECT = 1.5;
|
|
4
|
+
/** Aspect a side layout must fall below before it stacks again — the gap stops a legend whose own
|
|
5
|
+
* placement changes the measured height from flipping the layout back and forth. */
|
|
6
|
+
export declare const STACK_LEGEND_ASPECT = 1.35;
|
|
7
|
+
/** Most slices kept before the rest fold into "Other" (so 7 or more slices fold). */
|
|
8
|
+
export declare const DONUT_MAX_SLICES = 6;
|
|
9
|
+
export declare const OTHER_KEY = "__other";
|
|
10
|
+
/** Side layout: the ring's diameter never exceeds this share of the frame width. */
|
|
11
|
+
export declare const SIDE_RING_MAX_WIDTH_SHARE = 0.55;
|
|
12
|
+
/** Space kept between the ring's outer edge and the plot box. */
|
|
13
|
+
export declare const RING_PADDING = 4;
|
|
14
|
+
export type DonutLayout = {
|
|
15
|
+
side: boolean;
|
|
16
|
+
};
|
|
17
|
+
/** Side legend only on a wide-enough frame (`micro`/`compact` always stack under the ring).
|
|
18
|
+
* `wasSide` applies hysteresis: an already-side layout stays side until W/H falls below
|
|
19
|
+
* {@link STACK_LEGEND_ASPECT}. */
|
|
20
|
+
export declare function resolveDonutLayout(input: {
|
|
21
|
+
frameW: number;
|
|
22
|
+
frameH: number;
|
|
23
|
+
containerClass: ContainerClass;
|
|
24
|
+
wasSide?: boolean;
|
|
25
|
+
}): DonutLayout;
|
|
26
|
+
/** Ring outer radius: never negative and never wider than the plot; the side layout also caps the
|
|
27
|
+
* diameter at {@link SIDE_RING_MAX_WIDTH_SHARE} of the frame width. */
|
|
28
|
+
export declare function resolveDonutRadius(input: {
|
|
29
|
+
plotW: number;
|
|
30
|
+
plotH: number;
|
|
31
|
+
frameW: number;
|
|
32
|
+
side: boolean;
|
|
33
|
+
}): number;
|
|
34
|
+
/** Share of `total` as a whole percent; an empty total is 0%. */
|
|
35
|
+
export declare function sharePercent(value: number, total: number): number;
|
|
36
|
+
/** The key for the synthesized "Other" bucket — {@link OTHER_KEY}, prefixed until no input key uses it. */
|
|
37
|
+
export declare function resolveOtherKey(keys: readonly string[]): string;
|
|
38
|
+
/** Keeps the top {@link DONUT_MAX_SLICES} by value (in original order) and sums the rest into one
|
|
39
|
+
* trailing "Other" entry. Non-finite and negative values count as 0. */
|
|
40
|
+
export declare function foldOther<T extends {
|
|
41
|
+
key: string;
|
|
42
|
+
value: number;
|
|
43
|
+
}>(slices: readonly T[]): {
|
|
44
|
+
kept: T[];
|
|
45
|
+
other: number | null;
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=donut-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"donut-layout.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/donut-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE/D,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,MAAM,CAAA;AACrC;oFACoF;AACpF,eAAO,MAAM,mBAAmB,OAAO,CAAA;AACvC,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,SAAS,YAAY,CAAA;AAClC,oFAAoF;AACpF,eAAO,MAAM,yBAAyB,OAAO,CAAA;AAC7C,iEAAiE;AACjE,eAAO,MAAM,YAAY,IAAI,CAAA;AAE7B,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAE3C;;kCAEkC;AAClC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,cAAc,CAAA;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,WAAW,CAMd;AAED;uEACuE;AACvE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;CACd,GAAG,MAAM,CAMT;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjE;AAKD,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAK/D;AAED;wEACwE;AACxE,wBAAgB,SAAS,CAAC,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAChE,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAarC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const SIDE_LEGEND_ASPECT = 1.5;
|
|
2
|
+
const STACK_LEGEND_ASPECT = 1.35;
|
|
3
|
+
const DONUT_MAX_SLICES = 6;
|
|
4
|
+
const OTHER_KEY = "__other";
|
|
5
|
+
const SIDE_RING_MAX_WIDTH_SHARE = 0.55;
|
|
6
|
+
const RING_PADDING = 4;
|
|
7
|
+
function resolveDonutLayout(input) {
|
|
8
|
+
const { frameW, frameH, containerClass, wasSide = false } = input;
|
|
9
|
+
const roomy = containerClass !== "micro" && containerClass !== "compact";
|
|
10
|
+
if (!roomy || frameH <= 0) return { side: false };
|
|
11
|
+
const aspect = frameW / frameH;
|
|
12
|
+
return { side: wasSide ? aspect >= STACK_LEGEND_ASPECT : aspect > SIDE_LEGEND_ASPECT };
|
|
13
|
+
}
|
|
14
|
+
function resolveDonutRadius(input) {
|
|
15
|
+
const { plotW, plotH, frameW, side } = input;
|
|
16
|
+
const diameter = side ? Math.min(plotW, plotH, SIDE_RING_MAX_WIDTH_SHARE * frameW) : Math.min(plotW, plotH);
|
|
17
|
+
return Math.max(0, diameter / 2 - RING_PADDING);
|
|
18
|
+
}
|
|
19
|
+
function sharePercent(value, total) {
|
|
20
|
+
return total > 0 ? Math.round(value / total * 100) : 0;
|
|
21
|
+
}
|
|
22
|
+
const safeValue = (value) => Number.isFinite(value) && value > 0 ? value : 0;
|
|
23
|
+
function resolveOtherKey(keys) {
|
|
24
|
+
const taken = new Set(keys);
|
|
25
|
+
let key = OTHER_KEY;
|
|
26
|
+
while (taken.has(key)) key = `_${key}`;
|
|
27
|
+
return key;
|
|
28
|
+
}
|
|
29
|
+
function foldOther(slices) {
|
|
30
|
+
const safe = slices.map((s) => ({ ...s, value: safeValue(s.value) }));
|
|
31
|
+
if (safe.length <= DONUT_MAX_SLICES) return { kept: safe, other: null };
|
|
32
|
+
const top = new Set(
|
|
33
|
+
safe.toSorted((a, b) => b.value - a.value).slice(0, DONUT_MAX_SLICES).map((s) => s.key)
|
|
34
|
+
);
|
|
35
|
+
return {
|
|
36
|
+
kept: safe.filter((s) => top.has(s.key)),
|
|
37
|
+
other: safe.reduce((sum, s) => top.has(s.key) ? sum : sum + s.value, 0)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
DONUT_MAX_SLICES,
|
|
42
|
+
OTHER_KEY,
|
|
43
|
+
RING_PADDING,
|
|
44
|
+
SIDE_LEGEND_ASPECT,
|
|
45
|
+
SIDE_RING_MAX_WIDTH_SHARE,
|
|
46
|
+
STACK_LEGEND_ASPECT,
|
|
47
|
+
foldOther,
|
|
48
|
+
resolveDonutLayout,
|
|
49
|
+
resolveDonutRadius,
|
|
50
|
+
resolveOtherKey,
|
|
51
|
+
sharePercent
|
|
52
|
+
};
|
|
@@ -59,15 +59,20 @@ export type AutoMarginInput = {
|
|
|
59
59
|
/** Degrees of counter-clockwise rotation applied to the x tick labels. Default 0. */
|
|
60
60
|
rotate?: number;
|
|
61
61
|
/** Tick-label font size. Default `VX.axisFont`. A phone-tier chart passes its own smaller size
|
|
62
|
-
* (`
|
|
62
|
+
* (`chartMetrics().axisFont`) — the measured label must be the painted label. */
|
|
63
63
|
fontPx?: number;
|
|
64
64
|
/**
|
|
65
65
|
* Per-side FLOORS. Default `VX.margin`. The phone tier passes its tightened set
|
|
66
|
-
* (`
|
|
66
|
+
* (`chartMetrics().margin`) so a static 44px left gutter does not spend an eighth of a 360px
|
|
67
67
|
* chart on a three-character label. The law itself does not move: a side may still only ever
|
|
68
68
|
* grow past its floor.
|
|
69
69
|
*/
|
|
70
70
|
floor?: ChartMargin;
|
|
71
|
+
/** X labels anchored inward at the terminals (`AxisBottomDate anchorTerminals`): the last label
|
|
72
|
+
* no longer centres on the right edge, so the half-label right reservation is dropped. */
|
|
73
|
+
anchorTerminals?: boolean;
|
|
74
|
+
/** Lines the tallest (wrapped) x label takes. Default 1. */
|
|
75
|
+
bottomLines?: number;
|
|
71
76
|
/** Explicit per-side overrides — applied LAST, so an escape hatch always wins. */
|
|
72
77
|
override?: Partial<ChartMargin>;
|
|
73
78
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-margin.d.ts","sourceRoot":"","sources":["../../../src/charts/layout/auto-margin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAgC/C;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAG5E,CAAA;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiBlC;AAUD,MAAM,MAAM,eAAe,GAAG;IAC5B,gDAAgD;IAChD,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;
|
|
1
|
+
{"version":3,"file":"auto-margin.d.ts","sourceRoot":"","sources":["../../../src/charts/layout/auto-margin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAgC/C;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAG5E,CAAA;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiBlC;AAUD,MAAM,MAAM,eAAe,GAAG;IAC5B,gDAAgD;IAChD,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;qFACiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB;8FAC0F;IAC1F,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CAChC,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,KAAK,GAAE,eAAoB,GAAG,WAAW,CA4CnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9B,8EAA8E;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;qBAEiB;IACjB,KAAK,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;CACzB,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,CAatD"}
|
|
@@ -30,18 +30,27 @@ function rotatedLabelExtents(input) {
|
|
|
30
30
|
const LOG_TICK_FORMAT = new Intl.NumberFormat("en-US", { maximumFractionDigits: 20 });
|
|
31
31
|
function autoMargin(input = {}) {
|
|
32
32
|
const fontPx = input.fontPx ?? VX.axisFont;
|
|
33
|
-
const {
|
|
33
|
+
const {
|
|
34
|
+
left = [],
|
|
35
|
+
right = [],
|
|
36
|
+
bottom = [],
|
|
37
|
+
rotate = 0,
|
|
38
|
+
floor = VX.margin,
|
|
39
|
+
anchorTerminals = false,
|
|
40
|
+
bottomLines = 1,
|
|
41
|
+
override
|
|
42
|
+
} = input;
|
|
34
43
|
const leftWidth = maxTextWidth(left, fontPx);
|
|
35
44
|
const rightWidth = maxTextWidth(right, fontPx);
|
|
36
45
|
const bottomWidth = maxTextWidth(bottom, fontPx);
|
|
37
46
|
const rotated = rotatedLabelExtents({ labelWidth: bottomWidth, fontPx, rotate });
|
|
38
|
-
const bottomExtent = rotate === 0 ? lineHeight(fontPx) + AXIS_TICK_GAP : rotated.below;
|
|
47
|
+
const bottomExtent = rotate === 0 ? lineHeight(fontPx) * Math.max(bottomLines, 1) + AXIS_TICK_GAP : rotated.below;
|
|
39
48
|
return {
|
|
40
49
|
top: override?.top ?? floor.top,
|
|
41
50
|
right: override?.right ?? Math.ceil(
|
|
42
51
|
Math.max(
|
|
43
52
|
floor.right,
|
|
44
|
-
right.length > 0 ? rightWidth + AXIS_TICK_GAP : rotate === 0 ? bottomWidth / 2 : 0
|
|
53
|
+
right.length > 0 ? rightWidth + AXIS_TICK_GAP : rotate === 0 && !anchorTerminals ? bottomWidth / 2 : 0
|
|
45
54
|
)
|
|
46
55
|
),
|
|
47
56
|
bottom: override?.bottom ?? Math.ceil(Math.max(floor.bottom, bottomExtent)),
|