basalt-ui 2.2.0 → 2.4.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 +32 -0
- package/MIGRATING.md +78 -12
- package/agent/rules/basalt-state.md +1 -1
- package/configs/lefthook.yml +4 -1
- 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/CartesianChart.d.ts.map +1 -1
- package/dist/charts/CartesianChart.js +6 -2
- 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 +14 -10
- package/dist/charts/DualPanel.d.ts.map +1 -1
- package/dist/charts/DualPanel.js +32 -14
- package/dist/charts/Heatmap.d.ts +15 -15
- package/dist/charts/Heatmap.d.ts.map +1 -1
- package/dist/charts/Heatmap.js +2 -2
- package/dist/charts/Lines.js +2 -2
- package/dist/charts/MirroredBars.d.ts +9 -9
- package/dist/charts/MirroredBars.d.ts.map +1 -1
- package/dist/charts/MirroredBars.js +8 -7
- 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 +25 -2
- package/dist/charts/compile.d.ts.map +1 -1
- package/dist/charts/compile.js +204 -34
- 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/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.js +2 -2
- package/dist/charts/types.d.ts +101 -61
- package/dist/charts/types.d.ts.map +1 -1
- package/dist/state/fields.d.ts +19 -3
- package/dist/state/fields.d.ts.map +1 -1
- package/dist/state/fields.js +14 -8
- 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/CartesianChart.tsx +7 -2
- package/src/charts/ChartCard.tsx +17 -11
- package/src/charts/Donut.tsx +5 -5
- package/src/charts/DualPanel.tsx +50 -21
- package/src/charts/Heatmap.tsx +14 -14
- package/src/charts/Lines.tsx +2 -2
- package/src/charts/MirroredBars.tsx +16 -15
- package/src/charts/Sparkline.tsx +6 -6
- package/src/charts/StackedArea.tsx +2 -2
- package/src/charts/compile.ts +285 -36
- package/src/charts/index.ts +1 -0
- package/src/charts/marks.ts +35 -1
- package/src/charts/panel.tsx +2 -2
- package/src/charts/types.ts +105 -57
- package/src/state/fields.ts +55 -19
package/src/charts/Bars.tsx
CHANGED
|
@@ -27,7 +27,7 @@ export type BarsBar<T> = Pick<
|
|
|
27
27
|
'key' | 'label' | 'color' | 'getValue' | 'formatValue' | 'tooltip' | 'legend' | 'role' | 'note'
|
|
28
28
|
> & {
|
|
29
29
|
/** Default 0.85. */
|
|
30
|
-
fillOpacity?: number
|
|
30
|
+
fillOpacity?: number | undefined
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/** A line overlay; `axis: 'right'` reads the chart's `y2`. */
|
|
@@ -54,11 +54,11 @@ export type BarsProps<T, X extends ChartX = ChartX> = Omit<
|
|
|
54
54
|
'marks' | 'series'
|
|
55
55
|
> & {
|
|
56
56
|
bars: readonly BarsBar<T>[]
|
|
57
|
-
lines?: readonly BarsLine<T>[]
|
|
57
|
+
lines?: readonly BarsLine<T>[] | undefined
|
|
58
58
|
/** Default `'stacked'`. `'normalized'` stacks each x to its share of the total. */
|
|
59
|
-
layout?: 'stacked' | 'grouped' | 'normalized'
|
|
59
|
+
layout?: 'stacked' | 'grouped' | 'normalized' | undefined
|
|
60
60
|
/** Per-bar opacity (a partial week, an estimate). Overrides the series' `fillOpacity`. */
|
|
61
|
-
barOpacity?: (d: T, key: string) => number
|
|
61
|
+
barOpacity?: ((d: T, key: string) => number) | undefined
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
const DEFAULT_BAR_OPACITY = 0.85
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { useCallback, useId, useMemo, useState } from 'react'
|
|
10
10
|
import type { CSSProperties, ReactElement, ReactNode } from 'react'
|
|
11
11
|
import { useInChartCard } from './card-context'
|
|
12
|
-
import { compileCartesian } from './compile'
|
|
12
|
+
import { compileCartesian, refLegendSeries } from './compile'
|
|
13
13
|
import type { CartesianDefinition } from './compile'
|
|
14
14
|
import { ChartEngine, idPrefixOf } from './host'
|
|
15
15
|
import { ChartLegend, legendEntries } from './legend'
|
|
@@ -170,9 +170,14 @@ export function CartesianRung<T, X extends ChartX>(
|
|
|
170
170
|
(ctx: ShellContext) => compileCartesian({ ...stable, ...ctx }),
|
|
171
171
|
[stable],
|
|
172
172
|
)
|
|
173
|
+
// Reference lines that name themselves join the legend after the series (role `reference`).
|
|
174
|
+
const legendSeries = useMemo(
|
|
175
|
+
() => [...stable.series, ...refLegendSeries<T>(stable.refLines)],
|
|
176
|
+
[stable.series, stable.refLines],
|
|
177
|
+
)
|
|
173
178
|
return (
|
|
174
179
|
<ChartShell
|
|
175
|
-
series={
|
|
180
|
+
series={legendSeries}
|
|
176
181
|
compile={compile}
|
|
177
182
|
ariaLabel={ariaLabel}
|
|
178
183
|
{...(legend !== undefined && { legend })}
|
package/src/charts/ChartCard.tsx
CHANGED
|
@@ -92,32 +92,38 @@ export type ChartCardSlot = 'root' | 'header' | 'body'
|
|
|
92
92
|
|
|
93
93
|
export type ChartCardProps = BasaltProps &
|
|
94
94
|
SlotStylesProps<ChartCardSlot> & {
|
|
95
|
-
title?: string
|
|
95
|
+
title?: string | undefined
|
|
96
96
|
icon?: ReactNode
|
|
97
97
|
/** A muted line below the title row; does not by itself render the header. */
|
|
98
|
-
subtitle?: string
|
|
98
|
+
subtitle?: string | undefined
|
|
99
99
|
/** `WidgetHeader`'s info glyph beside the title. */
|
|
100
|
-
info?: string
|
|
100
|
+
info?: string | undefined
|
|
101
101
|
/** A pre-formatted metric value, with `delta` on the hero row. */
|
|
102
|
-
value?: string
|
|
103
|
-
delta?: number
|
|
104
|
-
deltaPeriod?: string
|
|
105
|
-
deltaPolarity?: DeltaPolarity
|
|
102
|
+
value?: string | undefined
|
|
103
|
+
delta?: number | undefined
|
|
104
|
+
deltaPeriod?: string | undefined
|
|
105
|
+
deltaPolarity?: DeltaPolarity | undefined
|
|
106
106
|
/** A mono count tag after the title. */
|
|
107
|
-
count?: number
|
|
107
|
+
count?: number | undefined
|
|
108
108
|
/** Right-aligned controls. */
|
|
109
109
|
actions?: ReactNode
|
|
110
110
|
/** A resolved state replaces `children` with its placeholder; the header stays. */
|
|
111
|
-
state?: ChartState
|
|
111
|
+
state?: ChartState | undefined
|
|
112
112
|
/** Body height while a placeholder shows. Default: the chart height law, i.e. exactly the box an
|
|
113
113
|
* unsized chart takes — pass the chart's own `height` when it states one, so a `<Suspense
|
|
114
114
|
* fallback={<ChartCard state={{ pending: true }} …/>}>` reserves the final size. */
|
|
115
|
-
placeholderHeight?: number | ResponsiveChartHeight
|
|
115
|
+
placeholderHeight?: number | ResponsiveChartHeight | undefined
|
|
116
116
|
/** A retry button or a "clear filters" link under the placeholder. */
|
|
117
117
|
stateAction?: ReactNode
|
|
118
118
|
children?: ReactNode
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
/** Drops explicit `undefined`s: `WidgetHeader` is exact-optional, this props type is not. */
|
|
122
|
+
const definedOnly = <T extends object>(o: T): { [K in keyof T]?: Exclude<T[K], undefined> } =>
|
|
123
|
+
Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as {
|
|
124
|
+
[K in keyof T]?: Exclude<T[K], undefined>
|
|
125
|
+
}
|
|
126
|
+
|
|
121
127
|
/** A header renders when one of these is set (a subtitle or delta alone does not). */
|
|
122
128
|
const HEADER_TRIGGERS = ['title', 'info', 'value', 'icon', 'count'] as const
|
|
123
129
|
|
|
@@ -150,7 +156,7 @@ export function ChartCard({
|
|
|
150
156
|
<div className={cx(classes.header, classNames?.header)}>
|
|
151
157
|
<WidgetHeader
|
|
152
158
|
tier="widget"
|
|
153
|
-
{...header}
|
|
159
|
+
{...definedOnly(header)}
|
|
154
160
|
title={header.title ?? ''}
|
|
155
161
|
{...(actions !== undefined && {
|
|
156
162
|
actions: <span data-basalt-tier="widget">{actions}</span>,
|
package/src/charts/Donut.tsx
CHANGED
|
@@ -34,13 +34,13 @@ export type DonutProps<K extends string = string> = BasaltProps & {
|
|
|
34
34
|
colorForKey: (key: K) => string
|
|
35
35
|
formatValue: (v: number) => string
|
|
36
36
|
/** Legend and tooltip label for a key. Default: the key. */
|
|
37
|
-
seriesLabel?: (key: K) => string
|
|
37
|
+
seriesLabel?: ((key: K) => string) | undefined
|
|
38
38
|
/** The ring's centre text, and the smaller line under it. */
|
|
39
|
-
centerLabel?: string
|
|
40
|
-
centerSubLabel?: string
|
|
39
|
+
centerLabel?: string | undefined
|
|
40
|
+
centerSubLabel?: string | undefined
|
|
41
41
|
/** Default 240. */
|
|
42
|
-
height?: number | ResponsiveChartHeight
|
|
43
|
-
state?: ChartState
|
|
42
|
+
height?: number | ResponsiveChartHeight | undefined
|
|
43
|
+
state?: ChartState | undefined
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/** Slices kept before the rest fold into "Other". */
|
package/src/charts/DualPanel.tsx
CHANGED
|
@@ -14,7 +14,7 @@ import { useCallback, useMemo } from 'react'
|
|
|
14
14
|
import type { ReactElement } from 'react'
|
|
15
15
|
import { VX, alpha } from '../tokens'
|
|
16
16
|
import { resolveContainerClass } from '../tokens/size-classes'
|
|
17
|
-
import { defaultFormatX, defaultNumberFormat, visibleSeries } from './compile'
|
|
17
|
+
import { defaultFormatX, defaultNumberFormat, engineRow, seriesRow, visibleSeries } from './compile'
|
|
18
18
|
import { barMark, emphasis, lineMark, markersOf, thinFill } from './marks'
|
|
19
19
|
import { PanelRung, paneX, paneY, rowsOf } from './panel'
|
|
20
20
|
import type { PaneBuilder, PanelInput, PanelPlan } from './panel'
|
|
@@ -61,15 +61,17 @@ export type DualPanelBar<T> = {
|
|
|
61
61
|
positive: string
|
|
62
62
|
/** The fill below zero. */
|
|
63
63
|
negative: string
|
|
64
|
-
/** Tick and tooltip
|
|
64
|
+
/** Tick formatter, and the tooltip's too unless `tooltipFormat` is given. */
|
|
65
65
|
format: (v: number) => string
|
|
66
|
+
/** The tooltip row's formatter. Default: `format`. */
|
|
67
|
+
tooltipFormat?: ((v: number) => string) | undefined
|
|
66
68
|
/** The tooltip row's value, for a unit or a decimal `format` cannot carry. */
|
|
67
|
-
formatValue?: (v: number, d: T) => string
|
|
69
|
+
formatValue?: ((v: number, d: T) => string) | undefined
|
|
68
70
|
/** Default `'auto'`: a symmetric `[-maxAbs, maxAbs]` from the data, rounded to nice ticks. A tuple
|
|
69
71
|
* is used verbatim. */
|
|
70
|
-
domain?: readonly [number, number] | 'auto'
|
|
72
|
+
domain?: readonly [number, number] | 'auto' | undefined
|
|
71
73
|
/** When `'auto'`: floors `maxAbs`, so a plateau does not amplify to fill the pane. */
|
|
72
|
-
maxAbsFloor?: number
|
|
74
|
+
maxAbsFloor?: number | undefined
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
export type DualPanelProps<T, X extends Date | number = Date | number> = Pick<
|
|
@@ -91,15 +93,24 @@ export type DualPanelProps<T, X extends Date | number = Date | number> = Pick<
|
|
|
91
93
|
series: readonly DualPanelLine<T>[]
|
|
92
94
|
/** Top pane y axis. Default domain `'auto'`: the visible lines' span plus 8%, rounded to nice
|
|
93
95
|
* ticks (not zero-based: the interesting range is often a narrow band far from zero). */
|
|
94
|
-
top?:
|
|
96
|
+
top?:
|
|
97
|
+
| {
|
|
98
|
+
domain?: readonly [number, number] | 'auto' | undefined
|
|
99
|
+
format?: ((v: number) => string) | undefined
|
|
100
|
+
/** The lines' tooltip formatter. Default: `format`. */
|
|
101
|
+
tooltipFormat?: ((v: number) => string) | undefined
|
|
102
|
+
}
|
|
103
|
+
| undefined
|
|
95
104
|
/**
|
|
96
105
|
* Shades the band between two top lines (by key), where both are visible. `aboveFill` colours the
|
|
97
106
|
* side where `to` runs above `from`; omitted, both sides take `fill`.
|
|
98
107
|
*/
|
|
99
|
-
fillBetween?:
|
|
108
|
+
fillBetween?:
|
|
109
|
+
| { from: string; to: string; fill: string; aboveFill?: string | undefined }
|
|
110
|
+
| undefined
|
|
100
111
|
bar: DualPanelBar<T>
|
|
101
112
|
/** The top pane's share of the chart height. Default 0.62. */
|
|
102
|
-
topFraction?: number
|
|
113
|
+
topFraction?: number | undefined
|
|
103
114
|
}
|
|
104
115
|
|
|
105
116
|
type FillRow<T, X> = { x: X; from: number; to: number; series: string; datum: T }
|
|
@@ -150,6 +161,8 @@ export function DualPanel<T, X extends Date | number = Date | number>(
|
|
|
150
161
|
)
|
|
151
162
|
const all = useMemo(() => [...lines, barSeries], [lines, barSeries])
|
|
152
163
|
const topFormat = top?.format ?? defaultNumberFormat
|
|
164
|
+
const topTooltipFormat = top?.tooltipFormat ?? topFormat
|
|
165
|
+
const barTooltipFormat = bar.tooltipFormat ?? bar.format
|
|
153
166
|
|
|
154
167
|
const plan = useCallback(
|
|
155
168
|
({ hidden, highlighted }: PanelInput): PanelPlan<T> => {
|
|
@@ -300,26 +313,42 @@ export function DualPanel<T, X extends Date | number = Date | number>(
|
|
|
300
313
|
for (const s of visible) {
|
|
301
314
|
const v = s.getValue(d)
|
|
302
315
|
if (s.tooltip === false || v === null || !Number.isFinite(v)) continue
|
|
303
|
-
out.push(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
316
|
+
out.push(
|
|
317
|
+
seriesRow(
|
|
318
|
+
s,
|
|
319
|
+
s.formatValue ? s.formatValue(v, d) : topTooltipFormat(v),
|
|
320
|
+
highlighted === s.key,
|
|
321
|
+
),
|
|
322
|
+
)
|
|
309
323
|
}
|
|
310
324
|
const v = barOn ? bar.getValue(d) : null
|
|
311
325
|
if (v !== null && Number.isFinite(v))
|
|
312
|
-
out.push(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
326
|
+
out.push(
|
|
327
|
+
engineRow({
|
|
328
|
+
label: bar.label,
|
|
329
|
+
value: bar.formatValue ? bar.formatValue(v, d) : barTooltipFormat(v),
|
|
330
|
+
color: v >= 0 ? bar.positive : bar.negative,
|
|
331
|
+
active: highlighted === BAR_KEY,
|
|
332
|
+
}),
|
|
333
|
+
)
|
|
318
334
|
return out
|
|
319
335
|
},
|
|
320
336
|
}
|
|
321
337
|
},
|
|
322
|
-
[
|
|
338
|
+
[
|
|
339
|
+
data,
|
|
340
|
+
x,
|
|
341
|
+
lines,
|
|
342
|
+
barSeries,
|
|
343
|
+
top,
|
|
344
|
+
fillBetween,
|
|
345
|
+
bar,
|
|
346
|
+
topFraction,
|
|
347
|
+
topFormat,
|
|
348
|
+
topTooltipFormat,
|
|
349
|
+
barTooltipFormat,
|
|
350
|
+
formatX,
|
|
351
|
+
],
|
|
323
352
|
)
|
|
324
353
|
|
|
325
354
|
return <PanelRung {...rung} series={all} plan={plan} />
|
package/src/charts/Heatmap.tsx
CHANGED
|
@@ -18,7 +18,7 @@ import type { CSSProperties, ReactElement } from 'react'
|
|
|
18
18
|
import type { BasaltProps } from '../common/props'
|
|
19
19
|
import { alpha, VX } from '../tokens'
|
|
20
20
|
import { resolveContainerClass } from '../tokens/size-classes'
|
|
21
|
-
import { strideTicks } from './compile'
|
|
21
|
+
import { engineRow, strideTicks } from './compile'
|
|
22
22
|
import type { CartesianDefinition } from './compile'
|
|
23
23
|
import { ChartEngine, idPrefixOf } from './host'
|
|
24
24
|
import { useCoarsePointer } from '../common/use-media-query'
|
|
@@ -38,28 +38,28 @@ export type HeatmapProps<T> = BasaltProps & {
|
|
|
38
38
|
/** The intensity; `null` is an absent cell (flat neutral), never a zero. */
|
|
39
39
|
getValue: (d: T) => number | null
|
|
40
40
|
/** Explicit band order. Default: first seen in `data`. */
|
|
41
|
-
rows?: readonly string[]
|
|
42
|
-
cols?: readonly string[]
|
|
41
|
+
rows?: readonly string[] | undefined
|
|
42
|
+
cols?: readonly string[] | undefined
|
|
43
43
|
/** The ink at full intensity, a `VX.*` ref or a series token. Default `VX.line`. */
|
|
44
|
-
color?: string
|
|
44
|
+
color?: string | undefined
|
|
45
45
|
/** The value range the color scale spans. Default `[0, max]` of the data. */
|
|
46
|
-
domain?: readonly [number, number]
|
|
46
|
+
domain?: readonly [number, number] | undefined
|
|
47
47
|
/** Tooltip, legend-end and `aria` value format. Default: the number as-is. */
|
|
48
|
-
formatValue?: (v: number) => string
|
|
48
|
+
formatValue?: ((v: number) => string) | undefined
|
|
49
49
|
/** Band tick and tooltip header labels. Default: the band key. */
|
|
50
|
-
formatRow?: (row: string) => string
|
|
51
|
-
formatCol?: (col: string) => string
|
|
50
|
+
formatRow?: ((row: string) => string) | undefined
|
|
51
|
+
formatCol?: ((col: string) => string) | undefined
|
|
52
52
|
/** `false` hides the gradient legend; `label` titles it. */
|
|
53
|
-
legend?: false | { label?: string }
|
|
53
|
+
legend?: false | { label?: string | undefined } | undefined
|
|
54
54
|
/** Rows after the value row, per cell (a sample count, a failure reason). Called with the datum. */
|
|
55
|
-
tooltip?: false | { rows?: (d: T) => readonly ChartTooltipRow[] }
|
|
55
|
+
tooltip?: (false | { rows?: ((d: T) => readonly ChartTooltipRow[]) | undefined }) | undefined
|
|
56
56
|
/** A fixed height, or one per container class. Default: by row count (160–420px). */
|
|
57
|
-
height?: number | ResponsiveChartHeight
|
|
57
|
+
height?: number | ResponsiveChartHeight | undefined
|
|
58
58
|
/** Fill the parent's height instead. Overrides `height`. CSS-owned like every other kind's box
|
|
59
59
|
* (`ChartBox`, no measuring, SSR-stable), so the parent needs a definite CSS height — a grid or
|
|
60
60
|
* flex stretch, `h-full`, an explicit height — which no kind can read off an auto-height parent. */
|
|
61
|
-
matchHeight?: boolean
|
|
62
|
-
state?: ChartState
|
|
61
|
+
matchHeight?: boolean | undefined
|
|
62
|
+
state?: ChartState | undefined
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/** Intensity steps: quantized, so the gradient legend and the cells are the same ramp. */
|
|
@@ -244,7 +244,7 @@ export function Heatmap<T>(props: HeatmapProps<T>): ReactElement {
|
|
|
244
244
|
...(point.color && { color: point.color }),
|
|
245
245
|
},
|
|
246
246
|
]
|
|
247
|
-
return { title: header(c), rows: [...value, ...extra] }
|
|
247
|
+
return { title: header(c), rows: [...value, ...extra].map(engineRow) }
|
|
248
248
|
},
|
|
249
249
|
}
|
|
250
250
|
: false,
|
package/src/charts/Lines.tsx
CHANGED
|
@@ -17,7 +17,7 @@ import { VX } from '../tokens'
|
|
|
17
17
|
import { CartesianRung } from './CartesianChart'
|
|
18
18
|
import { areaGradientId } from './compile'
|
|
19
19
|
import { chartCurve } from './curves'
|
|
20
|
-
import { lineMark, markersOf, yScaleOf } from './marks'
|
|
20
|
+
import { drawnRows, lineMark, markersOf, yScaleOf } from './marks'
|
|
21
21
|
import { rowX } from './types'
|
|
22
22
|
import type {
|
|
23
23
|
CartesianChartProps,
|
|
@@ -120,7 +120,7 @@ export function Lines<T, X extends ChartX = ChartX>(props: LinesProps<T, X>): Re
|
|
|
120
120
|
if (!s.area) continue
|
|
121
121
|
out.push(
|
|
122
122
|
decorative(
|
|
123
|
-
areaY(plot
|
|
123
|
+
areaY(drawnRows(plot, s), {
|
|
124
124
|
id: `${s.key}-area`,
|
|
125
125
|
x: rowX,
|
|
126
126
|
y2: 'y',
|
|
@@ -21,7 +21,7 @@ import { useCallback, useMemo } from 'react'
|
|
|
21
21
|
import type { ReactElement } from 'react'
|
|
22
22
|
import { VX, alpha } from '../tokens'
|
|
23
23
|
import { resolveContainerClass } from '../tokens/size-classes'
|
|
24
|
-
import { defaultFormatX, defaultNumberFormat, visibleSeries } from './compile'
|
|
24
|
+
import { defaultFormatX, defaultNumberFormat, seriesRow, visibleSeries } from './compile'
|
|
25
25
|
import { barMark, emphasis } from './marks'
|
|
26
26
|
import { PanelRung, paneX, paneY, rowsOf } from './panel'
|
|
27
27
|
import type { PaneBuilder, PanelInput, PanelPlan } from './panel'
|
|
@@ -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
|
|
@@ -277,12 +277,13 @@ export function MirroredBars<T, X extends ChartX = ChartX>(
|
|
|
277
277
|
// Each pane's row falls back to ITS OWN formatter: the panes are in different units.
|
|
278
278
|
const fallback =
|
|
279
279
|
s.key === up.key ? up.format : s.key === down.key ? down.format : defaultNumberFormat
|
|
280
|
-
out.push(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
280
|
+
out.push(
|
|
281
|
+
seriesRow(
|
|
282
|
+
s,
|
|
283
|
+
s.formatValue ? s.formatValue(v, d) : fallback(v),
|
|
284
|
+
highlighted === s.key,
|
|
285
|
+
),
|
|
286
|
+
)
|
|
286
287
|
}
|
|
287
288
|
return out
|
|
288
289
|
},
|
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>(
|