@guiexpert/table 1.1.94 → 1.1.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +12 -0
  2. package/css/main.css +192 -0
  3. package/css/table-calc.css +7 -0
  4. package/css/table-color-vars.css +46 -0
  5. package/css/table-fill-batch.css +58 -0
  6. package/css/table-row-drag.css +81 -0
  7. package/index.cjs +39 -37
  8. package/index.d.ts +28 -0
  9. package/index.js +5501 -1934
  10. package/lib/table/action/action-id.type.d.ts +1 -1
  11. package/lib/table/aria/aria-texts.d.ts +11 -0
  12. package/lib/table/aria/aria-texts.if.d.ts +87 -0
  13. package/lib/table/batch-edit/batch-edit-options.d.ts +21 -0
  14. package/lib/table/batch-edit/batch-edit-options.if.d.ts +20 -0
  15. package/lib/table/batch-edit/batch-edit-service.d.ts +104 -0
  16. package/lib/table/batch-edit/cell-change.if.d.ts +39 -0
  17. package/lib/table/batch-edit/cell-value-change.if.d.ts +18 -0
  18. package/lib/table/batch-edit/pending-cell-changes.d.ts +104 -0
  19. package/lib/table/calc/column-values.d.ts +55 -0
  20. package/lib/table/calc/show-values-as-internals.d.ts +4 -0
  21. package/lib/table/calc/show-values-as.d.ts +87 -0
  22. package/lib/table/calc/show-values-as.type.d.ts +55 -0
  23. package/lib/table/calc/value-getter-context.if.d.ts +35 -0
  24. package/lib/table/calc/value-getter.type.d.ts +36 -0
  25. package/lib/table/data/common/event/ge-batch-edit-event.d.ts +46 -0
  26. package/lib/table/data/common/event/ge-model-change-event.d.ts +27 -1
  27. package/lib/table/data/common/event/ge-row-drag-event.d.ts +89 -0
  28. package/lib/table/data/options/table-options.d.ts +6 -0
  29. package/lib/table/data/options/table-options.if.d.ts +44 -0
  30. package/lib/table/data/tablemodel/areamodel/abstract-area-model.d.ts +66 -0
  31. package/lib/table/data/tablemodel/areamodel/area-model-aggregate-footer.d.ts +5 -0
  32. package/lib/table/data/tablemodel/areamodel/area-model-array-of-arrays.d.ts +24 -0
  33. package/lib/table/data/tablemodel/areamodel/area-model-object-array.d.ts +70 -0
  34. package/lib/table/data/tablemodel/areamodel/area-model-pivot.d.ts +31 -0
  35. package/lib/table/data/tablemodel/areamodel/area-model-row-groups.d.ts +23 -1
  36. package/lib/table/data/tablemodel/areamodel/area-model-tree.d.ts +83 -0
  37. package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +55 -0
  38. package/lib/table/data/tablemodel/column/column-def.d.ts +31 -1
  39. package/lib/table/data/tablemodel/column/column-def.if.d.ts +86 -0
  40. package/lib/table/event-adapter.d.ts +7 -0
  41. package/lib/table/event-listener.if.d.ts +32 -0
  42. package/lib/table/factory/table-factory.d.ts +11 -0
  43. package/lib/table/fill/compute-fill-changes.d.ts +67 -0
  44. package/lib/table/fill/fill-direction.type.d.ts +7 -0
  45. package/lib/table/fill/fill-handle-options.d.ts +29 -0
  46. package/lib/table/fill/fill-handle-options.if.d.ts +35 -0
  47. package/lib/table/fill/fill-handle-service.d.ts +55 -0
  48. package/lib/table/fill/fill-series.d.ts +60 -0
  49. package/lib/table/fill/fill-value-context.if.d.ts +36 -0
  50. package/lib/table/formula/compile-formula.d.ts +86 -0
  51. package/lib/table/formula/evaluator.d.ts +19 -0
  52. package/lib/table/formula/formula-ast.if.d.ts +42 -0
  53. package/lib/table/formula/formula-error.d.ts +59 -0
  54. package/lib/table/formula/formula-options.if.d.ts +41 -0
  55. package/lib/table/formula/formula-values.d.ts +13 -0
  56. package/lib/table/formula/functions.d.ts +18 -0
  57. package/lib/table/formula/parser.d.ts +10 -0
  58. package/lib/table/formula/tokenizer.d.ts +22 -0
  59. package/lib/table/pivot/pivot-value.type.d.ts +13 -0
  60. package/lib/table/render-scope.d.ts +81 -0
  61. package/lib/table/renderer/edit/input-cell-renderer.d.ts +1 -1
  62. package/lib/table/renderer/edit/select-cell-renderer.d.ts +1 -1
  63. package/lib/table/row-drag/move-rows.d.ts +157 -0
  64. package/lib/table/row-drag/row-drag-options.d.ts +28 -0
  65. package/lib/table/row-drag/row-drag-options.if.d.ts +36 -0
  66. package/lib/table/row-drag/row-drag-service.d.ts +130 -0
  67. package/lib/table/row-drag/row-drop-target.if.d.ts +29 -0
  68. package/lib/table/service/excel-service.d.ts +6 -0
  69. package/lib/table/service/excel-service.if.d.ts +35 -0
  70. package/lib/table/table-api.d.ts +277 -2
  71. package/lib/table/table-scope.d.ts +121 -0
  72. package/package.json +1 -1
@@ -13,6 +13,15 @@ import { AreaModelIf } from './data/tablemodel/areamodel/area-model.if.js';
13
13
  import { PivotConfigIf } from './pivot/pivot-config.if.js';
14
14
  import { RowGroupField } from './rowgroup/row-group-field.type.js';
15
15
  import { SelectionAggregatesIf } from './aggregation/selection-aggregates.if.js';
16
+ import { ShowValuesAsConfig } from './calc/show-values-as.type.js';
17
+ import { FormulaOptionsIf } from './formula/formula-options.if.js';
18
+ import { FormulaError } from './formula/formula-error.js';
19
+ import { RowDropTargetIf } from './row-drag/row-drop-target.if.js';
20
+ import { CellChangeIf, CellChangeSource } from './batch-edit/cell-change.if.js';
21
+ import { CellValueChangeIf } from './batch-edit/cell-value-change.if.js';
22
+ import { FillDirection } from './fill/fill-direction.type.js';
23
+ import { FillMode } from './fill/fill-series.js';
24
+ import { CellRange } from './data/common/cell-range.js';
16
25
 
17
26
  /**
18
27
  * The public API of one table – everything you do with a table after it has been created:
@@ -37,7 +46,8 @@ import { SelectionAggregatesIf } from './aggregation/selection-aggregates.if.js'
37
46
  * | sort | {@link sortByColumn}, {@link sort}, {@link reSort} |
38
47
  * | filter | {@link externalFilterChanged} (with {@link TableOptionsIf.externalFilterFunction}) |
39
48
  * | export | {@link copyToClipboard}, {@link downloadExcel} |
40
- * | change data | {@link updateCells}, {@link setRows}, {@link addRows}, {@link updateRows}, {@link removeRows} |
49
+ * | change data | {@link updateCells}, {@link setRows}, {@link addRows}, {@link updateRows}, {@link removeRows}, {@link applyCellChanges} |
50
+ * | fill, batch edit | {@link fillRange}, {@link startBatchEdit}, {@link getPendingChanges}, {@link commitBatchEdit}, {@link cancelBatchEdit} |
41
51
  * | redraw | {@link repaint} (same row count), {@link repaintHard} (row count or heights changed) |
42
52
  * | columns | {@link autoResizeColumns}, {@link setColumnWidth}, {@link recalcColumnWidths}, {@link getColumnIndex} |
43
53
  * | tree | {@link expandAll}, {@link collapseAll}, {@link setRowExpanded} |
@@ -529,7 +539,7 @@ export declare class TableApi {
529
539
  * @param {ActionId} actionId - The ID of the action to trigger.
530
540
  * @return {void}
531
541
  */
532
- triggerAction(actionId: ActionId): void;
542
+ triggerAction(actionId: ActionId): boolean;
533
543
  /**
534
544
  * Retrieves the shortcut action mapping from the table's shortcut service.
535
545
  *
@@ -1297,6 +1307,69 @@ export declare class TableApi {
1297
1307
  * @since 1.1.94
1298
1308
  */
1299
1309
  getPivotConfig(): PivotConfigIf | undefined;
1310
+ /**
1311
+ * The value of a column for a row object – computed for a calculated column (`valueGetter`, `formula`), otherwise
1312
+ * the property (path). Use it in the external filter to filter by calculated values; a `TreeRow` is unwrapped.
1313
+ *
1314
+ * @param {any} row - a row object (or the `TreeRow` a tree filter gets)
1315
+ * @param {string} property - the property of the column
1316
+ * @returns {unknown} the value (a {@link FormulaError} for a formula error)
1317
+ *
1318
+ * @example
1319
+ * tableOptions.externalFilterFunction = (row: Item) => Number(tableApi.getRowValue(row, "total")) > 500;
1320
+ * tableApi.externalFilterChanged();
1321
+ *
1322
+ * @since 1.1.95
1323
+ */
1324
+ getRowValue(row: any, property: string): unknown;
1325
+ /**
1326
+ * „Show values as“: shows the numbers of a column differently – share of the column total, running total, rank …
1327
+ * (see {@link ShowValuesAs}) – or normal again (`undefined`). No new model: the table repaints.
1328
+ *
1329
+ * @param {string} property - the property of the column
1330
+ * @param {ShowValuesAsConfig | undefined} showValuesAs - the mode (with options) or `undefined` for the values
1331
+ * @returns {boolean} false if there is no such column or the mode is unknown
1332
+ *
1333
+ * @example
1334
+ * select.addEventListener("change", () =>
1335
+ * tableApi.setShowValuesAs("total", select.value ? select.value as ShowValuesAs : undefined));
1336
+ *
1337
+ * @since 1.1.95
1338
+ */
1339
+ setShowValuesAs(property: string, showValuesAs: ShowValuesAsConfig | undefined): boolean;
1340
+ /**
1341
+ * „Show values as“ of a column.
1342
+ *
1343
+ * @param {string} property - the property of the column
1344
+ * @returns {ShowValuesAsConfig | undefined} the configuration, `undefined` for none
1345
+ *
1346
+ * @example
1347
+ * const mode = tableApi.getShowValuesAs("total"); // "percentOfColumnTotal"
1348
+ *
1349
+ * @since 1.1.95
1350
+ */
1351
+ getShowValuesAs(property: string): ShowValuesAsConfig | undefined;
1352
+ /**
1353
+ * Sets (or replaces) the formula of a column – e.g. from an input field of your app. The formula is compiled
1354
+ * once; an invalid formula is set anyway (the cells show `#ERROR!` / `#NAME?`) and its error is returned, so you can
1355
+ * show the message next to the input. No code is ever executed (no `eval`). The table repaints; totals, sorting
1356
+ * and filter see the new values after `repaint`, `reSort()` resp. `externalFilterChanged()`.
1357
+ *
1358
+ * @param {string} property - the property of the column (it becomes a calculated column)
1359
+ * @param {string} formula - the formula, e.g. `"[price] * [quantity] * 1.19"`
1360
+ * @param {FormulaOptionsIf} [options] - own functions
1361
+ * @returns {FormulaError | undefined} the error of the formula itself, `undefined` if it is valid
1362
+ * (`#NAME?` also if there is no such column)
1363
+ *
1364
+ * @example
1365
+ * input.addEventListener("change", () => {
1366
+ * const error = tableApi.setColumnFormula("custom", input.value);
1367
+ * hint.textContent = error ? `${error.code} ${error.message}` : "";
1368
+ * });
1369
+ *
1370
+ * @since 1.1.95
1371
+ */
1372
+ setColumnFormula(property: string, formula: string, options?: FormulaOptionsIf): FormulaError | undefined;
1300
1373
  /**
1301
1374
  * Sorts the table data using a custom comparison function.
1302
1375
  *
@@ -1347,6 +1420,208 @@ export declare class TableApi {
1347
1420
  * tableApi.sort((a: TreeRowIf<OrderNode>, b: TreeRowIf<OrderNode>) => b.data.total - a.data.total);
1348
1421
  */
1349
1422
  sort(compareFn: (a: any, b: any) => number): void;
1423
+ /**
1424
+ * Moves body rows – the code way to do what row drag does (e.g. "up"/"down" buttons, the pointer alternative of
1425
+ * WCAG 2.5.7, or after the server confirmed an unmanaged drag). The body model must support it
1426
+ * ({@link AreaModelIf.moveRows}: object arrays, arrays of arrays, trees); no filter may hide rows and no column may be
1427
+ * sorted (asc/desc – a sorted view has no order of its own). Focus and a multi-row selection follow the rows; screen
1428
+ * readers hear "Row moved to position 7 of 20". No row drag events. `false` if nothing moved (also for a target
1429
+ * where the rows already are).
1430
+ *
1431
+ * @param {number[] | number} rowIndices - display index or indices of the rows to move
1432
+ * @param {RowDropTargetIf | number} target - drop target; a number = in front of that display index
1433
+ * (`getDisplayedRowCount()` = behind the last row)
1434
+ * @returns {boolean} true if the rows were moved
1435
+ *
1436
+ * @example
1437
+ * tableApi.moveRows(2, { rowIndex: 6, position: "after" }); // row 3 becomes row 7
1438
+ * tableApi.moveRows([0, 1], tableApi.getDisplayedRowCount()); // the first two rows to the end
1439
+ *
1440
+ * @example
1441
+ * // unmanaged drag: the server decides, then the table moves the rows
1442
+ * const listener = new EventAdapter();
1443
+ * listener.onRowDragEnd = async (evt: GeRowDragEvent) => {
1444
+ * if (evt.type === "end" && evt.target && (await fetch("/api/move", { method: "POST" })).ok) {
1445
+ * tableApi.moveRows(evt.rowIndices, evt.target);
1446
+ * }
1447
+ * };
1448
+ *
1449
+ * @since 1.1.95
1450
+ */
1451
+ moveRows(rowIndices: number[] | number, target: RowDropTargetIf | number): boolean;
1452
+ /**
1453
+ * True while rows are dragged with the pointer (mouse, touch, pen).
1454
+ *
1455
+ * @returns {boolean} true during a row drag
1456
+ *
1457
+ * @example
1458
+ * if (!tableApi.isRowDragging()) {
1459
+ * tableApi.updateCells([], true); // e.g. live data: wait until the drag is done
1460
+ * }
1461
+ *
1462
+ * @since 1.1.95
1463
+ */
1464
+ isRowDragging(): boolean;
1465
+ /**
1466
+ * Cancels a running row drag (like Escape): nothing is moved, `onRowDragEnd` gets the type `"cancel"`.
1467
+ *
1468
+ * @example
1469
+ * tableApi.cancelRowDrag(); // e.g. new data arrived from the server
1470
+ *
1471
+ * @since 1.1.95
1472
+ */
1473
+ cancelRowDrag(): void;
1474
+ /**
1475
+ * Writes values into body cells like the cell editor does – the one way the table changes cells (editor, fill
1476
+ * handle and batch commit use it too): cells that are not editable are skipped (`editable`, calculated columns
1477
+ * without `valueSetter`, group and pivot rows), values run through `editInputPipe` and {@link ColumnDefIf.validate}
1478
+ * (invalid ones are not written), totals and calculated columns follow, and **one** `onModelChanged` reports all
1479
+ * cells with old and new values. In a batch edit the values are marked as pending instead.
1480
+ *
1481
+ * Paste from the clipboard and undo/redo can be built on it: a {@link CellChangeIf} has the old and the new value.
1482
+ *
1483
+ * @param {CellValueChangeIf[]} changes - display row index, column (index or property) and value per cell
1484
+ * @param {CellChangeSource} [source="api"] - reported in {@link GeModelChangeEvent.source}
1485
+ * @returns {CellChangeIf[]} the written (batch edit: newly pending) cells
1486
+ *
1487
+ * @example
1488
+ * tableApi.applyCellChanges([
1489
+ * { rowIndex: 0, column: "price", value: 9.9 },
1490
+ * { rowIndex: 1, column: "price", value: 12 },
1491
+ * ]);
1492
+ *
1493
+ * @example
1494
+ * // undo the last change set (from onModelChanged)
1495
+ * const undo = (changes: CellChangeIf[]) => tableApi.applyCellChanges(
1496
+ * changes.map(c => ({ rowIndex: c.rowIndex, column: c.property, value: c.oldValue })));
1497
+ *
1498
+ * @since 1.1.96
1499
+ */
1500
+ applyCellChanges(changes: CellValueChangeIf[], source?: CellChangeSource): CellChangeIf[];
1501
+ /**
1502
+ * Fills cells next to a range – what dragging the fill handle does ({@link TableOptionsIf.fillHandle} is not
1503
+ * needed for this call): continues series (1, 2 → 3, 4; dates; `Item 1` → `Item 2`) or copies, writes with
1504
+ * {@link applyCellChanges} (one `onModelChanged`, source `"fill"`) and selects source and filled cells.
1505
+ *
1506
+ * @param {CellRange} source - the source range (body display indices)
1507
+ * @param {FillDirection} direction - `"down"`, `"up"`, `"right"` or `"left"`
1508
+ * @param {number} count - rows or columns to fill (clamped to the table)
1509
+ * @param {FillMode} [mode="auto"] - `"auto"`, `"alternate"` (like ⌥/Alt while dragging) or `"copy"`
1510
+ * @returns {number} the number of filled cells (batch edit: marked); `-1` if more than `maxCells`
1511
+ *
1512
+ * @example
1513
+ * // rows 0 and 1 of column 2 hold 1 and 2: rows 2…9 get 3…10
1514
+ * tableApi.fillRange(new CellRange(0, 2, 1, 2), "down", 8);
1515
+ *
1516
+ * @since 1.1.96
1517
+ */
1518
+ fillRange(source: CellRange, direction: FillDirection, count: number, mode?: FillMode): number;
1519
+ /**
1520
+ * True while the fill handle is dragged.
1521
+ *
1522
+ * @returns {boolean} true during a fill
1523
+ *
1524
+ * @example
1525
+ * if (!tableApi.isFilling()) {
1526
+ * tableApi.updateCells([], true); // e.g. live data: wait until the fill is done
1527
+ * }
1528
+ *
1529
+ * @since 1.1.96
1530
+ */
1531
+ isFilling(): boolean;
1532
+ /**
1533
+ * Cancels a running fill (like Escape): nothing is changed.
1534
+ *
1535
+ * @example
1536
+ * tableApi.cancelFill();
1537
+ *
1538
+ * @since 1.1.96
1539
+ */
1540
+ cancelFill(): void;
1541
+ /**
1542
+ * Starts a batch edit: from now on edited and filled values are **collected** – shown in the cells (class
1543
+ * `ge-table-cell-pending`), but not written into your rows – until {@link commitBatchEdit} or
1544
+ * {@link cancelBatchEdit}. Sorting, filtering, totals, copy and Excel use the written data. For a batch edit that is
1545
+ * always on use {@link TableOptionsIf.batchEdit}.
1546
+ *
1547
+ * @returns {boolean} false if a batch edit is already running
1548
+ *
1549
+ * @example
1550
+ * editButton.onclick = () => tableApi.startBatchEdit();
1551
+ * saveButton.onclick = () => tableApi.commitBatchEdit();
1552
+ * discardButton.onclick = () => tableApi.cancelBatchEdit();
1553
+ *
1554
+ * @since 1.1.96
1555
+ */
1556
+ startBatchEdit(): boolean;
1557
+ /**
1558
+ * True while values are collected (after {@link startBatchEdit}, or always with {@link TableOptionsIf.batchEdit}).
1559
+ *
1560
+ * @returns {boolean} whether a batch edit runs
1561
+ *
1562
+ * @example
1563
+ * saveButton.hidden = !tableApi.isBatchEditing();
1564
+ *
1565
+ * @since 1.1.96
1566
+ */
1567
+ isBatchEditing(): boolean;
1568
+ /**
1569
+ * True if a batch edit has values that are not written yet.
1570
+ *
1571
+ * @returns {boolean} whether there are pending changes
1572
+ *
1573
+ * @example
1574
+ * window.addEventListener("beforeunload", evt => {
1575
+ * if (tableApi.hasPendingChanges()) evt.preventDefault(); // "Leave site? Changes may not be saved."
1576
+ * });
1577
+ *
1578
+ * @since 1.1.96
1579
+ */
1580
+ hasPendingChanges(): boolean;
1581
+ /**
1582
+ * The values of a batch edit that are not written yet: row object, property, old and new value, the current display
1583
+ * index (`-1` while a filter hides the row) and the message of an invalid value. The changes belong to the rows, not
1584
+ * to their positions – sorting and filtering don't mix them up.
1585
+ *
1586
+ * @returns {CellChangeIf[]} the pending cells
1587
+ *
1588
+ * @example
1589
+ * saveButton.onclick = async () => {
1590
+ * const changes = tableApi.getPendingChanges()
1591
+ * .map(c => ({ id: (c.row as { id: number }).id, field: c.property, value: c.newValue }));
1592
+ * const response = await fetch("/api/prices", { method: "PATCH", body: JSON.stringify(changes) });
1593
+ * if (response.ok) tableApi.commitBatchEdit();
1594
+ * };
1595
+ *
1596
+ * @since 1.1.96
1597
+ */
1598
+ getPendingChanges(): CellChangeIf[];
1599
+ /**
1600
+ * Writes the pending values of a batch edit into the rows (through `setValue`, like the editor) and ends a batch edit
1601
+ * started with {@link startBatchEdit}: **one** `onModelChanged` (source `"commit"`) with all cells, then
1602
+ * `onBatchEditChanged` with the type `"commit"`. While a value is invalid ({@link ColumnDefIf.validate}) nothing is
1603
+ * written and the result is `false` (unless {@link BatchEditOptionsIf.blockCommitOnInvalid} is `false`).
1604
+ *
1605
+ * @returns {boolean} true if written
1606
+ *
1607
+ * @example
1608
+ * if (!tableApi.commitBatchEdit()) {
1609
+ * alert("Please fix the marked cells first.");
1610
+ * }
1611
+ *
1612
+ * @since 1.1.96
1613
+ */
1614
+ commitBatchEdit(): boolean;
1615
+ /**
1616
+ * Discards the pending values of a batch edit (the cells show the data again) and ends a batch edit started with
1617
+ * {@link startBatchEdit}.
1618
+ *
1619
+ * @example
1620
+ * discardButton.onclick = () => tableApi.cancelBatchEdit();
1621
+ *
1622
+ * @since 1.1.96
1623
+ */
1624
+ cancelBatchEdit(): void;
1350
1625
  /**
1351
1626
  * Ensures that a specific row is visible in the viewport by scrolling if necessary.
1352
1627
  * This method checks if the target row is within the currently visible range and
@@ -36,6 +36,13 @@ import { ResizeHandler } from './resize-handler.js';
36
36
  import { ExcelServiceIf } from './service/excel-service.if.js';
37
37
  import { ColumnDefIf } from './data/tablemodel/column/column-def.if.js';
38
38
  import { LiveAnnouncer } from './aria/live-announcer.js';
39
+ import { FillHandleOptionsIf } from './fill/fill-handle-options.if.js';
40
+ import { CellChangeIf, CellChangeSource } from './batch-edit/cell-change.if.js';
41
+ import { CellValueChangeIf } from './batch-edit/cell-value-change.if.js';
42
+ import { FillDirection } from './fill/fill-direction.type.js';
43
+ import { FillMode } from './fill/fill-series.js';
44
+ import { CellRange } from './data/common/cell-range.js';
45
+ import { AriaTextsIf } from './aria/aria-texts.if.js';
39
46
 
40
47
  /**
41
48
  * Creates and runs one table in a host element – the core that every framework wrapper uses.
@@ -146,6 +153,21 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
146
153
  * @return {boolean} - Returns true if the action was triggered successfully, false otherwise.
147
154
  */
148
155
  onActionTriggered(actionId: ActionId): boolean;
156
+ /**
157
+ * The event listener of this table (the one given to the constructor, or an empty {@link EventAdapter}).
158
+ *
159
+ * @returns {EventListenerIf} the listener
160
+ * @since 1.1.95
161
+ */
162
+ getEventListener(): EventListenerIf;
163
+ /**
164
+ * Called after rows were moved in the body model (row drag, {@link TableApi.moveRows}): drops derived values
165
+ * (totals, „Show values as“) and forgets a sort function of `tableApi.sort(fn)` – the moved order wins.
166
+ * The caller repaints.
167
+ *
168
+ * @since 1.1.95
169
+ */
170
+ afterRowsMoved(): void;
149
171
  /**
150
172
  * Speaks a message to screen reader users (polite live region, see {@link LiveAnnouncer}).
151
173
  *
@@ -223,7 +245,106 @@ export declare class TableScope extends RenderScope implements OnActionTriggered
223
245
  * first, so the blur caused by closing does not commit the typed text ("change" event)
224
246
  */
225
247
  cancelEditing(editor?: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void;
248
+ /**
249
+ * Writes the text of a cell editor (called by the input handler on "change"). Batch edit: the value is marked as
250
+ * pending instead. Uses {@link applyCellChanges} – one `onModelChanged` per edit, as before.
251
+ *
252
+ * @param {AreaIdent} areaIdent - only `"body"` is edited
253
+ * @param {number} rowIndex - display index
254
+ * @param {number} columnIndex - model index
255
+ * @param {string} value - the text of the editor
256
+ */
226
257
  updateModelValueAfterEdit(areaIdent: AreaIdent, rowIndex: number, columnIndex: number, value: string): void;
258
+ /**
259
+ * The one place that changes body cells (editor, fill handle, batch commit, {@link TableApi.applyCellChanges}):
260
+ * skips cells that are not editable (`editable`, calculated columns without `valueSetter`, group/pivot rows),
261
+ * applies `editInputPipe` and {@link ColumnDefIf.validate}, then writes – or, in a batch edit, marks the values as
262
+ * pending. Writing reports **one** `onModelChanged` with all cells; derived values (totals, calculated columns) are
263
+ * recomputed and the table repaints.
264
+ *
265
+ * @param {CellValueChangeIf[]} changes - cells and values (column as index or property)
266
+ * @param {CellChangeSource} [source="api"] - reported in the event
267
+ * @returns {CellChangeIf[]} the written (or, in a batch edit, newly pending) cells
268
+ * @since 1.1.96
269
+ */
270
+ applyCellChanges(changes: CellValueChangeIf[], source?: CellChangeSource): CellChangeIf[];
271
+ /**
272
+ * Writes cell values directly (no batch edit) – used by {@link applyCellChanges} and the batch commit.
273
+ *
274
+ * @param {{ rowIndex: number, columnIndex: number, value: unknown }[]} cells - resolved cells (display/model indices)
275
+ * @param {CellChangeSource} source - reported in the event
276
+ * @param {{ extraChanges?: CellChangeIf[], skipValidation?: boolean }} [opts] - changes written elsewhere (reported
277
+ * in the same event), no validation (commit: already checked)
278
+ * @returns {CellChangeIf[]} the written cells (including `extraChanges`)
279
+ * @since 1.1.96
280
+ */
281
+ writeCells(cells: {
282
+ rowIndex: number;
283
+ columnIndex: number;
284
+ value: unknown;
285
+ }[], source: CellChangeSource, opts?: {
286
+ extraChanges?: CellChangeIf[];
287
+ skipValidation?: boolean;
288
+ }): CellChangeIf[];
289
+ private writeCellsInternal;
290
+ /** Marks values as pending (batch edit): pipe, validation, then the batch edit service. */
291
+ private markPending;
292
+ /**
293
+ * Column property → index, range check, editable check (not for the editor: it was opened on an editable cell).
294
+ */
295
+ private resolveCellChanges;
296
+ /** The value after the column's `editInputPipe` (as `setValue` will store it). */
297
+ private pipeCellValue;
298
+ /** The message of {@link ColumnDefIf.validate} – `undefined` if valid or without validator. */
299
+ private validateCellValue;
300
+ /** The row object of a body row for events: the data of a `TreeRow`, `undefined` without objects. */
301
+ private rowObjectOf;
302
+ /**
303
+ * The options of the fill handle, `undefined` if it is off ({@link TableOptionsIf.fillHandle}).
304
+ *
305
+ * @returns {FillHandleOptionsIf | undefined} complete options
306
+ * @since 1.1.96
307
+ */
308
+ getFillHandleOptions(): FillHandleOptionsIf | undefined;
309
+ /**
310
+ * Fills cells next to a range (fill handle, Ctrl/⌘+D, {@link TableApi.fillRange}): computes the values
311
+ * ({@link computeFillChanges}, shown values – a batch edit's pending values count), writes them with
312
+ * {@link applyCellChanges} and selects source and filled cells.
313
+ *
314
+ * @param {CellRange} source - the source range (body display indices)
315
+ * @param {FillDirection} direction - down, up, right or left
316
+ * @param {number} count - rows or columns to fill (clamped to the table)
317
+ * @param {FillMode} [mode="auto"] - series or copy
318
+ * @param {CellRange} [selectAfter] - the selection afterwards (default: source and filled cells)
319
+ * @returns {number} the number of filled (or, in a batch edit, marked) cells; `-1` if refused (too many cells)
320
+ * @since 1.1.96
321
+ */
322
+ fillRange(source: CellRange, direction: FillDirection, count: number, mode?: FillMode, selectAfter?: CellRange): number;
323
+ /** The last selected range, clamped to the body (`undefined` without one). */
324
+ getFillSourceRange(): CellRange | undefined;
325
+ private normalizeRange;
326
+ /**
327
+ * Ctrl/⌘+D (down) and Ctrl/⌘+R (right): the first row (column) of the selected range is copied into the rest; a
328
+ * range of one row (column) gets the cell above (left of) it – like a spreadsheet.
329
+ *
330
+ * @param {"down" | "right"} direction - the key
331
+ * @returns {boolean} true if the key was used (the browser's own action – bookmark, reload – is prevented then)
332
+ */
333
+ private fillByKeyboard;
334
+ /**
335
+ * Sets `aria-keyshortcuts` of the host (the fill handle's keyboard alternative); removed again by {@link destroy}.
336
+ *
337
+ * @param {string | undefined} value - e.g. `"Control+D Control+R"`; `undefined` restores the value before
338
+ * @since 1.1.96
339
+ */
340
+ setHostKeyShortcuts(value: string | undefined): void;
341
+ /**
342
+ * The texts of fill and batch edit with defaults (an own {@link AriaTextsIf} implementation may lack them).
343
+ *
344
+ * @returns the texts
345
+ * @since 1.1.96
346
+ */
347
+ getEditTexts(): Required<Pick<AriaTextsIf, 'cellsFilled' | 'fillTooLarge' | 'pendingChanges' | 'changesCommitted' | 'changesDiscarded' | 'commitBlocked' | 'invalidValue'>>;
227
348
  /**
228
349
  * Retrieves the TableApi object.
229
350
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guiexpert/table",
3
- "version": "1.1.94",
3
+ "version": "1.1.96",
4
4
  "license": "MIT",
5
5
  "author": "Dr. Marc Kronberg <info@gui.expert> (https://gui.expert)",
6
6
  "repository": {