@svgrid/grid 3.0.1 → 3.0.3

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 (77) hide show
  1. package/dist/GridFooter.svelte +14 -5
  2. package/dist/GridFooter.svelte.d.ts +8 -0
  3. package/dist/GridMenus.svelte +18 -10
  4. package/dist/GridMenus.svelte.d.ts +2 -1
  5. package/dist/SvGrid.controller.svelte.d.ts +17 -0
  6. package/dist/SvGrid.controller.svelte.js +128 -14
  7. package/dist/SvGrid.css +79 -10
  8. package/dist/SvGrid.svelte +191 -186
  9. package/dist/SvGrid.types.d.ts +42 -1
  10. package/dist/SvGridChart.svelte +571 -41
  11. package/dist/SvGridChart.svelte.d.ts +63 -1
  12. package/dist/SvGridChartPanel.svelte +169 -21
  13. package/dist/SvGridChartView.svelte +9 -0
  14. package/dist/SvGridChartView.svelte.d.ts +7 -0
  15. package/dist/SvGroupCell.svelte +28 -3
  16. package/dist/SvGroupCell.svelte.d.ts +8 -0
  17. package/dist/SvRowGroupPanel.svelte +20 -4
  18. package/dist/SvRowGroupPanel.svelte.d.ts +8 -0
  19. package/dist/ai.d.ts +11 -2
  20. package/dist/ai.js +51 -7
  21. package/dist/cdn/GridMenus-CHOMnW-c.js +602 -0
  22. package/dist/cdn/{GridMenus-DFB6iwF8.js → GridMenus-DhdPF700.js} +152 -150
  23. package/dist/cdn/SvGridChart-1PMSp2LZ.js +1481 -0
  24. package/dist/cdn/SvGridChart-D02avhyr.js +1480 -0
  25. package/dist/cdn/SvGridChartPanel-DJnViOv4.js +834 -0
  26. package/dist/cdn/SvGridChartPanel-vPTNerFZ.js +810 -0
  27. package/dist/cdn/{SvGridChartView-BhUEJ5ki.js → SvGridChartView-C--HhdUo.js} +5 -3
  28. package/dist/cdn/{SvGridChartView-00LPUHL1.js → SvGridChartView-KyyFG-wY.js} +5 -3
  29. package/dist/cdn/cell-formatting-C2Hf5gqd.js +86 -0
  30. package/dist/cdn/chart-DLg3_zTQ.js +1652 -0
  31. package/dist/cdn/{export-format-Cv1Dll6k.js → export-format-CUDLy2yn.js} +84 -168
  32. package/dist/cdn/{src-C8QjSaq-.js → src-Bugf5XlI.js} +3608 -3414
  33. package/dist/cdn/{src-D0hO2eYN.js → src-D6XvA1Ij.js} +8617 -8423
  34. package/dist/cdn/svgrid.js +16 -15
  35. package/dist/cdn/svgrid.svelte-external.js +16 -15
  36. package/dist/cell-formatting.d.ts +7 -0
  37. package/dist/cell-formatting.js +7 -1
  38. package/dist/chart-export.d.ts +23 -2
  39. package/dist/chart-export.js +80 -6
  40. package/dist/chart.d.ts +410 -18
  41. package/dist/chart.js +824 -24
  42. package/dist/grid-icons.d.ts +49 -0
  43. package/dist/grid-icons.js +86 -0
  44. package/dist/index.d.ts +3 -2
  45. package/dist/index.js +3 -2
  46. package/package.json +11 -11
  47. package/src/GridFooter.svelte +14 -5
  48. package/src/GridMenus.svelte +18 -10
  49. package/src/SvGrid.controller.svelte.ts +146 -13
  50. package/src/SvGrid.css +79 -10
  51. package/src/SvGrid.svelte +191 -186
  52. package/src/SvGrid.types.ts +42 -1
  53. package/src/SvGridChart.svelte +571 -41
  54. package/src/SvGridChart.test.ts +243 -1
  55. package/src/SvGridChartPanel.svelte +169 -21
  56. package/src/SvGridChartView.svelte +9 -0
  57. package/src/SvGroupCell.svelte +28 -3
  58. package/src/SvRowGroupPanel.svelte +20 -4
  59. package/src/ai.test.ts +60 -1
  60. package/src/ai.ts +59 -6
  61. package/src/cell-formatting.ts +7 -1
  62. package/src/chart-export.test.ts +112 -0
  63. package/src/chart-export.ts +76 -8
  64. package/src/chart.test.ts +830 -1
  65. package/src/chart.ts +1053 -32
  66. package/src/grid-icons.test.ts +46 -0
  67. package/src/grid-icons.ts +184 -0
  68. package/src/icon-overrides.grid.test.ts +188 -0
  69. package/src/icon-seam.test.ts +100 -0
  70. package/src/index.ts +19 -0
  71. package/src/svgrid.charting.test.ts +120 -0
  72. package/dist/cdn/GridMenus-CYzOvmNQ.js +0 -600
  73. package/dist/cdn/SvGridChart-BEJmNNx9.js +0 -1203
  74. package/dist/cdn/SvGridChart-BwVos976.js +0 -1202
  75. package/dist/cdn/SvGridChartPanel-BOknOkrP.js +0 -561
  76. package/dist/cdn/SvGridChartPanel-D2PjII4O.js +0 -585
  77. package/dist/cdn/chart-i4XcXyHJ.js +0 -1214
package/dist/chart.d.ts CHANGED
@@ -1,14 +1,27 @@
1
- /**
2
- * Integrated chart geometry. Pure functions that turn categories + numeric
3
- * series into SVG primitives - the "chart from a grid range" enterprise
4
- * feature without bundling a charting library. The `<SvGridChart>` component
5
- * paints the result; this module has no DOM so it is unit-testable.
6
- *
7
- * Supports: grouped + stacked bars, line, area, pie/donut, combo charts
8
- * (per-series type), a secondary (right) Y axis, signed Y domains (negative
9
- * values drop below a zero baseline), and nice auto-scaled ticks.
10
- */
11
- export type ChartType = 'bar' | 'line' | 'area' | 'pie' | 'scatter' | 'heatmap' | 'waterfall' | 'funnel' | 'radar' | 'calendar' | 'gauge' | 'treemap' | 'sankey';
1
+ /** Every mark this engine can draw. `bar`, `line` and `area` compose (a series
2
+ * can override the spec's type for a combo chart); the rest are whole-chart
3
+ * types that ignore per-series overrides. */
4
+ export type ChartType = 'bar' | 'line' | 'area' | 'pie' | 'scatter' | 'heatmap' | 'waterfall' | 'funnel' | 'radar' | 'calendar' | 'gauge' | 'treemap' | 'sankey' | 'candlestick' | 'ohlc' | 'boxplot';
5
+ /** One open / high / low / close bar. */
6
+ export type OhlcBar = {
7
+ o: number;
8
+ h: number;
9
+ l: number;
10
+ c: number;
11
+ };
12
+ /** A five-number summary: one box, its whiskers, and anything past them.
13
+ * `min` / `max` are the WHISKER ENDS, not the extremes of the sample - with
14
+ * the usual 1.5 IQR rule those differ, and the points beyond go in
15
+ * `outliers` so they can be drawn individually. */
16
+ export type BoxStats = {
17
+ min: number;
18
+ q1: number;
19
+ median: number;
20
+ q3: number;
21
+ max: number;
22
+ /** Values outside the whiskers, drawn as individual points. */
23
+ outliers?: number[];
24
+ };
12
25
  /** A clicked bar / point / slice - the payload of `SvGridChart`'s `onSelect`.
13
26
  * `rowIds` is populated when the spec was built from grid rows (via
14
27
  * `rowsToChartSpec`) and lets a drill handler filter the grid back to the
@@ -40,7 +53,43 @@ export type ChartSeries = {
40
53
  values: number[];
41
54
  color?: string;
42
55
  /** Per-series chart type, for combo charts. Defaults to the spec `type`. */
43
- type?: 'bar' | 'line' | 'area';
56
+ type?: 'bar' | 'line' | 'area' | 'candlestick' | 'ohlc' | 'boxplot';
57
+ /**
58
+ * Open / high / low / close per category, parallel to `categories`. `null`
59
+ * is a gap (a day with no session) and draws nothing.
60
+ *
61
+ * Set `values` to the CLOSING prices alongside this. Everything that reads a
62
+ * series generically reads `values` - the tooltip rows, the CSV export, the
63
+ * screen-reader table, and `overlay` - so filling it in is what lets a
64
+ * candlestick series carry a moving average (`overlay: 'sma:20'`) or export
65
+ * to CSV without a single line of candle-specific code.
66
+ */
67
+ ohlc?: Array<OhlcBar | null>;
68
+ /**
69
+ * Five-number summaries per category, parallel to `categories`. `null` is a
70
+ * gap and draws nothing.
71
+ *
72
+ * Set `values` to the MEDIANS alongside this, for exactly the reason `ohlc`
73
+ * sets them to the closes: everything that reads a series generically reads
74
+ * `values`, so the tooltip rows, the CSV export, the screen-reader table and
75
+ * `overlay` all keep working with no box-specific code.
76
+ *
77
+ * `boxStats()` turns a raw sample into one of these.
78
+ */
79
+ boxes?: Array<BoxStats | null>;
80
+ /**
81
+ * Symmetric or asymmetric error bars, parallel to `values`. A number is a
82
+ * symmetric +/- margin; a pair is an explicit low/high; `null` draws nothing.
83
+ *
84
+ * These are an ANNOTATION on an existing mark rather than a mark of their
85
+ * own, so they compose: a bar, line, area or scatter series can carry them
86
+ * without changing its type. That is the whole reason they are not a
87
+ * `ChartType` - "bar chart with error bars" should not be a different chart.
88
+ */
89
+ errors?: Array<number | {
90
+ lo: number;
91
+ hi: number;
92
+ } | null>;
44
93
  /** Plot against the left (default) or right Y axis. */
45
94
  axis?: 'left' | 'right';
46
95
  /** Scatter / bubble points (used when `type === 'scatter'`). */
@@ -114,6 +163,16 @@ export type ChartSpec = {
114
163
  /** Number format for the value axis, tooltips, data labels and reference
115
164
  * lines. Unset = the default compact `1.2k` / `1.2M` style. */
116
165
  valueFormat?: ChartValueFormat;
166
+ /** BCP-47 locale for value formatting. Setting this (or `currency`) switches
167
+ * formatting to `Intl.NumberFormat`, so thousands separators, the decimal
168
+ * mark and the compact suffixes follow the locale rather than the built-in
169
+ * English `1.2k` / `1.2M`. Unset = the locale-free default, which is why the
170
+ * default output has never changed under anyone's feet. */
171
+ locale?: string | ReadonlyArray<string>;
172
+ /** ISO 4217 code for `valueFormat: 'currency'` (`'EUR'`, `'JPY'`, ...). Unset
173
+ * means the axis reads `$`, which is wrong everywhere outside the dollar
174
+ * zone and was the only currency this chart could draw for a long time. */
175
+ currency?: string;
117
176
  /** Grouped (nested) category axis: a parent tier spanning consecutive leaf
118
177
  * categories (spans must sum to `categories.length`). Vertical category
119
178
  * charts only (ignored for time / horizontal / pie). */
@@ -135,8 +194,18 @@ export type ChartSpec = {
135
194
  innerRadius?: number;
136
195
  /** Horizontal target / goal / average lines. */
137
196
  referenceLines?: ChartReferenceLine[];
138
- /** Treat `categories` as dates -> time-scaled x positions + date ticks. */
139
- xType?: 'category' | 'time';
197
+ /**
198
+ * How to read `categories` along the x axis.
199
+ *
200
+ * - `'category'` (default): evenly spaced labels, taken literally.
201
+ * - `'time'`: parsed as dates and positioned by ACTUAL elapsed time, so an
202
+ * irregular gap renders as a proportional gap.
203
+ * - `'ordinal-time'`: parsed as dates but spaced EVENLY, with date-derived
204
+ * ticks. This is what a series of trading sessions or business days needs:
205
+ * on a true time axis every weekend opens a hole a third as wide as the
206
+ * working week, which is noise rather than information.
207
+ */
208
+ xType?: 'category' | 'time' | 'ordinal-time';
140
209
  /** Axis titles (reserve gutter space + render). */
141
210
  yAxisTitle?: string;
142
211
  y2AxisTitle?: string;
@@ -203,6 +272,13 @@ export type ChartSpec = {
203
272
  negative?: string;
204
273
  total?: string;
205
274
  };
275
+ /** Candlestick / OHLC colors. Direction beats series identity here, the same
276
+ * way `waterfallColors` overrides the series color. Defaults to the green /
277
+ * red pair from the palette's own vocabulary. */
278
+ candleColors?: {
279
+ up?: string;
280
+ down?: string;
281
+ };
206
282
  /** Heatmap color scale. `'sequential'` maps min->max through one hue,
207
283
  * `'diverging'` runs cold->neutral->warm around 0. A custom array
208
284
  * (>=2 hex colors) defines an arbitrary gradient. Default `'sequential'`. */
@@ -367,6 +443,95 @@ export type ChartHeatmapCell = {
367
443
  rowLabel: string;
368
444
  colLabel: string;
369
445
  };
446
+ /**
447
+ * One candlestick / OHLC bar in SVG coordinates.
448
+ *
449
+ * Kept apart from {@link ChartBar} rather than folded into it: bars pick up
450
+ * series pattern fills, data labels and the brush mini-map, and all three are
451
+ * wrong for a candle. A separate array means every existing loop over `bars`
452
+ * keeps working untouched, which is the point of this flat geometry.
453
+ */
454
+ export type ChartCandle = {
455
+ /** Body rect left edge and width. In OHLC mode, the span of the two ticks. */
456
+ x: number;
457
+ w: number;
458
+ /** Wick line, and the OHLC bar's vertical. */
459
+ xCenter: number;
460
+ yOpen: number;
461
+ yClose: number;
462
+ yHigh: number;
463
+ yLow: number;
464
+ /** Body rect, pre-ordered so the renderer does no min/max of its own. */
465
+ bodyY: number;
466
+ bodyH: number;
467
+ /** Close at or above open. Drives colour and hollow-vs-filled. */
468
+ up: boolean;
469
+ color: string;
470
+ label: string;
471
+ series: string;
472
+ o: number;
473
+ h: number;
474
+ l: number;
475
+ c: number;
476
+ };
477
+ /**
478
+ * A laid-out box plot, in SVG coordinates. Its own array for the same reason
479
+ * candles have one: `bars` carries pattern fills, data labels and the brush
480
+ * mini-map, none of which mean anything for a box.
481
+ */
482
+ export type ChartBox = {
483
+ /** Box rect left edge and width. */
484
+ x: number;
485
+ w: number;
486
+ /** Whisker line and the caps, centred on the slot. */
487
+ xCenter: number;
488
+ yMin: number;
489
+ yQ1: number;
490
+ yMedian: number;
491
+ yQ3: number;
492
+ yMax: number;
493
+ /** Box rect, pre-ordered so the renderer does no min/max of its own. */
494
+ boxY: number;
495
+ boxH: number;
496
+ /** Points beyond the whiskers, already positioned. */
497
+ outliers: Array<{
498
+ y: number;
499
+ value: number;
500
+ }>;
501
+ color: string;
502
+ label: string;
503
+ series: string;
504
+ min: number;
505
+ q1: number;
506
+ median: number;
507
+ q3: number;
508
+ max: number;
509
+ };
510
+ /** One positioned error bar: a vertical span with caps, centred on its mark. */
511
+ export type ChartErrorBar = {
512
+ xCenter: number;
513
+ yLo: number;
514
+ yHi: number;
515
+ /** Cap half-width, so the renderer draws the same T at both ends. */
516
+ cap: number;
517
+ color: string;
518
+ label: string;
519
+ series: string;
520
+ lo: number;
521
+ hi: number;
522
+ };
523
+ /**
524
+ * Five-number summary of a raw sample, with the 1.5 IQR whisker rule.
525
+ *
526
+ * Whiskers stop at the last observation INSIDE the fence rather than at the
527
+ * fence itself, which is what makes them read as real data; anything past them
528
+ * comes back in `outliers`. Quartiles use linear interpolation between the two
529
+ * neighbouring order statistics.
530
+ *
531
+ * Returns `null` for an empty sample, so a category with no observations is a
532
+ * gap rather than a box drawn at zero.
533
+ */
534
+ export declare function boxStats(sample: ReadonlyArray<number>, whisker?: number): BoxStats | null;
370
535
  /** A computed bar rectangle in SVG coordinates. Output of {@link buildChart}, not an input. */
371
536
  export type ChartBar = {
372
537
  x: number;
@@ -467,7 +632,41 @@ export type ChartGeometry = {
467
632
  w: number;
468
633
  h: number;
469
634
  };
635
+ /**
636
+ * The value domain each axis was actually drawn against, and the slot width
637
+ * of the category axis. Plain data, deliberately: the geometry stays a
638
+ * serialisable value object, and `chartScales(geo)` turns this into the
639
+ * `xOf` / `yOf` functions a custom mark needs.
640
+ *
641
+ * Null on the types with no cartesian axes (pie, gauge, treemap, sankey,
642
+ * calendar, radar, funnel), which is also how a caller can tell whether
643
+ * drawing into plot coordinates means anything.
644
+ */
645
+ axes: {
646
+ y: {
647
+ min: number;
648
+ max: number;
649
+ log: boolean;
650
+ };
651
+ /** The right axis, when a series is plotted against one. */
652
+ y2: {
653
+ min: number;
654
+ max: number;
655
+ log: boolean;
656
+ } | null;
657
+ /** Horizontal room per category, in px. */
658
+ slot: number;
659
+ /** Number of categories the axis was laid out for. */
660
+ count: number;
661
+ } | null;
470
662
  bars: ChartBar[];
663
+ /** Candlestick / OHLC bars. Empty for every other chart type. */
664
+ candles: ChartCandle[];
665
+ /** Box plots. Empty for every other chart type. */
666
+ boxes: ChartBox[];
667
+ /** Error bars, from any series carrying `errors`. Empty when none do - they
668
+ * annotate whatever mark the series already draws. */
669
+ errorBars: ChartErrorBar[];
471
670
  lines: ChartLine[];
472
671
  slices: ChartPieSlice[];
473
672
  yTicks: ChartAxisTick[];
@@ -580,6 +779,37 @@ export declare function pickContrastText(bgHex: string): string;
580
779
  * the smallest that covers the top, then enumerate decade boundaries. Used
581
780
  * by log-scale axes (yScale: 'log'). */
582
781
  export declare function niceLogScale(min: number, max: number): NiceScale;
782
+ /** The scale functions for a laid-out cartesian chart. See {@link chartScales}. */
783
+ export type ChartScales = {
784
+ /** Pixel x at the centre of category `i`. Fractional indices interpolate,
785
+ * so `xOf(2.5)` is the midpoint between the third and fourth categories. */
786
+ xOf: (index: number) => number;
787
+ /** Pixel y for a value on the left axis (or the right, when asked). Returns
788
+ * NaN for a value the axis cannot express, e.g. zero on a log scale. */
789
+ yOf: (value: number, axis?: 'left' | 'right') => number;
790
+ /** The inverse of `xOf`: which category a pixel x falls on. Clamped. */
791
+ xInvert: (px: number) => number;
792
+ /** The inverse of `yOf`. */
793
+ yInvert: (px: number, axis?: 'left' | 'right') => number;
794
+ };
795
+ /**
796
+ * Turn a laid-out chart's axes into functions, so a caller can draw its own
797
+ * marks in the same coordinates the built-in ones use.
798
+ *
799
+ * This is the custom-series seam. Rather than a registry of mark types, the
800
+ * chart hands over its geometry and its scales and lets the caller render
801
+ * whatever SVG it likes into the plot - which is the Svelte-shaped answer, and
802
+ * means a custom mark is ordinary markup rather than a plugin.
803
+ *
804
+ * Deriving the scale from `geo.axes` matters: the domain a chart drew against
805
+ * is the NICE-ROUNDED one, stretched to include zero for bar charts and any
806
+ * reference lines. Recomputing it from the data outside would land custom marks
807
+ * a few pixels off the built-in ones, in a way that looks like a rendering bug.
808
+ *
809
+ * Returns `null` for a chart with no cartesian axes (pie, gauge, treemap,
810
+ * sankey, calendar, radar, funnel), where plot coordinates mean nothing.
811
+ */
812
+ export declare function chartScales(geo: ChartGeometry): ChartScales | null;
583
813
  /** Build an SVG path from a list of (x,y) pairs, optionally smoothed via
584
814
  * monotone cubic interpolation (preserves local extrema - no overshoots).
585
815
  * Breaks the path at `defined === false` gaps. */
@@ -604,19 +834,62 @@ export declare function computeOverlay(values: number[], spec: SeriesOverlay): n
604
834
  export declare function niceScale(min: number, max: number, tickCount?: number): NiceScale;
605
835
  /** Value-axis / tooltip / label number format. */
606
836
  export type ChartValueFormat = 'number' | 'currency' | 'percent' | 'compact';
837
+ /** Locale-aware formatting options, a structural subset of `ChartSpec` so a
838
+ * caller inside the engine can pass the spec straight through. */
839
+ export type ChartFormatLocale = {
840
+ locale?: string | ReadonlyArray<string>;
841
+ currency?: string;
842
+ };
607
843
  /**
608
844
  * Format a numeric value for display, honouring an optional `valueFormat`.
609
- * Builds on the compact `1.2k` / `1.2M` base: currency prefixes `$` (sign
610
- * outside), percent multiplies by 100 and suffixes `%`. Unset / `'number'` /
611
- * `'compact'` = the plain compact form.
845
+ *
846
+ * Two modes, on purpose. With no `locale` and no `currency` this is the original
847
+ * locale-free output: the compact `1.2k` / `1.2M` base, currency prefixed with
848
+ * `$` (sign outside), percent multiplied by 100 and suffixed `%`. Set either one
849
+ * and it switches to `Intl.NumberFormat`, so separators, the decimal mark and the
850
+ * compact suffixes all follow the locale.
851
+ *
852
+ * Keeping the old path as the default is deliberate rather than lazy. `Intl`'s
853
+ * compact notation is not the same string even for `en-US` (`1.2K`, capital),
854
+ * so formatting everything through it would silently restyle every axis in every
855
+ * existing chart. Opting in is the only version of this that is not a surprise.
856
+ */
857
+ export declare function formatChartValue(n: number, format?: ChartValueFormat, opts?: ChartFormatLocale): string;
858
+ /**
859
+ * Tick positions for an ordinal (evenly spaced) date axis, as INDICES into
860
+ * `times`.
861
+ *
862
+ * A time axis can put a tick anywhere, because x is a function of the
863
+ * timestamp. An ordinal axis cannot: x is a function of the index, so a tick
864
+ * has to land on a point that exists. This picks the first point of each
865
+ * calendar unit - day, week, month, year, whichever gets closest to `target`
866
+ * ticks without going over - so labels sit on real sessions and a weekend or a
867
+ * holiday never stretches the spacing.
612
868
  */
613
- export declare function formatChartValue(n: number, format?: ChartValueFormat): string;
869
+ export declare function ordinalDateTicks(times: number[], target?: number): number[];
614
870
  /**
615
871
  * Lay out a {@link ChartSpec} into renderable {@link ChartGeometry} - scales,
616
872
  * ticks, and the position of every bar, line, slice and dot. Pure: no DOM, so
617
873
  * it runs during SSR and can be unit-tested directly.
618
874
  */
619
875
  export declare function buildChart(spec: ChartSpec, theme?: 'light' | 'dark'): ChartGeometry;
876
+ /**
877
+ * Narrow a spec to the category window `[lo, hi]`, keeping every
878
+ * category-parallel array in step.
879
+ *
880
+ * This is the zoom / brush slice. It lives here rather than in the renderer
881
+ * because getting it wrong is a MODEL bug, not a paint bug, and it was wrong:
882
+ * the component used to slice `categories`, `values` and `rowIds` by hand and
883
+ * spread the rest of the series through untouched. `upperValues` and
884
+ * `lowerValues` therefore kept their full length, the equality guard on the
885
+ * confidence band (see `buildChart`) stopped matching, and the band silently
886
+ * disappeared the moment anyone zoomed.
887
+ *
888
+ * The lesson generalises: every array here is indexed by category, so each one
889
+ * added in future has to be sliced too. Keeping them in one function is what
890
+ * makes that a single place to remember rather than a scattered convention.
891
+ */
892
+ export declare function sliceChartWindow(spec: ChartSpec, lo: number, hi: number): ChartSpec;
620
893
  /**
621
894
  * Aggregate flat rows into a chart spec. Group by a category field, reduce a
622
895
  * value field per group. Three multi-series shapes:
@@ -649,3 +922,122 @@ export declare function rowsToChartSpec<T extends Record<string, unknown>>(rows:
649
922
  * the source rows. */
650
923
  idField?: keyof T & string;
651
924
  }): ChartSpec;
925
+ /**
926
+ * Reshape an aggregated spec into a tree-map hierarchy.
927
+ *
928
+ * One series gives a flat set of leaves. Several (a split-by) give two levels,
929
+ * category above series, which is the shape people expect from "sales by
930
+ * region, split by channel".
931
+ */
932
+ export declare function specToTreemap(spec: ChartSpec, rootName?: string): TreeNode;
933
+ /**
934
+ * Reshape an aggregated spec into calendar samples.
935
+ *
936
+ * Categories that do not parse as a date are dropped rather than rendered at
937
+ * epoch zero, which would put a stray cell in 1970 and rescale the whole year.
938
+ */
939
+ export declare function specToCalendar(spec: ChartSpec): Array<{
940
+ date: string;
941
+ value: number;
942
+ }>;
943
+ /**
944
+ * Reshape a pivoted spec into sankey nodes and links.
945
+ *
946
+ * The pivot `rowsToChartSpec` already performs is exactly an edge list read
947
+ * sideways: categories are sources, series are targets, and each cell is the
948
+ * flow between them. Zero cells and self-edges are dropped, the first because
949
+ * a zero-width ribbon is not a flow and the second because the layout has no
950
+ * meaningful place to put one.
951
+ */
952
+ export declare function specToSankey(spec: ChartSpec): {
953
+ nodes: Array<{
954
+ id: string;
955
+ label?: string;
956
+ }>;
957
+ links: Array<{
958
+ source: string;
959
+ target: string;
960
+ value: number;
961
+ }>;
962
+ };
963
+ /**
964
+ * The chart types that read ROWS directly instead of a grouped grid, behind one
965
+ * call. Returns `null` for every other type, which then goes through
966
+ * `rowsToChartSpec` and its reduce / sort / topN / "Other" pipeline.
967
+ *
968
+ * One entry point rather than a branch per type in the caller, because the
969
+ * caller is the grid controller and the controller is in the BASE bundle: every
970
+ * type named there is bytes paid by grids that never chart. Here it is in the
971
+ * lazy chart chunk, next to the builders it dispatches to, and adding a fourth
972
+ * direct type costs a grid nothing.
973
+ */
974
+ export declare function rowsToDirectSpec<T extends Record<string, unknown>>(type: ChartType, rows: ReadonlyArray<T>, opts: {
975
+ category?: string;
976
+ /** The measure. For scatter this is X. */
977
+ value?: string;
978
+ /** Scatter's Y measure. */
979
+ value2?: string;
980
+ series?: string;
981
+ reduce?: 'sum' | 'avg' | 'count';
982
+ palette?: string[];
983
+ }): ChartSpec | null;
984
+ /**
985
+ * Build a box plot spec straight from rows: group by a category, then reduce
986
+ * each group to a five-number summary.
987
+ *
988
+ * This is the one aggregate the panel's `sum | avg | count` cannot express, and
989
+ * that is the point of it. Every other chart answers "how much"; a box plot
990
+ * answers "how spread out", which needs the whole sample per group rather than
991
+ * one number, so it cannot go through `rowsToChartSpec`.
992
+ *
993
+ * `values` comes out as the medians, so tooltips, CSV and overlays work with no
994
+ * box-specific code - the same contract `ohlc` follows.
995
+ */
996
+ export declare function rowsToBoxSpec<T extends Record<string, unknown>>(rows: ReadonlyArray<T>, opts: {
997
+ category: keyof T & string;
998
+ value: keyof T & string;
999
+ /** One box series per distinct value of this field, side by side. */
1000
+ series?: keyof T & string;
1001
+ seriesLabel?: string;
1002
+ /** Whisker length in IQRs. Default 1.5. */
1003
+ whisker?: number;
1004
+ width?: number;
1005
+ height?: number;
1006
+ }): ChartSpec;
1007
+ /**
1008
+ * Build a scatter / bubble spec straight from rows.
1009
+ *
1010
+ * Unlike the adapters above this cannot reuse `rowsToChartSpec`: a scatter
1011
+ * point is one row, not one group, so there is nothing to reduce. `series`
1012
+ * colours the points by a categorical field.
1013
+ */
1014
+ export declare function rowsToScatterSpec<T extends Record<string, unknown>>(rows: ReadonlyArray<T>, opts: {
1015
+ x: keyof T & string;
1016
+ y: keyof T & string;
1017
+ /** Bubble radius field. Omit for a plain scatter. */
1018
+ r?: keyof T & string;
1019
+ /** Group points into one series per distinct value. */
1020
+ series?: keyof T & string;
1021
+ /** Per-point label, shown in the tooltip. */
1022
+ label?: keyof T & string;
1023
+ palette?: string[];
1024
+ width?: number;
1025
+ height?: number;
1026
+ }): ChartSpec;
1027
+ /**
1028
+ * Reduce rows to the single number a gauge shows.
1029
+ *
1030
+ * There is no category axis here, which is why this cannot go through
1031
+ * `rowsToChartSpec`. The dial ends on a nice round number rather than exactly
1032
+ * the value, so the needle never sits pinned at the far end of the arc.
1033
+ */
1034
+ export declare function rowsToGaugeSpec<T extends Record<string, unknown>>(rows: ReadonlyArray<T>, opts: {
1035
+ value: keyof T & string;
1036
+ reduce?: 'sum' | 'avg' | 'count';
1037
+ min?: number;
1038
+ max?: number;
1039
+ unit?: string;
1040
+ target?: number;
1041
+ width?: number;
1042
+ height?: number;
1043
+ }): ChartSpec;