@guiexpert/table 1.1.93 → 1.1.94

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 (68) hide show
  1. package/README.md +13 -0
  2. package/css/main.css +142 -0
  3. package/css/table-classes.css +34 -0
  4. package/css/table-color-vars.css +32 -0
  5. package/css/table-pivot.css +42 -0
  6. package/css/table-row-group.css +25 -0
  7. package/css/table-tree.css +9 -0
  8. package/index.cjs +44 -36
  9. package/index.d.ts +39 -0
  10. package/index.js +6247 -3509
  11. package/lib/table/aggregation/aggregate-internals.d.ts +30 -0
  12. package/lib/table/aggregation/aggregate-spec.if.d.ts +51 -0
  13. package/lib/table/aggregation/aggregate.d.ts +58 -0
  14. package/lib/table/aggregation/aggregator-name.type.d.ts +39 -0
  15. package/lib/table/aggregation/aggregator.if.d.ts +51 -0
  16. package/lib/table/aggregation/aggregators.d.ts +37 -0
  17. package/lib/table/aggregation/create-value-getter.d.ts +18 -0
  18. package/lib/table/aggregation/selection-aggregates.if.d.ts +35 -0
  19. package/lib/table/aggregation/value-accessor.type.d.ts +13 -0
  20. package/lib/table/data/common/row-number-column-def.d.ts +107 -0
  21. package/lib/table/data/common/row-number-columns.d.ts +17 -0
  22. package/lib/table/data/common/row-number-options.d.ts +19 -0
  23. package/lib/table/data/common/row-number-options.if.d.ts +44 -0
  24. package/lib/table/data/tablemodel/areamodel/aggregate-footer-options.if.d.ts +73 -0
  25. package/lib/table/data/tablemodel/areamodel/area-model-aggregate-footer.d.ts +145 -0
  26. package/lib/table/data/tablemodel/areamodel/area-model-cell-groups.d.ts +18 -1
  27. package/lib/table/data/tablemodel/areamodel/area-model-pivot-footer.d.ts +47 -0
  28. package/lib/table/data/tablemodel/areamodel/area-model-pivot.d.ts +250 -0
  29. package/lib/table/data/tablemodel/areamodel/area-model-row-groups.d.ts +314 -0
  30. package/lib/table/data/tablemodel/areamodel/area-model-tree.d.ts +14 -0
  31. package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +39 -0
  32. package/lib/table/data/tablemodel/areamodel/derived-values-change.if.d.ts +30 -0
  33. package/lib/table/factory/pivot-factory.d.ts +63 -0
  34. package/lib/table/factory/pivot-table-model-para.if.d.ts +44 -0
  35. package/lib/table/factory/row-group-factory.d.ts +70 -0
  36. package/lib/table/factory/row-group-table-model-para.if.d.ts +66 -0
  37. package/lib/table/factory/table-factory.d.ts +45 -1
  38. package/lib/table/instanceof-workaround.d.ts +143 -6
  39. package/lib/table/pivot/area-model-pivot-header.d.ts +9 -0
  40. package/lib/table/pivot/pivot-column-def.d.ts +28 -0
  41. package/lib/table/pivot/pivot-column-info.if.d.ts +25 -0
  42. package/lib/table/pivot/pivot-config.if.d.ts +58 -0
  43. package/lib/table/pivot/pivot-internals.d.ts +13 -0
  44. package/lib/table/pivot/pivot-layout.d.ts +40 -0
  45. package/lib/table/pivot/pivot-result.d.ts +157 -0
  46. package/lib/table/pivot/pivot-table-model.d.ts +86 -0
  47. package/lib/table/pivot/pivot-value.type.d.ts +67 -0
  48. package/lib/table/render-scope.d.ts +61 -4
  49. package/lib/table/renderer/aggregate-cell-renderer.d.ts +27 -0
  50. package/lib/table/renderer/row-number-cell-renderer.d.ts +27 -0
  51. package/lib/table/rowgroup/group-rows-internals.d.ts +14 -0
  52. package/lib/table/rowgroup/group-rows-options.if.d.ts +13 -0
  53. package/lib/table/rowgroup/group-rows.d.ts +48 -0
  54. package/lib/table/rowgroup/row-group-column-def.d.ts +26 -0
  55. package/lib/table/rowgroup/row-group-column-options.if.d.ts +27 -0
  56. package/lib/table/rowgroup/row-group-detail-row.d.ts +8 -0
  57. package/lib/table/rowgroup/row-group-field.type.d.ts +56 -0
  58. package/lib/table/rowgroup/row-group-internals.d.ts +31 -0
  59. package/lib/table/rowgroup/row-group-layout.d.ts +13 -0
  60. package/lib/table/rowgroup/row-group-model-options.if.d.ts +39 -0
  61. package/lib/table/rowgroup/row-group.d.ts +51 -0
  62. package/lib/table/rowgroup/row-group.if.d.ts +48 -0
  63. package/lib/table/selection/selection-aggregator.d.ts +37 -0
  64. package/lib/table/selection/selection-service.d.ts +7 -0
  65. package/lib/table/service/convenience-dom.service.d.ts +5 -0
  66. package/lib/table/table-api.d.ts +112 -1
  67. package/lib/table/table-scope.d.ts +19 -0
  68. package/package.json +3 -2
@@ -6,6 +6,8 @@ import { TableOptionsIf } from '../data/options/table-options.if.js';
6
6
  import { TableModelIf } from '../data/tablemodel/table-model.if.js';
7
7
  import { TableModel } from '../data/tablemodel/table-model.js';
8
8
  import { SelectionModelIf } from '../selection/selection-model.if.js';
9
+ import { RowNumberOptionsIf } from '../data/common/row-number-options.if.js';
10
+ import { AggregateFooterConfig } from '../data/tablemodel/areamodel/aggregate-footer-options.if.js';
9
11
 
10
12
  /**
11
13
  * Parameters of {@link TableFactory.createTableModel} – pass any subset (`Partial<CreateTableModelPara>`).
@@ -37,14 +39,45 @@ export interface CreateTableModelPara {
37
39
  headerAreaModel: AreaModelIf;
38
40
  /** Model of the body. Default: built from `rows` (objects or tree rows) or `bodyData`. See {@link AreaModel} for own models. */
39
41
  bodyAreaModel: AreaModelIf;
40
- /** Model of the footer. Default: `footerData`, otherwise no footer. Totals that follow the filter: an own {@link AreaModel}. */
42
+ /** Model of the footer. Default: `footerAggregates`, `footerData`, otherwise no footer. */
41
43
  footerAreaModel: AreaModelIf;
44
+ /**
45
+ * A footer with totals that follow filter and sorting ({@link AreaModelAggregateFooter}): `{ total: "sum" }` (one
46
+ * row – the key is the property of the column), `[{ label, aggregates }, …]` (several rows) or full
47
+ * {@link AggregateFooterOptionsIf}. Row height: `defaultRowHeights.footer`. Ignored with an own `footerAreaModel`
48
+ * (warning); `footerData` is ignored with it (warning).
49
+ *
50
+ * @example
51
+ * const tableModel = TableFactory.createTableModel({
52
+ * rows: orders,
53
+ * columnDefs,
54
+ * footerAggregates: { quantity: "sum", total: "sum" } // footer: "100,000 rows" | … | 549,812 | 27,481,033.5
55
+ * });
56
+ *
57
+ * @since 1.1.94
58
+ */
59
+ footerAggregates: AggregateFooterConfig;
42
60
  /** Number of columns fixed on the left (side "west"). Default 0. */
43
61
  fixedLeftColumnCount: number;
44
62
  /** Number of columns fixed on the right (side "east"). Default 0. */
45
63
  fixedRightColumnCount: number;
46
64
  /** Show a checkbox column for every row. Default false. */
47
65
  rowCheckboxVisible: boolean;
66
+ /**
67
+ * Row numbers (1, 2, 3 …) in a column in front of all others, fixed on the left: `true` or options
68
+ * ({@link RowNumberOptionsIf}). Puts a {@link RowNumberColumnDef} in front of `columnDefs` and adds 1 to
69
+ * `fixedLeftColumnCount`; `headerData`/`footerData` get an empty cell in front. Default false.
70
+ *
71
+ * The column is a real column: the indices of all other columns are one higher – use properties where you can
72
+ * ({@link TableApi.getColumnIndex}). With `bodyData` or own area models the flag is ignored (with a warning), because
73
+ * their columns would shift – put a `RowNumberColumnDef` into the column definitions of your models yourself.
74
+ *
75
+ * @example
76
+ * const tableModel = TableFactory.createTableModel({ rows: orders, columnDefs, rowNumbersVisible: true });
77
+ *
78
+ * @since 1.1.93
79
+ */
80
+ rowNumbersVisible: boolean | Partial<RowNumberOptionsIf>;
48
81
  /** Row heights of header, body and footer in px. Default: `tableOptions.defaultRowHeights`, otherwise 34 / 34 / 34. */
49
82
  defaultRowHeights: DefaultRowHeightsIf;
50
83
  /** The columns: property, header label, width, classes, renderers, sorting, editing. See {@link ColumnDef}. */
@@ -120,6 +153,17 @@ export declare class TableFactory {
120
153
  * });
121
154
  */
122
155
  static createTableModel(p: Partial<CreateTableModelPara>): TableModelIf;
156
+ /**
157
+ * `footerAggregates`: returns the configuration if the factory builds an aggregate footer (after the body model),
158
+ * `undefined` if there is none or an own `footerAreaModel` wins.
159
+ */
160
+ private static checkFooterAggregates;
161
+ /**
162
+ * `rowNumbersVisible`: puts a RowNumberColumnDef in front of the column definitions (and an empty cell in front of
163
+ * `headerData`/`footerData`) and fixes it on the left. Only where the factory builds the models from the column
164
+ * definitions – with `bodyData` or own area models every column would shift by one.
165
+ */
166
+ private static addRowNumberColumn;
123
167
  /**
124
168
  * Constructs a table model (an instance of `TableModelIf`) by using provided parameters.
125
169
  *
@@ -1,3 +1,13 @@
1
+ import { RowNumberColumnDef } from './data/common/row-number-column-def.js';
2
+ import { AreaModelAggregateFooter } from './data/tablemodel/areamodel/area-model-aggregate-footer.js';
3
+ import { AreaModelRowGroups } from './data/tablemodel/areamodel/area-model-row-groups.js';
4
+ import { RowGroupIf } from './rowgroup/row-group.if.js';
5
+ import { RowGroupColumnDef } from './rowgroup/row-group-column-def.js';
6
+ import { TreeRowIf } from './data/common/tree-row-if.js';
7
+ import { AreaModelPivot } from './data/tablemodel/areamodel/area-model-pivot.js';
8
+ import { PivotTableModel } from './pivot/pivot-table-model.js';
9
+ import { PivotColumnDef } from './pivot/pivot-column-def.js';
10
+
1
11
  /**
2
12
  * Checks if the given row is a tree row.
3
13
  *
@@ -17,6 +27,16 @@ export declare function isTreeRow(row: any): boolean;
17
27
  * @category Utilities
18
28
  */
19
29
  export declare function isAreaModelTree(model: any): boolean;
30
+ /**
31
+ * True for a {@link CheckboxCellRenderer} – also from another copy of the core (no `instanceof`).
32
+ *
33
+ * @example
34
+ * isCheckboxCellRenderer(new CheckboxCellRenderer()); // true
35
+ *
36
+ * @since 1.1.91
37
+ * @category Utilities
38
+ */
39
+ export declare function isCheckboxCellRenderer(o: any): boolean;
20
40
  /**
21
41
  * Checks if the given object is a CheckboxColumnDef.
22
42
  *
@@ -25,14 +45,131 @@ export declare function isAreaModelTree(model: any): boolean;
25
45
  *
26
46
  * @category Utilities
27
47
  */
48
+ export declare function isCheckboxColumnDef(o: any): boolean;
28
49
  /**
29
- * True for a {@link CheckboxCellRenderer} – also from another copy of the core (no `instanceof`).
50
+ * True for a {@link RowNumberColumnDef} – also from another copy of the core (no `instanceof`).
51
+ *
52
+ * @param {any} o - the object to check, e.g. `tableModel.getColumnDef(0)`
53
+ * @returns {boolean} true for a row number column
30
54
  *
31
55
  * @example
32
- * isCheckboxCellRenderer(new CheckboxCellRenderer()); // true
56
+ * const hasRowNumbers = isRowNumberColumnDef(tableModel.getColumnDef(0));
33
57
  *
34
- * @since 1.1.91
35
- * @category Utilities
58
+ * @since 1.1.93
59
+ * @category Row numbers
36
60
  */
37
- export declare function isCheckboxCellRenderer(o: any): boolean;
38
- export declare function isCheckboxColumnDef(o: any): boolean;
61
+ export declare function isRowNumberColumnDef(o: any): o is RowNumberColumnDef;
62
+ /**
63
+ * True for an {@link AreaModelAggregateFooter} – also from another copy of the core (no `instanceof`).
64
+ *
65
+ * @param {any} o - the object to check, e.g. `tableModel.getAreaModel("footer")`
66
+ * @returns {boolean} true for a footer with totals
67
+ *
68
+ * @example
69
+ * const footer = tableModel.getAreaModel("footer");
70
+ * const totals = isAreaModelAggregateFooter(footer) ? footer.getResults() : {};
71
+ *
72
+ * @since 1.1.94
73
+ * @category Aggregation
74
+ */
75
+ export declare function isAreaModelAggregateFooter(o: any): o is AreaModelAggregateFooter;
76
+ /**
77
+ * True for a group of a row grouping ({@link RowGroupIf}) – the `data` of a group row. Works across copies of the core.
78
+ *
79
+ * @param {any} o - the object to check, e.g. `treeRow.data`
80
+ * @returns {boolean} true for a group
81
+ *
82
+ * @example
83
+ * const row = tableModel.getBodyModel().getRowByIndex(rowIndex);
84
+ * if (isTreeRow(row) && isRowGroup(row.data)) console.log(row.data.label, row.data.count);
85
+ *
86
+ * @since 1.1.94
87
+ * @category Row grouping
88
+ */
89
+ export declare function isRowGroup(o: any): o is RowGroupIf;
90
+ /**
91
+ * True for a group row of a row grouping: a tree row whose `data` is a {@link RowGroupIf} (detail rows hold your objects).
92
+ *
93
+ * @param {any} row - a body row, e.g. `tableModel.getBodyModel().getRowByIndex(rowIndex)` or `mouseEvent.row`
94
+ * @returns {boolean} true for a group row
95
+ *
96
+ * @example
97
+ * const eventListener = new EventAdapter();
98
+ * eventListener.onMouseClicked = (evt: GeMouseEvent) => {
99
+ * const row = tableModel.getBodyModel().getRowByIndex(evt.rowIndex);
100
+ * if (isGroupRow(row)) console.log("group", row.data.path);
101
+ * };
102
+ *
103
+ * @since 1.1.94
104
+ * @category Row grouping
105
+ */
106
+ export declare function isGroupRow(row: any): row is TreeRowIf<RowGroupIf>;
107
+ /**
108
+ * True for the body model of a row grouping ({@link AreaModelRowGroups}). It is a tree as well
109
+ * (`isAreaModelTree` is true). Works across copies of the core.
110
+ *
111
+ * @param {any} o - the object to check, e.g. `tableModel.getBodyModel()`
112
+ * @returns {boolean} true for a row grouping
113
+ *
114
+ * @example
115
+ * const body = tableModel.getBodyModel();
116
+ * const groups = isAreaModelRowGroups(body) ? body.getGroups() : [];
117
+ *
118
+ * @since 1.1.94
119
+ * @category Row grouping
120
+ */
121
+ export declare function isAreaModelRowGroups(o: any): o is AreaModelRowGroups;
122
+ /**
123
+ * True for the group column of a row grouping ({@link RowGroupColumnDef}). Works across copies of the core.
124
+ *
125
+ * @param {any} o - the object to check, e.g. a column definition
126
+ * @returns {boolean} true for the group column
127
+ *
128
+ * @example
129
+ * const groupColumnIndex = (tableModel.getColumnDefs() ?? []).findIndex(isRowGroupColumnDef);
130
+ *
131
+ * @since 1.1.94
132
+ * @category Row grouping
133
+ */
134
+ export declare function isRowGroupColumnDef(o: any): o is RowGroupColumnDef;
135
+ /**
136
+ * True for the table model of a pivot table ({@link PivotTableModel}). Works across copies of the core.
137
+ *
138
+ * @param {any} o - the object to check, e.g. `tableApi.getTableModel()`
139
+ * @returns {boolean} true for a pivot table
140
+ *
141
+ * @example
142
+ * const model = tableApi.getTableModel();
143
+ * const config = isPivotTableModel(model) ? model.getPivotConfig() : undefined;
144
+ *
145
+ * @since 1.1.94
146
+ * @category Pivot
147
+ */
148
+ export declare function isPivotTableModel(o: any): o is PivotTableModel;
149
+ /**
150
+ * True for the body of a pivot table ({@link AreaModelPivot}). Works across copies of the core.
151
+ *
152
+ * @param {any} o - the object to check, e.g. `tableModel.getBodyModel()`
153
+ * @returns {boolean} true for a pivot body
154
+ *
155
+ * @example
156
+ * const body = tableModel.getBodyModel();
157
+ * const total = isAreaModelPivot(body) ? pivotBody.getResult().getValue() : undefined;
158
+ *
159
+ * @since 1.1.94
160
+ * @category Pivot
161
+ */
162
+ export declare function isAreaModelPivot(o: any): o is AreaModelPivot;
163
+ /**
164
+ * True for a value column of a pivot table ({@link PivotColumnDef}). Works across copies of the core.
165
+ *
166
+ * @param {any} o - the object to check, e.g. a column definition
167
+ * @returns {boolean} true for a value, subtotal or total column of a pivot
168
+ *
169
+ * @example
170
+ * const valueColumns = (tableModel.getColumnDefs() ?? []).filter(isPivotColumnDef);
171
+ *
172
+ * @since 1.1.94
173
+ * @category Pivot
174
+ */
175
+ export declare function isPivotColumnDef(o: any): o is PivotColumnDef;
@@ -0,0 +1,9 @@
1
+ import { AreaModelCellGroups } from '../data/tablemodel/areamodel/area-model-cell-groups.js';
2
+
3
+ /**
4
+ * The header of a pivot table: header groups with classes for the labels – column groups (`2026`, `Jan`) start at the
5
+ * left of their span (a wide group stays readable), column labels (`Q1`, `Revenue`) sit above their numbers.
6
+ */
7
+ export declare class AreaModelPivotHeader extends AreaModelCellGroups {
8
+ getCustomClassesAt(rowIndex: number, columnIndex: number): string[];
9
+ }
@@ -0,0 +1,28 @@
1
+ import { ColumnDef } from '../data/tablemodel/column/column-def.js';
2
+ import { SizeIf } from '../data/common/size.if.js';
3
+ import { PivotColumnInfoIf } from './pivot-column-info.if.js';
4
+
5
+ /**
6
+ * A value column of a pivot table – created by {@link PivotFactory} (you don't create them yourself). Its property is
7
+ * stable for the same column key and value (`pivot:[["monat","s:Jan"],"sum(umsatz)"]`), so widths and sorting are
8
+ * remembered like for any column; {@link AreaModelPivot.getColumnProperty} builds it for you.
9
+ *
10
+ * @example
11
+ * const columns = tableModel.getColumnDefs()?.filter(isPivotColumnDef) ?? [];
12
+ * columns.map(c => c.pivot.kind); // ["value", "value", "total"]
13
+ *
14
+ * @since 1.1.94
15
+ * @category Pivot
16
+ */
17
+ export declare class PivotColumnDef extends ColumnDef {
18
+ readonly pivot: PivotColumnInfoIf;
19
+ /** Marker for {@link isPivotColumnDef} (works across copies of the core). */
20
+ readonly type = "PivotColumnDef";
21
+ /**
22
+ * @param {string} property - the stable property
23
+ * @param {string} headerLabel - the label in the lowest header row
24
+ * @param {PivotColumnInfoIf} pivot - what the column shows
25
+ * @param {SizeIf} [width] - the width (default 100 px)
26
+ */
27
+ constructor(property: string, headerLabel: string, pivot: PivotColumnInfoIf, width?: SizeIf);
28
+ }
@@ -0,0 +1,25 @@
1
+ import { RowGroupIf } from '../rowgroup/row-group.if.js';
2
+ import { PivotValueInfoIf } from './pivot-value.type.js';
3
+
4
+ /**
5
+ * What a value column of a pivot table shows ({@link AreaModelPivot.getColumnInfo}): the values of one column key
6
+ * (`"value"`), the subtotal of a column group (`"subtotal"`, with {@link PivotConfigIf.columnSubtotals}) or the
7
+ * total over all column keys (`"total"`).
8
+ *
9
+ * @example
10
+ * const info = pivotModel.getPivotBody().getColumnInfo(columnIndex);
11
+ * if (info?.kind === "value") console.log(info.column?.path, info.value.name); // ["Jan"], "sum(umsatz)"
12
+ *
13
+ * @since 1.1.94
14
+ * @category Pivot
15
+ */
16
+ export interface PivotColumnInfoIf {
17
+ /** `"value"` – one column key, `"subtotal"` – a column group, `"total"` – all columns. */
18
+ readonly kind: "value" | "subtotal" | "total";
19
+ /** The column key (lowest level) or column group; undefined for the total. */
20
+ readonly column?: RowGroupIf;
21
+ /** The value shown in the column. */
22
+ readonly value: PivotValueInfoIf;
23
+ /** The index of the value in {@link PivotConfigIf.values}. */
24
+ readonly valueIndex: number;
25
+ }
@@ -0,0 +1,58 @@
1
+ import { RowGroupField } from '../rowgroup/row-group-field.type.js';
2
+ import { RowGroupExpanded } from '../rowgroup/row-group-model-options.if.js';
3
+ import { PivotValue } from './pivot-value.type.js';
4
+
5
+ /**
6
+ * What a pivot table shows: the row fields (grouped like a row grouping), the column fields (their values become
7
+ * columns) and the values (aggregated per row × column), plus subtotals and totals. Used by
8
+ * {@link PivotFactory.createTableModel}, {@link pivotRows} and {@link TableApi.setPivotConfig}.
9
+ *
10
+ * Fields have the form of a row grouping level ({@link RowGroupField}): a property path, a function (e.g. the quarter
11
+ * of a date) or {@link RowGroupFieldIf} with `label`, `format` and `order` – `groupBy` of a row grouping works as
12
+ * `rowFields`.
13
+ *
14
+ * @example
15
+ * const config: PivotConfigIf<Sale> = {
16
+ * rowFields: ["region", "produkt"],
17
+ * columnFields: [{ value: "monat", order: "insertion" }], // Jan before Feb (order in the data)
18
+ * values: ["umsatz"], // sum of umsatz
19
+ * emptyText: "–"
20
+ * };
21
+ *
22
+ * @typeParam T - the row type
23
+ * @since 1.1.94
24
+ * @category Pivot
25
+ */
26
+ export interface PivotConfigIf<T = any> {
27
+ /** The row levels, top first. Several levels form a hierarchy with subtotals. An empty list shows one total row. */
28
+ rowFields: RowGroupField<T>[];
29
+ /** The fields whose values become columns, top first. Several fields form a multi-row header. Default `[]` (totals only). */
30
+ columnFields?: RowGroupField<T>[];
31
+ /** The aggregated values (at least one): `"umsatz"` (sum) or {@link PivotValueIf}. With several values every column key gets one column per value. */
32
+ values: PivotValue<T>[];
33
+ /** Show the aggregates in the group rows (subtotals). Default true. */
34
+ subtotals?: boolean;
35
+ /**
36
+ * A total column behind every column group (e.g. "2026 Total" behind its quarters); the group gets a toggle and,
37
+ * when collapsed, shows only its total. Default: true with two or more column fields.
38
+ */
39
+ columnSubtotals?: boolean;
40
+ /** The total column(s) on the right: `"fixed"` (default, fixed on the right), `true` (last columns, scrolled) or `false`. */
41
+ totalColumn?: boolean | "fixed";
42
+ /** The total row in the footer. Default true. */
43
+ totalRow?: boolean;
44
+ /**
45
+ * The maximum number of column keys (of the lowest column level). More keys: the first ones are shown, a warning is
46
+ * logged and {@link PivotResult.truncated} is true – total column, subtotal columns and total row still count all rows.
47
+ * Default 1000.
48
+ */
49
+ maxColumns?: number;
50
+ /** Expanded row groups: `true` (default), `false`, open levels as a number (`0` = all closed) or a function per group. */
51
+ expanded?: RowGroupExpanded<T>;
52
+ /** The label of empty keys (`null`, `undefined`, `""`) – rows and columns. Default `"(empty)"`. */
53
+ emptyLabel?: string;
54
+ /** The text of a cell without data (the value stays `undefined`, not 0). Default `""`. */
55
+ emptyText?: string;
56
+ /** The word for totals: header of the total column, label of the total row, suffix of subtotal columns. Default `"Total"`. */
57
+ totalLabel?: string;
58
+ }
@@ -0,0 +1,13 @@
1
+ import { PivotValue, PivotValueInfoIf } from './pivot-value.type.js';
2
+
3
+ /** A value resolved for a pass over the rows. */
4
+ export interface ResolvedPivotValue<T = any> extends PivotValueInfoIf {
5
+ /** undefined for `count` (the value does not matter) */
6
+ readonly getValue?: (row: T) => unknown;
7
+ }
8
+ /** The default maximum number of column keys. */
9
+ export declare const DEFAULT_MAX_COLUMNS = 1000;
10
+ /** The default word for totals. */
11
+ export declare const DEFAULT_TOTAL_LABEL = "Total";
12
+ /** Resolves the values of a pivot configuration: aggregator, getter, unique name, label. */
13
+ export declare function resolvePivotValues<T>(values: PivotValue<T>[] | undefined): ResolvedPivotValue<T>[];
@@ -0,0 +1,40 @@
1
+ import { ColumnDefIf } from '../data/tablemodel/column/column-def.if.js';
2
+ import { CellGroupIf } from '../data/tablemodel/cellgroup/cell-group.if.js';
3
+ import { SizeIf } from '../data/common/size.if.js';
4
+ import { RowGroup } from '../rowgroup/row-group.js';
5
+ import { PivotConfigIf } from './pivot-config.if.js';
6
+ import { PivotResult } from './pivot-result.js';
7
+ import { PivotValueInfoIf } from './pivot-value.type.js';
8
+ import { RowGroupField } from '../rowgroup/row-group-field.type.js';
9
+
10
+ /** Columns, header groups and fixed right columns of a pivot. */
11
+ export interface PivotLayout {
12
+ /** leading columns (row numbers, group column) + value columns + total columns */
13
+ columnDefs: ColumnDefIf[];
14
+ /** the header groups, one leaf per column in the same order */
15
+ cellGroups: CellGroupIf[];
16
+ /** the number of total columns fixed on the right */
17
+ fixedRightColumnCount: number;
18
+ }
19
+ export interface PivotLayoutOptions {
20
+ /** width of a value column (default 100 px) */
21
+ valueWidth?: SizeIf;
22
+ /** ids of collapsed column groups (kept when the layout is built again) */
23
+ closedIds?: ReadonlySet<string>;
24
+ /** the widths of existing columns by property (kept when the layout is built again) */
25
+ widths?: ReadonlyMap<string, SizeIf>;
26
+ }
27
+ /** The property of a value column: column path + value name. */
28
+ export declare function pivotValueProperty(column: RowGroup, value: PivotValueInfoIf): string;
29
+ /** The property of a subtotal column of a column group. */
30
+ export declare function pivotSubtotalProperty(column: RowGroup, value: PivotValueInfoIf): string;
31
+ /** The property of a total column. */
32
+ export declare function pivotTotalProperty(value: PivotValueInfoIf): string;
33
+ /** The default name of a field path in a header: the last part, first letter upper case ("address.city" → "City"). */
34
+ export declare function humanizePath(path: string): string;
35
+ /** The header of the group column of a pivot: the row field labels, e.g. "Region › Produkt" ("" without row fields). */
36
+ export declare function pivotGroupHeaderLabel(rowFields: RowGroupField[]): string;
37
+ /** True if the subtotal columns are on (default: two or more column fields). */
38
+ export declare function hasColumnSubtotals(config: PivotConfigIf): boolean;
39
+ /** Builds the columns and the grouped header of a pivot. */
40
+ export declare function buildPivotLayout<T>(result: PivotResult<T>, config: PivotConfigIf<T>, leading: ColumnDefIf[], options?: PivotLayoutOptions): PivotLayout;
@@ -0,0 +1,157 @@
1
+ import { PivotConfigIf } from './pivot-config.if.js';
2
+ import { RowGroupIf } from '../rowgroup/row-group.if.js';
3
+ import { RowGroup } from '../rowgroup/row-group.js';
4
+ import { PivotValueInfoIf } from './pivot-value.type.js';
5
+
6
+ /**
7
+ * The result of a pivot ({@link pivotRows}, {@link AreaModelPivot.getResult}): the row and column hierarchies and the
8
+ * aggregated value of every combination – cells, subtotals and totals. DOM-free; the table reads its cells from here.
9
+ *
10
+ * - `getValue(row, column)` – a cell; leave out `row` for the column total, `column` for the row total, both for the
11
+ * grand total. Groups of higher levels give subtotals.
12
+ * - A combination without rows is `undefined` (not 0).
13
+ * - Every cell is computed from the rows (leaf cells) or by merging aggregation **states** – an average of a region is
14
+ * the average of its rows, never the average of the product averages. Order of the merges: first along the columns
15
+ * (column groups), then along the rows (row groups, total row) – children in key order. This matters for
16
+ * `first`/`last` only: a row total adds its rows in source order, a column group merges its keys in key order, so
17
+ * the two may differ. Keys cut off by `maxColumns` still count in subtotals and totals.
18
+ *
19
+ * @example
20
+ * const result = pivotRows(sales, { rowFields: ["region"], columnFields: ["monat"], values: ["umsatz"] });
21
+ * const nord = result.rowGroups[0]; // Nord
22
+ * const jan = result.columnLeaves.find(c => c.key === "Jan");
23
+ * result.getValue(nord, jan); // 150
24
+ * result.getValue(nord); // 270 – the row total
25
+ * result.getValue(undefined, jan); // 230 – the column total
26
+ * result.getValue(); // 450
27
+ *
28
+ * @typeParam T - the row type
29
+ * @since 1.1.94
30
+ * @category Pivot
31
+ */
32
+ export declare class PivotResult<T = any> {
33
+ /** @internal the source rows */
34
+ readonly source: ArrayLike<T>;
35
+ /** The row groups of the top level (with sub-groups); empty without row fields. */
36
+ readonly rowGroups: RowGroup<T>[];
37
+ /** The column groups of the top level (with sub-groups); empty without column fields. */
38
+ readonly columnGroups: RowGroup<T>[];
39
+ /** The shown column keys of the lowest level in display order – at most {@link PivotConfigIf.maxColumns}. */
40
+ readonly columnLeaves: RowGroup<T>[];
41
+ /** The values (name, label, aggregator, format). */
42
+ readonly values: readonly PivotValueInfoIf[];
43
+ /** True if there were more column keys than {@link PivotConfigIf.maxColumns} (the rest is not shown as columns). */
44
+ readonly truncated: boolean;
45
+ /** the lowest column key (index into allColumnLeaves) of every source row, -1: no column fields */
46
+ private readonly columnLeafOf;
47
+ /** all column keys of the lowest level, also the ones cut off by maxColumns (they count in subtotals) */
48
+ private readonly allColumnLeaves;
49
+ /** shown column groups (all levels) */
50
+ private readonly shownColumns;
51
+ /** non-leaf column groups (shown or not), deepest first */
52
+ private readonly columnParentsPostOrder;
53
+ /** non-leaf row groups, deepest first */
54
+ private readonly rowParentsPostOrder;
55
+ /** row leaves in display order */
56
+ private readonly rowLeaves;
57
+ private cells;
58
+ /** the values with their getters */
59
+ private readonly resolved;
60
+ private accept?;
61
+ /**
62
+ * Groups the rows by the row and column fields and aggregates the values. Use {@link pivotRows}.
63
+ *
64
+ * @param {ArrayLike<T>} source - the rows (not changed)
65
+ * @param {PivotConfigIf<T>} config - fields and values
66
+ * @param {(sourceIndex: number) => boolean} [accept] - a filter: only rows it accepts count
67
+ */
68
+ constructor(
69
+ /** @internal the source rows */
70
+ source: ArrayLike<T>, config: PivotConfigIf<T>, accept?: (sourceIndex: number) => boolean);
71
+ /**
72
+ * Computes all cells again (same keys) – after a filter change or changed values.
73
+ *
74
+ * @param {(sourceIndex: number) => boolean} [accept] - a filter: only rows it accepts count
75
+ *
76
+ * @example
77
+ * result.compute(i => sales[i].monat === "Jan");
78
+ * result.getValue(); // 230
79
+ */
80
+ compute(accept?: (sourceIndex: number) => boolean): void;
81
+ /**
82
+ * The aggregated value of a cell, a subtotal or a total.
83
+ *
84
+ * @param {RowGroupIf<T>} [row] - a row group (any level); undefined = all rows (column totals)
85
+ * @param {RowGroupIf<T>} [column] - a column key or column group (any level); undefined = all columns (row totals)
86
+ * @param {number | string} [value=0] - the index or name of the value
87
+ * @returns {unknown} the result, `undefined` if no row has this combination
88
+ *
89
+ * @example
90
+ * result.getValue(result.rowGroups[0], undefined, "sum(umsatz)"); // the total of the first row group
91
+ */
92
+ getValue(row?: RowGroupIf<T>, column?: RowGroupIf<T>, value?: number | string): unknown;
93
+ /**
94
+ * The number of rows of a cell, a subtotal or a total (after the filter).
95
+ *
96
+ * @param {RowGroupIf<T>} [row] - a row group; undefined = all rows
97
+ * @param {RowGroupIf<T>} [column] - a column key or group; undefined = all columns
98
+ * @returns {number} the row count, 0 for a combination without rows
99
+ *
100
+ * @example
101
+ * result.getCount(result.rowGroups[0]); // 3 – the rows of Nord
102
+ */
103
+ getCount(row?: RowGroupIf<T>, column?: RowGroupIf<T>): number;
104
+ /**
105
+ * The rows behind a cell (drill-down), after the filter, in source order.
106
+ *
107
+ * @param {RowGroupIf<T>} [row] - a row group; undefined = all rows
108
+ * @param {RowGroupIf<T>} [column] - a column key or group; undefined = all columns
109
+ * @returns {T[]} a new array
110
+ *
111
+ * @example
112
+ * result.getSourceRows(nord, jan).map(s => s.umsatz); // [100, 50]
113
+ */
114
+ getSourceRows(row?: RowGroupIf<T>, column?: RowGroupIf<T>): T[];
115
+ /**
116
+ * True if a column group is shown – false for groups whose keys were all cut off by `maxColumns`.
117
+ *
118
+ * @param {RowGroupIf<T>} column - a column group
119
+ * @returns {boolean} true if it has at least one shown column key
120
+ */
121
+ isColumnShown(column: RowGroupIf<T>): boolean;
122
+ /** @internal the index of a value (by index or name), -1 if unknown */
123
+ valueIndex(value: number | string): number;
124
+ private cell;
125
+ private newCell;
126
+ /** One pass over the rows of a row leaf: the cells per column key and the row total, then the column groups. */
127
+ private leafCells;
128
+ private mergeInto;
129
+ private mergeMap;
130
+ }
131
+ /**
132
+ * Pivots rows: groups them by the row fields and by the column fields and aggregates the values of every combination,
133
+ * with subtotals and totals – the engine behind {@link PivotFactory} (DOM-free, also usable without a table). One pass
134
+ * over the rows; empty combinations are `undefined`, averages are computed from sum and count.
135
+ *
136
+ * @param {ArrayLike<T>} rows - the rows (not changed)
137
+ * @param {PivotConfigIf<T>} config - row fields, column fields, values (see {@link PivotConfigIf})
138
+ * @param {(sourceIndex: number) => boolean} [accept] - a filter: only rows it accepts count (index into `rows`)
139
+ * @returns {PivotResult<T>} the hierarchies and the values
140
+ *
141
+ * @example
142
+ * // case 1: regions × months, sum of umsatz
143
+ * const result = pivotRows(sales, { rowFields: ["region"], columnFields: ["monat"], values: ["umsatz"] });
144
+ * result.rowGroups.map(r => `${r.label}: ${result.getValue(r)}`); // ["Nord: 270", "Süd: 180"]
145
+ * result.getValue(); // 450
146
+ *
147
+ * @example
148
+ * // case 3: the average of a column total is the average of its rows
149
+ * const avg = pivotRows(sales, { rowFields: ["region"], columnFields: ["monat"],
150
+ * values: [{ value: "umsatz", aggregator: "avg" }] });
151
+ * const jan = avg.columnLeaves.find(c => c.key === "Jan");
152
+ * avg.getValue(undefined, jan); // 76.666… (230 / 3) – not 77.5, the mean of 75 and 80
153
+ *
154
+ * @since 1.1.94
155
+ * @category Pivot
156
+ */
157
+ export declare function pivotRows<T = any>(rows: ArrayLike<T>, config: PivotConfigIf<T>, accept?: (sourceIndex: number) => boolean): PivotResult<T>;
@@ -0,0 +1,86 @@
1
+ import { TableModel } from '../data/tablemodel/table-model.js';
2
+ import { ColumnDefIf } from '../data/tablemodel/column/column-def.if.js';
3
+ import { DefaultRowHeightsIf } from '../data/options/default-row-heights.if.js';
4
+ import { GetT } from '../data/common/get-t.js';
5
+ import { SelectionModelIf } from '../selection/selection-model.if.js';
6
+ import { AreaModelCellGroups } from '../data/tablemodel/areamodel/area-model-cell-groups.js';
7
+ import { AreaModelPivot } from '../data/tablemodel/areamodel/area-model-pivot.js';
8
+ import { AreaModelPivotFooter } from '../data/tablemodel/areamodel/area-model-pivot-footer.js';
9
+ import { SizeIf } from '../data/common/size.if.js';
10
+ import { PivotConfigIf } from './pivot-config.if.js';
11
+
12
+ /**
13
+ * The table model of a pivot table – a {@link TableModel} (all wrappers take it) whose columns follow the pivot: a
14
+ * group column, one column per column key × value, subtotal and total columns, a grouped header and a total row.
15
+ * Created by {@link PivotFactory.createTableModel}.
16
+ *
17
+ * Pivot again at runtime – other fields, values or rows – with {@link TableApi.setPivotConfig}: the same model and the
18
+ * same table get new columns (no new model, so no rebuild in the framework wrappers).
19
+ *
20
+ * @example
21
+ * const tableModel = PivotFactory.createTableModel<Sale>({
22
+ * rows: sales, rowFields: ["region"], columnFields: ["monat"], values: ["umsatz"]
23
+ * });
24
+ * tableModel.getPivotBody().getResult().getValue(); // 450
25
+ * tableModel.getPivotConfig().columnFields; // ["monat"]
26
+ *
27
+ * @typeParam T - the row type
28
+ * @since 1.1.94
29
+ * @category Pivot
30
+ */
31
+ export declare class PivotTableModel<T = any> extends TableModel {
32
+ private readonly leadingColumnDefs;
33
+ private readonly valueWidth?;
34
+ /** Marker for {@link isPivotTableModel} (works across copies of the core). */
35
+ readonly kind = "PivotTableModel";
36
+ private pivotFixedRightColumnCount;
37
+ /**
38
+ * Use {@link PivotFactory.createTableModel}.
39
+ *
40
+ * @param {AreaModelCellGroups} header - the grouped header
41
+ * @param {AreaModelPivot<T>} body - the pivot body
42
+ * @param {AreaModelPivotFooter<T>} footer - the total row
43
+ * @param {ColumnDefIf[]} leadingColumnDefs - the columns in front of the values (row numbers, group column)
44
+ * @param {ColumnDefIf[]} columnDefs - all columns (leading columns, value columns, total columns)
45
+ * @param {number} fixedRightColumnCount - the fixed total columns on the right
46
+ * @param {number} fixedLeftColumnCount - fixed columns on the left (the leading columns)
47
+ * @param {DefaultRowHeightsIf} defaultRowHeights - row heights
48
+ * @param {GetT<SelectionModelIf>} getSelectionModel - selection model factory
49
+ * @param {SizeIf} [valueWidth] - the width of new value columns
50
+ */
51
+ constructor(header: AreaModelCellGroups, body: AreaModelPivot<T>, footer: AreaModelPivotFooter<T>, leadingColumnDefs: ColumnDefIf[], columnDefs: ColumnDefIf[], fixedRightColumnCount: number, fixedLeftColumnCount: number, defaultRowHeights: DefaultRowHeightsIf, getSelectionModel: GetT<SelectionModelIf>, valueWidth?: SizeIf | undefined);
52
+ getFixedRightColumnCount(): number;
53
+ /**
54
+ * The body: cells, row groups, drill-down ({@link AreaModelPivot.getCellSourceRows}) and the {@link PivotResult}.
55
+ *
56
+ * @returns {AreaModelPivot<T>} the body model
57
+ *
58
+ * @example
59
+ * const pivotBody = pivotModel.getPivotBody();
60
+ * pivotBody.getResult().columnLeaves.map(c => c.label); // ["Feb", "Jan"]
61
+ */
62
+ getPivotBody(): AreaModelPivot<T>;
63
+ /**
64
+ * The current configuration.
65
+ *
66
+ * @returns {PivotConfigIf<T>} a copy
67
+ *
68
+ * @example
69
+ * pivotModel.getPivotConfig().rowFields; // ["region"]
70
+ */
71
+ getPivotConfig(): PivotConfigIf<T>;
72
+ /**
73
+ * Pivots again with a changed configuration and/or new rows: new keys, columns, header and totals in this model.
74
+ * Prefer {@link TableApi.setPivotConfig} – it also lays the table out again; after this method alone the table
75
+ * must be laid out by you.
76
+ *
77
+ * @param {Partial<PivotConfigIf<T>>} changes - the changed parts, e.g. `{ columnFields: ["jahr"] }`
78
+ * @param {T[]} [rows] - new source rows (default: the current ones)
79
+ *
80
+ * @example
81
+ * pivotModel.setPivotConfig({ values: [{ value: "umsatz", aggregator: "avg" }] });
82
+ */
83
+ setPivotConfig(changes: Partial<PivotConfigIf<T>>, rows?: T[]): void;
84
+ /** Columns and header for the current pivot of the body. */
85
+ private relayout;
86
+ }