basalt-ui 1.30.2 → 1.31.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 +31 -0
- package/MIGRATING.md +172 -12
- package/agent/rules/basalt-controls.md +19 -19
- package/agent/rules/basalt-mantine.md +1 -1
- package/configs/oxlint-plugin.js +254 -4
- package/configs/oxlint-plugin.test.ts +145 -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 +54 -41
- 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 +145 -131
- 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 +83 -68
- 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 +271 -125
- 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 +74 -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 +133 -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 +212 -71
- package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
- package/dist/charts/primitives/ChartTooltip.js +4 -3
- package/dist/charts/primitives/Crosshair.js +2 -2
- package/dist/charts/primitives/HoverOverlay.d.ts +6 -1
- package/dist/charts/primitives/HoverOverlay.d.ts.map +1 -1
- package/dist/charts/primitives/HoverOverlay.js +37 -26
- 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 +29 -0
- package/dist/charts/primitives/chart-card-context.d.ts.map +1 -0
- package/dist/charts/primitives/chart-card-context.js +13 -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 +76 -29
- 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/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 +8 -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 +1 -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 +16 -4
- package/dist/dashboard/widget-grid.d.ts.map +1 -1
- 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.d.ts +23 -0
- package/dist/data/data-table.d.ts.map +1 -1
- package/dist/data/data-table.js +339 -141
- 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 +30 -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 +67 -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/provider/index.d.ts +20 -1
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +22 -2
- 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/index.d.ts +12 -0
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +57 -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 +36 -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/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 +17 -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 +11 -1
- package/src/charts/kinds/Donut.tsx +153 -62
- package/src/charts/kinds/DualPanel.tsx +19 -4
- package/src/charts/kinds/Heatmap.tsx +61 -22
- package/src/charts/kinds/MirroredBars.tsx +15 -3
- 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 -68
- package/src/charts/primitives/ChartCard.tsx +141 -48
- package/src/charts/primitives/ChartFrame.tsx +243 -60
- package/src/charts/primitives/ChartLegend.tsx +257 -73
- package/src/charts/primitives/ChartTooltip.tsx +8 -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 +15 -4
- package/src/charts/primitives/chart-card-context.ts +37 -0
- package/src/charts/primitives/chart-frame-layout.ts +214 -177
- package/src/charts/primitives/chart-layout.ts +318 -0
- package/src/charts/primitives/chart-tier.tsx +66 -21
- 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 +8 -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 +1 -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 +16 -4
- 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.module.css +94 -0
- package/src/data/data-table.module.css.d.ts +11 -0
- package/src/data/data-table.tsx +503 -164
- package/src/data/virtual-list.tsx +31 -0
- package/src/forms/form-layout.module.css +30 -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 +183 -3
- package/src/guard/types.ts +3 -2
- package/src/index.ts +2 -0
- package/src/provider/index.tsx +53 -1
- 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/index.tsx +200 -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 +36 -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/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;AAUrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/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;
|
|
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;AAUrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAE5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/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;AAgWD,eAAO,MAAM,YAAY,EAAuB,OAAO,iBAAiB,CAAA"}
|
|
@@ -208,74 +208,89 @@ function MirroredBarsPlot(props) {
|
|
|
208
208
|
});
|
|
209
209
|
const rows = point === null ? [] : deriveTooltipRows(visibleSeries, point, down.format);
|
|
210
210
|
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
|
-
|
|
211
|
+
/* @__PURE__ */ jsxs(
|
|
212
|
+
"svg",
|
|
213
|
+
{
|
|
214
|
+
ref: band.svgRef,
|
|
215
|
+
width: plot.width,
|
|
216
|
+
height: plot.height,
|
|
217
|
+
style: { touchAction: "pan-y" },
|
|
218
|
+
children: [
|
|
219
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
|
|
220
|
+
HatchPattern,
|
|
221
|
+
{
|
|
222
|
+
id: hatchId,
|
|
223
|
+
color: absentColor,
|
|
224
|
+
opacity: 0.7,
|
|
225
|
+
size: hatchSizeFor(bandWidth)
|
|
226
|
+
}
|
|
227
|
+
) }),
|
|
228
|
+
/* @__PURE__ */ jsxs(Group, { left: margin.left, top: margin.top, children: [
|
|
229
|
+
bars,
|
|
230
|
+
upVisible && band.yPlacement !== "none" && /* @__PURE__ */ jsx(
|
|
231
|
+
AxisLeftNumeric,
|
|
232
|
+
{
|
|
233
|
+
scale: upAxisScale,
|
|
234
|
+
numTicks: upTicks,
|
|
235
|
+
tickFormat: (v) => up.format(Number(v)),
|
|
236
|
+
inside: band.yPlacement === "inside"
|
|
237
|
+
}
|
|
238
|
+
),
|
|
239
|
+
downVisible && band.yPlacement !== "none" && /* @__PURE__ */ jsx(Group, { top: baseline, children: /* @__PURE__ */ jsx(
|
|
240
|
+
AxisLeftNumeric,
|
|
241
|
+
{
|
|
242
|
+
scale: downScale,
|
|
243
|
+
numTicks: downTicks,
|
|
244
|
+
tickFormat: (v) => down.format(Number(v)),
|
|
245
|
+
inside: band.yPlacement === "inside"
|
|
246
|
+
}
|
|
247
|
+
) }),
|
|
248
|
+
/* @__PURE__ */ jsx(
|
|
249
|
+
"line",
|
|
250
|
+
{
|
|
251
|
+
x1: 0,
|
|
252
|
+
x2: plotWidth,
|
|
253
|
+
y1: baseline,
|
|
254
|
+
y2: baseline,
|
|
255
|
+
stroke: VX.axisStroke,
|
|
256
|
+
strokeWidth: 1
|
|
257
|
+
}
|
|
258
|
+
),
|
|
259
|
+
crosshairX !== null && /* @__PURE__ */ jsx(Crosshair, { x: crosshairX, top: 0, bottom: barBand }),
|
|
260
|
+
/* @__PURE__ */ jsx(
|
|
261
|
+
AxisBottomDate,
|
|
262
|
+
{
|
|
263
|
+
top: barBand,
|
|
264
|
+
scale,
|
|
265
|
+
tickValues: band.tickValues,
|
|
266
|
+
tickFormat: (v) => formatX(String(v)),
|
|
267
|
+
anchorTerminals: band.xAnchorTerminals,
|
|
268
|
+
...band.xWrapWidth !== void 0 && { wrapWidth: band.xWrapWidth }
|
|
269
|
+
}
|
|
270
|
+
),
|
|
271
|
+
/* @__PURE__ */ jsx(
|
|
272
|
+
HoverOverlay,
|
|
273
|
+
{
|
|
274
|
+
width: plotWidth,
|
|
275
|
+
height: barBand,
|
|
276
|
+
onMove: cursor.onPointerMove,
|
|
277
|
+
onDown: cursor.onPointerDown,
|
|
278
|
+
onUp: cursor.onPointerUp,
|
|
279
|
+
onLeave: cursor.onPointerLeave,
|
|
280
|
+
onKeyDown: cursor.onKeyDown,
|
|
281
|
+
onBlur: cursor.onBlur,
|
|
282
|
+
valueMax: Math.max(bands.length - 1, 0),
|
|
283
|
+
...point !== null && {
|
|
284
|
+
valueNow: bands.indexOf(point),
|
|
285
|
+
valueText: formatX(getX(point))
|
|
286
|
+
},
|
|
287
|
+
...ariaLabel !== void 0 && { ariaLabel }
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
] })
|
|
291
|
+
]
|
|
292
|
+
}
|
|
293
|
+
),
|
|
279
294
|
band.showTooltip && point !== null && /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: band.tooltipAnchor, ariaLive: band.ariaLive, children: [
|
|
280
295
|
/* @__PURE__ */ jsx(
|
|
281
296
|
TooltipHeader,
|
|
@@ -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)),
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ContainerClass } from '../../tokens/size-classes.js';
|
|
2
|
+
import type { ChartSeries } from '../series.js';
|
|
3
|
+
/** Space between the plot edge and an end label's first glyph. */
|
|
4
|
+
export declare const END_LABEL_GAP = 6;
|
|
5
|
+
/** End labels are for a handful of lines; past this the legend alone names them. */
|
|
6
|
+
export declare const MAX_END_LABELS = 3;
|
|
7
|
+
/** Line box of one end label, as a multiple of its font size — the collision gap. */
|
|
8
|
+
export declare const END_LABEL_LINE_HEIGHT = 1.3;
|
|
9
|
+
/**
|
|
10
|
+
* Greedy collision nudging for direct labels. Each `ys` entry is a label's preferred CENTRE; the
|
|
11
|
+
* result keeps input order and holds every label at least `minGap` from its neighbours, inside
|
|
12
|
+
* `[min, max]`. Sorted by y, each label yields to the one above it, then a backward pass pulls the
|
|
13
|
+
* stack up off the bottom edge. Returns `null` when the labels cannot all fit — the caller draws
|
|
14
|
+
* none (the legend still names every series) rather than a partial or overlapping set.
|
|
15
|
+
*/
|
|
16
|
+
export declare function nudgeLabels(input: {
|
|
17
|
+
ys: readonly number[];
|
|
18
|
+
minGap: number;
|
|
19
|
+
min: number;
|
|
20
|
+
max: number;
|
|
21
|
+
}): number[] | null;
|
|
22
|
+
/**
|
|
23
|
+
* The right gutter the end labels need: the widest label plus the gap. `null` when it would eat
|
|
24
|
+
* more than a quarter of the plot — a label longer than that has no honest place in a gutter.
|
|
25
|
+
*/
|
|
26
|
+
export declare function endLabelGutter(input: {
|
|
27
|
+
labels: readonly string[];
|
|
28
|
+
fontPx: number;
|
|
29
|
+
plotWidth: number;
|
|
30
|
+
}): number | null;
|
|
31
|
+
/** One drawn end label: the series it names and its nudged centre y. */
|
|
32
|
+
export type EndLabel<T> = {
|
|
33
|
+
series: ChartSeries<T>;
|
|
34
|
+
y: number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Whether and how a chart draws end-of-line labels. Eligible only on a wide container with one y
|
|
38
|
+
* axis, no consumer `margin.right`, no header legend already naming every series for free (R2C-10:
|
|
39
|
+
* end labels REPLACE the legend, they never duplicate it), and 2..{@link MAX_END_LABELS} visible
|
|
40
|
+
* series that are all lines — a single line has its own title doing that job already (the same law
|
|
41
|
+
* that already suppresses a single-entry legend, `ChartFrame.resolveLegend`'s JSDoc). Each label
|
|
42
|
+
* sits at its line's last non-null value, nudged apart; the plan is `null` — no gutter reserved,
|
|
43
|
+
* nothing drawn — when any rule fails, a series has no plottable value, the stack cannot fit, or
|
|
44
|
+
* the gutter would be too wide. The gutter is measured from the label text.
|
|
45
|
+
*/
|
|
46
|
+
export declare function planEndLabels<T>(input: {
|
|
47
|
+
containerClass: ContainerClass;
|
|
48
|
+
hasY2: boolean;
|
|
49
|
+
hasMarginRight: boolean;
|
|
50
|
+
/** A `ChartCard` header slot already named every visible series — end labels would only repeat
|
|
51
|
+
* it, at the cost of a right-hand gutter the header slot cost nothing (R2C-10). */
|
|
52
|
+
hasHeaderLegend: boolean;
|
|
53
|
+
visible: readonly ChartSeries<T>[];
|
|
54
|
+
data: readonly T[];
|
|
55
|
+
yScale: (value: number) => number;
|
|
56
|
+
yMax: number;
|
|
57
|
+
fontPx: number;
|
|
58
|
+
/** Plot width before any gutter is taken. */
|
|
59
|
+
plotWidth: number;
|
|
60
|
+
}): {
|
|
61
|
+
gutter: number;
|
|
62
|
+
labels: EndLabel<T>[];
|
|
63
|
+
} | null;
|
|
64
|
+
//# sourceMappingURL=end-labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"end-labels.d.ts","sourceRoot":"","sources":["../../../src/charts/layout/end-labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG5C,kEAAkE;AAClE,eAAO,MAAM,aAAa,IAAI,CAAA;AAE9B,oFAAoF;AACpF,eAAO,MAAM,cAAc,IAAI,CAAA;AAE/B,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAKxC;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,MAAM,EAAE,GAAG,IAAI,CAsBlB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,MAAM,GAAG,IAAI,CAMhB;AAED,wEAAwE;AACxE,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/D;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE;IACtC,cAAc,EAAE,cAAc,CAAA;IAC9B,KAAK,EAAE,OAAO,CAAA;IACd,cAAc,EAAE,OAAO,CAAA;IACvB;uFACmF;IACnF,eAAe,EAAE,OAAO,CAAA;IACxB,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IAClC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAA;IAClB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,GAAG,IAAI,CAuCnD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { measureText } from "../utils/measure-text.js";
|
|
2
|
+
const END_LABEL_GAP = 6;
|
|
3
|
+
const MAX_END_LABELS = 3;
|
|
4
|
+
const END_LABEL_LINE_HEIGHT = 1.3;
|
|
5
|
+
const MAX_GUTTER_SHARE = 0.25;
|
|
6
|
+
function nudgeLabels(input) {
|
|
7
|
+
const { ys, minGap, min, max } = input;
|
|
8
|
+
if (ys.length === 0) return [];
|
|
9
|
+
if (ys.some((y) => !Number.isFinite(y))) return null;
|
|
10
|
+
if ((ys.length - 1) * minGap > max - min) return null;
|
|
11
|
+
const order = ys.map((y, i) => ({ y, i })).toSorted((a, b) => a.y - b.y);
|
|
12
|
+
let prev = Number.NEGATIVE_INFINITY;
|
|
13
|
+
const forward = order.map(({ y, i }) => {
|
|
14
|
+
prev = Math.max(y, min, prev + minGap);
|
|
15
|
+
return { i, y: prev };
|
|
16
|
+
});
|
|
17
|
+
let next = Number.POSITIVE_INFINITY;
|
|
18
|
+
const back = forward.toReversed().map(({ i, y }) => {
|
|
19
|
+
next = Math.min(y, max, next - minGap);
|
|
20
|
+
return { i, y: next };
|
|
21
|
+
});
|
|
22
|
+
if (next < min) return null;
|
|
23
|
+
return back.toSorted((a, b) => a.i - b.i).map((p) => p.y);
|
|
24
|
+
}
|
|
25
|
+
function endLabelGutter(input) {
|
|
26
|
+
const { labels, fontPx, plotWidth } = input;
|
|
27
|
+
if (labels.length === 0) return null;
|
|
28
|
+
const widest = labels.reduce((max, label) => Math.max(max, measureText(label, fontPx)), 0);
|
|
29
|
+
const gutter = Math.ceil(widest) + END_LABEL_GAP;
|
|
30
|
+
return gutter > plotWidth * MAX_GUTTER_SHARE ? null : gutter;
|
|
31
|
+
}
|
|
32
|
+
function planEndLabels(input) {
|
|
33
|
+
const {
|
|
34
|
+
containerClass,
|
|
35
|
+
hasY2,
|
|
36
|
+
hasMarginRight,
|
|
37
|
+
hasHeaderLegend,
|
|
38
|
+
visible,
|
|
39
|
+
data,
|
|
40
|
+
yScale,
|
|
41
|
+
yMax,
|
|
42
|
+
fontPx,
|
|
43
|
+
plotWidth
|
|
44
|
+
} = input;
|
|
45
|
+
if (containerClass !== "wide" || hasY2 || hasMarginRight || hasHeaderLegend) return null;
|
|
46
|
+
if (visible.length < 2 || visible.length > MAX_END_LABELS) return null;
|
|
47
|
+
if (!visible.every((s) => s.mark === "line")) return null;
|
|
48
|
+
const gutter = endLabelGutter({ labels: visible.map((s) => s.label), fontPx, plotWidth });
|
|
49
|
+
if (gutter === null) return null;
|
|
50
|
+
const placed = visible.flatMap((s) => {
|
|
51
|
+
const last = data.findLast((d) => s.getValue(d) !== null);
|
|
52
|
+
if (last === void 0) return [];
|
|
53
|
+
const value = s.getValue(last);
|
|
54
|
+
if (value === null) return [];
|
|
55
|
+
const y = yScale(value);
|
|
56
|
+
return Number.isFinite(y) ? [{ series: s, y }] : [];
|
|
57
|
+
});
|
|
58
|
+
if (placed.length !== visible.length) return null;
|
|
59
|
+
const lineHeight = Math.ceil(fontPx * END_LABEL_LINE_HEIGHT);
|
|
60
|
+
const ys = nudgeLabels({
|
|
61
|
+
ys: placed.map((p) => p.y),
|
|
62
|
+
minGap: lineHeight,
|
|
63
|
+
min: lineHeight / 2,
|
|
64
|
+
max: yMax - lineHeight / 2
|
|
65
|
+
});
|
|
66
|
+
if (ys === null) return null;
|
|
67
|
+
return { gutter, labels: placed.map((p, i) => ({ series: p.series, y: ys[i] ?? p.y })) };
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
END_LABEL_GAP,
|
|
71
|
+
END_LABEL_LINE_HEIGHT,
|
|
72
|
+
MAX_END_LABELS,
|
|
73
|
+
endLabelGutter,
|
|
74
|
+
nudgeLabels,
|
|
75
|
+
planEndLabels
|
|
76
|
+
};
|