@guiexpert/table 1.1.107 → 1.1.109
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 +11 -0
- package/index.cjs +28 -28
- package/index.d.ts +2 -0
- package/index.js +2687 -2011
- 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 +14 -0
- package/lib/table/data/tablemodel/areamodel/col-and-rowspan-model.d.ts +12 -0
- 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 +31 -0
- 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 +82 -4
- package/lib/table/table-scope.d.ts +51 -0
- package/llms.txt +572 -0
- package/package.json +4 -1
|
@@ -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
|
|
@@ -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.
|
|
@@ -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
|
}
|
|
@@ -11,6 +11,7 @@ import { CellRange } from './data/common/cell-range.js';
|
|
|
11
11
|
import { RendererCleanupFnType } from './renderer/renderer-cleanup-fn.type.js';
|
|
12
12
|
import { AreaIdent } from './data/tablemodel/area-ident.type.js';
|
|
13
13
|
import { SideIdent } from './data/side-ident.type.js';
|
|
14
|
+
import { RowIndexShift } from './live-append/row-index-shift.js';
|
|
14
15
|
import { DivScope } from './data/div-scope.type.js';
|
|
15
16
|
import { DerivedValuesChangeIf } from './data/tablemodel/areamodel/derived-values-change.if.js';
|
|
16
17
|
import { AreaModelIf } from './data/tablemodel/areamodel/area-model.if.js';
|
|
@@ -73,6 +74,17 @@ export declare class RenderScope extends EleScope {
|
|
|
73
74
|
* that is already rendered (`repaintHard({ py })`, `scrollToPixel()` render it at once) renders nothing.
|
|
74
75
|
*/
|
|
75
76
|
protected renderedScrollTop: number;
|
|
77
|
+
/**
|
|
78
|
+
* The body rows of the last render pass (live data, since 1.1.108): row count, first visible row and the content
|
|
79
|
+
* offset into it, last (partly) visible row, and whether the view was at the end.
|
|
80
|
+
*/
|
|
81
|
+
protected renderedBodyRows: {
|
|
82
|
+
count: number;
|
|
83
|
+
first: number;
|
|
84
|
+
offset: number;
|
|
85
|
+
last: number;
|
|
86
|
+
atEnd: boolean;
|
|
87
|
+
};
|
|
76
88
|
protected renderedScrollLeft: number;
|
|
77
89
|
/** Area heights read once at the start of adjustAfterScrolling() (before the DOM is modified). */
|
|
78
90
|
protected areaHeightsOfRenderPass?: {
|
|
@@ -273,6 +285,13 @@ export declare class RenderScope extends EleScope {
|
|
|
273
285
|
*
|
|
274
286
|
* @returns {void}
|
|
275
287
|
*/
|
|
288
|
+
/**
|
|
289
|
+
* Live data (since 1.1.108): the in-cell editor (`getEditRenderer`) and its draft follow their row when rows were
|
|
290
|
+
* removed at the start or inserted; a removed row closes the editor.
|
|
291
|
+
*
|
|
292
|
+
* @param shift - how the display indices move
|
|
293
|
+
*/
|
|
294
|
+
protected shiftEditorRow(shift: RowIndexShift): void;
|
|
276
295
|
resetEditorRenderer(): void;
|
|
277
296
|
/**
|
|
278
297
|
* Clears the selection in the component.
|
|
@@ -313,6 +332,18 @@ export declare class RenderScope extends EleScope {
|
|
|
313
332
|
* @return {void} This method does not return any value.
|
|
314
333
|
*/
|
|
315
334
|
repaintHard(scrollTo?: ScrollPositionIf): void;
|
|
335
|
+
/** Remembers which body rows the render pass drew ({@link renderedBodyRows}) – two O(log n) lookups. */
|
|
336
|
+
private rememberRenderedBodyRows;
|
|
337
|
+
/**
|
|
338
|
+
* Live data (since 1.1.108, prompt 018 part B): the body got more rows, but the drawn rows stay the same (rows
|
|
339
|
+
* appended or sorted in behind the visible ones, the view does not follow). Updates heights, scroll content, scroll
|
|
340
|
+
* bar and `aria-rowcount` – **without** rebuilding the cells. Returns false (and does nothing more) if that is not
|
|
341
|
+
* enough: the vertical scroll bar appeared or disappeared (the widths change) or col-/rowspans exist.
|
|
342
|
+
*
|
|
343
|
+
* @param {number} py - the content position to keep (the same rows as drawn)
|
|
344
|
+
* @returns {boolean} true if done, false if the caller must render
|
|
345
|
+
*/
|
|
346
|
+
protected updateRowCountWithoutRender(py: number): boolean;
|
|
316
347
|
/**
|
|
317
348
|
* Sets the scroll position of the viewport to a content position **without rendering** (shared by
|
|
318
349
|
* `scrollToPixel()` and `repaintHard({ px, py })`). `py` is a content position: the scroll bar range differs from the
|
|
@@ -2,6 +2,7 @@ import { CellRange } from '../data/common/cell-range.js';
|
|
|
2
2
|
import { ExtendedSelectionType, SelectionMode } from './selection.type.js';
|
|
3
3
|
import { SelectionModelIf } from './selection-model.if.js';
|
|
4
4
|
import { EventSelectionChangedListenerIf } from './event-selection-changed-listener.if.js';
|
|
5
|
+
import { RowIndexShift } from '../live-append/row-index-shift.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Saved state of a {@link SelectionModel} – see {@link SelectionModel.createSnapshot}.
|
|
@@ -84,6 +85,22 @@ export declare class SelectionModel implements SelectionModelIf {
|
|
|
84
85
|
* @param {SelectionSnapshot} snapshot - the state to restore
|
|
85
86
|
*/
|
|
86
87
|
restoreSnapshot(snapshot: SelectionSnapshot): void;
|
|
88
|
+
/**
|
|
89
|
+
* Live data (since 1.1.108): moves the selected rows along when rows were removed at the start or inserted
|
|
90
|
+
* (`tableApi.appendRows()` / `rowsAppended()`). Ranges are adjusted **in place** (snapshots and the anchor of the
|
|
91
|
+
* selection service keep pointing at them); removed rows leave a range, rows inserted inside split it (not
|
|
92
|
+
* selected – like Excel); whole columns (`r1 = 0`, `r2 = MAX_SAFE_INTEGER`) and "all selected" stay. No event.
|
|
93
|
+
*
|
|
94
|
+
* @param {RowIndexShift} shift - how the display indices move
|
|
95
|
+
* @returns {boolean} true if a selected row was removed
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // rows 0 and 1 removed (ring buffer): the selection of row 5 is row 3 now
|
|
99
|
+
* selectionModel.adjustForRowChanges(new RowIndexShift([0, 1], []));
|
|
100
|
+
*/
|
|
101
|
+
adjustForRowChanges(shift: RowIndexShift): boolean;
|
|
102
|
+
/** Shifts ranges in place (split pieces are appended); true if rows of a range were removed. */
|
|
103
|
+
private static shiftRanges;
|
|
87
104
|
getSelectionCount(rowIndex: number, columnIndex: number): number;
|
|
88
105
|
isInNegativeRange(rowIndex: number, columnIndex: number): boolean;
|
|
89
106
|
getRanges(): CellRange[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CellRange } from '../data/common/cell-range.js';
|
|
2
2
|
import { EventSelectionChangedListenerIf } from './event-selection-changed-listener.if.js';
|
|
3
|
+
import { RowIndexShift } from '../live-append/row-index-shift.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* What is selected in a table – a list of rectangles ({@link CellRange}). The implementation is {@link SelectionModel};
|
|
@@ -82,4 +83,16 @@ export interface SelectionModelIf {
|
|
|
82
83
|
isAllSelected(): boolean;
|
|
83
84
|
/** Called by the table on a click: starts a selection at this cell, depending on selection type and mode. */
|
|
84
85
|
firstClick(rowIndex: number, columnIndex: number): void;
|
|
86
|
+
/**
|
|
87
|
+
* Optional (live data, since 1.1.108): moves the selected rows along when rows were removed at the start or
|
|
88
|
+
* inserted (`tableApi.appendRows()` / `rowsAppended()`), instead of clearing the selection. Removed rows leave the
|
|
89
|
+
* selection; rows inserted inside a selected range split it (they are not selected); whole columns and "all
|
|
90
|
+
* selected" stay. Fires no event.
|
|
91
|
+
*
|
|
92
|
+
* @param {RowIndexShift} shift - how the display indices move
|
|
93
|
+
* @returns {boolean} true if a selected row was removed (the selection shows other rows now)
|
|
94
|
+
* @example
|
|
95
|
+
* selectionModel.adjustForRowChanges?.(new RowIndexShift([0, 1], [98, 99]));
|
|
96
|
+
*/
|
|
97
|
+
adjustForRowChanges?(shift: RowIndexShift): boolean;
|
|
85
98
|
}
|
|
@@ -7,6 +7,7 @@ import { CellRange } from '../data/common/cell-range.js';
|
|
|
7
7
|
import { OnActionTriggeredIf } from '../action/on-action-triggered.if.js';
|
|
8
8
|
import { ActionId } from '../action/action-id.type.js';
|
|
9
9
|
import { SelectionSnapshot } from './selection-model.js';
|
|
10
|
+
import { RowIndexShift } from '../live-append/row-index-shift.js';
|
|
10
11
|
|
|
11
12
|
/** @category Internals */
|
|
12
13
|
export declare class SelectionService implements OnActionTriggeredIf {
|
|
@@ -62,6 +63,13 @@ export declare class SelectionService implements OnActionTriggeredIf {
|
|
|
62
63
|
* @returns {[number, number] | undefined} row and column, `undefined` before the first click/keyboard move
|
|
63
64
|
* @since 1.1.99
|
|
64
65
|
*/
|
|
66
|
+
/**
|
|
67
|
+
* Live data (since 1.1.108): anchor, moving corner and last click follow their rows when rows were removed at the
|
|
68
|
+
* start or inserted (`tableApi.appendRows()`); a removed row drops them.
|
|
69
|
+
*
|
|
70
|
+
* @param {RowIndexShift} shift - how the display indices move
|
|
71
|
+
*/
|
|
72
|
+
adjustForRowChanges(shift: RowIndexShift): void;
|
|
65
73
|
getAnchor(): [number, number] | undefined;
|
|
66
74
|
/**
|
|
67
75
|
* The moving corner of the range Shift+arrows grow (the anchor if there is none).
|