@svgrid/enterprise 3.0.2 → 3.1.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 (364) hide show
  1. package/LICENSE +94 -24
  2. package/README.md +36 -4
  3. package/dist/SvAdvancedFilter.svelte +1 -1
  4. package/dist/SvAlertsManager.svelte +2 -1
  5. package/dist/SvBoard.svelte +2 -1
  6. package/dist/SvExportMenu.svelte +4 -1
  7. package/dist/SvExportMenu.svelte.d.ts +0 -13
  8. package/dist/SvExpressionEditor.svelte +3 -3
  9. package/dist/SvFormulaBar.svelte +94 -20
  10. package/dist/SvFormulaBar.svelte.d.ts +7 -0
  11. package/dist/SvGridAlerts.svelte +49 -9
  12. package/dist/SvGridBoard.svelte +13 -8
  13. package/dist/SvGridBulkEditDrawer.svelte +26 -2
  14. package/dist/SvGridEditPanel.svelte +3 -0
  15. package/dist/SvGridScheduler.svelte +69 -40
  16. package/dist/SvGridSelectionBar.svelte +10 -3
  17. package/dist/SvPivotDesigner.svelte +198 -40
  18. package/dist/SvPivotDesigner.svelte.d.ts +27 -20
  19. package/dist/SvSheet.svelte +4043 -243
  20. package/dist/SvSheet.svelte.d.ts +76 -3
  21. package/dist/SvSheetChartSetup.svelte +151 -0
  22. package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
  23. package/dist/SvSheetComment.svelte +216 -31
  24. package/dist/SvSheetComment.svelte.d.ts +11 -11
  25. package/dist/SvSheetConditionalFormat.svelte +28 -31
  26. package/dist/SvSheetDataValidation.svelte +66 -42
  27. package/dist/SvSheetEditRanges.svelte +217 -0
  28. package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
  29. package/dist/SvSheetErrors.svelte +125 -0
  30. package/dist/SvSheetErrors.svelte.d.ts +20 -0
  31. package/dist/SvSheetEvaluate.svelte +133 -0
  32. package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
  33. package/dist/SvSheetFilterMenu.svelte +137 -34
  34. package/dist/SvSheetFilterMenu.svelte.d.ts +5 -0
  35. package/dist/SvSheetFindReplace.svelte +19 -19
  36. package/dist/SvSheetFormatCells.svelte +125 -81
  37. package/dist/SvSheetGoalSeek.svelte +17 -16
  38. package/dist/SvSheetInsertFunction.svelte +15 -13
  39. package/dist/SvSheetIteration.svelte +81 -0
  40. package/dist/SvSheetIteration.svelte.d.ts +10 -0
  41. package/dist/SvSheetLink.svelte +99 -0
  42. package/dist/SvSheetLink.svelte.d.ts +17 -0
  43. package/dist/SvSheetListPicker.svelte +4 -2
  44. package/dist/SvSheetListPicker.svelte.d.ts +0 -6
  45. package/dist/SvSheetManageRules.svelte +20 -18
  46. package/dist/SvSheetNameManager.svelte +17 -15
  47. package/dist/SvSheetPageSetup.svelte +159 -0
  48. package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
  49. package/dist/SvSheetPasteSpecial.svelte +22 -20
  50. package/dist/SvSheetPivot.svelte +220 -0
  51. package/dist/SvSheetPivot.svelte.d.ts +21 -0
  52. package/dist/SvSheetProtectSheet.svelte +81 -0
  53. package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
  54. package/dist/SvSheetRemoveDuplicates.svelte +13 -10
  55. package/dist/SvSheetRibbon.svelte +104 -51
  56. package/dist/SvSheetSizeDialog.svelte +4 -2
  57. package/dist/SvSheetSort.svelte +218 -0
  58. package/dist/SvSheetSort.svelte.d.ts +28 -0
  59. package/dist/SvSheetSparklines.svelte +135 -0
  60. package/dist/SvSheetSparklines.svelte.d.ts +14 -0
  61. package/dist/SvSheetTable.svelte +160 -0
  62. package/dist/SvSheetTable.svelte.d.ts +24 -0
  63. package/dist/SvSheetTabs.svelte +161 -31
  64. package/dist/SvSheetTabs.svelte.d.ts +22 -8
  65. package/dist/SvSheetTextToColumns.svelte +20 -20
  66. package/dist/SvSheetValidationAlert.svelte +8 -6
  67. package/dist/advanced-filter-enable.js +1 -1
  68. package/dist/alerts/alert-engine.d.ts +6 -0
  69. package/dist/alerts/alert-engine.js +21 -4
  70. package/dist/alerts/alert-formats.js +2 -0
  71. package/dist/alerts/alert-types.d.ts +1 -1
  72. package/dist/alerts.d.ts +1 -1
  73. package/dist/alerts.js +2 -2
  74. package/dist/board.js +2 -2
  75. package/dist/bulk-edit.d.ts +3 -1
  76. package/dist/bulk-edit.js +1 -1
  77. package/dist/cdn/svgrid-enterprise.svelte-external.js +39827 -16429
  78. package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
  79. package/dist/designer/assets/{SvChartMenu-D9hEeHar.js → SvChartMenu-BDoeqGz6.js} +1 -1
  80. package/dist/designer/assets/{SvDateTimePicker-DARvKUL2.js → SvDateTimePicker-DCPg7WGN.js} +1 -1
  81. package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
  82. package/dist/designer/assets/{SvGridChart-B8j1SSy3.js → SvGridChart-Cy1ATrWh.js} +2 -2
  83. package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
  84. package/dist/designer/assets/{SvGridChartPanel-pT6ITc2P.js → SvGridChartPanel-CATdVc9X.js} +3 -3
  85. package/dist/designer/assets/{SvGridChartView-bg281UA1.js → SvGridChartView-CmsZtCED.js} +1 -1
  86. package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
  87. package/dist/designer/assets/{SvTabs-UFCMTHXS.js → SvTabs-2mHC6oaz.js} +1 -1
  88. package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
  89. package/dist/designer/assets/{chart-cIPUsbM5.js → chart-Cn7MnNqA.js} +1 -1
  90. package/dist/designer/assets/{chart-panel-messages-DtTxpBUU.js → chart-panel-messages-Dz7PTIqT.js} +1 -1
  91. package/dist/designer/assets/{chart-summary-Czu_5epb.js → chart-summary-BD1qYB2R.js} +1 -1
  92. package/dist/designer/assets/{chart-trend-D5I5VEe8.js → chart-trend-B8xr5LuD.js} +1 -1
  93. package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
  94. package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
  95. package/dist/designer/assets/{focus-trap-CAreAhlU.js → focus-trap-V2-6Fy9I.js} +1 -1
  96. package/dist/designer/assets/{index-DwU7CAMm.js → index-BSjv6Qec.js} +317 -315
  97. package/dist/designer/assets/index-_JVFxt02.css +1 -0
  98. package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
  99. package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
  100. package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
  101. package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
  102. package/dist/designer/index.html +17 -16
  103. package/dist/export-pdf.d.ts +75 -0
  104. package/dist/export-pdf.js +216 -15
  105. package/dist/export.js +10 -2
  106. package/dist/gantt/SvGridGantt.svelte +2890 -0
  107. package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
  108. package/dist/gantt/gantt-config.d.ts +73 -0
  109. package/dist/gantt/gantt-config.js +1 -0
  110. package/dist/gantt/gantt-critical-path.d.ts +67 -0
  111. package/dist/gantt/gantt-critical-path.js +207 -0
  112. package/dist/gantt/gantt-model.d.ts +257 -0
  113. package/dist/gantt/gantt-model.js +651 -0
  114. package/dist/gantt/gantt-resources.d.ts +59 -0
  115. package/dist/gantt/gantt-resources.js +71 -0
  116. package/dist/gantt/gantt.d.ts +7 -0
  117. package/dist/gantt/gantt.js +36 -0
  118. package/dist/gantt/index.d.ts +15 -0
  119. package/dist/gantt/index.js +22 -0
  120. package/dist/gantt/timeline-arrows.d.ts +102 -0
  121. package/dist/gantt/timeline-arrows.js +181 -0
  122. package/dist/import.d.ts +2 -2
  123. package/dist/import.js +1 -1
  124. package/dist/index.d.ts +34 -7
  125. package/dist/index.js +44 -7
  126. package/dist/install.js +8 -1
  127. package/dist/license-core.d.ts +17 -1
  128. package/dist/license-core.js +16 -5
  129. package/dist/license.d.ts +18 -2
  130. package/dist/license.js +71 -6
  131. package/dist/node/studio.js +140 -8
  132. package/dist/pivot-enable.js +2 -2
  133. package/dist/scheduler-dependencies.d.ts +35 -0
  134. package/dist/scheduler-dependencies.js +36 -1
  135. package/dist/scheduler.js +2 -2
  136. package/dist/selection-bar.js +2 -2
  137. package/dist/server/SvGroupCell.svelte +213 -0
  138. package/dist/server/SvGroupCell.svelte.d.ts +62 -0
  139. package/dist/server/SvRowGroupPanel.svelte +322 -0
  140. package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
  141. package/dist/server/enable.d.ts +17 -0
  142. package/dist/server/enable.js +49 -0
  143. package/dist/server/index.d.ts +22 -0
  144. package/dist/server/index.js +24 -0
  145. package/dist/server/messages.d.ts +45 -0
  146. package/dist/server/messages.js +35 -0
  147. package/dist/server/server-group-model.d.ts +104 -0
  148. package/dist/server/server-group-model.js +272 -0
  149. package/dist/server/server-pivot.d.ts +46 -0
  150. package/dist/server/server-pivot.js +57 -0
  151. package/dist/server/server-row-model.d.ts +547 -0
  152. package/dist/server/server-row-model.js +1551 -0
  153. package/dist/server/server-selection.d.ts +99 -0
  154. package/dist/server/server-selection.js +215 -0
  155. package/dist/server/svgrid-adapter.d.ts +155 -0
  156. package/dist/server/svgrid-adapter.js +202 -0
  157. package/dist/sheet/ast.d.ts +45 -1
  158. package/dist/sheet/ast.js +14 -0
  159. package/dist/sheet/auto-filter.d.ts +58 -4
  160. package/dist/sheet/auto-filter.js +159 -11
  161. package/dist/sheet/autocomplete.d.ts +9 -0
  162. package/dist/sheet/autocomplete.js +90 -4
  163. package/dist/sheet/cell-images.d.ts +39 -0
  164. package/dist/sheet/cell-images.js +90 -0
  165. package/dist/sheet/cell-types.d.ts +58 -0
  166. package/dist/sheet/cell-types.js +96 -0
  167. package/dist/sheet/coerce.d.ts +40 -0
  168. package/dist/sheet/coerce.js +170 -3
  169. package/dist/sheet/comments.d.ts +43 -9
  170. package/dist/sheet/comments.js +85 -27
  171. package/dist/sheet/conditional-formats.d.ts +29 -6
  172. package/dist/sheet/conditional-formats.js +37 -12
  173. package/dist/sheet/csv.d.ts +32 -0
  174. package/dist/sheet/csv.js +158 -0
  175. package/dist/sheet/culture.d.ts +87 -0
  176. package/dist/sheet/culture.js +247 -0
  177. package/dist/sheet/delta.d.ts +102 -0
  178. package/dist/sheet/delta.js +203 -0
  179. package/dist/sheet/deps.d.ts +45 -1
  180. package/dist/sheet/deps.js +77 -2
  181. package/dist/sheet/document.d.ts +106 -4
  182. package/dist/sheet/document.js +204 -3
  183. package/dist/sheet/engine.d.ts +67 -0
  184. package/dist/sheet/engine.js +19 -0
  185. package/dist/sheet/entry.d.ts +8 -4
  186. package/dist/sheet/entry.js +171 -21
  187. package/dist/sheet/error-check.d.ts +49 -0
  188. package/dist/sheet/error-check.js +83 -0
  189. package/dist/sheet/evaluate-steps.d.ts +48 -0
  190. package/dist/sheet/evaluate-steps.js +196 -0
  191. package/dist/sheet/evaluate.d.ts +67 -0
  192. package/dist/sheet/evaluate.js +725 -13
  193. package/dist/sheet/filter-files.d.ts +37 -0
  194. package/dist/sheet/filter-files.js +465 -0
  195. package/dist/sheet/format-store.d.ts +15 -0
  196. package/dist/sheet/format-store.js +11 -1
  197. package/dist/sheet/from-rows.d.ts +14 -0
  198. package/dist/sheet/from-rows.js +50 -0
  199. package/dist/sheet/function-catalog.d.ts +1 -1
  200. package/dist/sheet/function-catalog.js +296 -5
  201. package/dist/sheet/functions.js +363 -91
  202. package/dist/sheet/index.d.ts +35 -8
  203. package/dist/sheet/index.js +35 -8
  204. package/dist/sheet/links.d.ts +57 -0
  205. package/dist/sheet/links.js +174 -0
  206. package/dist/sheet/messages.d.ts +778 -0
  207. package/dist/sheet/messages.js +806 -0
  208. package/dist/sheet/number-format.d.ts +52 -5
  209. package/dist/sheet/number-format.js +465 -68
  210. package/dist/sheet/objects.d.ts +106 -0
  211. package/dist/sheet/objects.js +149 -0
  212. package/dist/sheet/ods-document.d.ts +44 -0
  213. package/dist/sheet/ods-document.js +1275 -0
  214. package/dist/sheet/open-file.d.ts +26 -0
  215. package/dist/sheet/open-file.js +56 -0
  216. package/dist/sheet/outline.d.ts +82 -0
  217. package/dist/sheet/outline.js +228 -0
  218. package/dist/sheet/packs/array.d.ts +16 -0
  219. package/dist/sheet/packs/array.js +172 -0
  220. package/dist/sheet/packs/database.d.ts +42 -0
  221. package/dist/sheet/packs/database.js +142 -0
  222. package/dist/sheet/packs/engineering.d.ts +2 -0
  223. package/dist/sheet/packs/engineering.js +296 -0
  224. package/dist/sheet/packs/financial.d.ts +5 -0
  225. package/dist/sheet/packs/financial.js +220 -0
  226. package/dist/sheet/packs/math-stats.d.ts +2 -0
  227. package/dist/sheet/packs/math-stats.js +372 -0
  228. package/dist/sheet/packs/special.d.ts +44 -0
  229. package/dist/sheet/packs/special.js +187 -0
  230. package/dist/sheet/packs/stats-dist.d.ts +2 -0
  231. package/dist/sheet/packs/stats-dist.js +785 -0
  232. package/dist/sheet/packs/text-date.d.ts +2 -0
  233. package/dist/sheet/packs/text-date.js +332 -0
  234. package/dist/sheet/packs/trig.d.ts +2 -0
  235. package/dist/sheet/packs/trig.js +73 -0
  236. package/dist/sheet/page-setup.d.ts +73 -0
  237. package/dist/sheet/page-setup.js +73 -0
  238. package/dist/sheet/parse.js +42 -10
  239. package/dist/sheet/paste-special.d.ts +22 -0
  240. package/dist/sheet/paste-special.js +14 -5
  241. package/dist/sheet/pivot-range.d.ts +160 -0
  242. package/dist/sheet/pivot-range.js +333 -0
  243. package/dist/sheet/presence.d.ts +73 -0
  244. package/dist/sheet/presence.js +79 -0
  245. package/dist/sheet/print.d.ts +104 -0
  246. package/dist/sheet/print.js +169 -0
  247. package/dist/sheet/protection.d.ts +55 -1
  248. package/dist/sheet/protection.js +55 -2
  249. package/dist/sheet/rects.d.ts +1 -1
  250. package/dist/sheet/refs.d.ts +48 -0
  251. package/dist/sheet/refs.js +155 -8
  252. package/dist/sheet/ribbon-icons.d.ts +1 -1
  253. package/dist/sheet/ribbon-icons.js +186 -0
  254. package/dist/sheet/ribbon.d.ts +1 -1
  255. package/dist/sheet/ribbon.js +324 -23
  256. package/dist/sheet/sheet-kinds.d.ts +74 -0
  257. package/dist/sheet/sheet-kinds.js +91 -0
  258. package/dist/sheet/shortcuts.d.ts +13 -3
  259. package/dist/sheet/shortcuts.js +63 -12
  260. package/dist/sheet/sort.d.ts +51 -0
  261. package/dist/sheet/sort.js +107 -0
  262. package/dist/sheet/sparklines.d.ts +111 -0
  263. package/dist/sheet/sparklines.js +204 -0
  264. package/dist/sheet/table-styles.d.ts +74 -0
  265. package/dist/sheet/table-styles.js +152 -0
  266. package/dist/sheet/tables.d.ts +19 -0
  267. package/dist/sheet/tables.js +31 -0
  268. package/dist/sheet/tokenize.d.ts +18 -1
  269. package/dist/sheet/tokenize.js +60 -9
  270. package/dist/sheet/validation.d.ts +16 -0
  271. package/dist/sheet/validation.js +37 -0
  272. package/dist/sheet/workbook.d.ts +148 -3
  273. package/dist/sheet/workbook.js +742 -31
  274. package/dist/sheet/xls-cfb.d.ts +32 -0
  275. package/dist/sheet/xls-cfb.js +290 -0
  276. package/dist/sheet/xls-document.d.ts +10 -0
  277. package/dist/sheet/xls-document.js +1243 -0
  278. package/dist/sheet/xls-formula.d.ts +40 -0
  279. package/dist/sheet/xls-formula.js +569 -0
  280. package/dist/sheet/xlsx-document.d.ts +108 -0
  281. package/dist/sheet/xlsx-document.js +1849 -0
  282. package/dist/sheet/xlsx-drawing.d.ts +99 -0
  283. package/dist/sheet/xlsx-drawing.js +420 -0
  284. package/dist/sheet-enable.js +6 -7
  285. package/dist/sheet-text.d.ts +7 -0
  286. package/dist/sheet-text.js +29 -0
  287. package/dist/sources/auth-supabase.js +2 -2
  288. package/dist/sources/realtime-supabase.js +2 -2
  289. package/dist/sources/rest.d.ts +6 -2
  290. package/dist/sources/rest.js +42 -7
  291. package/dist/sources/supabase.d.ts +10 -1
  292. package/dist/sources/supabase.js +73 -40
  293. package/dist/studio/emit-project.js +14 -1
  294. package/dist/studio/index.js +1 -1
  295. package/dist/studio/project.d.ts +11 -2
  296. package/dist/studio/project.js +5 -2
  297. package/dist/studio/ui-components.generated.js +107 -2
  298. package/dist/sveltekit/in-memory.d.ts +2 -2
  299. package/dist/sveltekit/in-memory.js +125 -4
  300. package/dist/sveltekit/index.d.ts +1 -1
  301. package/dist/sveltekit/index.js +1 -1
  302. package/dist/sveltekit/query-plan.d.ts +50 -4
  303. package/dist/sveltekit/query-plan.js +25 -3
  304. package/dist/sveltekit/sql-source.d.ts +6 -0
  305. package/dist/sveltekit/sql-source.js +34 -6
  306. package/dist/sveltekit/sql.d.ts +31 -0
  307. package/dist/sveltekit/sql.js +135 -25
  308. package/dist/sveltekit/transport.d.ts +10 -2
  309. package/dist/sveltekit/transport.js +30 -6
  310. package/dist/upgrade-prompt.d.ts +1 -1
  311. package/dist/version.d.ts +1 -1
  312. package/dist/version.js +1 -1
  313. package/dist/watermark.js +35 -2
  314. package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
  315. package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
  316. package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
  317. package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
  318. package/dist/wc/SvField-B_kurx_P.js +149 -0
  319. package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
  320. package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
  321. package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
  322. package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
  323. package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
  324. package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
  325. package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
  326. package/dist/wc/SvModal-DrfOYYyX.js +189 -0
  327. package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
  328. package/dist/wc/chart-6OXlybVT.js +4341 -0
  329. package/dist/wc/chart-export-CeSADGfi.js +135 -0
  330. package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
  331. package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
  332. package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
  333. package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
  334. package/dist/wc/client-DQIzjDBG.js +3064 -0
  335. package/dist/wc/column-resize-DUPgynvc.js +101 -0
  336. package/dist/wc/date-format-DS-z_h9v.js +1130 -0
  337. package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
  338. package/dist/wc/editor-contract-peBDxir_.js +22 -0
  339. package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
  340. package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
  341. package/dist/wc/list-option-DrRyivWp.js +82 -0
  342. package/dist/wc/popover-WsGlvtQv.js +69 -0
  343. package/dist/wc/positioning-BiKLfu1E.js +112 -0
  344. package/dist/wc/react.d.ts +41 -0
  345. package/dist/wc/react.js +90 -0
  346. package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
  347. package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
  348. package/dist/wc/row-resize-limG_N1z.js +111 -0
  349. package/dist/wc/sv-sheet-element.d.ts +97 -0
  350. package/dist/wc/sv-sheet-element.js +44213 -0
  351. package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
  352. package/dist/wc/validate-BqDthkNr.js +88 -0
  353. package/dist/wc/vue.d.ts +31 -0
  354. package/dist/wc/vue.js +75 -0
  355. package/package.json +30 -5
  356. package/dist/designer/assets/GridMenus-BlsvL_aU.js +0 -8
  357. package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +0 -4
  358. package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +0 -1
  359. package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
  360. package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
  361. package/dist/designer/assets/index-CMFgAoVV.css +0 -1
  362. package/dist/designer/assets/row-resize-DLktcqUK.js +0 -1
  363. package/dist/designer/assets/src-EdI3Xqds.js +0 -58
  364. package/dist/designer/assets/validate-h-aslRV9.js +0 -1
@@ -4,7 +4,10 @@
4
4
  * shapes without importing each other.
5
5
  */
6
6
  import type { CellRef } from './address.js';
7
- export type SheetError = '#REF!' | '#CYCLE!' | '#DIV/0!' | '#VALUE!' | '#NAME?' | '#NUM!' | '#N/A' | '#PARSE!';
7
+ export type SheetError = '#REF!' | '#CYCLE!' | '#DIV/0!' | '#VALUE!' | '#NAME?' | '#NUM!' | '#N/A' | '#PARSE!' | '#SPILL!' | '#CALC!'
8
+ /** Excel's empty intersection. Nothing here produces it; a file can
9
+ * carry it, and a formula can name it, so it is one of the values. */
10
+ | '#NULL!';
8
11
  /** A computed cell value. Errors are values, not exceptions, once evaluation
9
12
  * finishes - that is what lets `=IFERROR(A1, 0)` see one. */
10
13
  export type CellValue = string | number | boolean | {
@@ -16,6 +19,10 @@ export declare function isError(v: CellValue): v is {
16
19
  export declare function err(code: SheetError): {
17
20
  error: SheetError;
18
21
  };
22
+ /** The error a typed text stands for, or null when it is ordinary text. */
23
+ export declare function typedError(text: string): {
24
+ error: SheetError;
25
+ } | null;
19
26
  /** Thrown during evaluation and caught at the boundary, where it becomes a
20
27
  * value. Carrying the code on a real Error keeps stack traces useful in dev
21
28
  * without the evaluator having to thread a result type through every branch. */
@@ -33,12 +40,30 @@ export type Node = {
33
40
  k: 'bool';
34
41
  v: boolean;
35
42
  }
43
+ /** An error written INTO a formula: `=#N/A`, `=IFERROR(A1, #N/A)`. Excel
44
+ * takes one as a value, and a file from Excel, Google Sheets or
45
+ * LibreOffice can carry an error cell as a formula that is only this. */
46
+ | {
47
+ k: 'err';
48
+ v: SheetError;
49
+ }
36
50
  /** A single cell. `ref.row` is never null here; a column-only reference
37
51
  * parses as a range instead. */
38
52
  | {
39
53
  k: 'ref';
40
54
  ref: CellRef;
41
55
  }
56
+ /**
57
+ * The spilled-range operator, `A1#`: the rectangle a dynamic array
58
+ * anchored at `ref` currently spills into. Like a table reference, it is
59
+ * NOT resolved to a range here - the rectangle depends on how far the
60
+ * array spills right now, which changes as the array grows, so it is
61
+ * resolved against the workbook at evaluation. `ref.row` is never null.
62
+ */
63
+ | {
64
+ k: 'spill';
65
+ ref: CellRef;
66
+ }
42
67
  /** A rectangle. Either end's row may be null, meaning a whole-column ref
43
68
  * that runs to the last used row of the sheet. */
44
69
  | {
@@ -46,6 +71,19 @@ export type Node = {
46
71
  from: CellRef;
47
72
  to: CellRef;
48
73
  }
74
+ /**
75
+ * A 3D reference: `Sheet1:Sheet3!A1` or `Jan:Dec!B5:B10`. The same cell or
76
+ * rectangle on every sheet from `sheetFrom` to `sheetTo` in tab order,
77
+ * inclusive. `from`/`to` carry no sheet of their own (the sheets are the
78
+ * range); resolved against the workbook's sheet order at evaluation, so a
79
+ * tab inserted between the two joins the sum, as Excel's does. */
80
+ | {
81
+ k: 'ref3d';
82
+ sheetFrom: string;
83
+ sheetTo: string;
84
+ from: CellRef;
85
+ to: CellRef;
86
+ }
49
87
  /** A defined name (`=Tax`), resolved against the workbook at evaluation. */
50
88
  | {
51
89
  k: 'name';
@@ -83,6 +121,12 @@ export type Node = {
83
121
  k: 'fn';
84
122
  name: string;
85
123
  args: Node[];
124
+ }
125
+ /** An omitted argument: the gap in `PMT(rate, nper, pv, , 1)`. Reads as a
126
+ * blank, so a function sees its default the way it does when the
127
+ * argument is simply left off the end. */
128
+ | {
129
+ k: 'empty';
86
130
  };
87
131
  export type BinaryOp = '+' | '-' | '*' | '/' | '^' | '&' | '=' | '<>' | '<' | '>' | '<=' | '>=';
88
132
  /** Binding power. Comparison loosest, then concat, then arithmetic. */
package/dist/sheet/ast.js CHANGED
@@ -4,6 +4,20 @@ export function isError(v) {
4
4
  export function err(code) {
5
5
  return { error: code };
6
6
  }
7
+ /** The error codes a user can type into a cell. Excel stores what is typed
8
+ * as the error itself, so =ISNA(A1) over a cell holding #N/A is TRUE.
9
+ * #PARSE! is ours, not Excel's, and no one types it. */
10
+ const TYPED_ERRORS = [
11
+ '#REF!', '#DIV/0!', '#VALUE!', '#NAME?', '#NUM!', '#N/A', '#SPILL!', '#CALC!', '#CYCLE!', '#NULL!',
12
+ ];
13
+ /** The error a typed text stands for, or null when it is ordinary text. */
14
+ export function typedError(text) {
15
+ if (!text.startsWith('#'))
16
+ return null;
17
+ const upper = text.toUpperCase();
18
+ const found = TYPED_ERRORS.find((code) => code === upper);
19
+ return found ? { error: found } : null;
20
+ }
7
21
  /** Thrown during evaluation and caught at the boundary, where it becomes a
8
22
  * value. Carrying the code on a real Error keeps stack traces useful in dev
9
23
  * without the evaluator having to thread a result type through every branch. */
@@ -20,14 +20,47 @@ export type FilterCondition = {
20
20
  value?: string;
21
21
  valueTo?: string;
22
22
  };
23
+ /** Excel's Date Filters: a period around today, or a bound typed as a date. */
24
+ export type DatePeriod = 'equals' | 'before' | 'after' | 'between' | 'tomorrow' | 'today' | 'yesterday' | 'nextWeek' | 'thisWeek' | 'lastWeek' | 'nextMonth' | 'thisMonth' | 'lastMonth' | 'nextQuarter' | 'thisQuarter' | 'lastQuarter' | 'nextYear' | 'thisYear' | 'lastYear' | 'yearToDate';
23
25
  export type ColumnFilter = {
24
- kind: 'values'; /** Display texts left unticked; '' stands for the blanks. */
26
+ kind: 'values';
27
+ /** Display texts left unticked; '' stands for the blanks. */
25
28
  excluded: string[];
29
+ /** The texts ticked, from a file that lists what is IN (Excel and ODF
30
+ * both do): wins over `excluded` while set. The menu writes the
31
+ * exclusion form back the next time the filter is applied. */
32
+ included?: string[];
26
33
  } | {
27
34
  kind: 'condition';
28
35
  first: FilterCondition;
29
36
  join?: 'and' | 'or';
30
37
  second?: FilterCondition;
38
+ }
39
+ /** A date period; `value` and `valueTo` are `yyyy-mm-dd` for the typed bounds. */
40
+ | {
41
+ kind: 'date';
42
+ period: DatePeriod;
43
+ value?: string;
44
+ valueTo?: string;
45
+ }
46
+ /** Excel's Filter by Color: the cell's fill, or null for the cells with none. */
47
+ | {
48
+ kind: 'color';
49
+ fill: string | null;
50
+ }
51
+ /** Excel's Top 10: the `count` largest (or smallest) values, or that percent of the rows. */
52
+ | {
53
+ kind: 'top';
54
+ top: boolean;
55
+ count: number;
56
+ percent?: boolean;
57
+ };
58
+ /** What a filter reads beside the cell's value and text. */
59
+ export type FilterContext = {
60
+ /** The cell's fill, its own or a conditional format's; null when none. */
61
+ fillAt?: (r: number, c: number) => string | null;
62
+ /** The day the date periods count from. */
63
+ today?: Date;
31
64
  };
32
65
  export type AutoFilterState = {
33
66
  /** The region, header row first. */
@@ -46,14 +79,35 @@ export type FilterValue = {
46
79
  * rows other columns' filters hide, as Excel's list does.
47
80
  */
48
81
  export declare function distinctValues(state: AutoFilterState, col: number, valueAt: (r: number, c: number) => CellValue, displayAt: (r: number, c: number) => string, rowVisible?: (r: number) => boolean): FilterValue[];
49
- /** Whether a row passes one column's filter. */
50
- export declare function passesFilter(filter: ColumnFilter, value: CellValue, display: string): boolean;
82
+ /**
83
+ * The first and last day of a period, as UTC day-start milliseconds,
84
+ * counted from `today`. Weeks run Sunday to Saturday; quarters are the
85
+ * calendar's. The typed periods read `value` and `valueTo`.
86
+ */
87
+ export declare function datePeriodBounds(filter: Extract<ColumnFilter, {
88
+ kind: 'date';
89
+ }>, today?: Date): [from: number, to: number] | null;
90
+ /**
91
+ * Whether a row passes one column's filter. A Top 10 filter needs the
92
+ * whole column to know its threshold, which `hiddenRowsFor` works out and
93
+ * passes as `topPasses`; on its own the filter passes everything.
94
+ */
95
+ export declare function passesFilter(filter: ColumnFilter, value: CellValue, display: string, extra?: {
96
+ fill?: string | null;
97
+ today?: Date;
98
+ topPasses?: (value: CellValue) => boolean;
99
+ }): boolean;
51
100
  /**
52
101
  * The rows the state hides: every row of the region under the header
53
102
  * that fails a column's filter. Blanks past the region's edge are not in
54
103
  * it, as Excel's region is what was filtered.
55
104
  */
56
- export declare function hiddenRowsFor(state: AutoFilterState | null, valueAt: (r: number, c: number) => CellValue, displayAt: (r: number, c: number) => string): Set<number>;
105
+ export declare function hiddenRowsFor(state: AutoFilterState | null, valueAt: (r: number, c: number) => CellValue, displayAt: (r: number, c: number) => string, ctx?: FilterContext): Set<number>;
106
+ /** The fills a column's cells carry, each once, first seen first; null
107
+ * stands for the cells with none. Excel's Filter by Color list. */
108
+ export declare function distinctFills(state: AutoFilterState, col: number, fillAt: (r: number, c: number) => string | null): Array<string | null>;
109
+ /** Whether a column reads as dates: every cell with something in it holds one. */
110
+ export declare function isDateColumn(values: ReadonlyArray<FilterValue>): boolean;
57
111
  /** Whether any column is filtered. */
58
112
  export declare function isFiltering(state: AutoFilterState | null): boolean;
59
113
  /** The state with one column's filter set, or cleared with null. */
@@ -14,6 +14,7 @@
14
14
  import { compileExcelFilter } from '@svgrid/grid/filtering';
15
15
  import { isError } from './ast.js';
16
16
  import { shiftRect, lineShift } from './rects.js';
17
+ import { dateValue } from './validation.js';
17
18
  /** The operators that compare as numbers; the rest compare the display text. */
18
19
  const NUMERIC_OPS = new Set(['greaterThan', 'lessThan', 'between']);
19
20
  /**
@@ -60,31 +61,139 @@ function passesCondition(cond, value, display) {
60
61
  return test(display === '' ? null : display);
61
62
  return test(isError(value) ? value.error : display);
62
63
  }
63
- /** Whether a row passes one column's filter. */
64
- export function passesFilter(filter, value, display) {
65
- if (filter.kind === 'values')
66
- return !filter.excluded.includes(display);
67
- const first = passesCondition(filter.first, value, display);
68
- if (!filter.second)
69
- return first;
70
- const second = passesCondition(filter.second, value, display);
71
- return filter.join === 'or' ? first || second : first && second;
64
+ const DAY_MS = 86400000;
65
+ const dayStart = (d) => Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
66
+ /**
67
+ * The first and last day of a period, as UTC day-start milliseconds,
68
+ * counted from `today`. Weeks run Sunday to Saturday; quarters are the
69
+ * calendar's. The typed periods read `value` and `valueTo`.
70
+ */
71
+ export function datePeriodBounds(filter, today = new Date()) {
72
+ const t = dayStart(today);
73
+ const y = today.getUTCFullYear();
74
+ const m = today.getUTCMonth();
75
+ const q = Math.floor(m / 3);
76
+ const sunday = t - today.getUTCDay() * DAY_MS;
77
+ const month = (yy, mm) => [Date.UTC(yy, mm, 1), Date.UTC(yy, mm + 1, 0)];
78
+ const quarter = (yy, qq) => [Date.UTC(yy, qq * 3, 1), Date.UTC(yy, qq * 3 + 3, 0)];
79
+ const typed = (text) => {
80
+ if (!text)
81
+ return null;
82
+ const ms = dateValue(text.trim());
83
+ return ms === null ? null : dayStart(new Date(ms));
84
+ };
85
+ switch (filter.period) {
86
+ case 'today': return [t, t];
87
+ case 'yesterday': return [t - DAY_MS, t - DAY_MS];
88
+ case 'tomorrow': return [t + DAY_MS, t + DAY_MS];
89
+ case 'thisWeek': return [sunday, sunday + 6 * DAY_MS];
90
+ case 'lastWeek': return [sunday - 7 * DAY_MS, sunday - DAY_MS];
91
+ case 'nextWeek': return [sunday + 7 * DAY_MS, sunday + 13 * DAY_MS];
92
+ case 'thisMonth': return month(y, m);
93
+ case 'lastMonth': return month(y, m - 1);
94
+ case 'nextMonth': return month(y, m + 1);
95
+ case 'thisQuarter': return quarter(y, q);
96
+ case 'lastQuarter': return q === 0 ? quarter(y - 1, 3) : quarter(y, q - 1);
97
+ case 'nextQuarter': return q === 3 ? quarter(y + 1, 0) : quarter(y, q + 1);
98
+ case 'thisYear': return [Date.UTC(y, 0, 1), Date.UTC(y, 11, 31)];
99
+ case 'lastYear': return [Date.UTC(y - 1, 0, 1), Date.UTC(y - 1, 11, 31)];
100
+ case 'nextYear': return [Date.UTC(y + 1, 0, 1), Date.UTC(y + 1, 11, 31)];
101
+ case 'yearToDate': return [Date.UTC(y, 0, 1), t];
102
+ case 'equals': {
103
+ const d = typed(filter.value);
104
+ return d === null ? null : [d, d];
105
+ }
106
+ case 'before': {
107
+ const d = typed(filter.value);
108
+ return d === null ? null : [-Infinity, d - DAY_MS];
109
+ }
110
+ case 'after': {
111
+ const d = typed(filter.value);
112
+ return d === null ? null : [d + DAY_MS, Infinity];
113
+ }
114
+ case 'between': {
115
+ const a = typed(filter.value);
116
+ const b = typed(filter.valueTo);
117
+ return a === null || b === null ? null : [Math.min(a, b), Math.max(a, b)];
118
+ }
119
+ }
120
+ }
121
+ const sameFill = (a, b) => (a ?? '').trim().toLowerCase() === (b ?? '').trim().toLowerCase();
122
+ /**
123
+ * Whether a row passes one column's filter. A Top 10 filter needs the
124
+ * whole column to know its threshold, which `hiddenRowsFor` works out and
125
+ * passes as `topPasses`; on its own the filter passes everything.
126
+ */
127
+ export function passesFilter(filter, value, display, extra = {}) {
128
+ switch (filter.kind) {
129
+ case 'values': return filter.included ? filter.included.includes(display) : !filter.excluded.includes(display);
130
+ case 'date': {
131
+ const bounds = datePeriodBounds(filter, extra.today);
132
+ if (!bounds)
133
+ return true;
134
+ const ms = dateValue(value);
135
+ if (ms === null)
136
+ return false;
137
+ const day = dayStart(new Date(ms));
138
+ return day >= bounds[0] && day <= bounds[1];
139
+ }
140
+ case 'color': return sameFill(extra.fill ?? null, filter.fill);
141
+ case 'top': return extra.topPasses ? extra.topPasses(value) : true;
142
+ default: {
143
+ const first = passesCondition(filter.first, value, display);
144
+ if (!filter.second)
145
+ return first;
146
+ const second = passesCondition(filter.second, value, display);
147
+ return filter.join === 'or' ? first || second : first && second;
148
+ }
149
+ }
150
+ }
151
+ /** The test a Top 10 filter applies once the column's numbers are known:
152
+ * the values at or past the threshold, counted over the whole region as
153
+ * Excel counts them, whatever the other columns hide. */
154
+ function topPassesFor(filter, numbers) {
155
+ if (!numbers.length)
156
+ return () => false;
157
+ const sorted = numbers.slice().sort((a, b) => (filter.top ? b - a : a - b));
158
+ const count = filter.percent ? Math.round((filter.count / 100) * sorted.length) : filter.count;
159
+ const keep = Math.max(0, Math.min(sorted.length, Math.trunc(count)));
160
+ if (keep === 0)
161
+ return () => false;
162
+ const threshold = sorted[keep - 1];
163
+ return (value) => typeof value === 'number' && Number.isFinite(value) && (filter.top ? value >= threshold : value <= threshold);
72
164
  }
73
165
  /**
74
166
  * The rows the state hides: every row of the region under the header
75
167
  * that fails a column's filter. Blanks past the region's edge are not in
76
168
  * it, as Excel's region is what was filtered.
77
169
  */
78
- export function hiddenRowsFor(state, valueAt, displayAt) {
170
+ export function hiddenRowsFor(state, valueAt, displayAt, ctx = {}) {
79
171
  const out = new Set();
80
172
  if (!state)
81
173
  return out;
82
174
  const columns = Object.entries(state.filters).map(([c, f]) => [Number(c), f]);
83
175
  if (!columns.length)
84
176
  return out;
177
+ const tops = new Map();
178
+ for (const [c, filter] of columns) {
179
+ if (filter.kind !== 'top')
180
+ continue;
181
+ const numbers = [];
182
+ for (let r = state.range[0] + 1; r <= state.range[2]; r += 1) {
183
+ const v = valueAt(r, c);
184
+ if (typeof v === 'number' && Number.isFinite(v))
185
+ numbers.push(v);
186
+ }
187
+ tops.set(c, topPassesFor(filter, numbers));
188
+ }
85
189
  for (let r = state.range[0] + 1; r <= state.range[2]; r += 1) {
86
190
  for (const [c, filter] of columns) {
87
- if (!passesFilter(filter, valueAt(r, c), displayAt(r, c))) {
191
+ const extra = {
192
+ today: ctx.today,
193
+ fill: filter.kind === 'color' ? ctx.fillAt?.(r, c) ?? null : undefined,
194
+ topPasses: tops.get(c),
195
+ };
196
+ if (!passesFilter(filter, valueAt(r, c), displayAt(r, c), extra)) {
88
197
  out.add(r);
89
198
  break;
90
199
  }
@@ -92,6 +201,23 @@ export function hiddenRowsFor(state, valueAt, displayAt) {
92
201
  }
93
202
  return out;
94
203
  }
204
+ /** The fills a column's cells carry, each once, first seen first; null
205
+ * stands for the cells with none. Excel's Filter by Color list. */
206
+ export function distinctFills(state, col, fillAt) {
207
+ const seen = [];
208
+ for (let r = state.range[0] + 1; r <= state.range[2]; r += 1) {
209
+ const fill = fillAt(r, col);
210
+ const key = fill ? fill.trim().toLowerCase() : null;
211
+ if (!seen.some((f) => sameFill(f, key)))
212
+ seen.push(key);
213
+ }
214
+ return seen;
215
+ }
216
+ /** Whether a column reads as dates: every cell with something in it holds one. */
217
+ export function isDateColumn(values) {
218
+ const filled = values.filter((v) => v.text !== '');
219
+ return filled.length > 0 && filled.every((v) => v.numeric === null && dateValue(v.text) !== null);
220
+ }
95
221
  /** Whether any column is filtered. */
96
222
  export function isFiltering(state) {
97
223
  return !!state && Object.keys(state.filters).length > 0;
@@ -133,10 +259,32 @@ const OP_WORDS = {
133
259
  between: 'is between', contains: 'contains', notContains: 'does not contain', startsWith: 'begins with',
134
260
  endsWith: 'ends with', isBlank: 'is blank', isNotBlank: 'is not blank',
135
261
  };
262
+ const PERIOD_WORDS = {
263
+ equals: 'equals', before: 'is before', after: 'is after', between: 'is between',
264
+ tomorrow: 'tomorrow', today: 'today', yesterday: 'yesterday',
265
+ nextWeek: 'next week', thisWeek: 'this week', lastWeek: 'last week',
266
+ nextMonth: 'next month', thisMonth: 'this month', lastMonth: 'last month',
267
+ nextQuarter: 'next quarter', thisQuarter: 'this quarter', lastQuarter: 'last quarter',
268
+ nextYear: 'next year', thisYear: 'this year', lastYear: 'last year', yearToDate: 'year to date',
269
+ };
136
270
  /** A filter in words, for the menu's heading. */
137
271
  export function describeFilter(filter) {
272
+ if (filter.kind === 'values' && filter.included)
273
+ return filter.included.length === 1 ? '1 value shown' : `${filter.included.length} values shown`;
138
274
  if (filter.kind === 'values')
139
275
  return filter.excluded.length === 1 ? '1 value hidden' : `${filter.excluded.length} values hidden`;
276
+ if (filter.kind === 'date') {
277
+ const word = PERIOD_WORDS[filter.period];
278
+ if (filter.period === 'between')
279
+ return `${word} ${filter.value ?? ''} and ${filter.valueTo ?? ''}`;
280
+ if (filter.period === 'equals' || filter.period === 'before' || filter.period === 'after')
281
+ return `${word} ${filter.value ?? ''}`;
282
+ return word;
283
+ }
284
+ if (filter.kind === 'color')
285
+ return filter.fill ? `filled ${filter.fill}` : 'no fill';
286
+ if (filter.kind === 'top')
287
+ return `${filter.top ? 'top' : 'bottom'} ${filter.count}${filter.percent ? ' percent' : ''}`;
140
288
  const one = (c) => {
141
289
  const word = OP_WORDS[c.op] ?? c.op;
142
290
  if (c.op === 'isBlank' || c.op === 'isNotBlank')
@@ -5,6 +5,15 @@ export type FunctionSuggestion = {
5
5
  /** Where the caret is, i.e. where the partial name ends. */
6
6
  end: number;
7
7
  };
8
+ /**
9
+ * The evaluator dispatches these itself, so they are not in the table.
10
+ *
11
+ * Exported because `function-catalog.ts` needs the same list: it kept a
12
+ * copy of its own, the copy fell behind this one, and Insert Function
13
+ * quietly stopped listing LET, LAMBDA, the lambda helpers and SUBTOTAL
14
+ * even though it carried written descriptions for them. One list now.
15
+ */
16
+ export declare const EVALUATOR_NAMES: string[];
8
17
  /** Signature hints, for the ones whose argument order is not obvious. */
9
18
  export declare const SIGNATURES: Record<string, string>;
10
19
  /**
@@ -8,16 +8,40 @@
8
8
  * with an index, which the component owns.
9
9
  */
10
10
  import { FUNCTIONS } from './functions.js';
11
- const NAMES = Object.keys(FUNCTIONS).sort();
11
+ import { ARRAY_FUNCTIONS } from './packs/array.js';
12
+ /**
13
+ * The evaluator dispatches these itself, so they are not in the table.
14
+ *
15
+ * Exported because `function-catalog.ts` needs the same list: it kept a
16
+ * copy of its own, the copy fell behind this one, and Insert Function
17
+ * quietly stopped listing LET, LAMBDA, the lambda helpers and SUBTOTAL
18
+ * even though it carried written descriptions for them. One list now.
19
+ */
20
+ export const EVALUATOR_NAMES = ['IF', 'IFS', 'IFERROR', 'IFNA', 'SWITCH', 'ISERROR', 'ISERR', 'ISNA', 'ROW', 'COLUMN', 'ADDRESS', 'OFFSET', 'INDIRECT', 'SUBTOTAL',
21
+ // LET, LAMBDA and the helpers that take one: the evaluator answers these
22
+ // itself, since a lambda is an AST rather than a value.
23
+ 'LET', 'LAMBDA', 'MAP', 'BYROW', 'BYCOL', 'REDUCE', 'SCAN', 'MAKEARRAY'];
24
+ const NAMES = [...new Set([...Object.keys(FUNCTIONS), ...Object.keys(ARRAY_FUNCTIONS), ...EVALUATOR_NAMES])].sort();
12
25
  /** Signature hints, for the ones whose argument order is not obvious. */
13
26
  export const SIGNATURES = {
14
- VLOOKUP: 'VLOOKUP(lookup, table, colIndex)',
15
- HLOOKUP: 'HLOOKUP(lookup, table, rowIndex)',
16
- XLOOKUP: 'XLOOKUP(lookup, haystack, results, [ifMissing])',
27
+ LET: 'LET(name, value, ..., calculation)',
28
+ LAMBDA: 'LAMBDA(parameter, ..., calculation)',
29
+ MAP: 'MAP(array, ..., lambda)',
30
+ BYROW: 'BYROW(array, lambda)',
31
+ BYCOL: 'BYCOL(array, lambda)',
32
+ REDUCE: 'REDUCE(initial, array, lambda)',
33
+ SCAN: 'SCAN(initial, array, lambda)',
34
+ MAKEARRAY: 'MAKEARRAY(rows, columns, lambda)',
35
+ VLOOKUP: 'VLOOKUP(lookup, table, colIndex, [rangeLookup])',
36
+ HLOOKUP: 'HLOOKUP(lookup, table, rowIndex, [rangeLookup])',
37
+ XLOOKUP: 'XLOOKUP(lookup, haystack, results, [ifMissing], [matchMode], [searchMode])',
17
38
  INDEX: 'INDEX(range, row, [col])',
18
39
  MATCH: 'MATCH(lookup, range, [mode])',
19
40
  SUMIF: 'SUMIF(range, criterion, [sumRange])',
20
41
  SUMIFS: 'SUMIFS(sumRange, range, criterion, ...)',
42
+ SUBTOTAL: 'SUBTOTAL(code, range, ...)',
43
+ TRUE: 'TRUE()',
44
+ FALSE: 'FALSE()',
21
45
  COUNTIF: 'COUNTIF(range, criterion)',
22
46
  COUNTIFS: 'COUNTIFS(range, criterion, ...)',
23
47
  AVERAGEIF: 'AVERAGEIF(range, criterion, [avgRange])',
@@ -32,6 +56,68 @@ export const SIGNATURES = {
32
56
  MID: 'MID(text, start, length)',
33
57
  DATE: 'DATE(year, month, day)',
34
58
  EOMONTH: 'EOMONTH(date, months)',
59
+ PMT: 'PMT(rate, nper, pv, [fv], [type])',
60
+ IPMT: 'IPMT(rate, per, nper, pv, [fv], [type])',
61
+ PPMT: 'PPMT(rate, per, nper, pv, [fv], [type])',
62
+ PV: 'PV(rate, nper, pmt, [fv], [type])',
63
+ FV: 'FV(rate, nper, pmt, [pv], [type])',
64
+ NPER: 'NPER(rate, pmt, pv, [fv], [type])',
65
+ RATE: 'RATE(nper, pmt, pv, [fv], [type], [guess])',
66
+ NPV: 'NPV(rate, value1, ...)',
67
+ IRR: 'IRR(values, [guess])',
68
+ SLN: 'SLN(cost, salvage, life)',
69
+ SUMPRODUCT: 'SUMPRODUCT(array1, [array2], ...)',
70
+ CEILING: 'CEILING(number, significance)',
71
+ 'CEILING.MATH': 'CEILING.MATH(number, [significance], [mode])',
72
+ FLOOR: 'FLOOR(number, significance)',
73
+ 'FLOOR.MATH': 'FLOOR.MATH(number, [significance], [mode])',
74
+ MROUND: 'MROUND(number, multiple)',
75
+ TRUNC: 'TRUNC(number, [digits])',
76
+ LOG: 'LOG(number, [base])',
77
+ RANDBETWEEN: 'RANDBETWEEN(bottom, top)',
78
+ QUOTIENT: 'QUOTIENT(numerator, denominator)',
79
+ LARGE: 'LARGE(range, k)',
80
+ SMALL: 'SMALL(range, k)',
81
+ PERCENTILE: 'PERCENTILE(range, k)',
82
+ 'PERCENTILE.INC': 'PERCENTILE.INC(range, k)',
83
+ 'PERCENTILE.EXC': 'PERCENTILE.EXC(range, k)',
84
+ QUARTILE: 'QUARTILE(range, quart)',
85
+ 'QUARTILE.INC': 'QUARTILE.INC(range, quart)',
86
+ 'QUARTILE.EXC': 'QUARTILE.EXC(range, quart)',
87
+ AVERAGEIFS: 'AVERAGEIFS(avgRange, range, criterion, ...)',
88
+ MAXIFS: 'MAXIFS(maxRange, range, criterion, ...)',
89
+ MINIFS: 'MINIFS(minRange, range, criterion, ...)',
90
+ CORREL: 'CORREL(range1, range2)',
91
+ SLOPE: 'SLOPE(known_ys, known_xs)',
92
+ INTERCEPT: 'INTERCEPT(known_ys, known_xs)',
93
+ FORECAST: 'FORECAST(x, known_ys, known_xs)',
94
+ 'FORECAST.LINEAR': 'FORECAST.LINEAR(x, known_ys, known_xs)',
95
+ REPT: 'REPT(text, count)',
96
+ IMAGE: 'IMAGE(source, [alt_text])',
97
+ NUMBERVALUE: 'NUMBERVALUE(text, [decimal_separator], [group_separator])',
98
+ REPLACE: 'REPLACE(old_text, start, count, new_text)',
99
+ EXACT: 'EXACT(text1, text2)',
100
+ WEEKDAY: 'WEEKDAY(date, [type])',
101
+ EDATE: 'EDATE(date, months)',
102
+ NETWORKDAYS: 'NETWORKDAYS(start_date, end_date, [holidays])',
103
+ WORKDAY: 'WORKDAY(start_date, days, [holidays])',
104
+ WEEKNUM: 'WEEKNUM(date, [type])',
105
+ TIME: 'TIME(hour, minute, second)',
106
+ YEARFRAC: 'YEARFRAC(start_date, end_date, [basis])',
107
+ NA: 'NA()',
108
+ CHOOSE: 'CHOOSE(index, value1, ...)',
109
+ ROW: 'ROW([reference])',
110
+ COLUMN: 'COLUMN([reference])',
111
+ ADDRESS: 'ADDRESS(row, column, [abs], [a1], [sheet])',
112
+ OFFSET: 'OFFSET(reference, rows, cols, [height], [width])',
113
+ INDIRECT: 'INDIRECT(text, [a1])',
114
+ FILTER: 'FILTER(array, include, [if_empty])',
115
+ UNIQUE: 'UNIQUE(array, [by_col], [exactly_once])',
116
+ SORT: 'SORT(array, [sort_index], [sort_order], [by_col])',
117
+ SORTBY: 'SORTBY(array, by_array1, [sort_order1], ...)',
118
+ SEQUENCE: 'SEQUENCE(rows, [columns], [start], [step])',
119
+ TRANSPOSE: 'TRANSPOSE(array)',
120
+ TEXTSPLIT: 'TEXTSPLIT(text, col_delimiter, [row_delimiter], [ignore_empty])',
35
121
  };
36
122
  /**
37
123
  * The word being typed immediately before the caret, if it could be a function
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Excel's `IMAGE` function: a picture IN a cell rather than floating over
3
+ * it.
4
+ *
5
+ * The difference is the whole point. A picture object hangs from a cell and
6
+ * covers whatever is under it; an `IMAGE` cell IS the picture, so it sorts
7
+ * with its row, filters with it, copies as a formula and moves when the
8
+ * cells move, with nothing to keep in step. A catalogue with a thumbnail
9
+ * column wants this one.
10
+ *
11
+ * The function answers with the source, which is what makes `=IMAGE(A2)`
12
+ * read like any other formula: the value is text, `ISTEXT` says so, and a
13
+ * cell that reads it gets the address rather than a picture it cannot use.
14
+ * Drawing it is the shell's part, and this is what the shell reads to know
15
+ * a cell is one.
16
+ */
17
+ /** The arguments of a top-level `=IMAGE(...)`, as written. */
18
+ export type ImageCall = {
19
+ /** The source expression: a quoted URL, a reference, a formula. */
20
+ source: string;
21
+ /** The alt text expression, when the call gives one. */
22
+ alt?: string;
23
+ };
24
+ /**
25
+ * The call's arguments when a formula IS one `IMAGE(...)` call, or null.
26
+ *
27
+ * Read off the text rather than the parsed tree on purpose: this runs for
28
+ * every cell that paints, and a scan is cheaper than a parse. A formula
29
+ * that merely CONTAINS an IMAGE call (`=IF(A1, IMAGE(B1), "")`) is not one,
30
+ * because its value is not a picture in every case.
31
+ */
32
+ export declare function imageCall(text: string): ImageCall | null;
33
+ /**
34
+ * Whether a source is one a browser will load. A `data:` URL and an
35
+ * ordinary web address are; anything else (a file path, a `javascript:`
36
+ * scheme) is not, and a cell showing it as text says more than a broken
37
+ * image would.
38
+ */
39
+ export declare function isDrawableImageSource(source: string): boolean;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Excel's `IMAGE` function: a picture IN a cell rather than floating over
3
+ * it.
4
+ *
5
+ * The difference is the whole point. A picture object hangs from a cell and
6
+ * covers whatever is under it; an `IMAGE` cell IS the picture, so it sorts
7
+ * with its row, filters with it, copies as a formula and moves when the
8
+ * cells move, with nothing to keep in step. A catalogue with a thumbnail
9
+ * column wants this one.
10
+ *
11
+ * The function answers with the source, which is what makes `=IMAGE(A2)`
12
+ * read like any other formula: the value is text, `ISTEXT` says so, and a
13
+ * cell that reads it gets the address rather than a picture it cannot use.
14
+ * Drawing it is the shell's part, and this is what the shell reads to know
15
+ * a cell is one.
16
+ */
17
+ /**
18
+ * The call's arguments when a formula IS one `IMAGE(...)` call, or null.
19
+ *
20
+ * Read off the text rather than the parsed tree on purpose: this runs for
21
+ * every cell that paints, and a scan is cheaper than a parse. A formula
22
+ * that merely CONTAINS an IMAGE call (`=IF(A1, IMAGE(B1), "")`) is not one,
23
+ * because its value is not a picture in every case.
24
+ */
25
+ export function imageCall(text) {
26
+ const trimmed = text.trim();
27
+ const head = /^=\s*IMAGE\s*\(/i.exec(trimmed);
28
+ if (!head)
29
+ return null;
30
+ const inside = trimmed.slice(head[0].length);
31
+ const args = [];
32
+ let depth = 0;
33
+ let quoted = false;
34
+ let start = 0;
35
+ let closed = -1;
36
+ for (let i = 0; i < inside.length; i += 1) {
37
+ const ch = inside[i];
38
+ if (quoted) {
39
+ if (ch === '"') {
40
+ if (inside[i + 1] === '"')
41
+ i += 1;
42
+ else
43
+ quoted = false;
44
+ }
45
+ continue;
46
+ }
47
+ if (ch === '"') {
48
+ quoted = true;
49
+ continue;
50
+ }
51
+ if (ch === '(') {
52
+ depth += 1;
53
+ continue;
54
+ }
55
+ if (ch === ')') {
56
+ if (depth === 0) {
57
+ args.push(inside.slice(start, i));
58
+ closed = i;
59
+ break;
60
+ }
61
+ depth -= 1;
62
+ continue;
63
+ }
64
+ if (ch === ',' && depth === 0) {
65
+ args.push(inside.slice(start, i));
66
+ start = i + 1;
67
+ }
68
+ }
69
+ // Anything after the closing bracket means the call is part of a larger
70
+ // formula, so the cell is not simply a picture.
71
+ if (closed < 0 || inside.slice(closed + 1).trim() !== '')
72
+ return null;
73
+ const source = (args[0] ?? '').trim();
74
+ if (!source)
75
+ return null;
76
+ const alt = (args[1] ?? '').trim();
77
+ return { source, ...(alt ? { alt } : {}) };
78
+ }
79
+ /**
80
+ * Whether a source is one a browser will load. A `data:` URL and an
81
+ * ordinary web address are; anything else (a file path, a `javascript:`
82
+ * scheme) is not, and a cell showing it as text says more than a broken
83
+ * image would.
84
+ */
85
+ export function isDrawableImageSource(source) {
86
+ const value = source.trim();
87
+ if (/^data:image\//i.test(value))
88
+ return true;
89
+ return /^https?:\/\/\S+$/i.test(value);
90
+ }