@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
|
@@ -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';
|
|
@@ -30,6 +31,7 @@ import { AriaTextsIf } from './aria/aria-texts.if.js';
|
|
|
30
31
|
import { RowLayout } from './row-layout/row-layout.js';
|
|
31
32
|
import { MasterDetailService } from './master-detail/master-detail-service.js';
|
|
32
33
|
import { TableSheet } from './sheet/table-sheet.js';
|
|
34
|
+
import { ScrollPositionIf } from './data/common/scroll-position.if.js';
|
|
33
35
|
|
|
34
36
|
/** @category Internals */
|
|
35
37
|
export declare class RenderScope extends EleScope {
|
|
@@ -67,6 +69,23 @@ export declare class RenderScope extends EleScope {
|
|
|
67
69
|
scrollTop: number;
|
|
68
70
|
contentTop: number;
|
|
69
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* The scroll position (`scrollTop`, logical `scrollLeft`) of the last render pass – the `scroll` event of a position
|
|
74
|
+
* that is already rendered (`repaintHard({ py })`, `scrollToPixel()` render it at once) renders nothing.
|
|
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
|
+
};
|
|
88
|
+
protected renderedScrollLeft: number;
|
|
70
89
|
/** Area heights read once at the start of adjustAfterScrolling() (before the DOM is modified). */
|
|
71
90
|
protected areaHeightsOfRenderPass?: {
|
|
72
91
|
[key in AreaIdent]?: number;
|
|
@@ -214,8 +233,10 @@ export declare class RenderScope extends EleScope {
|
|
|
214
233
|
/** True if open detail rows take space between the body rows. */
|
|
215
234
|
protected hasBodyRowExtras(): boolean;
|
|
216
235
|
/**
|
|
217
|
-
* The top of a body row in content pixels
|
|
218
|
-
* rows above it (
|
|
236
|
+
* The top of a body row in content pixels – from the row layout of the table ({@link getBodyRowLayout}: the heights
|
|
237
|
+
* the rows are drawn with, plus the open detail rows above it). Since 1.1.107 always from the layout (before: without
|
|
238
|
+
* detail rows from {@link AreaModelIf.getYPosByRowIndex}, which an area model with its own `getRowHeight()` could
|
|
239
|
+
* get wrong – `scrollToIndex()` landed beside the row). O(1) for constant heights, otherwise after one O(n) build.
|
|
219
240
|
*
|
|
220
241
|
* @param {number} rowIndex - display index
|
|
221
242
|
* @returns {number} px from the top of the first body row
|
|
@@ -264,6 +285,13 @@ export declare class RenderScope extends EleScope {
|
|
|
264
285
|
*
|
|
265
286
|
* @returns {void}
|
|
266
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;
|
|
267
295
|
resetEditorRenderer(): void;
|
|
268
296
|
/**
|
|
269
297
|
* Clears the selection in the component.
|
|
@@ -296,13 +324,51 @@ export declare class RenderScope extends EleScope {
|
|
|
296
324
|
*/
|
|
297
325
|
invalidateAggregates(change?: DerivedValuesChangeIf): void;
|
|
298
326
|
/**
|
|
299
|
-
* Repaints the UI
|
|
300
|
-
*
|
|
301
|
-
* after scrolling.
|
|
327
|
+
* Repaints the UI after the row count or the row heights changed: new heights and padding, new size of the scroll
|
|
328
|
+
* content, new layout of the areas – then **one** render pass (since 1.1.107; before: two).
|
|
302
329
|
*
|
|
330
|
+
* @param {ScrollPositionIf} [scrollTo] - a content position to show in that render pass (like {@link scrollToPixel},
|
|
331
|
+
* exact also with a capped scroll height); a missing axis keeps its position
|
|
303
332
|
* @return {void} This method does not return any value.
|
|
304
333
|
*/
|
|
305
|
-
repaintHard(): void;
|
|
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;
|
|
347
|
+
/**
|
|
348
|
+
* Sets the scroll position of the viewport to a content position **without rendering** (shared by
|
|
349
|
+
* `scrollToPixel()` and `repaintHard({ px, py })`). `py` is a content position: the scroll bar range differs from the
|
|
350
|
+
* content range – always with a capped scroll height, but also slightly without (the scroll content is 1 px higher
|
|
351
|
+
* than the rows, the scroll viewport includes the footer and the horizontal scroll bar). `scrollTop = py` would leave
|
|
352
|
+
* the target row a few pixels off, so the exact content position is remembered (`pendingContentScroll`) and used by
|
|
353
|
+
* the next render passes as long as the scroll bar is not moved.
|
|
354
|
+
*
|
|
355
|
+
* @param {number | undefined} px - from the start of the rows (logical, right-to-left from the right edge);
|
|
356
|
+
* `undefined` keeps the horizontal position
|
|
357
|
+
* @param {number | undefined} py - content px from the top of the first body row; `undefined` keeps the vertical
|
|
358
|
+
* position
|
|
359
|
+
* @returns {boolean} true if the exact content position was set (then render now – a scroll event may not fire);
|
|
360
|
+
* false if the browser renders it with its scroll event (nothing to scroll vertically, or only `px`)
|
|
361
|
+
* @since 1.1.107
|
|
362
|
+
*/
|
|
363
|
+
protected setContentScrollPosition(px: number | undefined, py: number | undefined): boolean;
|
|
364
|
+
/**
|
|
365
|
+
* The `scroll` listener of the scroll viewport: renders the new position – nothing if the position is already
|
|
366
|
+
* rendered (the event of a `repaintHard({ py })`, `scrollToPixel()` or `ensureColumnIsVisible()` arrives after
|
|
367
|
+
* their own render pass).
|
|
368
|
+
*
|
|
369
|
+
* @since 1.1.107
|
|
370
|
+
*/
|
|
371
|
+
onViewportScroll(): void;
|
|
306
372
|
/**
|
|
307
373
|
* Recalculates the column widths of the table (% and weight columns depend on the available width) and repaints.
|
|
308
374
|
*
|
|
@@ -316,7 +382,7 @@ export declare class RenderScope extends EleScope {
|
|
|
316
382
|
protected setParentWidth(widthInPixel: number): void;
|
|
317
383
|
/** True if a column has a % or weight width (it depends on the width of the host). */
|
|
318
384
|
protected hasRelativeColumnWidths(): boolean;
|
|
319
|
-
|
|
385
|
+
protected layoutContainers(): void;
|
|
320
386
|
/**
|
|
321
387
|
* % and weight columns share the width next to the vertical scroll bar. The bar appears (or disappears) only after
|
|
322
388
|
* the rows are laid out – the first layout, rows added or removed, a filter: then the columns were computed for the
|
|
@@ -448,14 +514,14 @@ export declare class RenderScope extends EleScope {
|
|
|
448
514
|
* scaled and scrollTop is no longer a content pixel position.
|
|
449
515
|
*/
|
|
450
516
|
isScrollHeightCapped(): boolean;
|
|
517
|
+
/** The detail layer (master/detail) covers the visible body. @since 1.1.97 */
|
|
518
|
+
protected adjustDetailLayerBounds(left: number, top: number, width: number, height: number): void;
|
|
451
519
|
/**
|
|
452
520
|
* The model's content height plus the heights of open detail rows (master/detail).
|
|
453
521
|
*
|
|
454
522
|
* @returns {number} px
|
|
455
523
|
* @since 1.1.97
|
|
456
524
|
*/
|
|
457
|
-
/** The detail layer (master/detail) covers the visible body. @since 1.1.97 */
|
|
458
|
-
protected adjustDetailLayerBounds(left: number, top: number, width: number, height: number): void;
|
|
459
525
|
protected getBodyContentHeight(): number;
|
|
460
526
|
/** Scrollable range of the content in content pixels (content height minus visible body height). */
|
|
461
527
|
protected getContentScrollRangeY(): number;
|
|
@@ -601,7 +667,7 @@ export declare class RenderScope extends EleScope {
|
|
|
601
667
|
*/
|
|
602
668
|
private rowNumberWidth?;
|
|
603
669
|
/** true while the containers are adjusted to a new row number width (no second change in that nested pass). */
|
|
604
|
-
|
|
670
|
+
protected adjustingRowNumberWidth: boolean;
|
|
605
671
|
/** Guards {@link adjustRelativeColumnWidthsToScrollBar} against re-entry. */
|
|
606
672
|
private adjustingRelativeWidths;
|
|
607
673
|
/** The width % and weight columns were last computed for (`TableModelIf.setParentWidth`), -1 = unknown. */
|
|
@@ -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).
|
package/lib/table/table-api.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ import { CellRange } from './data/common/cell-range.js';
|
|
|
27
27
|
import { EventListenerIf } from './event-listener.if.js';
|
|
28
28
|
import { ExcelExportOptionsIf } from './service/excel-export-options.if.js';
|
|
29
29
|
import { SheetEngine } from './sheet/sheet-engine.js';
|
|
30
|
+
import { ScrollPositionIf } from './data/common/scroll-position.if.js';
|
|
31
|
+
import { AppendRowsOptionsIf, AppendRowsResultIf, RowsAppendedOptionsIf } from './live-append/append-rows-options.if.js';
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* The public API of one table – everything you do with a table after it has been created:
|
|
@@ -200,7 +202,7 @@ export declare class TableApi {
|
|
|
200
202
|
* };
|
|
201
203
|
*
|
|
202
204
|
* // Initialize your table with these options
|
|
203
|
-
* const tableApi =
|
|
205
|
+
* const tableApi = tableScope.getApi();
|
|
204
206
|
*
|
|
205
207
|
* // Later, when filter criteria change (e.g., in a search input handler)
|
|
206
208
|
* function onFilterTextChanged() {
|
|
@@ -432,7 +434,7 @@ export declare class TableApi {
|
|
|
432
434
|
*
|
|
433
435
|
* @example
|
|
434
436
|
* // Update data and repaint the table
|
|
435
|
-
* const tableApi =
|
|
437
|
+
* const tableApi = tableScope.getApi();
|
|
436
438
|
* tableApi.setRows(newData);
|
|
437
439
|
* tableApi.repaint();
|
|
438
440
|
*
|
|
@@ -464,19 +466,24 @@ export declare class TableApi {
|
|
|
464
466
|
*/
|
|
465
467
|
destroy(): void;
|
|
466
468
|
/**
|
|
467
|
-
* Performs a complete repaint of the table
|
|
469
|
+
* Performs a complete repaint of the table: use it when the row count or the row heights changed (rows added or
|
|
470
|
+
* removed, a filter, a new model content, `ColumnDefIf.isVisible` changed yourself …). It
|
|
471
|
+
* - drops cached derived values (footer totals, calculated columns),
|
|
472
|
+
* - recalculates the heights and the padding of the table model and the size of the scroll content,
|
|
473
|
+
* - lays out header, body and footer again and
|
|
474
|
+
* - renders the visible rows – **once** (since 1.1.107; before: twice).
|
|
468
475
|
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
476
|
+
* With `scrollTo` (since 1.1.107) it also sets the scroll position in that same render pass – exactly like
|
|
477
|
+
* {@link scrollToPixel}, also with a capped scroll height (more than {@link EleScope.maxScrollHeightInPx} px of rows).
|
|
478
|
+
* A live tail that appends rows and keeps a position needs one render per update instead of three
|
|
479
|
+
* (`repaintHard()` + `scrollToPixel()`). The `scroll` event of the browser for that position renders nothing.
|
|
480
|
+
* A missing axis keeps its position.
|
|
474
481
|
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
* -
|
|
478
|
-
*
|
|
479
|
-
*
|
|
482
|
+
* For a repaint with the same row count (values changed) {@link repaint} is enough.
|
|
483
|
+
*
|
|
484
|
+
* @param {ScrollPositionIf} [scrollTo] - the position to show: `px` horizontal scroll position from the start, `py`
|
|
485
|
+
* content pixels from the top of the first body row (both like {@link scrollToPixel}); without it the position stays
|
|
486
|
+
* @returns {void} This method doesn't return a value
|
|
480
487
|
*
|
|
481
488
|
* @example
|
|
482
489
|
* // Example 1: Basic usage
|
|
@@ -499,9 +506,20 @@ export declare class TableApi {
|
|
|
499
506
|
* column.isVisible = FalseFn;
|
|
500
507
|
* tableApi.repaintHard();
|
|
501
508
|
*
|
|
502
|
-
* @
|
|
509
|
+
* @example
|
|
510
|
+
* // Example 5: live tail – rows were appended to the area model, the first visible row stays at the top
|
|
511
|
+
* // (pixel-exact: keep your own py from the last update instead – e.g. from onScroll)
|
|
512
|
+
* const rowHeight = 20; // the row height of the area model
|
|
513
|
+
* const first = tableApi.getFirstVisibleRowIndex();
|
|
514
|
+
* rows.push(...newData); // the row count of the model grows
|
|
515
|
+
* tableApi.repaintHard({ py: first * rowHeight }); // one render pass, exact also for millions of rows
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* // Example 6: follow the end ("tail -f") – show the last row after every update
|
|
519
|
+
* rows.push(...newData);
|
|
520
|
+
* tableApi.repaintHard({ py: Number.MAX_SAFE_INTEGER }); // clamped to the end of the content
|
|
503
521
|
*/
|
|
504
|
-
repaintHard(): void;
|
|
522
|
+
repaintHard(scrollTo?: ScrollPositionIf): void;
|
|
505
523
|
/**
|
|
506
524
|
* Recalculates the column widths of the table.
|
|
507
525
|
*
|
|
@@ -888,7 +906,7 @@ export declare class TableApi {
|
|
|
888
906
|
*
|
|
889
907
|
* @example
|
|
890
908
|
* // Access the TableScope to perform a custom operation
|
|
891
|
-
* const tableApi =
|
|
909
|
+
* const tableApi = myTableScope.getApi();
|
|
892
910
|
* const tableScope = tableApi.getTableScope();
|
|
893
911
|
*
|
|
894
912
|
* // Example: Manually trigger a context menu at a specific location
|
|
@@ -1023,6 +1041,8 @@ export declare class TableApi {
|
|
|
1023
1041
|
* Only works with an {@link AreaModelObjectArray} body – logs a console warning otherwise.
|
|
1024
1042
|
* Does **not** repaint and resets filtering and sorting of the body: afterwards call
|
|
1025
1043
|
* {@link externalFilterChanged} (if a filter function is set) and {@link repaintHard} (the row count changed).
|
|
1044
|
+
* Copies all rows (O(n)) – for live data (rows arriving all the time) use {@link appendRows}: in place, filter and
|
|
1045
|
+
* order only for the new rows, selection and position stay.
|
|
1026
1046
|
*
|
|
1027
1047
|
* @template T - The type of elements in the rows array
|
|
1028
1048
|
* @param {T[]} rows - An array of data objects to append to the table's existing rows
|
|
@@ -1039,6 +1059,81 @@ export declare class TableApi {
|
|
|
1039
1059
|
* tableApi.repaintHard();
|
|
1040
1060
|
* tableApi.ensureRowIsVisible(tableApi.getDisplayedRowCount() - 1);
|
|
1041
1061
|
*/
|
|
1062
|
+
/**
|
|
1063
|
+
* **Live data** (a log tail, a ticker – since 1.1.108): appends rows to the body and shows them in **one** render
|
|
1064
|
+
* pass – O(k) for k new rows, not O(n).
|
|
1065
|
+
*
|
|
1066
|
+
* - **In place**: the rows are pushed to your array (`getAllRows()`), nothing is copied.
|
|
1067
|
+
* - **Filter and order** (`externalFilterFunction`, a sorted column or `sort(fn)`) apply to the new rows only:
|
|
1068
|
+
* filtered rows are kept but not shown, sorted rows are merged in (O(n + k), behind equal rows).
|
|
1069
|
+
* - **Selection, focus, anchor, checked rows** stay at their rows (the indices move along; no `onSelectionChanged`
|
|
1070
|
+
* unless a selected row was removed).
|
|
1071
|
+
* - **Position**: `follow: "auto"` (default) stays at the end if the view was at the end ("tail -f"), otherwise the
|
|
1072
|
+
* first visible row stays; `true` = always the end, `false` = always keep the row ("freeze scroll"). While the
|
|
1073
|
+
* mouse button is held in the table, `"auto"` keeps the row.
|
|
1074
|
+
* - **Ring buffer**: `maxRows` removes the oldest rows from the start.
|
|
1075
|
+
* - Rows behind the visible ones (a reader in the middle of the log): the cells are not rebuilt – only scroll height
|
|
1076
|
+
* and scroll bar change.
|
|
1077
|
+
*
|
|
1078
|
+
* Works with an {@link AreaModelObjectArray} body (`TableFactory.createTableModel({ rows, … })`) without cell
|
|
1079
|
+
* formulas; a tree, row grouping, pivot or spreadsheet → `false` and a console warning. Own area model:
|
|
1080
|
+
* {@link rowsAppended}.
|
|
1081
|
+
*
|
|
1082
|
+
* @param {T[]} rows - the new rows (appended in this order)
|
|
1083
|
+
* @param {AppendRowsOptionsIf} [options] - `follow` ("auto" | true | false), `maxRows`
|
|
1084
|
+
* @returns {AppendRowsResultIf | false} `{ added, shown, removed, following }`, or false
|
|
1085
|
+
*
|
|
1086
|
+
* @example
|
|
1087
|
+
* // a log viewer: new lines every animation frame, at most one million
|
|
1088
|
+
* const result = tableApi.appendRows(newLines, { follow: "auto", maxRows: 1_000_000 });
|
|
1089
|
+
* if (result && !result.following) {
|
|
1090
|
+
* console.log(`+${result.shown} new lines below`);
|
|
1091
|
+
* }
|
|
1092
|
+
*
|
|
1093
|
+
* @example
|
|
1094
|
+
* // "Freeze scroll" / "Scroll to end" buttons of the app
|
|
1095
|
+
* let frozen = false;
|
|
1096
|
+
* function onLines(lines: { time: string; text: string }[]) {
|
|
1097
|
+
* tableApi.appendRows(lines, { follow: frozen ? false : "auto" });
|
|
1098
|
+
* }
|
|
1099
|
+
* function scrollToEnd() {
|
|
1100
|
+
* frozen = false;
|
|
1101
|
+
* tableApi.repaintHard({ py: Number.MAX_SAFE_INTEGER });
|
|
1102
|
+
* }
|
|
1103
|
+
*
|
|
1104
|
+
* @since 1.1.108
|
|
1105
|
+
*/
|
|
1106
|
+
appendRows<T>(rows: T[], options?: AppendRowsOptionsIf): AppendRowsResultIf | false;
|
|
1107
|
+
/**
|
|
1108
|
+
* **Live data with an own area model** (since 1.1.108): your model appended `count` rows at the end (and maybe
|
|
1109
|
+
* removed `removedAtStart` rows at the start) – the table moves selection, focus and anchor along, keeps the first
|
|
1110
|
+
* visible row or follows the end (`follow` as in {@link appendRows}) and renders once (not at all if only rows behind
|
|
1111
|
+
* the visible ones came in). Filtering and sorting are up to your model.
|
|
1112
|
+
*
|
|
1113
|
+
* @param {number} count - rows appended at the end
|
|
1114
|
+
* @param {RowsAppendedOptionsIf} [options] - `follow`, `removedAtStart`
|
|
1115
|
+
* @returns {AppendRowsResultIf} `{ added, shown, removed, following }`
|
|
1116
|
+
*
|
|
1117
|
+
* @example
|
|
1118
|
+
* class LogBody extends AreaModel {
|
|
1119
|
+
* readonly lines: string[] = [];
|
|
1120
|
+
* override getRowCount(): number { return this.lines.length; }
|
|
1121
|
+
* override getRowHeight(): number { return 20; }
|
|
1122
|
+
* override getConstantRowHeight(): number { return 20; }
|
|
1123
|
+
* override getValueAt(row: number): string { return this.lines[row]; }
|
|
1124
|
+
* }
|
|
1125
|
+
* const body = new LogBody();
|
|
1126
|
+
*
|
|
1127
|
+
* function onNewLines(newLines: string[]) {
|
|
1128
|
+
* for (const line of newLines) body.lines.push(line); // a loop: push(...lines) overflows above ~100,000
|
|
1129
|
+
* const dropped = Math.max(0, body.lines.length - 1_000_000);
|
|
1130
|
+
* body.lines.splice(0, dropped); // the app's own ring buffer
|
|
1131
|
+
* tableApi.rowsAppended(newLines.length, { follow: "auto", removedAtStart: dropped });
|
|
1132
|
+
* }
|
|
1133
|
+
*
|
|
1134
|
+
* @since 1.1.108
|
|
1135
|
+
*/
|
|
1136
|
+
rowsAppended(count: number, options?: RowsAppendedOptionsIf): AppendRowsResultIf;
|
|
1042
1137
|
addRows<T>(rows: T[]): void;
|
|
1043
1138
|
/**
|
|
1044
1139
|
* Inserts new rows at a specific position in the table body.
|
|
@@ -2325,7 +2420,7 @@ export declare class TableApi {
|
|
|
2325
2420
|
* @example
|
|
2326
2421
|
* ```typescript
|
|
2327
2422
|
* // Get the first visible row index
|
|
2328
|
-
* const tableApi =
|
|
2423
|
+
* const tableApi = tableScope.getApi();
|
|
2329
2424
|
* const firstVisibleIndex = tableApi.getFirstVisibleRowIndex();
|
|
2330
2425
|
*
|
|
2331
2426
|
* // Use the index for scroll position calculations
|
|
@@ -2,6 +2,7 @@ import { TableOverlayChange } from './overlay/table-overlay.js';
|
|
|
2
2
|
import { GeOverlayKind } from './overlay/ge-overlay-kind.type.js';
|
|
3
3
|
import { TableModelIf } from './data/tablemodel/table-model.if.js';
|
|
4
4
|
import { AreaIdent } from './data/tablemodel/area-ident.type.js';
|
|
5
|
+
import { SideIdent } from './data/side-ident.type.js';
|
|
5
6
|
import { GeMouseEvent } from './data/common/event/ge-mouse-event.js';
|
|
6
7
|
import { DomServiceIf } from './service/dom-service.if.js';
|
|
7
8
|
import { TableOptionsIf } from './data/options/table-options.if.js';
|
|
@@ -50,6 +51,7 @@ import { ClipboardService } from './clipboard/clipboard-service.js';
|
|
|
50
51
|
import { UndoOptionsIf } from './undo/undo-options.if.js';
|
|
51
52
|
import { UndoService } from './undo/undo-service.js';
|
|
52
53
|
import { ShortcutActionIdMapping } from './action/shortcut-actionid-mapping.type.js';
|
|
54
|
+
import { AppendRowsOptionsIf, AppendRowsResultIf, RowsAppendedOptionsIf } from './live-append/append-rows-options.if.js';
|
|
53
55
|
|
|
54
56
|
/**
|
|
55
57
|
* Creates and runs one table in a host element – the core that every framework wrapper uses.
|
|
@@ -130,6 +132,8 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
130
132
|
private firstDraggingRendering;
|
|
131
133
|
/** Last comparator passed to `sort()`; re-applied after filtering. Cleared by a header sort. */
|
|
132
134
|
private lastSortCompareFn?;
|
|
135
|
+
/** Live data: the content position held while the mouse button was down in a view that followed the end. */
|
|
136
|
+
private followHeldAt?;
|
|
133
137
|
/** Excel-style editing (`tableOptions.editing`), `undefined` = off. @since 1.1.99 */
|
|
134
138
|
private readonly editingOptions?;
|
|
135
139
|
/** Listeners of {@link TableApi.subscribe}. @since 1.1.99 */
|
|
@@ -750,6 +754,22 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
750
754
|
* @return {GeMouseEvent} - The created GeMouseEvent object.
|
|
751
755
|
*/
|
|
752
756
|
createGeMouseEvent(mouseEvent: MouseEvent): GeMouseEvent;
|
|
757
|
+
/**
|
|
758
|
+
* Creates a GeMouseEvent for a given cell – used when the cell element of a mouse event is gone (a render replaced
|
|
759
|
+
* it between mousedown and mouseup, see {@link MouseHandler}) and the cell is known from the mousedown.
|
|
760
|
+
*
|
|
761
|
+
* @param mouseEvent - the original browser event
|
|
762
|
+
* @param cell - area, side, row and column of the cell, and the action of the pressed element
|
|
763
|
+
* @returns the event with row/column positions of the cell
|
|
764
|
+
* @since 1.1.108
|
|
765
|
+
*/
|
|
766
|
+
createGeMouseEventForCell(mouseEvent: MouseEvent, cell: {
|
|
767
|
+
areaIdent?: AreaIdent;
|
|
768
|
+
sideIdent?: SideIdent;
|
|
769
|
+
rowIndex: number;
|
|
770
|
+
columnIndex: number;
|
|
771
|
+
action: string | null;
|
|
772
|
+
}): GeMouseEvent;
|
|
753
773
|
/**
|
|
754
774
|
* The element a mouse event belongs to – usually `evt.target`. The scroll viewport lies above the footer areas (its
|
|
755
775
|
* horizontal scroll bar must stay usable), so a mouse event on a footer cell arrives at the viewport: then the footer
|
|
@@ -1039,6 +1059,37 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
1039
1059
|
private setAreaVisible;
|
|
1040
1060
|
autoResizeColumns(recalcWrappers?: boolean): void;
|
|
1041
1061
|
recalcWrappers(): void;
|
|
1062
|
+
/**
|
|
1063
|
+
* Live data (since 1.1.108): appends rows to an {@link AreaModelObjectArray} body in place – filter and sort order
|
|
1064
|
+
* only for the new rows, optional ring buffer – moves selection, focus and anchor along, keeps the first visible row
|
|
1065
|
+
* or follows the end, and renders once (not at all if only rows behind the visible ones came in).
|
|
1066
|
+
* See {@link TableApi.appendRows}.
|
|
1067
|
+
*
|
|
1068
|
+
* @param {T[]} rows - the new rows
|
|
1069
|
+
* @param {AppendRowsOptionsIf} [options] - follow mode, ring buffer
|
|
1070
|
+
* @returns {AppendRowsResultIf | false} what changed; false (with a warning) for other bodies (tree, row groups,
|
|
1071
|
+
* pivot, spreadsheet, cell formulas)
|
|
1072
|
+
*/
|
|
1073
|
+
appendRows<T>(rows: T[], options?: AppendRowsOptionsIf): AppendRowsResultIf | false;
|
|
1074
|
+
/**
|
|
1075
|
+
* Live data (since 1.1.108): an own area model appended `count` rows at the end (and maybe removed some at the
|
|
1076
|
+
* start) – moves selection, focus and anchor along, keeps the first visible row or follows the end, renders once.
|
|
1077
|
+
* See {@link TableApi.rowsAppended}.
|
|
1078
|
+
*
|
|
1079
|
+
* @param {number} count - rows the model appended at the end (display order)
|
|
1080
|
+
* @param {RowsAppendedOptionsIf} [options] - follow mode, rows removed at the start
|
|
1081
|
+
* @returns {AppendRowsResultIf} what changed
|
|
1082
|
+
*/
|
|
1083
|
+
notifyRowsAppended(count: number, options?: RowsAppendedOptionsIf): AppendRowsResultIf;
|
|
1084
|
+
/** The order new rows are sorted in: the last `sort(fn)`, otherwise the columns with a sort state. */
|
|
1085
|
+
protected getActiveSortComparator(): ((a: unknown, b: unknown) => number) | undefined;
|
|
1086
|
+
/** Moves the index-based state along, chooses the position and renders once (or only updates the row count). */
|
|
1087
|
+
private afterRowsAppended;
|
|
1088
|
+
/**
|
|
1089
|
+
* True if nothing else on the screen depends on the row count: no row number column (its width may grow), no
|
|
1090
|
+
* totals footer, no calculated/„show values as“ columns, no open detail rows.
|
|
1091
|
+
*/
|
|
1092
|
+
private canKeepDrawnRows;
|
|
1042
1093
|
reSort(): void;
|
|
1043
1094
|
sort(compareFn: (a: any, b: any) => number): void;
|
|
1044
1095
|
/**
|