@guiexpert/table 1.1.98 → 1.1.99
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 +9 -0
- package/css/main.css +296 -0
- package/css/table-clipboard.css +41 -0
- package/css/table-color-vars.css +56 -0
- package/css/table-sheet-editing.css +149 -0
- package/css/table-spreadsheet.css +50 -0
- package/index.cjs +46 -59
- package/index.d.ts +46 -0
- package/index.js +18934 -11624
- package/lib/table/action/action-id.type.d.ts +1 -1
- package/lib/table/action/shortcut.service.d.ts +9 -0
- package/lib/table/aria/aria-texts.d.ts +26 -0
- package/lib/table/aria/aria-texts.if.d.ts +196 -0
- package/lib/table/batch-edit/batch-edit-service.d.ts +22 -0
- package/lib/table/batch-edit/cell-change.if.d.ts +6 -2
- package/lib/table/batch-edit/pending-cell-changes.d.ts +7 -0
- package/lib/table/batch-edit/write-row-value.d.ts +14 -0
- package/lib/table/calc/column-values.d.ts +2 -0
- package/lib/table/clipboard/clipboard-html.d.ts +41 -0
- package/lib/table/clipboard/clipboard-keymap.d.ts +18 -0
- package/lib/table/clipboard/clipboard-options.d.ts +30 -0
- package/lib/table/clipboard/clipboard-options.if.d.ts +67 -0
- package/lib/table/clipboard/clipboard-service.d.ts +122 -0
- package/lib/table/clipboard/input-pipes.d.ts +59 -0
- package/lib/table/clipboard/paste-plan.d.ts +96 -0
- package/lib/table/clipboard/tsv.d.ts +31 -0
- package/lib/table/data/common/event/ge-edit-event.d.ts +46 -0
- package/lib/table/data/common/event/ge-row-drag-event.d.ts +2 -2
- package/lib/table/data/common/event/ge-undo-event.d.ts +29 -0
- package/lib/table/data/options/table-options.d.ts +28 -0
- package/lib/table/data/options/table-options.if.d.ts +99 -1
- package/lib/table/data/tablemodel/areamodel/abstract-area-model.d.ts +11 -2
- package/lib/table/data/tablemodel/areamodel/area-model-array-of-arrays.d.ts +14 -0
- package/lib/table/data/tablemodel/areamodel/area-model-object-array.d.ts +14 -0
- package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +11 -0
- package/lib/table/data/tablemodel/column/column-def.d.ts +13 -0
- package/lib/table/data/tablemodel/column/column-def.if.d.ts +36 -1
- package/lib/table/data/tablemodel/column/default-editable.d.ts +18 -0
- package/lib/table/event-adapter.d.ts +6 -0
- package/lib/table/event-listener-hub.d.ts +10 -0
- package/lib/table/event-listener.if.d.ts +16 -0
- package/lib/table/factory/pivot-factory.d.ts +1 -1
- package/lib/table/factory/row-group-factory.d.ts +1 -1
- package/lib/table/factory/table-factory.d.ts +14 -0
- package/lib/table/formula/formula-ast.if.d.ts +32 -2
- package/lib/table/formula/formula-error.d.ts +4 -2
- package/lib/table/formula/parser.d.ts +5 -2
- package/lib/table/formula/tokenizer.d.ts +5 -2
- package/lib/table/input-handler.d.ts +8 -0
- package/lib/table/master-detail/master-detail-service.d.ts +9 -0
- package/lib/table/render-scope.d.ts +40 -0
- package/lib/table/row-drag/row-drag-service.d.ts +3 -2
- package/lib/table/selection/selection-service.d.ts +48 -0
- package/lib/table/service/excel-export-options.if.d.ts +6 -0
- package/lib/table/service/excel-service.d.ts +4 -0
- package/lib/table/service/excel-service.if.d.ts +35 -0
- package/lib/table/sheet/cell-address.d.ts +100 -0
- package/lib/table/sheet/cell-formula-options.d.ts +27 -0
- package/lib/table/sheet/cell-formula-options.if.d.ts +27 -0
- package/lib/table/sheet/excel-formula.d.ts +20 -0
- package/lib/table/sheet/format-formula.d.ts +19 -0
- package/lib/table/sheet/sheet-cells.if.d.ts +17 -0
- package/lib/table/sheet/sheet-compiler.d.ts +47 -0
- package/lib/table/sheet/sheet-engine.d.ts +207 -0
- package/lib/table/sheet/sheet-function-info.d.ts +25 -0
- package/lib/table/sheet/sheet-functions.d.ts +27 -0
- package/lib/table/sheet/sheet-values.d.ts +154 -0
- package/lib/table/sheet/shift-formula.d.ts +71 -0
- package/lib/table/sheet/table-sheet.d.ts +214 -0
- package/lib/table/sheet-editing/cell-editor-service.d.ts +105 -0
- package/lib/table/sheet-editing/cell-editor.if.d.ts +110 -0
- package/lib/table/sheet-editing/editing-keymap.d.ts +17 -0
- package/lib/table/sheet-editing/editing-options.d.ts +34 -0
- package/lib/table/sheet-editing/editing-options.if.d.ts +49 -0
- package/lib/table/sheet-editing/editors/date-cell-editor.d.ts +23 -0
- package/lib/table/sheet-editing/editors/number-cell-editor.d.ts +18 -0
- package/lib/table/sheet-editing/editors/select-cell-editor.d.ts +36 -0
- package/lib/table/sheet-editing/editors/text-cell-editor.d.ts +35 -0
- package/lib/table/sheet-editing/formula-assist.d.ts +103 -0
- package/lib/table/sheet-editing/formula-text.d.ts +61 -0
- package/lib/table/sheet-editing/sheet-navigation.d.ts +26 -0
- package/lib/table/spreadsheet/area-model-sheet.d.ts +170 -0
- package/lib/table/spreadsheet/formula-bar.d.ts +53 -0
- package/lib/table/spreadsheet/spreadsheet-factory.d.ts +111 -0
- package/lib/table/spreadsheet/spreadsheet-options.if.d.ts +28 -0
- package/lib/table/spreadsheet/spreadsheet-preset.d.ts +37 -0
- package/lib/table/spreadsheet/structure-edit.d.ts +35 -0
- package/lib/table/table-api.d.ts +511 -2
- package/lib/table/table-scope.d.ts +294 -1
- package/lib/table/undo/cell-changes-undoable.d.ts +34 -0
- package/lib/table/undo/model-rows.d.ts +17 -0
- package/lib/table/undo/pending-changes-undoable.d.ts +35 -0
- package/lib/table/undo/undo-keymap.d.ts +17 -0
- package/lib/table/undo/undo-options.d.ts +26 -0
- package/lib/table/undo/undo-options.if.d.ts +30 -0
- package/lib/table/undo/undo-service.d.ts +103 -0
- package/lib/table/undo/undo-stack.d.ts +62 -0
- package/lib/table/undo/undoable.if.d.ts +36 -0
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A change of the sheet's structure that formulas must follow ({@link adjustFormula}): rows or columns inserted or
|
|
3
|
+
* deleted at `at` (0-based, `count` of them), or cells moved (cut + paste).
|
|
4
|
+
*
|
|
5
|
+
* @category Spreadsheet
|
|
6
|
+
* @since 1.1.99
|
|
7
|
+
*/
|
|
8
|
+
export type SheetStructureEditIf = {
|
|
9
|
+
kind: "insertRows" | "deleteRows" | "insertColumns" | "deleteColumns";
|
|
10
|
+
at: number;
|
|
11
|
+
count: number;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "moveCells";
|
|
14
|
+
from: {
|
|
15
|
+
r1: number;
|
|
16
|
+
c1: number;
|
|
17
|
+
r2: number;
|
|
18
|
+
c2: number;
|
|
19
|
+
};
|
|
20
|
+
to: readonly [number, number];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A formula copied by `dRow` rows and `dCol` columns (fill handle, copy and paste): relative references move, `$`
|
|
24
|
+
* parts stay; a reference that leaves the sheet becomes `#REF!`. Formula text without `=`.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} source - the formula (without `=`)
|
|
27
|
+
* @param {number} dRow - rows moved
|
|
28
|
+
* @param {number} dCol - columns moved
|
|
29
|
+
* @returns {string} the moved formula (canonical text)
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* shiftFormula("B2*C2+$F$1", 1, 0); // "B3*C3+$F$1"
|
|
33
|
+
* shiftFormula("A1", -1, 0); // "#REF!"
|
|
34
|
+
*
|
|
35
|
+
* @category Spreadsheet
|
|
36
|
+
* @since 1.1.99
|
|
37
|
+
*/
|
|
38
|
+
export declare function shiftFormula(source: string, dRow: number, dCol: number): string;
|
|
39
|
+
/**
|
|
40
|
+
* All references moved, also absolute ones – e.g. for an export whose cells start elsewhere (a header row above).
|
|
41
|
+
*
|
|
42
|
+
* @param {string} source - the formula (without `=`)
|
|
43
|
+
* @param {number} dRow - rows
|
|
44
|
+
* @param {number} dCol - columns
|
|
45
|
+
* @returns {string} the formula
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* offsetReferences("$F$1*B2", 1, 0); // "$F$2*B3"
|
|
49
|
+
*
|
|
50
|
+
* @category Spreadsheet
|
|
51
|
+
* @since 1.1.99
|
|
52
|
+
*/
|
|
53
|
+
export declare function offsetReferences(source: string, dRow: number, dCol: number): string;
|
|
54
|
+
/**
|
|
55
|
+
* A formula after rows or columns were inserted or deleted, or cells moved (Excel's rules): references behind the
|
|
56
|
+
* edit move, a range grows when rows are inserted inside it and shrinks when some of its rows are deleted; a deleted
|
|
57
|
+
* reference (or a fully deleted range) becomes `#REF!`, as does one pushed off the sheet (a range ending at the last
|
|
58
|
+
* row stays there). `moveCells`: references and ranges completely inside the moved cells follow them. Formula text
|
|
59
|
+
* without `=`; unparsable text and formulas without a changed reference are returned unchanged (same spelling).
|
|
60
|
+
*
|
|
61
|
+
* @param {string} source - the formula (without `=`)
|
|
62
|
+
* @param {SheetStructureEditIf} edit - the change
|
|
63
|
+
* @returns {string} the adjusted formula
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* adjustFormula("SUM(D2:D4)+B3", { kind: "deleteRows", at: 2, count: 1 }); // "SUM(D2:D3)+#REF!"
|
|
67
|
+
*
|
|
68
|
+
* @category Spreadsheet
|
|
69
|
+
* @since 1.1.99
|
|
70
|
+
*/
|
|
71
|
+
export declare function adjustFormula(source: string, edit: SheetStructureEditIf): string;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { TableModelIf } from '../data/tablemodel/table-model.if.js';
|
|
2
|
+
import { CellChangeIf } from '../batch-edit/cell-change.if.js';
|
|
3
|
+
import { SheetCellsIf } from './sheet-cells.if.js';
|
|
4
|
+
import { CellFormulaOptionsIf } from './cell-formula-options.if.js';
|
|
5
|
+
import { SheetEngine } from './sheet-engine.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A formula copied inside the table (copy and paste): the input and where it came from – pasted, its relative
|
|
9
|
+
* references move by the distance (Excel). `value` is pasted where formulas are not allowed.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export declare class CopiedFormula {
|
|
14
|
+
readonly input: string;
|
|
15
|
+
readonly row: number;
|
|
16
|
+
readonly col: number;
|
|
17
|
+
readonly value: unknown;
|
|
18
|
+
constructor(input: string, row: number, col: number, value: unknown);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The cell formulas of a table ({@link TableOptionsIf.cellFormulas}): connects the body model with a
|
|
22
|
+
* {@link SheetEngine}. Rows are the physical rows (`getAllRows()` / the array), columns the data columns (row number
|
|
23
|
+
* and checkbox columns don't count). The body asks it for the value of every text input (`SheetCellsIf`); the table
|
|
24
|
+
* reports every write (`cellsWritten`). A new rows array (`setRows`), another row count or other columns rebuild
|
|
25
|
+
* the engine.
|
|
26
|
+
*
|
|
27
|
+
* @category Internals
|
|
28
|
+
* @since 1.1.99
|
|
29
|
+
*/
|
|
30
|
+
export declare class TableSheet implements SheetCellsIf {
|
|
31
|
+
private readonly tableModel;
|
|
32
|
+
private readonly body;
|
|
33
|
+
readonly options: CellFormulaOptionsIf;
|
|
34
|
+
readonly engine: SheetEngine;
|
|
35
|
+
private dataColumns;
|
|
36
|
+
private engineColumns;
|
|
37
|
+
private properties;
|
|
38
|
+
private propertyColumns;
|
|
39
|
+
private formulaColumns;
|
|
40
|
+
/** Engine columns of calculated columns (`valueGetter`): their inputs change with every write of the row. */
|
|
41
|
+
private calculatedColumns;
|
|
42
|
+
private rowIndex;
|
|
43
|
+
private rowsRef?;
|
|
44
|
+
private rowsLength;
|
|
45
|
+
/** A spreadsheet body (sparse, positional columns) – otherwise objects or arrays. */
|
|
46
|
+
private readonly sheetBody?;
|
|
47
|
+
private columnDefsRef?;
|
|
48
|
+
private columnCount;
|
|
49
|
+
private syncing;
|
|
50
|
+
private constructor();
|
|
51
|
+
/**
|
|
52
|
+
* The cell formulas of a table model – `undefined` (with a warning) for a body that is not flat.
|
|
53
|
+
*
|
|
54
|
+
* @param {TableModelIf} tableModel - the model
|
|
55
|
+
* @param {CellFormulaOptionsIf} options - complete options
|
|
56
|
+
* @returns {TableSheet | undefined} the sheet, attached to the body
|
|
57
|
+
*/
|
|
58
|
+
static create(tableModel: TableModelIf, options: CellFormulaOptionsIf): TableSheet | undefined;
|
|
59
|
+
/** Detaches the sheet from the body (table destroyed). */
|
|
60
|
+
destroy(): void;
|
|
61
|
+
valueAt(row: unknown, columnIndex: number, input: string): unknown;
|
|
62
|
+
valueOfProperty(row: unknown, property: string, input: string): unknown;
|
|
63
|
+
isFormulaProperty(property: string): boolean;
|
|
64
|
+
isFormulaColumnIndex(columnIndex: number): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* True if a written value is a formula: text with `=` in a formula column (it skips `editInputPipe` and `validate`).
|
|
67
|
+
*
|
|
68
|
+
* @param {number} columnIndex - model column
|
|
69
|
+
* @param {unknown} value - the written value
|
|
70
|
+
* @returns {boolean} true for a formula
|
|
71
|
+
*/
|
|
72
|
+
isFormulaInput(columnIndex: number, value: unknown): value is string;
|
|
73
|
+
/**
|
|
74
|
+
* The message of a syntax error of a formula, `undefined` if it parses.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} input - the formula text (with `=`)
|
|
77
|
+
* @returns {string | undefined} the message
|
|
78
|
+
*/
|
|
79
|
+
syntaxError(input: string): string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Cells were written (their inputs changed): the engine compiles their formulas again and recalculates the
|
|
82
|
+
* dependent cells – before the table repaints.
|
|
83
|
+
*
|
|
84
|
+
* @param {CellChangeIf[]} changes - the written cells (row object or display index, model column)
|
|
85
|
+
*/
|
|
86
|
+
cellsWritten(changes: readonly CellChangeIf[]): void;
|
|
87
|
+
/**
|
|
88
|
+
* Recalculates everything (data changed outside the table) – {@link TableApi.recalculate}.
|
|
89
|
+
*/
|
|
90
|
+
recalculate(): void;
|
|
91
|
+
/**
|
|
92
|
+
* The value of a cell by physical row and engine column (the rows are checked first).
|
|
93
|
+
*
|
|
94
|
+
* @param {number} row - physical row
|
|
95
|
+
* @param {number} col - engine column
|
|
96
|
+
* @returns {unknown} the value
|
|
97
|
+
*/
|
|
98
|
+
cellValue(row: number, col: number): unknown;
|
|
99
|
+
/**
|
|
100
|
+
* Calculates a formula once against the sheet.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} source - the formula
|
|
103
|
+
* @returns {unknown} the result
|
|
104
|
+
*/
|
|
105
|
+
evaluate(source: string): unknown;
|
|
106
|
+
/**
|
|
107
|
+
* The input of a cell by physical row and engine column (also of a row a filter hides).
|
|
108
|
+
*
|
|
109
|
+
* @param {number} row - physical row
|
|
110
|
+
* @param {number} col - engine column
|
|
111
|
+
* @returns {unknown} the input
|
|
112
|
+
*/
|
|
113
|
+
inputAt(row: number, col: number): unknown;
|
|
114
|
+
/**
|
|
115
|
+
* Writes an input directly into the data (no events, no recalculation) – formulas adjusted after inserting or
|
|
116
|
+
* deleting rows. `row` is a physical row or the row itself (object or array).
|
|
117
|
+
*
|
|
118
|
+
* @param {number | object} row - physical row or row
|
|
119
|
+
* @param {number} col - engine column
|
|
120
|
+
* @param {unknown} value - the input
|
|
121
|
+
*/
|
|
122
|
+
writeInput(row: number | object, col: number, value: unknown): void;
|
|
123
|
+
/** @returns {unknown[] | undefined} the rows array of an object or array body (not of a sheet) */
|
|
124
|
+
rowsArray(): unknown[] | undefined;
|
|
125
|
+
/** @returns {number} the number of physical rows */
|
|
126
|
+
rowCount(): number;
|
|
127
|
+
/**
|
|
128
|
+
* The physical row of a display row (`undefined` if there is none).
|
|
129
|
+
*
|
|
130
|
+
* @param {number} displayRow - display index
|
|
131
|
+
* @returns {number | undefined} the row in `getAllRows()` / the array
|
|
132
|
+
*/
|
|
133
|
+
physicalRow(displayRow: number): number | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* The display row of a physical row, `-1` if a filter hides it.
|
|
136
|
+
*
|
|
137
|
+
* @param {number} physicalRow - the row in `getAllRows()` / the array
|
|
138
|
+
* @returns {number} the display index
|
|
139
|
+
*/
|
|
140
|
+
displayRow(physicalRow: number): number;
|
|
141
|
+
/** @returns {number | undefined} the engine column (A = 0) of a model column */
|
|
142
|
+
engineColumn(columnIndex: number): number | undefined;
|
|
143
|
+
/** @returns {number} the model column of an engine column, `-1` if there is none */
|
|
144
|
+
modelColumn(engineColumn: number): number;
|
|
145
|
+
/**
|
|
146
|
+
* The address of a cell (`"B3"`), `undefined` for a row number or checkbox column.
|
|
147
|
+
*
|
|
148
|
+
* @param {number} displayRow - display index
|
|
149
|
+
* @param {number} columnIndex - model column
|
|
150
|
+
* @returns {string | undefined} the address
|
|
151
|
+
*/
|
|
152
|
+
address(displayRow: number, columnIndex: number): string | undefined;
|
|
153
|
+
/**
|
|
154
|
+
* The cell of an address: display row (`-1` if a filter hides it) and model column; `undefined` if invalid.
|
|
155
|
+
*
|
|
156
|
+
* @param {string} address - `"B3"`, `"$B$3"`
|
|
157
|
+
* @returns {[number, number] | undefined} display row and model column
|
|
158
|
+
*/
|
|
159
|
+
cellOfAddress(address: string): [number, number] | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* A formula moved from one cell to another (fill handle, paste): relative references move by the physical distance.
|
|
162
|
+
*
|
|
163
|
+
* @param {string} input - the formula (with `=`)
|
|
164
|
+
* @param {number} fromRow - physical row of the source
|
|
165
|
+
* @param {number} fromCol - engine column of the source
|
|
166
|
+
* @param {number} toDisplayRow - display row of the target
|
|
167
|
+
* @param {number} toColumnIndex - model column of the target
|
|
168
|
+
* @returns {string | undefined} the moved formula, `undefined` if the target holds no formulas
|
|
169
|
+
*/
|
|
170
|
+
moveFormula(input: string, fromRow: number, fromCol: number, toDisplayRow: number, toColumnIndex: number): string | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* The copy of a cell inside the table: a {@link CopiedFormula} for a formula cell, otherwise `value`.
|
|
173
|
+
*
|
|
174
|
+
* @param {number} displayRow - display index
|
|
175
|
+
* @param {number} columnIndex - model column
|
|
176
|
+
* @param {unknown} input - the cell's input
|
|
177
|
+
* @param {unknown} value - the cell's value
|
|
178
|
+
* @returns {unknown} the copy
|
|
179
|
+
*/
|
|
180
|
+
copyOf(displayRow: number, columnIndex: number, input: unknown, value: unknown): unknown;
|
|
181
|
+
/**
|
|
182
|
+
* The cells and ranges a formula reads, as addresses (`["B2", "C2", "D2:D4", "A:A"]`).
|
|
183
|
+
*
|
|
184
|
+
* @param {number} displayRow - display index
|
|
185
|
+
* @param {number} columnIndex - model column
|
|
186
|
+
* @returns {string[]} the addresses (empty for a value cell)
|
|
187
|
+
*/
|
|
188
|
+
precedents(displayRow: number, columnIndex: number): string[];
|
|
189
|
+
/**
|
|
190
|
+
* The formula cells that read a cell directly (display row, model column; hidden rows left out).
|
|
191
|
+
*
|
|
192
|
+
* @param {number} displayRow - display index
|
|
193
|
+
* @param {number} columnIndex - model column
|
|
194
|
+
* @returns {Array<[number, number]>} the dependents
|
|
195
|
+
*/
|
|
196
|
+
dependents(displayRow: number, columnIndex: number): Array<[number, number]>;
|
|
197
|
+
/**
|
|
198
|
+
* False for arrays (moving a column moves the data of every row – the references would point elsewhere); object
|
|
199
|
+
* rows: the column letter belongs to the property and moves with it.
|
|
200
|
+
*
|
|
201
|
+
* @returns {boolean} true if columns may be dragged
|
|
202
|
+
*/
|
|
203
|
+
allowsColumnDrag(): boolean;
|
|
204
|
+
/** The engine column of a model column: arrays by position, objects by the property (dragged columns keep it). */
|
|
205
|
+
private columnOf;
|
|
206
|
+
private valueOf;
|
|
207
|
+
private physicalOfRow;
|
|
208
|
+
private rowCountOf;
|
|
209
|
+
private rows;
|
|
210
|
+
private readInput;
|
|
211
|
+
/** Rebuilds rows, columns and the engine if the rows array, its length or the columns changed. */
|
|
212
|
+
private sync;
|
|
213
|
+
private buildColumns;
|
|
214
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { TableScope } from '../table-scope.js';
|
|
2
|
+
import { EditingOptionsIf } from './editing-options.if.js';
|
|
3
|
+
import { CellEditMode, EditMove } from './cell-editor.if.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Excel-style editing ({@link TableOptionsIf.editing}): **one** editor element above the edited cell (not inside
|
|
7
|
+
* it – the cells are rebuilt on every render pass, the editor survives scrolling and repaints), typing to edit,
|
|
8
|
+
* Enter/Tab/arrow keys commit and move, Escape cancels, a click elsewhere commits. Created by {@link TableScope}
|
|
9
|
+
* only with the option (`tableScope.cellEditorService`).
|
|
10
|
+
*
|
|
11
|
+
* @category Internals
|
|
12
|
+
* @since 1.1.99
|
|
13
|
+
*/
|
|
14
|
+
export declare class CellEditorService {
|
|
15
|
+
private readonly tableScope;
|
|
16
|
+
readonly options: EditingOptionsIf;
|
|
17
|
+
private container?;
|
|
18
|
+
private editor?;
|
|
19
|
+
private session?;
|
|
20
|
+
/** Formula input of a formula column (pointing, colors, suggestions – since 1.1.99, `cellFormulas`). */
|
|
21
|
+
private assist?;
|
|
22
|
+
/** The column the last Tab sequence started in (Enter goes back to it, like Excel). */
|
|
23
|
+
private tabStartColumn;
|
|
24
|
+
private readonly editorId;
|
|
25
|
+
/** An invalid value refused a click: its mousedown/click/dblclick must not move the focus either. */
|
|
26
|
+
private blockClick;
|
|
27
|
+
constructor(tableScope: TableScope, options: EditingOptionsIf);
|
|
28
|
+
/** True while the editor is open. */
|
|
29
|
+
isOpen(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The edited cell.
|
|
32
|
+
*
|
|
33
|
+
* @returns {[number, number] | undefined} display row and model column, `undefined` without editor
|
|
34
|
+
*/
|
|
35
|
+
getCell(): [number, number] | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* The id of the editor element (and of the formula popups) if `(rowIndex, columnIndex)` is the edited cell – the cell gets `aria-owns` with it
|
|
38
|
+
* (screen readers find the editor in the cell, not as a stray child of the grid).
|
|
39
|
+
*
|
|
40
|
+
* @param {number} rowIndex - display row index
|
|
41
|
+
* @param {number} columnIndex - model column index
|
|
42
|
+
* @returns {string | undefined} the id
|
|
43
|
+
*/
|
|
44
|
+
getOwnedEditorId(rowIndex: number, columnIndex: number): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* True if this service edits the column (otherwise the column's own `getEditRenderer` – or an own
|
|
47
|
+
* `tableOptions.getEditRenderer` of the app – edits inside the cell, as before 1.1.99).
|
|
48
|
+
*
|
|
49
|
+
* @param {number} columnIndex - model column index
|
|
50
|
+
* @returns {boolean} true for the editor above the cell
|
|
51
|
+
*/
|
|
52
|
+
handlesColumn(columnIndex: number): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Opens the editor on a body cell.
|
|
55
|
+
*
|
|
56
|
+
* @param {number} rowIndex - display row index
|
|
57
|
+
* @param {number} columnIndex - model column index
|
|
58
|
+
* @param {{ mode?: CellEditMode, typedText?: string, textSelection?: "all" | "end" }} [opts] - "enter" with the typed
|
|
59
|
+
* character, or "edit" (F2: caret at the end)
|
|
60
|
+
* @returns {boolean} true if the editor is open
|
|
61
|
+
*/
|
|
62
|
+
start(rowIndex: number, columnIndex: number, opts?: {
|
|
63
|
+
mode?: CellEditMode;
|
|
64
|
+
typedText?: string;
|
|
65
|
+
textSelection?: "all" | "end";
|
|
66
|
+
imeStart?: boolean;
|
|
67
|
+
}): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Writes the editor's value (through `editInputPipe` and `validate`; batch edit: marks it) and moves on.
|
|
70
|
+
* An invalid value keeps the editor open (`aria-invalid`, the message is announced and the `title`).
|
|
71
|
+
*
|
|
72
|
+
* @param {EditMove} [move="none"] - where the active cell goes afterwards
|
|
73
|
+
* @param {{ fillSelection?: boolean, deferRepaint?: boolean }} [opts] - Ctrl/⌘+Enter: into all selected cells;
|
|
74
|
+
* a mouse click: repaint after the click (a repaint between mousedown and click loses the click)
|
|
75
|
+
* @returns {boolean} true if the editor closed
|
|
76
|
+
*/
|
|
77
|
+
commit(move?: EditMove, opts?: {
|
|
78
|
+
fillSelection?: boolean;
|
|
79
|
+
deferRepaint?: boolean;
|
|
80
|
+
tab?: boolean;
|
|
81
|
+
}): boolean;
|
|
82
|
+
/** Closes the editor without writing (Escape). */
|
|
83
|
+
cancel(): void;
|
|
84
|
+
/** Places the editor over its cell (called after every render pass) – also when the cell scrolled out of view. */
|
|
85
|
+
update(): void;
|
|
86
|
+
/** Removes the editor (table destroyed). */
|
|
87
|
+
destroy(): void;
|
|
88
|
+
private ensureContainer;
|
|
89
|
+
private createEditor;
|
|
90
|
+
/** The row moved (sorting, filter, inserted rows): the editor follows it; `false` if it is gone. */
|
|
91
|
+
private followRow;
|
|
92
|
+
/** The columns moved or changed (reordering, grouping, `setColumns`): the editor follows its column definition. */
|
|
93
|
+
private followColumn;
|
|
94
|
+
private close;
|
|
95
|
+
private fire;
|
|
96
|
+
private moveAfterCommit;
|
|
97
|
+
private onPointerDown;
|
|
98
|
+
private onBlockedMouse;
|
|
99
|
+
private onFocusOut;
|
|
100
|
+
private onKeyDown;
|
|
101
|
+
private isMac;
|
|
102
|
+
/** A key on the focused table (no editor open): printable keys open the editor ("enter" mode). */
|
|
103
|
+
private onTypeToEdit;
|
|
104
|
+
private onEditorKeyDown;
|
|
105
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ColumnDefIf } from '../data/tablemodel/column/column-def.if.js';
|
|
2
|
+
import { DomServiceIf } from '../service/dom-service.if.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* How the cell editor was opened: `"enter"` by typing (arrow keys commit and move, like Excel's "Enter" mode) or
|
|
6
|
+
* `"edit"` by F2, Enter or a double click (arrow keys move the caret). F2 switches between the two.
|
|
7
|
+
*
|
|
8
|
+
* @category Spreadsheet
|
|
9
|
+
* @since 1.1.99
|
|
10
|
+
*/
|
|
11
|
+
export type CellEditMode = "enter" | "edit";
|
|
12
|
+
/**
|
|
13
|
+
* Where the focus goes after the editor committed: one cell down, up, right, left – or nowhere.
|
|
14
|
+
*
|
|
15
|
+
* @category Spreadsheet
|
|
16
|
+
* @since 1.1.99
|
|
17
|
+
*/
|
|
18
|
+
export type EditMove = "down" | "up" | "right" | "left" | "none";
|
|
19
|
+
/**
|
|
20
|
+
* What a {@link CellEditorIf} gets when it opens (Excel-style editing, {@link TableOptionsIf.editing}).
|
|
21
|
+
*
|
|
22
|
+
* @category Spreadsheet
|
|
23
|
+
* @since 1.1.99
|
|
24
|
+
*/
|
|
25
|
+
export interface CellEditorContextIf {
|
|
26
|
+
/** Display row index of the edited body cell. */
|
|
27
|
+
readonly rowIndex: number;
|
|
28
|
+
/** Model column index. */
|
|
29
|
+
readonly columnIndex: number;
|
|
30
|
+
/** The row object (the data of a tree row), `undefined` for models without objects. */
|
|
31
|
+
readonly row: unknown;
|
|
32
|
+
/** The column definition, if the model has one. */
|
|
33
|
+
readonly columnDef?: ColumnDefIf;
|
|
34
|
+
/** The current value of the cell (a pending value in a batch edit). */
|
|
35
|
+
readonly value: unknown;
|
|
36
|
+
/** The value as editor text, e.g. `"42"` – the editor starts with it unless {@link typedText} is set. */
|
|
37
|
+
readonly input: string;
|
|
38
|
+
/** The character typed to open the editor ("enter" mode); it replaces the content. */
|
|
39
|
+
readonly typedText?: string;
|
|
40
|
+
/** "enter" (typed) or "edit" (F2, Enter, double click). */
|
|
41
|
+
readonly mode: CellEditMode;
|
|
42
|
+
/** "all": select the text, "end": caret at the end (F2 is always "end"). */
|
|
43
|
+
readonly textSelection: "all" | "end";
|
|
44
|
+
/** Writing direction of the table. */
|
|
45
|
+
readonly direction: "ltr" | "rtl";
|
|
46
|
+
/** Accessible name of the editor (the column label). */
|
|
47
|
+
readonly ariaLabel: string;
|
|
48
|
+
/** DOM access of the table. */
|
|
49
|
+
readonly domService: DomServiceIf;
|
|
50
|
+
/** The editor is done (e.g. a value was chosen in a list): commit and move. */
|
|
51
|
+
commit(move?: EditMove): void;
|
|
52
|
+
/** Close without writing. */
|
|
53
|
+
cancel(): void;
|
|
54
|
+
/** The text changed (the table reports it as `GeEditEvent` of the type `"input"`). */
|
|
55
|
+
inputChanged(): void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A cell editor of Excel-style editing: lives in one element above the cell (it survives scrolling) until it is
|
|
59
|
+
* committed or cancelled. Built-in: {@link TextCellEditor}, {@link NumberCellEditor}, {@link SelectCellEditor},
|
|
60
|
+
* {@link DateCellEditor}. The table handles Enter, Tab, Escape and the arrow keys; an editor that needs a key
|
|
61
|
+
* itself (a list, a date field) says so in {@link wantsKey}.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* class UpperCaseEditor extends TextCellEditor {
|
|
65
|
+
* override getValue(): unknown {
|
|
66
|
+
* return String(super.getValue()).toUpperCase();
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
* ColumnDef.create({ property: "code", editable: TrueFn, editor: ctx => new UpperCaseEditor() });
|
|
70
|
+
*
|
|
71
|
+
* @category Spreadsheet
|
|
72
|
+
* @since 1.1.99
|
|
73
|
+
*/
|
|
74
|
+
export interface CellEditorIf {
|
|
75
|
+
/** Builds the editor into `container` (the table positions the container over the cell). */
|
|
76
|
+
open(container: HTMLDivElement, ctx: CellEditorContextIf): void;
|
|
77
|
+
/** The value to write (it runs through `editInputPipe` and `validate` of the column). */
|
|
78
|
+
getValue(): unknown;
|
|
79
|
+
/** Gives the input element the keyboard focus. */
|
|
80
|
+
focus(): void;
|
|
81
|
+
/** Removes listeners and elements. */
|
|
82
|
+
close(): void;
|
|
83
|
+
/** The element that has the focus (the table names it and lets the active cell own it for screen readers). */
|
|
84
|
+
getFocusElement(): HTMLElement | undefined;
|
|
85
|
+
/** F2 switched the mode. */
|
|
86
|
+
setMode?(mode: CellEditMode): void;
|
|
87
|
+
/** `true` while an IME composition is running – the table ignores Enter, Tab and arrows then. */
|
|
88
|
+
isComposing?(): boolean;
|
|
89
|
+
/** `true` if the editor needs this key itself (e.g. ↑/↓ in a list) – the table does not commit then. */
|
|
90
|
+
wantsKey?(evt: KeyboardEvent, mode: CellEditMode): boolean;
|
|
91
|
+
/** The text of the editor, e.g. `"=B2*C2"` (formula input, later stages). */
|
|
92
|
+
getText?(): string;
|
|
93
|
+
/** Replaces the text and puts the caret at the end. */
|
|
94
|
+
setText?(text: string): void;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Creates the editor of a column for one edit (see {@link ColumnDefIf.editor}).
|
|
98
|
+
*
|
|
99
|
+
* @category Spreadsheet
|
|
100
|
+
* @since 1.1.99
|
|
101
|
+
*/
|
|
102
|
+
export type CellEditorFactory = (ctx: CellEditorContextIf) => CellEditorIf;
|
|
103
|
+
/**
|
|
104
|
+
* The editor of a column in Excel-style editing: a factory or the name of a built-in editor. Without it the
|
|
105
|
+
* table chooses by the value: numbers → `"number"`, dates → `"date"`, otherwise `"text"`.
|
|
106
|
+
*
|
|
107
|
+
* @category Spreadsheet
|
|
108
|
+
* @since 1.1.99
|
|
109
|
+
*/
|
|
110
|
+
export type ColumnEditorOption = CellEditorFactory | "text" | "number" | "date";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ShortcutActionIdMapping } from '../action/shortcut-actionid-mapping.type.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The keys of Excel-style editing ({@link TableOptionsIf.editing}) – a layer over the system mapping that the
|
|
5
|
+
* table only uses with the option; `tableOptions.shortcutActionIdMapping` still overrides it. Typing, F2, Enter,
|
|
6
|
+
* Escape and Ctrl/⌘+Enter are handled by the editor itself.
|
|
7
|
+
*
|
|
8
|
+
* @param {boolean} mac - macOS keys (⌘ instead of Ctrl for the data edge – ⌃+arrows belong to macOS Spaces)
|
|
9
|
+
* @returns {ShortcutActionIdMapping} the layer
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* editingShortcutLayer(false)["ctrl+down"]; // "NAVIGATE_DATA_EDGE_DOWN"
|
|
13
|
+
*
|
|
14
|
+
* @category Spreadsheet
|
|
15
|
+
* @since 1.1.99
|
|
16
|
+
*/
|
|
17
|
+
export declare function editingShortcutLayer(mac: boolean): ShortcutActionIdMapping;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EditingOptionsIf } from './editing-options.if.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The defaults of {@link EditingOptionsIf} (Excel-style editing, {@link TableOptionsIf.editing}).
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const options = EditingOptions.create(true);
|
|
8
|
+
* options?.enterKey; // "edit"
|
|
9
|
+
*
|
|
10
|
+
* @category Spreadsheet
|
|
11
|
+
* @since 1.1.99
|
|
12
|
+
*/
|
|
13
|
+
export declare class EditingOptions implements EditingOptionsIf {
|
|
14
|
+
startOnType: boolean;
|
|
15
|
+
enterKey: "edit" | "moveDown";
|
|
16
|
+
enterMoves: "down" | "right" | "none";
|
|
17
|
+
tabMoves: boolean;
|
|
18
|
+
arrowKeysCommit: boolean;
|
|
19
|
+
textSelection: "all" | "end";
|
|
20
|
+
clearKeys: boolean;
|
|
21
|
+
ctrlEnterFillsSelection: boolean;
|
|
22
|
+
collapseSelectionOnNavigate: boolean;
|
|
23
|
+
emptyValue: unknown;
|
|
24
|
+
defaultEditable: boolean;
|
|
25
|
+
maxClearCells: number;
|
|
26
|
+
/**
|
|
27
|
+
* The options of {@link TableOptionsIf.editing}: `undefined`/`false` = off, `true` = the defaults, an object = the
|
|
28
|
+
* defaults overridden by its values (`undefined` keeps the default).
|
|
29
|
+
*
|
|
30
|
+
* @param {boolean | Partial<EditingOptionsIf>} [option] - `tableOptions.editing`
|
|
31
|
+
* @returns {EditingOptionsIf | undefined} complete options, `undefined` if Excel-style editing is off
|
|
32
|
+
*/
|
|
33
|
+
static create(option?: boolean | Partial<EditingOptionsIf>): EditingOptionsIf | undefined;
|
|
34
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel-style editing ({@link TableOptionsIf.editing}): what typing, Enter, Tab, the arrow keys and Delete do.
|
|
3
|
+
* `editing: true` uses the defaults of {@link EditingOptions}; an object overrides single values.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const tableOptions: TableOptionsIf = {
|
|
7
|
+
* ...new TableOptions(),
|
|
8
|
+
* getSelectionModel: () => selectionModel, // new SelectionModel("range", "multi")
|
|
9
|
+
* editing: { enterKey: "moveDown", textSelection: "end" }, // Enter moves down like Excel
|
|
10
|
+
* };
|
|
11
|
+
*
|
|
12
|
+
* @category Spreadsheet
|
|
13
|
+
* @since 1.1.99
|
|
14
|
+
*/
|
|
15
|
+
export interface EditingOptionsIf {
|
|
16
|
+
/** A printable key on a focused editable cell opens the editor with that character ("enter" mode). Default `true`. */
|
|
17
|
+
startOnType: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Enter on a cell without editor: `"edit"` opens the editor (Google Sheets, default), `"moveDown"` moves down
|
|
20
|
+
* (Excel). Checkbox, tree, group and detail cells keep their own Enter action.
|
|
21
|
+
*/
|
|
22
|
+
enterKey: "edit" | "moveDown";
|
|
23
|
+
/** Where Enter in the editor goes after committing (Shift+Enter: the opposite). Default `"down"`. */
|
|
24
|
+
enterMoves: "down" | "right" | "none";
|
|
25
|
+
/**
|
|
26
|
+
* Tab/Shift+Tab commit and move to the next/previous shown column. In the last (first) column Tab is not used:
|
|
27
|
+
* the browser focus leaves the table (no keyboard trap). Default `true`.
|
|
28
|
+
*/
|
|
29
|
+
tabMoves: boolean;
|
|
30
|
+
/** In "enter" mode (opened by typing) the arrow keys commit and move; in "edit" mode they move the caret. Default `true`. */
|
|
31
|
+
arrowKeysCommit: boolean;
|
|
32
|
+
/** Enter and double click select the text of the editor (`"all"`, default) or put the caret at the end; F2 always at the end. */
|
|
33
|
+
textSelection: "all" | "end";
|
|
34
|
+
/** Delete clears the selected cells, Backspace clears one cell and opens the editor. Default `true`. */
|
|
35
|
+
clearKeys: boolean;
|
|
36
|
+
/** Ctrl/⌘+Enter in the editor writes the input into all selected cells. Default `true`. */
|
|
37
|
+
ctrlEnterFillsSelection: boolean;
|
|
38
|
+
/** Arrow keys, Tab, Enter and clicks select the active cell (Excel); Shift+arrows extend from it. Default `true`. */
|
|
39
|
+
collapseSelectionOnNavigate: boolean;
|
|
40
|
+
/** The value of a cleared cell (a column can have its own: {@link ColumnDefIf.emptyValue}). Default `""`. */
|
|
41
|
+
emptyValue: unknown;
|
|
42
|
+
/**
|
|
43
|
+
* `true`: columns without an own `editable` are editable (row numbers, checkbox and group columns, calculated
|
|
44
|
+
* columns without `valueSetter` stay read only). Default `false`.
|
|
45
|
+
*/
|
|
46
|
+
defaultEditable: boolean;
|
|
47
|
+
/** At most this many cells are cleared at once (Delete). Default 1 000 000. */
|
|
48
|
+
maxClearCells: number;
|
|
49
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CellEditMode, CellEditorContextIf } from '../cell-editor.if.js';
|
|
2
|
+
import { TextCellEditor } from './text-cell-editor.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Editor for dates: `input type="date"`. A `Date` value comes back as `Date` (its time of day stays), an ISO text
|
|
6
|
+
* (`"2026-10-16"`, also with a time part) as ISO text; an empty field as `""`. The arrow keys belong to the date
|
|
7
|
+
* field.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ColumnDef.create({ property: "due", editable: TrueFn, editor: "date" });
|
|
11
|
+
*
|
|
12
|
+
* @category Spreadsheet
|
|
13
|
+
* @since 1.1.99
|
|
14
|
+
*/
|
|
15
|
+
export declare class DateCellEditor extends TextCellEditor {
|
|
16
|
+
private original;
|
|
17
|
+
private originalText;
|
|
18
|
+
protected inputType(): string;
|
|
19
|
+
protected toText(ctx: CellEditorContextIf): string;
|
|
20
|
+
open(container: HTMLDivElement, ctx: CellEditorContextIf): void;
|
|
21
|
+
getValue(): unknown;
|
|
22
|
+
wantsKey(evt: KeyboardEvent, _mode: CellEditMode): boolean;
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CellEditorContextIf } from '../cell-editor.if.js';
|
|
2
|
+
import { TextCellEditor } from './text-cell-editor.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Editor for numbers: a text field with the numeric keyboard on touch devices (`inputmode="decimal"`), aligned to
|
|
6
|
+
* the end. Without an `editInputPipe` of the column a typed number is written as number (`"42"` → `42`), other text
|
|
7
|
+
* stays text.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ColumnDef.create({ property: "price", editable: TrueFn, editor: "number" });
|
|
11
|
+
*
|
|
12
|
+
* @category Spreadsheet
|
|
13
|
+
* @since 1.1.99
|
|
14
|
+
*/
|
|
15
|
+
export declare class NumberCellEditor extends TextCellEditor {
|
|
16
|
+
protected decorate(input: HTMLInputElement, ctx: CellEditorContextIf): void;
|
|
17
|
+
getValue(): unknown;
|
|
18
|
+
}
|