@guiexpert/table 1.1.106 → 1.1.108
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/README.md +24 -0
- package/index.cjs +28 -28
- package/index.d.ts +3 -0
- package/index.js +2864 -2082
- package/lib/table/data/common/scroll-position.if.d.ts +28 -0
- package/lib/table/data/options/table-options.if.d.ts +14 -4
- package/lib/table/data/tablemodel/areamodel/abstract-area-model.d.ts +23 -0
- package/lib/table/data/tablemodel/areamodel/area-model-cell-groups.d.ts +1 -1
- package/lib/table/data/tablemodel/areamodel/area-model-object-array.d.ts +43 -0
- package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +20 -0
- package/lib/table/data/tablemodel/areamodel/col-and-rowspan-model.d.ts +12 -0
- package/lib/table/data/tablemodel/table-model.d.ts +16 -2
- package/lib/table/ele-scope.d.ts +10 -1
- package/lib/table/factory/table-factory.d.ts +6 -1
- package/lib/table/focus/focus-model.d.ts +12 -0
- package/lib/table/focus/focus-model.if.d.ts +11 -0
- package/lib/table/live-append/append-rows-options.if.d.ts +101 -0
- package/lib/table/live-append/row-index-shift.d.ts +71 -0
- package/lib/table/mouse-handler.d.ts +57 -0
- package/lib/table/render-scope.d.ts +76 -10
- package/lib/table/selection/selection-model.d.ts +17 -0
- package/lib/table/selection/selection-model.if.d.ts +13 -0
- package/lib/table/selection/selection-service.d.ts +8 -0
- package/lib/table/table-api.d.ts +112 -17
- package/lib/table/table-scope.d.ts +51 -0
- package/llms.txt +572 -0
- package/package.json +4 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A scroll position – the argument of {@link TableApi.repaintHard} (since 1.1.107): the rows are counted again and the
|
|
3
|
+
* table shows this position in the same render pass. A missing axis keeps its position.
|
|
4
|
+
*
|
|
5
|
+
* - `px`: the horizontal scroll position from the start (0 = the first center column at the start; right-to-left
|
|
6
|
+
* measured from the right edge, see {@link TableOptionsIf.direction}) – the same as the first argument of
|
|
7
|
+
* {@link TableApi.scrollToPixel} (scroll bar pixels, not a column offset: for a column use `scrollToIndex`).
|
|
8
|
+
* - `py`: a **content** position from the top of the first body row (with the heights of open detail rows above) – the same as the second
|
|
9
|
+
* argument of {@link TableApi.scrollToPixel}, also exact with a capped scroll height (more than
|
|
10
|
+
* {@link EleScope.maxScrollHeightInPx} px of rows).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // live tail: rows were appended – count them and show row 500,000 (20 px rows) at the top
|
|
14
|
+
* tableApi.repaintHard({ py: 500_000 * 20 });
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // only horizontally: back to the first column, the vertical position stays
|
|
18
|
+
* tableApi.repaintHard({ px: 0 });
|
|
19
|
+
*
|
|
20
|
+
* @category Table & API
|
|
21
|
+
* @since 1.1.107
|
|
22
|
+
*/
|
|
23
|
+
export interface ScrollPositionIf {
|
|
24
|
+
/** Horizontal scroll position in px from the start (like `scrollToPixel`). Missing: the horizontal position stays. */
|
|
25
|
+
px?: number;
|
|
26
|
+
/** Vertical content position in px from the top of the first body row. Missing: the vertical position stays. */
|
|
27
|
+
py?: number;
|
|
28
|
+
}
|
|
@@ -118,15 +118,25 @@ export interface TableOptionsIf {
|
|
|
118
118
|
*/
|
|
119
119
|
horizontalBorderVisible: boolean;
|
|
120
120
|
/**
|
|
121
|
-
* The
|
|
121
|
+
* The css `overflow-x` of the scroll viewport (`.ge-table-scroll-viewport`): `"auto"` (default) shows the horizontal
|
|
122
|
+
* scroll bar only when the columns are wider than the table, `"scroll"` always.
|
|
122
123
|
*
|
|
123
|
-
*
|
|
124
|
+
* To hide the scroll bars completely use CSS – there is no `"hidden"` (wheel, touch, keyboard and the API still
|
|
125
|
+
* scroll, the table lays out without the bars):
|
|
126
|
+
* ```css
|
|
127
|
+
* .my-table .ge-table-scroll-viewport { scrollbar-width: none; }
|
|
128
|
+
* ```
|
|
124
129
|
*/
|
|
125
130
|
overflowX: "auto" | "scroll";
|
|
126
131
|
/**
|
|
127
|
-
* The
|
|
132
|
+
* The css `overflow-y` of the scroll viewport (`.ge-table-scroll-viewport`): `"auto"` (default) shows the vertical
|
|
133
|
+
* scroll bar only when the rows are higher than the body, `"scroll"` always.
|
|
128
134
|
*
|
|
129
|
-
*
|
|
135
|
+
* To hide the scroll bars completely use CSS – there is no `"hidden"` (wheel, touch, keyboard and the API still
|
|
136
|
+
* scroll, the table lays out without the bars):
|
|
137
|
+
* ```css
|
|
138
|
+
* .my-table .ge-table-scroll-viewport { scrollbar-width: none; }
|
|
139
|
+
* ```
|
|
130
140
|
*/
|
|
131
141
|
overflowY: "auto" | "scroll";
|
|
132
142
|
/**
|
|
@@ -19,6 +19,10 @@ export declare abstract class AbstractAreaModel<T> implements AreaModelIf, HasDe
|
|
|
19
19
|
private columnValuesInstance?;
|
|
20
20
|
private calcTextRenderer?;
|
|
21
21
|
protected cellRenderers: (CellRendererIf | undefined)[];
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated since 1.1.107 – filled by `init()` for `defaultRowHeight -1`, but no longer read:
|
|
24
|
+
* {@link getYPosByRowIndex} sums `getRowHeight()` (the cache missed rows added after `init()`).
|
|
25
|
+
*/
|
|
22
26
|
protected yPositions: number[];
|
|
23
27
|
/** Cell formulas of the table (since 1.1.99, set by the table for a flat body). @internal */
|
|
24
28
|
sheetCells?: SheetCellsIf;
|
|
@@ -41,6 +45,25 @@ export declare abstract class AbstractAreaModel<T> implements AreaModelIf, HasDe
|
|
|
41
45
|
setRowChecked(rowIndex: number, checked: boolean): void;
|
|
42
46
|
getMaxColspan(): number;
|
|
43
47
|
getMaxRowspan(): number;
|
|
48
|
+
/**
|
|
49
|
+
* The top of a row in px from the first row of this area.
|
|
50
|
+
*
|
|
51
|
+
* With a constant row height (`getConstantRowHeight()` of the subclass – the built-in models return their
|
|
52
|
+
* `defaultRowHeight` as long as `getRowHeight()` is not overridden) it is `rowIndex × height` (O(1)); otherwise the
|
|
53
|
+
* sum of `getRowHeight()` of all rows above (O(n), always up to date). Before 1.1.107 it was
|
|
54
|
+
* `defaultRowHeight × rowIndex` also when a subclass overrode `getRowHeight()`, and for `defaultRowHeight -1` a cache
|
|
55
|
+
* from `init()` that missed rows added later. The table itself positions the body rows with its own row layout.
|
|
56
|
+
*
|
|
57
|
+
* @param {number} rowIndex - the index of the row
|
|
58
|
+
* @returns {number} px from the top of the first row
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // a subclass with taller even rows: the positions follow the overridden getRowHeight()
|
|
62
|
+
* class Striped extends AreaModelObjectArray<any> {
|
|
63
|
+
* override getRowHeight(rowIndex: number): number { return rowIndex % 2 ? 20 : 40; }
|
|
64
|
+
* }
|
|
65
|
+
* const y = new Striped("body", rows, 34, columnDefs).getYPosByRowIndex(3); // 40 + 20 + 40 = 100
|
|
66
|
+
*/
|
|
44
67
|
getYPosByRowIndex(rowIndex: number): number;
|
|
45
68
|
init(): void;
|
|
46
69
|
abstract externalFilterChanged<T>(predictFn: FilterFunction<T>): void;
|
|
@@ -47,7 +47,7 @@ export declare class AreaModelCellGroups implements AreaModelIf {
|
|
|
47
47
|
getTooltipAt(_rowIndex: number, _columnIndex: number): any;
|
|
48
48
|
getValueAt(rowIndex: number, columnIndex: number): any;
|
|
49
49
|
getTextValueAt(rowIndex: number, columnIndex: number): string;
|
|
50
|
-
getYPosByRowIndex(
|
|
50
|
+
getYPosByRowIndex(rowIndex: number): number;
|
|
51
51
|
getRowHeight(_rowIndex: number): number;
|
|
52
52
|
isEditable(_rowIndex: number, _columnIndex: number): boolean;
|
|
53
53
|
isFilterable(): boolean;
|
|
@@ -9,6 +9,7 @@ import { CellRendererIf } from '../../../renderer/cell-render.if.js';
|
|
|
9
9
|
import { DerivedValuesChangeIf } from './derived-values-change.if.js';
|
|
10
10
|
import { ShowValuesAsIf } from '../../../calc/show-values-as.type.js';
|
|
11
11
|
import { RowDropTargetIf } from '../../../row-drag/row-drop-target.if.js';
|
|
12
|
+
import { AppendRowsContextIf, AppendRowsModelResultIf } from '../../../live-append/append-rows-options.if.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* @class AreaModelObjectArray
|
|
@@ -175,6 +176,11 @@ export declare class AreaModelObjectArray<T> extends AbstractAreaModel<T> implem
|
|
|
175
176
|
* @internal
|
|
176
177
|
*/
|
|
177
178
|
protected sorterService: SorterService;
|
|
179
|
+
/**
|
|
180
|
+
* True while the displayed rows are in the order of {@link getAllRows} (unsorted, maybe filtered) – then the rows a
|
|
181
|
+
* ring buffer removes at the start are a prefix of the displayed rows (no O(n) search, see {@link appendRows}).
|
|
182
|
+
*/
|
|
183
|
+
private displayInDataOrder;
|
|
178
184
|
/** Cached „Show values as“ values per property (cleared on filter, sorting and invalidation). */
|
|
179
185
|
private showValuesCache;
|
|
180
186
|
/**
|
|
@@ -251,6 +257,43 @@ export declare class AreaModelObjectArray<T> extends AbstractAreaModel<T> implem
|
|
|
251
257
|
* bodyAreaModel.setRows(newRows);
|
|
252
258
|
*/
|
|
253
259
|
setRows(rows: T[]): void;
|
|
260
|
+
/**
|
|
261
|
+
* Live data (since 1.1.108): appends rows **in place** to {@link getAllRows} (your array – no copy) and to the
|
|
262
|
+
* displayed rows: the active filter runs only for the new rows (O(k)), with an active sort order they are sorted
|
|
263
|
+
* and merged in (O(n + k), stable – behind equal rows, like a sort of all rows). With `ctx.maxRows` the oldest
|
|
264
|
+
* rows are removed from the start (ring buffer) – in blocks of at least 1 % of `maxRows` (moving the rows of an
|
|
265
|
+
* array is O(n)), so the row count stays between 99 % and 100 % of `maxRows`. Use `tableApi.appendRows()` – it passes filter and order and moves
|
|
266
|
+
* selection, focus and scroll position along.
|
|
267
|
+
*
|
|
268
|
+
* @param {unknown[]} newRows - the new rows (appended in this order)
|
|
269
|
+
* @param {AppendRowsContextIf<T>} [ctx] - active filter, sort order, ring buffer size
|
|
270
|
+
* @returns {AppendRowsModelResultIf} the removed and inserted display positions
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* const result = bodyAreaModel.appendRows(lines, { maxRows: 100_000 });
|
|
274
|
+
* console.log(result.insertedPositions); // where the new rows are shown
|
|
275
|
+
*
|
|
276
|
+
* @since 1.1.108
|
|
277
|
+
*/
|
|
278
|
+
appendRows(newRows: unknown[], ctx?: AppendRowsContextIf<T>): AppendRowsModelResultIf;
|
|
279
|
+
/** Removes the first `count` rows of the data (in place) and of the displayed rows; their old display positions. */
|
|
280
|
+
private removeFirstRows;
|
|
281
|
+
private appendShown;
|
|
282
|
+
/** Sorts the new rows and merges them into the (sorted) displayed rows from the back – stable, in place. */
|
|
283
|
+
private mergeSorted;
|
|
284
|
+
/**
|
|
285
|
+
* The comparator of sort items (first item = primary key, the following ones break ties), as used by
|
|
286
|
+
* {@link doSort} – e.g. to sort new rows in (live data). `undefined` if no item sorts (state "").
|
|
287
|
+
*
|
|
288
|
+
* @param {SortItem[]} sortItems - column index and sort state per sorted column
|
|
289
|
+
* @returns {((a: T, b: T) => number) | undefined} the comparator
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* const compare = bodyAreaModel.createSortComparator([new SortItem(2, "desc")]);
|
|
293
|
+
*
|
|
294
|
+
* @since 1.1.108
|
|
295
|
+
*/
|
|
296
|
+
createSortComparator(sortItems: SortItem[]): ((a: T, b: T) => number) | undefined;
|
|
254
297
|
/**
|
|
255
298
|
* Filters both the original rows and filtered rows arrays using the provided predicate function.
|
|
256
299
|
* Unlike `externalFilterChanged`, this method permanently modifies the original rows array.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RowDropTargetIf } from '../../../row-drag/row-drop-target.if.js';
|
|
2
|
+
import { AppendRowsContextIf, AppendRowsModelResultIf } from '../../../live-append/append-rows-options.if.js';
|
|
2
3
|
import { DerivedValuesChangeIf } from './derived-values-change.if.js';
|
|
3
4
|
import { CellRendererIf } from '../../../renderer/cell-render.if.js';
|
|
4
5
|
import { CheckedType } from '../../common/checked-type.js';
|
|
@@ -316,6 +317,19 @@ export interface AreaModelIf {
|
|
|
316
317
|
* @since 1.1.95
|
|
317
318
|
*/
|
|
318
319
|
moveRows?(rowIndices: number[], target: RowDropTargetIf): boolean;
|
|
320
|
+
/**
|
|
321
|
+
* Optional (live data, since 1.1.108): appends rows **in place** – the active filter only for the new rows, sorted
|
|
322
|
+
* in by the active order, oldest rows removed for a ring buffer – and reports the display positions, so the table
|
|
323
|
+
* moves selection, focus and scroll position along (`tableApi.appendRows()`). Implemented by
|
|
324
|
+
* {@link AreaModelObjectArray}; `false` = not supported (the table logs a warning and changes nothing).
|
|
325
|
+
*
|
|
326
|
+
* @param {unknown[]} rows - the new rows
|
|
327
|
+
* @param {AppendRowsContextIf} ctx - active filter, sort order, ring buffer size
|
|
328
|
+
* @returns {AppendRowsModelResultIf | false} what changed, or false
|
|
329
|
+
* @example
|
|
330
|
+
* const result = bodyModel.appendRows?.(lines, { maxRows: 100_000 });
|
|
331
|
+
*/
|
|
332
|
+
appendRows?(rows: unknown[], ctx: AppendRowsContextIf): AppendRowsModelResultIf | false;
|
|
319
333
|
/**
|
|
320
334
|
* Optional: drops cached, derived values (e.g. the totals of an {@link AreaModelAggregateFooter}). The table calls
|
|
321
335
|
* it for all three areas when data may have changed: filter, sorting, editing, `updateCells()` and the public
|
|
@@ -663,6 +677,10 @@ export interface AreaModelIf {
|
|
|
663
677
|
* Returns the height of the row at the specified index, in pixels.
|
|
664
678
|
* This method allows for variable row heights in the table.
|
|
665
679
|
*
|
|
680
|
+
* The table draws the rows with these heights, and since 1.1.107 the height of the area (scroll height of the body,
|
|
681
|
+
* height of header and footer) is their sum as well – {@link getConstantRowHeight} × row count if given.
|
|
682
|
+
* `defaultRowHeights` of the table model only counts if every row height is 0.
|
|
683
|
+
*
|
|
666
684
|
* @param {number} rowIndex - The index of the row
|
|
667
685
|
* @returns {number} The height of the row in pixels
|
|
668
686
|
*
|
|
@@ -699,6 +717,8 @@ export interface AreaModelIf {
|
|
|
699
717
|
* of all rows above it – with millions of rows this keeps scrolling at the end of the table as fast as at
|
|
700
718
|
* the beginning. Only return a number if `getRowHeight(i)` returns exactly this value for every row.
|
|
701
719
|
* If the method is missing or returns `undefined`, the renderer falls back to iterating the row heights.
|
|
720
|
+
* The height of the area (the scroll height of the body) is then this value × row count – O(1) – and wins over
|
|
721
|
+
* `defaultRowHeights` of the table model (since 1.1.107; before, `defaultRowHeights` came first).
|
|
702
722
|
*
|
|
703
723
|
* @returns {number | undefined} The constant row height in pixels, or `undefined` if row heights may vary.
|
|
704
724
|
*
|
|
@@ -15,6 +15,18 @@ export declare class ColAndRowspanModel {
|
|
|
15
15
|
/** Row count of the area model at the last {@link init} (−1: not initialized yet). */
|
|
16
16
|
protected rowCountAtInit: number;
|
|
17
17
|
init(): void;
|
|
18
|
+
/** Adds the spans starting in a row. */
|
|
19
|
+
private scanRow;
|
|
20
|
+
/**
|
|
21
|
+
* Live data (since 1.1.108): rows were inserted (and maybe removed at the start) – scans only the inserted rows
|
|
22
|
+
* (O(k)) instead of all rows ({@link init}: O(n) per update, because most area models report a possible span of 31).
|
|
23
|
+
* Only possible while no span exists; otherwise (or before the first init) false – then {@link initIfRowCountChanged}
|
|
24
|
+
* builds the ranges again.
|
|
25
|
+
*
|
|
26
|
+
* @param {ArrayLike<number>} insertedPositions - display indices of the inserted rows (after the step), ascending
|
|
27
|
+
* @returns {boolean} true if the ranges are up to date
|
|
28
|
+
*/
|
|
29
|
+
updateForInsertedRows(insertedPositions: ArrayLike<number>): boolean;
|
|
18
30
|
/**
|
|
19
31
|
* Builds the ranges again if the row count of the area model changed since the last {@link init} – e.g. after
|
|
20
32
|
* `setRows()` or a filter (the old ranges could point to rows that no longer exist). Cheap otherwise.
|
|
@@ -157,10 +157,24 @@ export declare class TableModel implements TableModelIf {
|
|
|
157
157
|
*/
|
|
158
158
|
getModel(rowAreaIdent: AreaIdent): AreaModelIf;
|
|
159
159
|
/**
|
|
160
|
-
* Calculates the height of the area identified by the given area identifier
|
|
160
|
+
* Calculates the height of the area identified by the given area identifier – the height of the rows the table
|
|
161
|
+
* draws (since 1.1.107 the same source as the rendering):
|
|
162
|
+
*
|
|
163
|
+
* 1. `getConstantRowHeight()` of the area model (> 0): row count × that height – O(1), also for millions of rows,
|
|
164
|
+
* 2. otherwise the sum of `getRowHeight(i)` of all rows (variable heights; O(n), like the row layout of the body),
|
|
165
|
+
* 3. only if the model has no row heights of its own (every `getRowHeight(i)` is 0): row count ×
|
|
166
|
+
* `defaultRowHeights[area]`.
|
|
167
|
+
*
|
|
168
|
+
* Before 1.1.107 `defaultRowHeights[area]` came first: an area model with other heights got a wrong scroll height
|
|
169
|
+
* (a scroll bar without overflow, a wrong thumb). The built-in area models take their row height from
|
|
170
|
+
* `defaultRowHeights` anyway, so nothing changes for them.
|
|
161
171
|
*
|
|
162
172
|
* @param {AreaIdent} areaIdent - The identifier of the area.
|
|
163
|
-
* @return {number} - The height of the area.
|
|
173
|
+
* @return {number} - The height of the area in px.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* // an own body with 20 px rows: 3000 rows are 60,000 px high – also if defaultRowHeights.body is 34
|
|
177
|
+
* const height = (tableModel as TableModel).getAreaHeight("body");
|
|
164
178
|
*/
|
|
165
179
|
getAreaHeight(areaIdent: AreaIdent): number;
|
|
166
180
|
/**
|
package/lib/table/ele-scope.d.ts
CHANGED
|
@@ -140,11 +140,20 @@ export declare class EleScope {
|
|
|
140
140
|
/** The element that holds the rows of an area (`DivScope.child`). */
|
|
141
141
|
protected getAreaChild(area: AreaIdent, side: SideIdent): HTMLDivElement;
|
|
142
142
|
/**
|
|
143
|
-
* Adjusts the containers and rows of the table based on the current state
|
|
143
|
+
* Adjusts the containers and rows of the table based on the current state: lays out the areas
|
|
144
|
+
* ({@link layoutContainers}) and renders the visible rows ({@link adjustAfterScrolling}).
|
|
144
145
|
*
|
|
145
146
|
* @return {void}
|
|
146
147
|
*/
|
|
147
148
|
adjustContainersAndRows(): void;
|
|
149
|
+
/**
|
|
150
|
+
* Lays out the scroll viewport, the nine areas, the separator borders, the overlay and the detail layer for the
|
|
151
|
+
* current size of the host and the current padding – without rendering the rows (that is
|
|
152
|
+
* {@link adjustAfterScrolling}). `repaintHard()` uses it to set a new scroll position before its one render pass.
|
|
153
|
+
*
|
|
154
|
+
* @since 1.1.107
|
|
155
|
+
*/
|
|
156
|
+
protected layoutContainers(): void;
|
|
148
157
|
/**
|
|
149
158
|
* The height the table lays out header, body and footer in: the host height minus a horizontal scroll bar that
|
|
150
159
|
* takes space (see {@link horizontalScrollBarHeight}).
|
|
@@ -103,7 +103,12 @@ export interface CreateTableModelPara {
|
|
|
103
103
|
* @since 1.1.99
|
|
104
104
|
*/
|
|
105
105
|
columnLetters: boolean;
|
|
106
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Row heights of header, body and footer in px. Default: `tableOptions.defaultRowHeights`, otherwise 34 / 34 / 34.
|
|
108
|
+
* The area models built by the factory get these heights. An own area model (`bodyAreaModel` …) keeps its own:
|
|
109
|
+
* since 1.1.107 the table measures every area with the heights of its model (`getConstantRowHeight()`, otherwise
|
|
110
|
+
* `getRowHeight(i)`) – `defaultRowHeights` only counts for a model whose `getRowHeight()` returns 0.
|
|
111
|
+
*/
|
|
107
112
|
defaultRowHeights: DefaultRowHeightsIf;
|
|
108
113
|
/** The columns: property, header label, width, classes, renderers, sorting, editing. See {@link ColumnDef}. */
|
|
109
114
|
columnDefs: ColumnDefIf[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FocusType } from './focus.type.js';
|
|
2
2
|
import { FocusModelIf } from './focus-model.if.js';
|
|
3
3
|
import { EventFocusChangedListenerIf } from './event-focus-changed-listener.if.js';
|
|
4
|
+
import { RowIndexShift } from '../live-append/row-index-shift.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* The `FocusModel` class is an implementation of the `FocusModelIf` interface.
|
|
@@ -63,6 +64,17 @@ export declare class FocusModel implements FocusModelIf {
|
|
|
63
64
|
hasChanged(): boolean;
|
|
64
65
|
clear(): void;
|
|
65
66
|
setFocus(rowIndex: number, columnIndex: number): void;
|
|
67
|
+
/**
|
|
68
|
+
* Live data (since 1.1.108): the focused row moves along when rows were removed at the start or inserted
|
|
69
|
+
* (`tableApi.appendRows()`). The same row keeps the focus without an event; if it was removed, the next remaining
|
|
70
|
+
* row gets it (with an event – the table keeps it inside the rows).
|
|
71
|
+
*
|
|
72
|
+
* @param {RowIndexShift} shift - how the display indices move
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* focusModel.adjustForRowChanges?.(new RowIndexShift([0, 1], [])); // row 5 → row 3
|
|
76
|
+
*/
|
|
77
|
+
adjustForRowChanges(shift: RowIndexShift): void;
|
|
66
78
|
hasFocus(rowIndex: number, columnIndex: number): boolean;
|
|
67
79
|
getFocus(): [number, number];
|
|
68
80
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EventFocusChangedListenerIf } from './event-focus-changed-listener.if.js';
|
|
2
|
+
import { RowIndexShift } from '../live-append/row-index-shift.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* The focused cell of a table (moved by click and arrow keys; F2 edits it). The implementation is {@link FocusModel};
|
|
@@ -31,4 +32,14 @@ export interface FocusModelIf {
|
|
|
31
32
|
hasChanged(): boolean;
|
|
32
33
|
/** Resets {@link hasChanged}. */
|
|
33
34
|
clearChanged(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Optional (live data, since 1.1.108): the focused row moves along when rows were removed at the start or
|
|
37
|
+
* inserted (`tableApi.appendRows()`). Same row: no event. Focused row removed: the next remaining row gets the
|
|
38
|
+
* focus (with an event).
|
|
39
|
+
*
|
|
40
|
+
* @param {RowIndexShift} shift - how the display indices move
|
|
41
|
+
* @example
|
|
42
|
+
* focusModel.adjustForRowChanges?.(new RowIndexShift([0], []));
|
|
43
|
+
*/
|
|
44
|
+
adjustForRowChanges?(shift: RowIndexShift): void;
|
|
34
45
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the view goes after new rows came in (`tableApi.appendRows()` / `rowsAppended()`):
|
|
3
|
+
* - `"auto"` (default): it follows the end if it was at the end before ("tail -f"), otherwise the first visible row
|
|
4
|
+
* stays where it is;
|
|
5
|
+
* - `true`: always to the end;
|
|
6
|
+
* - `false`: the first visible row always stays (a "freeze scroll" button of the app).
|
|
7
|
+
*
|
|
8
|
+
* While the mouse button is held in the table (a click, a drag), `"auto"` keeps the row – the content does not slide
|
|
9
|
+
* away under the pointer.
|
|
10
|
+
*
|
|
11
|
+
* @category Live data
|
|
12
|
+
* @since 1.1.108
|
|
13
|
+
*/
|
|
14
|
+
export type AppendFollowMode = "auto" | boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Options of `tableApi.appendRows(rows, options)`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const result = tableApi.appendRows(lines, { follow: "auto", maxRows: 1_000_000 });
|
|
20
|
+
*
|
|
21
|
+
* @category Live data
|
|
22
|
+
* @since 1.1.108
|
|
23
|
+
*/
|
|
24
|
+
export interface AppendRowsOptionsIf {
|
|
25
|
+
/** Where the view goes – see {@link AppendFollowMode}. Default `"auto"`. */
|
|
26
|
+
follow?: AppendFollowMode;
|
|
27
|
+
/**
|
|
28
|
+
* Ring buffer: keep at most this many rows – the oldest (first) rows of the data are removed from the start, in
|
|
29
|
+
* blocks of at least 1 % of `maxRows` (removing from the start of an array moves all rows: O(n) – the blocks make
|
|
30
|
+
* that rare), so the row count stays between 99 % and 100 % of `maxRows`.
|
|
31
|
+
* Selection, focus and the visible row stay at their rows; a selected row that is removed leaves the selection.
|
|
32
|
+
*/
|
|
33
|
+
maxRows?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Options of `tableApi.rowsAppended(count, options)` – an own area model that appended (and maybe removed) rows
|
|
37
|
+
* itself.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const logLines: string[] = []; // the data of an own area model
|
|
41
|
+
* for (const line of newLines) logLines.push(line);
|
|
42
|
+
* const dropped = Math.max(0, logLines.length - 100_000);
|
|
43
|
+
* logLines.splice(0, dropped); // the app keeps its own ring buffer
|
|
44
|
+
* tableApi.rowsAppended(newLines.length, { follow: "auto", removedAtStart: dropped });
|
|
45
|
+
*
|
|
46
|
+
* @category Live data
|
|
47
|
+
* @since 1.1.108
|
|
48
|
+
*/
|
|
49
|
+
export interface RowsAppendedOptionsIf {
|
|
50
|
+
/** Where the view goes – see {@link AppendFollowMode}. Default `"auto"`. */
|
|
51
|
+
follow?: AppendFollowMode;
|
|
52
|
+
/** Number of rows the app removed at the start (display indices 0 … n-1 before the step). Default 0. */
|
|
53
|
+
removedAtStart?: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Result of `tableApi.appendRows()` / `rowsAppended()`.
|
|
57
|
+
*
|
|
58
|
+
* @category Live data
|
|
59
|
+
* @since 1.1.108
|
|
60
|
+
*/
|
|
61
|
+
export interface AppendRowsResultIf {
|
|
62
|
+
/** rows added to the data */
|
|
63
|
+
added: number;
|
|
64
|
+
/** of them shown (an active filter hides the others) */
|
|
65
|
+
shown: number;
|
|
66
|
+
/** rows removed at the start (`maxRows` / `removedAtStart`) */
|
|
67
|
+
removed: number;
|
|
68
|
+
/** true if the view follows the end after this update */
|
|
69
|
+
following: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* What a table passes to {@link AreaModelIf.appendRows}: the active filter and sort order, so the model treats only
|
|
73
|
+
* the new rows (O(k) unsorted, O(n + k) sorted).
|
|
74
|
+
*
|
|
75
|
+
* @category Live data
|
|
76
|
+
* @since 1.1.108
|
|
77
|
+
*/
|
|
78
|
+
export interface AppendRowsContextIf<T = unknown> {
|
|
79
|
+
/** the active filter (`tableOptions.externalFilterFunction`) – new rows it rejects are kept but not shown */
|
|
80
|
+
filter?: (row: T) => boolean;
|
|
81
|
+
/** the active sort order – new rows are inserted at their place (stable: behind equal rows) */
|
|
82
|
+
compare?: (a: T, b: T) => number;
|
|
83
|
+
/** ring buffer size, see {@link AppendRowsOptionsIf.maxRows} */
|
|
84
|
+
maxRows?: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* What {@link AreaModelIf.appendRows} did – the table moves selection, focus and position along.
|
|
88
|
+
*
|
|
89
|
+
* @category Live data
|
|
90
|
+
* @since 1.1.108
|
|
91
|
+
*/
|
|
92
|
+
export interface AppendRowsModelResultIf {
|
|
93
|
+
added: number;
|
|
94
|
+
shown: number;
|
|
95
|
+
/** rows removed from the data */
|
|
96
|
+
removed: number;
|
|
97
|
+
/** display indices **before** the step of the removed rows that were shown, ascending */
|
|
98
|
+
removedPositions: Int32Array;
|
|
99
|
+
/** display indices **after** the step of the new shown rows, ascending */
|
|
100
|
+
insertedPositions: Int32Array;
|
|
101
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the display indices of the body rows move when rows are removed and inserted in one step (live data:
|
|
3
|
+
* `tableApi.appendRows()` / `rowsAppended()`, since 1.1.108) – so selection, focus and anchor stay at the same rows
|
|
4
|
+
* instead of being cleared. DOM-free.
|
|
5
|
+
*
|
|
6
|
+
* Order: first the `removed` rows leave (indices **before** the step), then the `inserted` rows come in (indices
|
|
7
|
+
* **after** the step). An old row keeps its relative order.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // 2 rows dropped at the start (ring buffer), 3 appended at the end of 10 → 11 rows
|
|
11
|
+
* const shift = new RowIndexShift([0, 1], [8, 9, 10]);
|
|
12
|
+
* shift.mapIndex(5); // 3
|
|
13
|
+
* shift.mapIndex(1); // -1 (removed)
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // sorted: one row inserted at display index 2 (between the old rows 1 and 2)
|
|
17
|
+
* const shift = new RowIndexShift([], [2]);
|
|
18
|
+
* shift.mapRange(0, 4); // [[0, 1], [3, 5]] – the new row splits the range (it is not selected)
|
|
19
|
+
*
|
|
20
|
+
* @category Live data
|
|
21
|
+
* @since 1.1.108
|
|
22
|
+
*/
|
|
23
|
+
export declare class RowIndexShift {
|
|
24
|
+
private readonly removed;
|
|
25
|
+
private readonly inserted;
|
|
26
|
+
/** inserted[j] - j: the number of old rows in front of the inserted row j (non-decreasing) */
|
|
27
|
+
private readonly insertBefore;
|
|
28
|
+
/**
|
|
29
|
+
* @param {ArrayLike<number>} removed - display indices before the step of the removed rows, ascending, unique
|
|
30
|
+
* @param {ArrayLike<number>} inserted - display indices after the step of the inserted rows, ascending, unique
|
|
31
|
+
*/
|
|
32
|
+
constructor(removed?: ArrayLike<number>, inserted?: ArrayLike<number>);
|
|
33
|
+
/** True if nothing moves (no row removed, none inserted). */
|
|
34
|
+
isEmpty(): boolean;
|
|
35
|
+
/** Number of removed rows. */
|
|
36
|
+
getRemovedCount(): number;
|
|
37
|
+
/** Number of inserted rows. */
|
|
38
|
+
getInsertedCount(): number;
|
|
39
|
+
/**
|
|
40
|
+
* True if a row at an old display index `<= index` is removed or a row is inserted in front of the old row `index`
|
|
41
|
+
* (i.e. the rows `0 … index` are not the same as before).
|
|
42
|
+
*
|
|
43
|
+
* @param {number} index - an old display index
|
|
44
|
+
* @returns {boolean} true if the rows up to this index changed
|
|
45
|
+
*/
|
|
46
|
+
touchesUpTo(index: number): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The new display index of an old one.
|
|
49
|
+
*
|
|
50
|
+
* @param {number} index - display index before the step
|
|
51
|
+
* @returns {number} the index after the step, -1 if the row was removed (or `index` is negative)
|
|
52
|
+
*/
|
|
53
|
+
mapIndex(index: number): number;
|
|
54
|
+
/**
|
|
55
|
+
* The display index after the step of the first remaining row at or after an old index – for a position that
|
|
56
|
+
* must stay on a row (e.g. the first visible row) when that row itself was removed.
|
|
57
|
+
*
|
|
58
|
+
* @param {number} index - display index before the step
|
|
59
|
+
* @returns {number} the index after the step (the end if no old row at or after `index` remains)
|
|
60
|
+
*/
|
|
61
|
+
mapIndexOrNext(index: number): number;
|
|
62
|
+
/**
|
|
63
|
+
* The new ranges of an old range of rows `lo … hi` (inclusive): removed rows leave it, inserted rows inside split
|
|
64
|
+
* it (they are not part of it). `hi = Number.MAX_SAFE_INTEGER` (whole columns) stays open at the end.
|
|
65
|
+
*
|
|
66
|
+
* @param {number} lo - first row of the range before the step
|
|
67
|
+
* @param {number} hi - last row of the range before the step (inclusive)
|
|
68
|
+
* @returns {[number, number][]} the pieces after the step, ascending, `[]` if all its rows were removed
|
|
69
|
+
*/
|
|
70
|
+
mapRange(lo: number, hi: number): [number, number][];
|
|
71
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TableScope } from './table-scope.js';
|
|
2
2
|
import { GeMouseEvent } from './data/common/event/ge-mouse-event.js';
|
|
3
|
+
import { RowIndexShift } from './live-append/row-index-shift.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Class representing a MouseHandler.
|
|
@@ -17,11 +18,26 @@ export declare class MouseHandler {
|
|
|
17
18
|
* @type {number}
|
|
18
19
|
*/
|
|
19
20
|
doubleClickDelay: number;
|
|
21
|
+
/**
|
|
22
|
+
* A render between mousedown and mouseup replaces the pressed cell, and the browser sends no "click" (both must hit
|
|
23
|
+
* the same element). The handler then reports the click itself for the pressed cell – if the mouse moved at most
|
|
24
|
+
* this many pixels (screen coordinates) between mousedown and mouseup. Since 1.1.108.
|
|
25
|
+
*
|
|
26
|
+
* @type {number}
|
|
27
|
+
*/
|
|
28
|
+
clickMoveTolerance: number;
|
|
20
29
|
mouseEvent?: MouseEvent;
|
|
21
30
|
startMouseEvent?: GeMouseEvent;
|
|
22
31
|
geMouseEvent?: GeMouseEvent;
|
|
23
32
|
geMouseEventOld?: GeMouseEvent;
|
|
24
33
|
private lastClickedCellKey;
|
|
34
|
+
/** The cell of the last left-button mousedown (see {@link PressedCell}). */
|
|
35
|
+
private pressedCell?;
|
|
36
|
+
/** Counts native "click" / "dblclick" events: a report of a lost click is dropped if the browser sent one after all. */
|
|
37
|
+
private nativeClickCount;
|
|
38
|
+
private nativeDblClickCount;
|
|
39
|
+
/** Timer of a pending report of a lost click (cleared by destroy via the abort signal). */
|
|
40
|
+
private lostClickTimer?;
|
|
25
41
|
/** The second click of a double click that was already reported (clickCount 2) – its "dblclick" is not. */
|
|
26
42
|
private reportedDoubleClick?;
|
|
27
43
|
private mouseDown;
|
|
@@ -49,6 +65,16 @@ export declare class MouseHandler {
|
|
|
49
65
|
* @return {void}
|
|
50
66
|
*/
|
|
51
67
|
private onHostElementClicked;
|
|
68
|
+
/**
|
|
69
|
+
* Handles a click: on `eventTarget`, or – if `cell` is given – on that cell (a click the browser did not send
|
|
70
|
+
* because a render replaced the pressed element; `eventTarget` is then the detached pressed element).
|
|
71
|
+
*/
|
|
72
|
+
private handleClick;
|
|
73
|
+
/** "area:row:column" of a cell given explicitly (same format as {@link getCellKey}). */
|
|
74
|
+
private toCellKey;
|
|
75
|
+
/** Target data of a replaced element: area, row and column come from the pressed cell (current row index). */
|
|
76
|
+
private applyCell;
|
|
77
|
+
private createCellEvent;
|
|
52
78
|
/** "area:row:column" of the cell of an event target ('' outside of a cell). */
|
|
53
79
|
private getCellKey;
|
|
54
80
|
/** A click that triggers an action on its own: row checkbox, tree arrow, "expand/collapse all", header group toggle. */
|
|
@@ -60,6 +86,8 @@ export declare class MouseHandler {
|
|
|
60
86
|
* @param {MouseEvent} event - The double click event.
|
|
61
87
|
*/
|
|
62
88
|
private onHostElementDblClicked;
|
|
89
|
+
/** Handles a double click on `eventTarget`, or on `cell` (see {@link handleClick}). */
|
|
90
|
+
private handleDblClick;
|
|
63
91
|
/**
|
|
64
92
|
* Publishes a GeMouseEvent.
|
|
65
93
|
*
|
|
@@ -77,12 +105,41 @@ export declare class MouseHandler {
|
|
|
77
105
|
private isInteractiveCellElement;
|
|
78
106
|
private getArrowColumnIndex;
|
|
79
107
|
private onMouseDown;
|
|
108
|
+
/** A mouseup that did not reach the host (released outside the table). */
|
|
109
|
+
private onDocumentMouseUp;
|
|
110
|
+
/**
|
|
111
|
+
* Live data (since 1.1.108): a drag in progress (range selection) keeps its start row when rows were removed at the
|
|
112
|
+
* start or inserted.
|
|
113
|
+
*
|
|
114
|
+
* @param {RowIndexShift} shift - how the display indices move
|
|
115
|
+
*/
|
|
116
|
+
adjustForRowChanges(shift: RowIndexShift): void;
|
|
80
117
|
private onMouseMove;
|
|
81
118
|
private onMouseUp;
|
|
119
|
+
/** The cell under a mousedown, or undefined outside of a cell. */
|
|
120
|
+
private readPressedCell;
|
|
121
|
+
/**
|
|
122
|
+
* After a mouseup: if a render replaced the pressed element, the browser sends no "click" (nor "dblclick"). Then the
|
|
123
|
+
* click is reported for the pressed cell – once this task is through and only if no native click came after all.
|
|
124
|
+
*/
|
|
125
|
+
private checkLostClick;
|
|
126
|
+
/**
|
|
127
|
+
* The current index of the pressed row: rows may have been added, removed or sorted in while the button was held.
|
|
128
|
+
* -1 if the row is gone.
|
|
129
|
+
*/
|
|
130
|
+
private resolveRowIndex;
|
|
131
|
+
private rowAt;
|
|
82
132
|
private mouseDraggingOnFrame;
|
|
83
133
|
/** Handles the end of the last drag now (in its frame, or earlier when the next mousedown comes first). */
|
|
84
134
|
private flushDraggingEnd;
|
|
85
135
|
private mouseMoveOnFrame;
|
|
136
|
+
/**
|
|
137
|
+
* True while the mouse button is held in the table (a click or a drag in progress) – live data does not jump to
|
|
138
|
+
* the end then (`tableApi.appendRows({ follow: "auto" })`, since 1.1.108).
|
|
139
|
+
*
|
|
140
|
+
* @returns {boolean} true between mousedown and mouseup
|
|
141
|
+
*/
|
|
142
|
+
isButtonDown(): boolean;
|
|
86
143
|
/** A mouse event on a blocking loading overlay ({@link TableOverlay.isEventBlocked}): the table ignores it. */
|
|
87
144
|
private isBlocked;
|
|
88
145
|
}
|