@guiexpert/table 1.1.93 → 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.
- package/README.md +25 -0
- package/css/main.css +334 -0
- package/css/table-calc.css +7 -0
- package/css/table-classes.css +34 -0
- package/css/table-color-vars.css +78 -0
- package/css/table-fill-batch.css +58 -0
- package/css/table-pivot.css +42 -0
- package/css/table-row-drag.css +81 -0
- package/css/table-row-group.css +25 -0
- package/css/table-tree.css +9 -0
- package/index.cjs +57 -47
- package/index.d.ts +67 -0
- package/index.js +11290 -4985
- package/lib/table/action/action-id.type.d.ts +1 -1
- package/lib/table/aggregation/aggregate-internals.d.ts +30 -0
- package/lib/table/aggregation/aggregate-spec.if.d.ts +51 -0
- package/lib/table/aggregation/aggregate.d.ts +58 -0
- package/lib/table/aggregation/aggregator-name.type.d.ts +39 -0
- package/lib/table/aggregation/aggregator.if.d.ts +51 -0
- package/lib/table/aggregation/aggregators.d.ts +37 -0
- package/lib/table/aggregation/create-value-getter.d.ts +18 -0
- package/lib/table/aggregation/selection-aggregates.if.d.ts +35 -0
- package/lib/table/aggregation/value-accessor.type.d.ts +13 -0
- package/lib/table/aria/aria-texts.d.ts +11 -0
- package/lib/table/aria/aria-texts.if.d.ts +87 -0
- package/lib/table/batch-edit/batch-edit-options.d.ts +21 -0
- package/lib/table/batch-edit/batch-edit-options.if.d.ts +20 -0
- package/lib/table/batch-edit/batch-edit-service.d.ts +104 -0
- package/lib/table/batch-edit/cell-change.if.d.ts +39 -0
- package/lib/table/batch-edit/cell-value-change.if.d.ts +18 -0
- package/lib/table/batch-edit/pending-cell-changes.d.ts +104 -0
- package/lib/table/calc/column-values.d.ts +55 -0
- package/lib/table/calc/show-values-as-internals.d.ts +4 -0
- package/lib/table/calc/show-values-as.d.ts +87 -0
- package/lib/table/calc/show-values-as.type.d.ts +55 -0
- package/lib/table/calc/value-getter-context.if.d.ts +35 -0
- package/lib/table/calc/value-getter.type.d.ts +36 -0
- package/lib/table/data/common/event/ge-batch-edit-event.d.ts +46 -0
- package/lib/table/data/common/event/ge-model-change-event.d.ts +27 -1
- package/lib/table/data/common/event/ge-row-drag-event.d.ts +89 -0
- package/lib/table/data/common/row-number-column-def.d.ts +107 -0
- package/lib/table/data/common/row-number-columns.d.ts +17 -0
- package/lib/table/data/common/row-number-options.d.ts +19 -0
- package/lib/table/data/common/row-number-options.if.d.ts +44 -0
- package/lib/table/data/options/table-options.d.ts +6 -0
- package/lib/table/data/options/table-options.if.d.ts +44 -0
- package/lib/table/data/tablemodel/areamodel/abstract-area-model.d.ts +66 -0
- package/lib/table/data/tablemodel/areamodel/aggregate-footer-options.if.d.ts +73 -0
- package/lib/table/data/tablemodel/areamodel/area-model-aggregate-footer.d.ts +150 -0
- package/lib/table/data/tablemodel/areamodel/area-model-array-of-arrays.d.ts +24 -0
- package/lib/table/data/tablemodel/areamodel/area-model-cell-groups.d.ts +18 -1
- package/lib/table/data/tablemodel/areamodel/area-model-object-array.d.ts +70 -0
- package/lib/table/data/tablemodel/areamodel/area-model-pivot-footer.d.ts +47 -0
- package/lib/table/data/tablemodel/areamodel/area-model-pivot.d.ts +281 -0
- package/lib/table/data/tablemodel/areamodel/area-model-row-groups.d.ts +336 -0
- package/lib/table/data/tablemodel/areamodel/area-model-tree.d.ts +97 -0
- package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +94 -0
- package/lib/table/data/tablemodel/areamodel/derived-values-change.if.d.ts +30 -0
- package/lib/table/data/tablemodel/column/column-def.d.ts +31 -1
- package/lib/table/data/tablemodel/column/column-def.if.d.ts +86 -0
- package/lib/table/event-adapter.d.ts +7 -0
- package/lib/table/event-listener.if.d.ts +32 -0
- package/lib/table/factory/pivot-factory.d.ts +63 -0
- package/lib/table/factory/pivot-table-model-para.if.d.ts +44 -0
- package/lib/table/factory/row-group-factory.d.ts +70 -0
- package/lib/table/factory/row-group-table-model-para.if.d.ts +66 -0
- package/lib/table/factory/table-factory.d.ts +56 -1
- package/lib/table/fill/compute-fill-changes.d.ts +67 -0
- package/lib/table/fill/fill-direction.type.d.ts +7 -0
- package/lib/table/fill/fill-handle-options.d.ts +29 -0
- package/lib/table/fill/fill-handle-options.if.d.ts +35 -0
- package/lib/table/fill/fill-handle-service.d.ts +55 -0
- package/lib/table/fill/fill-series.d.ts +60 -0
- package/lib/table/fill/fill-value-context.if.d.ts +36 -0
- package/lib/table/formula/compile-formula.d.ts +86 -0
- package/lib/table/formula/evaluator.d.ts +19 -0
- package/lib/table/formula/formula-ast.if.d.ts +42 -0
- package/lib/table/formula/formula-error.d.ts +59 -0
- package/lib/table/formula/formula-options.if.d.ts +41 -0
- package/lib/table/formula/formula-values.d.ts +13 -0
- package/lib/table/formula/functions.d.ts +18 -0
- package/lib/table/formula/parser.d.ts +10 -0
- package/lib/table/formula/tokenizer.d.ts +22 -0
- package/lib/table/instanceof-workaround.d.ts +143 -6
- package/lib/table/pivot/area-model-pivot-header.d.ts +9 -0
- package/lib/table/pivot/pivot-column-def.d.ts +28 -0
- package/lib/table/pivot/pivot-column-info.if.d.ts +25 -0
- package/lib/table/pivot/pivot-config.if.d.ts +58 -0
- package/lib/table/pivot/pivot-internals.d.ts +13 -0
- package/lib/table/pivot/pivot-layout.d.ts +40 -0
- package/lib/table/pivot/pivot-result.d.ts +157 -0
- package/lib/table/pivot/pivot-table-model.d.ts +86 -0
- package/lib/table/pivot/pivot-value.type.d.ts +80 -0
- package/lib/table/render-scope.d.ts +142 -4
- package/lib/table/renderer/aggregate-cell-renderer.d.ts +27 -0
- package/lib/table/renderer/edit/input-cell-renderer.d.ts +1 -1
- package/lib/table/renderer/edit/select-cell-renderer.d.ts +1 -1
- package/lib/table/renderer/row-number-cell-renderer.d.ts +27 -0
- package/lib/table/row-drag/move-rows.d.ts +157 -0
- package/lib/table/row-drag/row-drag-options.d.ts +28 -0
- package/lib/table/row-drag/row-drag-options.if.d.ts +36 -0
- package/lib/table/row-drag/row-drag-service.d.ts +130 -0
- package/lib/table/row-drag/row-drop-target.if.d.ts +29 -0
- package/lib/table/rowgroup/group-rows-internals.d.ts +14 -0
- package/lib/table/rowgroup/group-rows-options.if.d.ts +13 -0
- package/lib/table/rowgroup/group-rows.d.ts +48 -0
- package/lib/table/rowgroup/row-group-column-def.d.ts +26 -0
- package/lib/table/rowgroup/row-group-column-options.if.d.ts +27 -0
- package/lib/table/rowgroup/row-group-detail-row.d.ts +8 -0
- package/lib/table/rowgroup/row-group-field.type.d.ts +56 -0
- package/lib/table/rowgroup/row-group-internals.d.ts +31 -0
- package/lib/table/rowgroup/row-group-layout.d.ts +13 -0
- package/lib/table/rowgroup/row-group-model-options.if.d.ts +39 -0
- package/lib/table/rowgroup/row-group.d.ts +51 -0
- package/lib/table/rowgroup/row-group.if.d.ts +48 -0
- package/lib/table/selection/selection-aggregator.d.ts +37 -0
- package/lib/table/selection/selection-service.d.ts +7 -0
- package/lib/table/service/convenience-dom.service.d.ts +5 -0
- package/lib/table/service/excel-service.d.ts +6 -0
- package/lib/table/service/excel-service.if.d.ts +35 -0
- package/lib/table/table-api.d.ts +389 -3
- package/lib/table/table-scope.d.ts +140 -0
- package/package.json +3 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ColumnDefIf } from '../data/tablemodel/column/column-def.if.js';
|
|
2
|
+
import { TableOptionsIf } from '../data/options/table-options.if.js';
|
|
3
|
+
import { DefaultRowHeightsIf } from '../data/options/default-row-heights.if.js';
|
|
4
|
+
import { GetT } from '../data/common/get-t.js';
|
|
5
|
+
import { SelectionModelIf } from '../selection/selection-model.if.js';
|
|
6
|
+
import { RowNumberOptionsIf } from '../data/common/row-number-options.if.js';
|
|
7
|
+
import { AggregateSpecMap } from '../aggregation/aggregate-spec.if.js';
|
|
8
|
+
import { AggregateFooterConfig } from '../data/tablemodel/areamodel/aggregate-footer-options.if.js';
|
|
9
|
+
import { RowGroupField } from '../rowgroup/row-group-field.type.js';
|
|
10
|
+
import { RowGroupColumnOptionsIf } from '../rowgroup/row-group-column-options.if.js';
|
|
11
|
+
import { RowGroupExpanded } from '../rowgroup/row-group-model-options.if.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Parameters of {@link RowGroupFactory.createTableModel}.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const para: RowGroupTableModelParaIf<Sale> = {
|
|
18
|
+
* rows: sales,
|
|
19
|
+
* columnDefs,
|
|
20
|
+
* groupBy: ["region", "produkt"],
|
|
21
|
+
* aggregations: { umsatz: "sum" },
|
|
22
|
+
* expanded: 1 // regions open, products closed
|
|
23
|
+
* };
|
|
24
|
+
* const tableModel = RowGroupFactory.createTableModel(para);
|
|
25
|
+
*
|
|
26
|
+
* @typeParam T - the row type
|
|
27
|
+
* @since 1.1.94
|
|
28
|
+
* @category Row grouping
|
|
29
|
+
*/
|
|
30
|
+
export interface RowGroupTableModelParaIf<T = any> {
|
|
31
|
+
/** The flat rows (not changed). */
|
|
32
|
+
rows: T[];
|
|
33
|
+
/** The levels, top first: property paths (`"region"`), functions (`o => o.date.getFullYear()`) or {@link RowGroupFieldIf}. */
|
|
34
|
+
groupBy: RowGroupField<T>[];
|
|
35
|
+
/** The columns. Default: one per key of the first row. The group column is added in front of them. */
|
|
36
|
+
columnDefs?: ColumnDefIf[];
|
|
37
|
+
/** Aggregates in the group rows; the key is the property of the column (`{ umsatz: "sum" }`, see {@link AggregateSpecMap}). */
|
|
38
|
+
aggregations?: AggregateSpecMap<T>;
|
|
39
|
+
/**
|
|
40
|
+
* The total row: `true` = the `aggregations`, `false` = none, or an own configuration ({@link AggregateFooterConfig}).
|
|
41
|
+
* Default: `true` if there are aggregations.
|
|
42
|
+
*/
|
|
43
|
+
footerAggregates?: boolean | AggregateFooterConfig<T>;
|
|
44
|
+
/** The group column: header, width, count, own label, fixed. */
|
|
45
|
+
groupColumn?: Partial<RowGroupColumnOptionsIf<T>>;
|
|
46
|
+
/** Hide the columns of the grouped properties. Default true. */
|
|
47
|
+
hideGroupedColumns?: boolean;
|
|
48
|
+
/** Expanded groups: `true` (default), `false`, open levels as a number (`0` = all closed) or a function per group. */
|
|
49
|
+
expanded?: RowGroupExpanded<T>;
|
|
50
|
+
/** The label of the group of empty keys (`null`, `undefined`, `""`). Default `"(empty)"`. */
|
|
51
|
+
emptyLabel?: string;
|
|
52
|
+
/** Options of the table (row heights, selection model, filter …). */
|
|
53
|
+
tableOptions?: TableOptionsIf;
|
|
54
|
+
/** Columns fixed on the left besides the group column (which is fixed by itself). Default 0. */
|
|
55
|
+
fixedLeftColumnCount?: number;
|
|
56
|
+
/** Columns fixed on the right. Default 0. */
|
|
57
|
+
fixedRightColumnCount?: number;
|
|
58
|
+
/** Row numbers in front of all columns (counted per displayed row, group rows included). */
|
|
59
|
+
rowNumbersVisible?: boolean | Partial<RowNumberOptionsIf>;
|
|
60
|
+
/** Set with a {@link CheckboxColumnDef} in `columnDefs` (default: detected). */
|
|
61
|
+
rowCheckboxVisible?: boolean;
|
|
62
|
+
/** Row heights of header, body and footer. Default: `tableOptions.defaultRowHeights`. */
|
|
63
|
+
defaultRowHeights?: DefaultRowHeightsIf;
|
|
64
|
+
/** Selection model factory. Default: `tableOptions.getSelectionModel`. */
|
|
65
|
+
getSelectionModel?: GetT<SelectionModelIf>;
|
|
66
|
+
}
|
|
@@ -6,6 +6,8 @@ import { TableOptionsIf } from '../data/options/table-options.if.js';
|
|
|
6
6
|
import { TableModelIf } from '../data/tablemodel/table-model.if.js';
|
|
7
7
|
import { TableModel } from '../data/tablemodel/table-model.js';
|
|
8
8
|
import { SelectionModelIf } from '../selection/selection-model.if.js';
|
|
9
|
+
import { RowNumberOptionsIf } from '../data/common/row-number-options.if.js';
|
|
10
|
+
import { AggregateFooterConfig } from '../data/tablemodel/areamodel/aggregate-footer-options.if.js';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Parameters of {@link TableFactory.createTableModel} – pass any subset (`Partial<CreateTableModelPara>`).
|
|
@@ -37,14 +39,56 @@ export interface CreateTableModelPara {
|
|
|
37
39
|
headerAreaModel: AreaModelIf;
|
|
38
40
|
/** Model of the body. Default: built from `rows` (objects or tree rows) or `bodyData`. See {@link AreaModel} for own models. */
|
|
39
41
|
bodyAreaModel: AreaModelIf;
|
|
40
|
-
/** Model of the footer. Default: `footerData`, otherwise no footer.
|
|
42
|
+
/** Model of the footer. Default: `footerAggregates`, `footerData`, otherwise no footer. */
|
|
41
43
|
footerAreaModel: AreaModelIf;
|
|
44
|
+
/**
|
|
45
|
+
* A footer with totals that follow filter and sorting ({@link AreaModelAggregateFooter}): `{ total: "sum" }` (one
|
|
46
|
+
* row – the key is the property of the column), `[{ label, aggregates }, …]` (several rows) or full
|
|
47
|
+
* {@link AggregateFooterOptionsIf}. Row height: `defaultRowHeights.footer`. Ignored with an own `footerAreaModel`
|
|
48
|
+
* (warning); `footerData` is ignored with it (warning).
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const tableModel = TableFactory.createTableModel({
|
|
52
|
+
* rows: orders,
|
|
53
|
+
* columnDefs,
|
|
54
|
+
* footerAggregates: { quantity: "sum", total: "sum" } // footer: "100,000 rows" | … | 549,812 | 27,481,033.5
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* @since 1.1.94
|
|
58
|
+
*/
|
|
59
|
+
footerAggregates: AggregateFooterConfig;
|
|
42
60
|
/** Number of columns fixed on the left (side "west"). Default 0. */
|
|
43
61
|
fixedLeftColumnCount: number;
|
|
44
62
|
/** Number of columns fixed on the right (side "east"). Default 0. */
|
|
45
63
|
fixedRightColumnCount: number;
|
|
46
64
|
/** Show a checkbox column for every row. Default false. */
|
|
47
65
|
rowCheckboxVisible: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Row numbers (1, 2, 3 …) in a column in front of all others, fixed on the left: `true` or options
|
|
68
|
+
* ({@link RowNumberOptionsIf}). Puts a {@link RowNumberColumnDef} in front of `columnDefs` and adds 1 to
|
|
69
|
+
* `fixedLeftColumnCount`; `headerData`/`footerData` get an empty cell in front. Default false.
|
|
70
|
+
*
|
|
71
|
+
* The column is a real column: the indices of all other columns are one higher – use properties where you can
|
|
72
|
+
* ({@link TableApi.getColumnIndex}). With `bodyData` or own area models the flag is ignored (with a warning), because
|
|
73
|
+
* their columns would shift – put a `RowNumberColumnDef` into the column definitions of your models yourself.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const tableModel = TableFactory.createTableModel({ rows: orders, columnDefs, rowNumbersVisible: true });
|
|
77
|
+
*
|
|
78
|
+
* @since 1.1.93
|
|
79
|
+
*/
|
|
80
|
+
rowNumbersVisible: boolean | Partial<RowNumberOptionsIf>;
|
|
81
|
+
/**
|
|
82
|
+
* Row drag: `true` puts a drag handle into the first data column (behind row numbers and checkboxes) –
|
|
83
|
+
* sets {@link ColumnDefIf.rowDrag} on that column definition. Options: {@link TableOptionsIf.rowDragOptions}.
|
|
84
|
+
* Default false.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const tableModel = TableFactory.createTableModel({ rows: orders, rowDrag: true });
|
|
88
|
+
*
|
|
89
|
+
* @since 1.1.95
|
|
90
|
+
*/
|
|
91
|
+
rowDrag: boolean;
|
|
48
92
|
/** Row heights of header, body and footer in px. Default: `tableOptions.defaultRowHeights`, otherwise 34 / 34 / 34. */
|
|
49
93
|
defaultRowHeights: DefaultRowHeightsIf;
|
|
50
94
|
/** The columns: property, header label, width, classes, renderers, sorting, editing. See {@link ColumnDef}. */
|
|
@@ -120,6 +164,17 @@ export declare class TableFactory {
|
|
|
120
164
|
* });
|
|
121
165
|
*/
|
|
122
166
|
static createTableModel(p: Partial<CreateTableModelPara>): TableModelIf;
|
|
167
|
+
/**
|
|
168
|
+
* `footerAggregates`: returns the configuration if the factory builds an aggregate footer (after the body model),
|
|
169
|
+
* `undefined` if there is none or an own `footerAreaModel` wins.
|
|
170
|
+
*/
|
|
171
|
+
private static checkFooterAggregates;
|
|
172
|
+
/**
|
|
173
|
+
* `rowNumbersVisible`: puts a RowNumberColumnDef in front of the column definitions (and an empty cell in front of
|
|
174
|
+
* `headerData`/`footerData`) and fixes it on the left. Only where the factory builds the models from the column
|
|
175
|
+
* definitions – with `bodyData` or own area models every column would shift by one.
|
|
176
|
+
*/
|
|
177
|
+
private static addRowNumberColumn;
|
|
123
178
|
/**
|
|
124
179
|
* Constructs a table model (an instance of `TableModelIf`) by using provided parameters.
|
|
125
180
|
*
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CellRange } from '../data/common/cell-range.js';
|
|
2
|
+
import { CellValueChangeIf } from '../batch-edit/cell-value-change.if.js';
|
|
3
|
+
import { FillDirection } from './fill-direction.type.js';
|
|
4
|
+
import { FillValueContextIf } from './fill-value-context.if.js';
|
|
5
|
+
import { FillMode } from './fill-series.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Input of {@link computeFillChanges}.
|
|
9
|
+
*
|
|
10
|
+
* @category Fill handle & batch edit
|
|
11
|
+
* @since 1.1.96
|
|
12
|
+
*/
|
|
13
|
+
export interface FillRequestIf {
|
|
14
|
+
/** The selected source range (body display indices, `r1 <= r2`, `c1 <= c2`). */
|
|
15
|
+
source: CellRange;
|
|
16
|
+
/** Where the range is extended to. */
|
|
17
|
+
direction: FillDirection;
|
|
18
|
+
/** The number of rows (down/up) or columns (right/left) to fill. */
|
|
19
|
+
count: number;
|
|
20
|
+
/** Series or copy, see {@link FillMode}. */
|
|
21
|
+
mode?: FillMode;
|
|
22
|
+
/** The shown value of a cell (batch edit: the pending value). */
|
|
23
|
+
getValue: (rowIndex: number, columnIndex: number) => unknown;
|
|
24
|
+
/** `false` skips a target cell (not editable, hidden column …); the series keeps counting. */
|
|
25
|
+
isFillable?: (rowIndex: number, columnIndex: number) => boolean;
|
|
26
|
+
/** Own fill function, see {@link FillHandleOptionsIf.fillValue}. */
|
|
27
|
+
fillValue?: (ctx: FillValueContextIf) => unknown;
|
|
28
|
+
/** Row object and property of a cell – for `fillValue`. */
|
|
29
|
+
getCellInfo?: (rowIndex: number, columnIndex: number) => {
|
|
30
|
+
row: unknown;
|
|
31
|
+
property: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The cells a fill covers: the source range extended by `count` rows or columns in `direction`.
|
|
36
|
+
*
|
|
37
|
+
* @param {CellRange} source - the selected range
|
|
38
|
+
* @param {FillDirection} direction - the direction of the fill
|
|
39
|
+
* @param {number} count - rows or columns added
|
|
40
|
+
* @returns {CellRange} source and filled cells together
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* getFillRange(new CellRange(2, 1, 3, 1), "down", 3); // rows 2…6 of column 1
|
|
44
|
+
*
|
|
45
|
+
* @category Fill handle & batch edit
|
|
46
|
+
* @since 1.1.96
|
|
47
|
+
*/
|
|
48
|
+
export declare function getFillRange(source: CellRange, direction: FillDirection, count: number): CellRange;
|
|
49
|
+
/**
|
|
50
|
+
* The values a fill writes: per line of the source range (each column when filling down/up, each row when filling
|
|
51
|
+
* right/left) the continuation of its values ({@link computeFillValues}) – DOM-free, the table applies the result with
|
|
52
|
+
* {@link TableApi.applyCellChanges}.
|
|
53
|
+
*
|
|
54
|
+
* @param {FillRequestIf} request - source range, direction, count, value access
|
|
55
|
+
* @returns {CellValueChangeIf[]} one change per fillable target cell (column = model index)
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const values = [[1], [2]]; // a 2 × 1 source range
|
|
59
|
+
* computeFillChanges({
|
|
60
|
+
* source: new CellRange(0, 0, 1, 0), direction: "down", count: 2,
|
|
61
|
+
* getValue: (r, c) => values[r]?.[c],
|
|
62
|
+
* }); // [{ rowIndex: 2, column: 0, value: 3 }, { rowIndex: 3, column: 0, value: 4 }]
|
|
63
|
+
*
|
|
64
|
+
* @category Fill handle & batch edit
|
|
65
|
+
* @since 1.1.96
|
|
66
|
+
*/
|
|
67
|
+
export declare function computeFillChanges(request: FillRequestIf): CellValueChangeIf[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FillHandleOptionsIf } from './fill-handle-options.if.js';
|
|
2
|
+
import { FillValueContextIf } from './fill-value-context.if.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The defaults of {@link FillHandleOptionsIf}.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const options = FillHandleOptions.create(true);
|
|
9
|
+
* options?.direction; // "both"
|
|
10
|
+
*
|
|
11
|
+
* @category Fill handle & batch edit
|
|
12
|
+
* @since 1.1.96
|
|
13
|
+
*/
|
|
14
|
+
export declare class FillHandleOptions implements FillHandleOptionsIf {
|
|
15
|
+
direction: "vertical" | "horizontal" | "both";
|
|
16
|
+
fillValue?: (ctx: FillValueContextIf) => unknown;
|
|
17
|
+
maxCells: number;
|
|
18
|
+
dragThresholdInPx: number;
|
|
19
|
+
autoScrollZoneInPx: number;
|
|
20
|
+
autoScrollMaxSpeedInPx: number;
|
|
21
|
+
/**
|
|
22
|
+
* The options of {@link TableOptionsIf.fillHandle}: `undefined`/`false` = no fill handle, `true` = the defaults, an
|
|
23
|
+
* object = the defaults overridden by its values (`undefined` keeps the default).
|
|
24
|
+
*
|
|
25
|
+
* @param {boolean | Partial<FillHandleOptionsIf>} [option] - `tableOptions.fillHandle`
|
|
26
|
+
* @returns {FillHandleOptionsIf | undefined} complete options, `undefined` if the fill handle is off
|
|
27
|
+
*/
|
|
28
|
+
static create(option?: boolean | Partial<FillHandleOptionsIf>): FillHandleOptionsIf | undefined;
|
|
29
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { FillValueContextIf } from './fill-value-context.if.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options of the fill handle ({@link TableOptionsIf.fillHandle}): the small square at the bottom right corner of the
|
|
5
|
+
* selected range. Dragging it fills the neighbouring cells – copies values or continues series (1, 2, 3 …; dates;
|
|
6
|
+
* `Item 1` → `Item 2`). Needs a {@link SelectionModel} of the type `"range"`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const selectionModel = new SelectionModel("range", "multi"); // one model – not a new one per call
|
|
10
|
+
* const tableOptions: TableOptionsIf = {
|
|
11
|
+
* ...new TableOptions(),
|
|
12
|
+
* getSelectionModel: () => selectionModel,
|
|
13
|
+
* fillHandle: { direction: "vertical" },
|
|
14
|
+
* };
|
|
15
|
+
*
|
|
16
|
+
* @category Fill handle & batch edit
|
|
17
|
+
* @since 1.1.96
|
|
18
|
+
*/
|
|
19
|
+
export interface FillHandleOptionsIf {
|
|
20
|
+
/** Allowed directions: `"vertical"` (down/up), `"horizontal"` (right/left) or `"both"` (default). */
|
|
21
|
+
direction: "vertical" | "horizontal" | "both";
|
|
22
|
+
/**
|
|
23
|
+
* Own fill function, called for every filled cell. Return the value – or `undefined` for the default
|
|
24
|
+
* (`ctx.defaultValue`).
|
|
25
|
+
*/
|
|
26
|
+
fillValue?: (ctx: FillValueContextIf) => unknown;
|
|
27
|
+
/** At most this many cells are filled at once (default 100,000); a bigger fill is refused and announced. */
|
|
28
|
+
maxCells: number;
|
|
29
|
+
/** Distance in px the pointer has to move before a fill starts (default 3). */
|
|
30
|
+
dragThresholdInPx: number;
|
|
31
|
+
/** Width in px of the zone at the edges of the body that scrolls automatically (default 40). */
|
|
32
|
+
autoScrollZoneInPx: number;
|
|
33
|
+
/** Maximum auto-scroll speed in px per animation frame (default 24). */
|
|
34
|
+
autoScrollMaxSpeedInPx: number;
|
|
35
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { TableScope } from '../table-scope.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The fill handle of one table (`tableScope.fillHandleService`): the square at the bottom right corner of the selected
|
|
5
|
+
* range, the pointer drag with preview and auto-scroll, Escape. The values come from {@link TableScope.fillRange}.
|
|
6
|
+
* Use {@link TableApi.fillRange}, {@link TableApi.isFilling} and {@link TableApi.cancelFill} instead.
|
|
7
|
+
*
|
|
8
|
+
* Pointer Events (mouse, touch, pen) only on the handle; its `pointerdown` is prevented, so the mouse handler of the
|
|
9
|
+
* table (range selection, column drag) never sees it.
|
|
10
|
+
*
|
|
11
|
+
* @category Internals
|
|
12
|
+
* @since 1.1.96
|
|
13
|
+
*/
|
|
14
|
+
export declare class FillHandleService {
|
|
15
|
+
private readonly tableScope;
|
|
16
|
+
private handle?;
|
|
17
|
+
private preview?;
|
|
18
|
+
private pending?;
|
|
19
|
+
private session?;
|
|
20
|
+
private sessionAbortController?;
|
|
21
|
+
private autoScrollFrame;
|
|
22
|
+
private suppressClick;
|
|
23
|
+
private shortcutsSet;
|
|
24
|
+
constructor(tableScope: TableScope);
|
|
25
|
+
/** true while the handle is dragged. */
|
|
26
|
+
isFilling(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Places the handle at the bottom right corner of the last selected range (called after every render pass) – or
|
|
29
|
+
* hides it: no fill handle option, no range, the corner scrolled out, an open editor, a blocking overlay.
|
|
30
|
+
*/
|
|
31
|
+
update(): void;
|
|
32
|
+
/** The handle's position (the corner of the range) in host coordinates – `undefined` if it is not visible. */
|
|
33
|
+
private getCornerOf;
|
|
34
|
+
private ensureHandle;
|
|
35
|
+
private removeHandle;
|
|
36
|
+
/** Keyboard alternative on the grid: Ctrl/⌘+D, Ctrl/⌘+R (only directions the options allow). */
|
|
37
|
+
private updateHostShortcuts;
|
|
38
|
+
private isHandle;
|
|
39
|
+
private onPointerDown;
|
|
40
|
+
private listenToDocument;
|
|
41
|
+
private onPointerMove;
|
|
42
|
+
private onPointerUp;
|
|
43
|
+
private suppressNextClick;
|
|
44
|
+
private onClickCapture;
|
|
45
|
+
/** Target cell under the pointer → direction and count; preview; auto-scroll. */
|
|
46
|
+
private updateTarget;
|
|
47
|
+
private renderPreview;
|
|
48
|
+
private updateAutoScroll;
|
|
49
|
+
private autoScrollStep;
|
|
50
|
+
/** Cancels a running fill (Escape, `pointercancel`, {@link TableApi.cancelFill}): nothing is changed. */
|
|
51
|
+
cancel(): void;
|
|
52
|
+
private stopListening;
|
|
53
|
+
/** Releases everything (TableScope.destroy). */
|
|
54
|
+
destroy(): void;
|
|
55
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How {@link computeFillValues} continues the source values:
|
|
3
|
+
* - `"auto"`: the default rules – one number is copied, several numbers continue as a linear series, dates and texts
|
|
4
|
+
* with a trailing number count up, everything else repeats;
|
|
5
|
+
* - `"alternate"`: the other choice for numbers, dates and texts with a number (⌥/Alt or Ctrl while dragging the fill
|
|
6
|
+
* handle): one number counts up by 1, a series is copied;
|
|
7
|
+
* - `"copy"`: always repeat the source values (Ctrl/⌘+D, Ctrl/⌘+R).
|
|
8
|
+
*
|
|
9
|
+
* @category Fill handle & batch edit
|
|
10
|
+
* @since 1.1.96
|
|
11
|
+
*/
|
|
12
|
+
export type FillMode = "auto" | "alternate" | "copy";
|
|
13
|
+
/**
|
|
14
|
+
* Computes the values of a fill (fill handle, Ctrl/⌘+D): `count` values that continue `sourceValues` – forward
|
|
15
|
+
* (down/right) or backward (up/left: the value directly in front of the source first).
|
|
16
|
+
*
|
|
17
|
+
* | source | `"auto"` | `"alternate"` |
|
|
18
|
+
* |---|---|---|
|
|
19
|
+
* | one number `5` | 5, 5, 5 | 6, 7, 8 |
|
|
20
|
+
* | numbers `1, 2` | 3, 4, 5 (linear; uneven steps: best-fit line) | 1, 2, 1 |
|
|
21
|
+
* | date `2026-10-14` (`Date` or ISO text) | +1 day each; several dates a month apart: +1 month (month ends stay month ends) | copied |
|
|
22
|
+
* | text with a trailing number `Item 9` | `Item 10`, `Item 11` (leading zeros stay) | copied |
|
|
23
|
+
* | anything else | repeated: `A, B` → `A, B, A, B` | repeated |
|
|
24
|
+
*
|
|
25
|
+
* The type stays: a date text stays a text in the same format, a `Date` stays a `Date`, a number written as text
|
|
26
|
+
* stays a text. Decimal noise is rounded (0.1, 0.2 → 0.3, not 0.30000000000000004).
|
|
27
|
+
*
|
|
28
|
+
* @param {unknown[]} sourceValues - the values of one line (column or row) of the source range, in display order
|
|
29
|
+
* @param {number} count - the number of values to compute
|
|
30
|
+
* @param {boolean} [backward=false] - fill up/left: the values in front of the source, nearest first
|
|
31
|
+
* @param {FillMode} [mode="auto"] - see {@link FillMode}
|
|
32
|
+
* @returns {unknown[]} `count` values, nearest to the source first
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* computeFillValues([1, 2], 3); // [3, 4, 5]
|
|
36
|
+
* computeFillValues([5], 3); // [5, 5, 5]
|
|
37
|
+
* computeFillValues([5], 3, false, "alternate"); // [6, 7, 8]
|
|
38
|
+
* computeFillValues(["2026-10-14"], 2); // ["2026-10-15", "2026-10-16"]
|
|
39
|
+
* computeFillValues(["Item 9"], 2); // ["Item 10", "Item 11"]
|
|
40
|
+
* computeFillValues([1, 2], 2, true); // [0, -1] (filled upwards)
|
|
41
|
+
*
|
|
42
|
+
* @category Fill handle & batch edit
|
|
43
|
+
* @since 1.1.96
|
|
44
|
+
*/
|
|
45
|
+
export declare function computeFillValues(sourceValues: unknown[], count: number, backward?: boolean, mode?: FillMode): unknown[];
|
|
46
|
+
/**
|
|
47
|
+
* `true` if {@link computeFillValues} continues the values as a series, `false` if it repeats them.
|
|
48
|
+
*
|
|
49
|
+
* @param {unknown[]} sourceValues - the values of one line of the source range
|
|
50
|
+
* @param {FillMode} [mode="auto"] - see {@link FillMode}
|
|
51
|
+
* @returns {boolean} whether the fill is a series
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* isFillSeries([5]); // false – one number is copied
|
|
55
|
+
* isFillSeries([1, 2]); // true
|
|
56
|
+
*
|
|
57
|
+
* @category Fill handle & batch edit
|
|
58
|
+
* @since 1.1.96
|
|
59
|
+
*/
|
|
60
|
+
export declare function isFillSeries(sourceValues: unknown[], mode?: FillMode): boolean;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { FillDirection } from './fill-direction.type.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What an own fill function ({@link FillHandleOptionsIf.fillValue}) gets for each filled cell.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
8
|
+
* const fillValue = (ctx: FillValueContextIf) => {
|
|
9
|
+
* const last = ctx.sourceValues[ctx.sourceValues.length - 1];
|
|
10
|
+
* const i = weekdays.indexOf(String(last));
|
|
11
|
+
* return i < 0 || ctx.copy ? undefined : weekdays[(((i + ctx.step) % 7) + 7) % 7]; // undefined = default
|
|
12
|
+
* };
|
|
13
|
+
*
|
|
14
|
+
* @category Fill handle & batch edit
|
|
15
|
+
* @since 1.1.96
|
|
16
|
+
*/
|
|
17
|
+
export interface FillValueContextIf {
|
|
18
|
+
/** The values of the source line (the column when filling down/up, the row when filling right/left), as shown. */
|
|
19
|
+
sourceValues: unknown[];
|
|
20
|
+
/** 1, 2, 3 … after the source (down/right), −1, −2 … in front of it (up/left). */
|
|
21
|
+
step: number;
|
|
22
|
+
/** The direction of the fill. */
|
|
23
|
+
direction: FillDirection;
|
|
24
|
+
/** Display index of the filled cell's row. */
|
|
25
|
+
rowIndex: number;
|
|
26
|
+
/** Model index of the filled cell's column. */
|
|
27
|
+
columnIndex: number;
|
|
28
|
+
/** The property of the column (`""` without a column definition). */
|
|
29
|
+
property: string;
|
|
30
|
+
/** The row object of the filled cell (`undefined` for own area models without row objects). */
|
|
31
|
+
row: unknown;
|
|
32
|
+
/** The value the table would use (series or copy). */
|
|
33
|
+
defaultValue: unknown;
|
|
34
|
+
/** `true` if the values are copied (⌥/Alt on a series, Ctrl/⌘+D, Ctrl/⌘+R). */
|
|
35
|
+
copy: boolean;
|
|
36
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { FormulaNode } from './formula-ast.if.js';
|
|
2
|
+
import { FormulaError } from './formula-error.js';
|
|
3
|
+
import { FormulaOptionsIf, FormulaValue } from './formula-options.if.js';
|
|
4
|
+
import { ValueGetterContextIf } from '../calc/value-getter-context.if.js';
|
|
5
|
+
import { ValueGetter } from '../calc/value-getter.type.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The names of the built-in formula functions (upper case), e.g. for the help text of an own formula input.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* hint.textContent = `Functions: ${FORMULA_FUNCTION_NAMES.join(", ")}`;
|
|
12
|
+
*
|
|
13
|
+
* @since 1.1.95
|
|
14
|
+
* @category Calculated columns & formulas
|
|
15
|
+
*/
|
|
16
|
+
export declare const FORMULA_FUNCTION_NAMES: readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* A formula compiled once ({@link compileFormula}): the AST, the referenced fields and `evaluate()` for a row.
|
|
19
|
+
* A formula with a syntax error or an unknown function has `error` set; `evaluate()` then always returns it.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const f = compileFormula("[price] * [quantity] * 1.19");
|
|
23
|
+
* f.fields; // ["price", "quantity"]
|
|
24
|
+
* f.evaluate({ price: 1299, quantity: 2 }); // 3091.62
|
|
25
|
+
*
|
|
26
|
+
* @since 1.1.95
|
|
27
|
+
* @category Calculated columns & formulas
|
|
28
|
+
*/
|
|
29
|
+
export interface CompiledFormula {
|
|
30
|
+
/** The formula text as given. */
|
|
31
|
+
readonly source: string;
|
|
32
|
+
/** The syntax tree; `undefined` if the formula has an error. */
|
|
33
|
+
readonly ast?: FormulaNode;
|
|
34
|
+
/** The error of the formula itself (`#ERROR!`, `#NAME?` for an unknown function); `undefined` if it is valid. */
|
|
35
|
+
readonly error?: FormulaError;
|
|
36
|
+
/** The referenced fields (`[price]` → `"price"`), each once, in order of appearance. */
|
|
37
|
+
readonly fields: readonly string[];
|
|
38
|
+
/** True if the formula uses a column aggregate (`SUM([total])` …). */
|
|
39
|
+
readonly usesAggregates: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Evaluates the formula for a row. Never throws: errors are returned as {@link FormulaError}.
|
|
42
|
+
* Without a context, column aggregates (`SUM([x])`) return `#VALUE!`.
|
|
43
|
+
*/
|
|
44
|
+
evaluate(row: unknown, context?: ValueGetterContextIf): FormulaValue;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Compiles a formula once – no `eval`, no `new Function` (works with a strict Content-Security-Policy, user input
|
|
48
|
+
* cannot run code). The result evaluates rows; never throws.
|
|
49
|
+
*
|
|
50
|
+
* Syntax (details: instructions.md „Formulas“):
|
|
51
|
+
* - fields in brackets: `[price]`, `[address.city]`, `[Unit price]` – own properties of the row or calculated columns
|
|
52
|
+
* - numbers `12`, `1.5`, `1e3`, texts `"a"` / `'a'`, `TRUE`, `FALSE`
|
|
53
|
+
* - operators: `+ - * / ^` (power), `&` (text), `= <> < <= > >=`; `-2^2 = -4`
|
|
54
|
+
* - functions: `ROUND(x, 2)`, `IF(c, a, b)`, `IFERROR`, `AND`, `OR`, `NOT`, `ABS`, `MOD`, `SQRT`, `POWER`, `FLOOR`,
|
|
55
|
+
* `CEILING`, `CONCAT`, `LEN`, `UPPER`, `LOWER`, `TRIM`, `ISBLANK`; `SUM AVG MIN MAX COUNT` – with one field the
|
|
56
|
+
* aggregate of the column (`[total] / SUM([total])`), otherwise of the arguments
|
|
57
|
+
*
|
|
58
|
+
* @param {string} source - the formula, e.g. `"[price] * [quantity] * 1.19"` (a leading `=` is ignored)
|
|
59
|
+
* @param {FormulaOptionsIf} [options] - own functions
|
|
60
|
+
* @returns {CompiledFormula} the compiled formula
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* const gross = compileFormula("ROUND([price] * [quantity] * 1.19, 2)");
|
|
64
|
+
* gross.evaluate({ price: 25, quantity: 10 }); // 297.5
|
|
65
|
+
* compileFormula("[price] / 0").evaluate({ price: 1 }); // FormulaError #DIV/0!
|
|
66
|
+
* compileFormula("[price] *").error?.code; // "#ERROR!"
|
|
67
|
+
*
|
|
68
|
+
* @since 1.1.95
|
|
69
|
+
* @category Calculated columns & formulas
|
|
70
|
+
*/
|
|
71
|
+
export declare function compileFormula(source: string, options?: FormulaOptionsIf): CompiledFormula;
|
|
72
|
+
/**
|
|
73
|
+
* The {@link ValueGetter} of a formula – what `ColumnDef.create({ formula })` sets as `valueGetter`.
|
|
74
|
+
*
|
|
75
|
+
* @param {CompiledFormula | string} formula - a compiled formula or its text
|
|
76
|
+
* @param {FormulaOptionsIf} [options] - own functions (only with a text)
|
|
77
|
+
* @returns {ValueGetter} the getter
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* const column = ColumnDef.create({ property: "gross", headerLabel: "Gross" });
|
|
81
|
+
* column.valueGetter = createFormulaValueGetter("[net] * 1.19");
|
|
82
|
+
*
|
|
83
|
+
* @since 1.1.95
|
|
84
|
+
* @category Calculated columns & formulas
|
|
85
|
+
*/
|
|
86
|
+
export declare function createFormulaValueGetter(formula: CompiledFormula | string, options?: FormulaOptionsIf): ValueGetter;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FormulaNode } from './formula-ast.if.js';
|
|
2
|
+
import { FormulaFunction, FormulaValue } from './formula-options.if.js';
|
|
3
|
+
import { ValueGetterContextIf } from '../calc/value-getter-context.if.js';
|
|
4
|
+
|
|
5
|
+
type Evaluate = (row: unknown, context: ValueGetterContextIf | undefined) => FormulaValue;
|
|
6
|
+
/** Reads a field: own properties only (no prototype chain), path segments separated by ".". */
|
|
7
|
+
export declare function readField(row: unknown, name: string, context?: ValueGetterContextIf, path?: string[]): FormulaValue;
|
|
8
|
+
/** Compiles an AST into closures. Never throws at evaluation time (see {@link FormulaEvaluator.evaluate}). */
|
|
9
|
+
export declare class FormulaEvaluator {
|
|
10
|
+
private readonly functions;
|
|
11
|
+
constructor(functions: Map<string, FormulaFunction>);
|
|
12
|
+
/** The evaluation function of a (checked) AST. */
|
|
13
|
+
compile(node: FormulaNode): Evaluate;
|
|
14
|
+
/** Evaluates an AST once (compiles it each time – for single use). */
|
|
15
|
+
evaluate(node: FormulaNode, row: unknown, context?: ValueGetterContextIf): FormulaValue;
|
|
16
|
+
private node;
|
|
17
|
+
private call;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A node of a compiled formula (abstract syntax tree). Read-only; the evaluator walks it – no code is generated
|
|
3
|
+
* (no `eval`, no `new Function`).
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const ast = compileFormula("[price] * 2").ast;
|
|
7
|
+
* // { kind: "binary", op: "*", left: { kind: "field", name: "price" }, right: { kind: "literal", value: 2 } }
|
|
8
|
+
*
|
|
9
|
+
* @since 1.1.95
|
|
10
|
+
* @category Calculated columns & formulas
|
|
11
|
+
*/
|
|
12
|
+
export type FormulaNode = {
|
|
13
|
+
readonly kind: "literal";
|
|
14
|
+
readonly value: number | string | boolean;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: "field";
|
|
17
|
+
readonly name: string;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: "unary";
|
|
20
|
+
readonly op: "-" | "+";
|
|
21
|
+
readonly operand: FormulaNode;
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "binary";
|
|
24
|
+
readonly op: FormulaBinaryOperator;
|
|
25
|
+
readonly left: FormulaNode;
|
|
26
|
+
readonly right: FormulaNode;
|
|
27
|
+
} | {
|
|
28
|
+
readonly kind: "call";
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly args: readonly FormulaNode[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The binary operators of a formula: arithmetic (`+ - * / ^`), text concatenation (`&`) and comparisons
|
|
34
|
+
* (`=`/`==`, `<>`/`!=`, `<`, `<=`, `>`, `>=`; normalized to `=` and `<>`).
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const op: FormulaBinaryOperator = "&"; // "Total: " & [total]
|
|
38
|
+
*
|
|
39
|
+
* @since 1.1.95
|
|
40
|
+
* @category Calculated columns & formulas
|
|
41
|
+
*/
|
|
42
|
+
export type FormulaBinaryOperator = "+" | "-" | "*" | "/" | "^" | "&" | "=" | "<>" | "<" | "<=" | ">" | ">=";
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The error codes of a formula – like in a spreadsheet:
|
|
3
|
+
*
|
|
4
|
+
* | Code | Meaning |
|
|
5
|
+
* |---|---|
|
|
6
|
+
* | `#ERROR!` | syntax error (the whole column shows it) |
|
|
7
|
+
* | `#NAME?` | unknown field or function |
|
|
8
|
+
* | `#VALUE!` | wrong type, e.g. `"abc" * 2` |
|
|
9
|
+
* | `#DIV/0!` | division by zero |
|
|
10
|
+
* | `#NUM!` | the result is not a finite number (`SQRT(-1)`, overflow) |
|
|
11
|
+
* | `#CIRC!` | circular reference between calculated columns |
|
|
12
|
+
*
|
|
13
|
+
* @since 1.1.95
|
|
14
|
+
* @category Calculated columns & formulas
|
|
15
|
+
*/
|
|
16
|
+
export type FormulaErrorCode = "#ERROR!" | "#NAME?" | "#VALUE!" | "#DIV/0!" | "#NUM!" | "#CIRC!";
|
|
17
|
+
/**
|
|
18
|
+
* An error value of a formula. Formulas never throw: a cell shows the {@link FormulaErrorCode} (`toString()`), the
|
|
19
|
+
* table adds the CSS class `ge-table-cell-error` and shows the message as tooltip. Errors propagate through
|
|
20
|
+
* operators and functions (`[a] / 0 + 1` → `#DIV/0!`), `IFERROR(x, fallback)` catches them, aggregators skip them.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const result = compileFormula("[price] / [quantity]").evaluate({ price: 10, quantity: 0 });
|
|
24
|
+
* if (isFormulaError(result)) {
|
|
25
|
+
* console.log(result.code, result.message); // "#DIV/0!" "Division by zero"
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* @since 1.1.95
|
|
29
|
+
* @category Calculated columns & formulas
|
|
30
|
+
*/
|
|
31
|
+
export declare class FormulaError {
|
|
32
|
+
readonly code: FormulaErrorCode;
|
|
33
|
+
readonly message: string;
|
|
34
|
+
readonly position?: number | undefined;
|
|
35
|
+
/** Marker (works across copies of the core): {@link isFormulaError}. */
|
|
36
|
+
readonly type = "FormulaError";
|
|
37
|
+
/**
|
|
38
|
+
* @param {FormulaErrorCode} code - the code shown in the cell
|
|
39
|
+
* @param {string} message - a short English explanation (tooltip); never contains HTML
|
|
40
|
+
* @param {number} [position] - for syntax errors: the position in the formula text (0-based)
|
|
41
|
+
*/
|
|
42
|
+
constructor(code: FormulaErrorCode, message: string, position?: number | undefined);
|
|
43
|
+
/** The code, e.g. `"#DIV/0!"` – what a cell shows. */
|
|
44
|
+
toString(): string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* True for an error value of a formula ({@link FormulaError}) – also for one created by another copy of the core.
|
|
48
|
+
*
|
|
49
|
+
* @param {unknown} value - any value
|
|
50
|
+
* @returns {boolean} whether it is a formula error
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* const value = tableApi.getRowValue(row, "margin");
|
|
54
|
+
* if (!isFormulaError(value)) console.log(value);
|
|
55
|
+
*
|
|
56
|
+
* @since 1.1.95
|
|
57
|
+
* @category Calculated columns & formulas
|
|
58
|
+
*/
|
|
59
|
+
export declare function isFormulaError(value: unknown): value is FormulaError;
|