@pixerate/editor 0.19.0 → 0.21.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.
Files changed (112) hide show
  1. package/README.md +95 -4
  2. package/dist/agent/index.cjs +625 -2
  3. package/dist/agent/index.cjs.map +1 -1
  4. package/dist/agent/index.d.cts +286 -2
  5. package/dist/agent/index.d.ts +286 -2
  6. package/dist/agent/index.js +624 -1
  7. package/dist/agent/index.js.map +1 -1
  8. package/dist/canvas/index.cjs +1240 -22
  9. package/dist/canvas/index.cjs.map +1 -1
  10. package/dist/canvas/index.d.cts +515 -3
  11. package/dist/canvas/index.d.ts +515 -3
  12. package/dist/canvas/index.js +1219 -1
  13. package/dist/canvas/index.js.map +1 -1
  14. package/dist/chunk-3TYMNULT.js +1367 -0
  15. package/dist/chunk-3TYMNULT.js.map +1 -0
  16. package/dist/chunk-4QPLEUL2.cjs +4480 -0
  17. package/dist/chunk-4QPLEUL2.cjs.map +1 -0
  18. package/dist/chunk-4SUNJZWB.cjs +553 -0
  19. package/dist/chunk-4SUNJZWB.cjs.map +1 -0
  20. package/dist/chunk-A7DKIA72.js +2657 -0
  21. package/dist/chunk-A7DKIA72.js.map +1 -0
  22. package/dist/chunk-AXV2ZW34.cjs +118 -0
  23. package/dist/chunk-AXV2ZW34.cjs.map +1 -0
  24. package/dist/chunk-B2ZRLN4S.js +118 -0
  25. package/dist/chunk-B2ZRLN4S.js.map +1 -0
  26. package/dist/chunk-CYFJCKC4.js +4480 -0
  27. package/dist/chunk-CYFJCKC4.js.map +1 -0
  28. package/dist/chunk-GVW4P7BG.js +2706 -0
  29. package/dist/chunk-GVW4P7BG.js.map +1 -0
  30. package/dist/chunk-JACER6TE.cjs +1 -0
  31. package/dist/chunk-JACER6TE.cjs.map +1 -0
  32. package/dist/chunk-JYRIOFEN.cjs +2657 -0
  33. package/dist/chunk-JYRIOFEN.cjs.map +1 -0
  34. package/dist/chunk-KYRZDWM4.js +299 -0
  35. package/dist/chunk-KYRZDWM4.js.map +1 -0
  36. package/dist/chunk-LA7PEGU3.cjs +299 -0
  37. package/dist/chunk-LA7PEGU3.cjs.map +1 -0
  38. package/dist/chunk-N7FG6CBO.js +1 -0
  39. package/dist/chunk-N7FG6CBO.js.map +1 -0
  40. package/dist/chunk-OYXSKQFR.js +553 -0
  41. package/dist/chunk-OYXSKQFR.js.map +1 -0
  42. package/dist/chunk-TVRC4KVT.cjs +1367 -0
  43. package/dist/chunk-TVRC4KVT.cjs.map +1 -0
  44. package/dist/chunk-U6NDQFOK.cjs +2706 -0
  45. package/dist/chunk-U6NDQFOK.cjs.map +1 -0
  46. package/dist/controller-OUdxPY-X.d.cts +754 -0
  47. package/dist/controller-OUdxPY-X.d.ts +754 -0
  48. package/dist/extensions/index.cjs +144 -3
  49. package/dist/extensions/index.cjs.map +1 -1
  50. package/dist/extensions/index.d.cts +9 -144
  51. package/dist/extensions/index.d.ts +9 -144
  52. package/dist/extensions/index.js +145 -4
  53. package/dist/grammar/index.cjs +31 -3
  54. package/dist/grammar/index.cjs.map +1 -1
  55. package/dist/grammar/index.d.cts +239 -19
  56. package/dist/grammar/index.d.ts +239 -19
  57. package/dist/grammar/index.js +31 -3
  58. package/dist/history/index.d.cts +2 -41
  59. package/dist/history/index.d.ts +2 -41
  60. package/dist/index-Ng1pG7JE.d.ts +899 -0
  61. package/dist/index-k3mFbPx_.d.cts +899 -0
  62. package/dist/index.cjs +457 -20
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +99 -12
  65. package/dist/index.d.ts +99 -12
  66. package/dist/index.js +457 -20
  67. package/dist/index.js.map +1 -1
  68. package/dist/registry-iAHbqkYt.d.cts +128 -0
  69. package/dist/registry-iAHbqkYt.d.ts +128 -0
  70. package/dist/serializers/index.cjs +26 -3
  71. package/dist/serializers/index.cjs.map +1 -1
  72. package/dist/serializers/index.d.cts +119 -6
  73. package/dist/serializers/index.d.ts +119 -6
  74. package/dist/serializers/index.js +24 -1
  75. package/dist/spreadsheet/index.cjs +122 -2
  76. package/dist/spreadsheet/index.cjs.map +1 -1
  77. package/dist/spreadsheet/index.d.cts +371 -313
  78. package/dist/spreadsheet/index.d.ts +371 -313
  79. package/dist/spreadsheet/index.js +127 -7
  80. package/dist/tokens-CyLZmIei.d.cts +76 -0
  81. package/dist/tokens-CyLZmIei.d.ts +76 -0
  82. package/dist/track-changes-G8JcWB8b.d.cts +306 -0
  83. package/dist/track-changes-G8JcWB8b.d.ts +306 -0
  84. package/dist/types-BZgcDsC5.d.cts +42 -0
  85. package/dist/types-BZgcDsC5.d.ts +42 -0
  86. package/dist/{types-JV3S8VeR.d.cts → types-DMe0vFB1.d.cts} +1 -1
  87. package/dist/{types-JV3S8VeR.d.ts → types-DMe0vFB1.d.ts} +1 -1
  88. package/package.json +11 -4
  89. package/dist/chunk-7FWEWE6T.js +0 -1888
  90. package/dist/chunk-7FWEWE6T.js.map +0 -1
  91. package/dist/chunk-AIZUKWTL.js +0 -1715
  92. package/dist/chunk-AIZUKWTL.js.map +0 -1
  93. package/dist/chunk-GLSIZKOX.js +0 -17
  94. package/dist/chunk-GLSIZKOX.js.map +0 -1
  95. package/dist/chunk-LDES3EOS.cjs +0 -1888
  96. package/dist/chunk-LDES3EOS.cjs.map +0 -1
  97. package/dist/chunk-LLUAKTLW.cjs +0 -532
  98. package/dist/chunk-LLUAKTLW.cjs.map +0 -1
  99. package/dist/chunk-MPPXH7U5.cjs +0 -336
  100. package/dist/chunk-MPPXH7U5.cjs.map +0 -1
  101. package/dist/chunk-O7LOPQMH.js +0 -336
  102. package/dist/chunk-O7LOPQMH.js.map +0 -1
  103. package/dist/chunk-QGVMBCT5.js +0 -532
  104. package/dist/chunk-QGVMBCT5.js.map +0 -1
  105. package/dist/chunk-SEDR75VH.cjs +0 -17
  106. package/dist/chunk-SEDR75VH.cjs.map +0 -1
  107. package/dist/chunk-YQCI4CCN.cjs +0 -1715
  108. package/dist/chunk-YQCI4CCN.cjs.map +0 -1
  109. package/dist/mention-Dcevh3ff.d.cts +0 -32
  110. package/dist/mention-Dcevh3ff.d.ts +0 -32
  111. package/dist/tokens-7kRTEtPb.d.cts +0 -39
  112. package/dist/tokens-7kRTEtPb.d.ts +0 -39
@@ -1,343 +1,401 @@
1
- type CellFormat = 'text' | 'number' | 'currency' | 'percentage' | 'date' | 'badge' | 'status' | 'assignee';
2
- type ColumnType = 'bound' | 'freeform' | 'formula';
3
- interface ColumnBinding {
4
- dataSource: string;
5
- field: string;
6
- }
7
- interface SpreadsheetColumn {
8
- id: string;
9
- key: string;
10
- title: string;
11
- width?: number;
12
- type: ColumnType;
13
- binding?: ColumnBinding;
14
- formula?: string;
15
- format?: CellFormat;
16
- readOnly?: boolean;
17
- }
18
- type RowType = 'record' | 'freeform';
19
- interface SpreadsheetRow {
20
- id: string;
21
- index: number;
22
- height?: number;
23
- recordId?: string;
24
- type: RowType;
25
- }
26
- interface CellCoordinate {
27
- row: number;
28
- col: number;
29
- rowId?: string;
30
- colId?: string;
31
- }
32
- interface CellRange {
33
- startRow: number;
34
- startCol: number;
35
- endRow: number;
36
- endCol: number;
37
- }
38
- interface CellData {
39
- raw: string;
40
- value: any;
41
- error?: string;
42
- format?: CellFormat;
43
- readOnly?: boolean;
44
- }
45
- interface SpreadsheetDocument {
46
- id: string;
1
+ import { A as ASTNode, r as FormulaErrorCode, v as FormulaRange, G as GroupAggregate, J as SortDirection, e as CellRange, d as CellPosition, p as FilterRule, W as SpreadsheetController } from '../controller-OUdxPY-X.js';
2
+ export { B as BinaryOpNode, C as CellCoordinate, a as CellData, b as CellDep, c as CellFormat, f as CellRefNode, g as CellValueReader, h as ColumnBinding, i as ColumnType, j as CsvExportOptions, k as CsvImportOptions, D as DEFAULT_COLUMN_WIDTH, l as DEFAULT_ROW_HEIGHT, m as DataSourceBinder, n as DependencyGraph, E as EvaluationContext, F as FORMULA_ERRORS, o as FilterOperator, q as FormulaDiagnostic, s as FormulaEvaluationResult, t as FormulaEvaluator, u as FormulaParser, w as FormulaToken, x as FormulaTokenType, y as FunctionCallNode, z as GroupSummary, L as LiteralNode, N as NewFilterRule, P as ParsedSpreadsheetClipboard, H as PropertyRefNode, R as RangeNode, I as RowType, S as SPREADSHEET_CLIPBOARD_MIME, K as SortKey, M as SpreadsheetCellSpan, O as SpreadsheetClipboardCell, Q as SpreadsheetClipboardData, T as SpreadsheetClipboardPayload, U as SpreadsheetClipboardSource, V as SpreadsheetColumn, X as SpreadsheetControllerOptions, Y as SpreadsheetDataSource, Z as SpreadsheetDataSourceField, _ as SpreadsheetDocument, $ as SpreadsheetFilterState, a0 as SpreadsheetGrouping, a1 as SpreadsheetRow, a2 as SpreadsheetRowGroup, a3 as SpreadsheetRowSection, a4 as SpreadsheetTableSettings, a5 as SpreadsheetViewColumn, a6 as SpreadsheetViewModel, a7 as SpreadsheetViewRow, a8 as StructuralChange, a9 as UnaryOpNode, aa as WHOLE_COLUMN_END_ROW, ab as buildSpreadsheetView, ac as colNameToIndex, ad as columnDependencyKey, ae as computeRowGroups, af as createSpreadsheetClipboardData, ag as describeFormulaError, ah as extractCellDependencies, ai as getRowSection, aj as getTableSections, ak as indexToColName, al as isFormulaError, am as mapFormulaReferences, an as offsetFormulaReferences, ao as parseCellReference, ap as parseFormula, aq as parseHtmlTable, ar as parseRange, as as readSpreadsheetClipboard, at as rebaseClipboardRows, au as remapFormulaReferences, av as rowPassesFilters, aw as serializeHtmlTable, ax as shiftFormulaReferences, ay as tokenizeFormula } from '../controller-OUdxPY-X.js';
3
+ import { I as ImportAdapterRegistry, c as ImportAdapter, h as ImportInput, a as ImportOutcome } from '../registry-iAHbqkYt.js';
4
+
5
+ type FormulaFunctionCategory = 'math' | 'statistical' | 'logical' | 'text' | 'lookup' | 'date' | 'information';
6
+ /** What an argument expects. Used for documentation, hints and messages. */
7
+ type FormulaArgumentType = 'any' | 'number' | 'text' | 'logical' | 'date' | 'range' | 'criteria';
8
+ interface FormulaArgumentSpec {
9
+ /** Argument name shown in signatures, e.g. `sum_range`. */
47
10
  name: string;
48
- columns: SpreadsheetColumn[];
49
- rows: SpreadsheetRow[];
50
- cells: Record<string, Record<string, CellData>>;
51
- createdAt?: number;
52
- updatedAt?: number;
11
+ description: string;
12
+ type?: FormulaArgumentType;
13
+ /** The argument may be left out. */
14
+ optional?: boolean;
15
+ /**
16
+ * The argument repeats. Consecutive repeating arguments form a group that
17
+ * repeats together (`criteria_range, criteria` in SUMIFS). The group must be
18
+ * the last arguments, and is required once unless its first spec is optional.
19
+ */
20
+ repeating?: boolean;
53
21
  }
54
- interface SpreadsheetDataSourceField {
55
- key: string;
56
- label: string;
57
- type: 'string' | 'number' | 'date' | 'boolean' | 'enum';
58
- options?: Array<{
59
- key: string;
60
- label: string;
61
- color?: string;
62
- }>;
22
+ /** One argument of a call, evaluated lazily so functions like IF can short-circuit. */
23
+ interface FormulaArgument {
24
+ /** 0-based position in the call. */
25
+ readonly index: number;
26
+ readonly node: ASTNode;
27
+ /** Evaluates the argument (once; later calls return the cached value). Ranges evaluate to arrays. */
28
+ value(): any;
63
29
  }
64
- interface SpreadsheetDataSource {
65
- id: string;
30
+ /** What a function implementation receives. Coercion helpers report argument-indexed diagnostics. */
31
+ interface FormulaFunctionContext {
32
+ /** Upper-case function name. */
33
+ readonly name: string;
34
+ readonly args: readonly FormulaArgument[];
35
+ /** Returns `code` and records `message` as the reason (shown to the user if the cell ends up with that error). */
36
+ error(code: FormulaErrorCode, message?: string): string;
37
+ /** Like `error`, phrased as `Argument N of NAME <reason>`. */
38
+ argError(index: number, code: FormulaErrorCode, reason: string): string;
39
+ /** Whether argument `index` was supplied. */
40
+ has(index: number): boolean;
41
+ /** Raw (lazily evaluated) value of an argument; ranges are arrays. */
42
+ value(index: number): any;
43
+ /** Single value of an argument: a one-cell range is unwrapped, larger ranges are #VALUE!. */
44
+ scalar(index: number): any;
45
+ /** Argument as a number (or an error string). Text that isn't numeric is #VALUE!. */
46
+ number(index: number, fallback?: number): number | string;
47
+ /** Argument as an integer (truncated toward zero). */
48
+ integer(index: number, fallback?: number): number | string;
49
+ /** Argument as text (or an error string). */
50
+ text(index: number, fallback?: string): string;
51
+ /** Argument as a boolean (or an error string). */
52
+ boolean(index: number, fallback?: boolean): boolean | string;
53
+ /** Argument as a date (or an error string). */
54
+ date(index: number): Date | string;
55
+ /** Argument as a 2D range (or an error string if it is not a range). */
56
+ range(index: number): FormulaRange | string;
57
+ /** Every value of the arguments `from` (default 0) up to `to` (exclusive, default all), ranges flattened. */
58
+ flatValues(from?: number, to?: number): any[];
59
+ /**
60
+ * Numbers among the arguments `from`..`to` (exclusive), as SUM reads them:
61
+ * text, booleans and blanks are skipped; the first error is returned instead.
62
+ */
63
+ numbers(from?: number, to?: number): number[] | string;
64
+ }
65
+ interface FormulaFunctionDefinition {
66
+ /** Function name; matched case-insensitively. */
66
67
  name: string;
67
- getRecords(): Array<{
68
- id: string;
69
- [key: string]: any;
70
- }>;
71
- getFields(): SpreadsheetDataSourceField[];
72
- updateRecord(recordId: string, field: string, value: any): Promise<void> | void;
68
+ category: FormulaFunctionCategory;
69
+ description: string;
70
+ args: FormulaArgumentSpec[];
71
+ /** Result changes on every recalculation (RAND, NOW, TODAY). */
72
+ volatile?: boolean;
73
+ /**
74
+ * A repeating group may end with one extra argument (SWITCH's `default`).
75
+ * Otherwise a group must be complete.
76
+ */
77
+ allowTrailingArgument?: boolean;
78
+ evaluate(ctx: FormulaFunctionContext): any;
73
79
  }
74
-
75
- type FormulaTokenType = 'NUMBER' | 'STRING' | 'BOOLEAN' | 'ERROR' | 'CELL_REF' | 'RANGE' | 'PROPERTY_REF' | 'IDENTIFIER' | 'OPERATOR' | 'LPAREN' | 'RPAREN' | 'COMMA' | 'EOF';
76
- interface FormulaToken {
77
- type: FormulaTokenType;
78
- value: string;
79
- position: number;
80
+ /**
81
+ * Adds (or replaces) a formula function. Replacing a built-in is allowed, so
82
+ * apps can customise behaviour; the change is global.
83
+ */
84
+ declare function registerFormulaFunction(definition: FormulaFunctionDefinition): void;
85
+ /** Removes a formula function. Returns false if it was not registered. */
86
+ declare function unregisterFormulaFunction(name: string): boolean;
87
+ declare function getFormulaFunction(name: string): FormulaFunctionDefinition | undefined;
88
+ /** All registered functions sorted by name, optionally limited to one category. */
89
+ declare function listFormulaFunctions(category?: FormulaFunctionCategory): FormulaFunctionDefinition[];
90
+ /**
91
+ * Functions matching `query`, for autocomplete: names starting with the query
92
+ * first, then names containing it. An empty query lists every function.
93
+ */
94
+ declare function searchFormulaFunctions(query: string, options?: {
95
+ limit?: number;
96
+ category?: FormulaFunctionCategory;
97
+ }): FormulaFunctionDefinition[];
98
+ /**
99
+ * Index into `def.args` of the spec describing the call argument at
100
+ * `argIndex`, or -1 if the function takes no argument there.
101
+ */
102
+ declare function getFormulaArgumentSpecIndex(def: FormulaFunctionDefinition, argIndex: number): number;
103
+ /**
104
+ * Checks the number of arguments of a call. Returns a message such as
105
+ * `SUMIF needs at least 2 arguments, but 1 was given.`, or null when valid.
106
+ */
107
+ declare function checkFormulaArgumentCount(def: FormulaFunctionDefinition, count: number): string | null;
108
+ /** A piece of a rendered signature; `specIndex` is set on argument names. */
109
+ interface FormulaSignaturePart {
110
+ text: string;
111
+ specIndex: number | null;
112
+ active: boolean;
80
113
  }
81
- declare function tokenizeFormula(formula: string): FormulaToken[];
114
+ /**
115
+ * Renders a signature as parts, e.g. `SUMIFS(` `sum_range` `, ` ... `)`, with
116
+ * the argument at call position `activeArgIndex` (if any) marked active. A
117
+ * repeating group is shown twice (`value1, [value2, ...]`); arguments past
118
+ * the first repetition highlight the second one.
119
+ */
120
+ declare function getFormulaSignatureParts(nameOrDef: string | FormulaFunctionDefinition, activeArgIndex?: number | null): FormulaSignaturePart[];
121
+ /** Signature string such as `SUMIF(range, criteria, [sum_range])`. */
122
+ declare function getFormulaSignature(nameOrDef: string | FormulaFunctionDefinition): string;
82
123
 
83
- /** Row number used for the open end of whole-column ranges such as `A:A`. */
84
- declare const WHOLE_COLUMN_END_ROW = 1048576;
85
- type ASTNode = LiteralNode | CellRefNode | RangeNode | PropertyRefNode | BinaryOpNode | UnaryOpNode | FunctionCallNode;
86
- interface LiteralNode {
87
- type: 'Literal';
88
- value: number | string | boolean;
89
- }
90
- interface CellRefNode {
91
- type: 'CellRef';
92
- ref: string;
93
- col: string;
94
- row: number;
95
- }
96
- interface RangeNode {
97
- type: 'Range';
98
- raw: string;
99
- startCol: string;
100
- startRow: number;
101
- endCol: string;
102
- endRow: number;
103
- }
104
- interface PropertyRefNode {
105
- type: 'PropertyRef';
106
- property: string;
107
- }
108
- interface BinaryOpNode {
109
- type: 'BinaryOp';
110
- op: string;
111
- left: ASTNode;
112
- right: ASTNode;
124
+ /**
125
+ * Caret analysis for formula autocomplete. The input is scanned tolerantly
126
+ * (unterminated strings and unbalanced parentheses are expected while typing),
127
+ * so this never throws.
128
+ */
129
+ interface FormulaCaretContext {
130
+ /** The function-name prefix being typed right before the caret, if any. */
131
+ prefix: {
132
+ text: string;
133
+ start: number;
134
+ end: number;
135
+ } | null;
136
+ /** The innermost function call containing the caret, if any. */
137
+ call: {
138
+ name: string;
139
+ /** 0-based index of the argument the caret is in. */
140
+ argIndex: number;
141
+ /** Offset of the call's opening parenthesis. */
142
+ openParen: number;
143
+ } | null;
113
144
  }
114
- interface UnaryOpNode {
115
- type: 'UnaryOp';
116
- op: string;
117
- argument: ASTNode;
145
+ /** Determines what is being typed at `caret` in `input` (a formula starting with `=`). */
146
+ declare function getFormulaCaretContext(input: string, caret?: number): FormulaCaretContext;
147
+ /** A function suggestion for autocomplete. */
148
+ interface FormulaFunctionSuggestion {
149
+ name: string;
150
+ signature: string;
151
+ description: string;
152
+ category: FormulaFunctionDefinition['category'];
118
153
  }
119
- interface FunctionCallNode {
120
- type: 'FunctionCall';
154
+ interface FormulaActiveCall {
121
155
  name: string;
122
- args: ASTNode[];
156
+ signature: string;
157
+ description: string;
158
+ /** Signature split into parts, with the active argument marked. */
159
+ parts: FormulaSignaturePart[];
160
+ /** 0-based argument index at the caret. */
161
+ argIndex: number;
162
+ /** Spec of the active argument, if the function takes an argument there. */
163
+ argument: FormulaArgumentSpec | null;
123
164
  }
124
- declare function parseCellReference(ref: string): {
125
- col: string;
126
- row: number;
127
- };
128
- declare function parseRange(rangeStr: string): RangeNode;
129
- declare class FormulaParser {
130
- private tokens;
131
- private current;
132
- constructor(tokens: FormulaToken[]);
133
- parse(): ASTNode;
134
- private expression;
135
- private comparison;
136
- private concatenation;
137
- private addition;
138
- private multiplication;
139
- private exponentiation;
140
- private unary;
141
- private primary;
142
- private match;
143
- private matchOperator;
144
- private check;
145
- private advance;
146
- private isAtEnd;
147
- private peek;
148
- private previous;
149
- private consume;
165
+ interface FormulaHints {
166
+ context: FormulaCaretContext;
167
+ /** Functions matching the name prefix at the caret (empty when not typing a name). */
168
+ suggestions: FormulaFunctionSuggestion[];
169
+ /** The known function whose arguments the caret is in. */
170
+ activeCall: FormulaActiveCall | null;
150
171
  }
151
- declare function parseFormula(formula: string): ASTNode;
172
+ /** Everything formula autocomplete UIs need for `input` with the caret at `caret`. */
173
+ declare function getFormulaHints(input: string, caret?: number, options?: {
174
+ limit?: number;
175
+ }): FormulaHints;
176
+ /**
177
+ * Replaces the name prefix at the caret with `NAME(`, returning the new input
178
+ * and caret position (just inside the parenthesis).
179
+ */
180
+ declare function applyFormulaSuggestion(input: string, caret: number, name: string): {
181
+ value: string;
182
+ caret: number;
183
+ };
152
184
 
153
- interface EvaluationContext {
154
- resolveCell?: (col: string, row: number) => any;
155
- resolveRange?: (startCol: string, startRow: number, endCol: string, endRow: number) => any[];
156
- resolveProperty?: (property: string) => any;
157
- }
158
- /** Spreadsheet error values. They propagate through operators and functions. */
159
- declare const FORMULA_ERRORS: Set<string>;
160
- declare function isFormulaError(value: unknown): value is string;
161
- declare function colNameToIndex(col: string): number;
162
- declare function indexToColName(index: number): string;
163
- declare class FormulaEvaluator {
164
- private context;
165
- constructor(context?: EvaluationContext);
166
- evaluate(astOrFormula: ASTNode | string): any;
167
- private evaluateNode;
168
- private callFunction;
169
- }
185
+ /** Tests one value against a criterion. */
186
+ type FormulaCriteriaPredicate = (value: unknown) => boolean;
187
+ /**
188
+ * Builds a regular expression from a spreadsheet wildcard pattern: `*` is any
189
+ * run of characters, `?` any single character, and `~` escapes the next
190
+ * character (`~*` is a literal asterisk). Matching is case-insensitive.
191
+ */
192
+ declare function wildcardToRegExp(pattern: string): RegExp;
193
+ /**
194
+ * Parses a criterion as used by SUMIF, COUNTIFS etc.:
195
+ * - a number or boolean matches equal values (`5` matches 5 and the text "5");
196
+ * - text may start with `=`, `<>`, `<`, `<=`, `>` or `>=`. Numeric operands
197
+ * compare numbers; text operands compare text case-insensitively;
198
+ * - `=`/`<>` text operands and plain text support `*` and `?` wildcards;
199
+ * - `""` and `"="` match blank cells, `"<>"` matches non-blank cells.
200
+ * Error values in the data never match.
201
+ */
202
+ declare function parseCriteria(criterion: unknown): FormulaCriteriaPredicate;
170
203
 
171
- interface CellDep {
172
- col: string;
173
- row: number;
174
- }
175
204
  /**
176
- * Dependency key for "every cell in column `col`", used by whole-column ranges
177
- * (`A:A`) instead of expanding a million cell keys.
205
+ * A subset of spreadsheet number format codes, as used by TEXT():
206
+ * - numbers: `0`, `#`, `0.00`, `#,##0`, `#,##0.00`, `0%`, `0.0%`, `0.00E+00`,
207
+ * literal prefixes/suffixes (`$#,##0.00`, `0.0 "kg"`), and
208
+ * `positive;negative;zero` sections;
209
+ * - dates and times: `yyyy yy mmmm mmm mm m dddd ddd dd d hh h mm ss AM/PM`
210
+ * (`m`/`mm` after an hour or before seconds means minutes).
211
+ * Text values are returned unchanged; unsupported codes are best effort.
178
212
  */
179
- declare const columnDependencyKey: (col: string) => string;
180
- declare function extractCellDependencies(node: ASTNode): CellDep[];
181
- declare class DependencyGraph {
182
- private dependencies;
183
- private dependents;
184
- setCellFormula(cellKey: string, formulaStr: string | null): void;
185
- /** Removes every registered formula and dependency. */
186
- clear(): void;
187
- getDependencies(cellKey: string): string[];
188
- getDependents(cellKey: string): string[];
189
- /**
190
- * Detects if there is a cycle containing cellKey.
191
- */
192
- hasCycle(cellKey: string): boolean;
193
- /**
194
- * Returns cells affected by updating cellKey in topological order.
195
- */
196
- getEvaluationOrder(startCellKey: string): {
197
- order: string[];
198
- hasCycle: boolean;
199
- };
213
+ declare function formatValueWithCode(value: unknown, format: string): string | null;
214
+
215
+ /**
216
+ * RFC 4180 CSV (and other delimiter-separated values) parsing and
217
+ * serialization.
218
+ *
219
+ * - Fields may be quoted with `"`; a quote inside a quoted field is written
220
+ * as `""`. Quoted fields may contain delimiters and line breaks.
221
+ * - Records end at CRLF, LF or CR. A final line break does not add an empty
222
+ * record.
223
+ * - A leading UTF-8 byte order mark is ignored.
224
+ * - The parser is lenient like spreadsheet apps: a quote inside an unquoted
225
+ * field is kept as text, text after a closing quote is appended, and an
226
+ * unterminated quoted field runs to the end of the input.
227
+ */
228
+ interface CsvParseOptions {
229
+ /** Field separator. Default `,`. */
230
+ delimiter?: string;
200
231
  /**
201
- * Plans a recalculation over `cellKeys` (and, with `includeDependents`, every
202
- * cell that transitively depends on them). Returns the keys in evaluation
203
- * order (dependencies first) and the set of keys that are part of a cycle,
204
- * which must be marked `#CYCLE!` instead of evaluated. Every member of a
205
- * cycle is reported, not just the cell that closed it.
232
+ * Only treat a leading `"` as a quote when the quoted field is closed and
233
+ * followed by a delimiter or line break; otherwise keep it as text. Used for
234
+ * clipboard TSV, where plain text may legitimately start with a quote.
206
235
  */
207
- getEvaluationPlan(cellKeys: Iterable<string>, options?: {
208
- includeDependents?: boolean;
209
- }): {
210
- order: string[];
211
- cyclic: Set<string>;
212
- };
236
+ requireWellFormedQuotes?: boolean;
237
+ }
238
+ interface CsvSerializeOptions {
239
+ /** Field separator. Default `,`. */
240
+ delimiter?: string;
241
+ /** Record separator. Default `\r\n` (RFC 4180). */
242
+ lineEnding?: string;
243
+ /** Prefix the output with a UTF-8 byte order mark (helps Excel detect UTF-8). */
244
+ bom?: boolean;
245
+ /** Quote every field, not only those that need it. */
246
+ quoteAll?: boolean;
213
247
  }
248
+ declare function parseCsv(text: string, options?: CsvParseOptions): string[][];
249
+ /** Quotes `value` when it contains the delimiter, a quote or a line break. */
250
+ declare function escapeCsvField(value: string, delimiter?: string, quoteAll?: boolean): string;
251
+ declare function serializeCsv(rows: ReadonlyArray<ReadonlyArray<unknown>>, options?: CsvSerializeOptions): string;
252
+ /**
253
+ * Parses tab-separated clipboard text as spreadsheet apps write it: cells
254
+ * containing line breaks or tabs are quoted CSV-style. A field is only
255
+ * treated as quoted when it starts with `"` *and* its closing quote ends the
256
+ * field, so plain text that happens to start with a quote is kept as is.
257
+ */
258
+ declare function parseTsv(text: string): string[][];
259
+ /**
260
+ * Serializes values as TSV for the clipboard. Fields containing a tab, line
261
+ * break or a leading quote are quoted so `parseTsv` (and spreadsheet apps)
262
+ * read them back as one cell.
263
+ */
264
+ declare function serializeTsv(rows: ReadonlyArray<ReadonlyArray<unknown>>): string;
214
265
 
215
266
  /**
216
- * A row or column insertion/deletion. `index` is the 0-based position of the
217
- * inserted or deleted row/column.
267
+ * Pure helpers behind the controller's table operations: value comparison
268
+ * for sorting, filter matching, group aggregates, autofill series and range
269
+ * arithmetic. Framework packages use these through `SpreadsheetController`.
218
270
  */
219
- interface StructuralChange {
220
- axis: 'row' | 'col';
221
- index: number;
222
- type: 'insert' | 'delete';
223
- }
271
+
272
+ /** Returns `range` with start <= end on both axes. */
273
+ declare function normalizeRange(range: CellRange): CellRange;
274
+ declare function rangeContains(range: CellRange, row: number, col: number): boolean;
275
+ declare function rangesIntersect(a: CellRange, b: CellRange): boolean;
276
+ /** True when `inner` lies entirely inside `outer`. */
277
+ declare function rangeContainsRange(outer: CellRange, inner: CellRange): boolean;
278
+ declare function isSingleCellRange(range: CellRange): boolean;
279
+ declare function isBlankValue(value: unknown): boolean;
280
+ /** The numeric value of a number or numeric string, or null. */
281
+ declare function toNumber(value: unknown): number | null;
282
+ /**
283
+ * Sort order for cell values: numbers (ascending) before text (natural,
284
+ * case-insensitive). `desc` reverses that order. Blanks always sort last,
285
+ * whatever the direction.
286
+ */
287
+ declare function compareCellValues(a: unknown, b: unknown, direction?: SortDirection): number;
288
+ /** Whether a cell value passes one filter rule. */
289
+ declare function matchesFilterRule(value: unknown, rule: FilterRule): boolean;
290
+ /**
291
+ * Aggregates values the way category summaries do: `count` counts non-blank
292
+ * values; the other aggregates use numeric values only and return null when
293
+ * there are none.
294
+ */
295
+ declare function aggregateValues(values: unknown[], aggregate: GroupAggregate): number | null;
296
+ /** Removes binary floating point noise (0.1 + 0.2 -> 0.3). */
297
+ declare function roundFloat(value: number): number;
298
+ /**
299
+ * Extends `source` (raw values in fill order: for an upward or leftward fill,
300
+ * nearest-first) by `count` values, the way a fill handle does:
301
+ *
302
+ * - numbers: one value repeats; two or more continue their linear trend
303
+ * - ISO dates (`YYYY-MM-DD`): one date counts up by a day; two or more
304
+ * continue their day or month step
305
+ * - text ending in a number ("Item 1"): the number counts up (or continues
306
+ * the step of several values with the same prefix/suffix)
307
+ * - anything else (or a mix) repeats the source cyclically
308
+ *
309
+ * Formulas are not handled here; the controller shifts their references.
310
+ */
311
+ declare function fillSeries(source: string[], count: number): string[];
312
+ type FillDirection = 'down' | 'up' | 'right' | 'left';
313
+ /**
314
+ * Works out where a fill handle drag ends. Dragging further vertically than
315
+ * horizontally fills down/up the source's columns; otherwise right/left
316
+ * across its rows. Returns the full target range (source included), or null
317
+ * while the pointer is still inside the source.
318
+ */
319
+ declare function computeFillTarget(source: CellRange, pointer: CellPosition): CellRange | null;
224
320
  /**
225
- * Rewrites the cell and range references in `formula` after a row or column
226
- * is inserted or deleted, the way spreadsheet apps do: references after the
227
- * change shift, ranges grow or shrink, and references to a deleted row/column
228
- * become `#REF!`. Absolute (`$`) markers are kept. String literals, property
229
- * references and function names are left untouched.
321
+ * The direction of a fill from `source` into `target` (the extended range),
322
+ * or null when `target` does not extend `source` along exactly one edge.
230
323
  */
231
- declare function shiftFormulaReferences(formula: string, change: StructuralChange): string;
324
+ declare function getFillDirection(source: CellRange, target: CellRange): FillDirection | null;
232
325
 
233
- declare class DataSourceBinder {
234
- private dataSources;
235
- register(dataSource: SpreadsheetDataSource): void;
236
- unregister(dataSourceId: string): void;
237
- getDataSource(id: string): SpreadsheetDataSource | undefined;
238
- /**
239
- * Generates or reconciles spreadsheet rows from a primary data source.
240
- */
241
- syncRows(currentRows: SpreadsheetRow[], dataSourceId: string): SpreadsheetRow[];
242
- /**
243
- * Resolves a record's bound field value.
244
- */
245
- resolveBoundValue(dataSourceId: string, recordId: string, field: string): any;
246
- /**
247
- * Dispatches an update to the underlying data source.
248
- */
249
- commitBoundValue(dataSourceId: string, recordId: string, field: string, value: any): Promise<void>;
326
+ /**
327
+ * The spreadsheet's table context menu, defined once so the React and Svelte
328
+ * editors show the same actions. Frameworks render the items and call
329
+ * `run()`; the controller's change listeners refresh their state.
330
+ */
331
+
332
+ interface SpreadsheetMenuItem {
333
+ id: string;
334
+ label: string;
335
+ disabled?: boolean;
336
+ /** Draw a divider before this item. */
337
+ separatorBefore?: boolean;
338
+ run: () => void;
250
339
  }
340
+ /**
341
+ * Menu items for a right-click on `cell`. When the cell is inside the
342
+ * selection, range actions (hide, merge, transpose) apply to the selection;
343
+ * otherwise to the clicked cell.
344
+ */
345
+ declare function getSpreadsheetMenuItems(controller: SpreadsheetController, cell: CellPosition): SpreadsheetMenuItem[];
346
+
347
+ /**
348
+ * Controller methods the React and Svelte spreadsheet bindings expose as-is,
349
+ * so both frameworks offer the same table operations. They need no extra
350
+ * state syncing: the controller reports changes through `onDocumentChange`
351
+ * and `onSelectionChange`.
352
+ */
353
+ declare const SPREADSHEET_TABLE_ACTIONS: readonly ["sortRows", "getFilterState", "setFilterRules", "addFilterRule", "updateFilterRule", "removeFilterRule", "clearFilters", "setFiltersEnabled", "toggleFilters", "setHeaderRowCount", "setFooterRowCount", "setHeaderColumnCount", "setFrozenRowCount", "setFrozenColumnCount", "hideRows", "unhideRows", "hideColumns", "unhideColumns", "unhideAll", "getMerges", "getMergeAt", "mergeCells", "unmergeCells", "autofill", "groupRowsBy", "ungroupRows", "setGroupSummary", "setGroupCollapsed", "toggleGroupCollapsed", "getGroups", "transposeRange", "exportToCsv", "importFromCsv", "copyToClipboardData", "pasteClipboardData"];
354
+ type SpreadsheetTableActionName = (typeof SPREADSHEET_TABLE_ACTIONS)[number];
355
+ type SpreadsheetTableActions = Pick<SpreadsheetController, SpreadsheetTableActionName>;
356
+ /** The table operations of `controller`, bound so they can be passed around. */
357
+ declare function bindSpreadsheetTableActions(controller: SpreadsheetController): SpreadsheetTableActions;
358
+
359
+ /**
360
+ * `spreadsheet` import adapters for the import registry: CSV and TSV files
361
+ * parsed with the RFC 4180 parser in `csv.ts`.
362
+ *
363
+ * They are not registered by default (the default registry only knows
364
+ * `document` adapters). Registries are passed in explicitly so this entry
365
+ * point does not pull in the document adapters (markdown, TipTap):
366
+ *
367
+ * registerSpreadsheetImportAdapters(defaultImportRegistry);
368
+ * await importFileIntoSpreadsheet(controller, file, { registry: defaultImportRegistry });
369
+ */
251
370
 
252
- interface SpreadsheetControllerOptions {
253
- document?: Partial<SpreadsheetDocument>;
254
- dataSources?: SpreadsheetDataSource[];
255
- primaryDataSourceId?: string;
256
- onDocumentChange?: (doc: SpreadsheetDocument) => void;
257
- onSelectionChange?: (activeCell: CellCoordinate | null, range: CellRange | null) => void;
258
- onCellCommit?: (rowId: string, colId: string, raw: string, value: any) => void;
371
+ /** Result of every `spreadsheet` adapter. */
372
+ interface SpreadsheetImport {
373
+ /** Parsed records, one array of raw cell inputs per row. */
374
+ rows: string[][];
375
+ /** Field separator the file was parsed with. */
376
+ delimiter: string;
259
377
  }
260
- declare class SpreadsheetController {
261
- document: SpreadsheetDocument;
262
- activeCell: CellCoordinate | null;
263
- selectedRange: CellRange | null;
264
- editingCell: CellCoordinate | null;
265
- draftValue: string;
266
- readonly binder: DataSourceBinder;
267
- readonly depGraph: DependencyGraph;
268
- readonly evaluator: FormulaEvaluator;
269
- private primaryDataSourceId?;
270
- private onDocumentChange?;
271
- private onSelectionChange?;
272
- private onCellCommit?;
273
- private undoStack;
274
- private redoStack;
275
- private isApplyingHistory;
276
- private batching;
277
- private pendingCommits;
278
- private evaluatingRowIndex;
279
- constructor(options?: SpreadsheetControllerOptions);
280
- loadDocument(document: SpreadsheetDocument): void;
281
- registerDataSource(ds: SpreadsheetDataSource): void;
282
- setPrimaryDataSource(dataSourceId: string | undefined): void;
283
- syncWithDataSource(): void;
284
- private recomputeRowIndices;
285
- getColumn(colIdOrKey: string): SpreadsheetColumn | undefined;
286
- getRow(rowIdOrIndex: string | number): SpreadsheetRow | undefined;
287
- getCell(rowId: string, colId: string): CellData;
288
- /** Value of a cell with no stored data: bound record value, column formula, or blank. */
289
- private getDerivedCell;
290
- setCellValue(rowId: string, colId: string, raw: string): void;
291
- private getCellKey;
292
- /**
293
- * Recalculates a cell and everything that depends on it, in dependency
294
- * order. Every cell in a reference cycle is marked `#CYCLE!`.
295
- */
296
- recalculateCell(rowId: string, colId: string): void;
297
- /**
298
- * Rebuilds the dependency graph from scratch and recalculates every formula
299
- * in dependency order.
300
- */
301
- recalculateAll(): void;
302
- private runEvaluationPlan;
303
- private locateCellKey;
304
- private markCycle;
305
- private evalSingleCellByKey;
306
- private resolveCellByCoord;
307
- private resolveRangeByCoords;
308
- private resolveCurrentRowProperty;
309
- selectCell(row: number, col: number, extendSelection?: boolean): void;
310
- selectRange(range: CellRange): void;
311
- startEditing(row?: number, col?: number, initialValue?: string): void;
312
- commitEditing(valueToCommit?: string): void;
313
- cancelEditing(): void;
314
- moveCursor(direction: 'up' | 'down' | 'left' | 'right', extendSelection?: boolean): void;
315
- insertColumn(index: number, config?: Partial<SpreadsheetColumn>): void;
316
- deleteColumn(colId: string): void;
317
- insertRow(index: number, config?: Partial<SpreadsheetRow>): void;
318
- deleteRow(rowId: string): void;
319
- private generateId;
320
- /**
321
- * Rewrites references in every cell formula (and, for column changes, every
322
- * column formula) so they keep pointing at the same cells.
323
- */
324
- private shiftReferences;
325
- setColumnWidth(colId: string, width: number): void;
326
- autoFitColumnWidth(colId: string, customWidth?: number): void;
327
- /**
328
- * Exports cell values as TSV: the whole sheet, or only `range` (e.g. the
329
- * current selection) when given.
330
- */
331
- exportToTsv(range?: CellRange | null): string;
332
- /**
333
- * Pastes tab-separated values starting at (startRow, startCol), adding rows
334
- * and columns as needed. The whole paste is a single undo step.
335
- */
336
- importFromTsv(tsvData: string, startRow?: number, startCol?: number): void;
337
- private recordSnapshot;
338
- undo(): void;
339
- redo(): void;
340
- private notifyChange;
378
+ type SpreadsheetImportAdapter = ImportAdapter<SpreadsheetImport>;
379
+ declare const csvImportAdapter: SpreadsheetImportAdapter;
380
+ declare const tsvImportAdapter: SpreadsheetImportAdapter;
381
+ declare const SPREADSHEET_IMPORT_ADAPTERS: readonly SpreadsheetImportAdapter[];
382
+ /** Registers the CSV and TSV adapters; returns a function that unregisters them. */
383
+ declare function registerSpreadsheetImportAdapters(registry: ImportAdapterRegistry): () => void;
384
+ interface ImportFileIntoSpreadsheetOptions {
385
+ /** Registry to resolve the adapter from (e.g. `defaultImportRegistry`). */
386
+ registry: ImportAdapterRegistry;
387
+ /** Force an adapter instead of matching by file name / MIME type. */
388
+ adapterId?: string;
389
+ fileName?: string;
390
+ mimeType?: string;
391
+ /** Top-left cell to write to (0-based). Default A1. */
392
+ startRow?: number;
393
+ startCol?: number;
341
394
  }
395
+ /**
396
+ * Imports a CSV/TSV file (or any registered `spreadsheet` adapter that
397
+ * returns `SpreadsheetImport`) into the controller as one undoable change.
398
+ */
399
+ declare function importFileIntoSpreadsheet(controller: SpreadsheetController, input: ImportInput, options: ImportFileIntoSpreadsheetOptions): Promise<ImportOutcome<SpreadsheetImport>>;
342
400
 
343
- export { type ASTNode, type BinaryOpNode, type CellCoordinate, type CellData, type CellDep, type CellFormat, type CellRange, type CellRefNode, type ColumnBinding, type ColumnType, DataSourceBinder, DependencyGraph, type EvaluationContext, FORMULA_ERRORS, FormulaEvaluator, FormulaParser, type FormulaToken, type FormulaTokenType, type FunctionCallNode, type LiteralNode, type PropertyRefNode, type RangeNode, type RowType, type SpreadsheetColumn, SpreadsheetController, type SpreadsheetControllerOptions, type SpreadsheetDataSource, type SpreadsheetDataSourceField, type SpreadsheetDocument, type SpreadsheetRow, type StructuralChange, type UnaryOpNode, WHOLE_COLUMN_END_ROW, colNameToIndex, columnDependencyKey, extractCellDependencies, indexToColName, isFormulaError, parseCellReference, parseFormula, parseRange, shiftFormulaReferences, tokenizeFormula };
401
+ export { ASTNode, CellPosition, CellRange, type CsvParseOptions, type CsvSerializeOptions, type FillDirection, FilterRule, type FormulaActiveCall, type FormulaArgument, type FormulaArgumentSpec, type FormulaArgumentType, type FormulaCaretContext, type FormulaCriteriaPredicate, FormulaErrorCode, type FormulaFunctionCategory, type FormulaFunctionContext, type FormulaFunctionDefinition, type FormulaFunctionSuggestion, type FormulaHints, FormulaRange, type FormulaSignaturePart, GroupAggregate, type ImportFileIntoSpreadsheetOptions, SPREADSHEET_IMPORT_ADAPTERS, SPREADSHEET_TABLE_ACTIONS, SortDirection, SpreadsheetController, type SpreadsheetImport, type SpreadsheetImportAdapter, type SpreadsheetMenuItem, type SpreadsheetTableActionName, type SpreadsheetTableActions, aggregateValues, applyFormulaSuggestion, bindSpreadsheetTableActions, checkFormulaArgumentCount, compareCellValues, computeFillTarget, csvImportAdapter, escapeCsvField, fillSeries, formatValueWithCode, getFillDirection, getFormulaArgumentSpecIndex, getFormulaCaretContext, getFormulaFunction, getFormulaHints, getFormulaSignature, getFormulaSignatureParts, getSpreadsheetMenuItems, importFileIntoSpreadsheet, isBlankValue, isSingleCellRange, listFormulaFunctions, matchesFilterRule, normalizeRange, parseCriteria, parseCsv, parseTsv, rangeContains, rangeContainsRange, rangesIntersect, registerFormulaFunction, registerSpreadsheetImportAdapters, roundFloat, searchFormulaFunctions, serializeCsv, serializeTsv, toNumber, tsvImportAdapter, unregisterFormulaFunction, wildcardToRegExp };