@guiexpert/table 1.1.94 → 1.1.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +16 -0
  2. package/css/main.css +299 -0
  3. package/css/table-calc.css +7 -0
  4. package/css/table-color-vars.css +58 -0
  5. package/css/table-fill-batch.css +58 -0
  6. package/css/table-master-detail.css +95 -0
  7. package/css/table-row-drag.css +81 -0
  8. package/index.cjs +37 -35
  9. package/index.d.ts +34 -0
  10. package/index.js +9749 -5000
  11. package/lib/table/action/action-id.type.d.ts +1 -1
  12. package/lib/table/aria/aria-ids.d.ts +7 -0
  13. package/lib/table/aria/aria-texts.d.ts +13 -0
  14. package/lib/table/aria/aria-texts.if.d.ts +101 -0
  15. package/lib/table/batch-edit/batch-edit-options.d.ts +21 -0
  16. package/lib/table/batch-edit/batch-edit-options.if.d.ts +20 -0
  17. package/lib/table/batch-edit/batch-edit-service.d.ts +104 -0
  18. package/lib/table/batch-edit/cell-change.if.d.ts +39 -0
  19. package/lib/table/batch-edit/cell-value-change.if.d.ts +18 -0
  20. package/lib/table/batch-edit/pending-cell-changes.d.ts +104 -0
  21. package/lib/table/calc/column-values.d.ts +55 -0
  22. package/lib/table/calc/show-values-as-internals.d.ts +4 -0
  23. package/lib/table/calc/show-values-as.d.ts +87 -0
  24. package/lib/table/calc/show-values-as.type.d.ts +55 -0
  25. package/lib/table/calc/value-getter-context.if.d.ts +35 -0
  26. package/lib/table/calc/value-getter.type.d.ts +36 -0
  27. package/lib/table/data/common/event/ge-batch-edit-event.d.ts +46 -0
  28. package/lib/table/data/common/event/ge-detail-event.d.ts +40 -0
  29. package/lib/table/data/common/event/ge-model-change-event.d.ts +27 -1
  30. package/lib/table/data/common/event/ge-row-drag-event.d.ts +89 -0
  31. package/lib/table/data/options/auto-restore-options.d.ts +2 -0
  32. package/lib/table/data/options/auto-restore-options.if.d.ts +6 -0
  33. package/lib/table/data/options/table-options.d.ts +8 -0
  34. package/lib/table/data/options/table-options.if.d.ts +62 -0
  35. package/lib/table/data/tablemodel/areamodel/abstract-area-model.d.ts +66 -0
  36. package/lib/table/data/tablemodel/areamodel/area-model-aggregate-footer.d.ts +5 -0
  37. package/lib/table/data/tablemodel/areamodel/area-model-array-of-arrays.d.ts +24 -0
  38. package/lib/table/data/tablemodel/areamodel/area-model-object-array.d.ts +70 -0
  39. package/lib/table/data/tablemodel/areamodel/area-model-pivot.d.ts +31 -0
  40. package/lib/table/data/tablemodel/areamodel/area-model-row-groups.d.ts +23 -1
  41. package/lib/table/data/tablemodel/areamodel/area-model-tree.d.ts +83 -0
  42. package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +55 -0
  43. package/lib/table/data/tablemodel/column/column-def.d.ts +31 -1
  44. package/lib/table/data/tablemodel/column/column-def.if.d.ts +86 -0
  45. package/lib/table/ele-scope.d.ts +14 -0
  46. package/lib/table/event-adapter.d.ts +10 -0
  47. package/lib/table/event-listener.if.d.ts +39 -0
  48. package/lib/table/factory/table-factory.d.ts +11 -0
  49. package/lib/table/fill/compute-fill-changes.d.ts +67 -0
  50. package/lib/table/fill/fill-direction.type.d.ts +7 -0
  51. package/lib/table/fill/fill-handle-options.d.ts +29 -0
  52. package/lib/table/fill/fill-handle-options.if.d.ts +35 -0
  53. package/lib/table/fill/fill-handle-service.d.ts +55 -0
  54. package/lib/table/fill/fill-series.d.ts +60 -0
  55. package/lib/table/fill/fill-value-context.if.d.ts +36 -0
  56. package/lib/table/formula/compile-formula.d.ts +86 -0
  57. package/lib/table/formula/evaluator.d.ts +19 -0
  58. package/lib/table/formula/formula-ast.if.d.ts +42 -0
  59. package/lib/table/formula/formula-error.d.ts +59 -0
  60. package/lib/table/formula/formula-options.if.d.ts +41 -0
  61. package/lib/table/formula/formula-values.d.ts +13 -0
  62. package/lib/table/formula/functions.d.ts +18 -0
  63. package/lib/table/formula/parser.d.ts +10 -0
  64. package/lib/table/formula/tokenizer.d.ts +22 -0
  65. package/lib/table/master-detail/detail-renderer.if.d.ts +99 -0
  66. package/lib/table/master-detail/master-detail-options.d.ts +30 -0
  67. package/lib/table/master-detail/master-detail-options.if.d.ts +60 -0
  68. package/lib/table/master-detail/master-detail-service.d.ts +223 -0
  69. package/lib/table/pivot/pivot-value.type.d.ts +13 -0
  70. package/lib/table/render-scope.d.ts +154 -0
  71. package/lib/table/renderer/edit/input-cell-renderer.d.ts +1 -1
  72. package/lib/table/renderer/edit/select-cell-renderer.d.ts +1 -1
  73. package/lib/table/row-drag/move-rows.d.ts +157 -0
  74. package/lib/table/row-drag/row-drag-options.d.ts +28 -0
  75. package/lib/table/row-drag/row-drag-options.if.d.ts +36 -0
  76. package/lib/table/row-drag/row-drag-service.d.ts +130 -0
  77. package/lib/table/row-drag/row-drop-target.if.d.ts +29 -0
  78. package/lib/table/row-layout/row-layout.d.ts +120 -0
  79. package/lib/table/service/excel-service.d.ts +6 -0
  80. package/lib/table/service/excel-service.if.d.ts +35 -0
  81. package/lib/table/state/table-state.if.d.ts +4 -1
  82. package/lib/table/state/table-state.service.d.ts +4 -0
  83. package/lib/table/table-api.d.ts +378 -2
  84. package/lib/table/table-scope.d.ts +185 -0
  85. package/package.json +1 -1
@@ -0,0 +1,157 @@
1
+ import { RowDropTargetIf } from './row-drop-target.if.js';
2
+ import { TreeRowIf } from '../data/common/tree-row-if.js';
3
+
4
+ /**
5
+ * Sorted, unique row indices inside `0 … rowCount - 1` (the order of the dragged rows is their display order).
6
+ *
7
+ * @param {number[]} rowIndices - any indices, e.g. from a selection
8
+ * @param {number} rowCount - number of rows
9
+ * @returns {number[]} a new, ascending array
10
+ *
11
+ * @example
12
+ * normalizeRowIndices([5, 2, 2, 99, -1], 10); // [2, 5]
13
+ *
14
+ * @category Row drag
15
+ * @since 1.1.95
16
+ */
17
+ export declare function normalizeRowIndices(rowIndices: readonly number[], rowCount: number): number[];
18
+ /**
19
+ * The index in front of which the rows are inserted (before the move): `"after"` row 7 = in front of row 8.
20
+ * `"inside"` counts like `"after"` (flat lists have no children).
21
+ *
22
+ * @param {RowDropTargetIf} target - the drop target
23
+ * @returns {number} the insert position, 0 … rowCount
24
+ *
25
+ * @example
26
+ * getInsertBeforeIndex({ rowIndex: 7, position: "after" }); // 8
27
+ *
28
+ * @category Row drag
29
+ * @since 1.1.95
30
+ */
31
+ export declare function getInsertBeforeIndex(target: RowDropTargetIf): number;
32
+ /**
33
+ * The index of the first moved row after a move in a flat list: the insert position minus the moved rows in front
34
+ * of it. A target inside the moved rows (or right next to them) returns their current index – nothing changes.
35
+ *
36
+ * @param {number[]} rowIndices - ascending, unique row indices ({@link normalizeRowIndices})
37
+ * @param {RowDropTargetIf} target - the drop target
38
+ * @returns {number} the new index of the first moved row, -1 without rows
39
+ *
40
+ * @example
41
+ * // D1: row 3 (index 2) dropped between row 7 and 8 → it is row 7 (index 6) afterwards
42
+ * calcMoveToIndex([2], { rowIndex: 6, position: "after" }); // 6
43
+ *
44
+ * @category Row drag
45
+ * @since 1.1.95
46
+ */
47
+ export declare function calcMoveToIndex(rowIndices: readonly number[], target: RowDropTargetIf): number;
48
+ /**
49
+ * Moves items of an array **in place** (like `Array.prototype.sort`): the items at `indices` keep their order and are
50
+ * inserted in front of `insertBefore` (an index of the array before the move, `array.length` = at the end).
51
+ *
52
+ * @param {T[]} array - the array to change
53
+ * @param {number[]} indices - ascending, unique indices ({@link normalizeRowIndices})
54
+ * @param {number} insertBefore - 0 … array.length
55
+ * @returns {number} the new index of the first moved item (-1 if nothing was given)
56
+ *
57
+ * @example
58
+ * const list = ["a", "b", "c", "d", "e"];
59
+ * moveArrayItems(list, [1, 3], 5); // 3
60
+ * list; // ["a", "c", "e", "b", "d"]
61
+ *
62
+ * @category Row drag
63
+ * @since 1.1.95
64
+ */
65
+ export declare function moveArrayItems<T>(array: T[], indices: readonly number[], insertBefore: number): number;
66
+ /**
67
+ * The dragged tree rows without the ones that travel with an ancestor (a child of a dragged node moves with it).
68
+ *
69
+ * @param {TreeRowIf<S>[]} rows - dragged rows in display order
70
+ * @returns {TreeRowIf<S>[]} the topmost dragged rows, same order
71
+ *
72
+ * @category Row drag
73
+ * @since 1.1.95
74
+ */
75
+ export declare function getTopmostTreeRows<S>(rows: readonly TreeRowIf<S>[]): TreeRowIf<S>[];
76
+ /**
77
+ * True if the tree rows can be dropped at the target row: the target is none of the dragged rows and no descendant
78
+ * of them (a node cannot become its own child – no cycle).
79
+ *
80
+ * @param {TreeRowIf<S>[]} rows - dragged rows
81
+ * @param {TreeRowIf<S>} targetRow - the row under the drop marker
82
+ * @returns {boolean} false for a cycle
83
+ *
84
+ * @example
85
+ * const treeModel = tableModel.getBodyModel() as AreaModelTree<OrderNode>;
86
+ * const node = treeModel.rows[0];
87
+ * canMoveTreeRows([node], node.children?.[0]); // false – into its own child
88
+ *
89
+ * @category Row drag
90
+ * @since 1.1.95
91
+ */
92
+ export declare function canMoveTreeRows<S>(rows: readonly TreeRowIf<S>[], targetRow: TreeRowIf<S> | undefined): boolean;
93
+ /**
94
+ * Moves tree rows **in place**: in front of / behind `targetRow` (siblings, same parent) or `"inside"` it (last
95
+ * children; the target is expanded). Children travel with their parent; `parent` and `deep` are updated.
96
+ *
97
+ * @param {TreeRowIf<S>[]} roots - the top-level rows (e.g. `AreaModelTree.rows`)
98
+ * @param {TreeRowIf<S>[]} rows - dragged rows in display order
99
+ * @param {TreeRowIf<S>} targetRow - the row under the drop marker
100
+ * @param {"before" | "after" | "inside"} position - where to drop
101
+ * @returns {boolean} false if nothing was moved (cycle, no rows)
102
+ *
103
+ * @example
104
+ * const treeModel = tableModel.getBodyModel() as AreaModelTree<OrderNode>;
105
+ * moveTreeRows(treeModel.rows, [treeModel.rows[2]], treeModel.rows[0], "inside"); // 3rd root → child of the 1st
106
+ * treeModel.recalcVisibleTreeRows();
107
+ *
108
+ * @category Row drag
109
+ * @since 1.1.95
110
+ */
111
+ export declare function moveTreeRows<S>(roots: TreeRowIf<S>[], rows: readonly TreeRowIf<S>[], targetRow: TreeRowIf<S>, position: RowDropTargetIf["position"]): boolean;
112
+ /**
113
+ * Flat area models: true if the dragged rows can be moved – all rows are displayed (no filter hides one), the target
114
+ * row exists and is not `"inside"`.
115
+ *
116
+ * @param {number} displayedCount - displayed rows (`getRowCount()`)
117
+ * @param {number} allCount - all rows (`getUnfilteredRowCount()`)
118
+ * @param {number[]} rowIndices - display indices of the dragged rows
119
+ * @param {RowDropTargetIf} target - the drop target
120
+ * @returns {boolean} true if a move is possible
121
+ *
122
+ * @category Row drag
123
+ * @since 1.1.95
124
+ */
125
+ export declare function canMoveFlatRows(displayedCount: number, allCount: number, rowIndices: readonly number[], target: RowDropTargetIf): boolean;
126
+ /**
127
+ * Flat area models: moves the rows in the displayed array and writes the new order back to the array of all rows –
128
+ * both in place. Used by `AreaModelObjectArray` and `AreaModelArrayOfArrays`.
129
+ *
130
+ * @param {T[]} displayed - displayed rows (display order)
131
+ * @param {T[]} all - all rows (same rows – no filter hides one)
132
+ * @param {number[]} rowIndices - display indices of the dragged rows
133
+ * @param {RowDropTargetIf} target - the drop target
134
+ * @returns {boolean} true if moved
135
+ *
136
+ * @category Row drag
137
+ * @since 1.1.95
138
+ */
139
+ export declare function moveFlatRows<T>(displayed: T[], all: T[], rowIndices: readonly number[], target: RowDropTargetIf): boolean;
140
+ /**
141
+ * The row at a content position (y in px from the top of all body rows): constant row heights are computed directly,
142
+ * variable ones by a binary search over the row tops. Positions above / below the rows give the first / last row.
143
+ *
144
+ * @param {number} contentY - y in content pixels
145
+ * @param {number} rowCount - number of rows (> 0)
146
+ * @param {(rowIndex: number) => number} getYPosByRowIndex - top of a row in content pixels (`AreaModelIf.getYPosByRowIndex`)
147
+ * @param {number} [constantRowHeight] - the height of every row, if they are all equal (`AreaModelIf.getConstantRowHeight`)
148
+ * @returns {number} the row index, 0 … rowCount - 1
149
+ *
150
+ * @example
151
+ * const body = tableModel.getBodyModel();
152
+ * const rowIndex = findRowIndexAtY(1234, body.getRowCount(), i => body.getYPosByRowIndex(i), body.getConstantRowHeight?.());
153
+ *
154
+ * @category Row drag
155
+ * @since 1.1.95
156
+ */
157
+ export declare function findRowIndexAtY(contentY: number, rowCount: number, getYPosByRowIndex: (rowIndex: number) => number, constantRowHeight?: number): number;
@@ -0,0 +1,28 @@
1
+ import { RowDragOptionsIf } from './row-drag-options.if.js';
2
+
3
+ /**
4
+ * The defaults of {@link RowDragOptionsIf}.
5
+ *
6
+ * @example
7
+ * const options = RowDragOptions.create({ managed: false });
8
+ * options.autoScrollZoneInPx; // 40
9
+ *
10
+ * @category Row drag
11
+ * @since 1.1.95
12
+ */
13
+ export declare class RowDragOptions implements RowDragOptionsIf {
14
+ managed: boolean;
15
+ multiRow: boolean;
16
+ treeDropInside: boolean;
17
+ dragThresholdInPx: number;
18
+ autoScrollZoneInPx: number;
19
+ autoScrollMaxSpeedInPx: number;
20
+ ghostText?: (rows: any[]) => string;
21
+ /**
22
+ * The defaults, overridden by the given values (`undefined` keeps the default).
23
+ *
24
+ * @param {Partial<RowDragOptionsIf>} [options] - e.g. `tableOptions.rowDragOptions`
25
+ * @returns {RowDragOptionsIf} complete options
26
+ */
27
+ static create(options?: Partial<RowDragOptionsIf>): RowDragOptionsIf;
28
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Options of row dragging ({@link TableOptionsIf.rowDragOptions}). Rows get a drag handle in every column with
3
+ * {@link ColumnDefIf.rowDrag} (or `TableFactory.createTableModel({ rows, rowDrag: true })`).
4
+ *
5
+ * @example
6
+ * const tableOptions: TableOptionsIf = {
7
+ * ...new TableOptions(),
8
+ * rowDragOptions: { managed: false, autoScrollMaxSpeedInPx: 40 } // events only – the app moves the rows
9
+ * };
10
+ *
11
+ * @category Row drag
12
+ * @since 1.1.95
13
+ */
14
+ export interface RowDragOptionsIf {
15
+ /**
16
+ * `true` (default): the table moves the rows itself (`AreaModelIf.moveRows`) – only while the table is neither
17
+ * sorted (a column with sort state asc/desc) nor filtered. `false`: the table only reports the drag
18
+ * (`onRowDragStart/Move/End`), the app moves the rows (e.g. after the server confirmed), always allowed.
19
+ */
20
+ managed: boolean;
21
+ /** `true` (default): grabbing a selected row drags all rows with a selection (their order stays). */
22
+ multiRow: boolean;
23
+ /** `true` (default): tree – dropping on the middle of a row makes the rows its children. */
24
+ treeDropInside: boolean;
25
+ /** Distance in px the pointer has to move before a drag starts (default 4) – below it is a click on the handle. */
26
+ dragThresholdInPx: number;
27
+ /** Height in px of the zone at the top and bottom edge of the body that scrolls automatically (default 40). */
28
+ autoScrollZoneInPx: number;
29
+ /** Maximum auto-scroll speed in px per animation frame (default 24). */
30
+ autoScrollMaxSpeedInPx: number;
31
+ /**
32
+ * Text of the drag ghost. Default: the text of the handle cell of the first row, "(+2)" for two more rows.
33
+ * The text is shown as text (never as HTML).
34
+ */
35
+ ghostText?: (rows: any[]) => string;
36
+ }
@@ -0,0 +1,130 @@
1
+ import { TableScope } from '../table-scope.js';
2
+ import { AreaModelIf } from '../data/tablemodel/areamodel/area-model.if.js';
3
+ import { ColumnDefIf } from '../data/tablemodel/column/column-def.if.js';
4
+ import { RowDropTargetIf } from './row-drop-target.if.js';
5
+ import { RowDragOptionsIf } from './row-drag-options.if.js';
6
+
7
+ /**
8
+ * Whether a body cell shows a drag handle: `"none"`, `"enabled"`, or `"disabled"` (managed drag while the table is
9
+ * sorted or filtered).
10
+ *
11
+ * @category Row drag
12
+ * @since 1.1.95
13
+ */
14
+ export type RowDragHandleState = "none" | "enabled" | "disabled";
15
+ /**
16
+ * Row drag of one table (`tableScope.rowDragService`): drag handles ({@link ColumnDefIf.rowDrag}), pointer drag with
17
+ * ghost, drop marker and auto-scroll, the keyboard alternative (`MOVE_ROW_UP` / `MOVE_ROW_DOWN`) and the managed move.
18
+ * Use {@link TableApi.moveRows}, {@link TableApi.isRowDragging} and {@link TableApi.cancelRowDrag} instead.
19
+ *
20
+ * Pointer Events (mouse, touch, pen) – only on the drag handle; its `pointerdown` is prevented, so the mouse handler
21
+ * of the table (range selection, column drag) never sees it.
22
+ *
23
+ * @category Internals
24
+ * @since 1.1.95
25
+ */
26
+ export declare class RowDragService {
27
+ private readonly tableScope;
28
+ private pending?;
29
+ private session?;
30
+ private sessionAbortController?;
31
+ private ghost?;
32
+ private indicator?;
33
+ private autoScrollFrame;
34
+ private suppressClick;
35
+ private warnedUnsupported;
36
+ constructor(tableScope: TableScope);
37
+ /** The options of this table ({@link TableOptionsIf.rowDragOptions} + defaults). */
38
+ get options(): RowDragOptionsIf;
39
+ /** true while rows are dragged with the pointer. */
40
+ isDragging(): boolean;
41
+ /** true if the row is one of the dragged rows (it is painted dimmed). */
42
+ isDragSourceRow(rowIndex: number): boolean;
43
+ /**
44
+ * Why a managed drag is not possible right now: `"sorted"` (a column has the sort state asc/desc), `"filtered"`
45
+ * (a filter hides rows) – `undefined` if it is possible or the drag is unmanaged.
46
+ */
47
+ getBlockReason(): "sorted" | "filtered" | undefined;
48
+ /**
49
+ * The drag handle of a body cell: none (no `rowDrag`, a group or pivot row, a managed drag the model cannot do),
50
+ * enabled or disabled (managed + sorted/filtered).
51
+ */
52
+ getHandleState(rowIndex: number, columnDef: ColumnDefIf | undefined, areaModel: AreaModelIf): RowDragHandleState;
53
+ /**
54
+ * Adds the drag handle to a rendered body cell (called by the render pass for columns with `rowDrag`).
55
+ *
56
+ * @param {HTMLDivElement} cell - the cell div
57
+ * @param {RowDragHandleState} state - from {@link getHandleState}
58
+ */
59
+ decorateCell(cell: HTMLDivElement, state: RowDragHandleState): void;
60
+ private onPointerDown;
61
+ private listenToDocument;
62
+ private onPointerMove;
63
+ private onPointerUp;
64
+ private onPointerCancel;
65
+ private onKeyDown;
66
+ private onClickCapture;
67
+ /** Starts the drag after the threshold – false if the listener vetoed it. */
68
+ private startPointerDrag;
69
+ /** Computes the drop target from the pointer position, reports a change, moves ghost and marker, auto-scrolls. */
70
+ private updateTarget;
71
+ private autoScrollStep;
72
+ /**
73
+ * Speed in px per frame (negative = up): a quadratic ramp inside the zone at the top/bottom edge of the body, full
74
+ * speed above (header) and below (footer) the body.
75
+ */
76
+ private calcAutoScrollSpeed;
77
+ /** The row under the pointer and the position (before/after/inside) – computed, not read from the DOM. */
78
+ private computeTarget;
79
+ private isValidTarget;
80
+ private drop;
81
+ /**
82
+ * Cancels a running drag (Escape, `pointercancel`, {@link TableApi.cancelRowDrag}, destroy): `onRowDragEnd` with the
83
+ * type `"cancel"`, nothing is moved.
84
+ */
85
+ cancel(originalEvent?: PointerEvent | KeyboardEvent): void;
86
+ /** Ends the pointer session: listeners, ghost, marker, auto-scroll. */
87
+ private stopListening;
88
+ /** Releases everything (TableScope.destroy). A running drag is cancelled. */
89
+ destroy(): void;
90
+ private createDragElements;
91
+ private getGhostText;
92
+ private renderDragElements;
93
+ /** The rows' width (fixed columns + center columns), at most the visible width – the marker ends with the rows. */
94
+ private getMarkerWidth;
95
+ /**
96
+ * Moves rows in the model (managed), repaints, keeps focus and selection on the moved rows and announces the new
97
+ * position.
98
+ *
99
+ * @param {number[]} rowIndices - display indices
100
+ * @param {RowDropTargetIf} target - drop target
101
+ * @param {boolean} reselect - select the moved rows again (multi-row drag)
102
+ * @returns {number} the new display index of the first moved row, -1 if nothing moved
103
+ */
104
+ moveRows(rowIndices: number[], target: RowDropTargetIf, reselect?: boolean): number;
105
+ private findDisplayIndices;
106
+ /**
107
+ * `MOVE_ROW_UP` / `MOVE_ROW_DOWN`: moves the focused row (or the selected rows, if it is one of them) one position.
108
+ * Trees: among the siblings.
109
+ *
110
+ * @param {-1 | 1} direction - up or down
111
+ * @returns {boolean} true if the key was used (a row with a drag handle has the focus)
112
+ */
113
+ moveByKeyboard(direction: -1 | 1): boolean;
114
+ private getFlatKeyboardTarget;
115
+ private getTreeKeyboardTarget;
116
+ /** The dragged rows for a grabbed row: all rows with a selection if it is one of them (multiRow), else this one. */
117
+ getDragRowIndices(rowIndex: number): number[];
118
+ private getRows;
119
+ /** Index of the first column whose drag handle is shown for the row, -1 if none. */
120
+ private getHandleColumnIndex;
121
+ /** The state of the handle of a row that has one (see {@link getHandleColumnIndex}). */
122
+ private getHandleStateOfRow;
123
+ /** true if a column has the sort state asc or desc (the header shows the arrow). */
124
+ private isSorted;
125
+ private isManaged;
126
+ private canModelMove;
127
+ private createEvent;
128
+ private announceNotPossible;
129
+ private texts;
130
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Where dragged rows are dropped, relative to the row under the drop marker:
3
+ * `"before"` / `"after"` that row, or `"inside"` it (it becomes the last child – trees only).
4
+ *
5
+ * @example
6
+ * const target: RowDropTargetIf = { rowIndex: 7, position: "before" }; // between row 7 and row 8 (1-based)
7
+ *
8
+ * @category Row drag
9
+ * @since 1.1.95
10
+ */
11
+ export type RowDropPosition = "before" | "after" | "inside";
12
+ /**
13
+ * The drop target of a row drag ({@link GeRowDragEvent.target}, {@link TableApi.moveRows}).
14
+ *
15
+ * `rowIndex` is the display index (body row index) of the target row **before** the rows are moved.
16
+ *
17
+ * @example
18
+ * // move the rows 2 and 3 behind the last row
19
+ * tableApi.moveRows([2, 3], { rowIndex: tableApi.getDisplayedRowCount() - 1, position: "after" });
20
+ *
21
+ * @category Row drag
22
+ * @since 1.1.95
23
+ */
24
+ export interface RowDropTargetIf {
25
+ /** Display index of the row next to (or under) the drop marker – before the move. */
26
+ rowIndex: number;
27
+ /** Before or after that row, or inside it (tree: becomes its last child). */
28
+ position: RowDropPosition;
29
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Vertical positions of the body rows: the row heights as prefix sums plus optional extra heights behind single rows
3
+ * (the detail rows of master/detail). DOM-free; the table keeps one instance for its body
4
+ * ({@link RenderScope.getBodyRowTop}, {@link RenderScope.getBodyRowIndexAtY}).
5
+ *
6
+ * - Constant row height: positions are computed (`i * h`), no array.
7
+ * - Variable row heights: a `Float64Array` of `rowCount + 1` prefix sums, built lazily on the first access after
8
+ * {@link setRows} – then {@link getTop} is O(1) and {@link findIndexAt} O(log n) (before 1.1.97 the table summed the
9
+ * heights of all rows above the viewport in every scroll frame).
10
+ * - Extras: sorted row indices with their extra heights and the prefix sums of the extras (O(log k) per lookup,
11
+ * k = number of extras). Changing one extra height ({@link setExtraHeight}) costs O(k), not O(n).
12
+ *
13
+ * The slot of a row is the row plus its extra height below it: `getTop(i + 1) = getTop(i) + getRowHeight(i) +
14
+ * getExtraHeight(i)`.
15
+ *
16
+ * @example
17
+ * const layout = new RowLayout();
18
+ * layout.setRows(1000, i => i % 2 ? 30 : 50); // variable heights
19
+ * layout.setExtras([12, 40], [180, 240]); // details behind rows 12 and 40
20
+ * const top = layout.getTop(41); // top of row 41 below both details
21
+ * const row = layout.findIndexAt(5000); // the row whose slot contains y = 5000
22
+ *
23
+ * @category Internals
24
+ * @since 1.1.97
25
+ */
26
+ export declare class RowLayout {
27
+ private rowCount;
28
+ private constantHeight?;
29
+ private heightOf;
30
+ private prefix?;
31
+ private extraIndices;
32
+ private extraHeights;
33
+ private extraPrefix;
34
+ /**
35
+ * Sets the rows. Prefix sums of variable heights are built lazily on the first access.
36
+ * Extras behind rows that no longer exist are dropped.
37
+ *
38
+ * @param {number} rowCount - number of rows
39
+ * @param {(rowIndex: number) => number} heightOf - height of a row (called only for variable heights)
40
+ * @param {number} [constantHeight] - the height of every row, if they are all equal (`AreaModelIf.getConstantRowHeight`)
41
+ */
42
+ setRows(rowCount: number, heightOf: (rowIndex: number) => number, constantHeight?: number): void;
43
+ /**
44
+ * Sets the extra heights (e.g. detail rows) behind rows. Unsorted input is fine; heights of the same row add up;
45
+ * indices outside the rows and heights ≤ 0 are ignored. Replaces all previous extras.
46
+ *
47
+ * @param {ArrayLike<number>} rowIndices - the rows with an extra height below them
48
+ * @param {ArrayLike<number>} heights - the extra heights (same order as `rowIndices`)
49
+ */
50
+ setExtras(rowIndices: ArrayLike<number>, heights: ArrayLike<number>): void;
51
+ /**
52
+ * Changes the extra height behind one row that already has one (see {@link setExtras}).
53
+ *
54
+ * @param {number} rowIndex - the row
55
+ * @param {number} height - the new extra height (> 0)
56
+ * @returns {boolean} false if the row has no extra or the height did not change
57
+ */
58
+ setExtraHeight(rowIndex: number, height: number): boolean;
59
+ /**
60
+ * Sets, changes or (height ≤ 0) removes the extra height behind one row – O(k), the other extras stay.
61
+ *
62
+ * @param {number} rowIndex - the row (ignored outside the rows)
63
+ * @param {number} height - the extra height, ≤ 0 removes it
64
+ * @returns {boolean} true if something changed
65
+ */
66
+ setExtra(rowIndex: number, height: number): boolean;
67
+ /** The number of rows. */
68
+ getRowCount(): number;
69
+ /** The number of rows with an extra height. */
70
+ getExtraCount(): number;
71
+ /** True after the prefix sums of variable heights were built (never for constant heights). */
72
+ hasPrefixSums(): boolean;
73
+ /**
74
+ * The height of a row (without its extra).
75
+ *
76
+ * @param {number} rowIndex - the row
77
+ * @returns {number} the height in px
78
+ */
79
+ getRowHeight(rowIndex: number): number;
80
+ /**
81
+ * The extra height below a row (0 = none).
82
+ *
83
+ * @param {number} rowIndex - the row
84
+ * @returns {number} the extra height in px
85
+ */
86
+ getExtraHeight(rowIndex: number): number;
87
+ /**
88
+ * The sum of the extra heights of the rows above a row.
89
+ *
90
+ * @param {number} rowIndex - the row (`rowCount` = all extras)
91
+ * @returns {number} px
92
+ */
93
+ getExtraBefore(rowIndex: number): number;
94
+ /** The sum of all extra heights. */
95
+ getExtraTotal(): number;
96
+ /**
97
+ * The top of a row: heights and extras of all rows above it. `getTop(rowCount)` = total height. The index is
98
+ * clamped to `0 … rowCount`.
99
+ *
100
+ * @param {number} rowIndex - the row
101
+ * @returns {number} px from the top of the first row
102
+ */
103
+ getTop(rowIndex: number): number;
104
+ /** The height of all rows and extras. */
105
+ getTotalHeight(): number;
106
+ /**
107
+ * The row whose slot (row + extra) contains `y`; rows of height 0 are skipped. Above the first row: 0, below the
108
+ * last: the last row, without rows: -1. O(1) for constant heights without extras, otherwise O(log n).
109
+ *
110
+ * @param {number} y - px from the top of the first row
111
+ * @returns {number} the row index
112
+ */
113
+ findIndexAt(y: number): number;
114
+ private getBaseTop;
115
+ private ensurePrefix;
116
+ private rebuildExtraPrefix;
117
+ /** The number of extras behind rows with an index < rowIndex (lower bound). */
118
+ private countExtrasBelow;
119
+ private findExtra;
120
+ }
@@ -24,6 +24,8 @@ import { ExcelServiceIf } from './excel-service.if.js';
24
24
  * @category Export & clipboard
25
25
  */
26
26
  export declare class ExcelService implements ExcelServiceIf {
27
+ /** Understands cells `{ value, numberFormat }` ({@link ExcelFormattedValueIf}), since 1.1.95. */
28
+ readonly supportsNumberFormats = true;
27
29
  /**
28
30
  * Downloads a matrix data as an Excel file.
29
31
  *
@@ -44,6 +46,10 @@ export declare class ExcelService implements ExcelServiceIf {
44
46
  createExcelBlob(matrix: Array<Array<any>>, author?: string): Promise<Blob>;
45
47
  private generateMap;
46
48
  private getX1WorksheetsSheet1Xml;
49
+ /** Number format → cell style index (1-based; 0 = default), filled by withNumberFormats() before the sheet is written. */
50
+ private numberFormatStyles;
51
+ /** Adds one cell style per number format used in the matrix (`<numFmts>` + `<cellXfs>`); unchanged without formats. */
52
+ private withNumberFormats;
47
53
  private escapeXml;
48
54
  private getCellAddress;
49
55
  /**
@@ -7,4 +7,39 @@
7
7
  export interface ExcelServiceIf {
8
8
  /** Creates the file from `matrix` (rows of values) and hands it to the browser as download. */
9
9
  downloadExcel(matrix: Array<Array<any>>, filename: string, author?: string): void | Promise<void>;
10
+ /**
11
+ * True if the service understands cells of the form {@link ExcelFormattedValueIf} (`{ value, numberFormat }`).
12
+ * Only then {@link TableApi.downloadExcel} exports percentages of „Show values as“ columns with the format `0.0%`;
13
+ * otherwise a service gets plain numbers (since 1.1.95).
14
+ */
15
+ readonly supportsNumberFormats?: boolean;
10
16
  }
17
+ /**
18
+ * A cell of an Excel matrix with a number format, e.g. a share shown as percentage. Understood by
19
+ * {@link ExcelService} (`supportsNumberFormats`).
20
+ *
21
+ * @example
22
+ * await new ExcelService().downloadExcel([["Share"], [{ value: 0.667, numberFormat: "0.0%" }]], "shares.xlsx");
23
+ *
24
+ * @since 1.1.95
25
+ * @category Export & clipboard
26
+ */
27
+ export interface ExcelFormattedValueIf {
28
+ /** The number. */
29
+ value: number;
30
+ /** An Excel number format code, e.g. `"0.0%"`, `"#,##0.00"`. */
31
+ numberFormat: string;
32
+ }
33
+ /**
34
+ * True for a cell of the form {@link ExcelFormattedValueIf}.
35
+ *
36
+ * @param {unknown} cell - a cell of an Excel matrix
37
+ * @returns {boolean} whether it is a number with format
38
+ *
39
+ * @example
40
+ * isExcelFormattedValue({ value: 0.5, numberFormat: "0%" }); // true
41
+ *
42
+ * @since 1.1.95
43
+ * @category Export & clipboard
44
+ */
45
+ export declare function isExcelFormattedValue(cell: unknown): cell is ExcelFormattedValueIf;
@@ -21,11 +21,12 @@ export type TableStateRowId = string | number;
21
21
  * | `selection` | selected rows, columns, cells or ranges | `autoRestoreSelectedState` |
22
22
  * | `headerGroups` | collapsed header groups | `autoRestoreHeaderGroupState` |
23
23
  * | `custom` | data of your application ({@link TableApi.setCustomState}) | `autoRestoreCustomState` |
24
+ * | `details` | expanded detail rows of master/detail (since 1.1.97) | `autoRestoreDetailState` |
24
25
  *
25
26
  * @category State
26
27
  * @since 1.1.92
27
28
  */
28
- export type TableStatePart = "columns" | "sort" | "scroll" | "tree" | "checked" | "selection" | "headerGroups" | "custom";
29
+ export type TableStatePart = "columns" | "sort" | "scroll" | "tree" | "checked" | "selection" | "headerGroups" | "custom" | "details";
29
30
  /**
30
31
  * The state of a table as plain JSON: column layout, sorting, scroll position, tree, checked and selected rows,
31
32
  * header groups and data of your own. Get it with {@link TableApi.getState}, apply it with
@@ -72,6 +73,8 @@ export interface TableStateIf {
72
73
  tree?: TableTreeStateIf;
73
74
  /** The ids of the checked rows. */
74
75
  checkedRowIds?: TableStateRowId[];
76
+ /** The ids of the master rows with an expanded detail row (master/detail). @since 1.1.97 */
77
+ detailRowIds?: TableStateRowId[];
75
78
  /** The selection. */
76
79
  selection?: TableSelectionStateIf;
77
80
  /** The state of the header groups with a toggle. */
@@ -115,6 +115,10 @@ export declare class TableStateService {
115
115
  private computeScroll;
116
116
  private computeTree;
117
117
  private computeChecked;
118
+ /** The ids of the expanded master rows (master/detail, since 1.1.97); `undefined` without master/detail. */
119
+ private computeDetails;
120
+ /** Expands exactly the master rows with these ids (master/detail, since 1.1.97). */
121
+ private applyDetails;
118
122
  private computeSelection;
119
123
  /**
120
124
  * A cell range → ids and properties. A range to the last row / column (`MAX_SAFE_INTEGER`) has no `toRowId` /