basalt-ui 1.14.0 → 1.16.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 +279 -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/agent/templates/CLAUDE-block.md.tpl +9 -6
- 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 +45 -54
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.js +235 -392
- package/dist/charts/kinds/Bars.test.d.ts +2 -0
- package/dist/charts/kinds/Bars.test.d.ts.map +1 -0
- 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 +13 -0
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.js +185 -92
- package/dist/charts/kinds/DualPanel.test.d.ts +2 -0
- package/dist/charts/kinds/DualPanel.test.d.ts.map +1 -0
- 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 +122 -235
- package/dist/charts/kinds/MultiLine.test.d.ts +2 -0
- package/dist/charts/kinds/MultiLine.test.d.ts.map +1 -0
- 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 +104 -184
- package/dist/charts/kinds/ZonedLine.test.d.ts +2 -0
- package/dist/charts/kinds/ZonedLine.test.d.ts.map +1 -0
- 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 +161 -0
- package/dist/charts/primitives/CartesianChart.d.ts.map +1 -0
- package/dist/charts/primitives/CartesianChart.js +359 -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 +15 -1
- package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
- package/dist/charts/primitives/ChartLegend.js +25 -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 +54 -0
- package/dist/charts/primitives/XZoneRects.d.ts.map +1 -0
- package/dist/charts/primitives/XZoneRects.js +65 -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 +28 -3
- package/dist/charts/series.d.ts.map +1 -1
- package/dist/charts/series.js +5 -2
- 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/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 +35 -14
- package/src/charts/kinds/Bars.test.tsx +98 -0
- package/src/charts/kinds/Bars.tsx +350 -467
- package/src/charts/kinds/Donut.tsx +31 -23
- package/src/charts/kinds/DualPanel.test.tsx +131 -0
- package/src/charts/kinds/DualPanel.tsx +301 -135
- package/src/charts/kinds/Heatmap.tsx +72 -47
- package/src/charts/kinds/MultiLine.test.tsx +37 -0
- package/src/charts/kinds/MultiLine.tsx +171 -290
- package/src/charts/kinds/StackedArea.tsx +116 -175
- package/src/charts/kinds/ZonedLine.test.tsx +37 -0
- package/src/charts/kinds/ZonedLine.tsx +149 -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.tsx +160 -0
- package/src/charts/primitives/CartesianChart.tsx +598 -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 +78 -0
- package/src/charts/primitives/ChartLegend.tsx +52 -2
- package/src/charts/primitives/ChartTooltip.tsx +67 -37
- package/src/charts/primitives/HoverOverlay.tsx +39 -3
- package/src/charts/primitives/XZoneRects.test.tsx +123 -0
- package/src/charts/primitives/XZoneRects.tsx +132 -0
- package/src/charts/series.test.ts +112 -0
- package/src/charts/series.ts +33 -5
- 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/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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Bars.test.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/Bars.test.tsx"],"names":[],"mappings":""}
|
|
@@ -52,10 +52,11 @@ export type DonutProps<K extends string = SeriesKey> = {
|
|
|
52
52
|
/**
|
|
53
53
|
* Radial slice-share chart with a punched-out center label. Composes `ChartFrame` for a
|
|
54
54
|
* categorical legend derived from the slices (one `SeriesStyle` per slice, `mark: 'bar'`) so the
|
|
55
|
-
* legend can never drift from what's plotted
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
55
|
+
* legend can never drift from what's plotted — legend-hidden slices drop out of the ring, the
|
|
56
|
+
* center total, and the tooltip's "Share" row together (`docs/CHARTS-SPEC.md` §5). No crosshair —
|
|
57
|
+
* meaningless for a radial layout. Hover stays local to the pie (dimming siblings on hover) rather
|
|
58
|
+
* than joining the shared cursor: a date-keyed cursor has no counterpart on a donut, and cross-kind
|
|
59
|
+
* category sync (donut ↔ bar, via a generalized key) is a distinct, deliberately deferred feature.
|
|
59
60
|
*/
|
|
60
61
|
declare function DonutInner<K extends string = SeriesKey>(props: DonutProps<K>): import("react").JSX.Element;
|
|
61
62
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Donut.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/Donut.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"Donut.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/Donut.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,OAAO,CAAA;AAKpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,IAAI;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,IAAI;IACrD,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;IACrB,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAC/B,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;;;;;;;GAQG;AACH,iBAAS,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,+BAoBrE;AA2JD;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAuB,OAAO,UAAU,CAAA"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Group } from "@visx/group";
|
|
3
3
|
import { Pie } from "@visx/shape";
|
|
4
|
-
import { memo, useMemo } from "react";
|
|
5
|
-
import {
|
|
4
|
+
import { memo, useMemo, useState } from "react";
|
|
5
|
+
import { ChartTooltipFloat, TooltipBody, TooltipRow } from "../primitives/ChartTooltip.js";
|
|
6
6
|
import { ChartFrame } from "../primitives/ChartFrame.js";
|
|
7
|
-
import { useChartTooltip } from "../hooks/useChartTooltip.js";
|
|
8
7
|
import { VX } from "../../tokens/index.js";
|
|
9
8
|
function DonutInner(props) {
|
|
10
9
|
const { data, height, colorForKey, seriesLabel = (k) => k, ariaLabel, isPending } = props;
|
|
@@ -38,21 +37,25 @@ function DonutPlot(props) {
|
|
|
38
37
|
innerRatio = 0.6,
|
|
39
38
|
padAngle = 0.01
|
|
40
39
|
} = props;
|
|
41
|
-
const { width, height } = plot;
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
40
|
+
const { width, height, hidden } = plot;
|
|
41
|
+
const [tip, setTip] = useState(null);
|
|
42
|
+
const hoveredKey = tip?.key ?? null;
|
|
43
|
+
const visibleData = useMemo(() => data.filter((d) => !hidden.has(d.key)), [data, hidden]);
|
|
45
44
|
const radius = Math.min(width, height) / 2 - 4;
|
|
46
45
|
const innerRadius = radius * innerRatio;
|
|
47
46
|
const centerX = width / 2;
|
|
48
47
|
const centerY = height / 2;
|
|
49
|
-
const total = useMemo(() =>
|
|
48
|
+
const total = useMemo(() => visibleData.reduce((sum, d) => sum + d.value, 0), [visibleData]);
|
|
49
|
+
const show = (d, event) => {
|
|
50
|
+
setTip({ key: d.key, value: d.value, anchor: { x: event.clientX, y: event.clientY } });
|
|
51
|
+
};
|
|
52
|
+
const hide = () => setTip(null);
|
|
50
53
|
return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
51
54
|
/* @__PURE__ */ jsx("svg", { width, height, children: /* @__PURE__ */ jsxs(Group, { left: centerX, top: centerY, children: [
|
|
52
55
|
/* @__PURE__ */ jsx(
|
|
53
56
|
Pie,
|
|
54
57
|
{
|
|
55
|
-
data,
|
|
58
|
+
data: visibleData,
|
|
56
59
|
pieValue: (d) => d.value,
|
|
57
60
|
pieSortValues: () => 0,
|
|
58
61
|
outerRadius: radius,
|
|
@@ -135,13 +138,13 @@ function DonutPlot(props) {
|
|
|
135
138
|
children: centerContent
|
|
136
139
|
}
|
|
137
140
|
),
|
|
138
|
-
/* @__PURE__ */ jsx(
|
|
141
|
+
tip !== null && /* @__PURE__ */ jsx(ChartTooltipFloat, { anchor: tip.anchor, children: /* @__PURE__ */ jsxs(TooltipBody, { children: [
|
|
139
142
|
/* @__PURE__ */ jsx(
|
|
140
143
|
TooltipRow,
|
|
141
144
|
{
|
|
142
|
-
color: colorForKey(tip.
|
|
143
|
-
label: seriesLabel(tip.
|
|
144
|
-
value: formatValue(tip.
|
|
145
|
+
color: colorForKey(tip.key),
|
|
146
|
+
label: seriesLabel(tip.key),
|
|
147
|
+
value: formatValue(tip.value),
|
|
145
148
|
shape: "bar"
|
|
146
149
|
}
|
|
147
150
|
),
|
|
@@ -150,7 +153,7 @@ function DonutPlot(props) {
|
|
|
150
153
|
{
|
|
151
154
|
color: VX.grid,
|
|
152
155
|
label: "Share",
|
|
153
|
-
value: `${total > 0 ? Math.round(tip.
|
|
156
|
+
value: `${total > 0 ? Math.round(tip.value / total * 100) : 0}%`,
|
|
154
157
|
shape: "bar"
|
|
155
158
|
}
|
|
156
159
|
)
|
|
@@ -33,7 +33,20 @@ export type DualPanelProps<T> = {
|
|
|
33
33
|
/** Top pane share of the inner plot height. Default 0.62. */
|
|
34
34
|
topFraction?: number;
|
|
35
35
|
formatTop: (v: number) => string;
|
|
36
|
+
/** Drives the bottom-pane TICKS. Also the tooltip-row fallback when `formatBar` is omitted. */
|
|
36
37
|
formatBottom: (v: number) => string;
|
|
38
|
+
/** Per-row tooltip formatter for the bottom-pane bar — overrides `formatBottom` for the tooltip
|
|
39
|
+
* row only (ticks keep reading `formatBottom`). Receives the hovered datum alongside the value,
|
|
40
|
+
* so a row can add a unit/decimal `formatBottom` can't (e.g. a velocity reading). */
|
|
41
|
+
formatBar?: (v: number, d: T) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Bottom-pane y-domain. Default `'auto'`: a symmetric `[-maxAbs, maxAbs]` computed from the
|
|
44
|
+
* data, `nice`d. A fixed tuple pins the domain instead (and is used verbatim, un-`nice`d).
|
|
45
|
+
*/
|
|
46
|
+
bottomYDomain?: [number, number] | 'auto';
|
|
47
|
+
/** When `bottomYDomain` is `'auto'`: floors the symmetric max-abs so a plateau doesn't amplify
|
|
48
|
+
* to fill the whole pane (mirrors `AxisConfig.autoMaxFloor`). Ignored with a fixed tuple. */
|
|
49
|
+
bottomMaxAbsFloor?: number;
|
|
37
50
|
/** Tooltip badge — appears at the right of the tooltip header. */
|
|
38
51
|
tooltipLabel?: (d: T) => {
|
|
39
52
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DualPanel.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/DualPanel.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"DualPanel.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/DualPanel.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAIvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAe,MAAM,WAAW,CAAA;AAK5E,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACtB;8DAC0D;IAC1D,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACxB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAA;IACtC,2EAA2E;IAC3E,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACxD,wGAAwG;IACxG,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAClE,oDAAoD;IACpD,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;IACrB,8DAA8D;IAC9D,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAChC,+FAA+F;IAC/F,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IACnC;;yFAEqF;IACrF,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACvC;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAA;IACzC;iGAC6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,kEAAkE;IAClE,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC/D;4CACwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;IAClC,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAID;;;;;;;;;;;GAWG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,+BAmClD;AAsdD;;;GAGG;AACH,eAAO,MAAM,SAAS,EAA2B,OAAO,cAAc,CAAA"}
|
|
@@ -8,19 +8,20 @@ import { Threshold } from "@visx/threshold";
|
|
|
8
8
|
import { memo, useMemo } from "react";
|
|
9
9
|
import { AxisBottomDate, AxisLeftNumeric } from "../primitives/Axes.js";
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
ChartTooltipFloat,
|
|
12
12
|
TooltipBody,
|
|
13
13
|
TooltipHeader,
|
|
14
|
-
TooltipRow
|
|
15
|
-
useTooltipStyles
|
|
14
|
+
TooltipRow
|
|
16
15
|
} from "../primitives/ChartTooltip.js";
|
|
17
16
|
import { ChartFrame, resolveLegend } from "../primitives/ChartFrame.js";
|
|
18
17
|
import { Crosshair, SeriesDot } from "../primitives/Crosshair.js";
|
|
19
18
|
import { HoverOverlay } from "../primitives/HoverOverlay.js";
|
|
20
19
|
import { ZoneRects } from "../primitives/ZoneRects.js";
|
|
21
|
-
import {
|
|
20
|
+
import { useChartCursor } from "../hooks/useChartCursor.js";
|
|
21
|
+
import { autoMargin, probeAxisLabels } from "../layout/auto-margin.js";
|
|
22
22
|
import { deriveTooltipRows, LINE_OVERLAY_STROKE_WIDTH } from "../series.js";
|
|
23
23
|
import { VX } from "../../tokens/index.js";
|
|
24
|
+
import { fmtAxisDate } from "../utils/format.js";
|
|
24
25
|
import { smartTicks } from "../utils/ticks.js";
|
|
25
26
|
const PANE_GAP = 12;
|
|
26
27
|
function DualPanelInner(props) {
|
|
@@ -66,27 +67,21 @@ function DualPanelPlot(props) {
|
|
|
66
67
|
topFraction = 0.62,
|
|
67
68
|
formatTop,
|
|
68
69
|
formatBottom,
|
|
70
|
+
formatBar,
|
|
71
|
+
bottomYDomain = "auto",
|
|
72
|
+
bottomMaxAbsFloor,
|
|
69
73
|
tooltipLabel,
|
|
70
74
|
plot
|
|
71
75
|
} = props;
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const innerH = topH + PANE_GAP + bottomH;
|
|
79
|
-
const xScale = useMemo(
|
|
80
|
-
() => scalePoint({ domain: data.map(getX), range: [0, xMax], padding: 0.3 }),
|
|
81
|
-
[data, xMax, getX]
|
|
82
|
-
);
|
|
83
|
-
const topYScale = useMemo(() => {
|
|
84
|
-
if (topYDomain !== "auto") {
|
|
85
|
-
return scaleLinear({ domain: topYDomain, range: [topH, 0] });
|
|
86
|
-
}
|
|
76
|
+
const { hidden } = plot;
|
|
77
|
+
const visibleSeries = useMemo(() => series.filter((s) => !hidden.has(s.key)), [series, hidden]);
|
|
78
|
+
const barVisible = !hidden.has("__divergence");
|
|
79
|
+
const useNiceTop = topYDomain === "auto";
|
|
80
|
+
const topDomain = useMemo(() => {
|
|
81
|
+
if (topYDomain !== "auto") return topYDomain;
|
|
87
82
|
let lo = Infinity;
|
|
88
83
|
let hi = -Infinity;
|
|
89
|
-
for (const s of
|
|
84
|
+
for (const s of visibleSeries) {
|
|
90
85
|
for (const d of data) {
|
|
91
86
|
const v = s.getValue(d);
|
|
92
87
|
if (v === null || v === void 0 || Number.isNaN(v)) continue;
|
|
@@ -99,43 +94,112 @@ function DualPanelPlot(props) {
|
|
|
99
94
|
hi = 1;
|
|
100
95
|
}
|
|
101
96
|
const span = hi - lo || Math.abs(hi) || 1;
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
97
|
+
return [lo - span * 0.08, hi + span * 0.08];
|
|
98
|
+
}, [data, visibleSeries, topYDomain]);
|
|
99
|
+
const topLabels = useMemo(
|
|
100
|
+
() => probeAxisLabels({ domain: topDomain, ticks: 4, format: formatTop, nice: useNiceTop }).labels,
|
|
101
|
+
[topDomain, useNiceTop, formatTop]
|
|
102
|
+
);
|
|
103
|
+
const useNiceBottom = bottomYDomain === "auto";
|
|
104
|
+
const maxAbs = useMemo(() => {
|
|
105
|
+
if (bottomYDomain !== "auto") return 0;
|
|
106
|
+
let m = 0;
|
|
110
107
|
for (const d of data) {
|
|
111
108
|
const v = getBar(d);
|
|
112
109
|
if (v === null || v === void 0 || Number.isNaN(v)) continue;
|
|
113
110
|
const a = Math.abs(v);
|
|
114
|
-
if (a >
|
|
111
|
+
if (a > m) m = a;
|
|
115
112
|
}
|
|
116
|
-
|
|
117
|
-
return
|
|
118
|
-
|
|
113
|
+
const floored = bottomMaxAbsFloor !== void 0 ? Math.max(m, bottomMaxAbsFloor) : m;
|
|
114
|
+
return floored === 0 ? 1 : floored;
|
|
115
|
+
}, [data, getBar, bottomYDomain, bottomMaxAbsFloor]);
|
|
116
|
+
const bottomDomain = useMemo(
|
|
117
|
+
() => bottomYDomain === "auto" ? [-maxAbs, maxAbs] : bottomYDomain,
|
|
118
|
+
[bottomYDomain, maxAbs]
|
|
119
|
+
);
|
|
120
|
+
const bottomLabels = useMemo(
|
|
121
|
+
() => probeAxisLabels({
|
|
122
|
+
domain: bottomDomain,
|
|
123
|
+
ticks: 3,
|
|
124
|
+
format: formatBottom,
|
|
125
|
+
nice: useNiceBottom
|
|
126
|
+
}).labels,
|
|
127
|
+
[bottomDomain, formatBottom, useNiceBottom]
|
|
128
|
+
);
|
|
129
|
+
const xLabelsAll = useMemo(() => data.map((d) => fmtAxisDate(getX(d))), [data, getX]);
|
|
130
|
+
const margin = useMemo(
|
|
131
|
+
() => autoMargin({ left: [...topLabels, ...bottomLabels], bottom: xLabelsAll }),
|
|
132
|
+
[topLabels, bottomLabels, xLabelsAll]
|
|
133
|
+
);
|
|
134
|
+
const xMax = Math.max(plot.width - margin.left - margin.right, 0);
|
|
135
|
+
const plotH = plot.height - margin.top - margin.bottom - PANE_GAP;
|
|
136
|
+
const topH = Math.max(Math.round(plotH * topFraction), 1);
|
|
137
|
+
const bottomH = Math.max(plotH - topH, 1);
|
|
138
|
+
const bottomTop = topH + PANE_GAP;
|
|
139
|
+
const innerH = topH + PANE_GAP + bottomH;
|
|
140
|
+
const xScale = useMemo(
|
|
141
|
+
() => scalePoint({ domain: data.map(getX), range: [0, xMax], padding: 0.3 }),
|
|
142
|
+
[data, xMax, getX]
|
|
143
|
+
);
|
|
144
|
+
const topYScale = useMemo(
|
|
145
|
+
() => scaleLinear({
|
|
146
|
+
domain: topDomain,
|
|
147
|
+
range: [topH, 0],
|
|
148
|
+
...useNiceTop && { nice: true }
|
|
149
|
+
}),
|
|
150
|
+
[topDomain, useNiceTop, topH]
|
|
151
|
+
);
|
|
152
|
+
const bottomYScale = useMemo(
|
|
153
|
+
() => scaleLinear({
|
|
154
|
+
domain: bottomDomain,
|
|
119
155
|
range: [bottomH, 0],
|
|
120
|
-
nice: true
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
const tooltipStyles = useTooltipStyles();
|
|
124
|
-
const { tip, tooltipRef, syncedPoint, isDirectHover, handleMouse, handleLeave } = useHoverSync(
|
|
125
|
-
{
|
|
126
|
-
data,
|
|
127
|
-
chartId,
|
|
128
|
-
getKey: getX,
|
|
129
|
-
xScale,
|
|
130
|
-
marginLeft: MARGIN.left
|
|
131
|
-
}
|
|
156
|
+
...useNiceBottom && { nice: true }
|
|
157
|
+
}),
|
|
158
|
+
[bottomDomain, bottomH, useNiceBottom]
|
|
132
159
|
);
|
|
160
|
+
const cursor = useChartCursor({
|
|
161
|
+
data,
|
|
162
|
+
chartId,
|
|
163
|
+
getKey: getX,
|
|
164
|
+
xScale,
|
|
165
|
+
marginLeft: margin.left
|
|
166
|
+
});
|
|
133
167
|
const tickValues = useMemo(() => smartTicks(data.map(getX), xMax), [data, xMax, getX]);
|
|
134
168
|
const barWidth = data.length > 0 ? Math.max(xMax / data.length * 0.6, 2) : 2;
|
|
169
|
+
const histogramBars = useMemo(() => {
|
|
170
|
+
if (!barVisible) return [];
|
|
171
|
+
const y0 = bottomYScale(0);
|
|
172
|
+
const bars = [];
|
|
173
|
+
for (const d of data) {
|
|
174
|
+
const v = getBar(d);
|
|
175
|
+
if (v === null || v === void 0 || Number.isNaN(v)) continue;
|
|
176
|
+
const cx = xScale(getX(d)) ?? 0;
|
|
177
|
+
const yVal = bottomYScale(v);
|
|
178
|
+
bars.push({
|
|
179
|
+
key: `bar-${getX(d)}`,
|
|
180
|
+
x: cx - barWidth / 2,
|
|
181
|
+
y: Math.min(y0, yVal),
|
|
182
|
+
width: barWidth,
|
|
183
|
+
height: Math.max(Math.abs(yVal - y0), 1),
|
|
184
|
+
fill: v >= 0 ? barColorPositive : barColorNegative
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return bars;
|
|
188
|
+
}, [
|
|
189
|
+
barVisible,
|
|
190
|
+
data,
|
|
191
|
+
getBar,
|
|
192
|
+
getX,
|
|
193
|
+
xScale,
|
|
194
|
+
bottomYScale,
|
|
195
|
+
barWidth,
|
|
196
|
+
barColorPositive,
|
|
197
|
+
barColorNegative
|
|
198
|
+
]);
|
|
135
199
|
const fillPts = useMemo(() => {
|
|
136
200
|
if (!fillBetween) return [];
|
|
137
|
-
const fromLine =
|
|
138
|
-
const toLine =
|
|
201
|
+
const fromLine = visibleSeries.find((s) => s.key === fillBetween.from);
|
|
202
|
+
const toLine = visibleSeries.find((s) => s.key === fillBetween.to);
|
|
139
203
|
if (!fromLine || !toLine) return [];
|
|
140
204
|
const out = [];
|
|
141
205
|
for (const d of data) {
|
|
@@ -146,10 +210,10 @@ function DualPanelPlot(props) {
|
|
|
146
210
|
out.push({ __d: d, __from: f, __to: t });
|
|
147
211
|
}
|
|
148
212
|
return out;
|
|
149
|
-
}, [data, fillBetween,
|
|
213
|
+
}, [data, fillBetween, visibleSeries]);
|
|
150
214
|
const lineValid = useMemo(() => {
|
|
151
215
|
const out = /* @__PURE__ */ new Map();
|
|
152
|
-
for (const s of
|
|
216
|
+
for (const s of visibleSeries) {
|
|
153
217
|
const pts = [];
|
|
154
218
|
for (const d of data) {
|
|
155
219
|
const v = s.getValue(d);
|
|
@@ -158,12 +222,43 @@ function DualPanelPlot(props) {
|
|
|
158
222
|
out.set(s.key, pts);
|
|
159
223
|
}
|
|
160
224
|
return out;
|
|
161
|
-
}, [data,
|
|
162
|
-
const
|
|
163
|
-
|
|
225
|
+
}, [data, visibleSeries]);
|
|
226
|
+
const markerNodes = useMemo(
|
|
227
|
+
() => visibleSeries.flatMap((s) => {
|
|
228
|
+
const getMarker = s.getMarker;
|
|
229
|
+
if (!getMarker) return [];
|
|
230
|
+
const pts = lineValid.get(s.key) ?? [];
|
|
231
|
+
const markers = [];
|
|
232
|
+
for (const p of pts) {
|
|
233
|
+
const m = getMarker(p.__d);
|
|
234
|
+
if (m === null) continue;
|
|
235
|
+
const cx = xScale(getX(p.__d)) ?? 0;
|
|
236
|
+
const cy = topYScale(p.__y);
|
|
237
|
+
markers.push(
|
|
238
|
+
/* @__PURE__ */ jsx(
|
|
239
|
+
"circle",
|
|
240
|
+
{
|
|
241
|
+
cx,
|
|
242
|
+
cy,
|
|
243
|
+
r: m.r ?? VX.dotR,
|
|
244
|
+
fill: m.color ?? s.color,
|
|
245
|
+
stroke: VX.dotStroke,
|
|
246
|
+
strokeWidth: 2
|
|
247
|
+
},
|
|
248
|
+
`mk-${s.key}-${getX(p.__d)}`
|
|
249
|
+
)
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return markers;
|
|
253
|
+
}),
|
|
254
|
+
[visibleSeries, lineValid, xScale, topYScale, getX]
|
|
255
|
+
);
|
|
256
|
+
const point = cursor.point;
|
|
257
|
+
const sx = point !== null ? xScale(getX(point)) ?? 0 : 0;
|
|
258
|
+
const syncedBar = point !== null ? getBar(point) : null;
|
|
164
259
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
165
260
|
/* @__PURE__ */ jsxs("svg", { width: plot.width, height: plot.height, children: [
|
|
166
|
-
/* @__PURE__ */ jsxs(Group, { left:
|
|
261
|
+
/* @__PURE__ */ jsxs(Group, { left: margin.left, top: margin.top, children: [
|
|
167
262
|
/* @__PURE__ */ jsx(GridRows, { scale: topYScale, width: xMax, stroke: VX.grid, numTicks: 4 }),
|
|
168
263
|
/* @__PURE__ */ jsx(ZoneRects, { zones: topZones, width: xMax, leftScale: topYScale }),
|
|
169
264
|
fillBetween && fillPts.length > 0 && /* @__PURE__ */ jsx(
|
|
@@ -193,7 +288,7 @@ function DualPanelPlot(props) {
|
|
|
193
288
|
},
|
|
194
289
|
`top-ref-${i}`
|
|
195
290
|
)),
|
|
196
|
-
|
|
291
|
+
visibleSeries.map((s) => {
|
|
197
292
|
const valid = lineValid.get(s.key) ?? [];
|
|
198
293
|
if (valid.length === 0) return null;
|
|
199
294
|
return /* @__PURE__ */ jsx(
|
|
@@ -205,13 +300,15 @@ function DualPanelPlot(props) {
|
|
|
205
300
|
stroke: s.color,
|
|
206
301
|
strokeWidth: s.strokeWidth ?? VX.lineWidth,
|
|
207
302
|
strokeDasharray: s.dash === "dashed" ? VX.dashArray : void 0,
|
|
303
|
+
strokeOpacity: s.strokeOpacity ?? 1,
|
|
208
304
|
curve: curveMonotoneX
|
|
209
305
|
},
|
|
210
306
|
`top-line-${s.key}`
|
|
211
307
|
);
|
|
212
308
|
}),
|
|
213
|
-
|
|
214
|
-
|
|
309
|
+
markerNodes,
|
|
310
|
+
point !== null && /* @__PURE__ */ jsx(Fragment, { children: visibleSeries.map((s) => {
|
|
311
|
+
const v = s.getValue(point);
|
|
215
312
|
if (v === null || v === void 0 || Number.isNaN(v)) return null;
|
|
216
313
|
return /* @__PURE__ */ jsx(SeriesDot, { cx: sx, cy: topYScale(v), color: s.color }, `top-dot-${s.key}`);
|
|
217
314
|
}) }),
|
|
@@ -221,12 +318,14 @@ function DualPanelPlot(props) {
|
|
|
221
318
|
{
|
|
222
319
|
width: xMax,
|
|
223
320
|
height: topH + PANE_GAP,
|
|
224
|
-
onMove:
|
|
225
|
-
onLeave:
|
|
321
|
+
onMove: cursor.onPointerMove,
|
|
322
|
+
onLeave: cursor.onPointerLeave,
|
|
323
|
+
onKeyDown: cursor.onKeyDown,
|
|
324
|
+
onBlur: cursor.onBlur
|
|
226
325
|
}
|
|
227
326
|
)
|
|
228
327
|
] }),
|
|
229
|
-
/* @__PURE__ */ jsxs(Group, { left:
|
|
328
|
+
/* @__PURE__ */ jsxs(Group, { left: margin.left, top: margin.top + bottomTop, children: [
|
|
230
329
|
/* @__PURE__ */ jsx(
|
|
231
330
|
"line",
|
|
232
331
|
{
|
|
@@ -238,61 +337,54 @@ function DualPanelPlot(props) {
|
|
|
238
337
|
strokeWidth: 1
|
|
239
338
|
}
|
|
240
339
|
),
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
fillOpacity: 0.7,
|
|
256
|
-
rx: 1.4
|
|
257
|
-
},
|
|
258
|
-
`bar-${getX(d)}`
|
|
259
|
-
);
|
|
260
|
-
}),
|
|
261
|
-
syncedPoint && /* @__PURE__ */ jsx(Fragment, { children: syncedBar !== null && syncedBar !== void 0 && !Number.isNaN(syncedBar) && /* @__PURE__ */ jsx(
|
|
340
|
+
histogramBars.map((b) => /* @__PURE__ */ jsx(
|
|
341
|
+
Bar,
|
|
342
|
+
{
|
|
343
|
+
x: b.x,
|
|
344
|
+
y: b.y,
|
|
345
|
+
width: b.width,
|
|
346
|
+
height: b.height,
|
|
347
|
+
fill: b.fill,
|
|
348
|
+
fillOpacity: 0.7,
|
|
349
|
+
rx: 1.4
|
|
350
|
+
},
|
|
351
|
+
b.key
|
|
352
|
+
)),
|
|
353
|
+
barVisible && point !== null && syncedBar !== null && syncedBar !== void 0 && !Number.isNaN(syncedBar) && /* @__PURE__ */ jsx(
|
|
262
354
|
SeriesDot,
|
|
263
355
|
{
|
|
264
356
|
cx: sx,
|
|
265
357
|
cy: bottomYScale(syncedBar),
|
|
266
358
|
color: syncedBar >= 0 ? barColorPositive : barColorNegative
|
|
267
359
|
}
|
|
268
|
-
)
|
|
360
|
+
),
|
|
269
361
|
/* @__PURE__ */ jsx(AxisLeftNumeric, { scale: bottomYScale, numTicks: 3, tickFormat: formatBottom }),
|
|
270
362
|
/* @__PURE__ */ jsx(AxisBottomDate, { top: bottomH, scale: xScale, tickValues }),
|
|
271
363
|
/* @__PURE__ */ jsx(
|
|
272
364
|
HoverOverlay,
|
|
273
365
|
{
|
|
274
366
|
width: xMax,
|
|
275
|
-
height: bottomH +
|
|
276
|
-
onMove:
|
|
277
|
-
onLeave:
|
|
367
|
+
height: bottomH + margin.bottom,
|
|
368
|
+
onMove: cursor.onPointerMove,
|
|
369
|
+
onLeave: cursor.onPointerLeave
|
|
278
370
|
}
|
|
279
371
|
)
|
|
280
372
|
] }),
|
|
281
|
-
|
|
373
|
+
point !== null && /* @__PURE__ */ jsx(Group, { left: margin.left, top: margin.top, children: /* @__PURE__ */ jsx(Crosshair, { x: sx, top: 0, bottom: innerH }) })
|
|
282
374
|
] }),
|
|
283
|
-
|
|
375
|
+
cursor.isSource && point !== null && /* @__PURE__ */ jsxs(ChartTooltipFloat, { anchor: cursor.anchor, children: [
|
|
284
376
|
/* @__PURE__ */ jsx(
|
|
285
377
|
TooltipHeader,
|
|
286
378
|
{
|
|
287
|
-
date: getX(
|
|
379
|
+
date: getX(point),
|
|
288
380
|
...(() => {
|
|
289
|
-
const lbl = tooltipLabel?.(
|
|
381
|
+
const lbl = tooltipLabel?.(point) ?? null;
|
|
290
382
|
return lbl !== null ? { label: lbl.text, labelColor: lbl.color } : {};
|
|
291
383
|
})()
|
|
292
384
|
}
|
|
293
385
|
),
|
|
294
386
|
/* @__PURE__ */ jsxs(TooltipBody, { children: [
|
|
295
|
-
deriveTooltipRows(
|
|
387
|
+
deriveTooltipRows(visibleSeries, point, formatTop).map((row) => /* @__PURE__ */ jsx(
|
|
296
388
|
TooltipRow,
|
|
297
389
|
{
|
|
298
390
|
color: row.color,
|
|
@@ -304,21 +396,22 @@ function DualPanelPlot(props) {
|
|
|
304
396
|
},
|
|
305
397
|
row.key
|
|
306
398
|
)),
|
|
307
|
-
(() => {
|
|
308
|
-
const v = getBar(
|
|
399
|
+
barVisible && (() => {
|
|
400
|
+
const v = getBar(point);
|
|
309
401
|
if (v === null || v === void 0 || Number.isNaN(v)) return null;
|
|
402
|
+
const value = formatBar !== void 0 ? formatBar(v, point) : formatBottom(v);
|
|
310
403
|
return /* @__PURE__ */ jsx(
|
|
311
404
|
TooltipRow,
|
|
312
405
|
{
|
|
313
406
|
color: v >= 0 ? barColorPositive : barColorNegative,
|
|
314
407
|
label: barLabel,
|
|
315
|
-
value
|
|
408
|
+
value,
|
|
316
409
|
shape: "bar"
|
|
317
410
|
}
|
|
318
411
|
);
|
|
319
412
|
})()
|
|
320
413
|
] })
|
|
321
|
-
] })
|
|
414
|
+
] })
|
|
322
415
|
] });
|
|
323
416
|
}
|
|
324
417
|
const DualPanel = memo(DualPanelInner);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DualPanel.test.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/DualPanel.test.tsx"],"names":[],"mappings":""}
|
|
@@ -7,8 +7,12 @@ type HeatmapCell = {
|
|
|
7
7
|
};
|
|
8
8
|
export type HeatmapProps<T> = {
|
|
9
9
|
data: T[];
|
|
10
|
-
|
|
11
|
-
height
|
|
10
|
+
/** Fixed height in pixels. Used when neither `aspectRatio` nor `fill` is set. Default 240. */
|
|
11
|
+
height?: number;
|
|
12
|
+
/** height = Math.round(containerWidth / aspectRatio). Ignored when `fill` is set. */
|
|
13
|
+
aspectRatio?: number;
|
|
14
|
+
/** Fill the parent flex/grid cell's measured height instead of a fixed/derived one. */
|
|
15
|
+
fill?: boolean;
|
|
12
16
|
chartId: string;
|
|
13
17
|
/** Extracts the y-axis category (row) from a data point. */
|
|
14
18
|
getRow: (d: T) => string;
|
|
@@ -41,21 +45,21 @@ export type HeatmapProps<T> = {
|
|
|
41
45
|
min: string;
|
|
42
46
|
max: string;
|
|
43
47
|
};
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
* the legend strip and every cell/label/tooltip along with it. Unlike the other six kinds,
|
|
48
|
-
* `Heatmap` doesn't compose `ChartFrame` (it takes `width`/`height` directly rather than
|
|
49
|
-
* measuring), so this is handled locally instead of forwarded.
|
|
50
|
-
*/
|
|
48
|
+
/** Accessible text alternative, forwarded to `ChartFrame` as `aria-label` (+ `role="img"`). */
|
|
49
|
+
ariaLabel?: string;
|
|
50
|
+
/** Forwarded to `ChartFrame` — see `ChartPending`'s JSDoc for the three-state rationale. */
|
|
51
51
|
isPending?: boolean;
|
|
52
52
|
};
|
|
53
53
|
/**
|
|
54
54
|
* Category × category intensity grid. Each cell is a rounded rect filled with the base
|
|
55
55
|
* color at an opacity derived from its value; empty cells stay a faint neutral track.
|
|
56
56
|
* Generalizes argo's day-of-week × hour-of-day heatmap. Categorical axes are rendered as
|
|
57
|
-
* plain themed `<text>` (cells are not date-categorical, so no
|
|
58
|
-
*
|
|
57
|
+
* plain themed `<text>` (cells are not date-categorical, so there's no shared cursor here) —
|
|
58
|
+
* per-cell hover drives the local tooltip directly.
|
|
59
|
+
*
|
|
60
|
+
* Composes `ChartFrame` purely for measuring (`height`/`aspectRatio`/`fill`, the same three
|
|
61
|
+
* sizing modes every other kind exposes) — `legend={false}` and an empty `series` opt out of
|
|
62
|
+
* `ChartFrame`'s own derived legend, since Heatmap already ships its own gradient strip.
|
|
59
63
|
*/
|
|
60
64
|
declare function HeatmapInner<T>(props: HeatmapProps<T>): import("react").JSX.Element;
|
|
61
65
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Heatmap.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/Heatmap.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"Heatmap.d.ts","sourceRoot":"","sources":["../../../src/charts/kinds/Heatmap.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,OAAO,CAAA;AAWpD,kFAAkF;AAClF,KAAK,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAK9D,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,4DAA4D;IAC5D,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,+DAA+D;IAC/D,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IACxB,yCAAyC;IACzC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;IAC1B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAClD,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uCAAuC;IACvC,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,iEAAiE;IACjE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,SAAS,CAAA;IAChD,2EAA2E;IAC3E,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IACrC,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAgCD;;;;;;;;;;GAUG;AACH,iBAAS,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,+BAiB9C;AA6KD;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAyB,OAAO,YAAY,CAAA"}
|