@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
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @category Keyboard
|
|
7
7
|
*/
|
|
8
|
-
export declare const actionIds: readonly ["COPY_2_CLIPBOARD", "START_EDITING", "TOGGLE_SELECTION", "SELECT_ALL", "DESELECT_ALL", "NAVIGATE_LEFT", "NAVIGATE_RIGHT", "NAVIGATE_UP", "NAVIGATE_DOWN", "NAVIGATE_ROW_START", "NAVIGATE_ROW_END", "NAVIGATE_FIRST_CELL", "NAVIGATE_LAST_CELL", "NAVIGATE_PAGE_UP", "NAVIGATE_PAGE_DOWN", "ACTIVATE_CELL"];
|
|
8
|
+
export declare const actionIds: readonly ["COPY_2_CLIPBOARD", "START_EDITING", "TOGGLE_SELECTION", "SELECT_ALL", "DESELECT_ALL", "NAVIGATE_LEFT", "NAVIGATE_RIGHT", "NAVIGATE_UP", "NAVIGATE_DOWN", "NAVIGATE_ROW_START", "NAVIGATE_ROW_END", "NAVIGATE_FIRST_CELL", "NAVIGATE_LAST_CELL", "NAVIGATE_PAGE_UP", "NAVIGATE_PAGE_DOWN", "ACTIVATE_CELL", "MOVE_ROW_UP", "MOVE_ROW_DOWN", "FILL_DOWN", "FILL_RIGHT"];
|
|
9
9
|
/**
|
|
10
10
|
* Represents an action ID.
|
|
11
11
|
*
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AggregatorIf } from './aggregator.if.js';
|
|
2
|
+
import { AggregateSpec } from './aggregate-spec.if.js';
|
|
3
|
+
import { ValueAccessor } from './value-accessor.type.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A spec of {@link AggregateSpecMap} resolved for a pass over rows.
|
|
7
|
+
*/
|
|
8
|
+
export interface ResolvedAggregateSpec<T = any> {
|
|
9
|
+
key: string;
|
|
10
|
+
aggregator: AggregatorIf;
|
|
11
|
+
/** where the value comes from: the spec's `value`, otherwise the key as property path */
|
|
12
|
+
value: ValueAccessor<T>;
|
|
13
|
+
/** undefined for `count` (the value does not matter) */
|
|
14
|
+
getValue?: (row: T) => unknown;
|
|
15
|
+
format?: (result: unknown) => string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolves one entry of an {@link AggregateSpecMap}: the aggregator object, the value getter (default: the key as
|
|
19
|
+
* property path) and the format.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveAggregateSpec<T>(key: string, spec: AggregateSpec<T>): ResolvedAggregateSpec<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Runs resolved specs over the rows in one pass and returns the states (for `merge` by the caller) – the core of
|
|
24
|
+
* {@link aggregateColumns} and of {@link AreaModelAggregateFooter}.
|
|
25
|
+
*/
|
|
26
|
+
export declare function aggregateStates<T>(rows: ArrayLike<T>, specs: ResolvedAggregateSpec<T>[]): unknown[];
|
|
27
|
+
/**
|
|
28
|
+
* Like {@link aggregateStates} for models without row objects: the getters get the row index 0 … rowCount-1.
|
|
29
|
+
*/
|
|
30
|
+
export declare function aggregateIndexStates(rowCount: number, specs: Pick<ResolvedAggregateSpec<number>, 'aggregator' | 'getValue'>[]): unknown[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AggregatorRef } from './aggregator-name.type.js';
|
|
2
|
+
import { ValueAccessor } from './value-accessor.type.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* One aggregate in full form: which aggregator, which value, and (in a footer) how it is shown.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const spec: AggregateSpecIf<Order> = {
|
|
9
|
+
* aggregator: "avg",
|
|
10
|
+
* value: "total", // default: the key of the spec
|
|
11
|
+
* format: v => `${(v as number).toFixed(2)} €` // footer text; Excel gets the number
|
|
12
|
+
* };
|
|
13
|
+
*
|
|
14
|
+
* @since 1.1.94
|
|
15
|
+
* @category Aggregation
|
|
16
|
+
*/
|
|
17
|
+
export interface AggregateSpecIf<T = any> {
|
|
18
|
+
/** A built-in aggregator by name or an own one. */
|
|
19
|
+
aggregator: AggregatorRef;
|
|
20
|
+
/** The value of a row. Default: the key of the spec as property path. */
|
|
21
|
+
value?: ValueAccessor<T>;
|
|
22
|
+
/** The text in a footer cell. Default: numbers with at most two decimals (`"1,234.5"`), dates as date, `undefined` empty. */
|
|
23
|
+
format?: (result: unknown) => string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* An aggregate in short form (`"sum"`, an own aggregator) or in full form ({@link AggregateSpecIf}).
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const short: AggregateSpec<Order> = "sum";
|
|
30
|
+
* const full: AggregateSpec<Order> = { aggregator: "sum", value: o => o.quantity * o.price };
|
|
31
|
+
*
|
|
32
|
+
* @since 1.1.94
|
|
33
|
+
* @category Aggregation
|
|
34
|
+
*/
|
|
35
|
+
export type AggregateSpec<T = any> = AggregatorRef | AggregateSpecIf<T>;
|
|
36
|
+
/**
|
|
37
|
+
* Several aggregates by key. In {@link aggregateColumns} the key names the result (and is the default property path);
|
|
38
|
+
* in a footer ({@link AreaModelAggregateFooter}) the key is the property of the column that shows the result.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* const specs: AggregateSpecMap<Order> = {
|
|
42
|
+
* quantity: "sum",
|
|
43
|
+
* total: "sum",
|
|
44
|
+
* customer: "countDistinct",
|
|
45
|
+
* avgTotal: { aggregator: "avg", value: "total" } // a key without a column: only in the results
|
|
46
|
+
* };
|
|
47
|
+
*
|
|
48
|
+
* @since 1.1.94
|
|
49
|
+
* @category Aggregation
|
|
50
|
+
*/
|
|
51
|
+
export type AggregateSpecMap<T = any> = Record<string, AggregateSpec<T>>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AggregatorRef } from './aggregator-name.type.js';
|
|
2
|
+
import { ValueAccessor } from './value-accessor.type.js';
|
|
3
|
+
import { AggregateSpecMap } from './aggregate-spec.if.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Aggregates one value of all rows.
|
|
7
|
+
*
|
|
8
|
+
* @param {ArrayLike<T>} rows - the rows (an array, also filtered or sorted ones)
|
|
9
|
+
* @param {ValueAccessor<T>} value - property path (`"total"`, `"address.zip"`) or function
|
|
10
|
+
* @param {AggregatorRef} aggregator - `"sum"`, `"count"`, `"avg"`, `"min"`, `"max"`, `"countDistinct"`, `"first"`,
|
|
11
|
+
* `"last"` or an own {@link AggregatorIf}
|
|
12
|
+
* @returns {unknown} the result (`sum` of no numbers is `0`, `avg`/`min`/`max` of no numbers `undefined`)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* aggregate(orders, "total", "sum"); // all orders
|
|
16
|
+
* aggregate(orders.filter(o => o.city === "Berlin"), "total", "avg");
|
|
17
|
+
* aggregate(orders, o => o.quantity * o.price, "max"); // a computed value
|
|
18
|
+
*
|
|
19
|
+
* @since 1.1.94
|
|
20
|
+
* @category Aggregation
|
|
21
|
+
*/
|
|
22
|
+
export declare function aggregate<T = any>(rows: ArrayLike<T>, value: ValueAccessor<T>, aggregator: AggregatorRef): unknown;
|
|
23
|
+
/**
|
|
24
|
+
* Aggregates several values in **one** pass over the rows. The keys of `specs` name the results; a key is also the
|
|
25
|
+
* default property path.
|
|
26
|
+
*
|
|
27
|
+
* @param {ArrayLike<T>} rows - the rows
|
|
28
|
+
* @param {AggregateSpecMap<T>} specs - key → aggregator name, own aggregator or {@link AggregateSpecIf}
|
|
29
|
+
* @returns {Record<string, unknown>} key → result, in the order of `specs`
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const totals = aggregateColumns(orders, {
|
|
33
|
+
* quantity: "sum",
|
|
34
|
+
* total: "sum",
|
|
35
|
+
* customer: "countDistinct",
|
|
36
|
+
* avgTotal: { aggregator: "avg", value: "total" }
|
|
37
|
+
* });
|
|
38
|
+
* // { quantity: 549812, total: 27481033.5, customer: 412, avgTotal: 274.81 }
|
|
39
|
+
*
|
|
40
|
+
* @since 1.1.94
|
|
41
|
+
* @category Aggregation
|
|
42
|
+
*/
|
|
43
|
+
export declare function aggregateColumns<T = any>(rows: ArrayLike<T>, specs: AggregateSpecMap<T>): Record<string, unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* The default text of an aggregate (e.g. in a footer cell or a status bar): numbers with at most two decimals and
|
|
46
|
+
* thousands separators, dates as date (en-US), `null`/`undefined` empty, everything else as text.
|
|
47
|
+
*
|
|
48
|
+
* @param {unknown} value - an aggregation result
|
|
49
|
+
* @returns {string} the text
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* formatAggregateValue(1234.5678); // "1,234.57"
|
|
53
|
+
* formatAggregateValue(undefined); // ""
|
|
54
|
+
*
|
|
55
|
+
* @since 1.1.94
|
|
56
|
+
* @category Aggregation
|
|
57
|
+
*/
|
|
58
|
+
export declare function formatAggregateValue(value: unknown): string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AggregatorIf } from './aggregator.if.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The names of the built-in aggregators ({@link Aggregators}).
|
|
5
|
+
*
|
|
6
|
+
* | name | result | uses |
|
|
7
|
+
* |---|---|---|
|
|
8
|
+
* | `sum` | sum, `0` for no numbers | numbers (`NaN` ignored) |
|
|
9
|
+
* | `count` | number of rows | every row – the value does not matter |
|
|
10
|
+
* | `avg` | sum / count of the numbers, `undefined` for none | numbers |
|
|
11
|
+
* | `min`, `max` | smallest / largest value, `undefined` for none | numbers and valid `Date`s |
|
|
12
|
+
* | `countDistinct` | number of different values | everything except `null`/`undefined`; dates by time |
|
|
13
|
+
* | `first`, `last` | value of the first / last row | every row, the value as it is |
|
|
14
|
+
*
|
|
15
|
+
* Text is never converted to a number (like Excel's SUM over a range): `"12"` does not count. Use an accessor such as
|
|
16
|
+
* `row => Number(row.amount)` for numbers stored as text.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const name: AggregatorName = "avg";
|
|
20
|
+
* aggregate(orders, "total", name);
|
|
21
|
+
*
|
|
22
|
+
* @since 1.1.94
|
|
23
|
+
* @category Aggregation
|
|
24
|
+
*/
|
|
25
|
+
export type AggregatorName = "sum" | "count" | "avg" | "min" | "max" | "countDistinct" | "first" | "last";
|
|
26
|
+
/**
|
|
27
|
+
* A built-in aggregator by name or an own {@link AggregatorIf}.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const byName: AggregatorRef = "sum";
|
|
31
|
+
* const own: AggregatorRef = { name: "range", init: () => [Infinity, -Infinity],
|
|
32
|
+
* add: ([lo, hi]: number[], v: unknown) => typeof v === "number" ? [Math.min(lo, v), Math.max(hi, v)] : [lo, hi],
|
|
33
|
+
* merge: (a: number[], b: number[]) => [Math.min(a[0], b[0]), Math.max(a[1], b[1])],
|
|
34
|
+
* result: ([lo, hi]: number[]) => hi - lo };
|
|
35
|
+
*
|
|
36
|
+
* @since 1.1.94
|
|
37
|
+
* @category Aggregation
|
|
38
|
+
*/
|
|
39
|
+
export type AggregatorRef = AggregatorName | AggregatorIf;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An aggregation (sum, average, …) as four small functions over a **state**: `init` → `add` per value → `result`.
|
|
3
|
+
* `merge` combines two partial states – the result is the same as one pass over all values. That makes groups
|
|
4
|
+
* (row grouping, pivot) cheap: the state of a group is the merge of the states of its sub-groups, and an average of
|
|
5
|
+
* averages stays correct (`{ sum, count }` instead of a number).
|
|
6
|
+
*
|
|
7
|
+
* The built-in aggregators are in {@link Aggregators}; an own aggregator implements this interface and can be used
|
|
8
|
+
* everywhere a name like `"sum"` is accepted ({@link AggregatorRef}).
|
|
9
|
+
*
|
|
10
|
+
* `add(state, …)` and `merge(a, b)` may change `state` / `a` and return it (no allocation per row with millions of
|
|
11
|
+
* rows); `merge` never changes `b`, so a child state can be merged into several parents. Call `init()` for a fresh
|
|
12
|
+
* state, e.g. `merge(init(), child)` for a parent that must not change the child.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // the product of all numbers
|
|
16
|
+
* const product: AggregatorIf<number, number> = {
|
|
17
|
+
* name: "product",
|
|
18
|
+
* init: () => 1,
|
|
19
|
+
* add: (state, value) => typeof value === "number" ? state * value : state,
|
|
20
|
+
* merge: (a, b) => a * b,
|
|
21
|
+
* result: state => state
|
|
22
|
+
* };
|
|
23
|
+
* aggregate([{ f: 2 }, { f: 3 }, { f: 7 }], "f", product); // 42
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // partial results: the average of two groups is the average of all rows
|
|
27
|
+
* const avg = Aggregators.avg;
|
|
28
|
+
* const north = [100, 50, 120].reduce((s, v) => avg.add(s, v), avg.init());
|
|
29
|
+
* const south = [80, 70, 30].reduce((s, v) => avg.add(s, v), avg.init());
|
|
30
|
+
* avg.result(avg.merge(north, south)); // 75 – not the mean of 90 and 60
|
|
31
|
+
*
|
|
32
|
+
* @typeParam S - the state
|
|
33
|
+
* @typeParam R - the result
|
|
34
|
+
* @since 1.1.94
|
|
35
|
+
* @category Aggregation
|
|
36
|
+
*/
|
|
37
|
+
export interface AggregatorIf<S = any, R = unknown> {
|
|
38
|
+
/** The name, e.g. `"sum"` – the built-in ones use their {@link AggregatorName}. */
|
|
39
|
+
readonly name: string;
|
|
40
|
+
/** The state of the empty set. */
|
|
41
|
+
init(): S;
|
|
42
|
+
/** Takes one value into the state (values the aggregator can't use are ignored); returns the state. */
|
|
43
|
+
add(state: S, value: unknown): S;
|
|
44
|
+
/**
|
|
45
|
+
* Combines two partial states (`a` first, then `b` – matters for `first`/`last`); may change `a` and returns the
|
|
46
|
+
* combined state; never changes `b`.
|
|
47
|
+
*/
|
|
48
|
+
merge(a: S, b: S): S;
|
|
49
|
+
/** The result of a state, e.g. `sum / count` for the average. */
|
|
50
|
+
result(state: S): R;
|
|
51
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AggregatorIf } from './aggregator.if.js';
|
|
2
|
+
import { AggregatorName, AggregatorRef } from './aggregator-name.type.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The built-in aggregators by name ({@link AggregatorName}) – each one is an {@link AggregatorIf}, so `merge` combines
|
|
6
|
+
* partial results correctly (the average of groups is the average of all rows).
|
|
7
|
+
*
|
|
8
|
+
* - `sum` and `avg` sum with compensation (Neumaier): `0.1 + 0.2 + 0.3` is `0.6`, and splitting the data into groups
|
|
9
|
+
* does not change the result.
|
|
10
|
+
* - Numeric aggregators use numbers only (`NaN`, text, `null` … are ignored); `min`/`max` also valid `Date`s;
|
|
11
|
+
* `count` counts rows; `countDistinct` ignores `null`/`undefined`; `first`/`last` take the value as it is.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const { sum } = Aggregators;
|
|
15
|
+
* let state = sum.init();
|
|
16
|
+
* for (const order of orders) state = sum.add(state, order.total);
|
|
17
|
+
* sum.result(state); // the same as aggregate(orders, "total", "sum")
|
|
18
|
+
*
|
|
19
|
+
* @since 1.1.94
|
|
20
|
+
* @category Aggregation
|
|
21
|
+
*/
|
|
22
|
+
export declare const Aggregators: Readonly<Record<AggregatorName, AggregatorIf>>;
|
|
23
|
+
/**
|
|
24
|
+
* The aggregator for a name, or the given aggregator itself.
|
|
25
|
+
*
|
|
26
|
+
* @param {AggregatorRef} aggregator - a name like `"sum"` or an own {@link AggregatorIf}
|
|
27
|
+
* @returns {AggregatorIf} the aggregator
|
|
28
|
+
* @throws {Error} for an unknown name (the message lists the built-in names)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* getAggregator("avg").name; // "avg"
|
|
32
|
+
* getAggregator(Aggregators.max); // the same object
|
|
33
|
+
*
|
|
34
|
+
* @since 1.1.94
|
|
35
|
+
* @category Aggregation
|
|
36
|
+
*/
|
|
37
|
+
export declare function getAggregator(aggregator: AggregatorRef): AggregatorIf;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ValueAccessor } from './value-accessor.type.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A function that reads a value from a row: a property path (`"address.city"`, missing parents → `undefined`) or the
|
|
5
|
+
* given function itself.
|
|
6
|
+
*
|
|
7
|
+
* @param {ValueAccessor<T>} value - property path or function
|
|
8
|
+
* @returns {(row: T) => unknown} the getter
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const city = createValueGetter<{ address?: { city: string } }>("address.city");
|
|
12
|
+
* city({ address: { city: "Kiel" } }); // "Kiel"
|
|
13
|
+
* city({}); // undefined
|
|
14
|
+
*
|
|
15
|
+
* @since 1.1.94
|
|
16
|
+
* @category Aggregation
|
|
17
|
+
*/
|
|
18
|
+
export declare function createValueGetter<T = any>(value: ValueAccessor<T>): (row: T) => unknown;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Count, sum, average, minimum and maximum of the selected body cells – for a status bar like in a spreadsheet
|
|
3
|
+
* ({@link TableApi.getSelectionAggregates}).
|
|
4
|
+
*
|
|
5
|
+
* Counted are the selected cells of the visible data columns (row number and checkbox columns not); `numericCount`,
|
|
6
|
+
* `sum`, `avg`, `min`, `max` use the cells whose value is a number.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const a: SelectionAggregatesIf = tableApi.getSelectionAggregates();
|
|
10
|
+
* const text = a.capped ? "selection too large"
|
|
11
|
+
* : a.numericCount ? `Count ${a.count} · Sum ${formatAggregateValue(a.sum)} · Avg ${formatAggregateValue(a.avg)}`
|
|
12
|
+
* : a.count ? `Count ${a.count}` : "";
|
|
13
|
+
*
|
|
14
|
+
* @since 1.1.94
|
|
15
|
+
* @category Aggregation
|
|
16
|
+
*/
|
|
17
|
+
export interface SelectionAggregatesIf {
|
|
18
|
+
/** Number of selected cells. */
|
|
19
|
+
count: number;
|
|
20
|
+
/** Number of selected cells with a number. */
|
|
21
|
+
numericCount: number;
|
|
22
|
+
/** Sum of the numbers (`0` without numbers). */
|
|
23
|
+
sum: number;
|
|
24
|
+
/** Average of the numbers (`undefined` without numbers). */
|
|
25
|
+
avg: number | undefined;
|
|
26
|
+
/** Smallest number (`undefined` without numbers). */
|
|
27
|
+
min: number | undefined;
|
|
28
|
+
/** Largest number (`undefined` without numbers). */
|
|
29
|
+
max: number | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* `true` if the selection covers more than {@link SelectionAggregator.maxCells} cells: then nothing is computed
|
|
32
|
+
* (all values 0 / `undefined`) – a partial sum would be wrong.
|
|
33
|
+
*/
|
|
34
|
+
capped: boolean;
|
|
35
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an aggregation gets its value from a row: a property path (`"total"`, `"address.city"`) or a function
|
|
3
|
+
* (computed values, numbers stored as text, …).
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const byPath: ValueAccessor<Order> = "total";
|
|
7
|
+
* const computed: ValueAccessor<Order> = order => order.quantity * order.price;
|
|
8
|
+
*
|
|
9
|
+
* @typeParam T - the row type
|
|
10
|
+
* @since 1.1.94
|
|
11
|
+
* @category Aggregation
|
|
12
|
+
*/
|
|
13
|
+
export type ValueAccessor<T = any> = string | ((row: T) => unknown);
|
|
@@ -31,4 +31,15 @@ export declare class AriaTexts implements AriaTextsIf {
|
|
|
31
31
|
selectAllRows(): string;
|
|
32
32
|
expandGroup(groupLabel: string): string;
|
|
33
33
|
collapseGroup(groupLabel: string): string;
|
|
34
|
+
rowDragStarted(rowCount: number): string;
|
|
35
|
+
rowMoved(position: number, rowCount: number): string;
|
|
36
|
+
rowMoveNotPossible(): string;
|
|
37
|
+
rowDragCancelled(): string;
|
|
38
|
+
cellsFilled(cellCount: number): string;
|
|
39
|
+
fillTooLarge(maxCells: number): string;
|
|
40
|
+
pendingChanges(pendingCount: number): string;
|
|
41
|
+
changesCommitted(cellCount: number): string;
|
|
42
|
+
changesDiscarded(): string;
|
|
43
|
+
commitBlocked(invalidCount: number): string;
|
|
44
|
+
invalidValue(message: string): string;
|
|
34
45
|
}
|
|
@@ -85,4 +85,91 @@ export interface AriaTextsIf {
|
|
|
85
85
|
* @returns {string} default: `"Collapse group Q1"`
|
|
86
86
|
*/
|
|
87
87
|
collapseGroup(groupLabel: string): string;
|
|
88
|
+
/**
|
|
89
|
+
* Announced when a row drag starts (optional – {@link AriaTexts} has a default).
|
|
90
|
+
*
|
|
91
|
+
* @param {number} rowCount - number of dragged rows
|
|
92
|
+
* @returns {string} default: `"Dragging 1 row. Press Escape to cancel."`
|
|
93
|
+
* @since 1.1.95
|
|
94
|
+
*/
|
|
95
|
+
rowDragStarted?(rowCount: number): string;
|
|
96
|
+
/**
|
|
97
|
+
* Announced after rows were moved by drag and drop or Ctrl+Alt+↑/↓ (optional – {@link AriaTexts} has a default).
|
|
98
|
+
*
|
|
99
|
+
* @param {number} position - 1-based position of the first moved row
|
|
100
|
+
* @param {number} rowCount - number of displayed rows
|
|
101
|
+
* @returns {string} default: `"Row moved to position 7 of 20"`
|
|
102
|
+
* @since 1.1.95
|
|
103
|
+
*/
|
|
104
|
+
rowMoved?(position: number, rowCount: number): string;
|
|
105
|
+
/**
|
|
106
|
+
* Announced when rows cannot be moved: the table is sorted or filtered (managed row drag), or the row cannot move
|
|
107
|
+
* further (optional – {@link AriaTexts} has a default).
|
|
108
|
+
*
|
|
109
|
+
* @returns {string} default: `"Rows cannot be moved while the table is sorted or filtered"`
|
|
110
|
+
* @since 1.1.95
|
|
111
|
+
*/
|
|
112
|
+
rowMoveNotPossible?(): string;
|
|
113
|
+
/**
|
|
114
|
+
* Announced when a row drag was cancelled (Escape) – optional, {@link AriaTexts} has a default.
|
|
115
|
+
*
|
|
116
|
+
* @returns {string} default: `"Drag cancelled"`
|
|
117
|
+
* @since 1.1.95
|
|
118
|
+
*/
|
|
119
|
+
rowDragCancelled?(): string;
|
|
120
|
+
/**
|
|
121
|
+
* Announced after a fill (fill handle, Ctrl/⌘+D, Ctrl/⌘+R) – optional, {@link AriaTexts} has a default.
|
|
122
|
+
*
|
|
123
|
+
* @param {number} cellCount - the number of filled cells
|
|
124
|
+
* @returns {string} default: `"3 cells filled"`
|
|
125
|
+
* @since 1.1.96
|
|
126
|
+
*/
|
|
127
|
+
cellsFilled?(cellCount: number): string;
|
|
128
|
+
/**
|
|
129
|
+
* Announced when a fill is refused because it covers too many cells ({@link FillHandleOptionsIf.maxCells}).
|
|
130
|
+
*
|
|
131
|
+
* @param {number} maxCells - the limit
|
|
132
|
+
* @returns {string} default: `"Too many cells to fill (at most 100000)"`
|
|
133
|
+
* @since 1.1.96
|
|
134
|
+
*/
|
|
135
|
+
fillTooLarge?(maxCells: number): string;
|
|
136
|
+
/**
|
|
137
|
+
* Announced after a value was marked in a batch edit (or set back).
|
|
138
|
+
*
|
|
139
|
+
* @param {number} pendingCount - the number of pending cells
|
|
140
|
+
* @returns {string} default: `"3 changes not saved"`, `"No unsaved changes"`
|
|
141
|
+
* @since 1.1.96
|
|
142
|
+
*/
|
|
143
|
+
pendingChanges?(pendingCount: number): string;
|
|
144
|
+
/**
|
|
145
|
+
* Announced after {@link TableApi.commitBatchEdit}.
|
|
146
|
+
*
|
|
147
|
+
* @param {number} cellCount - the number of written cells
|
|
148
|
+
* @returns {string} default: `"3 changes saved"`
|
|
149
|
+
* @since 1.1.96
|
|
150
|
+
*/
|
|
151
|
+
changesCommitted?(cellCount: number): string;
|
|
152
|
+
/**
|
|
153
|
+
* Announced after {@link TableApi.cancelBatchEdit}.
|
|
154
|
+
*
|
|
155
|
+
* @returns {string} default: `"Changes discarded"`
|
|
156
|
+
* @since 1.1.96
|
|
157
|
+
*/
|
|
158
|
+
changesDiscarded?(): string;
|
|
159
|
+
/**
|
|
160
|
+
* Announced when invalid values block {@link TableApi.commitBatchEdit}.
|
|
161
|
+
*
|
|
162
|
+
* @param {number} invalidCount - the number of invalid cells
|
|
163
|
+
* @returns {string} default: `"2 invalid values – nothing saved"`
|
|
164
|
+
* @since 1.1.96
|
|
165
|
+
*/
|
|
166
|
+
commitBlocked?(invalidCount: number): string;
|
|
167
|
+
/**
|
|
168
|
+
* Announced when an edited value is invalid ({@link ColumnDefIf.validate}) and not written (without batch edit).
|
|
169
|
+
*
|
|
170
|
+
* @param {string} message - the message of the validator
|
|
171
|
+
* @returns {string} default: `"Invalid value: <message>"`
|
|
172
|
+
* @since 1.1.96
|
|
173
|
+
*/
|
|
174
|
+
invalidValue?(message: string): string;
|
|
88
175
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BatchEditOptionsIf } from './batch-edit-options.if.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The defaults of {@link BatchEditOptionsIf}.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* BatchEditOptions.create(true).blockCommitOnInvalid; // true
|
|
8
|
+
*
|
|
9
|
+
* @category Fill handle & batch edit
|
|
10
|
+
* @since 1.1.96
|
|
11
|
+
*/
|
|
12
|
+
export declare class BatchEditOptions implements BatchEditOptionsIf {
|
|
13
|
+
blockCommitOnInvalid: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The options of {@link TableOptionsIf.batchEdit} (`true`, `false` or an object) with defaults.
|
|
16
|
+
*
|
|
17
|
+
* @param {boolean | Partial<BatchEditOptionsIf>} [option] - `tableOptions.batchEdit`
|
|
18
|
+
* @returns {BatchEditOptionsIf} complete options
|
|
19
|
+
*/
|
|
20
|
+
static create(option?: boolean | Partial<BatchEditOptionsIf>): BatchEditOptionsIf;
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options of the batch edit ({@link TableOptionsIf.batchEdit}): changes are collected (marked, not written) and
|
|
3
|
+
* written with {@link TableApi.commitBatchEdit} or discarded with {@link TableApi.cancelBatchEdit}.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const tableOptions: TableOptionsIf = {
|
|
7
|
+
* ...new TableOptions(),
|
|
8
|
+
* batchEdit: { blockCommitOnInvalid: false }, // always collect; invalid values don't block saving
|
|
9
|
+
* };
|
|
10
|
+
*
|
|
11
|
+
* @category Fill handle & batch edit
|
|
12
|
+
* @since 1.1.96
|
|
13
|
+
*/
|
|
14
|
+
export interface BatchEditOptionsIf {
|
|
15
|
+
/**
|
|
16
|
+
* `true` (default): {@link TableApi.commitBatchEdit} writes nothing while a pending value is invalid
|
|
17
|
+
* ({@link ColumnDefIf.validate}) and returns `false`.
|
|
18
|
+
*/
|
|
19
|
+
blockCommitOnInvalid: boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { TableScope } from '../table-scope.js';
|
|
2
|
+
import { CellChangeIf } from './cell-change.if.js';
|
|
3
|
+
import { BatchEditOptionsIf } from './batch-edit-options.if.js';
|
|
4
|
+
import { PendingCellIf } from './pending-cell-changes.js';
|
|
5
|
+
|
|
6
|
+
/** A value to mark as pending – prepared by {@link TableScope.applyCellChanges}. */
|
|
7
|
+
export interface PendingInputIf {
|
|
8
|
+
rowIndex: number;
|
|
9
|
+
columnIndex: number;
|
|
10
|
+
/** after the editInputPipe */
|
|
11
|
+
value: unknown;
|
|
12
|
+
/** as entered */
|
|
13
|
+
rawValue: unknown;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Batch edit of one table (`tableScope.batchEditService`): collects changes instead of writing them, shows them
|
|
18
|
+
* (`ge-table-cell-pending`) and writes them on commit. Use {@link TableApi.startBatchEdit},
|
|
19
|
+
* {@link TableApi.commitBatchEdit}, {@link TableApi.cancelBatchEdit} and {@link TableApi.getPendingChanges}.
|
|
20
|
+
*
|
|
21
|
+
* The pending values belong to the row **objects** – sorting and filtering keep them on their rows. They are shown, but
|
|
22
|
+
* sorting, filtering, totals, copy and the Excel export use the written data (like ag-Grid).
|
|
23
|
+
*
|
|
24
|
+
* @category Internals
|
|
25
|
+
* @since 1.1.96
|
|
26
|
+
*/
|
|
27
|
+
export declare class BatchEditService {
|
|
28
|
+
private readonly tableScope;
|
|
29
|
+
private readonly pending;
|
|
30
|
+
private started;
|
|
31
|
+
constructor(tableScope: TableScope);
|
|
32
|
+
/** The options of this table ({@link TableOptionsIf.batchEdit} + defaults). */
|
|
33
|
+
get options(): BatchEditOptionsIf;
|
|
34
|
+
/** `tableOptions.batchEdit` is set: changes are always collected. */
|
|
35
|
+
isPermanent(): boolean;
|
|
36
|
+
/** True while changes are collected (started, or {@link isPermanent}). */
|
|
37
|
+
isActive(): boolean;
|
|
38
|
+
/** True if values are pending. */
|
|
39
|
+
hasPending(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Starts collecting changes (until commit or cancel).
|
|
42
|
+
*
|
|
43
|
+
* @returns {boolean} false if a batch edit is already running
|
|
44
|
+
*/
|
|
45
|
+
start(): boolean;
|
|
46
|
+
/** The key of a shown row: its object (tree: the data), the index for models without objects. */
|
|
47
|
+
rowKeyOf(rowIndex: number): unknown;
|
|
48
|
+
/** The key of a column: its property, `#<index>` without one. */
|
|
49
|
+
propertyOf(columnIndex: number): string;
|
|
50
|
+
/**
|
|
51
|
+
* The pending value of a shown body cell – asked for every rendered cell (one map lookup, nothing while empty).
|
|
52
|
+
*
|
|
53
|
+
* @param {number} rowIndex - display index
|
|
54
|
+
* @param {number} columnIndex - model index
|
|
55
|
+
* @returns {PendingCellIf | undefined} the entry
|
|
56
|
+
*/
|
|
57
|
+
getPendingAt(rowIndex: number, columnIndex: number): PendingCellIf | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* The value a body cell shows: the pending value, otherwise the model value.
|
|
60
|
+
*
|
|
61
|
+
* @param {number} rowIndex - display index
|
|
62
|
+
* @param {number} columnIndex - model index
|
|
63
|
+
* @returns {unknown} the shown value
|
|
64
|
+
*/
|
|
65
|
+
getShownValue(rowIndex: number, columnIndex: number): unknown;
|
|
66
|
+
/**
|
|
67
|
+
* Marks values as pending (B1, B6, B8) and reports the step (`onBatchEditChanged`, announcement). The caller repaints.
|
|
68
|
+
*
|
|
69
|
+
* @param {PendingInputIf[]} inputs - cells with piped and raw value
|
|
70
|
+
* @returns {CellChangeIf[]} the cells whose pending state changed
|
|
71
|
+
*/
|
|
72
|
+
addPending(inputs: PendingInputIf[]): CellChangeIf[];
|
|
73
|
+
/**
|
|
74
|
+
* All pending changes with the current display indices (one scan of the shown rows).
|
|
75
|
+
*
|
|
76
|
+
* @returns {CellChangeIf[]} the pending cells
|
|
77
|
+
*/
|
|
78
|
+
getPendingChanges(): CellChangeIf[];
|
|
79
|
+
/**
|
|
80
|
+
* Writes the pending values (B3): shown rows through `setValue` (the pipe runs once, row groupings regroup), rows a
|
|
81
|
+
* filter hides directly into their objects. One `onModelChanged` with all cells, then `onBatchEditChanged` "commit".
|
|
82
|
+
*
|
|
83
|
+
* @returns {boolean} false if invalid values block the commit ({@link BatchEditOptionsIf.blockCommitOnInvalid})
|
|
84
|
+
*/
|
|
85
|
+
commit(): boolean;
|
|
86
|
+
/** Discards the pending values (B4) and ends a started batch edit. */
|
|
87
|
+
cancel(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Forgets pending values of rows that are no longer in the model (`setRows`, a reloaded tree): they would never be
|
|
90
|
+
* shown, block a commit with an invalid value and be written into stale objects. Only for models whose rows are known
|
|
91
|
+
* (object arrays, trees, row groupings); others keep their entries.
|
|
92
|
+
*
|
|
93
|
+
* @returns {number} the number of removed entries
|
|
94
|
+
*/
|
|
95
|
+
pruneOrphans(): number;
|
|
96
|
+
/** All row keys of the body (also filtered and collapsed rows) – `undefined` if the model can't tell. */
|
|
97
|
+
private collectRowKeys;
|
|
98
|
+
private toChange;
|
|
99
|
+
private findColumnIndex;
|
|
100
|
+
/** Row key → display index, for the rows with pending values only. */
|
|
101
|
+
private createRowIndexMap;
|
|
102
|
+
private fire;
|
|
103
|
+
private texts;
|
|
104
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What started a change of cells: `"edit"` (cell editor), `"fill"` (fill handle, Ctrl/⌘+D, Ctrl/⌘+R),
|
|
3
|
+
* `"commit"` ({@link TableApi.commitBatchEdit}) or `"api"` ({@link TableApi.applyCellChanges}).
|
|
4
|
+
*
|
|
5
|
+
* @category Fill handle & batch edit
|
|
6
|
+
* @since 1.1.96
|
|
7
|
+
*/
|
|
8
|
+
export type CellChangeSource = "edit" | "fill" | "commit" | "api";
|
|
9
|
+
/**
|
|
10
|
+
* One changed cell: row, column, old and new value – the unit of a change set ({@link GeModelChangeEvent.changes},
|
|
11
|
+
* {@link TableApi.getPendingChanges}). With old **and** new value it is enough for undo and redo.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const listener = new EventAdapter();
|
|
15
|
+
* listener.onModelChanged = (evt: GeModelChangeEvent) => {
|
|
16
|
+
* for (const change of evt.changes ?? []) {
|
|
17
|
+
* console.log(change.property, change.oldValue, "→", change.newValue, change.row);
|
|
18
|
+
* }
|
|
19
|
+
* };
|
|
20
|
+
*
|
|
21
|
+
* @category Fill handle & batch edit
|
|
22
|
+
* @since 1.1.96
|
|
23
|
+
*/
|
|
24
|
+
export interface CellChangeIf<T = any> {
|
|
25
|
+
/** The row object (tree: the data of the `TreeRow`); `undefined` for own area models without row objects. */
|
|
26
|
+
row: T;
|
|
27
|
+
/** Display index of the row when the change was reported, `-1` if a filter hides the row. */
|
|
28
|
+
rowIndex: number;
|
|
29
|
+
/** Model index of the column when the change was reported, `-1` if the column no longer exists. */
|
|
30
|
+
columnIndex: number;
|
|
31
|
+
/** The property of the column (`"#3"` for a column without property). */
|
|
32
|
+
property: string;
|
|
33
|
+
/** The value before the change (batch edit: before the first change of the cell). */
|
|
34
|
+
oldValue: unknown;
|
|
35
|
+
/** The new value (after the column's `editInputPipe`). */
|
|
36
|
+
newValue: unknown;
|
|
37
|
+
/** Batch edit: the message of {@link ColumnDefIf.validate} if the new value is invalid. */
|
|
38
|
+
error?: string;
|
|
39
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A value to write into a body cell – the input of {@link TableApi.applyCellChanges} (and of the fill handle).
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* const change: CellValueChangeIf = { rowIndex: 3, column: "price", value: 9.9 };
|
|
6
|
+
* tableApi.applyCellChanges([change]);
|
|
7
|
+
*
|
|
8
|
+
* @category Fill handle & batch edit
|
|
9
|
+
* @since 1.1.96
|
|
10
|
+
*/
|
|
11
|
+
export interface CellValueChangeIf {
|
|
12
|
+
/** Display index of the row in the body. */
|
|
13
|
+
rowIndex: number;
|
|
14
|
+
/** Model index of the column, or its property. */
|
|
15
|
+
column: number | string;
|
|
16
|
+
/** The new value – like typed into the editor: it runs through the column's `editInputPipe`. */
|
|
17
|
+
value: unknown;
|
|
18
|
+
}
|