@ai-matrx/design-system 0.22.0 → 0.26.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 (115) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/dist/data-table/cell-undo.cjs +98 -0
  3. package/dist/data-table/cell-undo.cjs.map +1 -0
  4. package/dist/data-table/cell-undo.d.cts +85 -0
  5. package/dist/data-table/cell-undo.d.ts +85 -0
  6. package/dist/data-table/cell-undo.js +78 -0
  7. package/dist/data-table/cell-undo.js.map +1 -0
  8. package/dist/data-table/copy-helpers.d.cts +7 -2
  9. package/dist/data-table/copy-helpers.d.ts +7 -2
  10. package/dist/data-table/coverage.cjs +116 -0
  11. package/dist/data-table/coverage.cjs.map +1 -0
  12. package/dist/data-table/coverage.d.cts +65 -0
  13. package/dist/data-table/coverage.d.ts +65 -0
  14. package/dist/data-table/coverage.js +96 -0
  15. package/dist/data-table/coverage.js.map +1 -0
  16. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  17. package/dist/data-table/data-row-inspector.js.map +1 -1
  18. package/dist/data-table/data-row-window.cjs.map +1 -1
  19. package/dist/data-table/data-row-window.js.map +1 -1
  20. package/dist/data-table/facets.cjs +118 -0
  21. package/dist/data-table/facets.cjs.map +1 -0
  22. package/dist/data-table/facets.d.cts +100 -0
  23. package/dist/data-table/facets.d.ts +100 -0
  24. package/dist/data-table/facets.js +98 -0
  25. package/dist/data-table/facets.js.map +1 -0
  26. package/dist/data-table/fill.cjs +299 -0
  27. package/dist/data-table/fill.cjs.map +1 -0
  28. package/dist/data-table/fill.d.cts +129 -0
  29. package/dist/data-table/fill.d.ts +129 -0
  30. package/dist/data-table/fill.js +277 -0
  31. package/dist/data-table/fill.js.map +1 -0
  32. package/dist/data-table/filter-engine.d.cts +7 -2
  33. package/dist/data-table/filter-engine.d.ts +7 -2
  34. package/dist/data-table/grid-clipboard.cjs +165 -0
  35. package/dist/data-table/grid-clipboard.cjs.map +1 -0
  36. package/dist/data-table/grid-clipboard.d.cts +85 -0
  37. package/dist/data-table/grid-clipboard.d.ts +85 -0
  38. package/dist/data-table/grid-clipboard.js +145 -0
  39. package/dist/data-table/grid-clipboard.js.map +1 -0
  40. package/dist/data-table/grid-selection.cjs +258 -0
  41. package/dist/data-table/grid-selection.cjs.map +1 -0
  42. package/dist/data-table/grid-selection.d.cts +166 -0
  43. package/dist/data-table/grid-selection.d.ts +166 -0
  44. package/dist/data-table/grid-selection.js +238 -0
  45. package/dist/data-table/grid-selection.js.map +1 -0
  46. package/dist/data-table/grouping.cjs +302 -0
  47. package/dist/data-table/grouping.cjs.map +1 -0
  48. package/dist/data-table/grouping.d.cts +119 -0
  49. package/dist/data-table/grouping.d.ts +119 -0
  50. package/dist/data-table/grouping.js +282 -0
  51. package/dist/data-table/grouping.js.map +1 -0
  52. package/dist/data-table/host.cjs.map +1 -1
  53. package/dist/data-table/host.d.cts +18 -4
  54. package/dist/data-table/host.d.ts +18 -4
  55. package/dist/data-table/host.js.map +1 -1
  56. package/dist/data-table/index.cjs +3173 -451
  57. package/dist/data-table/index.cjs.map +1 -1
  58. package/dist/data-table/index.d.cts +13 -3
  59. package/dist/data-table/index.d.ts +13 -3
  60. package/dist/data-table/index.js +3174 -451
  61. package/dist/data-table/index.js.map +1 -1
  62. package/dist/data-table/infer-filter.d.cts +7 -2
  63. package/dist/data-table/infer-filter.d.ts +7 -2
  64. package/dist/data-table/layered-filters.d.cts +7 -2
  65. package/dist/data-table/layered-filters.d.ts +7 -2
  66. package/dist/data-table/menu-targets.cjs +77 -0
  67. package/dist/data-table/menu-targets.cjs.map +1 -0
  68. package/dist/data-table/menu-targets.d.cts +108 -0
  69. package/dist/data-table/menu-targets.d.ts +108 -0
  70. package/dist/data-table/menu-targets.js +57 -0
  71. package/dist/data-table/menu-targets.js.map +1 -0
  72. package/dist/data-table/pagination.cjs.map +1 -1
  73. package/dist/data-table/pagination.js.map +1 -1
  74. package/dist/data-table/query-control.d.cts +7 -2
  75. package/dist/data-table/query-control.d.ts +7 -2
  76. package/dist/data-table/spreadsheet.cjs +1062 -0
  77. package/dist/data-table/spreadsheet.cjs.map +1 -0
  78. package/dist/data-table/spreadsheet.d.cts +153 -0
  79. package/dist/data-table/spreadsheet.d.ts +153 -0
  80. package/dist/data-table/spreadsheet.js +1042 -0
  81. package/dist/data-table/spreadsheet.js.map +1 -0
  82. package/dist/data-table/types.cjs.map +1 -1
  83. package/dist/data-table/types.d.cts +7 -2
  84. package/dist/data-table/types.d.ts +7 -2
  85. package/dist/data-table/url-state.d.cts +7 -2
  86. package/dist/data-table/url-state.d.ts +7 -2
  87. package/dist/data-table/uuid-cell.cjs.map +1 -1
  88. package/dist/data-table/uuid-cell.js.map +1 -1
  89. package/dist/data-table/validation.cjs +229 -0
  90. package/dist/data-table/validation.cjs.map +1 -0
  91. package/dist/data-table/validation.d.cts +125 -0
  92. package/dist/data-table/validation.d.ts +125 -0
  93. package/dist/data-table/validation.js +209 -0
  94. package/dist/data-table/validation.js.map +1 -0
  95. package/dist/data-table/virtual-window.cjs +203 -0
  96. package/dist/data-table/virtual-window.cjs.map +1 -0
  97. package/dist/data-table/virtual-window.d.cts +84 -0
  98. package/dist/data-table/virtual-window.d.ts +84 -0
  99. package/dist/data-table/virtual-window.js +183 -0
  100. package/dist/data-table/virtual-window.js.map +1 -0
  101. package/dist/data-table/xlsx.d.cts +7 -2
  102. package/dist/data-table/xlsx.d.ts +7 -2
  103. package/dist/field-formats/index.d.cts +2 -2
  104. package/dist/field-formats/index.d.ts +2 -2
  105. package/dist/formulas/index.cjs +1041 -0
  106. package/dist/formulas/index.cjs.map +1 -0
  107. package/dist/formulas/index.d.cts +389 -0
  108. package/dist/formulas/index.d.ts +389 -0
  109. package/dist/formulas/index.js +1019 -0
  110. package/dist/formulas/index.js.map +1 -0
  111. package/dist/{types-BdbvlF9-.d.cts → types-CJWU1Gae.d.cts} +1 -1
  112. package/dist/{types-BdbvlF9-.d.ts → types-CJWU1Gae.d.ts} +1 -1
  113. package/dist/{types-D-flTpK0.d.ts → types-Cu5_eUG1.d.ts} +268 -4
  114. package/dist/{types-Sn249eoy.d.cts → types-DrJXAAoD.d.cts} +268 -4
  115. package/package.json +129 -2
@@ -0,0 +1,389 @@
1
+ /**
2
+ * @ai-matrx/design-system/formulas — THE formula language for computed columns.
3
+ *
4
+ * This module moved here from the app so every table in the product shares
5
+ * one formula language. It stays pure: no React, no DOM, no network.
6
+ *
7
+ * A **formula column** holds nothing. Its cell is always `null` in the
8
+ * database; the value the user sees is computed, on read, from the OTHER
9
+ * columns of the SAME row. Champion: Airtable's formula field.
10
+ *
11
+ * THE THREE RULES THIS FILE OBEYS
12
+ *
13
+ * 1. **No `eval`, no `new Function`, no dynamic code.** A formula is user
14
+ * content; it is tokenized, parsed into an AST, and interpreted. Nothing a
15
+ * user types ever becomes JavaScript.
16
+ * 2. **Nothing throws.** `parseFormula` and `evaluateFormula` both return a
17
+ * discriminated result. A syntax error, a missing column, a division by
18
+ * zero and a type mismatch are all `ok: false` with a plain-English
19
+ * sentence a non-technical person can act on — never an exception, never a
20
+ * silent blank cell (THE FALLBACK LAW, `lib/field-formats/FEATURE.md`).
21
+ * 3. **The engine is pure.** It reads cells through a caller-supplied
22
+ * `resolve(name)`. It never touches Redux, Supabase, or the DOM, which is
23
+ * what makes every rule below testable.
24
+ *
25
+ * THE COERCION RULES (the whole contract, in one place)
26
+ *
27
+ * - **BLANK** is `null`, `undefined`, or `""`. All three are the same value to
28
+ * a formula, because a text cell that was cleared holds `""` and a number
29
+ * cell that was cleared holds `null`, and a user does not distinguish them.
30
+ * - **A missing column is NOT blank.** `resolve()` returns `undefined` for a
31
+ * column that does not exist (as opposed to `null` for one that is empty),
32
+ * and that is an error: `{a} + {Typo}` must say the column is unknown rather
33
+ * than quietly computing with zero.
34
+ * - **Arithmetic treats BLANK as 0.** `{a} + {b}` with `b` empty is `{a}`.
35
+ * That is the tolerant reading every spreadsheet uses, and the alternative
36
+ * (the whole cell erroring because one input is empty) makes a formula
37
+ * column useless on real, partly-filled data.
38
+ * - **Numeric strings coerce.** `"1,234"`, `" 42 "`, `"$5"` and `"3.5"` are
39
+ * numbers in arithmetic; `"n/a"` is a type error naming the value.
40
+ * - **Booleans are 1 and 0 in arithmetic**, so SUM over a checkbox column
41
+ * counts the ticks.
42
+ * - **Aggregates SKIP blanks.** `SUM`/`MIN`/`MAX`/`AVERAGE` ignore empty
43
+ * inputs entirely — `AVERAGE` divides by the count of the values that were
44
+ * actually there, and returns BLANK when there were none.
45
+ * - **Text conversion**: BLANK becomes `""`, a number becomes its shortest
46
+ * exact decimal, a boolean becomes `"true"` / `"false"`.
47
+ * - **Comparison** is numeric when both sides read as numbers, otherwise a
48
+ * plain string comparison. BLANK takes the shape of what it is compared
49
+ * against — `0` beside a number, `""` beside text — so `{a} = BLANK()`,
50
+ * `{a} = 0` and `{a} = ''` all hold for an empty cell.
51
+ * - **Truthiness** (for `IF` / `AND` / `OR` / `NOT`): BLANK is false, a
52
+ * boolean is itself, a number is true unless `0`, a string is true unless
53
+ * empty.
54
+ * - **Dates are ISO strings, read and written in UTC.** A date function
55
+ * accepts an ISO string (or a `Date`) and returns an ISO string — date-only
56
+ * (`2026-09-14`) when the input was date-only, full (`2026-09-14T…Z`)
57
+ * otherwise. UTC throughout on purpose: reading `2026-09-14` with local
58
+ * getters turns it into the 13th for half the planet.
59
+ * - **Division (and `%`) by zero is an error**, never `Infinity` and never
60
+ * `NaN`. A cell may not lie about arithmetic that did not happen.
61
+ */
62
+ type FormulaValue = string | number | boolean | null;
63
+ type BinaryOperator = "+" | "-" | "*" | "/" | "%" | "&" | "=" | "!=" | "<>" | "<" | "<=" | ">" | ">=";
64
+ type FormulaAst = {
65
+ kind: "number";
66
+ value: number;
67
+ position: number;
68
+ } | {
69
+ kind: "string";
70
+ value: string;
71
+ position: number;
72
+ } | {
73
+ kind: "boolean";
74
+ value: boolean;
75
+ position: number;
76
+ } | {
77
+ kind: "reference";
78
+ name: string;
79
+ position: number;
80
+ } | {
81
+ kind: "unary";
82
+ operator: "-";
83
+ operand: FormulaAst;
84
+ position: number;
85
+ } | {
86
+ kind: "binary";
87
+ operator: BinaryOperator;
88
+ left: FormulaAst;
89
+ right: FormulaAst;
90
+ position: number;
91
+ } | {
92
+ kind: "call";
93
+ name: FormulaFunctionName;
94
+ args: FormulaAst[];
95
+ position: number;
96
+ };
97
+ type ParseResult = {
98
+ ok: true;
99
+ ast: FormulaAst;
100
+ references: string[];
101
+ } | {
102
+ ok: false;
103
+ error: string;
104
+ position: number;
105
+ };
106
+ type FormulaResult = {
107
+ ok: true;
108
+ value: FormulaValue;
109
+ } | {
110
+ ok: false;
111
+ error: string;
112
+ };
113
+ type FormulaResultType = "number" | "text" | "boolean" | "date" | "unknown";
114
+ /** What a cell lookup may answer: a value, BLANK, or `undefined` = no such column. */
115
+ type ResolveCell = (name: string) => unknown;
116
+ /** Best-effort declared type of a column, for static result typing. */
117
+ type ResolveColumnType = (name: string) => "number" | "text" | "boolean" | "date" | undefined;
118
+ declare const FUNCTION_SPECS: {
119
+ readonly SUM: {
120
+ readonly signature: "SUM(number, …)";
121
+ readonly description: "Adds every value, ignoring empty ones.";
122
+ readonly min: 1;
123
+ readonly max: number;
124
+ readonly result: "number";
125
+ };
126
+ readonly MIN: {
127
+ readonly signature: "MIN(number, …)";
128
+ readonly description: "The smallest value, ignoring empty ones.";
129
+ readonly min: 1;
130
+ readonly max: number;
131
+ readonly result: "number";
132
+ };
133
+ readonly MAX: {
134
+ readonly signature: "MAX(number, …)";
135
+ readonly description: "The largest value, ignoring empty ones.";
136
+ readonly min: 1;
137
+ readonly max: number;
138
+ readonly result: "number";
139
+ };
140
+ readonly AVERAGE: {
141
+ readonly signature: "AVERAGE(number, …)";
142
+ readonly description: "The average of the values that are filled in. Empty values are not counted.";
143
+ readonly min: 1;
144
+ readonly max: number;
145
+ readonly result: "number";
146
+ };
147
+ readonly ROUND: {
148
+ readonly signature: "ROUND(number, places?)";
149
+ readonly description: "Rounds to the given number of decimal places (0 when omitted). Halves round away from zero.";
150
+ readonly min: 1;
151
+ readonly max: 2;
152
+ readonly result: "number";
153
+ };
154
+ readonly ABS: {
155
+ readonly signature: "ABS(number)";
156
+ readonly description: "The value without its minus sign.";
157
+ readonly min: 1;
158
+ readonly max: 1;
159
+ readonly result: "number";
160
+ };
161
+ readonly LEN: {
162
+ readonly signature: "LEN(text)";
163
+ readonly description: "How many characters the text has.";
164
+ readonly min: 1;
165
+ readonly max: 1;
166
+ readonly result: "number";
167
+ };
168
+ readonly UPPER: {
169
+ readonly signature: "UPPER(text)";
170
+ readonly description: "The text in capitals.";
171
+ readonly min: 1;
172
+ readonly max: 1;
173
+ readonly result: "text";
174
+ };
175
+ readonly LOWER: {
176
+ readonly signature: "LOWER(text)";
177
+ readonly description: "The text in lower case.";
178
+ readonly min: 1;
179
+ readonly max: 1;
180
+ readonly result: "text";
181
+ };
182
+ readonly TRIM: {
183
+ readonly signature: "TRIM(text)";
184
+ readonly description: "The text without leading or trailing spaces.";
185
+ readonly min: 1;
186
+ readonly max: 1;
187
+ readonly result: "text";
188
+ };
189
+ readonly CONCATENATE: {
190
+ readonly signature: "CONCATENATE(text, …)";
191
+ readonly description: "Joins every value into one piece of text.";
192
+ readonly min: 1;
193
+ readonly max: number;
194
+ readonly result: "text";
195
+ };
196
+ readonly LEFT: {
197
+ readonly signature: "LEFT(text, count)";
198
+ readonly description: "The first few characters of the text.";
199
+ readonly min: 2;
200
+ readonly max: 2;
201
+ readonly result: "text";
202
+ };
203
+ readonly RIGHT: {
204
+ readonly signature: "RIGHT(text, count)";
205
+ readonly description: "The last few characters of the text.";
206
+ readonly min: 2;
207
+ readonly max: 2;
208
+ readonly result: "text";
209
+ };
210
+ readonly CONTAINS: {
211
+ readonly signature: "CONTAINS(text, part)";
212
+ readonly description: "Yes when the text contains that part. Upper and lower case are treated the same.";
213
+ readonly min: 2;
214
+ readonly max: 2;
215
+ readonly result: "boolean";
216
+ };
217
+ readonly IF: {
218
+ readonly signature: "IF(condition, then, otherwise?)";
219
+ readonly description: "The second value when the condition holds, otherwise the third (empty when omitted).";
220
+ readonly min: 2;
221
+ readonly max: 3;
222
+ readonly result: "unknown";
223
+ };
224
+ readonly AND: {
225
+ readonly signature: "AND(condition, …)";
226
+ readonly description: "Yes when every condition holds.";
227
+ readonly min: 1;
228
+ readonly max: number;
229
+ readonly result: "boolean";
230
+ };
231
+ readonly OR: {
232
+ readonly signature: "OR(condition, …)";
233
+ readonly description: "Yes when at least one condition holds.";
234
+ readonly min: 1;
235
+ readonly max: number;
236
+ readonly result: "boolean";
237
+ };
238
+ readonly NOT: {
239
+ readonly signature: "NOT(condition)";
240
+ readonly description: "Turns yes into no and no into yes.";
241
+ readonly min: 1;
242
+ readonly max: 1;
243
+ readonly result: "boolean";
244
+ };
245
+ readonly BLANK: {
246
+ readonly signature: "BLANK()";
247
+ readonly description: "An empty value, for comparing against or returning.";
248
+ readonly min: 0;
249
+ readonly max: 0;
250
+ readonly result: "unknown";
251
+ };
252
+ readonly ISBLANK: {
253
+ readonly signature: "ISBLANK(value)";
254
+ readonly description: "Yes when the value is empty.";
255
+ readonly min: 1;
256
+ readonly max: 1;
257
+ readonly result: "boolean";
258
+ };
259
+ readonly TODAY: {
260
+ readonly signature: "TODAY()";
261
+ readonly description: "Today's date.";
262
+ readonly min: 0;
263
+ readonly max: 0;
264
+ readonly result: "date";
265
+ };
266
+ readonly NOW: {
267
+ readonly signature: "NOW()";
268
+ readonly description: "The current date and time.";
269
+ readonly min: 0;
270
+ readonly max: 0;
271
+ readonly result: "date";
272
+ };
273
+ readonly DATEDIFF: {
274
+ readonly signature: "DATEDIFF(from, to, 'days' | 'hours' | 'minutes')";
275
+ readonly description: "How far the second date is after the first. Negative when it is earlier.";
276
+ readonly min: 3;
277
+ readonly max: 3;
278
+ readonly result: "number";
279
+ };
280
+ readonly YEAR: {
281
+ readonly signature: "YEAR(date)";
282
+ readonly description: "The four-digit year of the date.";
283
+ readonly min: 1;
284
+ readonly max: 1;
285
+ readonly result: "number";
286
+ };
287
+ readonly MONTH: {
288
+ readonly signature: "MONTH(date)";
289
+ readonly description: "The month of the date, 1 to 12.";
290
+ readonly min: 1;
291
+ readonly max: 1;
292
+ readonly result: "number";
293
+ };
294
+ readonly DAY: {
295
+ readonly signature: "DAY(date)";
296
+ readonly description: "The day of the month, 1 to 31.";
297
+ readonly min: 1;
298
+ readonly max: 1;
299
+ readonly result: "number";
300
+ };
301
+ readonly DATEADD: {
302
+ readonly signature: "DATEADD(date, count, 'days' | 'months' | 'years')";
303
+ readonly description: "The date moved forward by that many units. Use a negative count to go back.";
304
+ readonly min: 3;
305
+ readonly max: 3;
306
+ readonly result: "date";
307
+ };
308
+ };
309
+ type FormulaFunctionName = keyof typeof FUNCTION_SPECS;
310
+ /** The help list the formula editor shows. Order is the order it renders in. */
311
+ declare const FORMULA_FUNCTIONS: readonly {
312
+ name: FormulaFunctionName;
313
+ signature: string;
314
+ description: string;
315
+ }[];
316
+ /**
317
+ * Turn formula text into an AST plus the list of columns it reads.
318
+ *
319
+ * `references` holds every `{…}` name exactly as typed, in first-use order —
320
+ * the caller resolves them (display name OR machine field name) through its own
321
+ * lookup, so this module never needs to know the table.
322
+ */
323
+ declare function parseFormula(source: string): ParseResult;
324
+ /**
325
+ * Compute one cell. NEVER throws.
326
+ *
327
+ * `resolve(name)` is given the name exactly as it was typed between the braces
328
+ * and must return the cell's value, or `undefined` when no such column exists —
329
+ * the difference between "empty" and "misspelt", which is the difference
330
+ * between a working formula and a wrong answer.
331
+ */
332
+ declare function evaluateFormula(ast: FormulaAst, resolve: ResolveCell): FormulaResult;
333
+ /**
334
+ * Best-effort: what kind of value will this formula produce? The UI uses it to
335
+ * pick a sensible display format for the computed column. `unknown` is always a
336
+ * legal answer — never guess a format on a shaky reading.
337
+ */
338
+ declare function formulaResultType(ast: FormulaAst, columnType: ResolveColumnType): FormulaResultType;
339
+ /** The slice of a field row this helper needs to find and evaluate formulas. */
340
+ interface ComputedColumnField {
341
+ field_name: string;
342
+ display_name: string;
343
+ data_type: string;
344
+ metadata?: unknown;
345
+ }
346
+ interface ComputedColumn<F extends ComputedColumnField = ComputedColumnField> {
347
+ field: F;
348
+ parsed: ParseResult;
349
+ }
350
+ /** True when the column's declared format is `formula`. */
351
+ declare function isFormulaColumn(field: ComputedColumnField): boolean;
352
+ /** Every formula column among `fields`, each with its expression parsed once. */
353
+ declare function formulaColumnsOf<F extends ComputedColumnField>(fields: readonly F[]): ComputedColumn<F>[];
354
+ interface ComputedRowsResult<R> {
355
+ rows: R[];
356
+ /** `${rowId}::${fieldName}` → the plain-English reason that cell shows #ERROR. */
357
+ errors: Map<string, string>;
358
+ /** Machine names of the formula columns, for callers that must skip them. */
359
+ formulaFieldNames: Set<string>;
360
+ }
361
+ /**
362
+ * Return `rows` with every formula column's value computed from the row's
363
+ * other cells. Pure; the input rows are never mutated. When `fields` holds no
364
+ * formula column the SAME array is returned, so callers pay nothing.
365
+ *
366
+ * Formula columns are evaluated in `fields` order, and each one is written into
367
+ * the working copy of the row before the next runs — so a later formula may
368
+ * reference an earlier one. References resolve by machine name first, then by
369
+ * display name (case-insensitive), matching the grid.
370
+ */
371
+ declare function withComputedColumns<R extends {
372
+ id: string;
373
+ data: Record<string, unknown>;
374
+ }, F extends ComputedColumnField>(rows: readonly R[], fields: readonly F[]): ComputedRowsResult<R>;
375
+ /**
376
+ * Rewrite every `{from}` reference in `expression` to `{to}` — what keeps a
377
+ * formula working when the column it names is renamed (Airtable and Sheets do
378
+ * this silently; a rename that turned a working column into #ERROR would be
379
+ * the platform punishing the user for tidying up).
380
+ *
381
+ * Walks the source with the tokenizer's own rules for the two things that
382
+ * matter: a `{…}` inside a quoted string is TEXT and is left alone, and `\`
383
+ * escapes the next character inside a string. The match is on the trimmed
384
+ * name, case-insensitive — the same comparison `withComputedColumns` makes.
385
+ * Returns the SAME string when nothing referenced `from`.
386
+ */
387
+ declare function rewriteFormulaReferences(expression: string, from: string, to: string): string;
388
+
389
+ export { type BinaryOperator, type ComputedColumn, type ComputedColumnField, type ComputedRowsResult, FORMULA_FUNCTIONS, type FormulaAst, type FormulaFunctionName, type FormulaResult, type FormulaResultType, type FormulaValue, type ParseResult, type ResolveCell, type ResolveColumnType, evaluateFormula, formulaColumnsOf, formulaResultType, isFormulaColumn, parseFormula, rewriteFormulaReferences, withComputedColumns };