@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.
Files changed (85) hide show
  1. package/API.md +576 -0
  2. package/CHANGELOG.md +1213 -1
  3. package/dist/AreaChart.d.ts +12 -1
  4. package/dist/AreaChart.js +131 -13
  5. package/dist/BarChart.d.ts +56 -7
  6. package/dist/BarChart.js +263 -39
  7. package/dist/BarList.d.ts +85 -5
  8. package/dist/BarList.js +25 -4
  9. package/dist/BoxList.d.ts +70 -3
  10. package/dist/BoxList.js +21 -7
  11. package/dist/BoxPlot.d.ts +2 -1
  12. package/dist/BoxPlot.js +101 -9
  13. package/dist/Candlestick.d.ts +13 -1
  14. package/dist/Candlestick.js +89 -3
  15. package/dist/ChartContainer.d.ts +36 -48
  16. package/dist/ChartContainer.js +465 -59
  17. package/dist/ChartRow.d.ts +9 -2
  18. package/dist/ChartRow.js +176 -14
  19. package/dist/HeatMap.d.ts +176 -0
  20. package/dist/HeatMap.js +344 -0
  21. package/dist/Layers.d.ts +5 -1
  22. package/dist/Layers.js +1014 -253
  23. package/dist/Legend.js +8 -4
  24. package/dist/LineChart.d.ts +18 -1
  25. package/dist/LineChart.js +165 -4
  26. package/dist/ListTable.d.ts +30 -3
  27. package/dist/ListTable.js +381 -23
  28. package/dist/ScatterChart.d.ts +3 -2
  29. package/dist/ScatterChart.js +68 -4
  30. package/dist/XAxis.js +40 -22
  31. package/dist/YAxis.d.ts +58 -2
  32. package/dist/YAxis.js +3 -1
  33. package/dist/area.d.ts +34 -1
  34. package/dist/area.js +88 -1
  35. package/dist/bars.d.ts +67 -6
  36. package/dist/bars.js +250 -35
  37. package/dist/box.d.ts +2 -2
  38. package/dist/box.js +158 -40
  39. package/dist/brush.d.ts +142 -0
  40. package/dist/brush.js +179 -0
  41. package/dist/child-index.d.ts +27 -0
  42. package/dist/child-index.js +57 -0
  43. package/dist/context.d.ts +870 -39
  44. package/dist/cursors.d.ts +161 -0
  45. package/dist/cursors.js +503 -0
  46. package/dist/data.d.ts +38 -0
  47. package/dist/data.js +43 -0
  48. package/dist/decimate.d.ts +78 -1
  49. package/dist/decimate.js +157 -0
  50. package/dist/format.d.ts +15 -0
  51. package/dist/format.js +16 -1
  52. package/dist/heat.d.ts +163 -0
  53. package/dist/heat.js +659 -0
  54. package/dist/index.d.ts +13 -4
  55. package/dist/index.js +27 -0
  56. package/dist/line.d.ts +137 -0
  57. package/dist/line.js +328 -0
  58. package/dist/ohlc.d.ts +16 -1
  59. package/dist/ohlc.js +93 -4
  60. package/dist/range.d.ts +14 -1
  61. package/dist/range.js +24 -3
  62. package/dist/scatter.d.ts +17 -9
  63. package/dist/scatter.js +221 -33
  64. package/dist/select.d.ts +13 -5
  65. package/dist/select.js +14 -6
  66. package/dist/selection-fixtures.d.ts +174 -0
  67. package/dist/selection-fixtures.js +569 -0
  68. package/dist/selection-stories.d.ts +73 -0
  69. package/dist/selection-stories.js +301 -0
  70. package/dist/selectors.d.ts +316 -0
  71. package/dist/selectors.js +391 -0
  72. package/dist/span.d.ts +122 -0
  73. package/dist/span.js +203 -0
  74. package/dist/sweep.d.ts +154 -0
  75. package/dist/sweep.js +282 -0
  76. package/dist/theme.d.ts +510 -5
  77. package/dist/theme.js +217 -41
  78. package/dist/tracker.d.ts +6 -0
  79. package/dist/tracker.js +6 -0
  80. package/dist/tradingAxis.fixture.d.ts +78 -0
  81. package/dist/tradingAxis.fixture.js +215 -0
  82. package/dist/useChartLegend.js +18 -3
  83. package/dist/yticks.d.ts +3 -0
  84. package/dist/yticks.js +104 -0
  85. 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
- const selectedId = container?.selected?.id;
116
- const anySelected = selectedId !== undefined && entries.some((it) => it.id === selectedId);
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 && container?.selected?.id === item.id;
158
- const hovered = item.id !== undefined && container?.hovered?.id === item.id;
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',
@@ -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) => drawLine(ctx, cs, xScale, yScale, style, curveFactory, gaps, gapConnectorOpacity, sessionBreakInstants, decimate),
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(() => {
@@ -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
- readonly selected?: string | null | undefined;
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