basalt-ui 2.2.0 → 2.3.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 +14 -0
- package/MIGRATING.md +33 -12
- package/dist/charts/BandStrip.d.ts +7 -7
- package/dist/charts/BandStrip.d.ts.map +1 -1
- package/dist/charts/Bars.d.ts +4 -4
- package/dist/charts/Bars.d.ts.map +1 -1
- package/dist/charts/ChartCard.d.ts +10 -10
- package/dist/charts/ChartCard.d.ts.map +1 -1
- package/dist/charts/ChartCard.js +2 -1
- package/dist/charts/Donut.d.ts +5 -5
- package/dist/charts/Donut.d.ts.map +1 -1
- package/dist/charts/DualPanel.d.ts +9 -9
- package/dist/charts/DualPanel.d.ts.map +1 -1
- package/dist/charts/Heatmap.d.ts +15 -15
- package/dist/charts/Heatmap.d.ts.map +1 -1
- package/dist/charts/MirroredBars.d.ts +9 -9
- package/dist/charts/MirroredBars.d.ts.map +1 -1
- package/dist/charts/Sparkline.d.ts +6 -6
- package/dist/charts/Sparkline.d.ts.map +1 -1
- package/dist/charts/StackedArea.d.ts +2 -2
- package/dist/charts/StackedArea.d.ts.map +1 -1
- package/dist/charts/compile.d.ts +11 -1
- package/dist/charts/compile.d.ts.map +1 -1
- package/dist/charts/compile.js +51 -2
- package/dist/charts/index.d.ts +1 -0
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +3 -1
- package/dist/charts/types.d.ts +62 -60
- package/dist/charts/types.d.ts.map +1 -1
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/charts/BandStrip.tsx +12 -10
- package/src/charts/Bars.tsx +4 -4
- package/src/charts/ChartCard.tsx +17 -11
- package/src/charts/Donut.tsx +5 -5
- package/src/charts/DualPanel.tsx +13 -6
- package/src/charts/Heatmap.tsx +12 -12
- package/src/charts/MirroredBars.tsx +8 -8
- package/src/charts/Sparkline.tsx +6 -6
- package/src/charts/StackedArea.tsx +2 -2
- package/src/charts/compile.ts +82 -1
- package/src/charts/index.ts +1 -0
- package/src/charts/types.ts +68 -56
|
@@ -35,11 +35,11 @@ export type MirroredBarPane = {
|
|
|
35
35
|
* entry throws: the pane would vanish, which reads as a measured zero. */
|
|
36
36
|
key: string
|
|
37
37
|
/** The pane's upper bound. `'auto'` (default) is its own visible maximum; a number pins it. */
|
|
38
|
-
max?: number | 'auto'
|
|
38
|
+
max?: number | 'auto' | undefined
|
|
39
39
|
/** When `'auto'`: floors the upper bound, so a quiet window does not amplify noise to full height. */
|
|
40
|
-
autoMaxFloor?: number
|
|
40
|
+
autoMaxFloor?: number | undefined
|
|
41
41
|
/** Tick count for this pane's own axis. Default 3. */
|
|
42
|
-
ticks?: number
|
|
42
|
+
ticks?: number | undefined
|
|
43
43
|
/** Tick and tooltip formatter, in the pane's OWN units. */
|
|
44
44
|
format: (v: number) => string
|
|
45
45
|
}
|
|
@@ -71,18 +71,18 @@ export type MirroredBarsProps<T, X extends ChartX = ChartX> = Pick<
|
|
|
71
71
|
/** Drawn below the baseline. */
|
|
72
72
|
down: MirroredBarPane
|
|
73
73
|
/** The up pane's share of the height. Default 0.35: the pair is usually asymmetric. */
|
|
74
|
-
upFraction?: number
|
|
74
|
+
upFraction?: number | undefined
|
|
75
75
|
/** 0..1 of a bar's width that no source sample covers, drawn neutral across both panes. */
|
|
76
|
-
getAbsentFraction?: (d: T) => number
|
|
76
|
+
getAbsentFraction?: ((d: T) => number) | undefined
|
|
77
77
|
/** Per-datum bar opacity: a real but qualified measurement (a short bucket) drawn dimmer. */
|
|
78
|
-
getBarOpacity?: (d: T) => number
|
|
78
|
+
getBarOpacity?: ((d: T) => number) | undefined
|
|
79
79
|
/**
|
|
80
80
|
* Collapse adjacent data where one band per datum would be sub-pixel. `merge` is the consumer's
|
|
81
81
|
* (max, sum, or a rate from summed parts) and must keep `group[0]`'s x, the slot start.
|
|
82
82
|
*/
|
|
83
|
-
fold?: { minBandPx?: number; merge: (group: T[]) => T }
|
|
83
|
+
fold?: { minBandPx?: number | undefined; merge: (group: T[]) => T } | undefined
|
|
84
84
|
/** Default `'leading'`: x is a slot's start. */
|
|
85
|
-
cursorResolution?: CartesianChartProps<T, X>['cursorResolution']
|
|
85
|
+
cursorResolution?: CartesianChartProps<T, X>['cursorResolution'] | undefined
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
const DEFAULT_UP_FRACTION = 0.35
|
package/src/charts/Sparkline.tsx
CHANGED
|
@@ -29,18 +29,18 @@ export type SparklineProps = BasaltProps & {
|
|
|
29
29
|
/** Height in px. */
|
|
30
30
|
height: number
|
|
31
31
|
/** Width in px. Default: the container's, measured by the host. */
|
|
32
|
-
width?: number
|
|
32
|
+
width?: number | undefined
|
|
33
33
|
/** Default `'line'`. */
|
|
34
|
-
mark?: 'line' | 'bar'
|
|
34
|
+
mark?: 'line' | 'bar' | undefined
|
|
35
35
|
/** A `VX.*` ref or a series token. Default `VX.faint`. */
|
|
36
|
-
color?: string
|
|
36
|
+
color?: string | undefined
|
|
37
37
|
/** Paints the last point in `emphasisColor` — the one reading a trend beside a KPI is for. */
|
|
38
|
-
emphasizeLast?: boolean
|
|
38
|
+
emphasizeLast?: boolean | undefined
|
|
39
39
|
/** Default `VX.accent`. */
|
|
40
|
-
emphasisColor?: string
|
|
40
|
+
emphasisColor?: string | undefined
|
|
41
41
|
/** Pending / error / empty, the same contract as every other kind. The placeholder fills the
|
|
42
42
|
* sparkline's own `width` × `height`, so a loading tile does not shift when the trend lands. */
|
|
43
|
-
state?: ChartState
|
|
43
|
+
state?: ChartState | undefined
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
type Point = { i: number; v: number | null }
|
|
@@ -25,7 +25,7 @@ export type StackedAreaBand<T> = Pick<
|
|
|
25
25
|
'key' | 'label' | 'color' | 'getValue' | 'formatValue' | 'tooltip' | 'legend' | 'role' | 'note'
|
|
26
26
|
> & {
|
|
27
27
|
/** Default 0.85. */
|
|
28
|
-
fillOpacity?: number
|
|
28
|
+
fillOpacity?: number | undefined
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export type StackedAreaProps<T, X extends ChartX = ChartX> = Omit<
|
|
@@ -35,7 +35,7 @@ export type StackedAreaProps<T, X extends ChartX = ChartX> = Omit<
|
|
|
35
35
|
/** The bands, bottom to top. */
|
|
36
36
|
series: readonly StackedAreaBand<T>[]
|
|
37
37
|
/** No `scale`: a log axis has no additive zero to stack from. */
|
|
38
|
-
y?: Omit<NonNullable<CartesianChartProps<T, X>['y']>, 'scale'>
|
|
38
|
+
y?: Omit<NonNullable<CartesianChartProps<T, X>['y']>, 'scale'> | undefined
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function StackedArea<T, X extends ChartX = ChartX>(
|
package/src/charts/compile.ts
CHANGED
|
@@ -39,6 +39,7 @@ import type {
|
|
|
39
39
|
ChartTooltipRow,
|
|
40
40
|
ChartX,
|
|
41
41
|
PlotRow,
|
|
42
|
+
ZoneSpec,
|
|
42
43
|
} from './types'
|
|
43
44
|
|
|
44
45
|
/**
|
|
@@ -249,6 +250,86 @@ export function areaGradient(index: number, color: string): ChartGradient {
|
|
|
249
250
|
}
|
|
250
251
|
}
|
|
251
252
|
|
|
253
|
+
const areaTint = (color: string): string =>
|
|
254
|
+
`color-mix(in srgb, ${color} var(--vx-area-top), transparent)`
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* A series area filled by value zone: a vertical gradient whose stops sit at the zone boundaries.
|
|
258
|
+
* The engine writes `<linearGradient>` in the default `objectBoundingBox` units, so offsets are
|
|
259
|
+
* fractions of the AREA's own box, not of the plot: from the larger of the series' maximum and 0 down
|
|
260
|
+
* to the smaller of its minimum and 0, the baseline the area closes to even when the y domain
|
|
261
|
+
* excludes 0. A boundary at value `v` sits at `(ceiling - v) / (ceiling - floor)`. Hard edges:
|
|
262
|
+
* neighbouring zones meet at one offset; overlapping zones never run backwards. `null` when no zone
|
|
263
|
+
* reaches the area (the caller keeps the plain series-colour fade). Linear axes only.
|
|
264
|
+
*/
|
|
265
|
+
export function zoneAreaGradient(
|
|
266
|
+
index: number,
|
|
267
|
+
zones: readonly ZoneSpec[],
|
|
268
|
+
values: readonly (number | null)[],
|
|
269
|
+
): ChartGradient | null {
|
|
270
|
+
let floor = 0
|
|
271
|
+
let ceiling = 0
|
|
272
|
+
for (const v of values) {
|
|
273
|
+
if (v === null || !Number.isFinite(v)) continue
|
|
274
|
+
if (v < floor) floor = v
|
|
275
|
+
if (v > ceiling) ceiling = v
|
|
276
|
+
}
|
|
277
|
+
const span = ceiling - floor
|
|
278
|
+
if (span <= 0) return null
|
|
279
|
+
const offsetOf = (v: number): number => (ceiling - Math.min(ceiling, Math.max(floor, v))) / span
|
|
280
|
+
const reaching = zones
|
|
281
|
+
.filter((z) => !Number.isNaN(z.from) && !Number.isNaN(z.to) && z.to > floor && z.from < ceiling)
|
|
282
|
+
.toSorted((p, q) => q.to - p.to)
|
|
283
|
+
let previous = 0
|
|
284
|
+
const stops = reaching.flatMap((z) =>
|
|
285
|
+
[offsetOf(z.to), offsetOf(z.from)].map((raw) => {
|
|
286
|
+
previous = Math.max(previous, raw)
|
|
287
|
+
return { offset: previous, color: areaTint(z.fill) }
|
|
288
|
+
}),
|
|
289
|
+
)
|
|
290
|
+
if (stops.length === 0) return null
|
|
291
|
+
return { id: areaGradientId(index), x1: 0, y1: 0, x2: 0, y2: 1, stops }
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
let warnedLogZones = false
|
|
295
|
+
|
|
296
|
+
/** Zone stops are placed linearly in value; a log axis would put them in the wrong place (V2-SPEC
|
|
297
|
+
* § 9.9 precedent): dev throws, production logs once and keeps the series-colour fade. */
|
|
298
|
+
function guardLogZones(onLog: boolean): boolean {
|
|
299
|
+
if (!onLog) return false
|
|
300
|
+
const message = "area: 'zones' cannot use a log axis; use area: true"
|
|
301
|
+
if (process.env.NODE_ENV !== 'production') throw new Error(message)
|
|
302
|
+
// oxlint-disable-next-line no-console -- the production leg of a dev-only throw
|
|
303
|
+
if (!warnedLogZones) console.error(message)
|
|
304
|
+
warnedLogZones = true
|
|
305
|
+
return true
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/** The gradient resource for a series' `area` fill: zones, a colour ref, or the series colour. */
|
|
309
|
+
function seriesAreaGradient<T, X extends ChartX>(
|
|
310
|
+
s: ChartSeries<T>,
|
|
311
|
+
index: number,
|
|
312
|
+
input: CartesianInput<T, X>,
|
|
313
|
+
axes: Axes<T>,
|
|
314
|
+
): ChartGradient {
|
|
315
|
+
const plain = areaGradient(
|
|
316
|
+
index,
|
|
317
|
+
typeof s.area === 'string' && s.area !== 'zones' ? s.area : s.color,
|
|
318
|
+
)
|
|
319
|
+
if (s.area !== 'zones') return plain
|
|
320
|
+
const side = axes.onRight(s) ? 'right' : 'left'
|
|
321
|
+
const axisConfig = side === 'right' ? input.y2 : input.y
|
|
322
|
+
if (guardLogZones(axisConfig?.scale === 'log')) return plain
|
|
323
|
+
const zones = (input.zones ?? []).filter((z) => axes.scaleId(z.axisSide) === axes.scaleId(side))
|
|
324
|
+
return (
|
|
325
|
+
zoneAreaGradient(
|
|
326
|
+
index,
|
|
327
|
+
zones,
|
|
328
|
+
input.data.map((d) => s.getValue(d)),
|
|
329
|
+
) ?? plain
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
252
333
|
const isBar = <T>(s: ChartSeries<T>): boolean => s.mark === 'bar'
|
|
253
334
|
|
|
254
335
|
/** The two synthetic totals standing in for a stack's bars in its AUTO domain only: the positive
|
|
@@ -548,7 +629,7 @@ export function compileCartesian<T, X extends ChartX>(
|
|
|
548
629
|
const formatX = (v: ChartValue): string =>
|
|
549
630
|
input.formatX ? input.formatX(v as X) : defaultFormatX(v)
|
|
550
631
|
const gradients = input.series.flatMap((s, i) =>
|
|
551
|
-
s.area ? [
|
|
632
|
+
s.area ? [seriesAreaGradient(s, i, input, axes)] : [],
|
|
552
633
|
)
|
|
553
634
|
|
|
554
635
|
return {
|
package/src/charts/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ export {
|
|
|
28
28
|
} from './MirroredBars'
|
|
29
29
|
export { ChartCard, type ChartCardProps, type ChartCardSlot } from './ChartCard'
|
|
30
30
|
export { chartCursor } from './cursor'
|
|
31
|
+
export { chartCurve, type CurveName } from './curves'
|
|
31
32
|
export type {
|
|
32
33
|
AxisConfig,
|
|
33
34
|
CartesianChartProps,
|
package/src/charts/types.ts
CHANGED
|
@@ -24,35 +24,44 @@ export type ChartSeries<T> = {
|
|
|
24
24
|
* series whose `getValue` is always `null` is a legend-only entry (a zone or reference key). */
|
|
25
25
|
getValue: (d: T) => number | null
|
|
26
26
|
/** The legend swatch shape. Default: the kind's own mark (`line` in `Lines`, `bar` in `Bars`). */
|
|
27
|
-
mark?: 'line' | 'bar' | 'area'
|
|
27
|
+
mark?: 'line' | 'bar' | 'area' | undefined
|
|
28
28
|
/** Default `'solid'`; `'dashed'` is `VX.dashArray` on the line, the legend and the tooltip. */
|
|
29
|
-
dash?: 'solid' | 'dashed'
|
|
29
|
+
dash?: 'solid' | 'dashed' | undefined
|
|
30
30
|
/** Interpolation between points. Default `'monotone'`. A piecewise-constant quantity (a price
|
|
31
31
|
* tier, a config value) is a step: a smoothed curve draws values that never existed. */
|
|
32
|
-
curve?: CurveName
|
|
33
|
-
strokeWidth?: number
|
|
32
|
+
curve?: CurveName | undefined
|
|
33
|
+
strokeWidth?: number | undefined
|
|
34
34
|
/** Dims the plotted stroke (a faint companion line). Strokes only. */
|
|
35
|
-
strokeOpacity?: number
|
|
35
|
+
strokeOpacity?: number | undefined
|
|
36
36
|
/** Bars and areas. */
|
|
37
|
-
fillOpacity?: number
|
|
38
|
-
/** `Lines`: a soft gradient fill under the line — `true` in the series color,
|
|
39
|
-
|
|
37
|
+
fillOpacity?: number | undefined
|
|
38
|
+
/** `Lines`: a soft gradient fill under the line — `true` in the series color, a color ref, or
|
|
39
|
+
* `'zones'`: a vertical gradient coloured by the chart's `zones` on this series' axis, hard stops
|
|
40
|
+
* at the zone boundaries (no zone in reach: the series color). Linear axes only. */
|
|
41
|
+
area?: boolean | 'zones' | (string & {}) | undefined
|
|
40
42
|
/** Which y axis the series is measured against. `'right'` needs the chart's `y2`. */
|
|
41
|
-
axis?: 'left' | 'right'
|
|
43
|
+
axis?: 'left' | 'right' | undefined
|
|
42
44
|
/** Legend grouping: series → overlay → reference. Default `'series'`. */
|
|
43
|
-
role?: 'series' | 'overlay' | 'reference'
|
|
45
|
+
role?: 'series' | 'overlay' | 'reference' | undefined
|
|
44
46
|
/** `false` keeps it out of the legend (a companion line folded under `parent`). Default `true`. */
|
|
45
|
-
legend?: boolean
|
|
47
|
+
legend?: boolean | undefined
|
|
46
48
|
/** `false` draws and legends it but never lists it as a tooltip row. Default `true`. */
|
|
47
|
-
tooltip?: boolean
|
|
49
|
+
tooltip?: boolean | undefined
|
|
48
50
|
/** A companion (an MA line) names its parent, so a legend toggle and hover keep the pair. */
|
|
49
|
-
parent?: string
|
|
51
|
+
parent?: string | undefined
|
|
50
52
|
/** A short qualifier after the label in the legend and the tooltip row, in muted text. */
|
|
51
|
-
note?: string
|
|
53
|
+
note?: string | undefined
|
|
52
54
|
/** Per-series tooltip value format; receives the datum so a row can read more than the value. */
|
|
53
|
-
formatValue?: (v: number, d: T) => string
|
|
55
|
+
formatValue?: ((v: number, d: T) => string) | undefined
|
|
54
56
|
/** A marker at a point (a PR star, a status dot); `null` for none. */
|
|
55
|
-
getMarker?:
|
|
57
|
+
getMarker?:
|
|
58
|
+
| ((d: T) => {
|
|
59
|
+
color?: string | undefined
|
|
60
|
+
r?: number | undefined
|
|
61
|
+
fillOpacity?: number | undefined
|
|
62
|
+
ring?: boolean | undefined
|
|
63
|
+
} | null)
|
|
64
|
+
| undefined
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
/** One y axis. */
|
|
@@ -66,23 +75,24 @@ export type AxisConfig<T> = {
|
|
|
66
75
|
| readonly [number, number]
|
|
67
76
|
| 'auto'
|
|
68
77
|
| ((data: readonly T[], visible: readonly ChartSeries<T>[]) => readonly [number, number])
|
|
78
|
+
| undefined
|
|
69
79
|
/** When `'auto'`: the raw upper bound is at least this; padding applies after. */
|
|
70
|
-
autoMaxFloor?: number
|
|
80
|
+
autoMaxFloor?: number | undefined
|
|
71
81
|
/** When `'auto'`: the lower bound is at most this. Default `0` (a zero baseline); `Infinity` pads
|
|
72
82
|
* down from the data minimum instead. Ignored on a log axis. */
|
|
73
|
-
autoMinCeil?: number
|
|
83
|
+
autoMinCeil?: number | undefined
|
|
74
84
|
/** When `'auto'`: padding multiplier away from the data. Default `1.1`. */
|
|
75
|
-
autoPad?: number
|
|
85
|
+
autoPad?: number | undefined
|
|
76
86
|
/** A tick count, or the exact tick values. Default: one per ~48px of plot height, ≤ 5. */
|
|
77
|
-
ticks?: number | readonly number[]
|
|
87
|
+
ticks?: number | readonly number[] | undefined
|
|
78
88
|
/** Tick and tooltip formatter. Default: compact numbers (`12.5k`). */
|
|
79
|
-
format?: (v: number) => string
|
|
89
|
+
format?: ((v: number) => string) | undefined
|
|
80
90
|
/** Horizontal grid rules. Default: on for `y`, off for `y2`. */
|
|
81
|
-
grid?: boolean
|
|
91
|
+
grid?: boolean | undefined
|
|
82
92
|
/** Round the domain outward to nice ticks. Default `false` (a fixed domain stays fixed). */
|
|
83
|
-
nice?: boolean
|
|
93
|
+
nice?: boolean | undefined
|
|
84
94
|
/** Default `'linear'`. A log axis floors at the smallest positive visible value. */
|
|
85
|
-
scale?: 'linear' | 'log'
|
|
95
|
+
scale?: 'linear' | 'log' | undefined
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
/** A horizontal band on one y axis. `±Infinity` reaches the plot edge. */
|
|
@@ -90,7 +100,7 @@ export type ZoneSpec = {
|
|
|
90
100
|
from: number
|
|
91
101
|
to: number
|
|
92
102
|
fill: string
|
|
93
|
-
axisSide?: 'left' | 'right'
|
|
103
|
+
axisSide?: 'left' | 'right' | undefined
|
|
94
104
|
}
|
|
95
105
|
|
|
96
106
|
/**
|
|
@@ -99,18 +109,18 @@ export type ZoneSpec = {
|
|
|
99
109
|
* from one hour to another, both hours included).
|
|
100
110
|
*/
|
|
101
111
|
export type XZoneSpec<X extends ChartX = ChartX> = {
|
|
102
|
-
from?: X
|
|
103
|
-
to?: X
|
|
112
|
+
from?: X | undefined
|
|
113
|
+
to?: X | undefined
|
|
104
114
|
fill: string
|
|
105
|
-
align?: 'center' | 'edge'
|
|
115
|
+
align?: 'center' | 'edge' | undefined
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
/** A horizontal reference line — annotation only, no domain role beyond staying inside the plot. */
|
|
109
119
|
export type RefLine = {
|
|
110
120
|
value: number
|
|
111
121
|
color: string
|
|
112
|
-
dashed?: boolean
|
|
113
|
-
axis?: 'left' | 'right'
|
|
122
|
+
dashed?: boolean | undefined
|
|
123
|
+
axis?: 'left' | 'right' | undefined
|
|
114
124
|
}
|
|
115
125
|
|
|
116
126
|
/** A fill between the line and a value, on one side of it, tracking the line. */
|
|
@@ -134,44 +144,46 @@ export type ChartTooltipRow = {
|
|
|
134
144
|
export type ChartTooltipConfig<T, X extends ChartX = ChartX> = {
|
|
135
145
|
/** The tooltip title. Default: the x value through `formatX`'s long form (a date reads
|
|
136
146
|
* `Mon Sep 1 2026`). */
|
|
137
|
-
formatHeader?: (x: X, d: T) => string
|
|
147
|
+
formatHeader?: ((x: X, d: T) => string) | undefined
|
|
138
148
|
/** Rows after the per-series rows (a total, a zone badge, a context line). `visible`/`hidden` are
|
|
139
149
|
* the legend's split, so a row never names a series the plot no longer draws. */
|
|
140
|
-
rows?:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
150
|
+
rows?:
|
|
151
|
+
| ((
|
|
152
|
+
d: T,
|
|
153
|
+
ctx: { visible: readonly ChartSeries<T>[]; hidden: readonly ChartSeries<T>[] },
|
|
154
|
+
) => readonly ChartTooltipRow[])
|
|
155
|
+
| undefined
|
|
144
156
|
/** Show this chart's tooltip while it FOLLOWS a sibling's cursor. Default `false`: only the chart
|
|
145
157
|
* under the pointer or keyboard focus shows a tooltip and a live region. */
|
|
146
|
-
onFollow?: boolean
|
|
158
|
+
onFollow?: boolean | undefined
|
|
147
159
|
}
|
|
148
160
|
|
|
149
161
|
export type ChartLegendConfig = {
|
|
150
162
|
/** Default `'bottom'`. `'header'` draws the legend at the top of the chart body, spaced as the
|
|
151
163
|
* enclosing `ChartCard`'s header legend row (in the chart's own markup, so it is in the server
|
|
152
164
|
* HTML and the header never grows); outside a card it is `'top'`. */
|
|
153
|
-
placement?: 'top' | 'bottom' | 'header'
|
|
165
|
+
placement?: 'top' | 'bottom' | 'header' | undefined
|
|
154
166
|
/** Visually separate roles: series | overlay | reference. */
|
|
155
|
-
groups?: boolean
|
|
167
|
+
groups?: boolean | undefined
|
|
156
168
|
/** Clicking an entry hides that series. Default: on whenever there are two or more entries. */
|
|
157
|
-
toggle?: boolean
|
|
169
|
+
toggle?: boolean | undefined
|
|
158
170
|
}
|
|
159
171
|
|
|
160
172
|
/** A height per container class, `base` below `regular`. A plain number is fixed. */
|
|
161
173
|
export type ResponsiveChartHeight = {
|
|
162
174
|
base: number
|
|
163
|
-
regular?: number
|
|
164
|
-
wide?: number
|
|
175
|
+
regular?: number | undefined
|
|
176
|
+
wide?: number | undefined
|
|
165
177
|
}
|
|
166
178
|
|
|
167
179
|
/** The three "nothing to draw" states, pending → error → empty. */
|
|
168
180
|
export type ChartState = {
|
|
169
|
-
pending?: boolean
|
|
181
|
+
pending?: boolean | undefined
|
|
170
182
|
/** Truthy = the query failed; an `Error`'s message is the label. */
|
|
171
183
|
error?: unknown
|
|
172
184
|
/** `true`, or the empty label itself. The label is the one way to say WHY (`'No runs match the
|
|
173
185
|
* filter'` vs `'No runs yet'`): § 9 fixes the state shape, so there is no reason field. */
|
|
174
|
-
empty?: boolean | string
|
|
186
|
+
empty?: boolean | string | undefined
|
|
175
187
|
}
|
|
176
188
|
|
|
177
189
|
/** A row of `plot.rows(key)`: one per datum, `y: null` kept as a gap. */
|
|
@@ -215,27 +227,27 @@ export type CartesianChartProps<T, X extends ChartX = ChartX> = BasaltProps & {
|
|
|
215
227
|
series: readonly ChartSeries<T>[]
|
|
216
228
|
/** The plot's marks. Draw `plot.rows(key)` / `plot.visible`, never `series` directly. */
|
|
217
229
|
marks: (plot: PlotContext<T, X>) => ChartMarks
|
|
218
|
-
y?: AxisConfig<T>
|
|
230
|
+
y?: AxisConfig<T> | undefined
|
|
219
231
|
/** A right axis; series with `axis: 'right'` and marks bound to `plot.y2` read it. */
|
|
220
|
-
y2?: AxisConfig<T>
|
|
232
|
+
y2?: AxisConfig<T> | undefined
|
|
221
233
|
/** A tick count, or the exact x tick values. Default: by container class. */
|
|
222
|
-
xTicks?: number | readonly X[]
|
|
234
|
+
xTicks?: number | readonly X[] | undefined
|
|
223
235
|
/** Tick label for an x value. Default: `DD.MM` for dates, compact numbers, strings verbatim. */
|
|
224
|
-
formatX?: (x: X) => string
|
|
225
|
-
zones?: readonly ZoneSpec[]
|
|
226
|
-
xZones?: readonly XZoneSpec<X>[]
|
|
227
|
-
refLines?: readonly RefLine[]
|
|
236
|
+
formatX?: ((x: X) => string) | undefined
|
|
237
|
+
zones?: readonly ZoneSpec[] | undefined
|
|
238
|
+
xZones?: readonly XZoneSpec<X>[] | undefined
|
|
239
|
+
refLines?: readonly RefLine[] | undefined
|
|
228
240
|
/** `false` hides the legend. */
|
|
229
|
-
legend?: ChartLegendConfig | false
|
|
241
|
+
legend?: ChartLegendConfig | false | undefined
|
|
230
242
|
/** Default: the height law (measured width × class ratio, 160–420px, ≤ 45vh on touch). */
|
|
231
|
-
height?: number | ResponsiveChartHeight
|
|
232
|
-
state?: ChartState
|
|
243
|
+
height?: number | ResponsiveChartHeight | undefined
|
|
244
|
+
state?: ChartState | undefined
|
|
233
245
|
/** Joins a named cursor group instead of the page-shared default. */
|
|
234
|
-
cursorGroup?: string
|
|
246
|
+
cursorGroup?: string | undefined
|
|
235
247
|
/** Default `'nearest'`. `'leading'` for a series keyed by a bucket's leading edge (a weekly
|
|
236
248
|
* value keyed by its Monday). */
|
|
237
|
-
cursorResolution?: CursorResolution
|
|
238
|
-
tooltip?: ChartTooltipConfig<T, X> | false
|
|
249
|
+
cursorResolution?: CursorResolution | undefined
|
|
250
|
+
tooltip?: ChartTooltipConfig<T, X> | false | undefined
|
|
239
251
|
}
|
|
240
252
|
|
|
241
253
|
/** The x channel of a `plot.rows()` row, as an accessor (a field name does not type-check against a
|