basalt-ui 2.3.0 → 2.5.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/CHANGELOG.md +34 -0
- package/MIGRATING.md +79 -12
- package/agent/rules/basalt-state.md +1 -1
- package/configs/lefthook.yml +4 -1
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +4 -1
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/run-records.d.ts +12 -3
- package/dist/agent/run-records.d.ts.map +1 -1
- package/dist/agent/run-records.js +16 -3
- package/dist/agent/transport.d.ts +10 -3
- package/dist/agent/transport.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.js +23 -7
- package/dist/charts/CartesianChart.d.ts.map +1 -1
- package/dist/charts/CartesianChart.js +6 -2
- package/dist/charts/DualPanel.d.ts +5 -1
- package/dist/charts/DualPanel.d.ts.map +1 -1
- package/dist/charts/DualPanel.js +46 -19
- package/dist/charts/Heatmap.js +2 -2
- package/dist/charts/Lines.js +2 -2
- package/dist/charts/MirroredBars.d.ts.map +1 -1
- package/dist/charts/MirroredBars.js +14 -11
- package/dist/charts/compile.d.ts +19 -2
- package/dist/charts/compile.d.ts.map +1 -1
- package/dist/charts/compile.js +192 -42
- package/dist/charts/marks.d.ts +8 -0
- package/dist/charts/marks.d.ts.map +1 -1
- package/dist/charts/marks.js +22 -1
- package/dist/charts/panel.d.ts +6 -0
- package/dist/charts/panel.d.ts.map +1 -1
- package/dist/charts/panel.js +12 -3
- package/dist/charts/types.d.ts +39 -1
- package/dist/charts/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +8 -2
- package/dist/state/fields.d.ts +14 -3
- package/dist/state/fields.d.ts.map +1 -1
- package/dist/state/fields.js +41 -9
- package/dist/telemetry.d.ts +58 -4
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +13 -5
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/agent/ai-sdk-transport.ts +5 -2
- package/src/agent/index.ts +1 -1
- package/src/agent/run-records.ts +27 -3
- package/src/agent/transport.ts +11 -5
- package/src/agent/use-agent-thread-runs.ts +35 -8
- package/src/charts/CartesianChart.tsx +7 -2
- package/src/charts/DualPanel.tsx +50 -19
- package/src/charts/Heatmap.tsx +2 -2
- package/src/charts/Lines.tsx +2 -2
- package/src/charts/MirroredBars.tsx +13 -10
- package/src/charts/compile.ts +261 -46
- package/src/charts/marks.ts +35 -1
- package/src/charts/panel.tsx +18 -3
- package/src/charts/types.ts +37 -1
- package/src/index.ts +1 -1
- package/src/provider/index.tsx +8 -2
- package/src/state/fields.ts +79 -21
- package/src/telemetry.ts +70 -7
package/dist/charts/DualPanel.js
CHANGED
|
@@ -7,9 +7,9 @@ import { scaleUtc } from "d3-scale";
|
|
|
7
7
|
import { useCallback, useMemo } from "react";
|
|
8
8
|
import { VX, alpha } from "../tokens/index.js";
|
|
9
9
|
import { resolveContainerClass } from "../tokens/size-classes.js";
|
|
10
|
-
import { defaultFormatX, defaultNumberFormat, visibleSeries } from "./compile.js";
|
|
10
|
+
import { defaultFormatX, defaultNumberFormat, engineRow, seriesRow, visibleSeries } from "./compile.js";
|
|
11
11
|
import { barMark, emphasis, lineMark, markersOf, thinFill } from "./marks.js";
|
|
12
|
-
import { PanelRung, paneX, paneY, rowsOf } from "./panel.js";
|
|
12
|
+
import { PanelRung, chartHeightOf, paneX, paneY, rowsOf } from "./panel.js";
|
|
13
13
|
import { xScaleFor } from "./scales.js";
|
|
14
14
|
import { rowX } from "./types.js";
|
|
15
15
|
const BAR_KEY = "__bar";
|
|
@@ -60,6 +60,8 @@ function DualPanel(props) {
|
|
|
60
60
|
);
|
|
61
61
|
const all = useMemo(() => [...lines, barSeries], [lines, barSeries]);
|
|
62
62
|
const topFormat = top?.format ?? defaultNumberFormat;
|
|
63
|
+
const topTooltipFormat = top?.tooltipFormat ?? topFormat;
|
|
64
|
+
const barTooltipFormat = bar.tooltipFormat ?? bar.format;
|
|
63
65
|
const plan = useCallback(
|
|
64
66
|
({ hidden, highlighted }) => {
|
|
65
67
|
const model = xScaleFor(data.map(x), false);
|
|
@@ -145,12 +147,20 @@ function DualPanel(props) {
|
|
|
145
147
|
],
|
|
146
148
|
scales: {
|
|
147
149
|
x: { scale: xScale(), axis: false },
|
|
148
|
-
y: paneY({
|
|
150
|
+
y: paneY({
|
|
151
|
+
scale: topY,
|
|
152
|
+
domain: topDomain,
|
|
153
|
+
format: topFormat,
|
|
154
|
+
ticks: TOP_TICKS,
|
|
155
|
+
cls,
|
|
156
|
+
height: chartHeightOf(h, topFraction, PANE_GAP)
|
|
157
|
+
})
|
|
149
158
|
}
|
|
150
159
|
};
|
|
151
160
|
};
|
|
152
|
-
const barPane = ({ width }) => {
|
|
161
|
+
const barPane = ({ width, height: h }) => {
|
|
153
162
|
const cls = resolveContainerClass(width);
|
|
163
|
+
const whole = chartHeightOf(h, 1 - topFraction, PANE_GAP);
|
|
154
164
|
const barRows = barOn ? rowsOf(data, x, barSeries) : [];
|
|
155
165
|
const dim = emphasis(highlighted, { key: BAR_KEY });
|
|
156
166
|
return {
|
|
@@ -164,13 +174,14 @@ function DualPanel(props) {
|
|
|
164
174
|
})
|
|
165
175
|
],
|
|
166
176
|
scales: {
|
|
167
|
-
x: paneX({ scale: xScale(), model, format, cls }),
|
|
177
|
+
x: paneX({ scale: xScale(), model, format, cls, height: whole }),
|
|
168
178
|
y: paneY({
|
|
169
179
|
scale: barScale,
|
|
170
180
|
domain: barDomain,
|
|
171
181
|
format: bar.format,
|
|
172
182
|
ticks: BAR_TICKS,
|
|
173
|
-
cls
|
|
183
|
+
cls,
|
|
184
|
+
height: whole
|
|
174
185
|
})
|
|
175
186
|
}
|
|
176
187
|
};
|
|
@@ -186,26 +197,42 @@ function DualPanel(props) {
|
|
|
186
197
|
for (const s of visible) {
|
|
187
198
|
const v2 = s.getValue(d);
|
|
188
199
|
if (s.tooltip === false || v2 === null || !Number.isFinite(v2)) continue;
|
|
189
|
-
out.push(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
200
|
+
out.push(
|
|
201
|
+
seriesRow(
|
|
202
|
+
s,
|
|
203
|
+
s.formatValue ? s.formatValue(v2, d) : topTooltipFormat(v2),
|
|
204
|
+
highlighted === s.key
|
|
205
|
+
)
|
|
206
|
+
);
|
|
195
207
|
}
|
|
196
208
|
const v = barOn ? bar.getValue(d) : null;
|
|
197
209
|
if (v !== null && Number.isFinite(v))
|
|
198
|
-
out.push(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
210
|
+
out.push(
|
|
211
|
+
engineRow({
|
|
212
|
+
label: bar.label,
|
|
213
|
+
value: bar.formatValue ? bar.formatValue(v, d) : barTooltipFormat(v),
|
|
214
|
+
color: v >= 0 ? bar.positive : bar.negative,
|
|
215
|
+
active: highlighted === BAR_KEY
|
|
216
|
+
})
|
|
217
|
+
);
|
|
204
218
|
return out;
|
|
205
219
|
}
|
|
206
220
|
};
|
|
207
221
|
},
|
|
208
|
-
[
|
|
222
|
+
[
|
|
223
|
+
data,
|
|
224
|
+
x,
|
|
225
|
+
lines,
|
|
226
|
+
barSeries,
|
|
227
|
+
top,
|
|
228
|
+
fillBetween,
|
|
229
|
+
bar,
|
|
230
|
+
topFraction,
|
|
231
|
+
topFormat,
|
|
232
|
+
topTooltipFormat,
|
|
233
|
+
barTooltipFormat,
|
|
234
|
+
formatX
|
|
235
|
+
]
|
|
209
236
|
);
|
|
210
237
|
return /* @__PURE__ */ jsx(PanelRung, { ...rung, series: all, plan });
|
|
211
238
|
}
|
package/dist/charts/Heatmap.js
CHANGED
|
@@ -9,7 +9,7 @@ import { scaleQuantize } from "d3-scale";
|
|
|
9
9
|
import { useId, useMemo } from "react";
|
|
10
10
|
import { alpha, VX } from "../tokens/index.js";
|
|
11
11
|
import { resolveContainerClass } from "../tokens/size-classes.js";
|
|
12
|
-
import { strideTicks } from "./compile.js";
|
|
12
|
+
import { engineRow, strideTicks } from "./compile.js";
|
|
13
13
|
import { ChartEngine, idPrefixOf } from "./host.js";
|
|
14
14
|
import { useCoarsePointer } from "../common/use-media-query.js";
|
|
15
15
|
import { HEIGHT_MAX, HEIGHT_MIN } from "./box.js";
|
|
@@ -176,7 +176,7 @@ function Heatmap(props) {
|
|
|
176
176
|
...point.color && { color: point.color }
|
|
177
177
|
}
|
|
178
178
|
];
|
|
179
|
-
return { title: header(c), rows: [...value, ...extra] };
|
|
179
|
+
return { title: header(c), rows: [...value, ...extra].map(engineRow) };
|
|
180
180
|
}
|
|
181
181
|
} : false
|
|
182
182
|
};
|
package/dist/charts/Lines.js
CHANGED
|
@@ -8,7 +8,7 @@ import { VX } from "../tokens/index.js";
|
|
|
8
8
|
import { CartesianRung } from "./CartesianChart.js";
|
|
9
9
|
import { areaGradientId } from "./compile.js";
|
|
10
10
|
import { chartCurve } from "./curves.js";
|
|
11
|
-
import { lineMark, markersOf, yScaleOf } from "./marks.js";
|
|
11
|
+
import { drawnRows, lineMark, markersOf, yScaleOf } from "./marks.js";
|
|
12
12
|
import { rowX } from "./types.js";
|
|
13
13
|
const MAX_END_LABELS = 3;
|
|
14
14
|
const END_LABEL_MIN_GAP = 13;
|
|
@@ -80,7 +80,7 @@ function Lines(props) {
|
|
|
80
80
|
if (!s.area) continue;
|
|
81
81
|
out.push(
|
|
82
82
|
decorative(
|
|
83
|
-
areaY(plot
|
|
83
|
+
areaY(drawnRows(plot, s), {
|
|
84
84
|
id: `${s.key}-area`,
|
|
85
85
|
x: rowX,
|
|
86
86
|
y2: "y",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MirroredBars.d.ts","sourceRoot":"","sources":["../../src/charts/MirroredBars.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AASzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,EAAW,MAAM,SAAS,CAAA;AAEhF,4BAA4B;AAC5B,MAAM,MAAM,eAAe,GAAG;IAC5B;8EAC0E;IAC1E,GAAG,EAAE,MAAM,CAAA;IACX,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACjC,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,2DAA2D;IAC3D,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC9B,CAAA;AAED,oGAAoG;AACpG,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,IAAI,CACtC,WAAW,CAAC,CAAC,CAAC,EACd,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAChG,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CAChE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,EACvB,WAAW,GACX,MAAM,GACN,GAAG,GACH,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,aAAa,GACb,SAAS,GACT,WAAW,GACX,OAAO,CACV,GAAG;IACF,qEAAqE;IACrE,MAAM,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAA;IACxC,gCAAgC;IAChC,EAAE,EAAE,eAAe,CAAA;IACnB,gCAAgC;IAChC,IAAI,EAAE,eAAe,CAAA;IACrB,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;IAClD,6FAA6F;IAC7F,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;IAC9C;;;OAGG;IACH,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;KAAE,GAAG,SAAS,CAAA;IAC/E,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAA;CAC7E,CAAA;AAgDD,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACvD,KAAK,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7B,YAAY,
|
|
1
|
+
{"version":3,"file":"MirroredBars.d.ts","sourceRoot":"","sources":["../../src/charts/MirroredBars.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AASzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,EAAW,MAAM,SAAS,CAAA;AAEhF,4BAA4B;AAC5B,MAAM,MAAM,eAAe,GAAG;IAC5B;8EAC0E;IAC1E,GAAG,EAAE,MAAM,CAAA;IACX,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACjC,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,2DAA2D;IAC3D,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAC9B,CAAA;AAED,oGAAoG;AACpG,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,IAAI,CACtC,WAAW,CAAC,CAAC,CAAC,EACd,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAChG,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CAChE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,EACvB,WAAW,GACX,MAAM,GACN,GAAG,GACH,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,aAAa,GACb,SAAS,GACT,WAAW,GACX,OAAO,CACV,GAAG;IACF,qEAAqE;IACrE,MAAM,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAA;IACxC,gCAAgC;IAChC,EAAE,EAAE,eAAe,CAAA;IACnB,gCAAgC;IAChC,IAAI,EAAE,eAAe,CAAA;IACrB,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;IAClD,6FAA6F;IAC7F,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;IAC9C;;;OAGG;IACH,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;KAAE,GAAG,SAAS,CAAA;IAC/E,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAA;CAC7E,CAAA;AAgDD,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACvD,KAAK,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7B,YAAY,CA0Kd"}
|
|
@@ -6,9 +6,9 @@ import { scaleLinear } from "@tanstack/charts/scales/linear";
|
|
|
6
6
|
import { useCallback, useMemo } from "react";
|
|
7
7
|
import { VX, alpha } from "../tokens/index.js";
|
|
8
8
|
import { resolveContainerClass } from "../tokens/size-classes.js";
|
|
9
|
-
import { defaultFormatX, defaultNumberFormat, visibleSeries } from "./compile.js";
|
|
9
|
+
import { defaultFormatX, defaultNumberFormat, seriesRow, visibleSeries } from "./compile.js";
|
|
10
10
|
import { barMark, emphasis } from "./marks.js";
|
|
11
|
-
import { PanelRung, paneX, paneY, rowsOf } from "./panel.js";
|
|
11
|
+
import { PanelRung, chartHeightOf, paneX, paneY, rowsOf } from "./panel.js";
|
|
12
12
|
import { xScaleFor } from "./scales.js";
|
|
13
13
|
import { rowX } from "./types.js";
|
|
14
14
|
const DEFAULT_UP_FRACTION = 0.35;
|
|
@@ -69,8 +69,9 @@ function MirroredBars(props) {
|
|
|
69
69
|
const downMax = paneMax(down, downSeries, drawn, downOn);
|
|
70
70
|
const bandWidth = 2 * model.halfStep * BAND_FILL;
|
|
71
71
|
const bandScale = () => xScaleFor(drawn.map(x), true).scale;
|
|
72
|
-
const pane = (side, cfg, s, on, max) => ({ width: w }) => {
|
|
72
|
+
const pane = (side, cfg, s, on, max) => ({ width: w, height: h }) => {
|
|
73
73
|
const cls = resolveContainerClass(w);
|
|
74
|
+
const whole = chartHeightOf(h, side === "up" ? upFraction : 1 - upFraction, 0);
|
|
74
75
|
const domain = side === "up" ? [0, max] : [max, 0];
|
|
75
76
|
const rows = on ? rowsOf(drawn, x, s) : [];
|
|
76
77
|
const opacity = (d) => (getBarOpacity?.(d) ?? BAR_OPACITY) * emphasis(highlighted, s);
|
|
@@ -137,13 +138,14 @@ function MirroredBars(props) {
|
|
|
137
138
|
)
|
|
138
139
|
],
|
|
139
140
|
scales: {
|
|
140
|
-
x: side === "down" ? paneX({ scale: bandScale(), model, format, cls }) : { scale: bandScale(), axis: false },
|
|
141
|
+
x: side === "down" ? paneX({ scale: bandScale(), model, format, cls, height: whole }) : { scale: bandScale(), axis: false },
|
|
141
142
|
y: paneY({
|
|
142
143
|
scale: scaleLinear().domain(domain),
|
|
143
144
|
domain,
|
|
144
145
|
format: cfg.format,
|
|
145
146
|
ticks: cfg.ticks ?? DEFAULT_PANE_TICKS,
|
|
146
|
-
cls
|
|
147
|
+
cls,
|
|
148
|
+
height: whole
|
|
147
149
|
}),
|
|
148
150
|
zx: { channel: "x", scale: scaleLinear().domain([0, 1]), axis: false }
|
|
149
151
|
}
|
|
@@ -161,12 +163,13 @@ function MirroredBars(props) {
|
|
|
161
163
|
const v = s.getValue(d);
|
|
162
164
|
if (s.tooltip === false || v === null || !Number.isFinite(v)) continue;
|
|
163
165
|
const fallback = s.key === up.key ? up.format : s.key === down.key ? down.format : defaultNumberFormat;
|
|
164
|
-
out.push(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
out.push(
|
|
167
|
+
seriesRow(
|
|
168
|
+
s,
|
|
169
|
+
s.formatValue ? s.formatValue(v, d) : fallback(v),
|
|
170
|
+
highlighted === s.key
|
|
171
|
+
)
|
|
172
|
+
);
|
|
170
173
|
}
|
|
171
174
|
return out;
|
|
172
175
|
}
|
package/dist/charts/compile.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ChartGradient, ChartPositionScaleOptions, ChartValue, ResponsiveChartDefinition } from '@tanstack/charts/types/core';
|
|
1
|
+
import type { ChartGradient, ChartPositionScaleOptions, ChartTooltipRow as EngineTooltipRow, ChartValue, ResponsiveChartDefinition } from '@tanstack/charts/types/core';
|
|
2
2
|
import type { ContainerClass } from '../tokens/size-classes.js';
|
|
3
3
|
import type { XScaleModel } from './scales.js';
|
|
4
|
-
import type { AxisConfig, CartesianChartProps, ChartSeries, ChartX, ZoneSpec } from './types.js';
|
|
4
|
+
import type { AxisConfig, CartesianChartProps, ChartSeries, ChartTooltipRow, ChartX, RefLine, ZoneSpec } from './types.js';
|
|
5
5
|
/**
|
|
6
6
|
* The compiled definition. Annotated on purpose: TanStack's inferred definition type names internal
|
|
7
7
|
* modules (`dist/scene`, `cursor-host-contract`) and fails declaration emit (TS2883 / TS4058).
|
|
@@ -35,6 +35,19 @@ export declare function utcHeaderDate(d: Date): string;
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function dateTicks(domain: readonly [Date, Date], count: number, stepMs: number): Date[];
|
|
37
37
|
export declare function defaultFormatX(v: ChartValue): string;
|
|
38
|
+
/**
|
|
39
|
+
* A tooltip swatch is the engine's `background` shorthand, so a dashed one is a gradient: a 2px
|
|
40
|
+
* dashed line across the swatch's middle, in the row color.
|
|
41
|
+
*/
|
|
42
|
+
export declare const dashedSwatch: (color: string) => string;
|
|
43
|
+
/** A basalt tooltip row as the engine's: the swatch shape folded into the row color. */
|
|
44
|
+
export declare function engineRow(row: ChartTooltipRow & {
|
|
45
|
+
active?: boolean | undefined;
|
|
46
|
+
}): EngineTooltipRow;
|
|
47
|
+
/** A series row of a tooltip: the label with its note, the swatch following the series' dash. */
|
|
48
|
+
export declare function seriesRow(s: Pick<ChartSeries<never>, 'label' | 'note' | 'color' | 'dash'>, value: string, active: boolean): EngineTooltipRow;
|
|
49
|
+
/** Legend-only entries for the reference lines that name themselves, in line order. */
|
|
50
|
+
export declare function refLegendSeries<T>(refLines: readonly RefLine[] | undefined): ChartSeries<T>[];
|
|
38
51
|
/** The visible series: not toggled off, and not a companion whose parent is. */
|
|
39
52
|
export declare function visibleSeries<T>(series: readonly ChartSeries<T>[], hidden: ReadonlySet<string>): ChartSeries<T>[];
|
|
40
53
|
type YAxis = {
|
|
@@ -47,6 +60,8 @@ export declare function yGuide<T>(opts: {
|
|
|
47
60
|
cls: ContainerClass;
|
|
48
61
|
side: 'left' | 'right';
|
|
49
62
|
grid: boolean;
|
|
63
|
+
/** The whole chart's height: decides inside or gutter labels. */
|
|
64
|
+
height: number;
|
|
50
65
|
}): Omit<ChartPositionScaleOptions<number>, 'scale'>;
|
|
51
66
|
/**
|
|
52
67
|
* Every n-th value, n the smallest stride that leaves at most the class's x tick count (the same
|
|
@@ -59,6 +74,8 @@ export declare function xGuide<X extends ChartX>(opts: {
|
|
|
59
74
|
xTicks: number | readonly X[] | undefined;
|
|
60
75
|
format: (v: ChartValue) => string;
|
|
61
76
|
cls: ContainerClass;
|
|
77
|
+
/** The whole chart's height: decides whether the left margin is locked to zero. */
|
|
78
|
+
height: number;
|
|
62
79
|
}): Omit<ChartPositionScaleOptions<ChartValue>, 'scale'>;
|
|
63
80
|
/** Gradient resource id for a series' area fill; the host's `idPrefix` scopes it per chart. */
|
|
64
81
|
export declare const areaGradientId: (index: number) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/charts/compile.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAEV,aAAa,EAEb,yBAAyB,
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/charts/compile.ts"],"names":[],"mappings":"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"}
|
package/dist/charts/compile.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { crosshair } from "@tanstack/charts/crosshair";
|
|
2
2
|
import { decorative } from "@tanstack/charts/mark/decorative";
|
|
3
3
|
import { rect } from "@tanstack/charts/rect";
|
|
4
|
-
import { ruleY } from "@tanstack/charts/rule";
|
|
4
|
+
import { ruleX, ruleY } from "@tanstack/charts/rule";
|
|
5
5
|
import { scaleLinear } from "@tanstack/charts/scales/linear";
|
|
6
6
|
import { scaleUtc } from "d3-scale";
|
|
7
7
|
import { tooltip as tooltipHost } from "@tanstack/charts/tooltip";
|
|
8
8
|
import { portal } from "@tanstack/charts/tooltip/portal";
|
|
9
|
+
import { SHORT_CHART_HEIGHT } from "./box.js";
|
|
9
10
|
import { fmtCompact } from "../format/number.js";
|
|
10
11
|
import { VX } from "../tokens/index.js";
|
|
11
12
|
import { cursorBinding, sourceOnlyFocus } from "./cursor.js";
|
|
13
|
+
import { cursorDots } from "./marks.js";
|
|
12
14
|
import { resolveContainerClass } from "../tokens/size-classes.js";
|
|
13
15
|
import { resolveYDomain, xScaleFor, xZoneFractions, yScaleFor } from "./scales.js";
|
|
14
16
|
import { AXIS_LINE, CHART_THEME, CROSSHAIR, DASH, GRID_LINE } from "./theme.js";
|
|
@@ -20,6 +22,7 @@ const LADDER = {
|
|
|
20
22
|
};
|
|
21
23
|
const INSIDE_LABEL_DX = 4;
|
|
22
24
|
const INSIDE_LABEL_DY = -6;
|
|
25
|
+
const labelsInside = (cls, height) => cls === "compact" && height > 0 && height < SHORT_CHART_HEIGHT;
|
|
23
26
|
function defaultNumberFormat(v) {
|
|
24
27
|
return fmtCompact(v, { digits: Math.abs(v) >= 1e3 ? 1 : 2 });
|
|
25
28
|
}
|
|
@@ -47,18 +50,65 @@ function defaultFormatX(v) {
|
|
|
47
50
|
return String(v);
|
|
48
51
|
}
|
|
49
52
|
const clampTo = (v, [lo, hi]) => Math.min(Math.max(v, Math.min(lo, hi)), Math.max(lo, hi));
|
|
53
|
+
const dashedSwatch = (color) => `repeating-linear-gradient(90deg, ${color} 0 2px, transparent 2px 4px) center / 100% 2px no-repeat`;
|
|
54
|
+
function engineRow(row) {
|
|
55
|
+
const { label, value, color, swatch, active } = row;
|
|
56
|
+
return {
|
|
57
|
+
label,
|
|
58
|
+
value,
|
|
59
|
+
...color !== void 0 && { color: swatch === "dashed" ? dashedSwatch(color) : color },
|
|
60
|
+
...active && { active }
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function seriesRow(s, value, active) {
|
|
64
|
+
return engineRow({
|
|
65
|
+
label: s.note === void 0 ? s.label : `${s.label} \xB7 ${s.note}`,
|
|
66
|
+
value,
|
|
67
|
+
color: s.color,
|
|
68
|
+
swatch: s.dash === "dashed" ? "dashed" : "solid",
|
|
69
|
+
active
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const REF_KEY_PREFIX = "__ref-";
|
|
73
|
+
const refLegendKey = (index) => `${REF_KEY_PREFIX}${index}`;
|
|
74
|
+
const SWATCH_SOLID = /* @__PURE__ */ new Map([
|
|
75
|
+
[VX.goodRef, VX.goodSolid],
|
|
76
|
+
[VX.badRef, VX.badSolid],
|
|
77
|
+
[VX.warnRef, VX.warnSolid],
|
|
78
|
+
// The tinted status fills are as translucent, and a consumer may pass either as a line color.
|
|
79
|
+
[VX.good, VX.goodSolid],
|
|
80
|
+
[VX.goodSoft, VX.goodSolid],
|
|
81
|
+
[VX.bad, VX.badSolid],
|
|
82
|
+
[VX.warn, VX.warnSolid]
|
|
83
|
+
]);
|
|
84
|
+
function refLegendSeries(refLines) {
|
|
85
|
+
return (refLines ?? []).flatMap(
|
|
86
|
+
(r, i) => r.legend === void 0 ? [] : [
|
|
87
|
+
{
|
|
88
|
+
key: refLegendKey(i),
|
|
89
|
+
label: r.legend.label,
|
|
90
|
+
color: SWATCH_SOLID.get(r.color) ?? r.color,
|
|
91
|
+
role: "reference",
|
|
92
|
+
tooltip: false,
|
|
93
|
+
getValue: () => null,
|
|
94
|
+
...r.legend.mark !== void 0 && { mark: r.legend.mark },
|
|
95
|
+
...r.dashed && { dash: "dashed" }
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
);
|
|
99
|
+
}
|
|
50
100
|
function visibleSeries(series, hidden) {
|
|
51
101
|
return series.filter(
|
|
52
102
|
(s) => !hidden.has(s.key) && !(s.parent !== void 0 && hidden.has(s.parent))
|
|
53
103
|
);
|
|
54
104
|
}
|
|
55
105
|
function yGuide(opts) {
|
|
56
|
-
const { cfg, axis, cls, side, grid } = opts;
|
|
106
|
+
const { cfg, axis, cls, side, grid, height } = opts;
|
|
57
107
|
const ladder = LADDER[cls];
|
|
58
108
|
const ticks = typeof cfg?.ticks === "object" ? { values: cfg.ticks } : { count: typeof cfg?.ticks === "number" ? cfg.ticks : ladder.yTicks };
|
|
59
109
|
const gridLine = grid ? { grid: GRID_LINE } : {};
|
|
60
110
|
if (cls === "micro") return { ...gridLine, axis: false };
|
|
61
|
-
const inside = cls
|
|
111
|
+
const inside = labelsInside(cls, height);
|
|
62
112
|
return {
|
|
63
113
|
...gridLine,
|
|
64
114
|
...side === "right" && { side: "right" },
|
|
@@ -91,8 +141,9 @@ function strideTicks(values, cls) {
|
|
|
91
141
|
return values.filter((_, i) => i % stride === 0);
|
|
92
142
|
}
|
|
93
143
|
function xGuide(opts) {
|
|
94
|
-
const { model, xTicks, format, cls } = opts;
|
|
144
|
+
const { model, xTicks, format, cls, height } = opts;
|
|
95
145
|
const ladder = LADDER[cls];
|
|
146
|
+
const inside = labelsInside(cls, height);
|
|
96
147
|
const ticks = xTickPolicy(model, xTicks ?? ladder.xTicks);
|
|
97
148
|
return {
|
|
98
149
|
axis: {
|
|
@@ -102,8 +153,8 @@ function xGuide(opts) {
|
|
|
102
153
|
fontSize: ladder.font,
|
|
103
154
|
opacity: 1,
|
|
104
155
|
thin: true,
|
|
105
|
-
// A locked-zero left margin (
|
|
106
|
-
...
|
|
156
|
+
// A locked-zero left margin (inside labels) must not clip the first label.
|
|
157
|
+
...inside && {
|
|
107
158
|
anchor: ({ index }) => index === 0 ? "start" : void 0
|
|
108
159
|
}
|
|
109
160
|
}
|
|
@@ -241,27 +292,73 @@ function resolveAxes(input, visible) {
|
|
|
241
292
|
scaleId: (side) => side === "right" && hasY2 ? "y2" : "y"
|
|
242
293
|
};
|
|
243
294
|
}
|
|
295
|
+
const edgeSides = (edge, lower, upper) => ({
|
|
296
|
+
lower: edge !== void 0 && (edge.side === lower || edge.side === "both"),
|
|
297
|
+
upper: edge !== void 0 && (edge.side === upper || edge.side === "both")
|
|
298
|
+
});
|
|
299
|
+
const edgePaint = (edge) => ({
|
|
300
|
+
stroke: edge.color,
|
|
301
|
+
strokeOpacity: 1,
|
|
302
|
+
strokeWidth: edge.width ?? 1,
|
|
303
|
+
...edge.dashed && { strokeDasharray: DASH }
|
|
304
|
+
});
|
|
305
|
+
const edgeRule = (position, [lo, hi], make) => position !== null && position > lo && position < hi ? [make(position)] : [];
|
|
244
306
|
function underlayMarks(input, model, axes) {
|
|
245
307
|
const fractionRows = [{ f0: 0, f1: 1 }];
|
|
246
|
-
const zones = (input.zones ?? []).
|
|
308
|
+
const zones = (input.zones ?? []).flatMap((z, i) => {
|
|
247
309
|
const domain = axes.axisOf(z.axisSide).domain;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
})
|
|
310
|
+
const [lo, hi] = [Math.min(...domain), Math.max(...domain)];
|
|
311
|
+
const rule = (value, name) => edgeRule(
|
|
312
|
+
value,
|
|
313
|
+
[lo, hi],
|
|
314
|
+
(at) => decorative(
|
|
315
|
+
ruleY([at], {
|
|
316
|
+
id: `zone-${i}-${name}`,
|
|
317
|
+
yScale: axes.scaleId(z.axisSide),
|
|
318
|
+
...z.edge && edgePaint(z.edge)
|
|
319
|
+
})
|
|
320
|
+
)
|
|
260
321
|
);
|
|
322
|
+
const sides = edgeSides(z.edge, "bottom", "top");
|
|
323
|
+
return [
|
|
324
|
+
decorative(
|
|
325
|
+
rect(fractionRows, {
|
|
326
|
+
id: `zone-${i}`,
|
|
327
|
+
x1: "f0",
|
|
328
|
+
x2: "f1",
|
|
329
|
+
y1: () => clampTo(z.from, domain),
|
|
330
|
+
y2: () => clampTo(z.to, domain),
|
|
331
|
+
xScale: "zx",
|
|
332
|
+
yScale: axes.scaleId(z.axisSide),
|
|
333
|
+
fill: z.fill,
|
|
334
|
+
inset: 0
|
|
335
|
+
})
|
|
336
|
+
),
|
|
337
|
+
...sides.lower ? rule(Math.min(z.from, z.to), "bottom") : [],
|
|
338
|
+
...sides.upper ? rule(Math.max(z.from, z.to), "top") : []
|
|
339
|
+
];
|
|
261
340
|
});
|
|
262
341
|
const xZones = (input.xZones ?? []).flatMap((z, i) => {
|
|
263
342
|
const f = xZoneFractions(z, model);
|
|
264
343
|
if (!f) return [];
|
|
344
|
+
const sides = edgeSides(z.edge, "start", "end");
|
|
345
|
+
const widen = z.align === "edge" ? model.halfStep : 0;
|
|
346
|
+
const bound = (value, sign) => {
|
|
347
|
+
const fraction = value === void 0 ? null : model.fraction(value);
|
|
348
|
+
return fraction === null ? null : fraction + sign * widen;
|
|
349
|
+
};
|
|
350
|
+
const rule = (value, sign, name) => edgeRule(
|
|
351
|
+
bound(value, sign),
|
|
352
|
+
[0, 1],
|
|
353
|
+
(at) => decorative(
|
|
354
|
+
ruleX([at], {
|
|
355
|
+
id: `xzone-${i}-${name}`,
|
|
356
|
+
x: (v) => v,
|
|
357
|
+
xScale: "zx",
|
|
358
|
+
...z.edge && edgePaint(z.edge)
|
|
359
|
+
})
|
|
360
|
+
)
|
|
361
|
+
);
|
|
265
362
|
return [
|
|
266
363
|
decorative(
|
|
267
364
|
rect([{ f0: f[0], f1: f[1] }], {
|
|
@@ -274,32 +371,47 @@ function underlayMarks(input, model, axes) {
|
|
|
274
371
|
fill: z.fill,
|
|
275
372
|
inset: 0
|
|
276
373
|
})
|
|
277
|
-
)
|
|
374
|
+
),
|
|
375
|
+
// An omitted bound is the plot edge: nothing to draw a rule on.
|
|
376
|
+
...sides.lower ? rule(z.from, -1, "start") : [],
|
|
377
|
+
...sides.upper ? rule(z.to, 1, "end") : []
|
|
278
378
|
];
|
|
279
379
|
});
|
|
280
380
|
return [...zones, ...xZones];
|
|
281
381
|
}
|
|
282
|
-
const refLineMarks = (input, axes) => (input.refLines ?? []).
|
|
283
|
-
(r, i) =>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
382
|
+
const refLineMarks = (input, axes) => (input.refLines ?? []).flatMap(
|
|
383
|
+
(r, i) => (
|
|
384
|
+
// A line that names itself in the legend can be toggled off there.
|
|
385
|
+
input.hidden?.has(refLegendKey(i)) ? [] : [
|
|
386
|
+
ruleY([r.value], {
|
|
387
|
+
id: `ref-${i}`,
|
|
388
|
+
stroke: r.color,
|
|
389
|
+
strokeOpacity: 1,
|
|
390
|
+
strokeWidth: 1,
|
|
391
|
+
yScale: axes.scaleId(r.axis),
|
|
392
|
+
...r.dashed && { strokeDasharray: DASH }
|
|
393
|
+
})
|
|
394
|
+
]
|
|
395
|
+
)
|
|
291
396
|
);
|
|
292
397
|
function buildScales(opts) {
|
|
293
|
-
const { input, model, axes, formatX, cls, zoneScale } = opts;
|
|
398
|
+
const { input, model, axes, formatX, cls, height, zoneScale } = opts;
|
|
294
399
|
const { left, right } = axes;
|
|
295
400
|
return {
|
|
296
401
|
x: {
|
|
297
402
|
scale: model.scale,
|
|
298
|
-
...xGuide({ model, xTicks: input.xTicks, format: formatX, cls })
|
|
403
|
+
...xGuide({ model, xTicks: input.xTicks, format: formatX, cls, height })
|
|
299
404
|
},
|
|
300
405
|
y: {
|
|
301
406
|
scale: yScaleFor(input.y, left.domain),
|
|
302
|
-
...yGuide({
|
|
407
|
+
...yGuide({
|
|
408
|
+
cfg: input.y,
|
|
409
|
+
axis: left,
|
|
410
|
+
cls,
|
|
411
|
+
height,
|
|
412
|
+
side: "left",
|
|
413
|
+
grid: input.y?.grid ?? true
|
|
414
|
+
})
|
|
303
415
|
},
|
|
304
416
|
...right && {
|
|
305
417
|
y2: {
|
|
@@ -309,6 +421,7 @@ function buildScales(opts) {
|
|
|
309
421
|
cfg: input.y2,
|
|
310
422
|
axis: right,
|
|
311
423
|
cls,
|
|
424
|
+
height,
|
|
312
425
|
side: "right",
|
|
313
426
|
grid: input.y2?.grid ?? false
|
|
314
427
|
})
|
|
@@ -342,6 +455,17 @@ function rowsOf(input, visibleKeys) {
|
|
|
342
455
|
});
|
|
343
456
|
};
|
|
344
457
|
}
|
|
458
|
+
function cursorDotMarks(input, visible, axes) {
|
|
459
|
+
return visible.flatMap((s) => {
|
|
460
|
+
const { cursorValue } = s;
|
|
461
|
+
if (!cursorValue) return [];
|
|
462
|
+
const rows = input.data.flatMap((d) => {
|
|
463
|
+
const y = cursorValue(d);
|
|
464
|
+
return y === null || !Number.isFinite(y) ? [] : [{ x: input.x(d), y, series: s.key, datum: d }];
|
|
465
|
+
});
|
|
466
|
+
return [cursorDots(s, rows, axes.onRight(s) ? "y2" : void 0)];
|
|
467
|
+
});
|
|
468
|
+
}
|
|
345
469
|
function tooltipSpec(opts) {
|
|
346
470
|
const { input, axes, visible, keys, visibleKeys, formatX } = opts;
|
|
347
471
|
const hidden = input.series.filter((s) => !visibleKeys.has(s.key));
|
|
@@ -362,19 +486,32 @@ function tooltipSpec(opts) {
|
|
|
362
486
|
for (const s of rowSeries) {
|
|
363
487
|
const v = s.getValue(d);
|
|
364
488
|
if (v === null || !Number.isFinite(v)) continue;
|
|
365
|
-
rows.push(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
489
|
+
rows.push(
|
|
490
|
+
seriesRow(
|
|
491
|
+
s,
|
|
492
|
+
s.formatValue ? s.formatValue(v, d) : axes.axisOf(axes.onRight(s) ? "right" : "left").format(v),
|
|
493
|
+
input.highlighted === s.key
|
|
494
|
+
)
|
|
495
|
+
);
|
|
371
496
|
}
|
|
372
497
|
const extra = (input.tooltip || void 0)?.rows?.(d, { visible, hidden }) ?? [];
|
|
373
|
-
return {
|
|
498
|
+
return {
|
|
499
|
+
title: tooltipHeader(input, formatX, x, d),
|
|
500
|
+
rows: [...rows, ...extra.map(engineRow)]
|
|
501
|
+
};
|
|
374
502
|
}
|
|
375
503
|
};
|
|
376
504
|
}
|
|
505
|
+
function guardReservedKeys(series) {
|
|
506
|
+
if (process.env.NODE_ENV === "production") return;
|
|
507
|
+
const clash = series.find((s) => s.key.startsWith(REF_KEY_PREFIX));
|
|
508
|
+
if (clash)
|
|
509
|
+
throw new Error(
|
|
510
|
+
`[basalt] CartesianChart: the series key "${clash.key}" is reserved (\`${REF_KEY_PREFIX}\` prefix names reference-line legend entries)`
|
|
511
|
+
);
|
|
512
|
+
}
|
|
377
513
|
function compileCartesian(input) {
|
|
514
|
+
guardReservedKeys(input.series);
|
|
378
515
|
const visible = visibleSeries(input.series, input.hidden ?? /* @__PURE__ */ new Set());
|
|
379
516
|
const visibleKeys = new Set(visible.map((s) => s.key));
|
|
380
517
|
const keys = new Set(input.series.map((s) => s.key));
|
|
@@ -382,6 +519,7 @@ function compileCartesian(input) {
|
|
|
382
519
|
const axes = resolveAxes(input, visible);
|
|
383
520
|
const under = underlayMarks(input, model, axes);
|
|
384
521
|
const over = refLineMarks(input, axes);
|
|
522
|
+
const dots = cursorDotMarks(input, visible, axes);
|
|
385
523
|
const rows = rowsOf(input, visibleKeys);
|
|
386
524
|
const formatX = (v) => input.formatX ? input.formatX(v) : defaultFormatX(v);
|
|
387
525
|
const gradients = input.series.flatMap(
|
|
@@ -402,12 +540,20 @@ function compileCartesian(input) {
|
|
|
402
540
|
y2Domain: axes.right?.domain
|
|
403
541
|
});
|
|
404
542
|
return {
|
|
405
|
-
marks: [...under, ...kindMarks, ...over, crosshair({ x: CROSSHAIR, y: false })],
|
|
406
|
-
scales: buildScales({
|
|
543
|
+
marks: [...under, ...kindMarks, ...dots, ...over, crosshair({ x: CROSSHAIR, y: false })],
|
|
544
|
+
scales: buildScales({
|
|
545
|
+
input,
|
|
546
|
+
model,
|
|
547
|
+
axes,
|
|
548
|
+
formatX,
|
|
549
|
+
cls,
|
|
550
|
+
height,
|
|
551
|
+
zoneScale: under.length > 0
|
|
552
|
+
}),
|
|
407
553
|
theme: CHART_THEME,
|
|
408
554
|
...gradients.length > 0 && { gradients },
|
|
409
555
|
clip: true,
|
|
410
|
-
...cls
|
|
556
|
+
...labelsInside(cls, height) && { margin: { left: 0, ...axes.right && { right: 0 } } }
|
|
411
557
|
};
|
|
412
558
|
},
|
|
413
559
|
// Followers paint the crosshair only, unless the chart opts into following tooltips.
|
|
@@ -427,9 +573,13 @@ export {
|
|
|
427
573
|
areaGradient,
|
|
428
574
|
areaGradientId,
|
|
429
575
|
compileCartesian,
|
|
576
|
+
dashedSwatch,
|
|
430
577
|
dateTicks,
|
|
431
578
|
defaultFormatX,
|
|
432
579
|
defaultNumberFormat,
|
|
580
|
+
engineRow,
|
|
581
|
+
refLegendSeries,
|
|
582
|
+
seriesRow,
|
|
433
583
|
strideTicks,
|
|
434
584
|
utcAxisDate,
|
|
435
585
|
utcHeaderDate,
|