@alaarab/ogrid-core 2.2.0 → 2.3.0
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/dist/esm/index.js +3404 -16
- package/dist/types/formula/cellAddressUtils.d.ts +50 -0
- package/dist/types/formula/dependencyGraph.d.ts +72 -0
- package/dist/types/formula/errors.d.ts +15 -0
- package/dist/types/formula/evaluator.d.ts +25 -0
- package/dist/types/formula/formulaEngine.d.ts +104 -0
- package/dist/types/formula/functions/date.d.ts +2 -0
- package/dist/types/formula/functions/index.d.ts +2 -0
- package/dist/types/formula/functions/info.d.ts +2 -0
- package/dist/types/formula/functions/logical.d.ts +2 -0
- package/dist/types/formula/functions/lookup.d.ts +2 -0
- package/dist/types/formula/functions/math.d.ts +2 -0
- package/dist/types/formula/functions/stats.d.ts +2 -0
- package/dist/types/formula/functions/text.d.ts +2 -0
- package/dist/types/formula/index.d.ts +13 -0
- package/dist/types/formula/parser.d.ts +26 -0
- package/dist/types/formula/tokenizer.d.ts +7 -0
- package/dist/types/formula/types.d.ts +139 -0
- package/dist/types/index.d.ts +5 -1
- package/dist/types/types/columnTypes.d.ts +2 -0
- package/dist/types/utils/cellReference.d.ts +21 -0
- package/dist/types/utils/clipboardHelpers.d.ts +18 -2
- package/dist/types/utils/dataGridViewModel.d.ts +2 -1
- package/dist/types/utils/exportToCsv.d.ts +10 -2
- package/dist/types/utils/fillHelpers.d.ts +18 -1
- package/dist/types/utils/index.d.ts +3 -1
- package/package.json +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell address parsing and formatting utilities for the formula system.
|
|
3
|
+
* Extends the existing cellReference.ts with reverse parsing and absolute reference support.
|
|
4
|
+
*/
|
|
5
|
+
import type { ICellAddress, ICellRange, CellKey } from './types';
|
|
6
|
+
/**
|
|
7
|
+
* Parse a column letter string to a 0-based index.
|
|
8
|
+
* @example columnLetterToIndex('A') // 0
|
|
9
|
+
* @example columnLetterToIndex('Z') // 25
|
|
10
|
+
* @example columnLetterToIndex('AA') // 26
|
|
11
|
+
* @example columnLetterToIndex('AZ') // 51
|
|
12
|
+
*/
|
|
13
|
+
export declare function columnLetterToIndex(letters: string): number;
|
|
14
|
+
/**
|
|
15
|
+
* Parse a cell reference string like "A1", "$B$2", "$A1", "A$1".
|
|
16
|
+
* Returns null on invalid input.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseCellRef(ref: string): ICellAddress | null;
|
|
19
|
+
/**
|
|
20
|
+
* Parse a range string like "A1:B10".
|
|
21
|
+
* Returns null on invalid input.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseRange(rangeStr: string): ICellRange | null;
|
|
24
|
+
/**
|
|
25
|
+
* Convert a cell address back to a display string like "A1", "$A$1", or "Sheet2!A1".
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatAddress(addr: ICellAddress): string;
|
|
28
|
+
/**
|
|
29
|
+
* Adjusts relative cell references in a formula string by a row/column delta.
|
|
30
|
+
* Absolute references ($A$1) are not adjusted. Mixed refs ($A1, A$1) adjust only the relative part.
|
|
31
|
+
*
|
|
32
|
+
* @param formula The formula string (e.g. "=A1+B1")
|
|
33
|
+
* @param colDelta Column offset to apply to relative column references
|
|
34
|
+
* @param rowDelta Row offset to apply to relative row references
|
|
35
|
+
* @returns The adjusted formula string. Out-of-bounds references become "#REF!".
|
|
36
|
+
*/
|
|
37
|
+
export declare function adjustFormulaReferences(formula: string, colDelta: number, rowDelta: number): string;
|
|
38
|
+
/**
|
|
39
|
+
* Convert (col, row) to a CellKey for Map storage.
|
|
40
|
+
* When sheet is specified: "sheetName:col,row". Otherwise: "col,row".
|
|
41
|
+
*/
|
|
42
|
+
export declare function toCellKey(col: number, row: number, sheet?: string): CellKey;
|
|
43
|
+
/**
|
|
44
|
+
* Parse a CellKey back to (col, row) and optional sheet.
|
|
45
|
+
*/
|
|
46
|
+
export declare function fromCellKey(key: CellKey): {
|
|
47
|
+
col: number;
|
|
48
|
+
row: number;
|
|
49
|
+
sheet?: string;
|
|
50
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { CellKey } from './types';
|
|
2
|
+
export declare class DependencyGraph {
|
|
3
|
+
/** cell -> set of cells it depends on (references in its formula) */
|
|
4
|
+
private dependencies;
|
|
5
|
+
/** cell -> set of cells that depend on it (reverse index) */
|
|
6
|
+
private dependents;
|
|
7
|
+
/**
|
|
8
|
+
* Set the dependencies for a cell, replacing any previous ones.
|
|
9
|
+
* Updates both the forward (dependencies) and reverse (dependents) maps.
|
|
10
|
+
*/
|
|
11
|
+
setDependencies(cell: CellKey, deps: Set<CellKey>): void;
|
|
12
|
+
/**
|
|
13
|
+
* Remove all dependency information for a cell from both maps.
|
|
14
|
+
*/
|
|
15
|
+
removeDependencies(cell: CellKey): void;
|
|
16
|
+
/**
|
|
17
|
+
* Get all cells that directly or transitively depend on `changedCell`,
|
|
18
|
+
* returned in topological order (a cell appears AFTER all cells it depends on).
|
|
19
|
+
*
|
|
20
|
+
* Uses Kahn's algorithm. If a cycle is detected, cycle participants are
|
|
21
|
+
* appended at the end (the engine will assign #CIRC! to them).
|
|
22
|
+
*/
|
|
23
|
+
getRecalcOrder(changedCell: CellKey): CellKey[];
|
|
24
|
+
/**
|
|
25
|
+
* Same as getRecalcOrder but for multiple changed cells.
|
|
26
|
+
* Union of all transitive dependents, topologically sorted.
|
|
27
|
+
*/
|
|
28
|
+
getRecalcOrderBatch(changedCells: CellKey[]): CellKey[];
|
|
29
|
+
/**
|
|
30
|
+
* Check if adding dependencies from `cell` to `deps` would create a cycle.
|
|
31
|
+
* DFS from each dep: if we can reach `cell`, it would create a cycle.
|
|
32
|
+
*/
|
|
33
|
+
wouldCreateCycle(cell: CellKey, deps: Set<CellKey>): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Return direct dependents of a cell (cells whose formulas reference this cell).
|
|
36
|
+
* Returns an empty set if none.
|
|
37
|
+
*/
|
|
38
|
+
getDependents(cell: CellKey): ReadonlySet<CellKey>;
|
|
39
|
+
/**
|
|
40
|
+
* Return direct dependencies of a cell (cells referenced in this cell's formula).
|
|
41
|
+
* Returns an empty set if none.
|
|
42
|
+
*/
|
|
43
|
+
getDependencies(cell: CellKey): ReadonlySet<CellKey>;
|
|
44
|
+
/**
|
|
45
|
+
* Clear both maps entirely.
|
|
46
|
+
*/
|
|
47
|
+
clear(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Remove `cell` from the forward dependencies map and clean up reverse
|
|
50
|
+
* references in the dependents map.
|
|
51
|
+
*/
|
|
52
|
+
private removeDependenciesInternal;
|
|
53
|
+
/**
|
|
54
|
+
* Iterative DFS: check if `target` is reachable from `start` by following
|
|
55
|
+
* the dependency chain. Iterative to avoid stack overflow for deep chains.
|
|
56
|
+
*/
|
|
57
|
+
private canReach;
|
|
58
|
+
/**
|
|
59
|
+
* Topological sort using Kahn's algorithm.
|
|
60
|
+
*
|
|
61
|
+
* 1. Collect all cells transitively dependent on the changed cell(s).
|
|
62
|
+
* 2. Build in-degree map for these cells (count how many of their
|
|
63
|
+
* dependencies are in the affected set).
|
|
64
|
+
* 3. Start with cells whose in-degree is 0 (only depend on unaffected
|
|
65
|
+
* cells or the changed cells themselves).
|
|
66
|
+
* 4. Process queue: for each cell, reduce in-degree of its dependents,
|
|
67
|
+
* add to queue when in-degree reaches 0.
|
|
68
|
+
* 5. If any cells remain unprocessed, they're in a cycle — append them
|
|
69
|
+
* at the end (engine marks as #CIRC!).
|
|
70
|
+
*/
|
|
71
|
+
private topologicalSort;
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formula error constants for convenient usage.
|
|
3
|
+
*/
|
|
4
|
+
import { FormulaError } from './types';
|
|
5
|
+
import type { FormulaErrorType } from './types';
|
|
6
|
+
export { FormulaError, type FormulaErrorType };
|
|
7
|
+
export declare const REF_ERROR: FormulaError;
|
|
8
|
+
export declare const DIV_ZERO_ERROR: FormulaError;
|
|
9
|
+
export declare const VALUE_ERROR: FormulaError;
|
|
10
|
+
export declare const NAME_ERROR: FormulaError;
|
|
11
|
+
export declare const CIRC_ERROR: FormulaError;
|
|
12
|
+
export declare const GENERAL_ERROR: FormulaError;
|
|
13
|
+
export declare const NA_ERROR: FormulaError;
|
|
14
|
+
/** Check if a value is a FormulaError instance. */
|
|
15
|
+
export declare function isFormulaError(value: unknown): value is FormulaError;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formula evaluator — walks an AST and computes the result.
|
|
3
|
+
*/
|
|
4
|
+
import type { ASTNode, IFormulaContext, IEvaluator, IFormulaFunction } from './types';
|
|
5
|
+
import { FormulaError } from './types';
|
|
6
|
+
/** Coerce a value to number following Excel semantics. */
|
|
7
|
+
export declare function toNumber(val: unknown): number | FormulaError;
|
|
8
|
+
/** Coerce a value to string. */
|
|
9
|
+
export declare function toString(val: unknown): string;
|
|
10
|
+
/** Coerce a value to boolean following Excel semantics. */
|
|
11
|
+
export declare function toBoolean(val: unknown): boolean;
|
|
12
|
+
/** Evaluate each arg, expanding ranges into flat arrays. */
|
|
13
|
+
export declare function flattenArgs(args: ASTNode[], context: IFormulaContext, evaluator: IEvaluator): unknown[];
|
|
14
|
+
export declare class FormulaEvaluator implements IEvaluator {
|
|
15
|
+
private functions;
|
|
16
|
+
constructor(builtInFunctions: Map<string, IFormulaFunction>);
|
|
17
|
+
registerFunction(name: string, fn: IFormulaFunction): void;
|
|
18
|
+
evaluate(node: ASTNode, context: IFormulaContext): unknown;
|
|
19
|
+
private evaluateFunction;
|
|
20
|
+
private evaluateBinaryOp;
|
|
21
|
+
private evaluateUnaryOp;
|
|
22
|
+
private compare;
|
|
23
|
+
private numCompare;
|
|
24
|
+
private strCompare;
|
|
25
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FormulaEngine — orchestrates parser, evaluator, dependency graph, and formula storage.
|
|
3
|
+
*/
|
|
4
|
+
import type { IFormulaEngineConfig, IRecalcResult, IFormulaFunction, IGridDataAccessor, IAuditEntry, IAuditTrail } from './types';
|
|
5
|
+
export declare class FormulaEngine {
|
|
6
|
+
private readonly formulas;
|
|
7
|
+
private readonly parsedFormulas;
|
|
8
|
+
private readonly values;
|
|
9
|
+
private readonly depGraph;
|
|
10
|
+
private readonly evaluator;
|
|
11
|
+
private readonly maxChainLength;
|
|
12
|
+
private readonly namedRanges;
|
|
13
|
+
private readonly sheetAccessors;
|
|
14
|
+
constructor(config?: IFormulaEngineConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Set or clear a formula for a cell.
|
|
17
|
+
*/
|
|
18
|
+
setFormula(col: number, row: number, formula: string | null, accessor: IGridDataAccessor): IRecalcResult;
|
|
19
|
+
/**
|
|
20
|
+
* Notify the engine that a non-formula cell's value changed.
|
|
21
|
+
*/
|
|
22
|
+
onCellChanged(col: number, row: number, accessor: IGridDataAccessor): IRecalcResult;
|
|
23
|
+
/**
|
|
24
|
+
* Batch notify: multiple cells changed.
|
|
25
|
+
*/
|
|
26
|
+
onCellsChanged(cells: Array<{
|
|
27
|
+
col: number;
|
|
28
|
+
row: number;
|
|
29
|
+
}>, accessor: IGridDataAccessor): IRecalcResult;
|
|
30
|
+
/**
|
|
31
|
+
* Get the current computed value for a cell.
|
|
32
|
+
*/
|
|
33
|
+
getValue(col: number, row: number): unknown | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Get the formula string for a cell.
|
|
36
|
+
*/
|
|
37
|
+
getFormula(col: number, row: number): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Check if a cell has a formula.
|
|
40
|
+
*/
|
|
41
|
+
hasFormula(col: number, row: number): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Register a custom function at runtime.
|
|
44
|
+
*/
|
|
45
|
+
registerFunction(name: string, fn: IFormulaFunction): void;
|
|
46
|
+
/**
|
|
47
|
+
* Full recalculation of all formulas.
|
|
48
|
+
*/
|
|
49
|
+
recalcAll(accessor: IGridDataAccessor): IRecalcResult;
|
|
50
|
+
/**
|
|
51
|
+
* Clear all formulas and cached values.
|
|
52
|
+
*/
|
|
53
|
+
clear(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Get all formula entries for serialization.
|
|
56
|
+
*/
|
|
57
|
+
getAllFormulas(): Array<{
|
|
58
|
+
col: number;
|
|
59
|
+
row: number;
|
|
60
|
+
formula: string;
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* Bulk-load formulas. Recalculates everything.
|
|
64
|
+
*/
|
|
65
|
+
loadFormulas(formulas: Array<{
|
|
66
|
+
col: number;
|
|
67
|
+
row: number;
|
|
68
|
+
formula: string;
|
|
69
|
+
}>, accessor: IGridDataAccessor): IRecalcResult;
|
|
70
|
+
/**
|
|
71
|
+
* Define a named range (e.g. "Revenue" → "A1:A10").
|
|
72
|
+
*/
|
|
73
|
+
defineNamedRange(name: string, ref: string): void;
|
|
74
|
+
/**
|
|
75
|
+
* Remove a named range by name.
|
|
76
|
+
*/
|
|
77
|
+
removeNamedRange(name: string): void;
|
|
78
|
+
/**
|
|
79
|
+
* Get all named ranges as a Map (name → ref).
|
|
80
|
+
*/
|
|
81
|
+
getNamedRanges(): ReadonlyMap<string, string>;
|
|
82
|
+
/**
|
|
83
|
+
* Register a data accessor for a named sheet (for cross-sheet references).
|
|
84
|
+
*/
|
|
85
|
+
registerSheet(name: string, accessor: IGridDataAccessor): void;
|
|
86
|
+
/**
|
|
87
|
+
* Unregister a sheet accessor.
|
|
88
|
+
*/
|
|
89
|
+
unregisterSheet(name: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Get all cells that a cell depends on (deep, transitive precedents).
|
|
92
|
+
*/
|
|
93
|
+
getPrecedents(col: number, row: number): IAuditEntry[];
|
|
94
|
+
/**
|
|
95
|
+
* Get all cells that depend on this cell (deep, transitive dependents).
|
|
96
|
+
*/
|
|
97
|
+
getDependents(col: number, row: number): IAuditEntry[];
|
|
98
|
+
/**
|
|
99
|
+
* Get a full audit trail for a cell: target + precedents + dependents.
|
|
100
|
+
*/
|
|
101
|
+
getAuditTrail(col: number, row: number): IAuditTrail;
|
|
102
|
+
private createContext;
|
|
103
|
+
private recalcCells;
|
|
104
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formula system — barrel export.
|
|
3
|
+
*/
|
|
4
|
+
export type { ICellAddress, ICellRange, CellKey, FormulaErrorType, TokenType, Token, ASTNode, NumberLiteral, StringLiteral, BooleanLiteral, CellRefNode, RangeNode, FunctionCallNode, BinaryOp, BinaryOpNode, UnaryOpNode, ErrorNode, IFormulaContext, IFormulaFunction, IEvaluator, IRecalcResult, IFormulaEngineConfig, IGridDataAccessor, INamedRange, IAuditEntry, IAuditTrail, } from './types';
|
|
5
|
+
export { FormulaError } from './types';
|
|
6
|
+
export { REF_ERROR, DIV_ZERO_ERROR, VALUE_ERROR, NAME_ERROR, CIRC_ERROR, GENERAL_ERROR, NA_ERROR, isFormulaError, } from './errors';
|
|
7
|
+
export { columnLetterToIndex, parseCellRef, parseRange, formatAddress, toCellKey, fromCellKey, adjustFormulaReferences, } from './cellAddressUtils';
|
|
8
|
+
export { tokenize } from './tokenizer';
|
|
9
|
+
export { parse } from './parser';
|
|
10
|
+
export { FormulaEvaluator, toNumber, toString, toBoolean, flattenArgs, } from './evaluator';
|
|
11
|
+
export { DependencyGraph } from './dependencyGraph';
|
|
12
|
+
export { FormulaEngine } from './formulaEngine';
|
|
13
|
+
export { createBuiltInFunctions } from './functions';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursive descent parser: converts Token[] to an ASTNode.
|
|
3
|
+
*
|
|
4
|
+
* Grammar (precedence low → high):
|
|
5
|
+
* expression → comparison
|
|
6
|
+
* comparison → concat (('>' | '<' | '>=' | '<=' | '=' | '<>') concat)*
|
|
7
|
+
* concat → addition ('&' addition)*
|
|
8
|
+
* addition → multiplication (('+' | '-') multiplication)*
|
|
9
|
+
* multiplication → power (('*' | '/') power)*
|
|
10
|
+
* power → unary ('^' unary)*
|
|
11
|
+
* unary → ('-' | '+') unary | postfix
|
|
12
|
+
* postfix → primary '%'?
|
|
13
|
+
* primary → NUMBER | STRING | BOOLEAN | cellRefOrRange | functionCall
|
|
14
|
+
* | '(' expression ')'
|
|
15
|
+
* cellRefOrRange → CELL_REF (':' CELL_REF)?
|
|
16
|
+
* functionCall → FUNCTION '(' (expression (',' expression)*)? ')'
|
|
17
|
+
*/
|
|
18
|
+
import type { Token, ASTNode } from './types';
|
|
19
|
+
/**
|
|
20
|
+
* Parse an array of tokens into an AST.
|
|
21
|
+
* Never throws — returns an ErrorNode on parse errors.
|
|
22
|
+
*
|
|
23
|
+
* @param tokens - The token array from the tokenizer.
|
|
24
|
+
* @param namedRanges - Optional map of named ranges (name → ref string like "A1:B10").
|
|
25
|
+
*/
|
|
26
|
+
export declare function parse(tokens: Token[], namedRanges?: Map<string, string>): ASTNode;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Token } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Tokenizes a formula string (without the leading '=') into an array of tokens.
|
|
4
|
+
*
|
|
5
|
+
* This is a single-pass character-at-a-time lexer for spreadsheet formulas.
|
|
6
|
+
*/
|
|
7
|
+
export declare function tokenize(input: string): Token[];
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formula system type definitions.
|
|
3
|
+
*/
|
|
4
|
+
/** A parsed cell address. Row and column are 0-based internally. */
|
|
5
|
+
export interface ICellAddress {
|
|
6
|
+
col: number;
|
|
7
|
+
row: number;
|
|
8
|
+
absCol: boolean;
|
|
9
|
+
absRow: boolean;
|
|
10
|
+
/** Sheet name for cross-sheet references. Undefined = current sheet. */
|
|
11
|
+
sheet?: string;
|
|
12
|
+
}
|
|
13
|
+
/** A rectangular range of cells. */
|
|
14
|
+
export interface ICellRange {
|
|
15
|
+
start: ICellAddress;
|
|
16
|
+
end: ICellAddress;
|
|
17
|
+
}
|
|
18
|
+
/** String key for a cell: "col,row" for internal Map storage. */
|
|
19
|
+
export type CellKey = string;
|
|
20
|
+
export type FormulaErrorType = '#REF!' | '#DIV/0!' | '#VALUE!' | '#NAME?' | '#CIRC!' | '#ERROR!' | '#N/A' | '#NUM!';
|
|
21
|
+
export declare class FormulaError {
|
|
22
|
+
readonly type: FormulaErrorType;
|
|
23
|
+
readonly message?: string | undefined;
|
|
24
|
+
constructor(type: FormulaErrorType, message?: string | undefined);
|
|
25
|
+
toString(): string;
|
|
26
|
+
}
|
|
27
|
+
export type TokenType = 'NUMBER' | 'STRING' | 'BOOLEAN' | 'CELL_REF' | 'FUNCTION' | 'IDENTIFIER' | 'SHEET_REF' | 'LPAREN' | 'RPAREN' | 'COMMA' | 'COLON' | 'PLUS' | 'MINUS' | 'MULTIPLY' | 'DIVIDE' | 'POWER' | 'PERCENT' | 'AMPERSAND' | 'GT' | 'LT' | 'GTE' | 'LTE' | 'EQ' | 'NEQ' | 'EOF';
|
|
28
|
+
export interface Token {
|
|
29
|
+
type: TokenType;
|
|
30
|
+
value: string;
|
|
31
|
+
position: number;
|
|
32
|
+
}
|
|
33
|
+
export type ASTNode = NumberLiteral | StringLiteral | BooleanLiteral | CellRefNode | RangeNode | FunctionCallNode | BinaryOpNode | UnaryOpNode | ErrorNode;
|
|
34
|
+
export interface NumberLiteral {
|
|
35
|
+
kind: 'number';
|
|
36
|
+
value: number;
|
|
37
|
+
}
|
|
38
|
+
export interface StringLiteral {
|
|
39
|
+
kind: 'string';
|
|
40
|
+
value: string;
|
|
41
|
+
}
|
|
42
|
+
export interface BooleanLiteral {
|
|
43
|
+
kind: 'boolean';
|
|
44
|
+
value: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface CellRefNode {
|
|
47
|
+
kind: 'cellRef';
|
|
48
|
+
address: ICellAddress;
|
|
49
|
+
raw: string;
|
|
50
|
+
}
|
|
51
|
+
export interface RangeNode {
|
|
52
|
+
kind: 'range';
|
|
53
|
+
start: ICellAddress;
|
|
54
|
+
end: ICellAddress;
|
|
55
|
+
raw: string;
|
|
56
|
+
}
|
|
57
|
+
export interface FunctionCallNode {
|
|
58
|
+
kind: 'functionCall';
|
|
59
|
+
name: string;
|
|
60
|
+
args: ASTNode[];
|
|
61
|
+
}
|
|
62
|
+
export type BinaryOp = '+' | '-' | '*' | '/' | '^' | '%' | '&' | '>' | '<' | '>=' | '<=' | '=' | '<>';
|
|
63
|
+
export interface BinaryOpNode {
|
|
64
|
+
kind: 'binaryOp';
|
|
65
|
+
op: BinaryOp;
|
|
66
|
+
left: ASTNode;
|
|
67
|
+
right: ASTNode;
|
|
68
|
+
}
|
|
69
|
+
export interface UnaryOpNode {
|
|
70
|
+
kind: 'unaryOp';
|
|
71
|
+
op: '+' | '-';
|
|
72
|
+
operand: ASTNode;
|
|
73
|
+
}
|
|
74
|
+
export interface ErrorNode {
|
|
75
|
+
kind: 'error';
|
|
76
|
+
error: FormulaError;
|
|
77
|
+
}
|
|
78
|
+
/** Context passed to formula functions during evaluation. */
|
|
79
|
+
export interface IFormulaContext {
|
|
80
|
+
getCellValue(address: ICellAddress): unknown;
|
|
81
|
+
getRangeValues(range: ICellRange): unknown[][];
|
|
82
|
+
now(): Date;
|
|
83
|
+
}
|
|
84
|
+
/** A registered formula function. */
|
|
85
|
+
export interface IFormulaFunction {
|
|
86
|
+
minArgs: number;
|
|
87
|
+
maxArgs: number;
|
|
88
|
+
/** Functions receive raw AST nodes so they can handle ranges specially. */
|
|
89
|
+
evaluate(args: ASTNode[], context: IFormulaContext, evaluator: IEvaluator): unknown;
|
|
90
|
+
}
|
|
91
|
+
/** The evaluator interface that functions can call back into. */
|
|
92
|
+
export interface IEvaluator {
|
|
93
|
+
evaluate(node: ASTNode, context: IFormulaContext): unknown;
|
|
94
|
+
}
|
|
95
|
+
/** Result of a cell change: which cells were recalculated. */
|
|
96
|
+
export interface IRecalcResult {
|
|
97
|
+
updatedCells: Array<{
|
|
98
|
+
cellKey: CellKey;
|
|
99
|
+
col: number;
|
|
100
|
+
row: number;
|
|
101
|
+
oldValue: unknown;
|
|
102
|
+
newValue: unknown;
|
|
103
|
+
}>;
|
|
104
|
+
}
|
|
105
|
+
/** Configuration for the FormulaEngine. */
|
|
106
|
+
export interface IFormulaEngineConfig {
|
|
107
|
+
maxChainLength?: number;
|
|
108
|
+
customFunctions?: Record<string, IFormulaFunction>;
|
|
109
|
+
/** Named ranges: name → cell/range reference string (e.g. "A1:B10"). */
|
|
110
|
+
namedRanges?: Record<string, string>;
|
|
111
|
+
}
|
|
112
|
+
/** Grid data accessor — bridge between FormulaEngine and the grid's data model. */
|
|
113
|
+
export interface IGridDataAccessor {
|
|
114
|
+
getCellValue(col: number, row: number): unknown;
|
|
115
|
+
getRowCount(): number;
|
|
116
|
+
getColumnCount(): number;
|
|
117
|
+
}
|
|
118
|
+
/** A named range definition. */
|
|
119
|
+
export interface INamedRange {
|
|
120
|
+
name: string;
|
|
121
|
+
/** Cell or range reference string, e.g. "A1" or "A1:B10". */
|
|
122
|
+
ref: string;
|
|
123
|
+
}
|
|
124
|
+
/** A single cell entry in an audit trail. */
|
|
125
|
+
export interface IAuditEntry {
|
|
126
|
+
cellKey: CellKey;
|
|
127
|
+
col: number;
|
|
128
|
+
row: number;
|
|
129
|
+
formula?: string;
|
|
130
|
+
value: unknown;
|
|
131
|
+
}
|
|
132
|
+
/** Full audit trail for a cell: its precedents and dependents. */
|
|
133
|
+
export interface IAuditTrail {
|
|
134
|
+
target: IAuditEntry;
|
|
135
|
+
/** All cells that this cell depends on (deep, transitive). */
|
|
136
|
+
precedents: IAuditEntry[];
|
|
137
|
+
/** All cells that depend on this cell (deep, transitive). */
|
|
138
|
+
dependents: IAuditEntry[];
|
|
139
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type { ColumnFilterType, IDateFilterValue, IColumnFilterDef, IColumnMeta,
|
|
|
2
2
|
export type { RowId, UserLike, UserLikeInput, FilterValue, IFilters, IFetchParams, IPageResult, IDataSource, IGridColumnState, RowSelectionMode, IRowSelectionChangeEvent, StatusBarPanel, IStatusBarProps, IActiveCell, ISelectionRange, SideBarPanelId, ISideBarDef, IVirtualScrollConfig, IColumnReorderConfig, IOGridApi, } from './types';
|
|
3
3
|
export { toUserLike, isInSelectionRange, normalizeSelectionRange, } from './types';
|
|
4
4
|
export { escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, } from './utils';
|
|
5
|
-
export type { CsvColumn } from './utils';
|
|
5
|
+
export type { CsvColumn, FormulaExportOptions } from './utils';
|
|
6
6
|
export { getCellValue, isColumnEditable } from './utils';
|
|
7
7
|
export { flattenColumns, buildHeaderRows } from './utils';
|
|
8
8
|
export { isFilterConfig, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, } from './utils';
|
|
@@ -39,9 +39,13 @@ export type { ArrowNavigationContext, ArrowNavigationResult } from './utils';
|
|
|
39
39
|
export { rangesEqual, clampSelectionToBounds, computeAutoScrollSpeed, applyRangeRowSelection, computeRowSelectionState } from './utils';
|
|
40
40
|
export { formatCellValueForTsv, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear, } from './utils';
|
|
41
41
|
export { applyFillValues } from './utils';
|
|
42
|
+
export type { IFillFormulaOptions } from './utils';
|
|
42
43
|
export { UndoRedoStack } from './utils';
|
|
43
44
|
export { validateColumns, validateRowIds, validateVirtualScrollConfig } from './utils';
|
|
45
|
+
export { indexToColumnLetter, formatCellReference } from './utils';
|
|
44
46
|
export { CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, GRID_BORDER_RADIUS, } from './constants';
|
|
45
47
|
export { DEFAULT_DEBOUNCE_MS, PEOPLE_SEARCH_DEBOUNCE_MS, SIDEBAR_TRANSITION_MS, } from './constants';
|
|
46
48
|
export { Z_INDEX } from './constants';
|
|
47
49
|
export type { ZIndexKey } from './constants';
|
|
50
|
+
export { FormulaError, FormulaEngine, FormulaEvaluator, DependencyGraph, tokenize, parse, createBuiltInFunctions, columnLetterToIndex, parseCellRef, parseRange, formatAddress, toCellKey, fromCellKey, adjustFormulaReferences, toNumber, toString as formulaToString, toBoolean, flattenArgs, isFormulaError, REF_ERROR, DIV_ZERO_ERROR, VALUE_ERROR, NAME_ERROR, CIRC_ERROR, GENERAL_ERROR, NA_ERROR, } from './formula';
|
|
51
|
+
export type { ICellAddress, ICellRange, CellKey, FormulaErrorType, TokenType, Token, ASTNode, BinaryOp, IFormulaContext, IFormulaFunction, IEvaluator, IRecalcResult, IFormulaEngineConfig, IGridDataAccessor, INamedRange, IAuditEntry, IAuditTrail, } from './formula';
|
|
@@ -69,6 +69,8 @@ export interface ICellValueChangedEvent<T> {
|
|
|
69
69
|
oldValue: unknown;
|
|
70
70
|
newValue: unknown;
|
|
71
71
|
rowIndex: number;
|
|
72
|
+
/** True when the newValue was produced by the formula engine (not a direct user edit). */
|
|
73
|
+
isFormulaResult?: boolean;
|
|
72
74
|
}
|
|
73
75
|
/** Props passed to custom cell editor components. */
|
|
74
76
|
export interface ICellEditorProps<T> {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel-style cell reference utilities.
|
|
3
|
+
*
|
|
4
|
+
* Column letters use base-26 encoding: A–Z, AA–AZ, BA–BZ, …
|
|
5
|
+
* Row numbers are 1-based.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Convert a 0-based column index to an Excel-style column letter.
|
|
9
|
+
* @example indexToColumnLetter(0) // 'A'
|
|
10
|
+
* @example indexToColumnLetter(25) // 'Z'
|
|
11
|
+
* @example indexToColumnLetter(26) // 'AA'
|
|
12
|
+
* @example indexToColumnLetter(702) // 'AAA'
|
|
13
|
+
*/
|
|
14
|
+
export declare function indexToColumnLetter(index: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* Format a cell reference string from a 0-based column index and a 1-based row number.
|
|
17
|
+
* @example formatCellReference(0, 1) // 'A1'
|
|
18
|
+
* @example formatCellReference(2, 15) // 'C15'
|
|
19
|
+
* @example formatCellReference(26, 100) // 'AA100'
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatCellReference(colIndex: number, rowNumber: number): string;
|
|
@@ -20,9 +20,17 @@ export declare function formatCellValueForTsv(raw: unknown, formatted: unknown):
|
|
|
20
20
|
* @param items Flat array of all row data objects.
|
|
21
21
|
* @param visibleCols Visible column definitions.
|
|
22
22
|
* @param range The selection range to serialize (will be normalized).
|
|
23
|
+
* @param formulaOptions Optional formula-aware options. When provided, cells with
|
|
24
|
+
* formulas will have their formula string copied instead of
|
|
25
|
+
* the computed value.
|
|
23
26
|
* @returns TSV string with rows separated by \\r\\n and columns by \\t.
|
|
24
27
|
*/
|
|
25
|
-
export declare function formatSelectionAsTsv<T>(items: T[], visibleCols: IColumnDef<T>[], range: ISelectionRange
|
|
28
|
+
export declare function formatSelectionAsTsv<T>(items: T[], visibleCols: IColumnDef<T>[], range: ISelectionRange, formulaOptions?: {
|
|
29
|
+
colOffset: number;
|
|
30
|
+
flatColumns: IColumnDef<T>[];
|
|
31
|
+
getFormula?: (col: number, row: number) => string | undefined;
|
|
32
|
+
hasFormula?: (col: number, row: number) => boolean;
|
|
33
|
+
}): string;
|
|
26
34
|
/**
|
|
27
35
|
* Parse a TSV clipboard string into a 2D array of cell strings.
|
|
28
36
|
* Handles both \\r\\n and \\n line endings. Ignores trailing empty lines.
|
|
@@ -36,14 +44,22 @@ export declare function parseTsvClipboard(text: string): string[][];
|
|
|
36
44
|
* For each cell in the parsed rows, validates editability, parses the value,
|
|
37
45
|
* and produces a cell value changed event.
|
|
38
46
|
*
|
|
47
|
+
* When `formulaOptions` is provided, cells whose pasted text starts with "="
|
|
48
|
+
* are routed through `setFormula` instead of the normal value parse path.
|
|
49
|
+
*
|
|
39
50
|
* @param parsedRows 2D array of string values (from parseTsvClipboard).
|
|
40
51
|
* @param anchorRow Target starting row index.
|
|
41
52
|
* @param anchorCol Target starting column index (data column, not absolute).
|
|
42
53
|
* @param items Array of all row data objects.
|
|
43
54
|
* @param visibleCols Visible column definitions.
|
|
55
|
+
* @param formulaOptions Optional formula-aware options.
|
|
44
56
|
* @returns Array of cell value changed events to apply.
|
|
45
57
|
*/
|
|
46
|
-
export declare function applyPastedValues<T>(parsedRows: string[][], anchorRow: number, anchorCol: number, items: T[], visibleCols: IColumnDef<T>[]
|
|
58
|
+
export declare function applyPastedValues<T>(parsedRows: string[][], anchorRow: number, anchorCol: number, items: T[], visibleCols: IColumnDef<T>[], formulaOptions?: {
|
|
59
|
+
colOffset: number;
|
|
60
|
+
flatColumns: IColumnDef<T>[];
|
|
61
|
+
setFormula?: (col: number, row: number, formula: string | null) => void;
|
|
62
|
+
}): ICellValueChangedEvent<T>[];
|
|
47
63
|
/**
|
|
48
64
|
* Clear cells in a cut range by setting each editable cell to an empty-string-parsed value.
|
|
49
65
|
* Used after pasting cut content to clear the original cells.
|
|
@@ -181,8 +181,9 @@ export declare function getCellRenderDescriptor<T>(item: T, col: IColumnDef<T>,
|
|
|
181
181
|
export declare function resolveCellDisplayContent<T>(col: IColumnDef<T>, item: T, displayValue: unknown): unknown;
|
|
182
182
|
/**
|
|
183
183
|
* Resolves the cellStyle from a column def, handling both function and static values.
|
|
184
|
+
* When displayValue is a FormulaError, merges red error color styling.
|
|
184
185
|
*/
|
|
185
|
-
export declare function resolveCellStyle<T>(col: IColumnDef<T>, item: T): Record<string, string> | undefined;
|
|
186
|
+
export declare function resolveCellStyle<T>(col: IColumnDef<T>, item: T, displayValue?: unknown): Record<string, string> | undefined;
|
|
186
187
|
/**
|
|
187
188
|
* Builds props for InlineCellEditor. Shared across all UI packages.
|
|
188
189
|
*/
|
|
@@ -4,8 +4,16 @@ export interface CsvColumn {
|
|
|
4
4
|
}
|
|
5
5
|
export declare function escapeCsvValue(value: unknown): string;
|
|
6
6
|
export declare function buildCsvHeader(columns: CsvColumn[]): string;
|
|
7
|
-
export
|
|
8
|
-
|
|
7
|
+
export interface FormulaExportOptions {
|
|
8
|
+
getFormula?: (col: number, row: number) => string | undefined;
|
|
9
|
+
hasFormula?: (col: number, row: number) => boolean;
|
|
10
|
+
/** Map from columnId to flat column index */
|
|
11
|
+
columnIdToIndex?: Map<string, number>;
|
|
12
|
+
/** Export mode: 'values' (default) exports computed results, 'formulas' exports formula strings */
|
|
13
|
+
exportMode?: 'values' | 'formulas';
|
|
14
|
+
}
|
|
15
|
+
export declare function buildCsvRows<T>(items: T[], columns: CsvColumn[], getValue: (item: T, columnId: string) => unknown, formulaOptions?: FormulaExportOptions): string[];
|
|
16
|
+
export declare function exportToCsv<T>(items: T[], columns: CsvColumn[], getValue: (item: T, columnId: string) => unknown, filename?: string, formulaOptions?: FormulaExportOptions): void;
|
|
9
17
|
/**
|
|
10
18
|
* Triggers a browser CSV file download.
|
|
11
19
|
*
|