@guiexpert/table 1.1.109 → 1.1.113
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 +7 -0
- package/index.cjs +28 -28
- package/index.d.ts +5 -0
- package/index.js +2579 -2150
- package/lib/table/column-drag/column-auto-width-context.if.d.ts +29 -0
- package/lib/table/column-drag/column-auto-width-options.d.ts +24 -0
- package/lib/table/column-drag/column-auto-width-options.if.d.ts +35 -0
- package/lib/table/column-drag/column-order.d.ts +38 -0
- package/lib/table/column-drag/column-width-measurer.d.ts +26 -0
- package/lib/table/data/common/event/ge-column-move-event.d.ts +56 -0
- package/lib/table/data/common/event/ge-column-resize-event.d.ts +72 -0
- package/lib/table/data/common/row-number-column-def.d.ts +4 -0
- package/lib/table/data/options/table-options.d.ts +3 -0
- package/lib/table/data/options/table-options.if.d.ts +21 -2
- package/lib/table/data/tablemodel/column/column-def.d.ts +8 -0
- package/lib/table/data/tablemodel/column/column-def.if.d.ts +22 -0
- package/lib/table/event-adapter.d.ts +10 -0
- package/lib/table/event-listener.if.d.ts +30 -0
- package/lib/table/render-scope.d.ts +9 -1
- package/lib/table/table-api.d.ts +50 -1
- package/lib/table/table-scope.d.ts +76 -3
- package/llms.txt +31 -2
- package/package.json +1 -1
|
@@ -125,8 +125,9 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
125
125
|
private mouseStartAction;
|
|
126
126
|
private mouseStartWidth;
|
|
127
127
|
private mouseStartColumnIndex;
|
|
128
|
+
/** The column resize or move of the current press (prompt 022) – `undefined` without an allowed column action. */
|
|
129
|
+
private columnDrag?;
|
|
128
130
|
private dragFrom;
|
|
129
|
-
private dragTo;
|
|
130
131
|
private lastDragFrom;
|
|
131
132
|
private lastDragTo;
|
|
132
133
|
private firstDraggingRendering;
|
|
@@ -775,10 +776,16 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
775
776
|
* horizontal scroll bar must stay usable), so a mouse event on a footer cell arrives at the viewport: then the footer
|
|
776
777
|
* element below the mouse pointer is returned (not on the scroll bar itself).
|
|
777
778
|
*
|
|
779
|
+
* A target that a render replaced meanwhile (an event handled in a later animation frame – a drag frame, the end of a
|
|
780
|
+
* drag – while live data renders) is resolved again at the pointer position: its `data-row-index` would be the index
|
|
781
|
+
* of an earlier render (since 1.1.112).
|
|
782
|
+
*
|
|
778
783
|
* @param {MouseEvent} evt - a mouse event on the host element
|
|
779
784
|
* @returns {EventTarget | null} the target element
|
|
780
785
|
*/
|
|
781
786
|
getMouseEventTarget(evt: MouseEvent): EventTarget | null;
|
|
787
|
+
/** The cell element (or an element in it) of this table at a client position, `undefined` if there is none. */
|
|
788
|
+
private getCellElementAtPoint;
|
|
782
789
|
/**
|
|
783
790
|
* Handles the mouse down event.
|
|
784
791
|
*
|
|
@@ -786,6 +793,32 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
786
793
|
* @return {void}
|
|
787
794
|
*/
|
|
788
795
|
onMouseDown(mouseEvent: GeMouseEvent): void;
|
|
796
|
+
/** Forgets the column action of the last press (no events). */
|
|
797
|
+
private resetColumnDrag;
|
|
798
|
+
/**
|
|
799
|
+
* Starts the column drag of this press once the mouse moved past {@link MouseHandler.clickMoveTolerance}: reports
|
|
800
|
+
* `onColumnResizeStart` / `onColumnMoveStart` and listens for Escape.
|
|
801
|
+
*
|
|
802
|
+
* @returns true if the drag runs (started now or before), false below the threshold, without a drag or cancelled
|
|
803
|
+
*/
|
|
804
|
+
private beginColumnDrag;
|
|
805
|
+
/**
|
|
806
|
+
* true between the start and the end of a column resize or move by the user ({@link TableApi.isColumnDragging}).
|
|
807
|
+
*
|
|
808
|
+
* @returns {boolean} true while the user drags a column (or its resize handle)
|
|
809
|
+
* @since 1.1.110
|
|
810
|
+
*/
|
|
811
|
+
isColumnDragging(): boolean;
|
|
812
|
+
/**
|
|
813
|
+
* Cancels a running column drag like Escape ({@link TableApi.cancelColumnDrag}): the old width resp. order is back,
|
|
814
|
+
* the end is reported with type `"cancel"`. Without a running drag nothing happens.
|
|
815
|
+
*
|
|
816
|
+
* @param {Event} [originalEvent] - the key event (Escape)
|
|
817
|
+
* @since 1.1.110
|
|
818
|
+
*/
|
|
819
|
+
cancelColumnDrag(originalEvent?: Event): void;
|
|
820
|
+
/** Reports a column drag to the listener (and the subscribers). */
|
|
821
|
+
private emitColumnDragEvent;
|
|
789
822
|
/**
|
|
790
823
|
* Handles mouse dragging on the frame.
|
|
791
824
|
*
|
|
@@ -793,6 +826,12 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
793
826
|
* @param startMouseEvent
|
|
794
827
|
*/
|
|
795
828
|
mouseDraggingOnFrame(mouseEvent: GeMouseEvent, startMouseEvent: GeMouseEvent | undefined): void;
|
|
829
|
+
/**
|
|
830
|
+
* Moves the dragged column to the column under the mouse: within its area (fixed west, center, fixed east), locked
|
|
831
|
+
* columns (`movable: false`) keep their place; over a locked column it moves as far as it can towards it (the same
|
|
832
|
+
* result whether the mouse passed the columns in between in single frames or jumped there in one).
|
|
833
|
+
*/
|
|
834
|
+
private moveDraggedColumn;
|
|
796
835
|
/**
|
|
797
836
|
* Handles the end of mouse dragging event on a frame.
|
|
798
837
|
*
|
|
@@ -1028,13 +1067,47 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
|
|
|
1028
1067
|
* Calculates a width per column that fits the widest text of header, body and footer.
|
|
1029
1068
|
*
|
|
1030
1069
|
* The text is measured with the font and padding of a rendered cell label (canvas `measureText`),
|
|
1031
|
-
* so dates, numbers and long names are no longer cut off.
|
|
1032
|
-
*
|
|
1070
|
+
* so dates, numbers and long names are no longer cut off. The body is scanned once by character length and only the
|
|
1071
|
+
* longest candidates per column are measured. Body rows: all up to {@link ColumnAutoWidthOptionsIf.maxRows}
|
|
1072
|
+
* (10 000), above only the rows drawn now (since 1.1.110 – before, millions of rows froze the page).
|
|
1033
1073
|
* Without a canvas (e.g. in tests) it falls back to 8 px per character.
|
|
1034
1074
|
*
|
|
1035
1075
|
* @returns {number[]} one width in px per column (at least 50 px)
|
|
1036
1076
|
*/
|
|
1037
1077
|
calcAutoColumnWidths(): number[];
|
|
1078
|
+
/** The default widths of some columns: one pass over header, footer and the measured body rows. */
|
|
1079
|
+
private measureDefaultColumnWidths;
|
|
1080
|
+
/** The body rows the auto width measures: all up to `maxRows`, above only the rows drawn now. */
|
|
1081
|
+
private getMeasuredBodyRows;
|
|
1082
|
+
private getColumnAutoWidthOptions;
|
|
1083
|
+
/**
|
|
1084
|
+
* The fitted width of a column: {@link ColumnAutoWidthOptionsIf.getWidth} or the default, limited by
|
|
1085
|
+
* `minWidth` / `maxWidth`.
|
|
1086
|
+
*/
|
|
1087
|
+
private calcAutoColumnWidth;
|
|
1088
|
+
/**
|
|
1089
|
+
* Fits the width of one column to its content ({@link TableApi.autoResizeColumn}). No event.
|
|
1090
|
+
*
|
|
1091
|
+
* @param {number | string | ColumnDefIf} column - index, property or column definition
|
|
1092
|
+
* @returns {number | undefined} the width set, `undefined` for an unknown column, a row number column or
|
|
1093
|
+
* `resizable: false`
|
|
1094
|
+
* @since 1.1.110
|
|
1095
|
+
*/
|
|
1096
|
+
autoResizeColumn(column: number | string | ColumnDefIf): number | undefined;
|
|
1097
|
+
/**
|
|
1098
|
+
* A double click on the resize handle: fits the width (if allowed) and reports start and end with source
|
|
1099
|
+
* `"dblclick"`. Called by the {@link MouseHandler}.
|
|
1100
|
+
*
|
|
1101
|
+
* @param {number} columnIndex - the column of the handle
|
|
1102
|
+
* @param {Event} [originalEvent] - the double click
|
|
1103
|
+
* @returns {boolean} true if the width was fitted
|
|
1104
|
+
* @since 1.1.110
|
|
1105
|
+
*/
|
|
1106
|
+
autoResizeColumnByUser(columnIndex: number, originalEvent?: Event): boolean;
|
|
1107
|
+
/** Not for a row number column (its width follows the numbers), `resizable: false` or a hidden column. */
|
|
1108
|
+
private isColumnAutoResizable;
|
|
1109
|
+
/** Index of a column given by index, property or column definition; -1 if unknown. */
|
|
1110
|
+
private resolveColumnIndex;
|
|
1038
1111
|
setColumnWidth(columnIndex: number, width: number): void;
|
|
1039
1112
|
/**
|
|
1040
1113
|
* Shows or hides a column and repaints (see {@link TableApi.setColumnVisible}).
|
package/llms.txt
CHANGED
|
@@ -401,7 +401,10 @@ listener.onModelChanged = (evt: GeModelChangeEvent) => {
|
|
|
401
401
|
### R12 – Columns: fixed, hidden, width, index
|
|
402
402
|
|
|
403
403
|
- Fixed columns belong to the **model**: `TableFactory.createTableModel({ rows, properties, fixedLeftColumnCount: 1, fixedRightColumnCount: 1 })`.
|
|
404
|
-
- `tableApi.setColumnVisible("total", false)`, `tableApi.setColumnWidth(index, px)`, `tableApi.autoResizeColumns()
|
|
404
|
+
- `tableApi.setColumnVisible("total", false)`, `tableApi.setColumnWidth(index, px)`, `tableApi.autoResizeColumns()`,
|
|
405
|
+
one column `tableApi.autoResizeColumn("name")` (since 1.1.110).
|
|
406
|
+
- Lock a column for the user: `ColumnDef.create({ …, resizable: false, movable: false })` (since 1.1.110). Save the
|
|
407
|
+
layout when the user drags: R18.
|
|
405
408
|
- Row numbers (`rowNumbersVisible: true`), a checkbox column or a row-group column shift all column indices by one –
|
|
406
409
|
always `tableApi.getColumnIndex(property)`. Header groups: `instructions.md` 5.2, demo "headergroup".
|
|
407
410
|
|
|
@@ -455,6 +458,27 @@ host without destroying the first.
|
|
|
455
458
|
- **Drag between tables**: row drag works inside one table (`rowDrag: true`); between tables use `onRowDragEnd` +
|
|
456
459
|
`rowDragOptions.managed: false` and move the data yourself.
|
|
457
460
|
|
|
461
|
+
### R18 – Save the column layout when the user resizes or moves a column (since 1.1.110)
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
import { EventAdapter } from "@guiexpert/table";
|
|
465
|
+
import type { GeColumnMoveEvent, GeColumnResizeEvent, TableApi } from "@guiexpert/table";
|
|
466
|
+
|
|
467
|
+
declare const tableApi: TableApi;
|
|
468
|
+
const listener = new EventAdapter(); // 5th argument of new TableScope(…); wrappers: columnResizeEnd …
|
|
469
|
+
listener.onColumnResizeEnd = (evt: GeColumnResizeEvent) => {
|
|
470
|
+
if (evt.type === "end") localStorage.setItem("layout", JSON.stringify(tableApi.getState(["columns"])));
|
|
471
|
+
};
|
|
472
|
+
listener.onColumnMoveEnd = (evt: GeColumnMoveEvent) => {
|
|
473
|
+
if (evt.moved) localStorage.setItem("layout", JSON.stringify(tableApi.getState(["columns"])));
|
|
474
|
+
};
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Once per drag, after the table applied the change (no `setTimeout`); `type: "cancel"` after Escape; API calls
|
|
478
|
+
(`setColumnWidth`, `applyState`, `autoResizeColumns`) report nothing. Double click on the resize handle fits the width
|
|
479
|
+
(`source: "dblclick"`; own measurement `tableOptions.columnAutoWidth.getWidth`). Renders of a live table while the
|
|
480
|
+
user drags are fine. → instructions.md 6.27
|
|
481
|
+
|
|
458
482
|
More (short): tree + checkboxes `TreeFactory` (instructions.md 6.6), master/detail `masterDetail` (6.18), row grouping
|
|
459
483
|
`RowGroupFactory` (5.6), pivot `PivotFactory` (5.7), calculated columns `valueGetter`/`formula` (5.2, 5.9), spreadsheet
|
|
460
484
|
`SpreadsheetFactory.create` (6.25), cover grid (5.10), totals footer `footerAggregates` (5.4), row numbers (5.2).
|
|
@@ -498,6 +522,9 @@ Symptom → cause → fix.
|
|
|
498
522
|
dedupe `@guiexpert/table`.
|
|
499
523
|
- **TypeScript: unknown option** → "corrected" a misspelled API → use `showCheckboxWihoutExtraColumn`, `isHeaderVisibe`,
|
|
500
524
|
`emmitDataKey`, `createCoverGrisDefaultOptions` as they are.
|
|
525
|
+
- **Own `mousedown`/`mouseup`/`dblclick` listeners on the header** (to save widths, lock a column, fit on double click)
|
|
526
|
+
→ the table had no column events before 1.1.110 → `onColumnResizeEnd` / `onColumnMoveEnd` (R18),
|
|
527
|
+
`ColumnDef.resizable: false` / `movable: false`, the built-in double click (`columnAutoWidth`).
|
|
501
528
|
- **`AsyncBodyAreaModelObjectArray` cannot be imported** → unfinished, not exported → own `AreaModel` (R8, R17).
|
|
502
529
|
- **Invented APIs** – these do NOT exist: `getSelectedRows()`, `onKeyDown`, `api.addRow()`, `api.refresh()`,
|
|
503
530
|
`setData()`, `gridOptions`, `rowData`, `columnDefs` as a table option (it is a model parameter). Use R4–R7.
|
|
@@ -511,6 +538,7 @@ Full answers: instructions.md section 6.26 (https://github.com/guiexperttable/mo
|
|
|
511
538
|
- Rows that keep coming (log, stream, ticker of trades): `tableApi.appendRows(rows, { follow: "auto", maxRows })` (since 1.1.108) – in place, O(k), one render, filter/sort only for new rows, selection/focus stay; freeze = `follow: false`, jump to the end = `repaintHard({ py: Number.MAX_SAFE_INTEGER })`. Own AreaModel: `rowsAppended(count, { removedAtStart })`. Not `addRows()`.
|
|
512
539
|
- `repaint()` = values changed, same row count; `repaintHard()` = row count or heights changed; `updateCells()` = single cells.
|
|
513
540
|
- Variable row heights: implement `getRowHeight(i)`; `getConstantRowHeight()` only if all rows are equally high. `defaultRowHeights` only applies to models the factory builds or whose `getRowHeight()` returns 0.
|
|
541
|
+
- Save the column layout when the user resizes or moves a column: `onColumnResizeEnd` / `onColumnMoveEnd` (wrappers `columnResizeEnd`, `columnMoveEnd`, since 1.1.110) – once per drag, after the change; read `tableApi.getState(["columns"])` there. Lock a column: `ColumnDef.resizable: false`, `movable: false`. Double click on the column border fits the width (`columnAutoWidth`, `tableApi.autoResizeColumn(column)`).
|
|
514
542
|
- Empty table: the host div needs a fixed height and the stylesheet `@guiexpert/table/css/main.css`.
|
|
515
543
|
|
|
516
544
|
## Feature reference
|
|
@@ -544,7 +572,8 @@ What the table can do – one line per feature, details in instructions.md (each
|
|
|
544
572
|
- Undo/redo (since 1.1.99): tableOptions.undo: true | { maxSteps, maxCells, onConflict: "skip" | "overwrite", recordApiChanges } – Ctrl+Z / Ctrl+Y (Cmd+Shift+Z) for edit, fill, paste, cut, clear, batch edits and structure changes; rows found by object (sorting/filter safe). api.undo(), redo(), canUndo(), canRedo(), clearUndoHistory(), getUndoState(), batchUndoable(label, fn); event onUndoStackChanged (GeUndoEvent: canUndo, canRedo, undoLabel, redoLabel).
|
|
545
573
|
- Cell formulas with A1 references (since 1.1.99): tableOptions.cellFormulas: true | { columns, functions } (ColumnDef.cellFormulas: false = free text) – texts with "=" in the data are formulas ("'=" = text): A1, $A$1, B2:D9, A:A, 70 Excel functions (FORMULA_FUNCTION_INFO; SUM, AVERAGE, IF, IFS, VLOOKUP, XLOOKUP, INDEX/MATCH, SUMIFS, COUNTIFS, TEXT, DATE, EOMONTH …), errors #DIV/0! #REF! #NAME? #VALUE! #N/A #NUM! #CIRC!; dependency graph, only dependents recalculate; own parser, no eval. Formula input: colored references, pointing with arrows/mouse, F4 toggles $, function list (combobox) and hint. Fill/copy shift relative references; Excel export with real formulas: downloadExcel(name, author, { cellFormulas: true }). api.getCellInput/getCellValue/setCellInput/getCellAddress/getCellByAddress/evaluateFormula/getPrecedents/getDependents/recalculate/getSheetEngine. DOM-free: SheetEngine.fromArrays(data), shiftFormula, adjustFormula.
|
|
546
574
|
- Spreadsheet mode (since 1.1.99): SpreadsheetFactory.create({ data: unknown[][], rowCount (100), columnCount (26), columnWidth, rowHeight, rowNumbers, locale, functions, tableOptions }) → { tableModel: SpreadsheetTableModel, tableOptions } – column letters (AreaModelSheetHeader), row numbers, sparse AreaModelSheet; preset tableOptions.spreadsheet: true | { editing, clipboard, undo, cellFormulas, fillHandle } (false = off) for any flat table (TableFactory columnLetters: true). FormulaBar(container, api) – address box + formula input. api.getActiveCell(), goToAddress("B2:C5"), insertRows(at, count), deleteRows, insertColumns, deleteColumns (references adjusted, one undo step, source "structure"), getSheetData() (inputs for JSON).
|
|
547
|
-
- Angular signal component (since 1.1.100, Angular 22 and later): TableSignalComponent, selector guiexpert-table-signal, from @guiexpert/angular-table@22.x – inputs (input()) tableModel (TableModelIf | undefined), tableOptions (default new TableOptions()), loading, debounceMouseClickDelay (150, 0 = synchronous); tableApi = model<TableApi | undefined>() → [(tableApi)]="api" with api = signal<TableApi | undefined>(undefined), (tableApiChange), viewChild(TableSignalComponent)?.tableApi(); set when the table is built, switches directly to the new API on a new model/options, undefined after destroy, written from outside = replaced. Outputs (output()): no tableReady (the API comes as the signal tableApi / tableApiChange), mouseClicked, mouseMoved, mouseDragging, mouseDraggingEnded, contextMenu (camelCase – TableComponent's (contextmenu) also receives the native MouseEvent first), scroll, modelChanged, selectionChanged, focusChanged, checkboxChanged, stateChanged, rowDragStart/Move/End, batchEditChanged, detailExpandedChanged, editingChanged, undoStackChanged – events of the table (mouse, keyboard, scroll …) are emitted outside the Angular zone (write signals in handlers). effect() instead of ngOnChanges, no RxJS, zoneless (provideZonelessChangeDetection()), SSR: no table on the server. TableComponent (<guiexpert-table>) unchanged for Angular 14 – 22+.
|
|
575
|
+
- Angular signal component (since 1.1.100, Angular 22 and later): TableSignalComponent, selector guiexpert-table-signal, from @guiexpert/angular-table@22.x – inputs (input()) tableModel (TableModelIf | undefined), tableOptions (default new TableOptions()), loading, debounceMouseClickDelay (150, 0 = synchronous); tableApi = model<TableApi | undefined>() → [(tableApi)]="api" with api = signal<TableApi | undefined>(undefined), (tableApiChange), viewChild(TableSignalComponent)?.tableApi(); set when the table is built, switches directly to the new API on a new model/options, undefined after destroy, written from outside = replaced. Outputs (output()): no tableReady (the API comes as the signal tableApi / tableApiChange), mouseClicked, mouseMoved, mouseDragging, mouseDraggingEnded, contextMenu (camelCase – TableComponent's (contextmenu) also receives the native MouseEvent first), scroll, modelChanged, selectionChanged, focusChanged, checkboxChanged, stateChanged, rowDragStart/Move/End, batchEditChanged, detailExpandedChanged, editingChanged, undoStackChanged, columnResizeStart/End, columnMoveStart/End (since 1.1.110) – events of the table (mouse, keyboard, scroll …) are emitted outside the Angular zone (write signals in handlers). effect() instead of ngOnChanges, no RxJS, zoneless (provideZonelessChangeDetection()), SSR: no table on the server. TableComponent (<guiexpert-table>) unchanged for Angular 14 – 22+.
|
|
576
|
+
- Column drag (since 1.1.110): events EventListenerIf.onColumnResizeStart/End (GeColumnResizeEvent: type "start" | "end" | "cancel", source "mouse" | "dblclick", columnIndex, columnDef, property, oldWidth, newWidth) and onColumnMoveStart/End (GeColumnMoveEvent: type, fromIndex, toIndex, columnDef, property, columnOrder, moved) – only user actions, once per drag, the end after the change, start after 4 px, Escape / tableApi.cancelColumnDrag() = "cancel", tableApi.isColumnDragging(); wrappers columnResizeStart/End, columnMoveStart/End. Locks: ColumnDef.resizable: false (no handle, no double click, no auto width), movable: false (fixed place, applyState keeps it); RowNumberColumnDef has both false; a column stays in its area (west/center/east). Double click on the resize handle fits the width (no sorting): tableOptions.columnAutoWidth: { doubleClick (true), maxRows (10,000: all body rows, above only the rendered rows), getWidth(ctx: ColumnAutoWidthContextIf { columnIndex, columnDef, property, source, firstRenderedRow, lastRenderedRow, measureText(text), getDefaultWidth() }) => number | undefined }, limited by minWidth/maxWidth; tableApi.autoResizeColumn(index | property | ColumnDef) → width | undefined.
|
|
548
577
|
- Live data / log tail (since 1.1.108): tableApi.appendRows(rows, { follow?: "auto" (default: stays at the end if it was at the end, else the first visible row stays) | true (always the end) | false (freeze), maxRows?: ring buffer – oldest rows removed from the start in blocks of ≥ 1 % }) → AppendRowsResultIf { added, shown, removed, following } | false (tree, row groups, pivot, spreadsheet, cell formulas) – AreaModelObjectArray body only, IN PLACE (pushes to your array, no copy), O(k): externalFilterFunction only for the new rows, sorted column / sort(fn) → merged in (binary search, behind equal rows); selection, focus, Shift+arrow anchor and checked rows stay at their rows (RowIndexShift, SelectionModel/FocusModel.adjustForRowChanges – no onSelectionChanged unless a selected row left the buffer); one render pass, none when only rows below the view came in (cells not rebuilt). Held mouse button: "auto" keeps the rows under the pointer and follows again after release. Own AreaModel: append yourself, then tableApi.rowsAppended(count, { follow, removedAtStart }). Not addRows() (copies all rows, resets filter and sort). Showcase logtail, demo apps/table-demo/log-tail.html, LogTailController + createLogTailModelAndOptions in @guiexpert/demo-table-models.
|
|
549
578
|
- Custom filtering
|
|
550
579
|
- In-place cell editing
|