@svgrid/enterprise 3.0.0 → 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.
- package/README.md +95 -95
- package/dist/ExpressionEditorHarness.svelte.d.ts +2 -2
- package/dist/SvAdvancedFilter.svelte.d.ts +2 -2
- package/dist/SvAlertRuleEditor.svelte.d.ts +2 -2
- package/dist/SvAlertsManager.svelte.d.ts +3 -3
- package/dist/SvAlertsPanel.svelte.d.ts +1 -1
- package/dist/SvAuthGate.svelte +115 -115
- package/dist/SvAuthGate.svelte.d.ts +1 -1
- package/dist/SvBoard.svelte.d.ts +1 -1
- package/dist/SvExportMenu.svelte +553 -553
- package/dist/SvExportMenu.svelte.d.ts +2 -2
- package/dist/SvExpressionEditor.svelte.d.ts +2 -2
- package/dist/SvFileInput.svelte +113 -113
- package/dist/SvFormulaBar.svelte +606 -0
- package/dist/SvFormulaBar.svelte.d.ts +62 -0
- package/dist/SvGridAlerts.svelte.d.ts +2 -2
- package/dist/SvGridBoard.svelte +2358 -2358
- package/dist/SvGridBulkEditDrawer.svelte.d.ts +1 -1
- package/dist/SvGridEditPanel.svelte +1157 -1157
- package/dist/SvGridEditPanel.svelte.d.ts +3 -3
- package/dist/SvGridMasterDetail.svelte +116 -116
- package/dist/SvGridMasterDetail.svelte.d.ts +1 -1
- package/dist/SvGridScheduler.svelte +5358 -5358
- package/dist/SvImportDialog.svelte +1020 -1020
- package/dist/SvImportDialog.svelte.d.ts +2 -2
- package/dist/SvLookupInput.svelte +180 -180
- package/dist/SvLookupInput.svelte.d.ts +1 -1
- package/dist/SvPivotDesigner.svelte +2041 -1990
- package/dist/SvPivotDesigner.svelte.d.ts +2 -2
- package/dist/SvRecordDetail.svelte.d.ts +1 -1
- package/dist/SvRibbonIcon.svelte +46 -0
- package/dist/SvRibbonIcon.svelte.d.ts +17 -0
- package/dist/SvSchedule.svelte.d.ts +1 -1
- package/dist/SvSchemaChart.svelte +236 -234
- package/dist/SvSchemaChart.svelte.d.ts +2 -2
- package/dist/SvSchemaDashboard.svelte +130 -130
- package/dist/SvSchemaDashboard.svelte.d.ts +3 -3
- package/dist/SvSheet.svelte +4114 -0
- package/dist/SvSheet.svelte.d.ts +142 -0
- package/dist/SvSheetComment.svelte +98 -0
- package/dist/SvSheetComment.svelte.d.ts +22 -0
- package/dist/SvSheetConditionalFormat.svelte +162 -0
- package/dist/SvSheetConditionalFormat.svelte.d.ts +14 -0
- package/dist/SvSheetDataValidation.svelte +249 -0
- package/dist/SvSheetDataValidation.svelte.d.ts +14 -0
- package/dist/SvSheetFilterMenu.svelte +217 -0
- package/dist/SvSheetFilterMenu.svelte.d.ts +17 -0
- package/dist/SvSheetFindReplace.svelte +132 -0
- package/dist/SvSheetFindReplace.svelte.d.ts +10 -0
- package/dist/SvSheetFormatCells.svelte +421 -0
- package/dist/SvSheetFormatCells.svelte.d.ts +17 -0
- package/dist/SvSheetGoalSeek.svelte +144 -0
- package/dist/SvSheetGoalSeek.svelte.d.ts +12 -0
- package/dist/SvSheetInsertFunction.svelte +147 -0
- package/dist/SvSheetInsertFunction.svelte.d.ts +8 -0
- package/dist/SvSheetListPicker.svelte +89 -0
- package/dist/SvSheetListPicker.svelte.d.ts +16 -0
- package/dist/SvSheetManageRules.svelte +185 -0
- package/dist/SvSheetManageRules.svelte.d.ts +16 -0
- package/dist/SvSheetNameManager.svelte +225 -0
- package/dist/SvSheetNameManager.svelte.d.ts +11 -0
- package/dist/SvSheetPasteSpecial.svelte +105 -0
- package/dist/SvSheetPasteSpecial.svelte.d.ts +12 -0
- package/dist/SvSheetRemoveDuplicates.svelte +149 -0
- package/dist/SvSheetRemoveDuplicates.svelte.d.ts +12 -0
- package/dist/SvSheetRibbon.svelte +1201 -0
- package/dist/SvSheetRibbon.svelte.d.ts +34 -0
- package/dist/SvSheetSizeDialog.svelte +58 -0
- package/dist/SvSheetSizeDialog.svelte.d.ts +11 -0
- package/dist/SvSheetTabs.svelte +441 -0
- package/dist/SvSheetTabs.svelte.d.ts +36 -0
- package/dist/SvSheetTabs.test-harness.svelte.d.ts +17 -0
- package/dist/SvSheetTabs.test-harness.svelte.js +22 -0
- package/dist/SvSheetTextToColumns.svelte +172 -0
- package/dist/SvSheetTextToColumns.svelte.d.ts +13 -0
- package/dist/SvSheetValidationAlert.svelte +83 -0
- package/dist/SvSheetValidationAlert.svelte.d.ts +15 -0
- package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -1
- package/dist/advanced-filter-enable.js +3 -3
- package/dist/alerts/alert-engine-attach.d.ts +2 -2
- package/dist/alerts/alert-engine-attach.js +3 -3
- package/dist/alerts/alert-engine.d.ts +1 -1
- package/dist/alerts/alert-engine.js +2 -2
- package/dist/alerts/alert-formats.d.ts +1 -1
- package/dist/alerts/alert-formats.js +1 -1
- package/dist/alerts/alert-observer.d.ts +3 -3
- package/dist/alerts/alert-observer.js +1 -1
- package/dist/alerts/alert-storage.d.ts +1 -1
- package/dist/alerts/alert-store.svelte.d.ts +1 -1
- package/dist/alerts/alert-types.d.ts +2 -2
- package/dist/alerts.js +2 -2
- package/dist/board.js +2 -2
- package/dist/cdn/svgrid-enterprise.svelte-external.js +19046 -5428
- package/dist/designer/assets/GridMenus-BlsvL_aU.js +8 -0
- package/dist/designer/assets/SvChartMenu-BYO9cYdy.css +1 -0
- package/dist/designer/assets/SvChartMenu-D9hEeHar.js +1 -0
- package/dist/designer/assets/SvDateRangeInput-BBRzrQeg.js +1 -0
- package/dist/designer/assets/SvDateRangeInput-C0iCCZ8o.css +1 -0
- package/dist/designer/assets/SvDateTimePicker-DARvKUL2.js +1 -0
- package/dist/designer/assets/SvDateTimePicker-DPv09DIT.css +1 -0
- package/dist/designer/assets/{preload-helper-CG0n22O7.js → SvGrid.helpers-BgT-gnCo.js} +1 -1
- package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +4 -0
- package/dist/designer/assets/SvGridChart-B8j1SSy3.js +3 -0
- package/dist/designer/assets/SvGridChart-BgLuPO7I.css +1 -0
- package/dist/designer/assets/SvGridChartBuilder-08YWWeqY.css +1 -0
- package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +1 -0
- package/dist/designer/assets/SvGridChartPanel-4Pc8y5yO.css +1 -0
- package/dist/designer/assets/SvGridChartPanel-pT6ITc2P.js +4 -0
- package/dist/designer/assets/SvGridChartView-7msfnWZT.css +1 -0
- package/dist/designer/assets/SvGridChartView-bg281UA1.js +1 -0
- package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +1 -0
- package/dist/designer/assets/SvGridDropdown-CcidB3rm.css +1 -0
- package/dist/designer/assets/SvListBox-BDS66lmZ.js +110 -0
- package/dist/designer/assets/SvListBox-BXfyqy4a.css +1 -0
- package/dist/designer/assets/SvMenuList-DJ47ba1h.css +1 -0
- package/dist/designer/assets/SvMenuList-Dgq2D5VN.js +1 -0
- package/dist/designer/assets/SvTabs-DKmwb5p1.css +1 -0
- package/dist/designer/assets/SvTabs-UFCMTHXS.js +1 -0
- package/dist/designer/assets/cell-formatting-wr5wm7US.js +1 -0
- package/dist/designer/assets/chart-cIPUsbM5.js +1 -0
- package/dist/designer/assets/chart-export-B6bkQ3X8.js +11 -0
- package/dist/designer/assets/chart-export-pdf-BbA28-gt.js +11 -0
- package/dist/designer/assets/chart-panel-messages-DtTxpBUU.js +1 -0
- package/dist/designer/assets/chart-summary-Czu_5epb.js +1 -0
- package/dist/designer/assets/chart-trend-D5I5VEe8.js +1 -0
- package/dist/designer/assets/chart-validate-BMqM-qkF.js +1 -0
- package/dist/designer/assets/column-resize-BYDzR1Ve.js +1 -0
- package/dist/designer/assets/date-format-B8JbEtIG.js +1 -0
- package/dist/designer/assets/date-format-DKS-z0xS.css +1 -0
- package/dist/designer/assets/editor-contract-Bpoa7A5g.js +1 -0
- package/dist/designer/assets/export-format-D-eP4b2l.js +6 -0
- package/dist/designer/assets/focus-trap-CAreAhlU.js +1 -0
- package/dist/designer/assets/index-CMFgAoVV.css +1 -0
- package/dist/designer/assets/{index-zUBix-JQ.js → index-DwU7CAMm.js} +2985 -141
- package/dist/designer/assets/list-option-BP_dWS66.js +1 -0
- package/dist/designer/assets/preload-helper-HclGiUj8.js +1 -0
- package/dist/designer/assets/row-resize-DLktcqUK.js +1 -0
- package/dist/designer/assets/src-CITpcm6b.js +1 -0
- package/dist/designer/assets/src-EdI3Xqds.js +58 -0
- package/dist/designer/index.html +32 -23
- package/dist/export-conditional.d.ts +1 -1
- package/dist/export-pdf.d.ts +89 -0
- package/dist/export-pdf.js +130 -0
- package/dist/export-print.js +19 -19
- package/dist/export-xls.d.ts +2 -2
- package/dist/export.d.ts +2 -2
- package/dist/export.js +23 -16
- package/dist/expressions/builder-tree.d.ts +2 -2
- package/dist/expressions/builder-tree.js +1 -1
- package/dist/expressions/compile.d.ts +1 -1
- package/dist/import.js +1 -1
- package/dist/index.d.ts +116 -53
- package/dist/index.js +117 -50
- package/dist/install.d.ts +4 -4
- package/dist/install.js +16 -11
- package/dist/license.d.ts +3 -2
- package/dist/license.js +9 -4
- package/dist/node/studio.js +187 -116
- package/dist/pivot-chart.d.ts +26 -2
- package/dist/pivot-chart.js +25 -69
- package/dist/pivot-designer.d.ts +1 -1
- package/dist/pivot-enable.js +3 -3
- package/dist/print.d.ts +1 -1
- package/dist/print.js +4 -4
- package/dist/scheduler-config.d.ts +5 -5
- package/dist/scheduler-freebusy.d.ts +1 -1
- package/dist/scheduler-freebusy.js +1 -1
- package/dist/scheduler.js +2 -2
- package/dist/schema-designer.d.ts +1 -1
- package/dist/schema-designer.js +2 -2
- package/dist/selection-bar.js +2 -2
- package/dist/sheet/address.d.ts +43 -0
- package/dist/sheet/address.js +81 -0
- package/dist/sheet/ast.d.ts +94 -0
- package/dist/sheet/ast.js +56 -0
- package/dist/sheet/auto-filter.d.ts +66 -0
- package/dist/sheet/auto-filter.js +147 -0
- package/dist/sheet/autocomplete.d.ts +42 -0
- package/dist/sheet/autocomplete.js +162 -0
- package/dist/sheet/coerce.d.ts +31 -0
- package/dist/sheet/coerce.js +122 -0
- package/dist/sheet/commands.d.ts +89 -0
- package/dist/sheet/commands.js +230 -0
- package/dist/sheet/comments.d.ts +29 -0
- package/dist/sheet/comments.js +73 -0
- package/dist/sheet/conditional-formats.d.ts +144 -0
- package/dist/sheet/conditional-formats.js +316 -0
- package/dist/sheet/deps.d.ts +60 -0
- package/dist/sheet/deps.js +199 -0
- package/dist/sheet/document.d.ts +150 -0
- package/dist/sheet/document.js +264 -0
- package/dist/sheet/edit-keys.d.ts +14 -0
- package/dist/sheet/edit-keys.js +40 -0
- package/dist/sheet/entry.d.ts +31 -0
- package/dist/sheet/entry.js +76 -0
- package/dist/sheet/evaluate.d.ts +61 -0
- package/dist/sheet/evaluate.js +337 -0
- package/dist/sheet/find-replace.d.ts +62 -0
- package/dist/sheet/find-replace.js +152 -0
- package/dist/sheet/format-store.d.ts +99 -0
- package/dist/sheet/format-store.js +233 -0
- package/dist/sheet/freeze.d.ts +54 -0
- package/dist/sheet/freeze.js +58 -0
- package/dist/sheet/function-catalog.d.ts +10 -0
- package/dist/sheet/function-catalog.js +94 -0
- package/dist/sheet/functions.d.ts +28 -0
- package/dist/sheet/functions.js +362 -0
- package/dist/sheet/goal-seek.d.ts +73 -0
- package/dist/sheet/goal-seek.js +153 -0
- package/dist/sheet/index.d.ts +53 -0
- package/dist/sheet/index.js +53 -0
- package/dist/sheet/merges.d.ts +71 -0
- package/dist/sheet/merges.js +137 -0
- package/dist/sheet/names.d.ts +31 -0
- package/dist/sheet/names.js +87 -0
- package/dist/sheet/navigate.d.ts +52 -0
- package/dist/sheet/navigate.js +135 -0
- package/dist/sheet/number-format.d.ts +63 -0
- package/dist/sheet/number-format.js +508 -0
- package/dist/sheet/palette.d.ts +19 -0
- package/dist/sheet/palette.js +84 -0
- package/dist/sheet/parse.d.ts +13 -0
- package/dist/sheet/parse.js +108 -0
- package/dist/sheet/paste-special.d.ts +164 -0
- package/dist/sheet/paste-special.js +592 -0
- package/dist/sheet/protection.d.ts +21 -0
- package/dist/sheet/protection.js +48 -0
- package/dist/sheet/rects.d.ts +45 -0
- package/dist/sheet/rects.js +112 -0
- package/dist/sheet/refs.d.ts +82 -0
- package/dist/sheet/refs.js +266 -0
- package/dist/sheet/ribbon-icons.d.ts +31 -0
- package/dist/sheet/ribbon-icons.js +350 -0
- package/dist/sheet/ribbon.d.ts +173 -0
- package/dist/sheet/ribbon.js +753 -0
- package/dist/sheet/shortcuts.d.ts +164 -0
- package/dist/sheet/shortcuts.js +623 -0
- package/dist/sheet/structure.d.ts +87 -0
- package/dist/sheet/structure.js +166 -0
- package/dist/sheet/tables.d.ts +70 -0
- package/dist/sheet/tables.js +147 -0
- package/dist/sheet/tokenize.d.ts +54 -0
- package/dist/sheet/tokenize.js +304 -0
- package/dist/sheet/transforms.d.ts +76 -0
- package/dist/sheet/transforms.js +154 -0
- package/dist/sheet/validation.d.ts +92 -0
- package/dist/sheet/validation.js +241 -0
- package/dist/sheet/workbook.d.ts +72 -0
- package/dist/sheet/workbook.js +409 -0
- package/dist/sheet-enable.d.ts +6 -0
- package/dist/sheet-enable.js +46 -0
- package/dist/sources/aggregate.d.ts +1 -1
- package/dist/sources/auth-supabase.js +1 -1
- package/dist/sources/dashboard.d.ts +2 -2
- package/dist/sources/dashboard.js +1 -1
- package/dist/sources/index.d.ts +13 -13
- package/dist/sources/index.js +13 -13
- package/dist/sources/realtime-supabase.js +1 -1
- package/dist/sources/relation-lookup.d.ts +1 -1
- package/dist/sources/relation-lookup.js +1 -1
- package/dist/sources/rest-adapters.d.ts +1 -1
- package/dist/sources/rest-adapters.js +1 -1
- package/dist/sources/rest.d.ts +2 -2
- package/dist/sources/rest.js +3 -3
- package/dist/sources/supabase.d.ts +2 -2
- package/dist/sources/supabase.js +3 -3
- package/dist/sources/with-entity-rules.d.ts +1 -1
- package/dist/sources/with-entity-rules.js +1 -1
- package/dist/sources/with-relation-labels.d.ts +1 -1
- package/dist/studio/emit-project.js +2161 -2127
- package/dist/studio/emit-schema.js +369 -369
- package/dist/studio/index.d.ts +1 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio/introspect-db.js +45 -45
- package/dist/studio/project.d.ts +10 -0
- package/dist/studio/samples/crm.js +6 -6
- package/dist/studio/samples/fleet.js +7 -7
- package/dist/studio/samples/insurance.js +9 -9
- package/dist/studio/samples/inventory.js +12 -12
- package/dist/studio/samples/projects.js +5 -5
- package/dist/studio/samples/support.js +8 -8
- package/dist/studio/scaffold-app.js +104 -104
- package/dist/studio/scaffold.js +151 -151
- package/dist/studio/ui-components.d.ts +7 -0
- package/dist/studio/ui-components.generated.js +63 -1
- package/dist/studio/ui-components.js +35 -0
- package/dist/sveltekit/in-memory.d.ts +3 -3
- package/dist/sveltekit/in-memory.js +4 -4
- package/dist/sveltekit/index.d.ts +6 -6
- package/dist/sveltekit/index.js +5 -5
- package/dist/sveltekit/query-plan.d.ts +1 -1
- package/dist/sveltekit/sql-source.d.ts +4 -4
- package/dist/sveltekit/sql-source.js +4 -4
- package/dist/sveltekit/sql.d.ts +1 -1
- package/dist/sveltekit/transport.d.ts +2 -2
- package/dist/sveltekit/transport.js +1 -1
- package/dist/upgrade-prompt.js +25 -25
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +12 -4
- package/dist/designer/assets/GridMenus-Cgilexpk.js +0 -8
- package/dist/designer/assets/SvDateRangeInput-BV5OXYQ2.css +0 -1
- package/dist/designer/assets/SvDateRangeInput-CVn-yqrQ.js +0 -1
- package/dist/designer/assets/SvDateTimePicker-BdioTrJQ.js +0 -1
- package/dist/designer/assets/SvDateTimePicker-CY8TK4BT.css +0 -1
- package/dist/designer/assets/SvField-BF-9TJSd.css +0 -1
- package/dist/designer/assets/SvField-BsqiA5me.js +0 -1
- package/dist/designer/assets/SvGridCellEditor-dLY7_kk9.js +0 -2
- package/dist/designer/assets/SvGridChart-BEDNTdc5.js +0 -2
- package/dist/designer/assets/SvGridChart-Vu4Nvjiv.css +0 -1
- package/dist/designer/assets/SvGridChartPanel-x3lzSxuf.js +0 -10
- package/dist/designer/assets/SvGridChartView-CAKhPELi.js +0 -1
- package/dist/designer/assets/SvGridChartView-DX9HfkBR.css +0 -1
- package/dist/designer/assets/SvGridDropdown-CAYG7Y-O.js +0 -1
- package/dist/designer/assets/SvGridDropdown-Crwb2P3Q.css +0 -1
- package/dist/designer/assets/SvListBox-CVYQcLX9.js +0 -1
- package/dist/designer/assets/SvListBox-DgN8kvjt.css +0 -1
- package/dist/designer/assets/chart-DHEgt4lN.js +0 -1
- package/dist/designer/assets/column-resize-C_inr5zT.js +0 -1
- package/dist/designer/assets/date-format-4DJvNtG2.js +0 -1
- package/dist/designer/assets/date-format-Dzy4mTGh.css +0 -1
- package/dist/designer/assets/easing-zaypKrr0.js +0 -3
- package/dist/designer/assets/export-format-DwjuTfrQ.js +0 -6
- package/dist/designer/assets/index-Cp7fDJ3b.css +0 -1
- package/dist/designer/assets/js-scroller.svelte-Bhxqb3-c.js +0 -110
- package/dist/designer/assets/row-resize-B0FWHcNr.js +0 -1
- package/dist/designer/assets/src-B7DNcoQK.css +0 -1
- package/dist/designer/assets/src-BoYyigAC.js +0 -2896
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -178
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js +0 -3875
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js +0 -21
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js +0 -1938
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js +0 -205
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js +0 -18
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js +0 -264
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js +0 -697
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -3
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -134
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -55
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -46843
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -237
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -4
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -7
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -4
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -5
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -6
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -83
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -559
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -24
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -122
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -2
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -89
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -241
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js +0 -4938
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js +0 -495
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js +0 -190
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js +0 -8
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js.map +0 -1
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js +0 -138
- package/dist/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js.map +0 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What Excel makes of a typed entry before it is stored.
|
|
3
|
+
*
|
|
4
|
+
* `12%` is the number 0.12 shown as a percentage, `$1,200` is 1200 shown
|
|
5
|
+
* as currency, `1,234.5` is 1234.5 with a thousands separator: the text
|
|
6
|
+
* the user typed names both a value and how to show it, and the cell keeps
|
|
7
|
+
* both, so `=A1*2` over a `12%` cell is 0.24 rather than `#VALUE!`. The
|
|
8
|
+
* format is the one Excel would pick, with the decimals the user typed.
|
|
9
|
+
* Anything else, formulas included, is stored as typed.
|
|
10
|
+
*/
|
|
11
|
+
export type ParsedEntry = {
|
|
12
|
+
/** The number, as text the workbook stores. */
|
|
13
|
+
value: string;
|
|
14
|
+
/** The Excel format string the entry implies. */
|
|
15
|
+
numFmt: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Excel's AutoComplete for a column of text.
|
|
19
|
+
*
|
|
20
|
+
* As a cell is typed into, the entries in the same column that run without
|
|
21
|
+
* a blank above and below it are the candidates; when exactly one distinct
|
|
22
|
+
* text entry starts with what was typed, that entry is the completion, in
|
|
23
|
+
* its own case ("jo" completes to "John Smith"). Two candidates that both
|
|
24
|
+
* fit ("Apple", "Apricot" for "Ap") complete nothing until the typing tells
|
|
25
|
+
* them apart. Numbers, formulas and booleans never complete, and a typed
|
|
26
|
+
* text that already is an entry needs none.
|
|
27
|
+
*
|
|
28
|
+
* `entries` are the distinct text entries of the run, any order.
|
|
29
|
+
*/
|
|
30
|
+
export declare function completeEntry(typed: string, entries: Iterable<string>): string | null;
|
|
31
|
+
export declare function parseEntry(text: string): ParsedEntry | null;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const zeros = (n) => (n > 0 ? '.' + '0'.repeat(n) : '');
|
|
2
|
+
/** Digits with optional thousands separators and decimals, as a number. */
|
|
3
|
+
function numberOf(digits) {
|
|
4
|
+
const plain = digits.replace(/,/g, '');
|
|
5
|
+
const n = Number(plain);
|
|
6
|
+
return Number.isFinite(n) ? n : null;
|
|
7
|
+
}
|
|
8
|
+
const decimalsOf = (digits) => digits.split('.')[1]?.length ?? 0;
|
|
9
|
+
/** Round away the binary noise of a division: 33.3% is 0.333, not 0.33299999. */
|
|
10
|
+
const trim = (n, places) => String(Number(n.toFixed(places)));
|
|
11
|
+
const GROUPED = String.raw `(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?`;
|
|
12
|
+
const PERCENT = new RegExp(String.raw `^(-?)(${GROUPED})\s?%$`);
|
|
13
|
+
const CURRENCY = new RegExp(String.raw `^(-?)\$\s?(${GROUPED})$`);
|
|
14
|
+
const CURRENCY_PAREN = new RegExp(String.raw `^\(\$\s?(${GROUPED})\)$`);
|
|
15
|
+
const THOUSANDS = new RegExp(String.raw `^(-?)(\d{1,3}(?:,\d{3})+(?:\.\d+)?)$`);
|
|
16
|
+
/**
|
|
17
|
+
* Excel's AutoComplete for a column of text.
|
|
18
|
+
*
|
|
19
|
+
* As a cell is typed into, the entries in the same column that run without
|
|
20
|
+
* a blank above and below it are the candidates; when exactly one distinct
|
|
21
|
+
* text entry starts with what was typed, that entry is the completion, in
|
|
22
|
+
* its own case ("jo" completes to "John Smith"). Two candidates that both
|
|
23
|
+
* fit ("Apple", "Apricot" for "Ap") complete nothing until the typing tells
|
|
24
|
+
* them apart. Numbers, formulas and booleans never complete, and a typed
|
|
25
|
+
* text that already is an entry needs none.
|
|
26
|
+
*
|
|
27
|
+
* `entries` are the distinct text entries of the run, any order.
|
|
28
|
+
*/
|
|
29
|
+
export function completeEntry(typed, entries) {
|
|
30
|
+
if (typed === '' || typed.startsWith('=') || typed.includes('\n'))
|
|
31
|
+
return null;
|
|
32
|
+
const lower = typed.toLowerCase();
|
|
33
|
+
let found = null;
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
if (entry.length <= typed.length || !entry.toLowerCase().startsWith(lower))
|
|
36
|
+
continue;
|
|
37
|
+
if (found !== null && found !== entry)
|
|
38
|
+
return null;
|
|
39
|
+
found = entry;
|
|
40
|
+
}
|
|
41
|
+
return found;
|
|
42
|
+
}
|
|
43
|
+
export function parseEntry(text) {
|
|
44
|
+
const t = text.trim();
|
|
45
|
+
if (t === '' || t.startsWith('='))
|
|
46
|
+
return null;
|
|
47
|
+
let m = PERCENT.exec(t);
|
|
48
|
+
if (m) {
|
|
49
|
+
const n = numberOf(m[2]);
|
|
50
|
+
if (n === null)
|
|
51
|
+
return null;
|
|
52
|
+
const places = decimalsOf(m[2]);
|
|
53
|
+
return { value: trim((m[1] ? -n : n) / 100, places + 2), numFmt: `0${zeros(places)}%` };
|
|
54
|
+
}
|
|
55
|
+
m = CURRENCY.exec(t);
|
|
56
|
+
const paren = m ? null : CURRENCY_PAREN.exec(t);
|
|
57
|
+
if (m || paren) {
|
|
58
|
+
const digits = (m ? m[2] : paren[1]);
|
|
59
|
+
const n = numberOf(digits);
|
|
60
|
+
if (n === null)
|
|
61
|
+
return null;
|
|
62
|
+
const negative = m ? m[1] === '-' : true;
|
|
63
|
+
const places = decimalsOf(digits) > 0 ? 2 : 0;
|
|
64
|
+
const body = `$#,##0${zeros(places)}`;
|
|
65
|
+
return { value: String(negative ? -n : n), numFmt: `${body};(${body})` };
|
|
66
|
+
}
|
|
67
|
+
m = THOUSANDS.exec(t);
|
|
68
|
+
if (m) {
|
|
69
|
+
const n = numberOf(m[2]);
|
|
70
|
+
if (n === null)
|
|
71
|
+
return null;
|
|
72
|
+
const places = decimalsOf(m[2]);
|
|
73
|
+
return { value: String(m[1] ? -n : n), numFmt: `#,##0${zeros(places)}` };
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The evaluator.
|
|
3
|
+
*
|
|
4
|
+
* Errors travel as VALUES once evaluation finishes, but as thrown
|
|
5
|
+
* `FormulaError`s while it runs. That split is deliberate: a coercion buried
|
|
6
|
+
* three calls deep inside a function needs to abort the whole expression, and
|
|
7
|
+
* threading a result type through every branch of every builtin would swamp the
|
|
8
|
+
* table. The throw is caught here, at the one boundary, and becomes a value.
|
|
9
|
+
*
|
|
10
|
+
* Four functions never reach the table because they must NOT have every
|
|
11
|
+
* argument evaluated first: IF and IFS pick a branch, IFERROR needs to catch,
|
|
12
|
+
* and SWITCH matches before evaluating. Evaluating both branches of an IF is
|
|
13
|
+
* not just wasted work - `=IF(A1=0, 0, 100/A1)` would raise #DIV/0! from the
|
|
14
|
+
* branch it did not take.
|
|
15
|
+
*/
|
|
16
|
+
import { type CellValue, type Node } from './ast.js';
|
|
17
|
+
import { type SheetFunction } from './functions.js';
|
|
18
|
+
import { type TableRegion } from './tables.js';
|
|
19
|
+
export type EvalContext = {
|
|
20
|
+
/** Read one cell. Out of bounds should return `{ error: '#REF!' }`. */
|
|
21
|
+
resolve(sheet: string | null, row: number, col: number): CellValue;
|
|
22
|
+
/** Last used row of a sheet, for open-ended whole-column ranges. */
|
|
23
|
+
lastRow(sheet: string | null): number;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a defined name to the reference it stands for, or null when
|
|
26
|
+
* there is no such name. The node is evaluated in place of the name, so a
|
|
27
|
+
* name that refers to a range behaves as that range: `=SUM(Sales)` adds
|
|
28
|
+
* the whole column and `=VLOOKUP(x, Prices, 2)` searches the whole table.
|
|
29
|
+
* Preferred over `resolveName`, which can only ever produce one value.
|
|
30
|
+
*/
|
|
31
|
+
resolveNameNode?(name: string): Node | null;
|
|
32
|
+
/** Resolve a defined name to a single value. Consulted when
|
|
33
|
+
* `resolveNameNode` is absent or returns null; undefined is #NAME?. */
|
|
34
|
+
resolveName?(name: string): CellValue | undefined;
|
|
35
|
+
functions?: Record<string, SheetFunction>;
|
|
36
|
+
/** Look a table up by name. */
|
|
37
|
+
findTable?(name: string): TableRegion | undefined;
|
|
38
|
+
/** The table containing the cell the formula lives in, which is the only
|
|
39
|
+
* way the unqualified `[@Amount]` form can mean anything. */
|
|
40
|
+
tableAt?(sheet: string | null, row: number, col: number): TableRegion | undefined;
|
|
41
|
+
/** Where the formula being evaluated sits. Needed for `[@Column]`, which
|
|
42
|
+
* is relative to the formula rather than to the table. */
|
|
43
|
+
currentCell?: {
|
|
44
|
+
sheet: string | null;
|
|
45
|
+
row: number;
|
|
46
|
+
col: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Evaluate a parsed formula. Never throws: a `FormulaError` raised anywhere
|
|
51
|
+
* inside becomes the matching error value.
|
|
52
|
+
*/
|
|
53
|
+
/**
|
|
54
|
+
* The values a node stands for as a grid: a range, a reference (one cell),
|
|
55
|
+
* or a name that refers to either. Null for anything else, which is how a
|
|
56
|
+
* caller tells "a list source that is a range" from "a formula".
|
|
57
|
+
*/
|
|
58
|
+
export declare function rangeValues(node: Node, ctx: EvalContext): CellValue[][] | null;
|
|
59
|
+
export declare function evaluate(node: Node, ctx: EvalContext): CellValue;
|
|
60
|
+
/** Render a computed value the way a cell shows it. */
|
|
61
|
+
export declare function formatValue(v: CellValue): string;
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The evaluator.
|
|
3
|
+
*
|
|
4
|
+
* Errors travel as VALUES once evaluation finishes, but as thrown
|
|
5
|
+
* `FormulaError`s while it runs. That split is deliberate: a coercion buried
|
|
6
|
+
* three calls deep inside a function needs to abort the whole expression, and
|
|
7
|
+
* threading a result type through every branch of every builtin would swamp the
|
|
8
|
+
* table. The throw is caught here, at the one boundary, and becomes a value.
|
|
9
|
+
*
|
|
10
|
+
* Four functions never reach the table because they must NOT have every
|
|
11
|
+
* argument evaluated first: IF and IFS pick a branch, IFERROR needs to catch,
|
|
12
|
+
* and SWITCH matches before evaluating. Evaluating both branches of an IF is
|
|
13
|
+
* not just wasted work - `=IF(A1=0, 0, 100/A1)` would raise #DIV/0! from the
|
|
14
|
+
* branch it did not take.
|
|
15
|
+
*/
|
|
16
|
+
import { FormulaError, isError, err, } from './ast.js';
|
|
17
|
+
import { toNumber, toBool, toText, looseEquals, compare } from './coerce.js';
|
|
18
|
+
import { withCustomFunctions } from './functions.js';
|
|
19
|
+
import { resolveTableRange, columnIndexOf, } from './tables.js';
|
|
20
|
+
function rangeGrid(from, to, ctx) {
|
|
21
|
+
const sheet = from.sheet ?? to.sheet;
|
|
22
|
+
const r1 = Math.min(from.row ?? 0, to.row ?? from.row ?? 0);
|
|
23
|
+
const r2 = to.row === null || from.row === null
|
|
24
|
+
? ctx.lastRow(sheet)
|
|
25
|
+
: Math.max(from.row, to.row);
|
|
26
|
+
const c1 = Math.min(from.col, to.col);
|
|
27
|
+
const c2 = Math.max(from.col, to.col);
|
|
28
|
+
const out = [];
|
|
29
|
+
for (let r = r1; r <= r2; r += 1) {
|
|
30
|
+
const row = [];
|
|
31
|
+
for (let c = c1; c <= c2; c += 1)
|
|
32
|
+
row.push(ctx.resolve(sheet, r, c));
|
|
33
|
+
out.push(row);
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
function binary(op, l, r) {
|
|
38
|
+
switch (op) {
|
|
39
|
+
case '+': return toNumber(l) + toNumber(r);
|
|
40
|
+
case '-': return toNumber(l) - toNumber(r);
|
|
41
|
+
case '*': return toNumber(l) * toNumber(r);
|
|
42
|
+
case '/': {
|
|
43
|
+
const d = toNumber(r);
|
|
44
|
+
return d === 0 ? err('#DIV/0!') : toNumber(l) / d;
|
|
45
|
+
}
|
|
46
|
+
case '^': return Math.pow(toNumber(l), toNumber(r));
|
|
47
|
+
case '&': return toText(l) + toText(r);
|
|
48
|
+
case '=': return looseEquals(l, r);
|
|
49
|
+
case '<>': return !looseEquals(l, r);
|
|
50
|
+
case '<': return compare(l, r) < 0;
|
|
51
|
+
case '>': return compare(l, r) > 0;
|
|
52
|
+
case '<=': return compare(l, r) <= 0;
|
|
53
|
+
case '>=': return compare(l, r) >= 0;
|
|
54
|
+
default: return err('#VALUE!');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Functions handled before the table, because their arguments must not all
|
|
58
|
+
* be evaluated up front. */
|
|
59
|
+
const SHORT_CIRCUIT = new Set(['IF', 'IFS', 'IFERROR', 'IFNA', 'SWITCH']);
|
|
60
|
+
function evalNode(node, ctx) {
|
|
61
|
+
switch (node.k) {
|
|
62
|
+
case 'num': return node.v;
|
|
63
|
+
case 'str': return node.v;
|
|
64
|
+
case 'bool': return node.v;
|
|
65
|
+
case 'ref':
|
|
66
|
+
return ctx.resolve(node.ref.sheet, node.ref.row ?? 0, node.ref.col);
|
|
67
|
+
case 'range': {
|
|
68
|
+
// A range in scalar position collapses to its top-left cell, which is
|
|
69
|
+
// what Excel does outside an array context.
|
|
70
|
+
const grid = rangeGrid(node.from, node.to, ctx);
|
|
71
|
+
return grid[0]?.[0] ?? '';
|
|
72
|
+
}
|
|
73
|
+
case 'name': {
|
|
74
|
+
const target = nameTarget(node.name, ctx);
|
|
75
|
+
if (target)
|
|
76
|
+
return evalNode(target, ctx);
|
|
77
|
+
const v = ctx.resolveName?.(node.name);
|
|
78
|
+
return v === undefined ? err('#NAME?') : v;
|
|
79
|
+
}
|
|
80
|
+
case 'unary': {
|
|
81
|
+
const v = evalNode(node.arg, ctx);
|
|
82
|
+
if (isError(v))
|
|
83
|
+
return v;
|
|
84
|
+
if (node.op === '-')
|
|
85
|
+
return -toNumber(v);
|
|
86
|
+
if (node.op === '%')
|
|
87
|
+
return toNumber(v) / 100;
|
|
88
|
+
return toNumber(v);
|
|
89
|
+
}
|
|
90
|
+
case 'binary': {
|
|
91
|
+
const l = evalNode(node.left, ctx);
|
|
92
|
+
if (isError(l))
|
|
93
|
+
return l;
|
|
94
|
+
const r = evalNode(node.right, ctx);
|
|
95
|
+
if (isError(r))
|
|
96
|
+
return r;
|
|
97
|
+
return binary(node.op, l, r);
|
|
98
|
+
}
|
|
99
|
+
case 'table':
|
|
100
|
+
return evalTableRef(node, ctx);
|
|
101
|
+
case 'fn':
|
|
102
|
+
return evalCall(node, ctx);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Turn a structured reference into a rectangle and read it.
|
|
107
|
+
*
|
|
108
|
+
* Every failure here is #REF! rather than a throw, because a table reference
|
|
109
|
+
* naming a column that was renamed is an ordinary thing to find in a sheet,
|
|
110
|
+
* and one broken total should not take the rest of the workbook with it.
|
|
111
|
+
*/
|
|
112
|
+
function tableRectOf(node, ctx) {
|
|
113
|
+
const here = ctx.currentCell;
|
|
114
|
+
const table = node.table
|
|
115
|
+
? ctx.findTable?.(node.table)
|
|
116
|
+
: here
|
|
117
|
+
? ctx.tableAt?.(here.sheet, here.row, here.col)
|
|
118
|
+
: undefined;
|
|
119
|
+
if (!table)
|
|
120
|
+
return null;
|
|
121
|
+
const headerAt = (sheet, row, col) => {
|
|
122
|
+
const v = ctx.resolve(sheet, row, col);
|
|
123
|
+
return isError(v) ? '' : toText(v);
|
|
124
|
+
};
|
|
125
|
+
let columns = null;
|
|
126
|
+
if (node.column !== null) {
|
|
127
|
+
const from = columnIndexOf(table, node.column, headerAt);
|
|
128
|
+
if (from < 0)
|
|
129
|
+
return null;
|
|
130
|
+
const to = node.columnTo != null
|
|
131
|
+
? columnIndexOf(table, node.columnTo, headerAt)
|
|
132
|
+
: from;
|
|
133
|
+
if (to < 0)
|
|
134
|
+
return null;
|
|
135
|
+
columns = { from: Math.min(from, to), to: Math.max(from, to) };
|
|
136
|
+
}
|
|
137
|
+
return resolveTableRange(table, node.specifier, columns, here ? here.row : null);
|
|
138
|
+
}
|
|
139
|
+
function evalTableRef(node, ctx) {
|
|
140
|
+
const rect = tableRectOf(node, ctx);
|
|
141
|
+
if (!rect)
|
|
142
|
+
return err('#REF!');
|
|
143
|
+
// Scalar position collapses to the top-left, the same as an A1 range.
|
|
144
|
+
return ctx.resolve(rect.sheet, rect.firstRow, rect.firstCol);
|
|
145
|
+
}
|
|
146
|
+
/** Every cell of a structured reference, for the aggregate functions. */
|
|
147
|
+
function tableGrid(node, ctx) {
|
|
148
|
+
const rect = tableRectOf(node, ctx);
|
|
149
|
+
if (!rect)
|
|
150
|
+
return null;
|
|
151
|
+
const out = [];
|
|
152
|
+
for (let r = rect.firstRow; r <= rect.lastRow; r += 1) {
|
|
153
|
+
const line = [];
|
|
154
|
+
for (let c = rect.firstCol; c <= rect.lastCol; c += 1)
|
|
155
|
+
line.push(ctx.resolve(rect.sheet, r, c));
|
|
156
|
+
out.push(line);
|
|
157
|
+
}
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The reference a defined name stands for, or null.
|
|
162
|
+
*
|
|
163
|
+
* A name may be defined as another name (`Sales` -> `Q3Sales`), so this
|
|
164
|
+
* follows the chain. It stops after a handful of hops rather than walking a
|
|
165
|
+
* circular definition forever: `A` -> `B` -> `A` is a mistake in the Name
|
|
166
|
+
* Manager, and the formula that used it reads #NAME? rather than hanging.
|
|
167
|
+
*/
|
|
168
|
+
function nameTarget(name, ctx) {
|
|
169
|
+
let node = ctx.resolveNameNode?.(name) ?? null;
|
|
170
|
+
for (let hops = 0; node && node.k === 'name'; hops += 1) {
|
|
171
|
+
if (hops >= 8)
|
|
172
|
+
return null;
|
|
173
|
+
node = ctx.resolveNameNode?.(node.name) ?? null;
|
|
174
|
+
}
|
|
175
|
+
return node;
|
|
176
|
+
}
|
|
177
|
+
/** Functions whose arguments must not all be evaluated up front. */
|
|
178
|
+
function evalCall(node, ctx) {
|
|
179
|
+
const { name, args } = node;
|
|
180
|
+
// Every short-circuiting function below indexes its arguments directly.
|
|
181
|
+
// `=IF()` parses fine, so without this the index is undefined and the
|
|
182
|
+
// TypeError escapes the boundary this module promises never to throw past.
|
|
183
|
+
if (SHORT_CIRCUIT.has(name) && args.length === 0)
|
|
184
|
+
return err('#VALUE!');
|
|
185
|
+
if (name === 'IF') {
|
|
186
|
+
const cond = evalNode(args[0], ctx);
|
|
187
|
+
if (isError(cond))
|
|
188
|
+
return cond;
|
|
189
|
+
const branch = toBool(cond) ? args[1] : args[2];
|
|
190
|
+
if (!branch)
|
|
191
|
+
return toBool(cond);
|
|
192
|
+
return evalNode(branch, ctx);
|
|
193
|
+
}
|
|
194
|
+
if (name === 'IFERROR' || name === 'IFNA') {
|
|
195
|
+
try {
|
|
196
|
+
const v = evalNode(args[0], ctx);
|
|
197
|
+
if (!isError(v))
|
|
198
|
+
return v;
|
|
199
|
+
if (name === 'IFNA' && v.error !== '#N/A')
|
|
200
|
+
return v;
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
if (!(e instanceof FormulaError))
|
|
204
|
+
throw e;
|
|
205
|
+
if (name === 'IFNA' && e.code !== '#N/A')
|
|
206
|
+
return err(e.code);
|
|
207
|
+
}
|
|
208
|
+
return args[1] ? evalNode(args[1], ctx) : err('#N/A');
|
|
209
|
+
}
|
|
210
|
+
if (name === 'IFS') {
|
|
211
|
+
for (let i = 0; i + 1 < args.length; i += 2) {
|
|
212
|
+
const cond = evalNode(args[i], ctx);
|
|
213
|
+
if (isError(cond))
|
|
214
|
+
return cond;
|
|
215
|
+
if (toBool(cond))
|
|
216
|
+
return evalNode(args[i + 1], ctx);
|
|
217
|
+
}
|
|
218
|
+
return err('#N/A');
|
|
219
|
+
}
|
|
220
|
+
if (name === 'SWITCH') {
|
|
221
|
+
const subject = evalNode(args[0], ctx);
|
|
222
|
+
if (isError(subject))
|
|
223
|
+
return subject;
|
|
224
|
+
let i = 1;
|
|
225
|
+
for (; i + 1 < args.length; i += 2) {
|
|
226
|
+
const candidate = evalNode(args[i], ctx);
|
|
227
|
+
if (isError(candidate))
|
|
228
|
+
return candidate;
|
|
229
|
+
if (looseEquals(subject, candidate))
|
|
230
|
+
return evalNode(args[i + 1], ctx);
|
|
231
|
+
}
|
|
232
|
+
// A trailing odd argument is the default.
|
|
233
|
+
return i < args.length ? evalNode(args[i], ctx) : err('#N/A');
|
|
234
|
+
}
|
|
235
|
+
const table = ctx.functions ?? withCustomFunctions(undefined);
|
|
236
|
+
const fn = table[name];
|
|
237
|
+
if (!fn)
|
|
238
|
+
return err('#NAME?');
|
|
239
|
+
// Evaluate every argument, keeping range shape for the lookups that need it.
|
|
240
|
+
const perArg = [];
|
|
241
|
+
const grids = [];
|
|
242
|
+
for (const given of args) {
|
|
243
|
+
// A name stands for whatever it was defined as. Substituting the node
|
|
244
|
+
// here, before the shape check, is what lets `Sales` in =SUM(Sales) be a
|
|
245
|
+
// whole column rather than the top-left cell a scalar read would give.
|
|
246
|
+
const arg = given.k === 'name' ? (nameTarget(given.name, ctx) ?? given) : given;
|
|
247
|
+
if (arg.k === 'range') {
|
|
248
|
+
const grid = rangeGrid(arg.from, arg.to, ctx);
|
|
249
|
+
grids.push(grid);
|
|
250
|
+
perArg.push(grid.flat());
|
|
251
|
+
}
|
|
252
|
+
else if (arg.k === 'table') {
|
|
253
|
+
// A structured reference expands exactly as a range does, which is
|
|
254
|
+
// what makes =SUM(Orders[Amount]) work.
|
|
255
|
+
const grid = tableGrid(arg, ctx);
|
|
256
|
+
if (!grid) {
|
|
257
|
+
grids.push(null);
|
|
258
|
+
perArg.push([err('#REF!')]);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
grids.push(grid);
|
|
262
|
+
perArg.push(grid.flat());
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
grids.push(null);
|
|
267
|
+
perArg.push([evalNode(arg, ctx)]);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const flat = perArg.flat();
|
|
271
|
+
// An error anywhere in the arguments propagates, except for the counting
|
|
272
|
+
// functions, which Excel lets see errors in their range.
|
|
273
|
+
if (name !== 'COUNTA' && name !== 'COUNTBLANK') {
|
|
274
|
+
for (const v of flat)
|
|
275
|
+
if (isError(v))
|
|
276
|
+
return v;
|
|
277
|
+
}
|
|
278
|
+
const payload = { flat, args: perArg, grids };
|
|
279
|
+
return fn(payload);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Evaluate a parsed formula. Never throws: a `FormulaError` raised anywhere
|
|
283
|
+
* inside becomes the matching error value.
|
|
284
|
+
*/
|
|
285
|
+
/**
|
|
286
|
+
* The values a node stands for as a grid: a range, a reference (one cell),
|
|
287
|
+
* or a name that refers to either. Null for anything else, which is how a
|
|
288
|
+
* caller tells "a list source that is a range" from "a formula".
|
|
289
|
+
*/
|
|
290
|
+
export function rangeValues(node, ctx) {
|
|
291
|
+
try {
|
|
292
|
+
if (node.k === 'range')
|
|
293
|
+
return rangeGrid(node.from, node.to, ctx);
|
|
294
|
+
if (node.k === 'ref')
|
|
295
|
+
return [[ctx.resolve(node.ref.sheet, node.ref.row ?? 0, node.ref.col)]];
|
|
296
|
+
if (node.k === 'name') {
|
|
297
|
+
const target = nameTarget(node.name, ctx);
|
|
298
|
+
return target ? rangeValues(target, ctx) : null;
|
|
299
|
+
}
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
if (e instanceof FormulaError)
|
|
304
|
+
return [[err(e.code)]];
|
|
305
|
+
throw e;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
export function evaluate(node, ctx) {
|
|
309
|
+
try {
|
|
310
|
+
return evalNode(node, ctx);
|
|
311
|
+
}
|
|
312
|
+
catch (e) {
|
|
313
|
+
if (e instanceof FormulaError)
|
|
314
|
+
return err(e.code);
|
|
315
|
+
if (e instanceof RangeError)
|
|
316
|
+
return err('#NUM!');
|
|
317
|
+
// Last resort. This module promises callers it never throws, and a cell
|
|
318
|
+
// showing #VALUE! is recoverable where an exception out of a render pass
|
|
319
|
+
// is not.
|
|
320
|
+
if (e instanceof TypeError)
|
|
321
|
+
return err('#VALUE!');
|
|
322
|
+
throw e;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/** Render a computed value the way a cell shows it. */
|
|
326
|
+
export function formatValue(v) {
|
|
327
|
+
if (isError(v))
|
|
328
|
+
return v.error;
|
|
329
|
+
if (typeof v === 'boolean')
|
|
330
|
+
return v ? 'TRUE' : 'FALSE';
|
|
331
|
+
if (typeof v === 'number') {
|
|
332
|
+
if (!Number.isFinite(v))
|
|
333
|
+
return '#NUM!';
|
|
334
|
+
return String(v);
|
|
335
|
+
}
|
|
336
|
+
return String(v);
|
|
337
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find and Replace.
|
|
3
|
+
*
|
|
4
|
+
* The grid already has find: a Ctrl+F overlay over displayed values, with
|
|
5
|
+
* next/prev. What it has no notion of is replacing, and the two differ in more
|
|
6
|
+
* than direction.
|
|
7
|
+
*
|
|
8
|
+
* Finding looks at what the user SEES. Replacing has to write what the user
|
|
9
|
+
* TYPED, which for a formula cell is the formula, not its result. Replacing
|
|
10
|
+
* "100" inside a cell showing `100` that actually holds `=B2*C2` would either
|
|
11
|
+
* do nothing or destroy the formula, depending on which text you reached for.
|
|
12
|
+
* Hence `lookIn`, and hence replace always writing through the raw text.
|
|
13
|
+
*/
|
|
14
|
+
import type { GridCommandContext } from '@svgrid/grid/shortcuts';
|
|
15
|
+
export type FindOptions = {
|
|
16
|
+
matchCase?: boolean;
|
|
17
|
+
/** The cell must equal the search text, not merely contain it. */
|
|
18
|
+
matchEntireCell?: boolean;
|
|
19
|
+
/** Search the formula source, or the value a cell displays. Default 'values'. */
|
|
20
|
+
lookIn?: 'values' | 'formulas';
|
|
21
|
+
/** Restrict to the current selection. Default the whole sheet. */
|
|
22
|
+
scope?: 'sheet' | 'selection';
|
|
23
|
+
};
|
|
24
|
+
export type FindHit = {
|
|
25
|
+
rowIndex: number;
|
|
26
|
+
colIndex: number;
|
|
27
|
+
};
|
|
28
|
+
/** How a cell's text is obtained for each `lookIn` mode. */
|
|
29
|
+
export type FindTarget = {
|
|
30
|
+
/** The raw text the user typed, formula included. */
|
|
31
|
+
getRaw(rowIndex: number, colIndex: number): string;
|
|
32
|
+
/** What the cell displays. Defaults to the raw text when not supplied. */
|
|
33
|
+
getDisplay?(rowIndex: number, colIndex: number): string;
|
|
34
|
+
setRaw(rowIndex: number, colIndex: number, text: string): void;
|
|
35
|
+
/** Whether a cell may be written. Read-only cells are skipped by replace
|
|
36
|
+
* but still reported by find. */
|
|
37
|
+
isEditable?(rowIndex: number, colIndex: number): boolean;
|
|
38
|
+
onChange?(): void;
|
|
39
|
+
};
|
|
40
|
+
export declare function setFindTarget(next: FindTarget | null): void;
|
|
41
|
+
export declare function getFindTarget(): FindTarget | null;
|
|
42
|
+
/** Does `haystack` match `needle` under these options? */
|
|
43
|
+
export declare function cellMatches(haystack: string, needle: string, opts?: FindOptions): boolean;
|
|
44
|
+
/** Every cell matching, in reading order. */
|
|
45
|
+
export declare function findAll(cmd: GridCommandContext, needle: string, opts?: FindOptions): FindHit[];
|
|
46
|
+
/** The next hit after the active cell, wrapping. Null when there are none. */
|
|
47
|
+
export declare function findNext(cmd: GridCommandContext, needle: string, opts?: FindOptions, direction?: 1 | -1): FindHit | null;
|
|
48
|
+
/** Replace inside one string, honouring case sensitivity and whole-cell. */
|
|
49
|
+
export declare function replaceInText(haystack: string, needle: string, replacement: string, opts?: FindOptions): string;
|
|
50
|
+
/**
|
|
51
|
+
* Replace the active cell if it matches, then move to the next hit. Returns
|
|
52
|
+
* whether anything was written.
|
|
53
|
+
*/
|
|
54
|
+
export declare function replaceOne(cmd: GridCommandContext, needle: string, replacement: string, opts?: FindOptions): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Replace every match. Returns how many cells changed.
|
|
57
|
+
*
|
|
58
|
+
* Runs inside `cmd.batch`, so a hundred replacements are ONE Ctrl+Z. Without
|
|
59
|
+
* that this would be the single worst thing in the feature set for undo: it is
|
|
60
|
+
* the one command that routinely writes more cells than the history can hold.
|
|
61
|
+
*/
|
|
62
|
+
export declare function replaceAll(cmd: GridCommandContext, needle: string, replacement: string, opts?: FindOptions): number;
|