@guiexpert/table 1.1.94 → 1.1.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +12 -0
  2. package/css/main.css +192 -0
  3. package/css/table-calc.css +7 -0
  4. package/css/table-color-vars.css +46 -0
  5. package/css/table-fill-batch.css +58 -0
  6. package/css/table-row-drag.css +81 -0
  7. package/index.cjs +39 -37
  8. package/index.d.ts +28 -0
  9. package/index.js +5501 -1934
  10. package/lib/table/action/action-id.type.d.ts +1 -1
  11. package/lib/table/aria/aria-texts.d.ts +11 -0
  12. package/lib/table/aria/aria-texts.if.d.ts +87 -0
  13. package/lib/table/batch-edit/batch-edit-options.d.ts +21 -0
  14. package/lib/table/batch-edit/batch-edit-options.if.d.ts +20 -0
  15. package/lib/table/batch-edit/batch-edit-service.d.ts +104 -0
  16. package/lib/table/batch-edit/cell-change.if.d.ts +39 -0
  17. package/lib/table/batch-edit/cell-value-change.if.d.ts +18 -0
  18. package/lib/table/batch-edit/pending-cell-changes.d.ts +104 -0
  19. package/lib/table/calc/column-values.d.ts +55 -0
  20. package/lib/table/calc/show-values-as-internals.d.ts +4 -0
  21. package/lib/table/calc/show-values-as.d.ts +87 -0
  22. package/lib/table/calc/show-values-as.type.d.ts +55 -0
  23. package/lib/table/calc/value-getter-context.if.d.ts +35 -0
  24. package/lib/table/calc/value-getter.type.d.ts +36 -0
  25. package/lib/table/data/common/event/ge-batch-edit-event.d.ts +46 -0
  26. package/lib/table/data/common/event/ge-model-change-event.d.ts +27 -1
  27. package/lib/table/data/common/event/ge-row-drag-event.d.ts +89 -0
  28. package/lib/table/data/options/table-options.d.ts +6 -0
  29. package/lib/table/data/options/table-options.if.d.ts +44 -0
  30. package/lib/table/data/tablemodel/areamodel/abstract-area-model.d.ts +66 -0
  31. package/lib/table/data/tablemodel/areamodel/area-model-aggregate-footer.d.ts +5 -0
  32. package/lib/table/data/tablemodel/areamodel/area-model-array-of-arrays.d.ts +24 -0
  33. package/lib/table/data/tablemodel/areamodel/area-model-object-array.d.ts +70 -0
  34. package/lib/table/data/tablemodel/areamodel/area-model-pivot.d.ts +31 -0
  35. package/lib/table/data/tablemodel/areamodel/area-model-row-groups.d.ts +23 -1
  36. package/lib/table/data/tablemodel/areamodel/area-model-tree.d.ts +83 -0
  37. package/lib/table/data/tablemodel/areamodel/area-model.if.d.ts +55 -0
  38. package/lib/table/data/tablemodel/column/column-def.d.ts +31 -1
  39. package/lib/table/data/tablemodel/column/column-def.if.d.ts +86 -0
  40. package/lib/table/event-adapter.d.ts +7 -0
  41. package/lib/table/event-listener.if.d.ts +32 -0
  42. package/lib/table/factory/table-factory.d.ts +11 -0
  43. package/lib/table/fill/compute-fill-changes.d.ts +67 -0
  44. package/lib/table/fill/fill-direction.type.d.ts +7 -0
  45. package/lib/table/fill/fill-handle-options.d.ts +29 -0
  46. package/lib/table/fill/fill-handle-options.if.d.ts +35 -0
  47. package/lib/table/fill/fill-handle-service.d.ts +55 -0
  48. package/lib/table/fill/fill-series.d.ts +60 -0
  49. package/lib/table/fill/fill-value-context.if.d.ts +36 -0
  50. package/lib/table/formula/compile-formula.d.ts +86 -0
  51. package/lib/table/formula/evaluator.d.ts +19 -0
  52. package/lib/table/formula/formula-ast.if.d.ts +42 -0
  53. package/lib/table/formula/formula-error.d.ts +59 -0
  54. package/lib/table/formula/formula-options.if.d.ts +41 -0
  55. package/lib/table/formula/formula-values.d.ts +13 -0
  56. package/lib/table/formula/functions.d.ts +18 -0
  57. package/lib/table/formula/parser.d.ts +10 -0
  58. package/lib/table/formula/tokenizer.d.ts +22 -0
  59. package/lib/table/pivot/pivot-value.type.d.ts +13 -0
  60. package/lib/table/render-scope.d.ts +81 -0
  61. package/lib/table/renderer/edit/input-cell-renderer.d.ts +1 -1
  62. package/lib/table/renderer/edit/select-cell-renderer.d.ts +1 -1
  63. package/lib/table/row-drag/move-rows.d.ts +157 -0
  64. package/lib/table/row-drag/row-drag-options.d.ts +28 -0
  65. package/lib/table/row-drag/row-drag-options.if.d.ts +36 -0
  66. package/lib/table/row-drag/row-drag-service.d.ts +130 -0
  67. package/lib/table/row-drag/row-drop-target.if.d.ts +29 -0
  68. package/lib/table/service/excel-service.d.ts +6 -0
  69. package/lib/table/service/excel-service.if.d.ts +35 -0
  70. package/lib/table/table-api.d.ts +277 -2
  71. package/lib/table/table-scope.d.ts +121 -0
  72. package/package.json +1 -1
@@ -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;
@@ -0,0 +1,41 @@
1
+ import { FormulaError } from './formula-error.js';
2
+
3
+ /**
4
+ * A value inside a formula: a number, a text, a boolean, blank (`null`) or an error.
5
+ *
6
+ * @example
7
+ * const fn: FormulaFunction = (x: FormulaValue) => typeof x === "number" ? x * 1.19 : x;
8
+ *
9
+ * @since 1.1.95
10
+ * @category Calculated columns & formulas
11
+ */
12
+ export type FormulaValue = number | string | boolean | null | FormulaError;
13
+ /**
14
+ * An own function for formulas. It gets the evaluated arguments (never an error – an error argument is returned
15
+ * without calling the function) and returns a number, text, boolean or `null`. Anything else, an exception or
16
+ * `NaN` becomes `#VALUE!` resp. `#NUM!`.
17
+ *
18
+ * @example
19
+ * const VAT: FormulaFunction = (net) => Number(net) * 0.19;
20
+ * compileFormula("VAT([price])", { functions: { VAT } });
21
+ *
22
+ * @since 1.1.95
23
+ * @category Calculated columns & formulas
24
+ */
25
+ export type FormulaFunction = (...args: FormulaValue[]) => unknown;
26
+ /**
27
+ * Options of {@link compileFormula}.
28
+ *
29
+ * @example
30
+ * const options: FormulaOptionsIf = {
31
+ * functions: { NET: (gross) => Number(gross) / 1.19 }
32
+ * };
33
+ * ColumnDef.create({ property: "net", headerLabel: "Net", formula: "NET([gross])", formulaOptions: options });
34
+ *
35
+ * @since 1.1.95
36
+ * @category Calculated columns & formulas
37
+ */
38
+ export interface FormulaOptionsIf {
39
+ /** Own functions by name (case-insensitive). They may replace built-in ones. */
40
+ functions?: Record<string, FormulaFunction>;
41
+ }
@@ -0,0 +1,13 @@
1
+ import { FormulaError } from './formula-error.js';
2
+ import { FormulaValue } from './formula-options.if.js';
3
+
4
+ export declare function isBlank(v: FormulaValue): boolean;
5
+ /** A value from the data (a field) as formula value: Date → ms, function/object → #VALUE!. */
6
+ export declare function fromData(v: unknown, name: string, trusted?: boolean): FormulaValue;
7
+ export declare function toNumber(v: FormulaValue): number | FormulaError;
8
+ export declare function toText(v: FormulaValue): string | FormulaError;
9
+ export declare function toBoolean(v: FormulaValue): boolean | FormulaError;
10
+ /** A number result: NaN / ±Infinity → #NUM!, -0 → 0. */
11
+ export declare function numberResult(n: number): number | FormulaError;
12
+ /** Compares two values: numbers numerically, texts case-insensitively, blank = 0 = "" = FALSE. */
13
+ export declare function compareValues(a: FormulaValue, b: FormulaValue): number | FormulaError;
@@ -0,0 +1,18 @@
1
+ import { FormulaValue } from './formula-options.if.js';
2
+
3
+ /** A built-in function with eagerly evaluated arguments (errors are returned before the call). */
4
+ export interface BuiltInFunction {
5
+ readonly min: number;
6
+ readonly max: number;
7
+ readonly fn: (args: FormulaValue[]) => FormulaValue;
8
+ }
9
+ /** Functions with lazily evaluated arguments – handled by the evaluator itself. */
10
+ export declare const LAZY_FUNCTIONS: Record<string, {
11
+ min: number;
12
+ max: number;
13
+ }>;
14
+ /** SUM, AVG … with exactly one field reference: an aggregate over the (filtered) rows of the table. */
15
+ export declare const AGGREGATE_FUNCTIONS: Record<string, "sum" | "avg" | "min" | "max" | "count">;
16
+ /** Rounds half away from zero (like Excel) without binary artefacts: ROUND(1.005, 2) = 1.01. */
17
+ export declare function roundHalfAwayFromZero(x: number, digits: number): number;
18
+ export declare const BUILT_IN_FUNCTIONS: Record<string, BuiltInFunction>;
@@ -0,0 +1,10 @@
1
+ import { FormulaNode } from './formula-ast.if.js';
2
+
3
+ /** The maximum length of a formula (characters). */
4
+ export declare const MAX_FORMULA_LENGTH = 10000;
5
+ /** The maximum nesting depth (parentheses, function calls, unary operators). */
6
+ export declare const MAX_FORMULA_DEPTH = 64;
7
+ /** The maximum number of binary operators (a long chain is a deep tree, too). */
8
+ export declare const MAX_FORMULA_OPERATORS = 1000;
9
+ /** Parses a formula into an AST. Throws a {@link FormulaSyntaxError}. */
10
+ export declare function parseFormula(source: string): FormulaNode;
@@ -0,0 +1,22 @@
1
+ import { FormulaError } from './formula-error.js';
2
+
3
+ /** The kinds of tokens of a formula. */
4
+ export type FormulaTokenKind = "number" | "string" | "field" | "ident" | "op" | "(" | ")" | "," | "eof";
5
+ /** One token: kind, text (number/string already decoded) and position in the source. */
6
+ export interface FormulaToken {
7
+ readonly kind: FormulaTokenKind;
8
+ readonly text: string;
9
+ readonly value?: number;
10
+ readonly pos: number;
11
+ }
12
+ /** Thrown by tokenizer and parser, caught by `compileFormula` – never leaves the formula module. */
13
+ export declare class FormulaSyntaxError extends Error {
14
+ readonly pos: number;
15
+ constructor(message: string, pos: number);
16
+ toFormulaError(): FormulaError;
17
+ }
18
+ /**
19
+ * Splits a formula into tokens. Whitespace is ignored. Throws a {@link FormulaSyntaxError} for an unknown character,
20
+ * an unterminated string or field reference.
21
+ */
22
+ export declare function tokenize(source: string): FormulaToken[];
@@ -1,6 +1,7 @@
1
1
  import { ValueAccessor } from '../aggregation/value-accessor.type.js';
2
2
  import { AggregatorRef } from '../aggregation/aggregator-name.type.js';
3
3
  import { AggregatorIf } from '../aggregation/aggregator.if.js';
4
+ import { ShowValuesAsConfig, ShowValuesAsIf } from '../calc/show-values-as.type.js';
4
5
 
5
6
  /**
6
7
  * One value of a pivot table in full form: where the value of a row comes from, how it is aggregated, and how its
@@ -32,6 +33,16 @@ export interface PivotValueIf<T = any> {
32
33
  label?: string;
33
34
  /** The text of a result in a cell. Default: numbers with at most two decimals (`"1,234.5"`). Excel gets the raw value. */
34
35
  format?: (result: unknown) => string;
36
+ /**
37
+ * „Show values as“ (since 1.1.95): `"percentOfRowTotal"` (each pivot row = 100 %), `"percentOfColumnTotal"`,
38
+ * `"percentOfGrandTotal"` or `"percentOfParentTotal"` (share of the parent row group). The cells then hold the
39
+ * fraction (Excel: number with percent format), the text is a percentage; `format` is not used. Other modes of
40
+ * {@link ShowValuesAs} don't apply to a pivot (the value is shown).
41
+ *
42
+ * @example
43
+ * values: [{ value: "umsatz", showValuesAs: "percentOfRowTotal" }]
44
+ */
45
+ showValuesAs?: ShowValuesAsConfig;
35
46
  }
36
47
  /**
37
48
  * A value of a pivot table: a property path or function (summed) or the full form {@link PivotValueIf}.
@@ -64,4 +75,6 @@ export interface PivotValueInfoIf {
64
75
  readonly aggregator: AggregatorIf;
65
76
  /** The format of a result, if one was given. */
66
77
  readonly format?: (result: unknown) => string;
78
+ /** „Show values as“, if one was given (since 1.1.95). */
79
+ readonly showValuesAs?: ShowValuesAsIf;
67
80
  }
@@ -1,3 +1,6 @@
1
+ import { RowDragService } from './row-drag/row-drag-service.js';
2
+ import { BatchEditService } from './batch-edit/batch-edit-service.js';
3
+ import { FillHandleService } from './fill/fill-handle-service.js';
1
4
  import { TableOverlayChange } from './overlay/table-overlay.js';
2
5
  import { EleScope } from './ele-scope.js';
3
6
  import { TableModelIf } from './data/tablemodel/table-model.if.js';
@@ -85,7 +88,80 @@ export declare class RenderScope extends EleScope {
85
88
  * first body row, see `TableScope`. `undefined`: the focus is in the body ({@link FocusModelIf}).
86
89
  */
87
90
  protected headerFocus?: [number, number];
91
+ /**
92
+ * Row drag of this table (drag handles, pointer and keyboard drag) – created by {@link TableScope}.
93
+ * @since 1.1.95
94
+ */
95
+ rowDragService?: RowDragService;
96
+ /**
97
+ * Batch edit of this table (pending values, shown in the cells) – created by {@link TableScope}.
98
+ * @since 1.1.96
99
+ */
100
+ batchEditService?: BatchEditService;
101
+ /**
102
+ * Fill handle of this table – created by {@link TableScope}.
103
+ * @since 1.1.96
104
+ */
105
+ fillHandleService?: FillHandleService;
88
106
  constructor(hostElement: HTMLDivElement, tableModel: TableModelIf, dom: ConvenienceDomService, tableOptions: TableOptionsIf);
107
+ /**
108
+ * The DOM service of this table (all DOM access of the table goes through it).
109
+ *
110
+ * @returns {ConvenienceDomService} the service
111
+ * @since 1.1.95
112
+ */
113
+ getDomService(): ConvenienceDomService;
114
+ /**
115
+ * The visible body in client (viewport) coordinates – including fixed west/east columns, without the scroll bar –
116
+ * and the content pixels scrolled out at its top. Row drag computes the row under the pointer with it.
117
+ *
118
+ * @returns {{ top: number, height: number, left: number, width: number, contentScrollTop: number }} the geometry
119
+ * @since 1.1.95
120
+ */
121
+ getBodyViewport(): {
122
+ top: number;
123
+ height: number;
124
+ left: number;
125
+ width: number;
126
+ contentScrollTop: number;
127
+ };
128
+ /**
129
+ * The rectangle of a body cell in host coordinates (relative to the padding box of the host) – computed from the
130
+ * row and column positions, also for cells that are not rendered – and the visible part of its area (`clip…`: the
131
+ * body between header and footer, horizontally the fixed west/east area or the scrollable center).
132
+ *
133
+ * @param {number} rowIndex - display index
134
+ * @param {number} columnIndex - model index
135
+ * @returns {{ left: number, top: number, width: number, height: number, clipLeft: number, clipRight: number, clipTop: number, clipBottom: number }} the geometry
136
+ * @since 1.1.96
137
+ */
138
+ getBodyCellRectInHost(rowIndex: number, columnIndex: number): {
139
+ left: number;
140
+ top: number;
141
+ width: number;
142
+ height: number;
143
+ clipLeft: number;
144
+ clipRight: number;
145
+ clipTop: number;
146
+ clipBottom: number;
147
+ };
148
+ /**
149
+ * The body cell at a point in host coordinates, clamped to the body (a point above the body = row 0, right of the
150
+ * columns = the last column …) – computed, not read from the DOM.
151
+ *
152
+ * @param {number} x - x relative to the host's padding box
153
+ * @param {number} y - y relative to the host's padding box
154
+ * @returns {[number, number]} row and column index, `[-1, -1]` without rows or columns
155
+ * @since 1.1.96
156
+ */
157
+ getBodyCellAtHostPoint(x: number, y: number): [number, number];
158
+ /**
159
+ * Scroll bar pixels per content pixel: 1, below 1 for a capped scroll height ({@link isScrollHeightCapped}).
160
+ *
161
+ * @returns {number} the factor for `scrollTop` changes
162
+ * @since 1.1.95
163
+ */
164
+ getScrollerToContentRatioY(): number;
89
165
  isEditing(): boolean;
90
166
  /**
91
167
  * Resets the editor renderer by clearing its values and state.
@@ -193,6 +269,11 @@ export declare class RenderScope extends EleScope {
193
269
  * @returns {void}
194
270
  */
195
271
  updateCells(events: TableCellUpdateEventIf[], repaintAll?: boolean): void;
272
+ /**
273
+ * After `updateCells()` without a repaint: draws the rendered cells of calculated and „Show values as“ columns of
274
+ * the body again (they depend on the changed cells, e.g. `total = price * quantity` or a share of the total).
275
+ */
276
+ protected rerenderCalculatedCells(): void;
196
277
  /**
197
278
  * After `updateCells()` without a repaint: draws the rendered aggregate cells of the group rows of a row grouping
198
279
  * again (they follow the changed rows; labels and counts don't change – a moved row repaints the whole table).
@@ -6,5 +6,5 @@ import { RendererCleanupFnType } from '../renderer-cleanup-fn.type.js';
6
6
 
7
7
  /** @category Renderers & editing */
8
8
  export declare class InputCellRenderer implements CellRendererIf {
9
- render(cellDiv: HTMLDivElement, rowIndex: number, columnIndex: number, areaIdent: AreaIdent, areaModel: AreaModelIf, _cellValue: any, domService: DomServiceIf): RendererCleanupFnType | undefined;
9
+ render(cellDiv: HTMLDivElement, rowIndex: number, columnIndex: number, areaIdent: AreaIdent, areaModel: AreaModelIf, cellValue: any, domService: DomServiceIf): RendererCleanupFnType | undefined;
10
10
  }
@@ -10,5 +10,5 @@ export declare class SelectCellRenderer implements CellRendererIf {
10
10
  protected options: ValueLabelIf[];
11
11
  constructor(options: ValueLabelIf[]);
12
12
  static create(values: string[]): SelectCellRenderer;
13
- render(cellDiv: HTMLDivElement, rowIndex: number, columnIndex: number, areaIdent: AreaIdent, areaModel: AreaModelIf, _cellValue: any, domService: DomServiceIf): RendererCleanupFnType | undefined;
13
+ render(cellDiv: HTMLDivElement, rowIndex: number, columnIndex: number, areaIdent: AreaIdent, areaModel: AreaModelIf, cellValue: any, domService: DomServiceIf): RendererCleanupFnType | undefined;
14
14
  }