basalt-ui 1.13.0 → 1.15.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 +15 -0
- package/README.md +38 -2
- package/agent/rules/basalt-charts.md +260 -108
- package/agent/rules/basalt-mantine.md +4 -2
- package/agent/skills/basalt-charts/SKILL.md +114 -64
- package/agent/skills/basalt-design/SKILL.md +4 -3
- package/configs/oxlint-plugin.js +152 -0
- package/configs/oxlint-plugin.test.ts +107 -0
- package/configs/oxlint.json +2 -0
- package/dist/charts/cursor/resolve.d.ts +33 -0
- package/dist/charts/cursor/resolve.d.ts.map +1 -0
- package/dist/charts/cursor/resolve.js +61 -0
- package/dist/charts/cursor/resolve.test.d.ts +2 -0
- package/dist/charts/cursor/resolve.test.d.ts.map +1 -0
- package/dist/charts/cursor/scope.d.ts +17 -0
- package/dist/charts/cursor/scope.d.ts.map +1 -0
- package/dist/charts/cursor/scope.js +20 -0
- package/dist/charts/cursor/store.d.ts +31 -0
- package/dist/charts/cursor/store.d.ts.map +1 -0
- package/dist/charts/cursor/store.js +25 -0
- package/dist/charts/cursor/store.test.d.ts +2 -0
- package/dist/charts/cursor/store.test.d.ts.map +1 -0
- package/dist/charts/hooks/useChartCursor.d.ts +39 -0
- package/dist/charts/hooks/useChartCursor.d.ts.map +1 -0
- package/dist/charts/hooks/useChartCursor.js +104 -0
- package/dist/charts/hooks/useChartSize.d.ts +8 -4
- package/dist/charts/hooks/useChartSize.d.ts.map +1 -1
- package/dist/charts/index.d.ts +16 -13
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +38 -19
- package/dist/charts/kinds/Bars.d.ts +25 -47
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.js +230 -390
- package/dist/charts/kinds/Donut.d.ts +5 -4
- package/dist/charts/kinds/Donut.d.ts.map +1 -1
- package/dist/charts/kinds/Donut.js +17 -14
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.js +136 -90
- package/dist/charts/kinds/Heatmap.d.ts +15 -11
- package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
- package/dist/charts/kinds/Heatmap.js +38 -22
- package/dist/charts/kinds/MultiLine.d.ts +27 -35
- package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
- package/dist/charts/kinds/MultiLine.js +114 -237
- package/dist/charts/kinds/StackedArea.d.ts +21 -10
- package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
- package/dist/charts/kinds/StackedArea.js +74 -132
- package/dist/charts/kinds/ZonedLine.d.ts +24 -40
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/charts/kinds/ZonedLine.js +103 -184
- package/dist/charts/layout/auto-margin.d.ts +60 -0
- package/dist/charts/layout/auto-margin.d.ts.map +1 -0
- package/dist/charts/layout/auto-margin.js +37 -0
- package/dist/charts/layout/auto-margin.test.d.ts +2 -0
- package/dist/charts/layout/auto-margin.test.d.ts.map +1 -0
- package/dist/charts/primitives/CartesianChart.d.ts +143 -0
- package/dist/charts/primitives/CartesianChart.d.ts.map +1 -0
- package/dist/charts/primitives/CartesianChart.js +349 -0
- package/dist/charts/primitives/CartesianChart.test.d.ts +2 -0
- package/dist/charts/primitives/CartesianChart.test.d.ts.map +1 -0
- package/dist/charts/primitives/ChartFrame.d.ts +16 -5
- package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
- package/dist/charts/primitives/ChartFrame.js +17 -2
- package/dist/charts/primitives/ChartLegend.d.ts +12 -1
- package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
- package/dist/charts/primitives/ChartLegend.js +21 -3
- package/dist/charts/primitives/ChartLegend.test.d.ts +2 -0
- package/dist/charts/primitives/ChartLegend.test.d.ts.map +1 -0
- package/dist/charts/primitives/ChartTooltip.d.ts +16 -16
- package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
- package/dist/charts/primitives/ChartTooltip.js +45 -19
- package/dist/charts/primitives/HoverOverlay.d.ts +19 -4
- package/dist/charts/primitives/HoverOverlay.d.ts.map +1 -1
- package/dist/charts/primitives/HoverOverlay.js +22 -1
- package/dist/charts/primitives/XZoneRects.d.ts +40 -0
- package/dist/charts/primitives/XZoneRects.d.ts.map +1 -0
- package/dist/charts/primitives/XZoneRects.js +28 -0
- package/dist/charts/primitives/XZoneRects.test.d.ts +2 -0
- package/dist/charts/primitives/XZoneRects.test.d.ts.map +1 -0
- package/dist/charts/series.d.ts +16 -1
- package/dist/charts/series.d.ts.map +1 -1
- package/dist/charts/series.js +3 -1
- package/dist/charts/series.test.d.ts +2 -0
- package/dist/charts/series.test.d.ts.map +1 -0
- package/dist/charts/utils/measure-text.d.ts +25 -0
- package/dist/charts/utils/measure-text.d.ts.map +1 -0
- package/dist/charts/utils/measure-text.js +64 -0
- package/dist/charts/utils/measure-text.test.d.ts +2 -0
- package/dist/charts/utils/measure-text.test.d.ts.map +1 -0
- package/dist/content/fence-block.d.ts.map +1 -1
- package/dist/shell/app-sidebar.d.ts +19 -1
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +30 -26
- package/dist/shell/app-sidebar.module.css +11 -0
- package/dist/shell/app-sidebar.module.css.d.ts +1 -0
- package/dist/shell/app-sidebar.test.d.ts +2 -0
- package/dist/shell/app-sidebar.test.d.ts.map +1 -0
- package/dist/shell/index.d.ts +10 -1
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +2 -0
- package/dist/shell/index.test.d.ts +2 -0
- package/dist/shell/index.test.d.ts.map +1 -0
- package/dist/surfaces.d.ts +1 -1
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +1 -1
- package/dist/tokens/chart-margin.test.d.ts +2 -0
- package/dist/tokens/chart-margin.test.d.ts.map +1 -0
- package/dist/tokens/index.d.ts +29 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +10 -0
- package/dist/tokens/palette.d.ts +4 -0
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +3 -0
- package/llms.txt +3 -3
- package/package.json +1 -1
- package/src/charts/cursor/resolve.test.ts +61 -0
- package/src/charts/cursor/resolve.ts +102 -0
- package/src/charts/cursor/scope.tsx +32 -0
- package/src/charts/cursor/store.test.ts +46 -0
- package/src/charts/cursor/store.ts +53 -0
- package/src/charts/hooks/useChartCursor.ts +163 -0
- package/src/charts/hooks/useChartSize.ts +8 -4
- package/src/charts/index.ts +34 -14
- package/src/charts/kinds/Bars.tsx +327 -460
- package/src/charts/kinds/Donut.tsx +31 -23
- package/src/charts/kinds/DualPanel.tsx +228 -134
- package/src/charts/kinds/Heatmap.tsx +72 -47
- package/src/charts/kinds/MultiLine.tsx +158 -294
- package/src/charts/kinds/StackedArea.tsx +116 -175
- package/src/charts/kinds/ZonedLine.tsx +148 -255
- package/src/charts/layout/auto-margin.test.ts +42 -0
- package/src/charts/layout/auto-margin.ts +110 -0
- package/src/charts/primitives/CartesianChart.test.ts +99 -0
- package/src/charts/primitives/CartesianChart.tsx +566 -0
- package/src/charts/primitives/ChartFrame.test.tsx +33 -0
- package/src/charts/primitives/ChartFrame.tsx +40 -4
- package/src/charts/primitives/ChartLegend.test.tsx +48 -0
- package/src/charts/primitives/ChartLegend.tsx +45 -2
- package/src/charts/primitives/ChartTooltip.tsx +67 -37
- package/src/charts/primitives/HoverOverlay.tsx +39 -3
- package/src/charts/primitives/XZoneRects.test.tsx +63 -0
- package/src/charts/primitives/XZoneRects.tsx +67 -0
- package/src/charts/series.test.ts +61 -0
- package/src/charts/series.ts +18 -1
- package/src/charts/utils/measure-text.test.ts +36 -0
- package/src/charts/utils/measure-text.ts +109 -0
- package/src/content/fence-block.tsx +2 -3
- package/src/shell/app-sidebar.module.css +11 -0
- package/src/shell/app-sidebar.module.css.d.ts +1 -0
- package/src/shell/app-sidebar.test.tsx +98 -0
- package/src/shell/app-sidebar.tsx +22 -0
- package/src/shell/index.test.tsx +35 -0
- package/src/shell/index.tsx +11 -0
- package/src/surfaces.ts +2 -1
- package/src/theme/spacing.test.ts +2 -0
- package/src/tokens/chart-margin.test.ts +39 -0
- package/src/tokens/density.test.ts +1 -0
- package/src/tokens/index.ts +36 -0
- package/src/tokens/palette.ts +3 -0
- package/dist/charts/hooks/useChartTooltip.d.ts +0 -13
- package/dist/charts/hooks/useChartTooltip.d.ts.map +0 -1
- package/dist/charts/hooks/useChartTooltip.js +0 -26
- package/dist/charts/hooks/useHoverSync.d.ts +0 -46
- package/dist/charts/hooks/useHoverSync.d.ts.map +0 -1
- package/dist/charts/hooks/useHoverSync.js +0 -75
- package/dist/charts/hover-context.d.ts +0 -21
- package/dist/charts/hover-context.d.ts.map +0 -1
- package/dist/charts/hover-context.js +0 -12
- package/dist/charts/hover-sync.d.ts +0 -14
- package/dist/charts/hover-sync.d.ts.map +0 -1
- package/dist/charts/hover-sync.js +0 -17
- package/dist/charts/primitives/ResponsiveChart.d.ts +0 -45
- package/dist/charts/primitives/ResponsiveChart.d.ts.map +0 -1
- package/dist/charts/primitives/ResponsiveChart.js +0 -24
- package/src/charts/hooks/useChartTooltip.ts +0 -31
- package/src/charts/hooks/useHoverSync.ts +0 -152
- package/src/charts/hover-context.ts +0 -28
- package/src/charts/hover-sync.tsx +0 -37
- package/src/charts/primitives/ResponsiveChart.tsx +0 -64
|
@@ -1,66 +1,58 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CartesianTooltipConfig, AxisConfig } from '../primitives/CartesianChart.js';
|
|
2
|
+
import type { XZoneSpec } from '../primitives/XZoneRects.js';
|
|
2
3
|
import type { ZoneSpec } from '../primitives/ZoneRects.js';
|
|
3
4
|
import type { ChartLegendConfig, ChartSeries } from '../series.js';
|
|
4
5
|
export type MultiLineProps<T> = {
|
|
5
6
|
data: T[];
|
|
6
|
-
/** Fixed height in pixels, forwarded to
|
|
7
|
+
/** Fixed height in pixels, forwarded to `CartesianChart`. Default 240. */
|
|
7
8
|
height?: number;
|
|
8
9
|
chartId: string;
|
|
9
10
|
/** Extracts the x-axis category (date string) from a data point. */
|
|
10
11
|
getX: (d: T) => string;
|
|
11
|
-
/** 1+ line series sharing
|
|
12
|
-
* tooltip rows. */
|
|
12
|
+
/** 1+ line series sharing the y-axis(es) — the single source of truth for color, dash, legend,
|
|
13
|
+
* and tooltip rows. A series opts into the right axis with `axis: 'right'`. */
|
|
13
14
|
series: ChartSeries<T>[];
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/** When 'auto': padding multiplier applied away from the domain. Default 1.1. The lower bound
|
|
22
|
-
* always pads DOWN from `min(dataMin, yAutoMinCeil)` (never up, which would clip data) — see
|
|
23
|
-
* {@link padAutoLower}. */
|
|
24
|
-
yAutoPad?: number;
|
|
25
|
-
/** Horizontal value-range overlays (target zones), rendered behind the lines on the left scale. */
|
|
15
|
+
/** Left y-axis. Collapses the old `yDomain` / `yAutoMaxFloor` / `yAutoMinCeil` / `yAutoPad` /
|
|
16
|
+
* `numTicksY` / `formatYTick` prop soup into one object. */
|
|
17
|
+
y?: AxisConfig<T>;
|
|
18
|
+
/** Right y-axis. Passing it is what makes the chart dual-axis — the margin widens by
|
|
19
|
+
* measurement, and `axis: 'right'` series read against it. */
|
|
20
|
+
y2?: AxisConfig<T>;
|
|
21
|
+
/** Horizontal value-range overlays (target zones), rendered behind the lines. */
|
|
26
22
|
zones?: ZoneSpec[];
|
|
23
|
+
/** Vertical x-range overlays (time windows), rendered behind the lines. Bounds are `getX`
|
|
24
|
+
* domain keys. */
|
|
25
|
+
xZones?: XZoneSpec[];
|
|
27
26
|
/** Horizontal reference lines. Solid by default; set dashed: true for a dashed line. */
|
|
28
27
|
refLines?: {
|
|
29
28
|
value: number;
|
|
30
29
|
color: string;
|
|
31
30
|
dashed?: boolean;
|
|
32
31
|
}[];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/** Tooltip
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
formatYTick?: (v: number) => string;
|
|
39
|
-
/** Label shown at the right of the tooltip header (e.g. status badge). */
|
|
40
|
-
tooltipLabel?: (d: T) => {
|
|
41
|
-
text: string;
|
|
42
|
-
color: string;
|
|
43
|
-
} | null;
|
|
44
|
-
/** Extra tooltip rows rendered after the per-series rows. */
|
|
45
|
-
renderExtraTooltipRows?: (d: T) => ReactNode;
|
|
32
|
+
/** Exact number of x ticks. Default: as many as fit. */
|
|
33
|
+
xTicks?: number;
|
|
34
|
+
/** Tooltip config — `label` for a right-aligned header badge, `extraRows` for rows appended
|
|
35
|
+
* after the derived per-series rows. `false` disables the tooltip entirely. */
|
|
36
|
+
tooltip?: CartesianTooltipConfig<T> | false;
|
|
46
37
|
/** Marker glyph for per-point markers. Default 'circle'. */
|
|
47
38
|
markerShape?: 'circle' | 'star';
|
|
48
|
-
/** Legend config forwarded to `
|
|
39
|
+
/** Legend config forwarded to `CartesianChart`; `false` disables the legend (sparkline escape).
|
|
49
40
|
* Default `{ placement: 'bottom' }`. */
|
|
50
41
|
legend?: ChartLegendConfig | false;
|
|
51
|
-
/** Accessible text alternative, forwarded to `
|
|
42
|
+
/** Accessible text alternative, forwarded to `CartesianChart` as `aria-label` (+ `role="img"`). */
|
|
52
43
|
ariaLabel?: string;
|
|
53
|
-
/** Forwarded to `
|
|
44
|
+
/** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
54
45
|
isPending?: boolean;
|
|
55
46
|
};
|
|
56
47
|
/**
|
|
57
|
-
* N series sharing one y-
|
|
48
|
+
* N series sharing one or two y-axes, with optional zones/reference lines, per-point markers
|
|
58
49
|
* (PR stars / status dots), a dashed companion line per series, legend-hover dimming, and a
|
|
59
50
|
* shared-cursor tooltip. Generalizes the multi-line argo charts (e1RM trend, relative
|
|
60
51
|
* progression, training load, fitness trends).
|
|
61
52
|
*
|
|
62
|
-
* Composes `
|
|
63
|
-
*
|
|
53
|
+
* Composes `CartesianChart` for measuring, scales, grid, axes, cursor, and tooltip — this kind
|
|
54
|
+
* draws ONLY the marks (lines + per-point markers). `series` is the single array that drives the
|
|
55
|
+
* plotted lines, the legend, and the tooltip rows.
|
|
64
56
|
*
|
|
65
57
|
* X-axis is built from the full `data` array so the calendar is preserved even when a series
|
|
66
58
|
* has nulls; each series line skips null points (creating visual gaps).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiLine.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MultiLine.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MultiLine.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/MultiLine.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAEnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG/D,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;mFAC+E;IAC/E,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;gEAC4D;IAC5D,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB;kEAC8D;IAC9D,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IAClB,iFAAiF;IACjF,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;IAClB;sBACkB;IAClB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAC/D,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;mFAC+E;IAC/E,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAA;IAC3C,4DAA4D;IAC5D,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;IAC/B;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AA4BD;;;;;;;;;;;;GAYG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BAgDlD;AAoGD;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
|
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { curveMonotoneX } from "@visx/curve";
|
|
3
|
-
import { GridRows } from "@visx/grid";
|
|
4
|
-
import { Group } from "@visx/group";
|
|
5
|
-
import { scaleLinear, scalePoint } from "@visx/scale";
|
|
6
3
|
import { LinePath } from "@visx/shape";
|
|
7
|
-
import { memo, useMemo
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
ChartTooltip,
|
|
11
|
-
TooltipBody,
|
|
12
|
-
TooltipHeader,
|
|
13
|
-
TooltipRow,
|
|
14
|
-
useTooltipStyles
|
|
15
|
-
} from "../primitives/ChartTooltip.js";
|
|
16
|
-
import { ChartFrame, resolveLegend } from "../primitives/ChartFrame.js";
|
|
17
|
-
import { Crosshair, SeriesDot } from "../primitives/Crosshair.js";
|
|
18
|
-
import { HoverOverlay } from "../primitives/HoverOverlay.js";
|
|
19
|
-
import { ZoneRects } from "../primitives/ZoneRects.js";
|
|
20
|
-
import { useHoverSync } from "../hooks/useHoverSync.js";
|
|
21
|
-
import { deriveTooltipRows, LINE_OVERLAY_STROKE_WIDTH } from "../series.js";
|
|
4
|
+
import { memo, useMemo } from "react";
|
|
5
|
+
import { CartesianChart } from "../primitives/CartesianChart.js";
|
|
6
|
+
import { LINE_OVERLAY_STROKE_WIDTH } from "../series.js";
|
|
22
7
|
import { VX } from "../../tokens/index.js";
|
|
23
|
-
import { padAutoLower } from "../utils/domain.js";
|
|
24
|
-
import { smartTicks, smartTicksEvery } from "../utils/ticks.js";
|
|
25
8
|
const STAR_R = 6;
|
|
26
9
|
function starPath(cx, cy, r) {
|
|
27
10
|
const inner = r * 0.4;
|
|
@@ -33,241 +16,135 @@ function starPath(cx, cy, r) {
|
|
|
33
16
|
}
|
|
34
17
|
return `M${pts.join("L")}Z`;
|
|
35
18
|
}
|
|
36
|
-
function
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return /* @__PURE__ */ jsx(
|
|
44
|
-
ChartFrame,
|
|
45
|
-
{
|
|
46
|
-
series: styledSeries,
|
|
47
|
-
chartId,
|
|
48
|
-
...height !== void 0 && { height },
|
|
49
|
-
...ariaLabel !== void 0 && { ariaLabel },
|
|
50
|
-
...isPending !== void 0 && { isPending },
|
|
51
|
-
legend: resolveLegend(legend, {
|
|
52
|
-
highlighted: highlightedKey,
|
|
53
|
-
onHighlight: setHighlightedKey
|
|
54
|
-
}),
|
|
55
|
-
children: (plot) => /* @__PURE__ */ jsx(
|
|
56
|
-
MultiLinePlot,
|
|
57
|
-
{
|
|
58
|
-
...props,
|
|
59
|
-
series: styledSeries,
|
|
60
|
-
plot,
|
|
61
|
-
highlightedKey
|
|
62
|
-
}
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
);
|
|
19
|
+
function seriesPoints(series, data) {
|
|
20
|
+
const pts = [];
|
|
21
|
+
for (const d of data) {
|
|
22
|
+
const v = series.getValue(d);
|
|
23
|
+
if (v !== null && v !== void 0 && !Number.isNaN(v)) pts.push({ __d: d, __y: v });
|
|
24
|
+
}
|
|
25
|
+
return pts;
|
|
66
26
|
}
|
|
67
|
-
function
|
|
27
|
+
function MultiLineInner(props) {
|
|
68
28
|
const {
|
|
69
29
|
data,
|
|
70
30
|
chartId,
|
|
71
31
|
getX,
|
|
72
32
|
series,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
numTicksY = 5,
|
|
81
|
-
formatValue,
|
|
82
|
-
formatYTick,
|
|
83
|
-
tooltipLabel,
|
|
84
|
-
renderExtraTooltipRows,
|
|
33
|
+
y,
|
|
34
|
+
y2,
|
|
35
|
+
zones,
|
|
36
|
+
xZones,
|
|
37
|
+
refLines,
|
|
38
|
+
xTicks,
|
|
39
|
+
tooltip,
|
|
85
40
|
markerShape = "circle",
|
|
86
|
-
|
|
87
|
-
|
|
41
|
+
height,
|
|
42
|
+
legend,
|
|
43
|
+
ariaLabel,
|
|
44
|
+
isPending
|
|
88
45
|
} = props;
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const yMax = plot.height - MARGIN.top - MARGIN.bottom;
|
|
93
|
-
const xScale = useMemo(
|
|
94
|
-
() => scalePoint({
|
|
95
|
-
// Full calendar — axis does not compress across nulls.
|
|
96
|
-
domain: data.map(getX),
|
|
97
|
-
range: [0, xMax],
|
|
98
|
-
padding: 0.3
|
|
99
|
-
}),
|
|
100
|
-
[data, xMax, getX]
|
|
46
|
+
const styledSeries = useMemo(
|
|
47
|
+
() => series.map((s) => ({ ...s, strokeWidth: s.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH })),
|
|
48
|
+
[series]
|
|
101
49
|
);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
let dataMax = -Infinity;
|
|
105
|
-
let dataMin = Infinity;
|
|
106
|
-
for (const d of data) {
|
|
107
|
-
for (const s of series) {
|
|
108
|
-
const v = s.getValue(d);
|
|
109
|
-
if (v === null || v === void 0 || Number.isNaN(v)) continue;
|
|
110
|
-
if (v > dataMax) dataMax = v;
|
|
111
|
-
if (v < dataMin) dataMin = v;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
const safeMax = Number.isFinite(dataMax) ? dataMax : 0;
|
|
115
|
-
const safeMin = Number.isFinite(dataMin) ? dataMin : 0;
|
|
116
|
-
const upper = Math.max(safeMax, yAutoMaxFloor ?? safeMax) * yAutoPad;
|
|
117
|
-
const lower = padAutoLower(Math.min(safeMin, yAutoMinCeil), yAutoPad);
|
|
118
|
-
return scaleLinear({ domain: [lower, upper], range: [yMax, 0], nice: true });
|
|
119
|
-
}
|
|
120
|
-
return scaleLinear({ domain: yDomain, range: [yMax, 0] });
|
|
121
|
-
}, [data, series, yDomain, yMax, yAutoPad, yAutoMaxFloor, yAutoMinCeil]);
|
|
122
|
-
const tooltipStyles = useTooltipStyles();
|
|
123
|
-
const { tip, tooltipRef, syncedPoint, isDirectHover, handleMouse, handleLeave } = useHoverSync(
|
|
50
|
+
return /* @__PURE__ */ jsx(
|
|
51
|
+
CartesianChart,
|
|
124
52
|
{
|
|
125
53
|
data,
|
|
126
54
|
chartId,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
55
|
+
getX,
|
|
56
|
+
series: styledSeries,
|
|
57
|
+
...y !== void 0 && { y },
|
|
58
|
+
...y2 !== void 0 && { y2 },
|
|
59
|
+
...zones !== void 0 && { zones },
|
|
60
|
+
...xZones !== void 0 && { xZones },
|
|
61
|
+
...refLines !== void 0 && { refLines },
|
|
62
|
+
...xTicks !== void 0 && { xTicks },
|
|
63
|
+
...tooltip !== void 0 && { tooltip },
|
|
64
|
+
...height !== void 0 && { height },
|
|
65
|
+
...legend !== void 0 && { legend },
|
|
66
|
+
...ariaLabel !== void 0 && { ariaLabel },
|
|
67
|
+
...isPending !== void 0 && { isPending },
|
|
68
|
+
children: (ctx) => /* @__PURE__ */ jsx(MultiLineMarks, { getX, markerShape, ctx })
|
|
130
69
|
}
|
|
131
70
|
);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return out;
|
|
147
|
-
}, [data, series]);
|
|
148
|
-
const tooltipLbl = tip ? tooltipLabel?.(tip.data) ?? null : null;
|
|
71
|
+
}
|
|
72
|
+
function MultiLineMarks({
|
|
73
|
+
getX,
|
|
74
|
+
markerShape,
|
|
75
|
+
ctx
|
|
76
|
+
}) {
|
|
77
|
+
const { data, visible, xScale, yScale, y2Scale, highlighted } = ctx;
|
|
78
|
+
const pointsBySeries = useMemo(() => {
|
|
79
|
+
const m = /* @__PURE__ */ new Map();
|
|
80
|
+
for (const s of visible) m.set(s.key, seriesPoints(s, data));
|
|
81
|
+
return m;
|
|
82
|
+
}, [visible, data]);
|
|
83
|
+
const dimOpacity = (s) => highlighted === null || s.key === highlighted || s.parent === highlighted ? 1 : 0.25;
|
|
84
|
+
const scaleFor = (s) => s.axis === "right" && y2Scale !== null ? y2Scale : yScale;
|
|
149
85
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
86
|
+
visible.map((s) => {
|
|
87
|
+
const valid = pointsBySeries.get(s.key) ?? [];
|
|
88
|
+
if (valid.length === 0) return null;
|
|
89
|
+
const scale = scaleFor(s);
|
|
90
|
+
return /* @__PURE__ */ jsx(
|
|
91
|
+
LinePath,
|
|
155
92
|
{
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
strokeDasharray:
|
|
93
|
+
data: valid,
|
|
94
|
+
x: (p) => xScale(getX(p.__d)) ?? 0,
|
|
95
|
+
y: (p) => scale(p.__y),
|
|
96
|
+
stroke: s.color,
|
|
97
|
+
strokeWidth: s.strokeWidth ?? LINE_OVERLAY_STROKE_WIDTH,
|
|
98
|
+
strokeDasharray: s.dash === "dashed" ? VX.dashArray : void 0,
|
|
99
|
+
strokeOpacity: dimOpacity(s),
|
|
100
|
+
curve: curveMonotoneX
|
|
162
101
|
},
|
|
163
|
-
`
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
102
|
+
`line-${s.key}`
|
|
103
|
+
);
|
|
104
|
+
}),
|
|
105
|
+
visible.flatMap((s) => {
|
|
106
|
+
const getMarker = s.getMarker;
|
|
107
|
+
if (!getMarker) return [];
|
|
108
|
+
const scale = scaleFor(s);
|
|
109
|
+
const op = dimOpacity(s);
|
|
110
|
+
const markers = [];
|
|
111
|
+
for (const p of pointsBySeries.get(s.key) ?? []) {
|
|
112
|
+
const m = getMarker(p.__d);
|
|
113
|
+
if (m === null) continue;
|
|
114
|
+
const cx = xScale(getX(p.__d)) ?? 0;
|
|
115
|
+
const cy = scale(p.__y);
|
|
116
|
+
const color = m.color ?? s.color;
|
|
117
|
+
const r = m.r ?? (markerShape === "star" ? STAR_R : VX.dotR);
|
|
118
|
+
markers.push(
|
|
119
|
+
markerShape === "star" ? /* @__PURE__ */ jsx(
|
|
120
|
+
"path",
|
|
121
|
+
{
|
|
122
|
+
d: starPath(cx, cy, r),
|
|
123
|
+
fill: color,
|
|
124
|
+
stroke: VX.dotStroke,
|
|
125
|
+
strokeWidth: 1.5,
|
|
126
|
+
fillOpacity: op,
|
|
127
|
+
strokeOpacity: op
|
|
128
|
+
},
|
|
129
|
+
`mk-${s.key}-${getX(p.__d)}`
|
|
130
|
+
) : /* @__PURE__ */ jsx(
|
|
131
|
+
"circle",
|
|
132
|
+
{
|
|
133
|
+
cx,
|
|
134
|
+
cy,
|
|
135
|
+
r,
|
|
136
|
+
fill: color,
|
|
137
|
+
stroke: VX.dotStroke,
|
|
138
|
+
strokeWidth: 2,
|
|
139
|
+
fillOpacity: op,
|
|
140
|
+
strokeOpacity: op
|
|
141
|
+
},
|
|
142
|
+
`mk-${s.key}-${getX(p.__d)}`
|
|
143
|
+
)
|
|
181
144
|
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (!getMarker) return [];
|
|
186
|
-
const op = dimOpacity(s);
|
|
187
|
-
const markers = [];
|
|
188
|
-
for (const p of seriesPts.get(s.key) ?? []) {
|
|
189
|
-
const m = getMarker(p.__d);
|
|
190
|
-
if (m === null) continue;
|
|
191
|
-
const cx = xScale(getX(p.__d)) ?? 0;
|
|
192
|
-
const cy = yScale(p.__y);
|
|
193
|
-
const color = m.color ?? s.color;
|
|
194
|
-
const r = m.r ?? (markerShape === "star" ? STAR_R : VX.dotR);
|
|
195
|
-
markers.push(
|
|
196
|
-
markerShape === "star" ? /* @__PURE__ */ jsx(
|
|
197
|
-
"path",
|
|
198
|
-
{
|
|
199
|
-
d: starPath(cx, cy, r),
|
|
200
|
-
fill: color,
|
|
201
|
-
stroke: VX.dotStroke,
|
|
202
|
-
strokeWidth: 1.5,
|
|
203
|
-
fillOpacity: op,
|
|
204
|
-
strokeOpacity: op
|
|
205
|
-
},
|
|
206
|
-
`mk-${s.key}-${getX(p.__d)}`
|
|
207
|
-
) : /* @__PURE__ */ jsx(
|
|
208
|
-
"circle",
|
|
209
|
-
{
|
|
210
|
-
cx,
|
|
211
|
-
cy,
|
|
212
|
-
r,
|
|
213
|
-
fill: color,
|
|
214
|
-
stroke: VX.dotStroke,
|
|
215
|
-
strokeWidth: 2,
|
|
216
|
-
fillOpacity: op,
|
|
217
|
-
strokeOpacity: op
|
|
218
|
-
},
|
|
219
|
-
`mk-${s.key}-${getX(p.__d)}`
|
|
220
|
-
)
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
return markers;
|
|
224
|
-
}),
|
|
225
|
-
syncedPoint && (() => {
|
|
226
|
-
const sx = xScale(getX(syncedPoint)) ?? 0;
|
|
227
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
228
|
-
/* @__PURE__ */ jsx(Crosshair, { x: sx, top: 0, bottom: yMax }),
|
|
229
|
-
series.map((s) => {
|
|
230
|
-
const v = s.getValue(syncedPoint);
|
|
231
|
-
if (v === null || v === void 0 || Number.isNaN(v)) return null;
|
|
232
|
-
return /* @__PURE__ */ jsx(SeriesDot, { cx: sx, cy: yScale(v), color: s.color }, `dot-${s.key}`);
|
|
233
|
-
})
|
|
234
|
-
] });
|
|
235
|
-
})(),
|
|
236
|
-
/* @__PURE__ */ jsx(
|
|
237
|
-
AxisLeftNumeric,
|
|
238
|
-
{
|
|
239
|
-
scale: yScale,
|
|
240
|
-
numTicks: numTicksY,
|
|
241
|
-
...formatYTick !== void 0 && { tickFormat: formatYTick }
|
|
242
|
-
}
|
|
243
|
-
),
|
|
244
|
-
/* @__PURE__ */ jsx(AxisBottomDate, { top: yMax, scale: xScale, tickValues }),
|
|
245
|
-
/* @__PURE__ */ jsx(HoverOverlay, { width: xMax, height: yMax, onMove: handleMouse, onLeave: handleLeave })
|
|
246
|
-
] }) }),
|
|
247
|
-
/* @__PURE__ */ jsx(ChartTooltip, { tip: isDirectHover ? tip : null, tooltipRef, styles: tooltipStyles, children: tip && isDirectHover && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
248
|
-
/* @__PURE__ */ jsx(
|
|
249
|
-
TooltipHeader,
|
|
250
|
-
{
|
|
251
|
-
date: getX(tip.data),
|
|
252
|
-
...tooltipLbl !== null && { label: tooltipLbl.text, labelColor: tooltipLbl.color }
|
|
253
|
-
}
|
|
254
|
-
),
|
|
255
|
-
/* @__PURE__ */ jsxs(TooltipBody, { children: [
|
|
256
|
-
deriveTooltipRows(series, tip.data, formatValue).map((row) => /* @__PURE__ */ jsx(
|
|
257
|
-
TooltipRow,
|
|
258
|
-
{
|
|
259
|
-
color: row.color,
|
|
260
|
-
label: row.label,
|
|
261
|
-
value: row.value,
|
|
262
|
-
shape: row.shape,
|
|
263
|
-
dashed: row.dashed,
|
|
264
|
-
...row.strokeWidth !== void 0 && { strokeWidth: row.strokeWidth }
|
|
265
|
-
},
|
|
266
|
-
row.key
|
|
267
|
-
)),
|
|
268
|
-
renderExtraTooltipRows?.(tip.data)
|
|
269
|
-
] })
|
|
270
|
-
] }) })
|
|
145
|
+
}
|
|
146
|
+
return markers;
|
|
147
|
+
})
|
|
271
148
|
] });
|
|
272
149
|
}
|
|
273
150
|
const MultiLine = memo(MultiLineInner);
|
|
@@ -1,30 +1,41 @@
|
|
|
1
|
+
import type { AxisConfig } from '../primitives/CartesianChart.js';
|
|
1
2
|
import type { ChartLegendConfig, ChartSeries } from '../series.js';
|
|
2
3
|
export type StackedAreaProps<T> = {
|
|
3
4
|
data: T[];
|
|
4
|
-
/** Fixed height in pixels, forwarded to
|
|
5
|
+
/** Fixed height in pixels, forwarded to `CartesianChart`. Default 240. */
|
|
5
6
|
height?: number;
|
|
6
7
|
chartId: string;
|
|
7
8
|
getX: (d: T) => string;
|
|
8
9
|
/** The stacked bands, bottom to top — the single source of truth for color, legend, and tooltip
|
|
9
10
|
* rows. Typically `mark: 'area'` (rendered as a `bar`-shaped legend/tooltip swatch). */
|
|
10
11
|
series: ChartSeries<T>[];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/**
|
|
12
|
+
/** Axis config for ticks/format/grid. `domain` defaults to the summed per-point stack total
|
|
13
|
+
* (padded ×1.1, or `autoMaxFloor` if higher) rather than a per-series max — the seam a stacked
|
|
14
|
+
* chart needs, since the plotted quantity is the cumulative band top, not any one series' own
|
|
15
|
+
* value. Pass a fixed tuple or your own function to override. */
|
|
16
|
+
y?: AxisConfig<T>;
|
|
17
|
+
/** X tick count override. Default: as many as fit. */
|
|
18
|
+
xTicks?: number;
|
|
19
|
+
/** Legend config forwarded to `CartesianChart`; `false` disables the legend (sparkline escape).
|
|
17
20
|
* Default `{ placement: 'bottom' }`. */
|
|
18
21
|
legend?: ChartLegendConfig | false;
|
|
19
|
-
/** Accessible text alternative, forwarded
|
|
22
|
+
/** Accessible text alternative, forwarded as `aria-label` (+ `role="img"`). */
|
|
20
23
|
ariaLabel?: string;
|
|
21
|
-
/** Forwarded to `
|
|
24
|
+
/** Forwarded to `CartesianChart` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
22
25
|
isPending?: boolean;
|
|
23
26
|
};
|
|
24
27
|
/**
|
|
25
28
|
* Multi-series stacked-area chart with an optional derived legend (default on) and legend-hover
|
|
26
29
|
* dimming. Each band's fillOpacity is dimmed when a different key is highlighted via the legend.
|
|
27
|
-
*
|
|
30
|
+
*
|
|
31
|
+
* Composes `CartesianChart` (`docs/CHARTS-SPEC.md` §2) — margin, scale, grid, axes, cursor, and
|
|
32
|
+
* tooltip are the primitive's job. This file draws only the `AreaStack` bands.
|
|
33
|
+
*
|
|
34
|
+
* The tooltip must render top-to-bottom (matching the visual stack read from the top), but the
|
|
35
|
+
* marks must stack bottom-to-top (matching `series`' own order) — the two can't share one order.
|
|
36
|
+
* `CartesianChart`'s `series` prop drives BOTH the derived tooltip rows and legend, so `series` is
|
|
37
|
+
* passed reversed to it (tooltip/legend read top-first); the marks then reverse `ctx.visible` back
|
|
38
|
+
* to restore the original bottom-to-top stacking order for `AreaStack`'s `keys`.
|
|
28
39
|
*/
|
|
29
40
|
declare function StackedAreaInner<T>(props: StackedAreaProps<T>): import("react").JSX.Element;
|
|
30
41
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StackedArea.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/StackedArea.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StackedArea.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/StackedArea.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,8BAA8B,CAAA;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE/D,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;4FACwF;IACxF,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB;;;qEAGiE;IACjE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACjB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,iBAAS,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,+BAgEtD;AA+CD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAA6B,OAAO,gBAAgB,CAAA"}
|