@kanunilabs/pivotgrid-core 1.6.0 → 1.7.1

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/dist/index.d.ts CHANGED
@@ -164,22 +164,6 @@ interface PivotDictionary {
164
164
  drillDown: string;
165
165
  /** `Label: {count}` — no plural engine, so no locale is ever ungrammatical. */
166
166
  drillDownRecords: string;
167
- /** Chart panel (#214); the eleven shared strings come from DataGrid. */
168
- chart: string;
169
- chartClose: string;
170
- chartFullscreen: string;
171
- chartExitFullscreen: string;
172
- chartEmpty: string;
173
- /** `Showing {shown} of {total}.` — used for categories AND for series. */
174
- chartWindowed: string;
175
- chartTypeColumn: string;
176
- chartTypeBar: string;
177
- chartTypeLine: string;
178
- chartTypeArea: string;
179
- chartTypePie: string;
180
- chartTypeScatter: string;
181
- chartTypePolar: string;
182
- chartTypeCombination: string;
183
167
  /** PDF export header (#215). */
184
168
  exportGeneratedOn: string;
185
169
  /** Designer level tiles and live formula verdict (#220). */
@@ -316,6 +300,310 @@ declare class PivotSelectionModel {
316
300
  private static getBounds;
317
301
  }
318
302
 
303
+ /** How a cartesian chart lays out several series: beside, on top, or as shares of 100. */
304
+ type ChartStacking = 'grouped' | 'stacked' | 'normalized';
305
+ interface StackedSegment {
306
+ /** Where the segment starts, per category. NaN where the series has no value. */
307
+ low: Float64Array;
308
+ /** Where it ends; a line is drawn through these. NaN where the series has no value. */
309
+ high: Float64Array;
310
+ /**
311
+ * The value's percentage of its category's absolute total (`normalized`
312
+ * only; NaN otherwise and where there is no value) — what a tooltip prints
313
+ * next to the raw number.
314
+ */
315
+ share: Float64Array;
316
+ }
317
+ /**
318
+ * Value-axis ticks for a 100% stack: every 25%, ending exactly at 100.
319
+ *
320
+ * A general "nice ticks" routine rounds the domain OUTWARD, and on a 100%
321
+ * stack that drew an axis running to 150% above bars that cannot pass 100
322
+ * (seen in the first visual check, 2026-10-02). `min` is the lowest segment
323
+ * edge — below zero only when some values are negative.
324
+ */
325
+ declare function percentAxisTicks(min: number): number[];
326
+ /**
327
+ * Lay series out on top of one another.
328
+ *
329
+ * `series[s][c]` is the value of series `s` in category `c`. The result is
330
+ * index-aligned with `series`; an excluded series (hidden from the legend)
331
+ * comes back as `null` and takes no room in the stack. Earlier series sit
332
+ * nearer the axis.
333
+ */
334
+ declare function stackSeries(series: ReadonlyArray<ArrayLike<number>>, mode: Exclude<ChartStacking, 'grouped'>, include?: (index: number) => boolean): Array<StackedSegment | null>;
335
+
336
+ /** Where the legend sits around the plot, or `'none'` to hide it. */
337
+ type ChartLegendPosition = 'top' | 'bottom' | 'left' | 'right' | 'none';
338
+ interface ChartFormat {
339
+ /** Shown above the chart, and written into an exported image. */
340
+ title?: string;
341
+ /** Caption under the category axis (the left one for horizontal bars). */
342
+ categoryAxisTitle?: string;
343
+ /** Caption beside the value axis. */
344
+ valueAxisTitle?: string;
345
+ /** Default `'top'`. */
346
+ legend?: ChartLegendPosition;
347
+ /** Print each value on its mark. Default `false`. */
348
+ dataLabels?: boolean;
349
+ /**
350
+ * The value axis: `'linear'` (default) or `'log'` — for values spanning
351
+ * several orders of magnitude, where a linear axis flattens all but the
352
+ * largest. A log axis cannot show zero or a negative value; those marks are
353
+ * left out. It does not apply to a stacked layout, whose segments add up.
354
+ */
355
+ valueScale?: 'linear' | 'log';
356
+ }
357
+ /**
358
+ * Value-axis ticks for a log scale: every power of ten from just below `min`
359
+ * to just above `max` (both > 0). With fewer than two decades the 2 and 5
360
+ * steps in between are added so the axis still has something to read.
361
+ */
362
+ declare function logAxisTicks(min: number, max: number): number[];
363
+ declare const CHART_LEGEND_POSITIONS: readonly ChartLegendPosition[];
364
+ /**
365
+ * A saved format read back defensively — from storage, a report or an older
366
+ * build — keeping only fields of the right kind. Key order is fixed, so two
367
+ * formats with the same content serialise the same.
368
+ */
369
+ declare function readChartFormat(value: unknown): ChartFormat;
370
+ /**
371
+ * What a chart API's image calls take — `getImageDataUrl` and `download` on
372
+ * the DataGrid chart API, `getChartImageDataUrl` and `downloadChart` on the
373
+ * PivotGrid one.
374
+ */
375
+ interface ChartImageRequest {
376
+ /** `'png'` (default), `'jpeg'` or `'svg'`. */
377
+ format?: 'png' | 'jpeg' | 'svg';
378
+ /** File name without extension (`download` only). Defaults to one naming what the chart shows. */
379
+ fileName?: string;
380
+ /**
381
+ * Image size in CSS pixels. One side keeps the chart's proportions; both fix
382
+ * the box and centre the chart in it. Ignored for SVG, which scales anyway.
383
+ */
384
+ width?: number;
385
+ height?: number;
386
+ /** JPEG quality, 0–1. Default `0.92`. */
387
+ quality?: number;
388
+ /** Raster pixel ratio. Default `2`. */
389
+ pixelRatio?: number;
390
+ /** Background colour; `null` keeps transparency (not for JPEG). Default white. */
391
+ background?: string | null;
392
+ }
393
+ /**
394
+ * `count` colours derived from `accent`, index-stable.
395
+ *
396
+ * Falls back to the packaged eight when the accent cannot be read — an unthemed
397
+ * grid, or a custom theme whose `--dg-primary` is something this cannot parse
398
+ * (a named colour, `color-mix()`, `oklch()`). Falling back is deliberate: a
399
+ * chart with the wrong-but-readable palette beats a chart of black shapes.
400
+ *
401
+ * A near-grey accent also falls back. Rotating the hue of something with almost
402
+ * no saturation produces eight indistinguishable greys, which is worse than an
403
+ * off-theme palette that can actually be told apart.
404
+ */
405
+ declare function chartPalette(accent: string | null | undefined, count: number): string[];
406
+
407
+ interface WaterfallStep {
408
+ /** Running total before and after this step. */
409
+ start: number;
410
+ end: number;
411
+ /** An increase, a decrease, or the closing total bar (which starts at zero). */
412
+ kind: 'up' | 'down' | 'total';
413
+ /** The step's own value (the total's value is the running total). */
414
+ value: number;
415
+ }
416
+ /**
417
+ * Each category moves the running total by its value; the bar floats from the
418
+ * old total to the new one. With `total`, a last bar shows where it ended,
419
+ * standing on zero. NaN ("nothing to total") moves nothing and draws a step
420
+ * of zero height, so the categories stay aligned.
421
+ */
422
+ declare function waterfallSteps(values: ArrayLike<number>, total?: boolean): WaterfallStep[];
423
+ /** Lowest and highest point a waterfall reaches, zero included. */
424
+ declare function waterfallDomain(steps: readonly WaterfallStep[]): {
425
+ min: number;
426
+ max: number;
427
+ };
428
+ interface FunnelStage {
429
+ /** Index into the input values. */
430
+ index: number;
431
+ value: number;
432
+ /** Bar width as a share of the widest stage, 0..1. */
433
+ ratio: number;
434
+ /** Share of the FIRST stage (the funnel's conversion so far), 0..1. */
435
+ ofFirst: number;
436
+ }
437
+ /**
438
+ * Stages in the order given — a funnel's order is the process, not the
439
+ * magnitude, so it is never re-sorted. Negative and NaN values are stages of
440
+ * zero width: a funnel stage cannot hold less than nothing.
441
+ */
442
+ declare function funnelStages(values: ArrayLike<number>): FunnelStage[];
443
+ interface TreemapCell {
444
+ /** Index into the input values. */
445
+ index: number;
446
+ value: number;
447
+ x: number;
448
+ y: number;
449
+ width: number;
450
+ height: number;
451
+ }
452
+ /**
453
+ * Squarified treemap (Bruls, Huizing, van Wijk): rectangles with areas
454
+ * proportional to the values, laid out to stay as close to square as the
455
+ * values allow — a long thin sliver is hard to compare and to label. Only
456
+ * positive values take area; the rest are left out (a negative area has no
457
+ * meaning). Largest first.
458
+ */
459
+ declare function squarify(values: ArrayLike<number>, x: number, y: number, width: number, height: number): TreemapCell[];
460
+ /**
461
+ * A heatmap cell's colour: `t` in 0..1 between `from` and `to` (hex colours),
462
+ * as an `rgb()` literal — a presentation attribute cannot hold `var()`.
463
+ */
464
+ declare function heatColor(t: number, from?: string, to?: string): string;
465
+ /** Text that stays readable on a heat colour: dark on light cells, white on dark. */
466
+ declare function heatTextColor(t: number): string;
467
+
468
+ type MarkTone = 'muted' | 'border' | 'text';
469
+ type ChartMark = {
470
+ kind: 'rect';
471
+ x: number;
472
+ y: number;
473
+ width: number;
474
+ height: number;
475
+ fill: string;
476
+ /** Category / series index, for tooltips and clicks (absent on chrome). */
477
+ ci?: number;
478
+ si?: number;
479
+ /** Native tooltip text. */
480
+ title?: string;
481
+ rx?: number;
482
+ opacity?: number;
483
+ } | {
484
+ kind: 'text';
485
+ x: number;
486
+ y: number;
487
+ text: string;
488
+ anchor: 'start' | 'middle' | 'end';
489
+ size?: number;
490
+ weight?: number;
491
+ /** A literal colour, or a chrome role. */
492
+ fill?: string;
493
+ tone?: MarkTone;
494
+ /** Degrees, about (x, y). */
495
+ rotate?: number;
496
+ } | {
497
+ kind: 'line';
498
+ x1: number;
499
+ y1: number;
500
+ x2: number;
501
+ y2: number;
502
+ dashed?: boolean;
503
+ tone: MarkTone;
504
+ } | {
505
+ /** An SVG path — the arcs of a sunburst. */
506
+ kind: 'path';
507
+ d: string;
508
+ fill: string;
509
+ ci?: number;
510
+ si?: number;
511
+ title?: string;
512
+ opacity?: number;
513
+ };
514
+ interface ShapeChartInput {
515
+ /** Category labels, blanks already captioned. */
516
+ categories: string[];
517
+ /** The series to draw (hidden ones already left out), each with its ORIGINAL index. */
518
+ series: Array<{
519
+ index: number;
520
+ label: string;
521
+ values: ArrayLike<number>;
522
+ color: string;
523
+ }>;
524
+ width: number;
525
+ height: number;
526
+ /** A value as the series' column or measure prints it. */
527
+ format: (seriesIndex: number, value: number) => string;
528
+ /** Compact axis captions ("5.5M"). */
529
+ compact: (value: number) => string;
530
+ /** Caption of the waterfall's closing bar. */
531
+ totalLabel?: string;
532
+ /** Category / value axis titles (waterfall). */
533
+ categoryAxisTitle?: string;
534
+ valueAxisTitle?: string;
535
+ /** Colours: waterfall up / down / total, heatmap ramp ends. Defaults are neutral. */
536
+ colors?: {
537
+ up?: string;
538
+ down?: string;
539
+ total?: string;
540
+ heatFrom?: string;
541
+ heatTo?: string;
542
+ };
543
+ rtl?: boolean;
544
+ }
545
+ /**
546
+ * The first series as a waterfall: each category moves the running total,
547
+ * increases and decreases coloured apart, a closing total bar on zero.
548
+ * Connector lines run from each bar's end to the next bar's start.
549
+ */
550
+ declare function waterfallMarks(input: ShapeChartInput): ChartMark[];
551
+ /**
552
+ * The first series as a funnel: one centred bar per category, in the given
553
+ * order (the order is the process), each labelled with its value and its
554
+ * share of the first stage.
555
+ */
556
+ declare function funnelMarks(input: ShapeChartInput, percentText: (share: number) => string): ChartMark[];
557
+ /**
558
+ * The first series as a treemap: a rectangle per category with area
559
+ * proportional to its value (positive values only), labelled where the
560
+ * label fits. Colours run through the given palette by category.
561
+ */
562
+ declare function treemapMarks(input: ShapeChartInput, palette: readonly string[]): ChartMark[];
563
+ /**
564
+ * Categories across, series down, each cell coloured by its value on one ramp
565
+ * over all the visible cells — a matrix read at a glance. Values print in the
566
+ * cells that have room; a cell with nothing to total stays blank.
567
+ */
568
+ declare function heatmapMarks(input: ShapeChartInput): ChartMark[];
569
+ /**
570
+ * The first two series as a RANGE per category: one floating bar from the
571
+ * lower of the two values to the higher — a day's low and high, a price band,
572
+ * a planned-versus-actual span. Which series is "low" does not matter: each
573
+ * category draws from its own smaller value to its larger one. A category
574
+ * missing either value draws nothing (a span needs both ends).
575
+ */
576
+ declare function rangeBarMarks(input: ShapeChartInput): ChartMark[];
577
+ interface SunburstInput {
578
+ /**
579
+ * The leaves, each with its path from the outermost level in (`['EMEA',
580
+ * 'Berlin']`), its value and the category index a click or tooltip names.
581
+ * Inner rings are the sums of the leaves under them.
582
+ */
583
+ leaves: Array<{
584
+ path: readonly string[];
585
+ value: number;
586
+ ci: number;
587
+ }>;
588
+ width: number;
589
+ height: number;
590
+ /** One colour per outermost-level node; deeper rings take their parent's, lighter. */
591
+ colors: readonly string[];
592
+ format: (value: number) => string;
593
+ /** The share of the whole, as the reader's locale prints a percentage. */
594
+ percentText: (share: number) => string;
595
+ }
596
+ /**
597
+ * A hierarchy as rings: the outermost level in the middle ring, each level
598
+ * further out, every arc's angle its share of the whole. The leaves sum up
599
+ * into their parents, so the picture answers "what is this made of, and of
600
+ * what is that made". Zero, negative and missing leaves take no angle.
601
+ */
602
+ declare function sunburstMarks(input: SunburstInput): ChartMark[];
603
+ /** The chart types laid out here. */
604
+ declare const SHAPE_CHART_TYPES: readonly ["waterfall", "funnel", "treemap", "heatmap", "rangeBar", "sunburst"];
605
+ type ShapeChartType = (typeof SHAPE_CHART_TYPES)[number];
606
+
319
607
  type DateFormatContext = 'grid' | 'chart' | 'export';
320
608
  type DateGranularity = 'year' | 'quarter' | 'month' | 'day' | 'dayOfWeek' | string | number;
321
609
  declare class DateFormatter {
@@ -382,6 +670,12 @@ interface WorkerFilterSpec {
382
670
  fieldId: string;
383
671
  filterType: 'include' | 'exclude';
384
672
  dictIds: number[];
673
+ /**
674
+ * Filter values the dictionary does not hold yet. No stored row can match
675
+ * them, but a row added by a later transaction can — a rebuild would include
676
+ * it, so the engine keeps them and resolves them as the dictionary grows.
677
+ */
678
+ valueStrings?: string[];
385
679
  }
386
680
  interface PrefilterConditionSpec {
387
681
  fieldId: string;
@@ -473,6 +767,23 @@ interface WorkerReconfigureRequest {
473
767
  /** Dictionary entries appended (in order) since the worker's dictionary was last synced. */
474
768
  dictionaryAppend?: string[];
475
769
  }
770
+ /**
771
+ * Live update (G-PIV-02): replace, remove and append rows of the stored
772
+ * columns. Positions are those BEFORE the transaction; `update` and `remove`
773
+ * never share a position. `columns` carries, for EVERY stored column, the
774
+ * values of the updated rows (in `update` order) followed by the added rows —
775
+ * encoded by the main thread with the same field definitions as the column.
776
+ */
777
+ interface WorkerTransactionRequest {
778
+ action: 'transaction';
779
+ id: string;
780
+ update: Int32Array;
781
+ /** Ascending. */
782
+ remove: Int32Array;
783
+ addCount: number;
784
+ columns: Record<string, ArrayBuffer>;
785
+ dictionaryAppend?: string[];
786
+ }
476
787
  /**
477
788
  * Flat cell matrix returned by the engine.
478
789
  * `keys[i]` = `rowId * MAX_C + colId` hash; `sums[i * numDF + df]` = finalized aggregated value.
@@ -485,11 +796,31 @@ interface FlatCellMatrix {
485
796
  /** Post-processed display values after summary display modes are applied. */
486
797
  displaySums?: Float64Array;
487
798
  }
799
+ /**
800
+ * What the main thread needs to run `summaryType: 'custom'` measures.
801
+ *
802
+ * A custom summary is the customer's own function (or a registry aggregator),
803
+ * and functions cannot be posted to a worker — so the worker groups and the
804
+ * main thread summarises. Each stored row is mapped to its leaf group, and
805
+ * each leaf group to the visible cells it rolls up into, so the main thread
806
+ * feeds every cell exactly the rows that cell covers, in source-row order.
807
+ */
808
+ interface CustomSummaryInputs {
809
+ /** Leaf group of each stored row; -1 for a row the filters removed. */
810
+ rowGroupOf: Int32Array;
811
+ /** Cells of leaf group g are `groupCells[groupCellOffsets[g] .. groupCellOffsets[g + 1])` (cell flat indexes). */
812
+ groupCellOffsets: Int32Array;
813
+ groupCells: Int32Array;
814
+ /** Per-row value of each custom data field, by field id, as encoded for the worker. */
815
+ values: Record<string, Float64Array>;
816
+ }
488
817
  interface WorkerResponse {
489
818
  id: string;
490
819
  rowTree: PivotNode[];
491
820
  colTree: PivotNode[];
492
821
  cellMatrix: FlatCellMatrix;
822
+ /** Present only when a data field has `summaryType: 'custom'`. */
823
+ customSummary?: CustomSummaryInputs;
493
824
  rowIndexMap: Record<string, number>;
494
825
  columnIndexMap: Record<string, number>;
495
826
  cardinalityMap: Record<string, number>;
@@ -505,13 +836,18 @@ interface WorkerResponse {
505
836
  isInitComplete?: boolean;
506
837
  isFilterComplete?: boolean;
507
838
  isReconfigureComplete?: boolean;
839
+ isTransactionComplete?: boolean;
840
+ /** Rows stored after a transaction — the main thread checks it against its own array. */
841
+ rowCount?: number;
508
842
  }
509
843
  /**
510
844
  * TypedArray-based pivot computation engine designed to run inside a Web Worker.
511
845
  *
512
846
  * Pipelines: monolithic `init()` → `applyFilter()` → `compute()`, or the
513
847
  * chunked `initStart()` → `initChunk()`× → `initEnd()` → `compute()` (filters
514
- * applied during the chunked build; result state is identical).
848
+ * applied during the chunked build; result state is identical). Either may be
849
+ * followed by any number of `applyTransaction()` (live updates) — the state
850
+ * after each is the one a fresh init over the resulting rows would reach.
515
851
  * Uses {@link FastTrie} for hierarchical grouping and pre-aggregates leaf groups
516
852
  * into flat TypedArrays supporting SUM, COUNT, AVG, MIN, MAX, and DISTINCT.
517
853
  */
@@ -525,8 +861,13 @@ declare class FlatPivotEngine {
525
861
  private lastMask;
526
862
  private isBuilt;
527
863
  private buildState;
528
- private incrementalFilters;
529
- private incrementalPrefilter;
864
+ private activeFilters;
865
+ private activePrefilter;
866
+ private tracking;
867
+ private groupRows;
868
+ private groupMap;
869
+ private rowLive;
870
+ private colLive;
530
871
  private rowTrie;
531
872
  private colTrie;
532
873
  private cardinalityMap;
@@ -543,6 +884,7 @@ declare class FlatPivotEngine {
543
884
  private leafGroupMins;
544
885
  private leafGroupMaxes;
545
886
  private leafGroupDistinctSets;
887
+ private rowGroupOf;
546
888
  init(req: WorkerInitRequest): void;
547
889
  /**
548
890
  * Swap field roles and regroup the already-stored columnar data under the
@@ -561,6 +903,10 @@ declare class FlatPivotEngine {
561
903
  initChunk(req: WorkerInitChunkRequest): void;
562
904
  /** Close the chunked init and commit the accumulated build. */
563
905
  initEnd(): void;
906
+ /** Append dictionary entries and resolve pending filter strings against them. */
907
+ private appendDictionary;
908
+ /** Put filters in force and size the mask for them (null when nothing filters). */
909
+ private setFilters;
564
910
  /**
565
911
  * Resolve pending filter value strings against dictionary entries from
566
912
  * `fromIndex` on. A string that is not yet in the dictionary cannot match
@@ -584,8 +930,42 @@ declare class FlatPivotEngine {
584
930
  private processRange;
585
931
  /** Commit the build state into the engine + rebuild per-build caches. */
586
932
  private finalizeBuild;
933
+ /** Path string per trie node; `known` (from an earlier pass) is extended, not redone. */
587
934
  private buildPathStrs;
588
935
  private buildIndexMap;
936
+ /**
937
+ * Live update (G-PIV-02): replace, remove and append rows, then bring the
938
+ * groups up to date — without re-reading the rows that did not change.
939
+ *
940
+ * What it costs, and why each part is there:
941
+ * - Each changed row is regrouped (two trie walks, one group lookup).
942
+ * - Every leaf group a changed row left or joined is RE-SUMMED from its
943
+ * rows, in row order, in one pass over the row→group column. Not patched
944
+ * by subtracting the old value: for floats that drifts (0.1 + 0.2 - 0.2 is
945
+ * 0.10000000000000003) and the error walks with every tick; min, max and
946
+ * distinct cannot be un-applied at all. A re-sum in row order produces the
947
+ * very value a rebuild produces.
948
+ * - Removing rows compacts the stored columns (a memmove per column), so
949
+ * rows stay in the order of the array the main thread holds.
950
+ * - Only when a group appears, empties or comes back is node visibility,
951
+ * the index maps and the cardinality redone — O(groups + nodes), never
952
+ * O(rows).
953
+ * The first transaction turns tracking on with one regroup of the stored
954
+ * columns (no re-encode, no transfer), and once empty groups outnumber live
955
+ * ones the engine regroups again rather than carry them through every
956
+ * compute. Returns the number of rows stored afterwards.
957
+ */
958
+ applyTransaction(req: WorkerTransactionRequest): number;
959
+ /** Reset the touched groups and fold their rows back in — the same arithmetic, in the same order, as processRange. */
960
+ private resumGroups;
961
+ /**
962
+ * One trie, after a transaction reshaped the groups: which nodes a live
963
+ * group still reaches, each node's live child count (what `hasChildren`
964
+ * reads), the path strings for nodes it created, the index map without the
965
+ * dead nodes, and the fields' cardinality counted over live nodes — what
966
+ * the build's seen-bitmaps count over rows.
967
+ */
968
+ private relive;
589
969
  compute(req: WorkerComputeRequest): WorkerResponse;
590
970
  }
591
971
 
@@ -596,6 +976,11 @@ interface PivotEngineResult {
596
976
  rowIndexMap: Record<string, number>;
597
977
  columnIndexMap: Record<string, number>;
598
978
  cardinalityMap: Record<string, number>;
979
+ /**
980
+ * Worker grouping for `summaryType: 'custom'` measures, consumed (and then
981
+ * removed) by `applyCustomSummaries` before any other post-phase.
982
+ */
983
+ customSummary?: CustomSummaryInputs;
599
984
  }
600
985
  interface FieldDistinctEntry {
601
986
  rawStr: string;
@@ -656,6 +1041,17 @@ prefilterState?: {
656
1041
  * set lookups on columnar data instead of string comparisons.
657
1042
  */
658
1043
  declare function filterPivotEngineAsync(fields: PivotField<any>[], prefilter?: PivotPrefilter): Promise<void>;
1044
+ /**
1045
+ * Live update (G-PIV-02): a resolved transaction, in positions of the array
1046
+ * the engine holds. See controller/rowTransaction.ts.
1047
+ */
1048
+ interface EngineRowChange<TRow> {
1049
+ data: TRow[];
1050
+ updateIndex: number[];
1051
+ updateRows: TRow[];
1052
+ removeIndex: number[];
1053
+ addRows: TRow[];
1054
+ }
659
1055
  declare function computePivotMatrixAsync(expandedPaths: string[], expandedColPaths: string[]): Promise<PivotEngineResult>;
660
1056
  /**
661
1057
  * Cached distinct values for a header filter.
@@ -674,6 +1070,19 @@ interface PivotReportState {
674
1070
  expandedPaths: string[];
675
1071
  expandedColPaths?: string[];
676
1072
  chartState?: Record<string, unknown>;
1073
+ /**
1074
+ * State kept by layers above the core, by name — the Enterprise chart panel
1075
+ * keeps its chart under `chart`. A report saved before a part existed has
1076
+ * none, and loading it leaves that part as it is.
1077
+ */
1078
+ parts?: Record<string, unknown>;
1079
+ }
1080
+ /** A piece of a saved report owned outside the core (see `registerReportStatePart`). */
1081
+ interface ReportStatePart {
1082
+ /** A JSON-safe snapshot of the part. */
1083
+ get(): unknown;
1084
+ /** Restore a snapshot `get` produced (or an older build's — validate it). */
1085
+ apply(value: unknown): void;
677
1086
  }
678
1087
  interface PivotReport {
679
1088
  id: string;
@@ -1020,13 +1429,34 @@ declare function buildPivotAOA(engineResult: PivotEngineResult, rowFields: Pivot
1020
1429
  styles: (ExportCellStyle | null)[][] | null;
1021
1430
  } | null>;
1022
1431
 
1432
+ type PivotRowKey = string | number;
1433
+ /** A field name, or a function returning the key — the DataGrid `rowKey` contract. */
1434
+ type PivotRowKeyResolver<TRow> = keyof TRow | ((row: TRow) => PivotRowKey);
1435
+ interface PivotRowTransaction<TRow> {
1436
+ /** Rows appended after the existing ones. */
1437
+ add?: TRow[];
1438
+ /** Replace the row with the same key, in place. A key the grid does not have is ignored. */
1439
+ update?: TRow[];
1440
+ /** Keys, or rows (matched by their key), to take out. */
1441
+ remove?: (PivotRowKey | TRow)[];
1442
+ }
1443
+ interface PivotTransactionResult {
1444
+ added: number;
1445
+ updated: number;
1446
+ removed: number;
1447
+ }
1448
+
1023
1449
  /** Area where a {@link PivotField} can be placed. */
1024
1450
  type PivotArea = 'row' | 'column' | 'data' | 'filter' | 'chooser';
1025
1451
  /** Aggregation function applied to data fields in worker pre-aggregation. */
1026
1452
  type PivotSummaryType = 'sum' | 'count' | 'avg' | 'min' | 'max' | 'distinct' | 'custom';
1027
1453
  /** Post-aggregation display transformation applied after cell values are computed. */
1028
1454
  type PivotSummaryDisplayMode = 'absolute' | 'percentOfTotal' | 'percentOfColumnTotal' | 'percentOfRowTotal' | 'runningTotal' | 'difference' | 'percentDifference';
1029
- /** Temporal or numeric grouping interval for date/number fields. */
1455
+ /**
1456
+ * Date grouping interval. `'numeric'` and `'custom'` are accepted for
1457
+ * compatibility and have no effect (the grid reports them): numeric bins are
1458
+ * set with a number on {@link PivotField.groupInterval}.
1459
+ */
1030
1460
  type PivotGroupInterval = 'year' | 'quarter' | 'month' | 'day' | 'numeric' | 'custom';
1031
1461
  /** Supported UI locale identifiers. */
1032
1462
  type PivotLocale = 'tr' | 'en' | 'ar' | 'de' | 'fr' | 'es' | 'it' | 'pt' | 'ru' | 'zh-CN' | 'ja' | 'ko';
@@ -1108,10 +1538,27 @@ interface PivotField<TRow = any, TCellTemplate = PivotCellTemplate, TStyle = any
1108
1538
  areaIndex?: number;
1109
1539
  /** Whether the field is visible in the field chooser. */
1110
1540
  visible?: boolean;
1111
- /** Aggregation type — computed in the Web Worker for all types. */
1541
+ /**
1542
+ * Aggregation type. The built-ins are computed in the Web Worker; `'custom'`
1543
+ * runs {@link PivotField.calculateCustomSummary} on the main thread over
1544
+ * rows the worker grouped.
1545
+ */
1112
1546
  summaryType?: PivotSummaryType;
1113
1547
  /** Post-aggregation display transformation (e.g. percent of total). */
1114
1548
  summaryDisplayMode?: PivotSummaryDisplayMode;
1549
+ /**
1550
+ * The summary for `summaryType: 'custom'`, run once per cell (leaf,
1551
+ * subtotal and grand total alike) over that cell's own rows.
1552
+ *
1553
+ * - A function gets one options object per cell through three phases:
1554
+ * `'start'` (once), `'calculate'` (once per row, in source order, with the
1555
+ * row's value in `value`) and `'finalize'` (once). The cell shows
1556
+ * `totalValue` after finalize; other properties you set on the object
1557
+ * persist between phases.
1558
+ * - A string names an aggregator registered with
1559
+ * `registry.registerAggregator(id, fn)`; `fn` receives the cell's values.
1560
+ * An unregistered name is an engine error, not a silent sum.
1561
+ */
1115
1562
  calculateCustomSummary?: string | ((options: CustomSummaryOptions) => void);
1116
1563
  /** True for calculated (virtual) fields that derive from other fields. */
1117
1564
  isCalculated?: boolean;
@@ -1127,7 +1574,11 @@ interface PivotField<TRow = any, TCellTemplate = PivotCellTemplate, TStyle = any
1127
1574
  conditionalFormatting?: PivotConditionRule<TStyle>[];
1128
1575
  /** Custom cell render function. */
1129
1576
  cellTemplate?: TCellTemplate;
1130
- /** Date/numeric grouping interval. */
1577
+ /**
1578
+ * Grouping interval: `'year' | 'quarter' | 'month' | 'day'` for a date
1579
+ * field, or a bin width as a number for a number field (`100` → 0–99,
1580
+ * 100–199, …). `'numeric'` and `'custom'` have no effect.
1581
+ */
1131
1582
  groupInterval?: PivotGroupInterval | number;
1132
1583
  /** Active filter values for header filter (include/exclude mode). */
1133
1584
  filterValues?: Set<any>;
@@ -1155,12 +1606,9 @@ interface PivotLayoutState {
1155
1606
  /** The grand total ROW, at the end of the grid. */
1156
1607
  showRowGrandTotals?: boolean;
1157
1608
  /**
1158
- * @deprecated NOT IMPLEMENTED. Subtotals on the column axis do not exist:
1159
- * row subtotals are inserted while flattening the row tree, and the column
1160
- * axis has no equivalent pass in the renderer. Setting this to `true`
1161
- * explicitly reports through `onError`; it is left in the type because it
1162
- * has always had a default of `true`, so removing it would be a breaking
1163
- * change for a value that never did anything.
1609
+ * Per-level subtotals on the column axis: an expanded column group gets a
1610
+ * total column (before or after its children, per `totalsPosition`).
1611
+ * Default `true`.
1164
1612
  */
1165
1613
  showColumnTotals?: boolean;
1166
1614
  /** Per-level subtotals on the row axis. */
@@ -1173,9 +1621,8 @@ interface PivotLayoutState {
1173
1621
  */
1174
1622
  showGrandTotals?: 'rows' | 'columns' | 'both' | 'none';
1175
1623
  /**
1176
- * Coarse form of `showRowTotals`. Bridged for the ROW axis only — asking for
1177
- * `'columns'` or `'both'` reports through `onError`, because column subtotals
1178
- * are not implemented. See `showColumnTotals`.
1624
+ * Coarse form of `showRowTotals` + `showColumnTotals`. Bridged at the
1625
+ * controller boundary; an explicitly passed granular flag wins.
1179
1626
  */
1180
1627
  showSubTotals?: 'rows' | 'columns' | 'both' | 'none';
1181
1628
  /** Alias of `totalsPosition`, bridged at the controller boundary. */
@@ -1374,6 +1821,12 @@ interface PivotControllerOptions<TRow = any> extends PivotControllerCallbacks<TR
1374
1821
  controlledLayout?: PivotLayoutState;
1375
1822
  chartIntegrationOptions?: Record<string, any>;
1376
1823
  registry?: PivotEngineRegistry;
1824
+ /**
1825
+ * Server-side pivot (A4 / G-PIV-01, Enterprise): the server aggregates and
1826
+ * the grid lays the answer out. With it, `data` is not read; build one with
1827
+ * `pivotServerSource` from an Enterprise package.
1828
+ */
1829
+ serverSource?: PivotServerSource;
1377
1830
  locale?: string;
1378
1831
  workerUrl?: string | URL;
1379
1832
  /**
@@ -1399,6 +1852,13 @@ interface PivotControllerOptions<TRow = any> extends PivotControllerCallbacks<TR
1399
1852
  * with nothing to set.
1400
1853
  */
1401
1854
  enterpriseEdition?: boolean;
1855
+ /**
1856
+ * What identifies a row for `applyTransaction`: a field name, or a function
1857
+ * returning a string or number — the DataGrid's `rowKey`. Without it rows
1858
+ * are matched by object identity, so an update must pass the very object
1859
+ * that is in `data` (mutated in place) and a remove cannot name a bare key.
1860
+ */
1861
+ rowKey?: PivotRowKeyResolver<TRow>;
1402
1862
  }
1403
1863
  /**
1404
1864
  * Starting widths, in pixels, for every column of a kind — the renderer's
@@ -1442,6 +1902,94 @@ interface PivotGridRef {
1442
1902
  getCell: (rowPath: string[], colPath: string[]) => PivotCell | null;
1443
1903
  }
1444
1904
  declare const defaultPivotLayout: PivotLayoutState;
1905
+ /** One field as a server-side pivot request names it. */
1906
+ interface PivotServerField {
1907
+ fieldId: string;
1908
+ /** The source column, when the field reads one (calculated fields do not). */
1909
+ dataField?: string;
1910
+ dataType: PivotField['dataType'];
1911
+ groupInterval?: PivotField['groupInterval'];
1912
+ }
1913
+ /**
1914
+ * What a server-side pivot asks for: the layout and the filters, and which
1915
+ * groups are open — so the server can answer only the levels on screen.
1916
+ */
1917
+ interface PivotServerRequest {
1918
+ /** Row fields, outermost first. */
1919
+ rows: PivotServerField[];
1920
+ /** Column fields, outermost first. */
1921
+ columns: PivotServerField[];
1922
+ /** Measures, in the order the cells carry them. */
1923
+ values: Array<PivotServerField & {
1924
+ summaryType: PivotSummaryType;
1925
+ }>;
1926
+ /** Value filters (header filter, filter area): keep or drop the listed values. */
1927
+ filters: Array<PivotServerField & {
1928
+ type: 'include' | 'exclude';
1929
+ values: unknown[];
1930
+ }>;
1931
+ prefilter: PivotPrefilter | null;
1932
+ /** Open row groups by path, or `'all'`. A closed group's children are not wanted. */
1933
+ expandedRows: string[][] | 'all';
1934
+ expandedColumns: string[][] | 'all';
1935
+ }
1936
+ /** What the grid hands its server source on each compute. */
1937
+ interface PivotServerInput<TRow = any> {
1938
+ gridId: string;
1939
+ fields: PivotField<TRow>[];
1940
+ prefilter: PivotPrefilter | null;
1941
+ /** Open row / column group keys (`'A|B'`); `'*'` for all. */
1942
+ expandedRows: Set<string>;
1943
+ expandedColumns: Set<string>;
1944
+ }
1945
+ /**
1946
+ * The grid side of a server-side pivot; `pivotServerSource` (Enterprise)
1947
+ * builds one. Kept to two calls so the Community bundle carries only the
1948
+ * scheduling — the request, the answer's translation and the field values
1949
+ * are the source's.
1950
+ */
1951
+ interface PivotServerSource {
1952
+ /** The pivot for the grid's current state, as the engine would produce it. */
1953
+ compute(input: PivotServerInput): Promise<PivotEngineResult>;
1954
+ /** Forget cached answers (an explicit refresh: the server's data changed). */
1955
+ reset?(): void;
1956
+ }
1957
+
1958
+ interface PivotChartState {
1959
+ /** Bumped when the shape changes, so an old snapshot is refused rather than misread. */
1960
+ version: 1;
1961
+ /** Whether the chart panel is showing. */
1962
+ open: boolean;
1963
+ /** Chart type id (`'column'`, `'line'`, `'heatmap'`…). */
1964
+ type: string;
1965
+ stacking: ChartStacking;
1966
+ /** Title, axis titles, legend position, data labels and value scale. */
1967
+ format: ChartFormat;
1968
+ /** Series switched off in the legend, by series key (a chart series' `dataKey`). */
1969
+ hiddenSeries: string[];
1970
+ }
1971
+ /** Which part of the state a `chartChanged` event moved. */
1972
+ type PivotChartChange = 'type' | 'stacking' | 'format' | 'hiddenSeries';
1973
+ interface PivotChartOpenedEvent {
1974
+ state: PivotChartState;
1975
+ }
1976
+ interface PivotChartChangedEvent {
1977
+ state: PivotChartState;
1978
+ changes: PivotChartChange[];
1979
+ }
1980
+ interface PivotChartClosedEvent {
1981
+ state: PivotChartState;
1982
+ }
1983
+ /**
1984
+ * Read a saved chart state defensively — it came from storage, a report or an
1985
+ * older build. Fields of the wrong kind fall back to their defaults; `null`
1986
+ * only for something that is not a chart state of this version at all. The
1987
+ * type is not checked against a list: which types exist is the renderer's
1988
+ * business, and an unknown one draws the panel's empty state, not an error.
1989
+ */
1990
+ declare function readPivotChartState(input: unknown): PivotChartState | null;
1991
+ /** Which parts differ between two states (the `changes` of `chartChanged`). */
1992
+ declare function diffPivotChartState(previous: PivotChartState, next: PivotChartState): PivotChartChange[];
1445
1993
 
1446
1994
  type PivotStateListener = () => void;
1447
1995
  /**
@@ -1503,6 +2051,13 @@ interface PivotControllerEvents<TRow> {
1503
2051
  activeReportId: string | null;
1504
2052
  };
1505
2053
  exporting: ExportingEvent;
2054
+ /**
2055
+ * The Enterprise chart panel opened, changed or closed — each with the
2056
+ * panel's whole `PivotChartState`. A Community grid never fires them.
2057
+ */
2058
+ chartOpened: PivotChartOpenedEvent;
2059
+ chartChanged: PivotChartChangedEvent;
2060
+ chartClosed: PivotChartClosedEvent;
1506
2061
  }
1507
2062
  interface PivotImportLabels {
1508
2063
  initializing: string;
@@ -1527,6 +2082,10 @@ interface PivotImportLabels {
1527
2082
  declare class PivotController<TRow> {
1528
2083
  private store;
1529
2084
  private events;
2085
+ /** Saved-report parts owned above the core, and loaded ones still waiting for their owner. */
2086
+ private readonly reportParts;
2087
+ private pendingReportParts;
2088
+ private readonly chartReporter;
1530
2089
  private options;
1531
2090
  private reportService;
1532
2091
  private engineService;
@@ -1535,13 +2094,54 @@ declare class PivotController<TRow> {
1535
2094
  /** Full row set of a parsed import awaiting preview commit (kept out of observable state). */
1536
2095
  private pendingImportRows;
1537
2096
  private disposed;
2097
+ /**
2098
+ * The array the application last handed in. After a transaction the
2099
+ * controller's rows are a NEW array; a binding that re-sends every option
2100
+ * (React's usePivotController does, on every render) would otherwise hand
2101
+ * back this one and undo every transaction. Same array: not a change.
2102
+ */
2103
+ private externalData;
1538
2104
  constructor(options: PivotControllerOptions<TRow>);
1539
2105
  subscribe: (listener: PivotStateListener) => (() => void);
1540
2106
  getSnapshot: () => PivotControllerState<TRow>;
1541
2107
  getState(): PivotControllerState<TRow>;
1542
2108
  on<K extends keyof PivotControllerEvents<TRow>>(eventName: K, handler: (payload: PivotControllerEvents<TRow>[K]) => void): () => void;
2109
+ /**
2110
+ * The chart panel's state, now. The controller turns it into `chartOpened` /
2111
+ * `chartChanged` / `chartClosed` — call it after every change, as often as
2112
+ * convenient: the same state twice is one event, and edits while the panel
2113
+ * is closed arrive with the next `chartOpened`.
2114
+ */
2115
+ reportChartState(state: PivotChartState): void;
2116
+ /**
2117
+ * Keep a piece of state owned outside the core inside saved reports — the
2118
+ * Enterprise chart panel keeps its chart this way. Order-independent: the
2119
+ * default report loads while the controller is constructed, BEFORE any
2120
+ * Enterprise layer has mounted, so a part loaded before its owner registers
2121
+ * is held and handed over on registration. Returns the unregister function.
2122
+ */
2123
+ registerReportStatePart(key: string, part: ReportStatePart): () => void;
2124
+ private collectReportParts;
1543
2125
  updateOptions(options: Partial<PivotControllerOptions<TRow>>): void;
1544
2126
  setFields(fields: PivotField<TRow>[]): void;
2127
+ /**
2128
+ * Replace every row — a full rebuild, transactions included. Unlike
2129
+ * `updateOptions({ data })`, passing the array the grid started from still
2130
+ * replaces: an explicit call means what it says.
2131
+ */
2132
+ setData(data: TRow[]): void;
2133
+ /**
2134
+ * Add, update and remove rows without rebuilding the pivot (live updates).
2135
+ *
2136
+ * Only the changed rows are encoded and sent to the worker, which regroups
2137
+ * them and re-sums the groups they touched; the result is the pivot a
2138
+ * rebuild from the new rows gives. Rows are matched by `rowKey` (by object
2139
+ * identity without one). An update for a key the grid does not have is
2140
+ * ignored; a remove wins over an update of the same row; adds go to the end
2141
+ * — the DataGrid's semantics. `getRawData()` returns the new rows at once;
2142
+ * the recomputed pivot follows (listen for `engineCompleted`).
2143
+ */
2144
+ applyTransaction(transaction: PivotRowTransaction<TRow>): PivotTransactionResult;
1545
2145
  updateField(updatedField: PivotField<TRow>): void;
1546
2146
  deleteField(fieldId: string): void;
1547
2147
  changeFieldArea(fieldId: string, area: PivotArea): void;
@@ -1713,20 +2313,67 @@ declare class PivotEngineService<TRow> {
1713
2313
  private disposed;
1714
2314
  private isInitComplete;
1715
2315
  private forceNextReencode;
2316
+ private engineLock;
2317
+ private busy;
2318
+ private pendingChanges;
2319
+ private drainQueued;
2320
+ private computing;
2321
+ private recomputeAfter;
1716
2322
  private hashes;
1717
2323
  constructor(config: PivotEngineServiceConfig<TRow>);
1718
2324
  refresh(): void;
2325
+ /**
2326
+ * A transaction changed the rows from `previous` to `change.data` (already
2327
+ * the controller's data). Applied incrementally when the engine holds
2328
+ * `previous`; otherwise the change is just new data and takes the normal path.
2329
+ */
2330
+ applyRowChange(change: EngineRowChange<TRow>, previous: TRow[]): void;
2331
+ /**
2332
+ * Run an engine phase alone. Inits, reconfigures and live updates all
2333
+ * encode against the rows the worker holds, and the first two are async
2334
+ * (encoding yields to the main thread): interleaved, one would hand the
2335
+ * worker columns of a length the other just changed, or a second init's
2336
+ * chunks would land inside the first one's build.
2337
+ */
2338
+ private exclusive;
2339
+ private scheduleDrain;
2340
+ /**
2341
+ * Recompute for a live update without ever pushing a picture back. A compute
2342
+ * already due includes the change (the worker takes messages in order), so
2343
+ * it is joined, not restarted; one in flight does not include it, so another
2344
+ * follows it — and the one in flight is still shown. Restarting the debounce
2345
+ * and bumping the version, as view changes do, would let a feed that ticks
2346
+ * faster than a compute keep the grid on its first picture indefinitely.
2347
+ */
2348
+ private computeAfterChange;
2349
+ /** Post one change; on refusal or failure, rebuild from the current data. */
2350
+ private pushRowChange;
2351
+ /** Send the queued changes, in order. False = one was refused and a rebuild is on its way. */
2352
+ private drainRowChanges;
1719
2353
  refreshData(): void;
1720
2354
  computeIfReady(): void;
1721
2355
  dispose(): void;
1722
2356
  private scheduleInit;
1723
2357
  private runInit;
2358
+ private initPhase;
1724
2359
  private scheduleReconfigure;
1725
2360
  private runReconfigure;
1726
2361
  private scheduleFilter;
1727
2362
  private runFilter;
1728
2363
  private scheduleComputeIfReady;
1729
2364
  private runCompute;
2365
+ private serverTimeout;
2366
+ /** What the last scheduled server compute was for; an identical one is skipped. */
2367
+ private serverKey;
2368
+ private serverInput;
2369
+ private scheduleServerCompute;
2370
+ /**
2371
+ * Everything after the aggregation, on the main thread: custom summaries,
2372
+ * calculated summary fields, sorting and top-N, display modes. One copy for
2373
+ * the three ways a result arrives (worker, fully-expanded snapshot, server).
2374
+ */
2375
+ private postPhases;
2376
+ private runServerCompute;
1730
2377
  /**
1731
2378
  * Produce a fully-expanded engine snapshot on demand, WITHOUT mutating the
1732
2379
  * grid's live state. Used by `expandAll` exports: the cached engineResult
@@ -1809,6 +2456,8 @@ declare class PivotFieldService {
1809
2456
  static placeFields<TRow>(fields: PivotField<TRow>[], fieldIds: string[], pick: (field: PivotField<TRow>) => PivotArea): PivotField<TRow>[];
1810
2457
  static moveFieldByDirection<TRow>(fields: PivotField<TRow>[], fieldId: string, direction: 'start' | 'end' | 'left' | 'right'): PivotField<TRow>[];
1811
2458
  static moveFieldFromDrop<TRow>(fields: PivotField<TRow>[], command: FieldDropCommand): Promise<PivotField<TRow>[]>;
2459
+ /** The field list after the drop, or `fields` itself when the drop changes nothing. */
2460
+ private static applyDrop;
1812
2461
  static calculateDropIntent(pointerX: number, pointerY: number, itemRect: DropIntentRect, previousIntent: DropIntent, isLastItem: boolean, orientation?: 'horizontal' | 'vertical'): DropIntent;
1813
2462
  private static isArea;
1814
2463
  }
@@ -1840,6 +2489,28 @@ declare function cellHash(rId: number, cId: number): number;
1840
2489
  declare function cellHashRow(hash: number): number;
1841
2490
  declare function cellHashCol(hash: number): number;
1842
2491
 
2492
+ interface XYPairInput {
2493
+ name: string;
2494
+ fieldId?: string;
2495
+ seriesKey?: string;
2496
+ seriesLabel?: string;
2497
+ }
2498
+ interface XYPair {
2499
+ /** Legend caption: the column path, or the y measure when there is none. */
2500
+ label: string;
2501
+ /** Indexes into the input series. */
2502
+ x: number;
2503
+ y: number;
2504
+ size: number | null;
2505
+ }
2506
+ /**
2507
+ * Group series by column path (in first-seen order) and pair each group's
2508
+ * measures. A group with fewer measures than the type needs is left out —
2509
+ * there is nothing to plot it against. An empty result means the pivot does
2510
+ * not have enough measures at all; the caller says so.
2511
+ */
2512
+ declare function pairSeriesForXY(series: readonly XYPairInput[], sized: boolean): XYPair[];
2513
+
1843
2514
  declare class PivotCellAggregator<TRow> {
1844
2515
  private accumulators;
1845
2516
  private dataFields;
@@ -2296,4 +2967,186 @@ declare function coerceRecords(records: Record<string, unknown>[], onProgress?:
2296
2967
  */
2297
2968
  declare function parseCsvToRows(text: string, onProgress?: (p: CsvParseProgress) => void): Record<string, unknown>[];
2298
2969
 
2299
- export { type AdvancedExportRequest, type AdvancedExporter, type CellClickEvent, type CellPreparedEvent, type CellType, type ColHeaderCell, type ColumnSlot, type ColumnSlotOptions, type ConditionalVisual, type CsvParseProgress, CsvReader, type CustomSummaryOptions, DEFAULT_DATA_COLUMN_WIDTH, DEFAULT_ROW_HEADER_WIDTH, DataNormalizer, type DateFormatContext, DateFormatter, type DateGranularity, type DimensionFieldInfo, type DropIntent, type ExportFormat, type ExportOptions, ExportStreamController, type ExportingEvent, FastTrie, type FieldDistinctEntry, type FieldMoveEvent, type FilterCondition, type FilterGroup, type FilterOperator, type FlatCellMatrix, FlatPivotEngine, type FlatRow, type IFileReader, type ImportFormat, ImportManager, type ImportManagerOptions, type ImportProgress, type ImportResult, type ImportSnapshot, ImportStreamController, type ImportWorkerKind, type ImportWorkerResult, MAX_C, type ParseFileOptions, type PivotArea, type PivotCell, PivotCellAggregator, type PivotCellTemplate, type PivotCellTextAccessor, type PivotCellValueAccessor, type PivotColumnWidthDefaults, type PivotConditionRule, PivotController, type PivotControllerCallbacks, type PivotControllerEvents, type PivotControllerOptions, type PivotControllerState, type PivotDataSource, type PivotDictionary, type PivotDragIntentState, PivotEngineRegistry, type PivotEngineResult, PivotEngineService, type PivotEngineServiceConfig, PivotEventEmitter, type PivotEventHandler, type PivotEventMap, PivotExportService, type PivotField, PivotFieldService, type PivotGridRef, type PivotGroupInterval, type PivotImportField, type PivotImportLabels, type PivotImportPreviewState, type PivotImportStatus, type PivotLayoutProfile, type PivotLayoutState, type PivotLocale, type PivotNode, type PivotPlugin, type PivotPrefilter, type PivotReport, PivotReportManager, PivotReportService, type PivotReportState, type PivotSelectionMode, PivotSelectionModel, type PivotSelectionRange, type PivotSelectionState, type PivotSelectionStats, type PivotStateListener, PivotStateStore, type PivotStateStoringConfig, type PivotSummaryDisplayMode, type PivotSummaryType, type PivotTheme, type PivotToolbarConfig, type PivotValue, type PrefilterConditionSpec, type PrefilterGroupSpec, type ProcessFileStreamingOptions, type ProcessFromUrlOptions, ROW_HEADER_MAX_PINNED_FRACTION, ROW_HEADER_MIN_COL_WIDTH, ROW_HEADER_MIN_DATA_STRIP, type RowHeaderLayout, type ValidationResult, type ValueRange, type WorkerComputeRequest, type WorkerFilterRequest, type WorkerFilterSpec, type WorkerInitRequest, type WorkerResponse, XmlReader, ar, buildCellLookup, buildColPathsList, buildColumnHeaders, buildPivotAOA, buildRowLabelCells, cellHash, cellHashCol, cellHashRow, classifyValue, clearFormatCache, coerceRecords, coerceValue, compileSafeFormula, computeFieldRanges, computePivotMatrixAsync, computeRowHeaderWidths, conditionRuleToExcelStyle, cssColorToRgb, de, dedupeHeaders, defaultPivotLayout, destroyEngineWorker, detectDelimiter, en, es, escapeXmlText, executePostAggregationPhase, executeSummaryDisplayModesPhase, exportPivotData, extractGroupValue, fieldNeedsRange, filterEmptySummaryTree, filterPivotEngineAsync, filterRecords, filterRecordsAsync, flattenExportRows, flattenRowTree, flattenRowTreeTabular, flattenRowTreeTree, formatCellValue, formatCellValueCached, formatDimensionValue, formatHeaderValue, fr, getAdvancedExporter, getCellVal, getFieldDistinctValues, getVisibleColLeaves, getVisibleColSlots, getVisibleLeafCount, getVisibleMaxDepth, inferColumnType, initPivotEngineAsync, intlFormatToExcelNumFmt, invertRowHeaderWidth, it, ja, ko, parseBoolean, parseColor, parseCsvToRows, parseDelimited, parseFlexibleDate, parseLocaleNumber, pt, rangeRatio, reconfigurePivotEngineAsync, registerAdvancedExporter, resolveColPath, resolveColumnWidthDefaults, resolveConditionalVisual, ru, safeKey, sanitizeRows, scaleColor, setActiveEngineGrid, sortPivotTree, stripBom, testSafeFormula, tr, zhCN };
2970
+ /** The parts of the pivot a model may read and change. */
2971
+ type PivotAiFeature = 'fields' | 'filter' | 'sort' | 'totals';
2972
+ declare const PIVOT_AI_FEATURES: readonly PivotAiFeature[];
2973
+ interface PivotAiFieldOptions {
2974
+ /** Plain-language meaning: "Net revenue in EUR". */
2975
+ description?: string;
2976
+ /**
2977
+ * List the field's distinct values in the schema so "only Izmir" can be
2978
+ * matched to what is stored. Off by default: the values travel to whatever
2979
+ * model the application uses. An answer's filter values are checked against
2980
+ * the data either way, locally.
2981
+ */
2982
+ includeValues?: boolean;
2983
+ /** Leave the field out entirely; it keeps its place and the model never sees it. */
2984
+ exclude?: boolean;
2985
+ }
2986
+ interface PivotAiOptions {
2987
+ /** Parts the model may not change (and is not told about). */
2988
+ exclude?: readonly PivotAiFeature[];
2989
+ /** Per-field descriptions, value lists and exclusions, by field id. */
2990
+ fields?: Readonly<Record<string, PivotAiFieldOptions>>;
2991
+ /** Most values listed per field with `includeValues`. Default 100. */
2992
+ maxValues?: number;
2993
+ }
2994
+ interface PivotAiValue {
2995
+ fieldId: string;
2996
+ summaryType: PivotSummaryType;
2997
+ displayMode: PivotSummaryDisplayMode;
2998
+ }
2999
+ interface PivotAiFilter {
3000
+ fieldId: string;
3001
+ type: 'include' | 'exclude';
3002
+ values: Array<string | number | boolean>;
3003
+ }
3004
+ interface PivotAiSort {
3005
+ fieldId: string;
3006
+ direction: 'asc' | 'desc';
3007
+ /** Order by this measure's grand total instead of by the field's own values. */
3008
+ byValueField: string | null;
3009
+ /** Keep only the first N after sorting (needs `byValueField`). */
3010
+ top: number | null;
3011
+ }
3012
+ interface PivotAiTotals {
3013
+ grandTotalRow: boolean;
3014
+ grandTotalColumn: boolean;
3015
+ subtotalRows: boolean;
3016
+ subtotalColumns: boolean;
3017
+ rowHeaderLayout: 'tabular' | 'tree';
3018
+ }
3019
+ /** The pivot's layout in the schema's shape; a part left out is left as it is. */
3020
+ interface PivotAiState {
3021
+ /** Row dimensions, outermost first. */
3022
+ rows?: string[];
3023
+ /** Column dimensions, outermost first. */
3024
+ columns?: string[];
3025
+ /** Measures in the cells. */
3026
+ values?: PivotAiValue[];
3027
+ /** Every value filter; [] clears them. */
3028
+ filters?: PivotAiFilter[];
3029
+ /** Every dimension sort; a dimension not listed keeps its data order. */
3030
+ sort?: PivotAiSort[];
3031
+ totals?: PivotAiTotals;
3032
+ }
3033
+ interface PivotAiApplyResult {
3034
+ applied: PivotAiFeature[];
3035
+ dropped: string[];
3036
+ }
3037
+ /**
3038
+ * The JSON Schema of this pivot's layout, as narrow as its fields allow.
3039
+ * Send it to your own model as the structured-output format together with
3040
+ * `getPivotAiState()` and the user's request; pass the answer to
3041
+ * `applyPivotAiState`. No model ships with the grid and nothing is sent.
3042
+ */
3043
+ declare function getPivotAiSchema<TRow>(controller: PivotController<TRow>, options?: PivotAiOptions): Record<string, unknown>;
3044
+ /** The current layout in the schema's shape — what the model should start from. */
3045
+ declare function getPivotAiState<TRow>(controller: PivotController<TRow>, options?: PivotAiOptions): PivotAiState;
3046
+ /**
3047
+ * Apply a model's answer, object or JSON text. What is valid is applied in one
3048
+ * field commit (plus one layout update when totals changed); what is not is
3049
+ * listed in `dropped`. Never throws on a bad answer. Pass the options the
3050
+ * schema was built with.
3051
+ */
3052
+ declare function applyPivotAiState<TRow>(controller: PivotController<TRow>, answer: unknown, options?: PivotAiOptions): PivotAiApplyResult;
3053
+
3054
+ /**
3055
+ * The column paths a row's trend runs over: the columns ON SCREEN, left to
3056
+ * right, totals left out. A collapsed column group is one step (its subtotal
3057
+ * is what the row shows there); an expanded one is its children.
3058
+ */
3059
+ declare function trendColumnPaths(colTree: readonly PivotNode[]): string[][];
3060
+ /** One measure's values for a row across those columns; NaN where there is no cell. */
3061
+ declare function pivotRowTrend(getCell: (rowPath: string[], colPath: string[]) => PivotCell | null, colPaths: readonly string[][], rowPath: string[], fieldId: string): number[];
3062
+ interface TrendShape {
3063
+ /** `points` for an SVG polyline over the present values, in order. */
3064
+ line: string;
3065
+ /** One bar per value from the zero line (or the floor); NaN values have none. */
3066
+ bars: Array<{
3067
+ x: number;
3068
+ y: number;
3069
+ width: number;
3070
+ height: number;
3071
+ negative: boolean;
3072
+ }>;
3073
+ /** The last present value — the dot the eye goes to. */
3074
+ last: {
3075
+ x: number;
3076
+ y: number;
3077
+ } | null;
3078
+ }
3079
+ /**
3080
+ * Lay the values out in a `width` × `height` box. The scale is the row's own
3081
+ * (a sparkline shows SHAPE, not size — the total beside it gives the size);
3082
+ * a flat row sits in the middle. Fewer than two values draw no line.
3083
+ */
3084
+ declare function trendShape(values: readonly number[], width: number, height: number, pad?: number): TrendShape;
3085
+ /** Options for the row sparkline, shared by both Enterprise renderers. */
3086
+ interface PivotRowSparkline {
3087
+ /** The measure to draw, by field id. Default: the first measure. */
3088
+ field?: string;
3089
+ /** `'line'` (default) or `'bar'`. */
3090
+ type?: 'line' | 'bar';
3091
+ /** Drawing size in px. Default 60 × 16. */
3092
+ width?: number;
3093
+ height?: number;
3094
+ }
3095
+
3096
+ /** A header value as it travels: what the engine would have grouped by. */
3097
+ type PivotServerValue = string | number | boolean | null;
3098
+ /** One cell of the answer: a row path, a column path, the measures there. */
3099
+ interface PivotServerCell {
3100
+ /** Row values from the outermost field in; `[]` is the grand-total row. */
3101
+ row: PivotServerValue[];
3102
+ /** Column values from the outermost field in; `[]` is the grand-total column. */
3103
+ col: PivotServerValue[];
3104
+ /** Each measure's value by field id; null or missing for "no value". */
3105
+ values: Record<string, number | null>;
3106
+ }
3107
+ interface PivotServerResponse {
3108
+ /**
3109
+ * Every (row path, column path) pair the request's open groups make
3110
+ * visible — each level's subtotals and the grand totals included. Cells
3111
+ * deeper than the open groups are ignored, so a server may send more than
3112
+ * was asked.
3113
+ */
3114
+ cells: PivotServerCell[];
3115
+ }
3116
+ interface PivotServerSourceOptions {
3117
+ /** Answer a request — usually one call to your API. */
3118
+ load: (request: PivotServerRequest) => Promise<PivotServerResponse>;
3119
+ /** Every value of a field, for the header filter's checklist. Optional. */
3120
+ loadFieldValues?: (field: PivotServerField) => Promise<unknown[]>;
3121
+ /**
3122
+ * Answers kept per distinct request, so closing a group and opening it
3123
+ * again, or switching totals, does not ask again. Default 16; 0 turns the
3124
+ * cache off.
3125
+ */
3126
+ cacheSize?: number;
3127
+ }
3128
+ /** The request for the grid's state: the layout, the filters, the open groups. */
3129
+ declare function serverRequestFor(input: PivotServerInput): PivotServerRequest;
3130
+ /** The grid side of a server-side pivot: pass it as `serverSource`. */
3131
+ declare function pivotServerSource(options: PivotServerSourceOptions): PivotServerSource & {
3132
+ clearCache(): void;
3133
+ };
3134
+ /**
3135
+ * The cells as a PivotEngineResult: the row and column trees (open groups
3136
+ * only), the index maps, and the flat cell matrix the renderers read.
3137
+ */
3138
+ declare function buildEngineResult(request: PivotServerRequest, response: PivotServerResponse): PivotEngineResult;
3139
+ /**
3140
+ * Answer a request from rows held in memory — the specification a real server
3141
+ * implements, and what tests and demos run against. For each open row group
3142
+ * and open column group (the grand totals included), one cell per pair, the
3143
+ * filters and the prefilter applied first.
3144
+ *
3145
+ * `fields` resolves the fields a prefilter names that the request does not
3146
+ * carry (it only names the fields it lays out and filters by).
3147
+ */
3148
+ declare function rollupInMemory<TRow>(rows: readonly TRow[], request: PivotServerRequest, fields?: readonly PivotField<TRow>[]): PivotServerResponse;
3149
+ /** Every value of a field in rows held in memory — the reference `loadFieldValues`. */
3150
+ declare function fieldValuesInMemory<TRow>(rows: readonly TRow[], field: PivotServerField): unknown[];
3151
+
3152
+ export { type AdvancedExportRequest, type AdvancedExporter, CHART_LEGEND_POSITIONS, type CellClickEvent, type CellPreparedEvent, type CellType, type ChartFormat, type ChartImageRequest, type ChartLegendPosition, type ChartMark, type ChartStacking, type ColHeaderCell, type ColumnSlot, type ColumnSlotOptions, type ConditionalVisual, type CsvParseProgress, CsvReader, type CustomSummaryOptions, DEFAULT_DATA_COLUMN_WIDTH, DEFAULT_ROW_HEADER_WIDTH, DataNormalizer, type DateFormatContext, DateFormatter, type DateGranularity, type DimensionFieldInfo, type DropIntent, type ExportFormat, type ExportOptions, ExportStreamController, type ExportingEvent, FastTrie, type FieldDistinctEntry, type FieldMoveEvent, type FilterCondition, type FilterGroup, type FilterOperator, type FlatCellMatrix, FlatPivotEngine, type FlatRow, type FunnelStage, type IFileReader, type ImportFormat, ImportManager, type ImportManagerOptions, type ImportProgress, type ImportResult, type ImportSnapshot, ImportStreamController, type ImportWorkerKind, type ImportWorkerResult, MAX_C, type MarkTone, PIVOT_AI_FEATURES, type ParseFileOptions, type PivotAiApplyResult, type PivotAiFeature, type PivotAiFieldOptions, type PivotAiFilter, type PivotAiOptions, type PivotAiSort, type PivotAiState, type PivotAiTotals, type PivotAiValue, type PivotArea, type PivotCell, PivotCellAggregator, type PivotCellTemplate, type PivotCellTextAccessor, type PivotCellValueAccessor, type PivotChartChange, type PivotChartChangedEvent, type PivotChartClosedEvent, type PivotChartOpenedEvent, type PivotChartState, type PivotColumnWidthDefaults, type PivotConditionRule, PivotController, type PivotControllerCallbacks, type PivotControllerEvents, type PivotControllerOptions, type PivotControllerState, type PivotDataSource, type PivotDictionary, type PivotDragIntentState, PivotEngineRegistry, type PivotEngineResult, PivotEngineService, type PivotEngineServiceConfig, PivotEventEmitter, type PivotEventHandler, type PivotEventMap, PivotExportService, type PivotField, PivotFieldService, type PivotGridRef, type PivotGroupInterval, type PivotImportField, type PivotImportLabels, type PivotImportPreviewState, type PivotImportStatus, type PivotLayoutProfile, type PivotLayoutState, type PivotLocale, type PivotNode, type PivotPlugin, type PivotPrefilter, type PivotReport, PivotReportManager, PivotReportService, type PivotReportState, type PivotRowKey, type PivotRowKeyResolver, type PivotRowSparkline, type PivotRowTransaction, type PivotSelectionMode, PivotSelectionModel, type PivotSelectionRange, type PivotSelectionState, type PivotSelectionStats, type PivotServerCell, type PivotServerField, type PivotServerInput, type PivotServerRequest, type PivotServerResponse, type PivotServerSource, type PivotServerSourceOptions, type PivotServerValue, type PivotStateListener, PivotStateStore, type PivotStateStoringConfig, type PivotSummaryDisplayMode, type PivotSummaryType, type PivotTheme, type PivotToolbarConfig, type PivotTransactionResult, type PivotValue, type PrefilterConditionSpec, type PrefilterGroupSpec, type ProcessFileStreamingOptions, type ProcessFromUrlOptions, ROW_HEADER_MAX_PINNED_FRACTION, ROW_HEADER_MIN_COL_WIDTH, ROW_HEADER_MIN_DATA_STRIP, type ReportStatePart, type RowHeaderLayout, SHAPE_CHART_TYPES, type ShapeChartInput, type ShapeChartType, type StackedSegment, type TreemapCell, type TrendShape, type ValidationResult, type ValueRange, type WaterfallStep, type WorkerComputeRequest, type WorkerFilterRequest, type WorkerFilterSpec, type WorkerInitRequest, type WorkerResponse, type WorkerTransactionRequest, type XYPair, type XYPairInput, XmlReader, applyPivotAiState, ar, buildCellLookup, buildColPathsList, buildColumnHeaders, buildEngineResult, buildPivotAOA, buildRowLabelCells, cellHash, cellHashCol, cellHashRow, chartPalette, classifyValue, clearFormatCache, coerceRecords, coerceValue, compileSafeFormula, computeFieldRanges, computePivotMatrixAsync, computeRowHeaderWidths, conditionRuleToExcelStyle, cssColorToRgb, de, dedupeHeaders, defaultPivotLayout, destroyEngineWorker, detectDelimiter, diffPivotChartState, en, es, escapeXmlText, executePostAggregationPhase, executeSummaryDisplayModesPhase, exportPivotData, extractGroupValue, fieldNeedsRange, fieldValuesInMemory, filterEmptySummaryTree, filterPivotEngineAsync, filterRecords, filterRecordsAsync, flattenExportRows, flattenRowTree, flattenRowTreeTabular, flattenRowTreeTree, formatCellValue, formatCellValueCached, formatDimensionValue, formatHeaderValue, fr, funnelMarks, funnelStages, getAdvancedExporter, getCellVal, getFieldDistinctValues, getPivotAiSchema, getPivotAiState, getVisibleColLeaves, getVisibleColSlots, getVisibleLeafCount, getVisibleMaxDepth, heatColor, heatTextColor, heatmapMarks, inferColumnType, initPivotEngineAsync, intlFormatToExcelNumFmt, invertRowHeaderWidth, it, ja, ko, logAxisTicks, pairSeriesForXY, parseBoolean, parseColor, parseCsvToRows, parseDelimited, parseFlexibleDate, parseLocaleNumber, percentAxisTicks, pivotRowTrend, pivotServerSource, pt, rangeBarMarks, rangeRatio, readChartFormat, readPivotChartState, reconfigurePivotEngineAsync, registerAdvancedExporter, resolveColPath, resolveColumnWidthDefaults, resolveConditionalVisual, rollupInMemory, ru, safeKey, sanitizeRows, scaleColor, serverRequestFor, setActiveEngineGrid, sortPivotTree, squarify, stackSeries, stripBom, sunburstMarks, testSafeFormula, tr, treemapMarks, trendColumnPaths, trendShape, waterfallDomain, waterfallMarks, waterfallSteps, zhCN };