@alaarab/ogrid-core 2.2.0 → 2.4.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 +5218 -19
- package/dist/types/constants/formulaBar.d.ts +60 -0
- package/dist/types/constants/index.d.ts +1 -0
- 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/financial.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/reference.d.ts +2 -0
- package/dist/types/formula/functions/statistical-extended.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 +141 -0
- package/dist/types/index.d.ts +10 -3
- package/dist/types/types/columnTypes.d.ts +2 -0
- package/dist/types/types/dataGridTypes.d.ts +7 -0
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/utils/cellReference.d.ts +21 -0
- package/dist/types/utils/cellValue.d.ts +6 -0
- package/dist/types/utils/clipboardHelpers.d.ts +18 -2
- package/dist/types/utils/dataGridViewModel.d.ts +8 -1
- package/dist/types/utils/exportToCsv.d.ts +10 -2
- package/dist/types/utils/fillHelpers.d.ts +18 -1
- package/dist/types/utils/formulaBarHelpers.d.ts +40 -0
- package/dist/types/utils/index.d.ts +6 -2
- package/package.json +1 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formula bar and formula reference highlighting constants.
|
|
3
|
+
* Shared across React, Angular, Vue, and JS packages.
|
|
4
|
+
*/
|
|
5
|
+
/** Color palette for formula reference highlights (cycles 0–5). Uses CSS vars with fallbacks. */
|
|
6
|
+
export declare const FORMULA_REF_COLORS: readonly ["var(--ogrid-formula-ref-0, #4285f4)", "var(--ogrid-formula-ref-1, #ea4335)", "var(--ogrid-formula-ref-2, #34a853)", "var(--ogrid-formula-ref-3, #9334e6)", "var(--ogrid-formula-ref-4, #ff6d01)", "var(--ogrid-formula-ref-5, #46bdc6)"];
|
|
7
|
+
/** CSS text for the formula bar container (used by JS and Angular inline styles). */
|
|
8
|
+
export declare const FORMULA_BAR_CSS: {
|
|
9
|
+
readonly bar: "display:flex;align-items:center;border-bottom:1px solid var(--ogrid-border, #e0e0e0);background:var(--ogrid-bg, #fff);min-height:28px;font-size:13px;";
|
|
10
|
+
readonly nameBox: "font-family:monospace;font-size:12px;font-weight:500;padding:2px 8px;border-right:1px solid var(--ogrid-border, #e0e0e0);background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424);min-width:52px;text-align:center;line-height:24px;user-select:none;white-space:nowrap;";
|
|
11
|
+
readonly fxLabel: "padding:2px 8px;font-style:italic;font-weight:600;color:var(--ogrid-muted-fg, #888);user-select:none;border-right:1px solid var(--ogrid-border, #e0e0e0);line-height:24px;font-size:12px;";
|
|
12
|
+
readonly input: "flex:1;border:none;outline:none;padding:2px 8px;font-family:monospace;font-size:12px;line-height:24px;background:transparent;color:var(--ogrid-fg, #242424);min-width:0;";
|
|
13
|
+
};
|
|
14
|
+
/** Style objects for the formula bar — used by React and Vue (CSSProperties-compatible). */
|
|
15
|
+
export declare const FORMULA_BAR_STYLES: {
|
|
16
|
+
readonly bar: {
|
|
17
|
+
readonly display: "flex";
|
|
18
|
+
readonly alignItems: "center";
|
|
19
|
+
readonly borderBottom: "1px solid var(--ogrid-border, #e0e0e0)";
|
|
20
|
+
readonly background: "var(--ogrid-bg, #fff)";
|
|
21
|
+
readonly minHeight: "28px";
|
|
22
|
+
readonly fontSize: "13px";
|
|
23
|
+
};
|
|
24
|
+
readonly nameBox: {
|
|
25
|
+
readonly fontFamily: "monospace";
|
|
26
|
+
readonly fontSize: "12px";
|
|
27
|
+
readonly fontWeight: 500;
|
|
28
|
+
readonly padding: "2px 8px";
|
|
29
|
+
readonly borderRight: "1px solid var(--ogrid-border, #e0e0e0)";
|
|
30
|
+
readonly background: "var(--ogrid-bg, #fff)";
|
|
31
|
+
readonly color: "var(--ogrid-fg, #242424)";
|
|
32
|
+
readonly minWidth: "52px";
|
|
33
|
+
readonly textAlign: "center";
|
|
34
|
+
readonly lineHeight: "24px";
|
|
35
|
+
readonly userSelect: "none";
|
|
36
|
+
readonly whiteSpace: "nowrap";
|
|
37
|
+
};
|
|
38
|
+
readonly fxLabel: {
|
|
39
|
+
readonly padding: "2px 8px";
|
|
40
|
+
readonly fontStyle: "italic";
|
|
41
|
+
readonly fontWeight: 600;
|
|
42
|
+
readonly color: "var(--ogrid-muted-fg, #888)";
|
|
43
|
+
readonly userSelect: "none";
|
|
44
|
+
readonly borderRight: "1px solid var(--ogrid-border, #e0e0e0)";
|
|
45
|
+
readonly lineHeight: "24px";
|
|
46
|
+
readonly fontSize: "12px";
|
|
47
|
+
};
|
|
48
|
+
readonly input: {
|
|
49
|
+
readonly flex: 1;
|
|
50
|
+
readonly border: "none";
|
|
51
|
+
readonly outline: "none";
|
|
52
|
+
readonly padding: "2px 8px";
|
|
53
|
+
readonly fontFamily: "monospace";
|
|
54
|
+
readonly fontSize: "12px";
|
|
55
|
+
readonly lineHeight: "24px";
|
|
56
|
+
readonly background: "transparent";
|
|
57
|
+
readonly color: "var(--ogrid-fg, #242424)";
|
|
58
|
+
readonly minWidth: 0;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -2,3 +2,4 @@ export { CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDT
|
|
|
2
2
|
export { DEFAULT_DEBOUNCE_MS, PEOPLE_SEARCH_DEBOUNCE_MS, SIDEBAR_TRANSITION_MS, } from './timing';
|
|
3
3
|
export { Z_INDEX } from './zIndex';
|
|
4
4
|
export type { ZIndexKey } from './zIndex';
|
|
5
|
+
export { FORMULA_REF_COLORS, FORMULA_BAR_CSS, FORMULA_BAR_STYLES } from './formulaBar';
|
|
@@ -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,141 @@
|
|
|
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
|
+
/** Optional: return the formula string for a cell, or undefined if not a formula cell. */
|
|
84
|
+
getCellFormula?(address: ICellAddress): string | undefined;
|
|
85
|
+
}
|
|
86
|
+
/** A registered formula function. */
|
|
87
|
+
export interface IFormulaFunction {
|
|
88
|
+
minArgs: number;
|
|
89
|
+
maxArgs: number;
|
|
90
|
+
/** Functions receive raw AST nodes so they can handle ranges specially. */
|
|
91
|
+
evaluate(args: ASTNode[], context: IFormulaContext, evaluator: IEvaluator): unknown;
|
|
92
|
+
}
|
|
93
|
+
/** The evaluator interface that functions can call back into. */
|
|
94
|
+
export interface IEvaluator {
|
|
95
|
+
evaluate(node: ASTNode, context: IFormulaContext): unknown;
|
|
96
|
+
}
|
|
97
|
+
/** Result of a cell change: which cells were recalculated. */
|
|
98
|
+
export interface IRecalcResult {
|
|
99
|
+
updatedCells: Array<{
|
|
100
|
+
cellKey: CellKey;
|
|
101
|
+
col: number;
|
|
102
|
+
row: number;
|
|
103
|
+
oldValue: unknown;
|
|
104
|
+
newValue: unknown;
|
|
105
|
+
}>;
|
|
106
|
+
}
|
|
107
|
+
/** Configuration for the FormulaEngine. */
|
|
108
|
+
export interface IFormulaEngineConfig {
|
|
109
|
+
maxChainLength?: number;
|
|
110
|
+
customFunctions?: Record<string, IFormulaFunction>;
|
|
111
|
+
/** Named ranges: name → cell/range reference string (e.g. "A1:B10"). */
|
|
112
|
+
namedRanges?: Record<string, string>;
|
|
113
|
+
}
|
|
114
|
+
/** Grid data accessor — bridge between FormulaEngine and the grid's data model. */
|
|
115
|
+
export interface IGridDataAccessor {
|
|
116
|
+
getCellValue(col: number, row: number): unknown;
|
|
117
|
+
getRowCount(): number;
|
|
118
|
+
getColumnCount(): number;
|
|
119
|
+
}
|
|
120
|
+
/** A named range definition. */
|
|
121
|
+
export interface INamedRange {
|
|
122
|
+
name: string;
|
|
123
|
+
/** Cell or range reference string, e.g. "A1" or "A1:B10". */
|
|
124
|
+
ref: string;
|
|
125
|
+
}
|
|
126
|
+
/** A single cell entry in an audit trail. */
|
|
127
|
+
export interface IAuditEntry {
|
|
128
|
+
cellKey: CellKey;
|
|
129
|
+
col: number;
|
|
130
|
+
row: number;
|
|
131
|
+
formula?: string;
|
|
132
|
+
value: unknown;
|
|
133
|
+
}
|
|
134
|
+
/** Full audit trail for a cell: its precedents and dependents. */
|
|
135
|
+
export interface IAuditTrail {
|
|
136
|
+
target: IAuditEntry;
|
|
137
|
+
/** All cells that this cell depends on (deep, transitive). */
|
|
138
|
+
precedents: IAuditEntry[];
|
|
139
|
+
/** All cells that depend on this cell (deep, transitive). */
|
|
140
|
+
dependents: IAuditEntry[];
|
|
141
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export type { ColumnFilterType, IDateFilterValue, IColumnFilterDef, IColumnMeta, IValueParserParams, IColumnDef, ICellValueChangedEvent, ICellEditorProps, CellEditorParams, IColumnGroupDef, HeaderCell, HeaderRow, IColumnDefinition, } from './types';
|
|
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';
|
|
2
|
+
export type { RowId, UserLike, UserLikeInput, FilterValue, IFilters, IFetchParams, IPageResult, IDataSource, IGridColumnState, RowSelectionMode, IRowSelectionChangeEvent, StatusBarPanel, IStatusBarProps, IActiveCell, ISelectionRange, SideBarPanelId, ISideBarDef, ISheetDef, 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';
|
|
6
|
-
export { getCellValue, isColumnEditable } from './utils';
|
|
5
|
+
export type { CsvColumn, FormulaExportOptions } from './utils';
|
|
6
|
+
export { getCellValue, isColumnEditable, createGridDataAccessor } from './utils';
|
|
7
7
|
export { flattenColumns, buildHeaderRows } from './utils';
|
|
8
8
|
export { isFilterConfig, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, } from './utils';
|
|
9
9
|
export { getStatusBarParts } from './utils';
|
|
@@ -39,9 +39,16 @@ 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';
|
|
46
|
+
export { extractFormulaReferences, processFormulaBarCommit, deriveFormulaBarText, handleFormulaBarKeyDown } from './utils';
|
|
47
|
+
export type { FormulaReference } from './utils';
|
|
44
48
|
export { CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, GRID_BORDER_RADIUS, } from './constants';
|
|
45
49
|
export { DEFAULT_DEBOUNCE_MS, PEOPLE_SEARCH_DEBOUNCE_MS, SIDEBAR_TRANSITION_MS, } from './constants';
|
|
46
50
|
export { Z_INDEX } from './constants';
|
|
47
51
|
export type { ZIndexKey } from './constants';
|
|
52
|
+
export { FORMULA_REF_COLORS, FORMULA_BAR_CSS, FORMULA_BAR_STYLES } from './constants';
|
|
53
|
+
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';
|
|
54
|
+
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> {
|
|
@@ -128,6 +128,13 @@ export interface ISideBarDef {
|
|
|
128
128
|
/** Position of the side bar (default: 'right'). */
|
|
129
129
|
position?: 'left' | 'right';
|
|
130
130
|
}
|
|
131
|
+
/** Definition for a sheet tab. */
|
|
132
|
+
export interface ISheetDef {
|
|
133
|
+
id: string;
|
|
134
|
+
name: string;
|
|
135
|
+
/** Optional tab color (CSS value). */
|
|
136
|
+
color?: string;
|
|
137
|
+
}
|
|
131
138
|
/** Configuration for virtual scrolling. */
|
|
132
139
|
export interface IVirtualScrollConfig {
|
|
133
140
|
/** Enable virtual scrolling (default: false). */
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export type { ColumnFilterType, IDateFilterValue, IColumnFilterDef, IColumnMeta, IValueParserParams, IColumnDef, ICellValueChangedEvent, ICellEditorProps, CellEditorParams, IColumnGroupDef, HeaderCell, HeaderRow, IColumnDefinition, } from './columnTypes';
|
|
2
|
-
export type { RowId, UserLike, UserLikeInput, FilterValue, IFilters, IFetchParams, IPageResult, IDataSource, IGridColumnState, RowSelectionMode, IRowSelectionChangeEvent, StatusBarPanel, IStatusBarProps, IActiveCell, ISelectionRange, SideBarPanelId, ISideBarDef, IVirtualScrollConfig, IColumnReorderConfig, IOGridApi, } from './dataGridTypes';
|
|
2
|
+
export type { RowId, UserLike, UserLikeInput, FilterValue, IFilters, IFetchParams, IPageResult, IDataSource, IGridColumnState, RowSelectionMode, IRowSelectionChangeEvent, StatusBarPanel, IStatusBarProps, IActiveCell, ISelectionRange, SideBarPanelId, ISideBarDef, ISheetDef, IVirtualScrollConfig, IColumnReorderConfig, IOGridApi, } from './dataGridTypes';
|
|
3
3
|
export { toUserLike, isInSelectionRange, normalizeSelectionRange, } from './dataGridTypes';
|