@svgrid/enterprise 3.0.1 → 3.0.2

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 (197) hide show
  1. package/dist/SvFormulaBar.svelte +606 -0
  2. package/dist/SvFormulaBar.svelte.d.ts +62 -0
  3. package/dist/SvPivotDesigner.svelte +65 -14
  4. package/dist/SvRibbonIcon.svelte +46 -0
  5. package/dist/SvRibbonIcon.svelte.d.ts +17 -0
  6. package/dist/SvSchemaChart.svelte +4 -2
  7. package/dist/SvSheet.svelte +4114 -0
  8. package/dist/SvSheet.svelte.d.ts +142 -0
  9. package/dist/SvSheetComment.svelte +98 -0
  10. package/dist/SvSheetComment.svelte.d.ts +22 -0
  11. package/dist/SvSheetConditionalFormat.svelte +162 -0
  12. package/dist/SvSheetConditionalFormat.svelte.d.ts +14 -0
  13. package/dist/SvSheetDataValidation.svelte +249 -0
  14. package/dist/SvSheetDataValidation.svelte.d.ts +14 -0
  15. package/dist/SvSheetFilterMenu.svelte +217 -0
  16. package/dist/SvSheetFilterMenu.svelte.d.ts +17 -0
  17. package/dist/SvSheetFindReplace.svelte +132 -0
  18. package/dist/SvSheetFindReplace.svelte.d.ts +10 -0
  19. package/dist/SvSheetFormatCells.svelte +421 -0
  20. package/dist/SvSheetFormatCells.svelte.d.ts +17 -0
  21. package/dist/SvSheetGoalSeek.svelte +144 -0
  22. package/dist/SvSheetGoalSeek.svelte.d.ts +12 -0
  23. package/dist/SvSheetInsertFunction.svelte +147 -0
  24. package/dist/SvSheetInsertFunction.svelte.d.ts +8 -0
  25. package/dist/SvSheetListPicker.svelte +89 -0
  26. package/dist/SvSheetListPicker.svelte.d.ts +16 -0
  27. package/dist/SvSheetManageRules.svelte +185 -0
  28. package/dist/SvSheetManageRules.svelte.d.ts +16 -0
  29. package/dist/SvSheetNameManager.svelte +225 -0
  30. package/dist/SvSheetNameManager.svelte.d.ts +11 -0
  31. package/dist/SvSheetPasteSpecial.svelte +105 -0
  32. package/dist/SvSheetPasteSpecial.svelte.d.ts +12 -0
  33. package/dist/SvSheetRemoveDuplicates.svelte +149 -0
  34. package/dist/SvSheetRemoveDuplicates.svelte.d.ts +12 -0
  35. package/dist/SvSheetRibbon.svelte +1201 -0
  36. package/dist/SvSheetRibbon.svelte.d.ts +34 -0
  37. package/dist/SvSheetSizeDialog.svelte +58 -0
  38. package/dist/SvSheetSizeDialog.svelte.d.ts +11 -0
  39. package/dist/SvSheetTabs.svelte +441 -0
  40. package/dist/SvSheetTabs.svelte.d.ts +36 -0
  41. package/dist/SvSheetTabs.test-harness.svelte.d.ts +17 -0
  42. package/dist/SvSheetTabs.test-harness.svelte.js +22 -0
  43. package/dist/SvSheetTextToColumns.svelte +172 -0
  44. package/dist/SvSheetTextToColumns.svelte.d.ts +13 -0
  45. package/dist/SvSheetValidationAlert.svelte +83 -0
  46. package/dist/SvSheetValidationAlert.svelte.d.ts +15 -0
  47. package/dist/cdn/svgrid-enterprise.svelte-external.js +18997 -5396
  48. package/dist/designer/assets/GridMenus-BlsvL_aU.js +8 -0
  49. package/dist/designer/assets/SvChartMenu-BYO9cYdy.css +1 -0
  50. package/dist/designer/assets/SvChartMenu-D9hEeHar.js +1 -0
  51. package/dist/designer/assets/SvDateRangeInput-BBRzrQeg.js +1 -0
  52. package/dist/designer/assets/SvDateTimePicker-DARvKUL2.js +1 -0
  53. package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +4 -0
  54. package/dist/designer/assets/SvGridChart-B8j1SSy3.js +3 -0
  55. package/dist/designer/assets/SvGridChart-BgLuPO7I.css +1 -0
  56. package/dist/designer/assets/SvGridChartBuilder-08YWWeqY.css +1 -0
  57. package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +1 -0
  58. package/dist/designer/assets/SvGridChartPanel-4Pc8y5yO.css +1 -0
  59. package/dist/designer/assets/SvGridChartPanel-pT6ITc2P.js +4 -0
  60. package/dist/designer/assets/{SvGridChartView-DUc-1RUf.css → SvGridChartView-7msfnWZT.css} +1 -1
  61. package/dist/designer/assets/SvGridChartView-bg281UA1.js +1 -0
  62. package/dist/designer/assets/SvListBox-BDS66lmZ.js +110 -0
  63. package/dist/designer/assets/SvMenuList-DJ47ba1h.css +1 -0
  64. package/dist/designer/assets/SvMenuList-Dgq2D5VN.js +1 -0
  65. package/dist/designer/assets/SvTabs-DKmwb5p1.css +1 -0
  66. package/dist/designer/assets/SvTabs-UFCMTHXS.js +1 -0
  67. package/dist/designer/assets/chart-cIPUsbM5.js +1 -0
  68. package/dist/designer/assets/chart-export-B6bkQ3X8.js +11 -0
  69. package/dist/designer/assets/chart-export-pdf-BbA28-gt.js +11 -0
  70. package/dist/designer/assets/chart-panel-messages-DtTxpBUU.js +1 -0
  71. package/dist/designer/assets/chart-summary-Czu_5epb.js +1 -0
  72. package/dist/designer/assets/chart-trend-D5I5VEe8.js +1 -0
  73. package/dist/designer/assets/chart-validate-BMqM-qkF.js +1 -0
  74. package/dist/designer/assets/column-resize-BYDzR1Ve.js +1 -0
  75. package/dist/designer/assets/date-format-B8JbEtIG.js +1 -0
  76. package/dist/designer/assets/date-format-DKS-z0xS.css +1 -0
  77. package/dist/designer/assets/editor-contract-Bpoa7A5g.js +1 -0
  78. package/dist/designer/assets/focus-trap-CAreAhlU.js +1 -0
  79. package/dist/designer/assets/index-CMFgAoVV.css +1 -0
  80. package/dist/designer/assets/{index-C_a9Cj8Y.js → index-DwU7CAMm.js} +291 -290
  81. package/dist/designer/assets/list-option-BP_dWS66.js +1 -0
  82. package/dist/designer/assets/row-resize-DLktcqUK.js +1 -0
  83. package/dist/designer/assets/src-CITpcm6b.js +1 -0
  84. package/dist/designer/assets/src-EdI3Xqds.js +58 -0
  85. package/dist/designer/index.html +23 -14
  86. package/dist/export-pdf.d.ts +89 -0
  87. package/dist/export-pdf.js +130 -0
  88. package/dist/export.js +17 -10
  89. package/dist/index.d.ts +64 -1
  90. package/dist/index.js +68 -1
  91. package/dist/install.js +5 -0
  92. package/dist/node/studio.js +64 -2
  93. package/dist/pivot-chart.d.ts +25 -1
  94. package/dist/pivot-chart.js +25 -69
  95. package/dist/sheet/address.d.ts +43 -0
  96. package/dist/sheet/address.js +81 -0
  97. package/dist/sheet/ast.d.ts +94 -0
  98. package/dist/sheet/ast.js +56 -0
  99. package/dist/sheet/auto-filter.d.ts +66 -0
  100. package/dist/sheet/auto-filter.js +147 -0
  101. package/dist/sheet/autocomplete.d.ts +42 -0
  102. package/dist/sheet/autocomplete.js +162 -0
  103. package/dist/sheet/coerce.d.ts +31 -0
  104. package/dist/sheet/coerce.js +122 -0
  105. package/dist/sheet/commands.d.ts +89 -0
  106. package/dist/sheet/commands.js +230 -0
  107. package/dist/sheet/comments.d.ts +29 -0
  108. package/dist/sheet/comments.js +73 -0
  109. package/dist/sheet/conditional-formats.d.ts +144 -0
  110. package/dist/sheet/conditional-formats.js +316 -0
  111. package/dist/sheet/deps.d.ts +60 -0
  112. package/dist/sheet/deps.js +199 -0
  113. package/dist/sheet/document.d.ts +150 -0
  114. package/dist/sheet/document.js +264 -0
  115. package/dist/sheet/edit-keys.d.ts +14 -0
  116. package/dist/sheet/edit-keys.js +40 -0
  117. package/dist/sheet/entry.d.ts +31 -0
  118. package/dist/sheet/entry.js +76 -0
  119. package/dist/sheet/evaluate.d.ts +61 -0
  120. package/dist/sheet/evaluate.js +337 -0
  121. package/dist/sheet/find-replace.d.ts +62 -0
  122. package/dist/sheet/find-replace.js +152 -0
  123. package/dist/sheet/format-store.d.ts +99 -0
  124. package/dist/sheet/format-store.js +233 -0
  125. package/dist/sheet/freeze.d.ts +54 -0
  126. package/dist/sheet/freeze.js +58 -0
  127. package/dist/sheet/function-catalog.d.ts +10 -0
  128. package/dist/sheet/function-catalog.js +94 -0
  129. package/dist/sheet/functions.d.ts +28 -0
  130. package/dist/sheet/functions.js +362 -0
  131. package/dist/sheet/goal-seek.d.ts +73 -0
  132. package/dist/sheet/goal-seek.js +153 -0
  133. package/dist/sheet/index.d.ts +53 -0
  134. package/dist/sheet/index.js +53 -0
  135. package/dist/sheet/merges.d.ts +71 -0
  136. package/dist/sheet/merges.js +137 -0
  137. package/dist/sheet/names.d.ts +31 -0
  138. package/dist/sheet/names.js +87 -0
  139. package/dist/sheet/navigate.d.ts +52 -0
  140. package/dist/sheet/navigate.js +135 -0
  141. package/dist/sheet/number-format.d.ts +63 -0
  142. package/dist/sheet/number-format.js +508 -0
  143. package/dist/sheet/palette.d.ts +19 -0
  144. package/dist/sheet/palette.js +84 -0
  145. package/dist/sheet/parse.d.ts +13 -0
  146. package/dist/sheet/parse.js +108 -0
  147. package/dist/sheet/paste-special.d.ts +164 -0
  148. package/dist/sheet/paste-special.js +592 -0
  149. package/dist/sheet/protection.d.ts +21 -0
  150. package/dist/sheet/protection.js +48 -0
  151. package/dist/sheet/rects.d.ts +45 -0
  152. package/dist/sheet/rects.js +112 -0
  153. package/dist/sheet/refs.d.ts +82 -0
  154. package/dist/sheet/refs.js +266 -0
  155. package/dist/sheet/ribbon-icons.d.ts +31 -0
  156. package/dist/sheet/ribbon-icons.js +350 -0
  157. package/dist/sheet/ribbon.d.ts +173 -0
  158. package/dist/sheet/ribbon.js +753 -0
  159. package/dist/sheet/shortcuts.d.ts +164 -0
  160. package/dist/sheet/shortcuts.js +623 -0
  161. package/dist/sheet/structure.d.ts +87 -0
  162. package/dist/sheet/structure.js +166 -0
  163. package/dist/sheet/tables.d.ts +70 -0
  164. package/dist/sheet/tables.js +147 -0
  165. package/dist/sheet/tokenize.d.ts +54 -0
  166. package/dist/sheet/tokenize.js +304 -0
  167. package/dist/sheet/transforms.d.ts +76 -0
  168. package/dist/sheet/transforms.js +154 -0
  169. package/dist/sheet/validation.d.ts +92 -0
  170. package/dist/sheet/validation.js +241 -0
  171. package/dist/sheet/workbook.d.ts +72 -0
  172. package/dist/sheet/workbook.js +409 -0
  173. package/dist/sheet-enable.d.ts +6 -0
  174. package/dist/sheet-enable.js +46 -0
  175. package/dist/studio/ui-components.generated.js +63 -1
  176. package/dist/version.d.ts +1 -1
  177. package/dist/version.js +1 -1
  178. package/package.json +9 -4
  179. package/dist/designer/assets/GridMenus-B1JtIN21.js +0 -8
  180. package/dist/designer/assets/SvDateRangeInput-CjO7nn_x.js +0 -1
  181. package/dist/designer/assets/SvDateTimePicker-ByBD_ov6.js +0 -1
  182. package/dist/designer/assets/SvField-YDLipR6O.css +0 -1
  183. package/dist/designer/assets/SvField-cj1PFNgZ.js +0 -1
  184. package/dist/designer/assets/SvGridCellEditor-0W1L2hJ1.js +0 -2
  185. package/dist/designer/assets/SvGridChart-DBOR4xcz.js +0 -2
  186. package/dist/designer/assets/SvGridChart-fkMWeh1J.css +0 -1
  187. package/dist/designer/assets/SvGridChartPanel-symrhNnR.js +0 -11
  188. package/dist/designer/assets/SvGridChartView-BmRxq6mU.js +0 -1
  189. package/dist/designer/assets/SvListBox-1oUF6Iav.js +0 -110
  190. package/dist/designer/assets/chart-DXFganU8.js +0 -1
  191. package/dist/designer/assets/column-resize-C_inr5zT.js +0 -1
  192. package/dist/designer/assets/date-format-DGagAqRc.css +0 -1
  193. package/dist/designer/assets/date-format-onlYDsrY.js +0 -1
  194. package/dist/designer/assets/easing-zaypKrr0.js +0 -3
  195. package/dist/designer/assets/index-k2stW6L8.css +0 -1
  196. package/dist/designer/assets/row-resize-B0FWHcNr.js +0 -1
  197. package/dist/designer/assets/src-D9p27OGC.js +0 -58
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Keys are "rowId columnId" with each half percent-encoded.
3
+ *
4
+ * Encoding is what makes the key reversible. Ids come from the grid and may
5
+ * contain spaces, so a plain join cannot be split back apart - and `hydrate`
6
+ * has to split it, or the row and column indexes come back empty and
7
+ * `forgetRow` / `forgetColumn` become silent no-ops on a restored store.
8
+ */
9
+ function keyOf(rowId, columnId) {
10
+ return `${encodeURIComponent(rowId)} ${encodeURIComponent(columnId)}`;
11
+ }
12
+ function splitKey(key) {
13
+ const gap = key.indexOf(' ');
14
+ if (gap < 0)
15
+ return null;
16
+ try {
17
+ return {
18
+ rowId: decodeURIComponent(key.slice(0, gap)),
19
+ columnId: decodeURIComponent(key.slice(gap + 1)),
20
+ };
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ export function createFormatStore(initial) {
27
+ const cells = new Map();
28
+ const rowsIndex = new Map();
29
+ const colsIndex = new Map();
30
+ function remember(rowId, columnId, key) {
31
+ let byRow = rowsIndex.get(rowId);
32
+ if (!byRow) {
33
+ byRow = new Set();
34
+ rowsIndex.set(rowId, byRow);
35
+ }
36
+ byRow.add(key);
37
+ let byCol = colsIndex.get(columnId);
38
+ if (!byCol) {
39
+ byCol = new Set();
40
+ colsIndex.set(columnId, byCol);
41
+ }
42
+ byCol.add(key);
43
+ }
44
+ function eachCell(rects, at, fn) {
45
+ const seen = new Set();
46
+ for (const [minRow, minCol, maxRow, maxCol] of rects) {
47
+ for (let r = minRow; r <= maxRow; r += 1) {
48
+ const rowId = at.rowIdAt(r);
49
+ if (rowId === null)
50
+ continue;
51
+ for (let c = minCol; c <= maxCol; c += 1) {
52
+ const columnId = at.columnIdAt(c);
53
+ if (columnId === null)
54
+ continue;
55
+ // Overlapping ranges must not apply a toggle twice.
56
+ const key = keyOf(rowId, columnId);
57
+ if (seen.has(key))
58
+ continue;
59
+ seen.add(key);
60
+ fn(rowId, columnId);
61
+ }
62
+ }
63
+ }
64
+ }
65
+ const store = {
66
+ get(rowId, columnId) {
67
+ return cells.get(keyOf(rowId, columnId));
68
+ },
69
+ set(rects, patch, at) {
70
+ eachCell(rects, at, (rowId, columnId) => {
71
+ const key = keyOf(rowId, columnId);
72
+ const next = { ...(cells.get(key) ?? {}), ...patch };
73
+ // Strip keys explicitly set to undefined so an entry does not grow
74
+ // a field that means nothing.
75
+ for (const [k, v] of Object.entries(next)) {
76
+ if (v === undefined)
77
+ delete next[k];
78
+ }
79
+ if (Object.keys(next).length === 0) {
80
+ cells.delete(key);
81
+ return;
82
+ }
83
+ cells.set(key, next);
84
+ remember(rowId, columnId, key);
85
+ });
86
+ },
87
+ clear(rects, at) {
88
+ eachCell(rects, at, (rowId, columnId) => {
89
+ cells.delete(keyOf(rowId, columnId));
90
+ });
91
+ },
92
+ toggle(rects, field, at) {
93
+ // Excel's rule, and the one users expect: a mixed selection turns ON.
94
+ let all = true;
95
+ eachCell(rects, at, (rowId, columnId) => {
96
+ if (!cells.get(keyOf(rowId, columnId))?.[field])
97
+ all = false;
98
+ });
99
+ // `set` treats undefined as "remove this field", so one pass does both
100
+ // directions.
101
+ store.set(rects, { [field]: all ? undefined : true }, at);
102
+ },
103
+ forgetRow(rowId) {
104
+ for (const key of rowsIndex.get(rowId) ?? [])
105
+ cells.delete(key);
106
+ rowsIndex.delete(rowId);
107
+ },
108
+ forgetColumn(columnId) {
109
+ for (const key of colsIndex.get(columnId) ?? [])
110
+ cells.delete(key);
111
+ colsIndex.delete(columnId);
112
+ },
113
+ get size() {
114
+ return cells.size;
115
+ },
116
+ serialize() {
117
+ return Object.fromEntries(cells);
118
+ },
119
+ hydrate(entries) {
120
+ cells.clear();
121
+ rowsIndex.clear();
122
+ colsIndex.clear();
123
+ for (const [key, entry] of Object.entries(entries)) {
124
+ cells.set(key, entry);
125
+ // Rebuild the indexes, or forgetRow / forgetColumn do nothing on a
126
+ // store that came back from storage.
127
+ const parts = splitKey(key);
128
+ if (parts)
129
+ remember(parts.rowId, parts.columnId, key);
130
+ }
131
+ },
132
+ clearAll() {
133
+ cells.clear();
134
+ rowsIndex.clear();
135
+ colsIndex.clear();
136
+ },
137
+ remapRows(fn) {
138
+ const next = {};
139
+ for (const [key, entry] of cells) {
140
+ const parts = splitKey(key);
141
+ if (!parts)
142
+ continue;
143
+ const rowId = fn(parts.rowId);
144
+ if (rowId !== null)
145
+ next[keyOf(rowId, parts.columnId)] = entry;
146
+ }
147
+ store.hydrate(next);
148
+ },
149
+ remapColumns(fn) {
150
+ const next = {};
151
+ for (const [key, entry] of cells) {
152
+ const parts = splitKey(key);
153
+ if (!parts)
154
+ continue;
155
+ const columnId = fn(parts.columnId);
156
+ if (columnId !== null)
157
+ next[keyOf(parts.rowId, columnId)] = entry;
158
+ }
159
+ store.hydrate(next);
160
+ },
161
+ };
162
+ if (initial)
163
+ store.hydrate(initial);
164
+ return store;
165
+ }
166
+ /** Turn an entry into inline style text for a cell renderer. */
167
+ export function entryToStyle(entry) {
168
+ if (!entry)
169
+ return '';
170
+ const parts = [];
171
+ if (entry.bold)
172
+ parts.push('font-weight:700');
173
+ if (entry.italic)
174
+ parts.push('font-style:italic');
175
+ if (entry.underline && entry.strike)
176
+ parts.push('text-decoration:underline line-through');
177
+ else if (entry.underline)
178
+ parts.push('text-decoration:underline');
179
+ else if (entry.strike)
180
+ parts.push('text-decoration:line-through');
181
+ if (entry.color)
182
+ parts.push(`color:${entry.color}`);
183
+ if (entry.fill)
184
+ parts.push(`background:${entry.fill}`);
185
+ if (entry.align)
186
+ parts.push(`text-align:${entry.align}`);
187
+ if (entry.fontFamily)
188
+ parts.push(`font-family:${entry.fontFamily}`);
189
+ if (entry.fontSize)
190
+ parts.push(`font-size:${entry.fontSize}px`);
191
+ if (entry.wrap)
192
+ parts.push('white-space:pre-wrap');
193
+ if (entry.indent)
194
+ parts.push(`padding-left:${entry.indent * 12}px`);
195
+ const borders = borderShadows(entry.border);
196
+ if (borders)
197
+ parts.push(`box-shadow:${borders}`);
198
+ return parts.join(';');
199
+ }
200
+ /**
201
+ * Cell borders as inset shadows, one per side.
202
+ *
203
+ * The cell span fills its td edge to edge, so an inset shadow along one
204
+ * edge is a border that costs no layout: a real border would push the text
205
+ * and change the cell's size, and a bordered cell next to a plain one would
206
+ * misalign. Shadows stack, so a cell can carry any combination of sides.
207
+ */
208
+ export function borderShadows(border) {
209
+ if (!border)
210
+ return '';
211
+ const parts = [];
212
+ const line = (spec) => ({
213
+ w: spec?.width ?? 1,
214
+ c: spec?.color ?? 'currentColor',
215
+ });
216
+ if (border.top) {
217
+ const { w, c } = line(border.top);
218
+ parts.push(`inset 0 ${w}px 0 0 ${c}`);
219
+ }
220
+ if (border.bottom) {
221
+ const { w, c } = line(border.bottom);
222
+ parts.push(`inset 0 -${w}px 0 0 ${c}`);
223
+ }
224
+ if (border.left) {
225
+ const { w, c } = line(border.left);
226
+ parts.push(`inset ${w}px 0 0 0 ${c}`);
227
+ }
228
+ if (border.right) {
229
+ const { w, c } = line(border.right);
230
+ parts.push(`inset -${w}px 0 0 0 ${c}`);
231
+ }
232
+ return parts.join(',');
233
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Freeze panes, over what the grid already has.
3
+ *
4
+ * Columns freeze through `api.setColumnPinning({ left: [...] })`, which
5
+ * makes them sticky and excludes them from the horizontal scroll, and rows
6
+ * through the grid's `frozenRows` prop, set here with `api.setOption`: the
7
+ * first N rows stay under the header, still the grid's own rows, editable
8
+ * and numbered, while the virtualized body scrolls beneath them. Both halves
9
+ * go through the api, so Freeze Panes is one call for any consumer.
10
+ *
11
+ * `splitFrozenRows` stays for a grid that renders its own pinned band from
12
+ * `pinnedTopRows` instead.
13
+ */
14
+ import type { GridCommandContext } from '@svgrid/grid/shortcuts';
15
+ export type FreezeState = {
16
+ /** How many leading rows should be pinned. */
17
+ rows: number;
18
+ /** How many leading columns should be pinned. */
19
+ cols: number;
20
+ };
21
+ export type FreezeSplit<TData> = {
22
+ /** Pass as `pinnedTopRows`. */
23
+ pinnedTopRows: ReadonlyArray<TData>;
24
+ /** Pass as `data`. The pinned rows are REMOVED, so nothing renders twice. */
25
+ bodyRows: ReadonlyArray<TData>;
26
+ };
27
+ /**
28
+ * Split a row array for a frozen-row count.
29
+ *
30
+ * ```svelte
31
+ * {@const split = splitFrozenRows(rows, freeze.rows)}
32
+ * <SvGrid data={split.bodyRows} pinnedTopRows={split.pinnedTopRows} ... />
33
+ * ```
34
+ */
35
+ export declare function splitFrozenRows<TData>(rows: ReadonlyArray<TData>, count: number): FreezeSplit<TData>;
36
+ /** Column ids left of `cols`, which is what column pinning takes. */
37
+ export declare function frozenColumnIds(cmd: GridCommandContext, cols: number): string[];
38
+ /**
39
+ * Apply both halves through the api and report the state: the columns pin,
40
+ * the rows freeze. Zero rows clears the row half.
41
+ */
42
+ export declare function applyFreeze(cmd: GridCommandContext, state: FreezeState): FreezeState;
43
+ /**
44
+ * Excel's Freeze Panes: everything above and to the left of the active cell
45
+ * freezes. With the cursor on B3 you get two frozen rows and one frozen
46
+ * column.
47
+ */
48
+ export declare function freezeAtActiveCell(cmd: GridCommandContext): FreezeState;
49
+ /** Freeze Top Row. */
50
+ export declare function freezeTopRow(cmd: GridCommandContext): FreezeState;
51
+ /** Freeze First Column. */
52
+ export declare function freezeFirstColumn(cmd: GridCommandContext): FreezeState;
53
+ /** Unfreeze everything. */
54
+ export declare function unfreeze(cmd: GridCommandContext): FreezeState;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Split a row array for a frozen-row count.
3
+ *
4
+ * ```svelte
5
+ * {@const split = splitFrozenRows(rows, freeze.rows)}
6
+ * <SvGrid data={split.bodyRows} pinnedTopRows={split.pinnedTopRows} ... />
7
+ * ```
8
+ */
9
+ export function splitFrozenRows(rows, count) {
10
+ const n = Math.max(0, Math.min(Math.floor(count), rows.length));
11
+ if (n === 0)
12
+ return { pinnedTopRows: [], bodyRows: rows };
13
+ return { pinnedTopRows: rows.slice(0, n), bodyRows: rows.slice(n) };
14
+ }
15
+ /** Column ids left of `cols`, which is what column pinning takes. */
16
+ export function frozenColumnIds(cmd, cols) {
17
+ const out = [];
18
+ for (let c = 0; c < Math.min(cols, cmd.colCount); c += 1) {
19
+ const id = cmd.columnIdAt(c);
20
+ if (id !== null)
21
+ out.push(id);
22
+ }
23
+ return out;
24
+ }
25
+ /**
26
+ * Apply both halves through the api and report the state: the columns pin,
27
+ * the rows freeze. Zero rows clears the row half.
28
+ */
29
+ export function applyFreeze(cmd, state) {
30
+ const api = cmd.api;
31
+ api.setColumnPinning?.({ left: frozenColumnIds(cmd, state.cols) });
32
+ api.setOption?.('frozenRows', state.rows > 0 ? state.rows : undefined);
33
+ return state;
34
+ }
35
+ /**
36
+ * Excel's Freeze Panes: everything above and to the left of the active cell
37
+ * freezes. With the cursor on B3 you get two frozen rows and one frozen
38
+ * column.
39
+ */
40
+ export function freezeAtActiveCell(cmd) {
41
+ const active = cmd.activeCell;
42
+ const state = active
43
+ ? { rows: active.rowIndex, cols: active.colIndex }
44
+ : { rows: 0, cols: 0 };
45
+ return applyFreeze(cmd, state);
46
+ }
47
+ /** Freeze Top Row. */
48
+ export function freezeTopRow(cmd) {
49
+ return applyFreeze(cmd, { rows: 1, cols: 0 });
50
+ }
51
+ /** Freeze First Column. */
52
+ export function freezeFirstColumn(cmd) {
53
+ return applyFreeze(cmd, { rows: 0, cols: 1 });
54
+ }
55
+ /** Unfreeze everything. */
56
+ export function unfreeze(cmd) {
57
+ return applyFreeze(cmd, { rows: 0, cols: 0 });
58
+ }
@@ -0,0 +1,10 @@
1
+ export type FunctionGroup = 'Math' | 'Statistical' | 'Logical' | 'Information' | 'Text' | 'Date & Time' | 'Lookup & Reference' | 'Other';
2
+ export type FunctionInfo = {
3
+ name: string;
4
+ group: FunctionGroup;
5
+ signature: string;
6
+ description: string;
7
+ };
8
+ export declare const FUNCTION_GROUPS: ReadonlyArray<FunctionGroup>;
9
+ /** Every function the engine knows, described, alphabetical. */
10
+ export declare function functionCatalog(): FunctionInfo[];
@@ -0,0 +1,94 @@
1
+ /**
2
+ * What Insert Function shows for each function: its group, the argument
3
+ * list, and one line on what it does. The engine's table (`FUNCTIONS`) is
4
+ * the source of truth for which names exist; a name missing here is listed
5
+ * with a bare `NAME(...)` and no description rather than left out, so a
6
+ * custom function registered through `withCustomFunctions` appears too.
7
+ */
8
+ import { FUNCTIONS } from './functions.js';
9
+ import { SIGNATURES } from './autocomplete.js';
10
+ const CATALOG = {
11
+ SUM: { group: 'Math', description: 'Adds all the numbers in a range of cells.', signature: 'SUM(number1, [number2], ...)' },
12
+ ABS: { group: 'Math', description: 'Returns the absolute value of a number, a number without its sign.', signature: 'ABS(number)' },
13
+ INT: { group: 'Math', description: 'Rounds a number down to the nearest integer.', signature: 'INT(number)' },
14
+ MOD: { group: 'Math', description: 'Returns the remainder after a number is divided by a divisor.', signature: 'MOD(number, divisor)' },
15
+ POWER: { group: 'Math', description: 'Returns the result of a number raised to a power.', signature: 'POWER(number, power)' },
16
+ SQRT: { group: 'Math', description: 'Returns the square root of a number.', signature: 'SQRT(number)' },
17
+ ROUND: { group: 'Math', description: 'Rounds a number to a specified number of digits.' },
18
+ ROUNDUP: { group: 'Math', description: 'Rounds a number up, away from zero.', signature: 'ROUNDUP(number, digits)' },
19
+ ROUNDDOWN: { group: 'Math', description: 'Rounds a number down, toward zero.', signature: 'ROUNDDOWN(number, digits)' },
20
+ SUMIF: { group: 'Math', description: 'Adds the cells specified by a given condition or criteria.' },
21
+ SUMIFS: { group: 'Math', description: 'Adds the cells specified by a given set of conditions or criteria.' },
22
+ AVERAGE: { group: 'Statistical', description: 'Returns the average (arithmetic mean) of its arguments.', signature: 'AVERAGE(number1, [number2], ...)' },
23
+ AVG: { group: 'Statistical', description: 'The same as AVERAGE.', signature: 'AVG(number1, [number2], ...)' },
24
+ MIN: { group: 'Statistical', description: 'Returns the smallest number in a set of values.', signature: 'MIN(number1, [number2], ...)' },
25
+ MAX: { group: 'Statistical', description: 'Returns the largest value in a set of values.', signature: 'MAX(number1, [number2], ...)' },
26
+ COUNT: { group: 'Statistical', description: 'Counts the number of cells in a range that contain numbers.', signature: 'COUNT(value1, [value2], ...)' },
27
+ COUNTA: { group: 'Statistical', description: 'Counts the number of cells in a range that are not empty.', signature: 'COUNTA(value1, [value2], ...)' },
28
+ COUNTBLANK: { group: 'Statistical', description: 'Counts the number of empty cells in a range.', signature: 'COUNTBLANK(range)' },
29
+ MEDIAN: { group: 'Statistical', description: 'Returns the median, the number in the middle of a set of numbers.', signature: 'MEDIAN(number1, [number2], ...)' },
30
+ STDEV: { group: 'Statistical', description: 'Estimates standard deviation based on a sample.', signature: 'STDEV(number1, [number2], ...)' },
31
+ RANK: { group: 'Statistical', description: 'Returns the rank of a number in a list of numbers.', signature: 'RANK(number, ref, [order])' },
32
+ COUNTIF: { group: 'Statistical', description: 'Counts the number of cells within a range that meet the given condition.' },
33
+ COUNTIFS: { group: 'Statistical', description: 'Counts the number of cells specified by a given set of conditions.' },
34
+ AVERAGEIF: { group: 'Statistical', description: 'Finds the average of the cells specified by a given condition.' },
35
+ IF: { group: 'Logical', description: 'Checks whether a condition is met, and returns one value if TRUE and another if FALSE.' },
36
+ IFS: { group: 'Logical', description: 'Checks whether one or more conditions are met and returns a value corresponding to the first TRUE condition.' },
37
+ IFERROR: { group: 'Logical', description: 'Returns a value you specify if a formula evaluates to an error; otherwise, returns the result of the formula.' },
38
+ IFNA: { group: 'Logical', description: 'Returns the value you specify if the expression resolves to #N/A, otherwise returns the result of the expression.', signature: 'IFNA(value, fallback)' },
39
+ SWITCH: { group: 'Logical', description: 'Evaluates an expression against a list of values and returns the result corresponding to the first matching value.' },
40
+ AND: { group: 'Logical', description: 'Checks whether all arguments are TRUE, and returns TRUE if all arguments are TRUE.', signature: 'AND(logical1, [logical2], ...)' },
41
+ OR: { group: 'Logical', description: 'Checks whether any of the arguments are TRUE, and returns TRUE or FALSE.', signature: 'OR(logical1, [logical2], ...)' },
42
+ NOT: { group: 'Logical', description: 'Changes FALSE to TRUE, or TRUE to FALSE.', signature: 'NOT(logical)' },
43
+ XOR: { group: 'Logical', description: 'Returns a logical exclusive OR of all arguments.', signature: 'XOR(logical1, [logical2], ...)' },
44
+ ISNUMBER: { group: 'Information', description: 'Checks whether a value is a number, and returns TRUE or FALSE.', signature: 'ISNUMBER(value)' },
45
+ ISTEXT: { group: 'Information', description: 'Checks whether a value is text, and returns TRUE or FALSE.', signature: 'ISTEXT(value)' },
46
+ ISLOGICAL: { group: 'Information', description: 'Checks whether a value is a logical value (TRUE or FALSE), and returns TRUE or FALSE.', signature: 'ISLOGICAL(value)' },
47
+ ISBLANK: { group: 'Information', description: 'Checks whether a reference is to an empty cell, and returns TRUE or FALSE.', signature: 'ISBLANK(value)' },
48
+ LEN: { group: 'Text', description: 'Returns the number of characters in a text string.', signature: 'LEN(text)' },
49
+ LEFT: { group: 'Text', description: 'Returns the specified number of characters from the start of a text string.', signature: 'LEFT(text, [count])' },
50
+ RIGHT: { group: 'Text', description: 'Returns the specified number of characters from the end of a text string.', signature: 'RIGHT(text, [count])' },
51
+ MID: { group: 'Text', description: 'Returns the characters from the middle of a text string, given a starting position and length.' },
52
+ UPPER: { group: 'Text', description: 'Converts a text string to all uppercase letters.', signature: 'UPPER(text)' },
53
+ LOWER: { group: 'Text', description: 'Converts all letters in a text string to lowercase.', signature: 'LOWER(text)' },
54
+ TRIM: { group: 'Text', description: 'Removes all spaces from a text string except for single spaces between words.', signature: 'TRIM(text)' },
55
+ CONCAT: { group: 'Text', description: 'Concatenates a list or range of text strings.', signature: 'CONCAT(text1, [text2], ...)' },
56
+ CONCATENATE: { group: 'Text', description: 'Joins several text strings into one text string.', signature: 'CONCATENATE(text1, [text2], ...)' },
57
+ TEXTJOIN: { group: 'Text', description: 'Concatenates a list or range of text strings using a delimiter.' },
58
+ SUBSTITUTE: { group: 'Text', description: 'Replaces existing text with new text in a text string.' },
59
+ FIND: { group: 'Text', description: 'Returns the starting position of one text string within another; case-sensitive.', signature: 'FIND(find, within, [start])' },
60
+ SEARCH: { group: 'Text', description: 'Returns the position of one text string within another; not case-sensitive.', signature: 'SEARCH(find, within, [start])' },
61
+ TEXT: { group: 'Text', description: 'Converts a value to text in a specific number format.' },
62
+ TODAY: { group: 'Date & Time', description: "Returns the current date formatted as a date.", signature: 'TODAY()' },
63
+ NOW: { group: 'Date & Time', description: 'Returns the current date and time formatted as a date and time.', signature: 'NOW()' },
64
+ YEAR: { group: 'Date & Time', description: 'Returns the year of a date, an integer in the range 1900 - 9999.', signature: 'YEAR(date)' },
65
+ MONTH: { group: 'Date & Time', description: 'Returns the month, a number from 1 (January) to 12 (December).', signature: 'MONTH(date)' },
66
+ DAY: { group: 'Date & Time', description: 'Returns the day of the month, a number from 1 to 31.', signature: 'DAY(date)' },
67
+ DATE: { group: 'Date & Time', description: 'Returns the date for a given year, month and day.' },
68
+ EOMONTH: { group: 'Date & Time', description: 'Returns the last day of the month before or after a specified number of months.' },
69
+ DAYS: { group: 'Date & Time', description: 'Returns the number of days between two dates.', signature: 'DAYS(end_date, start_date)' },
70
+ DATEDIF: { group: 'Date & Time', description: 'Calculates the number of days, months or years between two dates.', signature: 'DATEDIF(start_date, end_date, unit)' },
71
+ VLOOKUP: { group: 'Lookup & Reference', description: 'Looks for a value in the leftmost column of a table, and returns a value in the same row from a column you specify.' },
72
+ HLOOKUP: { group: 'Lookup & Reference', description: 'Looks for a value in the top row of a table, and returns a value in the same column from a row you specify.' },
73
+ XLOOKUP: { group: 'Lookup & Reference', description: 'Searches a range for a match and returns the corresponding item from a second range.' },
74
+ INDEX: { group: 'Lookup & Reference', description: 'Returns a value from a range at the intersection of a given row and column.' },
75
+ MATCH: { group: 'Lookup & Reference', description: 'Returns the relative position of an item in a range that matches a specified value.' },
76
+ };
77
+ /** The IF family is dispatched by the evaluator, not the function table. */
78
+ const EVALUATOR_FUNCTIONS = ['IF', 'IFS', 'IFERROR', 'IFNA', 'SWITCH'];
79
+ export const FUNCTION_GROUPS = [
80
+ 'Math', 'Statistical', 'Logical', 'Information', 'Text', 'Date & Time', 'Lookup & Reference', 'Other',
81
+ ];
82
+ /** Every function the engine knows, described, alphabetical. */
83
+ export function functionCatalog() {
84
+ const names = new Set([...Object.keys(FUNCTIONS), ...EVALUATOR_FUNCTIONS]);
85
+ return [...names].sort().map((name) => {
86
+ const entry = CATALOG[name];
87
+ return {
88
+ name,
89
+ group: entry?.group ?? 'Other',
90
+ signature: entry?.signature ?? SIGNATURES[name] ?? `${name}(...)`,
91
+ description: entry?.description ?? '',
92
+ };
93
+ });
94
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The function table.
3
+ *
4
+ * Each entry receives its arguments already evaluated, in two shapes:
5
+ * - `flat` every argument flattened into one list, ranges expanded. What
6
+ * SUM and COUNT want.
7
+ * - `args` one list per argument, so a function can tell `SUM(A1:A3, 5)`
8
+ * from `SUM(A1:A3)` and `SUMIF` can line a range up against a
9
+ * parallel one.
10
+ * - `grids` the 2-D shape of any range argument, kept for VLOOKUP / INDEX /
11
+ * MATCH, which lose meaning once flattened.
12
+ *
13
+ * Functions that must NOT evaluate every argument (IF, IFERROR, AND, OR with
14
+ * short-circuit semantics) are handled in the evaluator instead, because by the
15
+ * time a table entry runs, evaluation has already happened.
16
+ */
17
+ import { isError, type CellValue } from './ast.js';
18
+ export type FnArgs = {
19
+ flat: ReadonlyArray<CellValue>;
20
+ args: ReadonlyArray<ReadonlyArray<CellValue>>;
21
+ grids: ReadonlyArray<ReadonlyArray<ReadonlyArray<CellValue>> | null>;
22
+ };
23
+ export type SheetFunction = (a: FnArgs) => CellValue;
24
+ export declare const FUNCTIONS: Record<string, SheetFunction>;
25
+ /** Merge caller-supplied functions over the built-ins. Keys are uppercased so
26
+ * a consumer can register `myFn` and write `=MYFN()`. */
27
+ export declare function withCustomFunctions(custom: Record<string, SheetFunction> | undefined): Record<string, SheetFunction>;
28
+ export { isError };