@pond-ts/charts 0.57.0 → 0.59.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/API.md +576 -0
- package/CHANGELOG.md +1213 -1
- package/dist/AreaChart.d.ts +12 -1
- package/dist/AreaChart.js +131 -13
- package/dist/BarChart.d.ts +56 -7
- package/dist/BarChart.js +263 -39
- package/dist/BarList.d.ts +85 -5
- package/dist/BarList.js +25 -4
- package/dist/BoxList.d.ts +70 -3
- package/dist/BoxList.js +21 -7
- package/dist/BoxPlot.d.ts +2 -1
- package/dist/BoxPlot.js +101 -9
- package/dist/Candlestick.d.ts +13 -1
- package/dist/Candlestick.js +89 -3
- package/dist/ChartContainer.d.ts +36 -48
- package/dist/ChartContainer.js +465 -59
- package/dist/ChartRow.d.ts +9 -2
- package/dist/ChartRow.js +176 -14
- package/dist/HeatMap.d.ts +176 -0
- package/dist/HeatMap.js +344 -0
- package/dist/Layers.d.ts +5 -1
- package/dist/Layers.js +1014 -253
- package/dist/Legend.js +8 -4
- package/dist/LineChart.d.ts +18 -1
- package/dist/LineChart.js +165 -4
- package/dist/ListTable.d.ts +30 -3
- package/dist/ListTable.js +381 -23
- package/dist/ScatterChart.d.ts +3 -2
- package/dist/ScatterChart.js +68 -4
- package/dist/XAxis.js +40 -22
- package/dist/YAxis.d.ts +58 -2
- package/dist/YAxis.js +3 -1
- package/dist/area.d.ts +34 -1
- package/dist/area.js +88 -1
- package/dist/bars.d.ts +67 -6
- package/dist/bars.js +250 -35
- package/dist/box.d.ts +2 -2
- package/dist/box.js +158 -40
- package/dist/brush.d.ts +142 -0
- package/dist/brush.js +179 -0
- package/dist/child-index.d.ts +27 -0
- package/dist/child-index.js +57 -0
- package/dist/context.d.ts +870 -39
- package/dist/cursors.d.ts +161 -0
- package/dist/cursors.js +503 -0
- package/dist/data.d.ts +38 -0
- package/dist/data.js +43 -0
- package/dist/decimate.d.ts +78 -1
- package/dist/decimate.js +157 -0
- package/dist/format.d.ts +15 -0
- package/dist/format.js +16 -1
- package/dist/heat.d.ts +163 -0
- package/dist/heat.js +659 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.js +27 -0
- package/dist/line.d.ts +137 -0
- package/dist/line.js +328 -0
- package/dist/ohlc.d.ts +16 -1
- package/dist/ohlc.js +93 -4
- package/dist/range.d.ts +14 -1
- package/dist/range.js +24 -3
- package/dist/scatter.d.ts +17 -9
- package/dist/scatter.js +221 -33
- package/dist/select.d.ts +13 -5
- package/dist/select.js +14 -6
- package/dist/selection-fixtures.d.ts +174 -0
- package/dist/selection-fixtures.js +569 -0
- package/dist/selection-stories.d.ts +73 -0
- package/dist/selection-stories.js +301 -0
- package/dist/selectors.d.ts +316 -0
- package/dist/selectors.js +391 -0
- package/dist/span.d.ts +122 -0
- package/dist/span.js +203 -0
- package/dist/sweep.d.ts +154 -0
- package/dist/sweep.js +282 -0
- package/dist/theme.d.ts +510 -5
- package/dist/theme.js +217 -41
- package/dist/tracker.d.ts +6 -0
- package/dist/tracker.js +6 -0
- package/dist/tradingAxis.fixture.d.ts +78 -0
- package/dist/tradingAxis.fixture.js +215 -0
- package/dist/useChartLegend.js +18 -3
- package/dist/yticks.d.ts +3 -0
- package/dist/yticks.js +104 -0
- package/package.json +6 -5
package/dist/Legend.js
CHANGED
|
@@ -112,8 +112,10 @@ export function Legend({ placement = 'top-right', items, onRowClick, onRowHover,
|
|
|
112
112
|
// dulls (the ticker-compare treatment) — quieter and clearer than
|
|
113
113
|
// decorating the selected item itself. Only when the selection points at an
|
|
114
114
|
// item of THIS legend, so selecting an off-legend mark dulls nothing.
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
// Any member of the selection set that names an item of THIS legend
|
|
116
|
+
// ([PND-MULTISEL]); selecting an off-legend mark still dulls nothing.
|
|
117
|
+
const selectedIds = container?.selected ?? [];
|
|
118
|
+
const anySelected = entries.some((it) => it.id !== undefined && selectedIds.some((m) => m.id === it.id));
|
|
117
119
|
const enter = (item) => {
|
|
118
120
|
if (onRowHover)
|
|
119
121
|
return onRowHover(item);
|
|
@@ -154,8 +156,10 @@ export function Legend({ placement = 'top-right', items, onRowClick, onRowHover,
|
|
|
154
156
|
const interactive = onRowClick !== undefined ||
|
|
155
157
|
onRowHover !== undefined ||
|
|
156
158
|
(item.id !== undefined && container !== null);
|
|
157
|
-
const selected = item.id !== undefined &&
|
|
158
|
-
|
|
159
|
+
const selected = item.id !== undefined &&
|
|
160
|
+
(container?.selected ?? []).some((m) => m.id === item.id);
|
|
161
|
+
const hovered = item.id !== undefined &&
|
|
162
|
+
(container?.hovered ?? []).some((m) => m.id === item.id);
|
|
159
163
|
return (_jsxs("div", { onPointerEnter: () => enter(item), onPointerLeave: () => leave(item), onClick: () => click(item), style: {
|
|
160
164
|
display: 'flex',
|
|
161
165
|
alignItems: 'center',
|
package/dist/LineChart.d.ts
CHANGED
|
@@ -14,6 +14,23 @@ export interface LineChartCommon<S extends SeriesSchema = SeriesSchema, VS exten
|
|
|
14
14
|
* is what bred react-timeseries-charts' styling bugs; restyle via the theme).
|
|
15
15
|
*/
|
|
16
16
|
as?: string;
|
|
17
|
+
/**
|
|
18
|
+
* **Opt in to selection** — the layer identity a `<Selector>` /
|
|
19
|
+
* `<MultiSelector>` reports and a `selected` entry names. **Omitted ⇒ the
|
|
20
|
+
* trace is inert**, exactly as every other layer's `id` gates it.
|
|
21
|
+
*
|
|
22
|
+
* A trace's selection is not shaped like a bar's, because **a trace has no
|
|
23
|
+
* marks** ([PND-TRACESEL]):
|
|
24
|
+
*
|
|
25
|
+
* - a **click** commits a **series-scoped** {@link SelectInfo} — `key` and
|
|
26
|
+
* `value` are `NaN`, because no sample was selected, and a stable `mark`
|
|
27
|
+
* carries the identity so the documented deselect-toggle works;
|
|
28
|
+
* - a **sweep** commits a {@link SpanSelection} with **no marks**. The span
|
|
29
|
+
* _is_ the selection. A trace's samples are usually undrawn and there are
|
|
30
|
+
* several per pixel, so "the samples you swept" is a set you never
|
|
31
|
+
* expressed — take the span and slice your own series with it.
|
|
32
|
+
*/
|
|
33
|
+
id?: string;
|
|
17
34
|
/**
|
|
18
35
|
* Which `<YAxis>` (by its `id`) this line scales against — picks the *scale*,
|
|
19
36
|
* where `as` picks the *style* (separate concerns). **Omitted ⇒ the row's
|
|
@@ -107,6 +124,6 @@ export type LineChartProps<S extends SeriesSchema = SeriesSchema, VS extends Val
|
|
|
107
124
|
* (scaling against its `axis`), and renders nothing to the DOM — the row draws
|
|
108
125
|
* it. The line breaks at gaps rather than spanning them.
|
|
109
126
|
*/
|
|
110
|
-
export declare function LineChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, column, readout, as: semantic, axis, curve, gaps, sessionBreaks, decimate, legend, index, }: LineChartProps<S, VS>): null;
|
|
127
|
+
export declare function LineChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, column, readout, as: semantic, axis, id, curve, gaps, sessionBreaks, decimate, legend, index, }: LineChartProps<S, VS>): null;
|
|
111
128
|
export {};
|
|
112
129
|
//# sourceMappingURL=LineChart.d.ts.map
|
package/dist/LineChart.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { useContext, useEffect, useMemo } from 'react';
|
|
2
2
|
import { ValueSeries } from 'pond-ts';
|
|
3
3
|
import { assertNumericColumn, fromTimeSeries, fromValueSeries, } from './data.js';
|
|
4
|
-
import { drawLine, yExtent } from './line.js';
|
|
4
|
+
import { drawLine, drawPartitioned, plotExtentOf, sliceTrace, strokeSpanEdges, traceHitIndex, traceStateStyle, yExtent, } from './line.js';
|
|
5
|
+
import { sweepSpan } from './sweep.js';
|
|
5
6
|
import { resolveCurve } from './curve.js';
|
|
6
7
|
import { DEFAULT_GAP_MODE, DEFAULT_GAP_CONNECTOR_OPACITY, } from './gaps.js';
|
|
7
|
-
import { ContainerContext, LayersContext } from './context.js';
|
|
8
|
+
import { ContainerContext, LayersContext, } from './context.js';
|
|
8
9
|
import { legendLabelFor, useLegendItems, } from './swatch.js';
|
|
9
10
|
import { useSlotKey } from './use-slot-key.js';
|
|
10
11
|
/** Stable empty boundary list — so `sessionBreaks={false}` keeps a referentially
|
|
@@ -16,7 +17,7 @@ const NO_BREAKS = [];
|
|
|
16
17
|
* (scaling against its `axis`), and renders nothing to the DOM — the row draws
|
|
17
18
|
* it. The line breaks at gaps rather than spanning them.
|
|
18
19
|
*/
|
|
19
|
-
export function LineChart({ series, column, readout, as: semantic, axis, curve, gaps = DEFAULT_GAP_MODE, sessionBreaks = false, decimate = true, legend, index = 0, }) {
|
|
20
|
+
export function LineChart({ series, column, readout, as: semantic, axis, id, curve, gaps = DEFAULT_GAP_MODE, sessionBreaks = false, decimate = true, legend, index = 0, }) {
|
|
20
21
|
const container = useContext(ContainerContext);
|
|
21
22
|
if (container === null) {
|
|
22
23
|
throw new Error('<LineChart> must be rendered inside a <ChartContainer>');
|
|
@@ -64,6 +65,56 @@ export function LineChart({ series, column, readout, as: semantic, axis, curve,
|
|
|
64
65
|
}
|
|
65
66
|
return provider.boundaries(cs.x[0], cs.x[cs.length - 1]);
|
|
66
67
|
}, [sessionBreaks, container.discontinuities, cs]);
|
|
68
|
+
// ── The trace's interaction state ([PND-TRACESEL]).
|
|
69
|
+
//
|
|
70
|
+
// Read here so a selection change re-registers the layer and the canvas
|
|
71
|
+
// repaints — the same plumbing `<BarChart>` uses. Reference-stable when
|
|
72
|
+
// nothing names this layer, so an unrelated selection elsewhere in the
|
|
73
|
+
// container neither re-identifies this entry nor repaints it.
|
|
74
|
+
const selectedEntries = container.selected;
|
|
75
|
+
const hoveredEntries = container.hovered;
|
|
76
|
+
// The committed spans, plus the **live** ones of a sweep in flight. A
|
|
77
|
+
// previewed span draws exactly as a committed one, so releasing changes
|
|
78
|
+
// nothing visually — the preview cannot promise a picture the commit does not
|
|
79
|
+
// deliver. The live channel wins while it is non-empty, because during a drag
|
|
80
|
+
// it IS the current answer.
|
|
81
|
+
const previewing = container.previewSpans.length > 0;
|
|
82
|
+
const allSpans = previewing
|
|
83
|
+
? container.previewSpans
|
|
84
|
+
: container.selectedSpans;
|
|
85
|
+
const traceState = useMemo(() => {
|
|
86
|
+
if (id === undefined)
|
|
87
|
+
return 'rest';
|
|
88
|
+
// A span on THIS layer is handled by the partitioned draw below, not by a
|
|
89
|
+
// whole-series state: the emphasis is a region, not the series.
|
|
90
|
+
if (allSpans.some((sp) => sp.id === id))
|
|
91
|
+
return 'rest';
|
|
92
|
+
const mine = (e) => e.id === id;
|
|
93
|
+
if (selectedEntries.some(mine))
|
|
94
|
+
return 'selected';
|
|
95
|
+
if (hoveredEntries.some(mine))
|
|
96
|
+
return 'hover';
|
|
97
|
+
// Something else is selected ⇒ recede. Nothing dims while the selection is
|
|
98
|
+
// empty: with nothing selected there is nothing to recede *from*, the same
|
|
99
|
+
// rule `BarStyle.dimmed` states for the marks.
|
|
100
|
+
if (selectedEntries.length > 0 || allSpans.length > 0)
|
|
101
|
+
return 'dimmed';
|
|
102
|
+
return 'rest';
|
|
103
|
+
}, [id, selectedEntries, hoveredEntries, allSpans]);
|
|
104
|
+
// The swept window on this layer, in **key units** — mapped to pixels at draw
|
|
105
|
+
// time, because that is when the scale is known.
|
|
106
|
+
// **`spanColor` only when this is the ONLY swept trace.** The hue is
|
|
107
|
+
// justified by identity not being in question inside a single series — but
|
|
108
|
+
// sweep two traces and both would go blue, so inside the window you could no
|
|
109
|
+
// longer tell them apart, which is the very thing the rule exists to prevent.
|
|
110
|
+
// With more than one, the window thickens and every trace keeps its colour.
|
|
111
|
+
const soleSpannedTrace = allSpans.length === 1;
|
|
112
|
+
const spanX = useMemo(() => {
|
|
113
|
+
if (id === undefined)
|
|
114
|
+
return null;
|
|
115
|
+
const mine = allSpans.find((sp) => sp.id === id);
|
|
116
|
+
return mine === undefined ? null : mine.x;
|
|
117
|
+
}, [id, allSpans]);
|
|
67
118
|
const entry = useMemo(() => ({
|
|
68
119
|
layer: {
|
|
69
120
|
as: semantic,
|
|
@@ -72,6 +123,44 @@ export function LineChart({ series, column, readout, as: semantic, axis, curve,
|
|
|
72
123
|
// its layers: a ValueSeries plots on a value axis, a TimeSeries on time.
|
|
73
124
|
xKind: series instanceof ValueSeries ? 'value' : 'time',
|
|
74
125
|
xExtent: () => cs.length === 0 ? null : [cs.x[0], cs.x[cs.length - 1]],
|
|
126
|
+
// ── Selection, gated on `id` exactly as every other layer ([PND-TRACESEL]).
|
|
127
|
+
...(id === undefined
|
|
128
|
+
? {}
|
|
129
|
+
: {
|
|
130
|
+
// A trace is 1-D in x: the value axis says nothing about what a
|
|
131
|
+
// drag covered, so no rect and no y window.
|
|
132
|
+
sweepsRect: false,
|
|
133
|
+
sweepAxis: 'x',
|
|
134
|
+
sweepSpanOnly: true,
|
|
135
|
+
hitTest: (px, py, xScale, yScale) => {
|
|
136
|
+
const i = traceHitIndex(cs, px, py, xScale, yScale);
|
|
137
|
+
if (i === null)
|
|
138
|
+
return null;
|
|
139
|
+
return {
|
|
140
|
+
id,
|
|
141
|
+
// **Series-scoped**: no sample was selected, because a
|
|
142
|
+
// sample is not a mark. `NaN` is what that already means
|
|
143
|
+
// (see `SelectInfo.key`), and the stable `mark` below is
|
|
144
|
+
// what gives the entry an identity — `sameMark` prefers it
|
|
145
|
+
// over `key`, so two clicks anywhere on the trace are the
|
|
146
|
+
// same selection and re-clicking deselects. Without the
|
|
147
|
+
// `mark` they never would: `NaN !== NaN`.
|
|
148
|
+
key: NaN,
|
|
149
|
+
value: NaN,
|
|
150
|
+
color: style.color,
|
|
151
|
+
label,
|
|
152
|
+
mark: label,
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
beginSweep: () => cs.length === 0
|
|
156
|
+
? null
|
|
157
|
+
: sweepSpan({
|
|
158
|
+
id,
|
|
159
|
+
// Clamped to the trace's own span, so a drag off the end
|
|
160
|
+
// does not commit a range the series never covered.
|
|
161
|
+
bounds: [cs.x[0], cs.x[cs.length - 1]],
|
|
162
|
+
}),
|
|
163
|
+
}),
|
|
75
164
|
sampleAt: (x) => {
|
|
76
165
|
// No readout past the data (tracker policy — nearest clamps to an
|
|
77
166
|
// endpoint outside the span); bounds from the columnar x axis.
|
|
@@ -122,7 +211,61 @@ export function LineChart({ series, column, readout, as: semantic, axis, curve,
|
|
|
122
211
|
]
|
|
123
212
|
: [];
|
|
124
213
|
},
|
|
125
|
-
draw: (ctx, xScale, yScale) =>
|
|
214
|
+
draw: (ctx, xScale, yScale) => {
|
|
215
|
+
const stroke = (st, alpha, only) => () => {
|
|
216
|
+
const prior = ctx.globalAlpha;
|
|
217
|
+
const priorCap = ctx.lineCap;
|
|
218
|
+
if (alpha !== 1)
|
|
219
|
+
ctx.globalAlpha = prior * alpha;
|
|
220
|
+
// Round the emphasised segment's ends. Only meaningful on a sliced
|
|
221
|
+
// path, whose endpoints ARE the window's — a clipped stroke is
|
|
222
|
+
// sheared vertically and no cap shows.
|
|
223
|
+
if (only !== undefined)
|
|
224
|
+
ctx.lineCap = 'round';
|
|
225
|
+
const out = drawLine(ctx, only ?? cs, xScale, yScale, st, curveFactory, gaps, gapConnectorOpacity, sessionBreakInstants, decimate);
|
|
226
|
+
ctx.globalAlpha = prior;
|
|
227
|
+
ctx.lineCap = priorCap;
|
|
228
|
+
return out;
|
|
229
|
+
};
|
|
230
|
+
// No window on this layer ⇒ one pass, in the series' own state.
|
|
231
|
+
if (spanX === null) {
|
|
232
|
+
const [st, alpha] = traceStateStyle(style, traceState);
|
|
233
|
+
return stroke(st, alpha)();
|
|
234
|
+
}
|
|
235
|
+
// A window: the trace outside it recedes and the portion inside is
|
|
236
|
+
// emphasised — the trace's answer to lighting the covered marks.
|
|
237
|
+
// `spanColor` is the one hue a trace's state may take, because inside
|
|
238
|
+
// a single series identity is not in question; with none themed the
|
|
239
|
+
// window just thickens.
|
|
240
|
+
// EXPERIMENT: annotation-register rules at the window's edges,
|
|
241
|
+
// underneath the trace ink (drawn first). See `strokeSpanEdges`.
|
|
242
|
+
//
|
|
243
|
+
// **Committed spans only.** While the drag is live the brush band
|
|
244
|
+
// already strokes its own edges at the same two x positions, so
|
|
245
|
+
// drawing these too put two rules a fraction of a pixel apart on each
|
|
246
|
+
// boundary — which read as one muddy smear rather than as either. The
|
|
247
|
+
// handoff is the honest reading anyway: the band is the gesture's
|
|
248
|
+
// mark and belongs to the drag; these preview the annotation you
|
|
249
|
+
// would get, and belong to the result.
|
|
250
|
+
if (!previewing)
|
|
251
|
+
strokeSpanEdges(ctx, [xScale(spanX[0]), xScale(spanX[1])], ctx.canvas.height, container.theme.annotation?.spanEdge ?? '#f0b26b');
|
|
252
|
+
const [outStyle, outAlpha] = traceStateStyle(style, 'dimmed');
|
|
253
|
+
const [inStyle] = traceStateStyle(style, 'selected');
|
|
254
|
+
// The emphasised pass strokes a **slice** of the trace rather than
|
|
255
|
+
// the whole thing clipped, so its ends are real path ends and can be
|
|
256
|
+
// rounded. With nothing of the trace inside the window there is
|
|
257
|
+
// nothing to emphasise, and the muted pass alone is the picture.
|
|
258
|
+
const inner = sliceTrace(cs, spanX[0], spanX[1]);
|
|
259
|
+
const inInk = style.spanColor === undefined || !soleSpannedTrace
|
|
260
|
+
? inStyle
|
|
261
|
+
: { ...inStyle, color: style.spanColor };
|
|
262
|
+
return drawPartitioned(ctx, [xScale(spanX[0]), xScale(spanX[1])], plotExtentOf(ctx, xScale, yScale).height, stroke(outStyle, outAlpha), inner === null
|
|
263
|
+
? () => ({ sourceCount: 0, drawnCount: 0, decimated: false })
|
|
264
|
+
: stroke(inInk, 1, inner), false,
|
|
265
|
+
// The round cap overhangs the boundary by half its width; keep the
|
|
266
|
+
// muted trace out from under it.
|
|
267
|
+
inInk.width / 2, plotExtentOf(ctx, xScale, yScale).width);
|
|
268
|
+
},
|
|
126
269
|
},
|
|
127
270
|
axisId: axis,
|
|
128
271
|
index,
|
|
@@ -140,6 +283,11 @@ export function LineChart({ series, column, readout, as: semantic, axis, curve,
|
|
|
140
283
|
sessionBreakInstants,
|
|
141
284
|
decimate,
|
|
142
285
|
axis,
|
|
286
|
+
id,
|
|
287
|
+
traceState,
|
|
288
|
+
spanX,
|
|
289
|
+
soleSpannedTrace,
|
|
290
|
+
previewing,
|
|
143
291
|
index,
|
|
144
292
|
]);
|
|
145
293
|
// A stable per-instance slot (see useSlotKey) keeps this layer's z-position
|
|
@@ -159,6 +307,19 @@ export function LineChart({ series, column, readout, as: semantic, axis, curve,
|
|
|
159
307
|
useEffect(() => {
|
|
160
308
|
registerTrackerSource(slot, entry.layer);
|
|
161
309
|
}, [registerTrackerSource, slot, entry.layer]);
|
|
310
|
+
// Advertise selectability (only when an `id` was given) — the same
|
|
311
|
+
// registration `<BarChart>`/`<ScatterChart>`/`<BoxPlot>`/`<HeatMap>` make.
|
|
312
|
+
// A trace became selectable in [PND-TRACESEL] but never joined this set, so
|
|
313
|
+
// the container's "wired but nothing is selectable" guard fired on every
|
|
314
|
+
// trace-only chart that *was* correctly wired, and told the consumer to add
|
|
315
|
+
// an `id` to a mark layer they hadn't mounted.
|
|
316
|
+
const { registerSelectable, unregisterSelectable } = container;
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
if (id === undefined)
|
|
319
|
+
return;
|
|
320
|
+
registerSelectable(slot);
|
|
321
|
+
return () => unregisterSelectable(slot);
|
|
322
|
+
}, [registerSelectable, unregisterSelectable, slot, id]);
|
|
162
323
|
// And a legend row: the readout identity + the resolved line style, so a
|
|
163
324
|
// `<Legend>` swatch can never drift from what the canvas draws.
|
|
164
325
|
const legendRows = useMemo(() => {
|
package/dist/ListTable.d.ts
CHANGED
|
@@ -12,22 +12,49 @@
|
|
|
12
12
|
* shared shell can evolve without a compatibility contract.
|
|
13
13
|
*/
|
|
14
14
|
import { type ReactNode } from 'react';
|
|
15
|
+
import type { SelectModifiers } from './context.js';
|
|
15
16
|
import type { ListCellSpec, ListRow } from './list.js';
|
|
16
17
|
import type { ChartTheme } from './theme.js';
|
|
18
|
+
/**
|
|
19
|
+
* A row's interaction state, handed to {@link ListTableProps.renderGlyphs} so
|
|
20
|
+
* the glyphs can follow it — the fill is the one channel the shell cannot
|
|
21
|
+
* paint for them.
|
|
22
|
+
*
|
|
23
|
+
* `dimmed` is derived, not passed in: it means *something else* is selected.
|
|
24
|
+
* Nothing dims while the selection is empty, because with nothing selected
|
|
25
|
+
* there is nothing to recede from — the same rule `BarStyle.dimmed` states
|
|
26
|
+
* for the canvas.
|
|
27
|
+
*/
|
|
28
|
+
export interface ListRowState {
|
|
29
|
+
readonly selected: boolean;
|
|
30
|
+
readonly hovered: boolean;
|
|
31
|
+
readonly dimmed: boolean;
|
|
32
|
+
}
|
|
17
33
|
export interface ListTableProps<R extends ListRow> {
|
|
18
34
|
/** Rows in display order (the caller sorts). */
|
|
19
35
|
readonly rows: readonly R[];
|
|
20
36
|
/** Which sister is rendering — stamped as `data-list` for styling/tests. */
|
|
21
37
|
readonly kind: 'bar' | 'box';
|
|
22
38
|
/** The glyph cell's content for one row (the bar / box lines). */
|
|
23
|
-
readonly renderGlyphs: (row: R) => ReactNode;
|
|
39
|
+
readonly renderGlyphs: (row: R, state: ListRowState) => ReactNode;
|
|
24
40
|
readonly before?: readonly ListCellSpec<R>[] | undefined;
|
|
25
41
|
readonly after?: readonly ListCellSpec<R>[] | undefined;
|
|
26
42
|
readonly renderExpanded?: ((row: R) => ReactNode) | undefined;
|
|
27
43
|
readonly defaultExpanded?: readonly string[] | undefined;
|
|
28
44
|
readonly onExpandToggle?: ((key: string, expanded: boolean) => void) | undefined;
|
|
29
|
-
|
|
45
|
+
/** Selected row(s) — one key, a set of them, or nothing. Widened to match
|
|
46
|
+
* {@link ListTableProps.hovered}; see `<BarList selected>`. */
|
|
47
|
+
readonly selected?: string | readonly string[] | null | undefined;
|
|
30
48
|
readonly onRowClick?: ((row: R) => void) | undefined;
|
|
49
|
+
/** Plural select — a click's one row, or a drag's run. See `<BarList
|
|
50
|
+
* onRowSelect>`; mounting it is what enables the drag. */
|
|
51
|
+
readonly onRowSelect?: ((rows: readonly R[], modifiers: SelectModifiers) => void) | undefined;
|
|
52
|
+
/** Controlled hover — one row key, a set of them, or nothing. Omitted ⇒
|
|
53
|
+
* uncontrolled (the shell tracks the pointer itself, as it always has). */
|
|
54
|
+
readonly hovered?: string | readonly string[] | null | undefined;
|
|
55
|
+
/** Hover out: the entered row, or `null` on leaving every row. Fires in
|
|
56
|
+
* controlled and uncontrolled mode alike, deduped by row key. */
|
|
57
|
+
readonly onHover?: ((row: R | null) => void) | undefined;
|
|
31
58
|
readonly divided?: boolean | undefined;
|
|
32
59
|
/** Draw the vertical **baseline rule** at the scale origin (the glyph
|
|
33
60
|
* cell's left edge) — the shared reference the eye aligns rows against. */
|
|
@@ -47,5 +74,5 @@ export interface ListTableProps<R extends ListRow> {
|
|
|
47
74
|
/** The shared text ink: the band-label tone when the theme has one (stronger
|
|
48
75
|
* than tick labels — these cells are primary content), else the tick ink. */
|
|
49
76
|
export declare function listInk(theme: ChartTheme): string;
|
|
50
|
-
export declare function ListTable<R extends ListRow>({ rows, kind, renderGlyphs, before, after, renderExpanded, defaultExpanded, onExpandToggle, selected, onRowClick, divided, baseline, markers, theme, }: ListTableProps<R>): import("react/jsx-runtime").JSX.Element;
|
|
77
|
+
export declare function ListTable<R extends ListRow>({ rows, kind, renderGlyphs, before, after, renderExpanded, defaultExpanded, onExpandToggle, selected, onRowClick, onRowSelect, hovered, onHover, divided, baseline, markers, theme, }: ListTableProps<R>): import("react/jsx-runtime").JSX.Element;
|
|
51
78
|
//# sourceMappingURL=ListTable.d.ts.map
|