@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,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formula-bar autocomplete, kept out of the component so the interesting part
|
|
3
|
+
* is testable without mounting anything.
|
|
4
|
+
*
|
|
5
|
+
* The job is narrow: given the text in the bar and where the caret is, work out
|
|
6
|
+
* whether the user is partway through typing a function name, and if so which
|
|
7
|
+
* ones match. Everything else (arrow keys, accepting a suggestion) is a list
|
|
8
|
+
* with an index, which the component owns.
|
|
9
|
+
*/
|
|
10
|
+
import { FUNCTIONS } from './functions.js';
|
|
11
|
+
const NAMES = Object.keys(FUNCTIONS).sort();
|
|
12
|
+
/** Signature hints, for the ones whose argument order is not obvious. */
|
|
13
|
+
export const SIGNATURES = {
|
|
14
|
+
VLOOKUP: 'VLOOKUP(lookup, table, colIndex)',
|
|
15
|
+
HLOOKUP: 'HLOOKUP(lookup, table, rowIndex)',
|
|
16
|
+
XLOOKUP: 'XLOOKUP(lookup, haystack, results, [ifMissing])',
|
|
17
|
+
INDEX: 'INDEX(range, row, [col])',
|
|
18
|
+
MATCH: 'MATCH(lookup, range, [mode])',
|
|
19
|
+
SUMIF: 'SUMIF(range, criterion, [sumRange])',
|
|
20
|
+
SUMIFS: 'SUMIFS(sumRange, range, criterion, ...)',
|
|
21
|
+
COUNTIF: 'COUNTIF(range, criterion)',
|
|
22
|
+
COUNTIFS: 'COUNTIFS(range, criterion, ...)',
|
|
23
|
+
AVERAGEIF: 'AVERAGEIF(range, criterion, [avgRange])',
|
|
24
|
+
IF: 'IF(condition, then, else)',
|
|
25
|
+
IFS: 'IFS(condition, value, ...)',
|
|
26
|
+
IFERROR: 'IFERROR(value, fallback)',
|
|
27
|
+
SWITCH: 'SWITCH(subject, case, value, ..., [default])',
|
|
28
|
+
ROUND: 'ROUND(number, digits)',
|
|
29
|
+
TEXT: 'TEXT(number, pattern)',
|
|
30
|
+
TEXTJOIN: 'TEXTJOIN(separator, skipEmpty, ...)',
|
|
31
|
+
SUBSTITUTE: 'SUBSTITUTE(text, find, replace)',
|
|
32
|
+
MID: 'MID(text, start, length)',
|
|
33
|
+
DATE: 'DATE(year, month, day)',
|
|
34
|
+
EOMONTH: 'EOMONTH(date, months)',
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* The word being typed immediately before the caret, if it could be a function
|
|
38
|
+
* name. Returns null when the caret is not in a formula, or sits somewhere a
|
|
39
|
+
* function name cannot start (inside a string, or right after a reference).
|
|
40
|
+
*/
|
|
41
|
+
export function partialAt(text, caret) {
|
|
42
|
+
if (!text.startsWith('='))
|
|
43
|
+
return null;
|
|
44
|
+
const upto = text.slice(0, caret);
|
|
45
|
+
// Inside a string literal there is nothing to suggest. Count unescaped
|
|
46
|
+
// quotes: an odd number means the caret is inside one.
|
|
47
|
+
let quotes = 0;
|
|
48
|
+
for (let i = 0; i < upto.length; i += 1) {
|
|
49
|
+
if (upto[i] === '"') {
|
|
50
|
+
if (upto[i + 1] === '"') {
|
|
51
|
+
i += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
quotes += 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (quotes % 2 === 1)
|
|
58
|
+
return null;
|
|
59
|
+
const m = /([A-Za-z][A-Za-z0-9.]*)$/.exec(upto);
|
|
60
|
+
if (!m)
|
|
61
|
+
return null;
|
|
62
|
+
const word = m[1];
|
|
63
|
+
const start = caret - word.length;
|
|
64
|
+
// A word followed by digits is a cell reference being typed, not a function.
|
|
65
|
+
if (/\d$/.test(word))
|
|
66
|
+
return null;
|
|
67
|
+
return { word, start };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Function names matching what is being typed.
|
|
71
|
+
*
|
|
72
|
+
* Prefix matches first, then anything merely containing the text, so typing
|
|
73
|
+
* "look" still finds VLOOKUP. Within each group, SHORTER names rank first:
|
|
74
|
+
* alphabetical order puts SUBSTITUTE above SUM for "SU", which is exactly
|
|
75
|
+
* backwards from what someone typing two letters wants.
|
|
76
|
+
*/
|
|
77
|
+
export function suggestFunctions(text, caret, limit = 8) {
|
|
78
|
+
const partial = partialAt(text, caret);
|
|
79
|
+
if (!partial || partial.word.length < 1)
|
|
80
|
+
return [];
|
|
81
|
+
const upper = partial.word.toUpperCase();
|
|
82
|
+
const prefix = [];
|
|
83
|
+
const contains = [];
|
|
84
|
+
for (const name of NAMES) {
|
|
85
|
+
if (name === upper)
|
|
86
|
+
continue;
|
|
87
|
+
if (name.startsWith(upper))
|
|
88
|
+
prefix.push(name);
|
|
89
|
+
else if (name.includes(upper))
|
|
90
|
+
contains.push(name);
|
|
91
|
+
}
|
|
92
|
+
const byCloseness = (a, b) => a.length - b.length || a.localeCompare(b);
|
|
93
|
+
return [...prefix.sort(byCloseness), ...contains.sort(byCloseness)]
|
|
94
|
+
.slice(0, limit)
|
|
95
|
+
.map((name) => ({ name, start: partial.start, end: caret }));
|
|
96
|
+
}
|
|
97
|
+
/** Splice an accepted suggestion in, leaving the caret inside the parens. */
|
|
98
|
+
export function applySuggestion(text, suggestion) {
|
|
99
|
+
const before = text.slice(0, suggestion.start);
|
|
100
|
+
const after = text.slice(suggestion.end);
|
|
101
|
+
// Do not double up a parenthesis the user already typed.
|
|
102
|
+
const needsParen = !after.startsWith('(');
|
|
103
|
+
// Only the OPENING parenthesis, as Excel inserts it. Inserting the pair
|
|
104
|
+
// put the caret between them, and everyone who then typed the arguments
|
|
105
|
+
// finished with a ")" of their own and got =SUM(A1:A3)) and #PARSE!.
|
|
106
|
+
// The closing one is supplied at commit by `balanceParens` when it is
|
|
107
|
+
// still missing, which is what Excel does too.
|
|
108
|
+
const inserted = needsParen ? `${suggestion.name}(` : suggestion.name;
|
|
109
|
+
return {
|
|
110
|
+
text: before + inserted + after,
|
|
111
|
+
caret: before.length + inserted.length,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Close the parentheses a formula left open, the way Excel corrects
|
|
116
|
+
* "=SUM(A1:A3" to "=SUM(A1:A3)" when it is entered. Quoted text is skipped,
|
|
117
|
+
* so a ")" inside a string neither closes nor needs closing. Text that is
|
|
118
|
+
* not a formula, or has more closers than openers, is returned as it is:
|
|
119
|
+
* that one is an error the engine should report, not paper over.
|
|
120
|
+
*/
|
|
121
|
+
export function balanceParens(text) {
|
|
122
|
+
if (!text.startsWith('='))
|
|
123
|
+
return text;
|
|
124
|
+
let depth = 0;
|
|
125
|
+
let inString = false;
|
|
126
|
+
for (const ch of text) {
|
|
127
|
+
if (ch === '"')
|
|
128
|
+
inString = !inString;
|
|
129
|
+
else if (!inString && ch === '(')
|
|
130
|
+
depth += 1;
|
|
131
|
+
else if (!inString && ch === ')')
|
|
132
|
+
depth -= 1;
|
|
133
|
+
}
|
|
134
|
+
return depth > 0 ? text + ')'.repeat(depth) : text;
|
|
135
|
+
}
|
|
136
|
+
/** The signature hint for whatever call the caret is inside, if any. */
|
|
137
|
+
export function signatureAt(text, caret) {
|
|
138
|
+
if (!text.startsWith('='))
|
|
139
|
+
return null;
|
|
140
|
+
const upto = text.slice(0, caret);
|
|
141
|
+
// Walk back looking for an unclosed '(' and read the name before it.
|
|
142
|
+
let depth = 0;
|
|
143
|
+
for (let i = upto.length - 1; i >= 0; i -= 1) {
|
|
144
|
+
const ch = upto[i];
|
|
145
|
+
if (ch === ')') {
|
|
146
|
+
depth += 1;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (ch === '(') {
|
|
150
|
+
if (depth > 0) {
|
|
151
|
+
depth -= 1;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const name = /([A-Za-z][A-Za-z0-9.]*)$/.exec(upto.slice(0, i))?.[1];
|
|
155
|
+
if (!name)
|
|
156
|
+
return null;
|
|
157
|
+
const upper = name.toUpperCase();
|
|
158
|
+
return SIGNATURES[upper] ?? (upper in FUNCTIONS ? `${upper}(...)` : null);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Value coercions, shared by the evaluator and the function table.
|
|
3
|
+
*
|
|
4
|
+
* Excel's rules, not JavaScript's. The differences that matter:
|
|
5
|
+
* - An empty cell is 0 in arithmetic but is NOT counted by COUNT or averaged
|
|
6
|
+
* by AVERAGE, so "coerce to number" and "is a number" are separate tests.
|
|
7
|
+
* - Text that does not parse as a number is `#VALUE!`, not NaN. Returning NaN
|
|
8
|
+
* would let a bad cell poison a total silently.
|
|
9
|
+
* - Text comparison is case-insensitive: `="a"="A"` is TRUE.
|
|
10
|
+
* - Booleans are 1 and 0 in arithmetic but are skipped by numeric aggregates.
|
|
11
|
+
*/
|
|
12
|
+
import { type CellValue } from './ast.js';
|
|
13
|
+
export declare function toNumber(v: CellValue): number;
|
|
14
|
+
export declare function toBool(v: CellValue): boolean;
|
|
15
|
+
export declare function toText(v: CellValue): string;
|
|
16
|
+
/** Excel's `=` between two values. Text compares case-insensitively; a number
|
|
17
|
+
* never equals the text that looks like it. */
|
|
18
|
+
export declare function looseEquals(a: CellValue, b: CellValue): boolean;
|
|
19
|
+
/** Ordering for `<` and friends. Excel orders number < text < boolean. */
|
|
20
|
+
export declare function compare(a: CellValue, b: CellValue): number;
|
|
21
|
+
/** The numeric members of a flattened argument list. Blanks, text and booleans
|
|
22
|
+
* are skipped, which is what makes AVERAGE of a column with a header work. */
|
|
23
|
+
export declare function numericOnly(values: ReadonlyArray<CellValue>): number[];
|
|
24
|
+
/** Is this cell empty for COUNTA / COUNTBLANK purposes. */
|
|
25
|
+
export declare function isBlank(v: CellValue): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* An Excel criterion: a bare value matches by equality, a string starting with
|
|
28
|
+
* an operator compares (`">100"`, `"<>x"`). Used by SUMIF / COUNTIF / their
|
|
29
|
+
* plural forms, which all share this grammar.
|
|
30
|
+
*/
|
|
31
|
+
export declare function matchesCriterion(value: CellValue, criterion: CellValue): boolean;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Value coercions, shared by the evaluator and the function table.
|
|
3
|
+
*
|
|
4
|
+
* Excel's rules, not JavaScript's. The differences that matter:
|
|
5
|
+
* - An empty cell is 0 in arithmetic but is NOT counted by COUNT or averaged
|
|
6
|
+
* by AVERAGE, so "coerce to number" and "is a number" are separate tests.
|
|
7
|
+
* - Text that does not parse as a number is `#VALUE!`, not NaN. Returning NaN
|
|
8
|
+
* would let a bad cell poison a total silently.
|
|
9
|
+
* - Text comparison is case-insensitive: `="a"="A"` is TRUE.
|
|
10
|
+
* - Booleans are 1 and 0 in arithmetic but are skipped by numeric aggregates.
|
|
11
|
+
*/
|
|
12
|
+
import { FormulaError, isError } from './ast.js';
|
|
13
|
+
export function toNumber(v) {
|
|
14
|
+
if (typeof v === 'number')
|
|
15
|
+
return v;
|
|
16
|
+
if (typeof v === 'boolean')
|
|
17
|
+
return v ? 1 : 0;
|
|
18
|
+
if (typeof v === 'string') {
|
|
19
|
+
if (v.trim() === '')
|
|
20
|
+
return 0;
|
|
21
|
+
const n = Number(v);
|
|
22
|
+
if (Number.isFinite(n))
|
|
23
|
+
return n;
|
|
24
|
+
throw new FormulaError('#VALUE!');
|
|
25
|
+
}
|
|
26
|
+
if (isError(v))
|
|
27
|
+
throw new FormulaError(v.error);
|
|
28
|
+
return 0;
|
|
29
|
+
}
|
|
30
|
+
export function toBool(v) {
|
|
31
|
+
if (typeof v === 'boolean')
|
|
32
|
+
return v;
|
|
33
|
+
if (typeof v === 'number')
|
|
34
|
+
return v !== 0;
|
|
35
|
+
if (typeof v === 'string') {
|
|
36
|
+
const upper = v.trim().toUpperCase();
|
|
37
|
+
if (upper === 'TRUE')
|
|
38
|
+
return true;
|
|
39
|
+
if (upper === 'FALSE')
|
|
40
|
+
return false;
|
|
41
|
+
return v.length > 0;
|
|
42
|
+
}
|
|
43
|
+
if (isError(v))
|
|
44
|
+
throw new FormulaError(v.error);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
export function toText(v) {
|
|
48
|
+
if (typeof v === 'string')
|
|
49
|
+
return v;
|
|
50
|
+
if (typeof v === 'boolean')
|
|
51
|
+
return v ? 'TRUE' : 'FALSE';
|
|
52
|
+
if (typeof v === 'number')
|
|
53
|
+
return String(v);
|
|
54
|
+
if (isError(v))
|
|
55
|
+
throw new FormulaError(v.error);
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
/** Excel's `=` between two values. Text compares case-insensitively; a number
|
|
59
|
+
* never equals the text that looks like it. */
|
|
60
|
+
export function looseEquals(a, b) {
|
|
61
|
+
if (typeof a === 'number' && typeof b === 'number')
|
|
62
|
+
return a === b;
|
|
63
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
64
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
if (typeof a === 'boolean' && typeof b === 'boolean')
|
|
67
|
+
return a === b;
|
|
68
|
+
if (isError(a) || isError(b))
|
|
69
|
+
return false;
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
/** Ordering for `<` and friends. Excel orders number < text < boolean. */
|
|
73
|
+
export function compare(a, b) {
|
|
74
|
+
if (typeof a === 'number' && typeof b === 'number')
|
|
75
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
76
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
77
|
+
const x = a.toLowerCase();
|
|
78
|
+
const y = b.toLowerCase();
|
|
79
|
+
return x < y ? -1 : x > y ? 1 : 0;
|
|
80
|
+
}
|
|
81
|
+
return toNumber(a) < toNumber(b) ? -1 : toNumber(a) > toNumber(b) ? 1 : 0;
|
|
82
|
+
}
|
|
83
|
+
/** The numeric members of a flattened argument list. Blanks, text and booleans
|
|
84
|
+
* are skipped, which is what makes AVERAGE of a column with a header work. */
|
|
85
|
+
export function numericOnly(values) {
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const v of values) {
|
|
88
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
89
|
+
out.push(v);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
/** Is this cell empty for COUNTA / COUNTBLANK purposes. */
|
|
94
|
+
export function isBlank(v) {
|
|
95
|
+
return v === '' || v === null || v === undefined;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* An Excel criterion: a bare value matches by equality, a string starting with
|
|
99
|
+
* an operator compares (`">100"`, `"<>x"`). Used by SUMIF / COUNTIF / their
|
|
100
|
+
* plural forms, which all share this grammar.
|
|
101
|
+
*/
|
|
102
|
+
export function matchesCriterion(value, criterion) {
|
|
103
|
+
if (typeof criterion === 'string') {
|
|
104
|
+
const m = /^(<=|>=|<>|<|>|=)(.*)$/.exec(criterion.trim());
|
|
105
|
+
if (m) {
|
|
106
|
+
const opText = m[1];
|
|
107
|
+
const rest = m[2].trim();
|
|
108
|
+
const n = Number(rest);
|
|
109
|
+
const operand = rest !== '' && Number.isFinite(n) ? n : rest;
|
|
110
|
+
switch (opText) {
|
|
111
|
+
case '=': return looseEquals(value, operand);
|
|
112
|
+
case '<>': return !looseEquals(value, operand);
|
|
113
|
+
case '<': return compare(value, operand) < 0;
|
|
114
|
+
case '>': return compare(value, operand) > 0;
|
|
115
|
+
case '<=': return compare(value, operand) <= 0;
|
|
116
|
+
case '>=': return compare(value, operand) >= 0;
|
|
117
|
+
default: break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return looseEquals(value, criterion);
|
|
122
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The keyboard commands themselves, written against `GridCommandContext` so
|
|
3
|
+
* they stay testable without mounting a grid.
|
|
4
|
+
*
|
|
5
|
+
* Every one that writes more than one cell runs inside `cmd.batch()`, so the
|
|
6
|
+
* whole action is a single Ctrl+Z. That is the seam added in @svgrid/grid;
|
|
7
|
+
* without it a Ctrl+D down a hundred rows would take a hundred presses to undo
|
|
8
|
+
* and would evict the history behind it.
|
|
9
|
+
*
|
|
10
|
+
* Phase 1 fills VALUES. Excel also translates relative references as it fills,
|
|
11
|
+
* so `=A1*2` in the source row becomes `=A2*2` one row down; that needs the
|
|
12
|
+
* formula engine's AST and lands with it in phase 2. Until then a formula
|
|
13
|
+
* fills as literal text, which is wrong for formulas and right for everything
|
|
14
|
+
* else, and is why `fillDown` routes through one `translateForFill` hook
|
|
15
|
+
* rather than inlining the copy.
|
|
16
|
+
*/
|
|
17
|
+
import type { GridCommandContext } from '@svgrid/grid/shortcuts';
|
|
18
|
+
import { type Rect } from './navigate.js';
|
|
19
|
+
/**
|
|
20
|
+
* How a value copied from (srcRow, srcCol) to (dstRow, dstCol) is rewritten.
|
|
21
|
+
* Phase 1 is identity. Phase 2 swaps in the engine's `translateFormula`, which
|
|
22
|
+
* is why every fill path calls it rather than copying the value directly.
|
|
23
|
+
*/
|
|
24
|
+
export type FillTranslator = (value: unknown, delta: {
|
|
25
|
+
rows: number;
|
|
26
|
+
cols: number;
|
|
27
|
+
}) => unknown;
|
|
28
|
+
/** Install the formula-aware translator. The engine calls this in phase 2. */
|
|
29
|
+
export declare function setFillTranslator(fn: FillTranslator | null): void;
|
|
30
|
+
export declare function targetRect(cmd: GridCommandContext): Rect | null;
|
|
31
|
+
/**
|
|
32
|
+
* Ctrl+D. Copies the TOP row of the selection into every row below it.
|
|
33
|
+
*
|
|
34
|
+
* Excel has a second behaviour here: with only one cell selected it fills from
|
|
35
|
+
* the cell directly above instead, which is what makes Ctrl+D useful while
|
|
36
|
+
* typing down a column. Both are implemented.
|
|
37
|
+
*/
|
|
38
|
+
export declare function fillDown(cmd: GridCommandContext): boolean;
|
|
39
|
+
/** Ctrl+R. The same shape as fillDown, across instead of down. */
|
|
40
|
+
export declare function fillRight(cmd: GridCommandContext): boolean;
|
|
41
|
+
/** Write one value into every cell of the selection. Excel's Ctrl+Enter. */
|
|
42
|
+
export declare function fillSelection(cmd: GridCommandContext, value: unknown): boolean;
|
|
43
|
+
/** Ctrl+; and Ctrl+Shift+;. ISO rather than locale-formatted, because the
|
|
44
|
+
* value goes into the data and a column's own `format` decides how it reads;
|
|
45
|
+
* stamping a localised string would put display text in the model. */
|
|
46
|
+
export declare function stampNow(kind: 'date' | 'time' | 'datetime', now?: Date): string;
|
|
47
|
+
export declare function stampDate(cmd: GridCommandContext, kind: 'date' | 'time' | 'datetime', now?: Date): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Ctrl+'. Copies the cell above VERBATIM - no reference translation, which is
|
|
50
|
+
* the whole point of the shortcut: it is how you get a copy of the formula
|
|
51
|
+
* above to edit, rather than one that has already shifted.
|
|
52
|
+
*/
|
|
53
|
+
export declare function copyFromAbove(cmd: GridCommandContext): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Ctrl+Shift+". The VALUE of the cell above: what a formula there shows,
|
|
56
|
+
* not the formula, so a running total can be frozen as a number. With an
|
|
57
|
+
* engine attached the evaluated value is what goes in; without one there is
|
|
58
|
+
* nothing but the text, which is what Ctrl+' copies. An error above copies
|
|
59
|
+
* nothing.
|
|
60
|
+
*/
|
|
61
|
+
export declare function copyValueFromAbove(cmd: GridCommandContext): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Alt+=. The range Excel guesses for a SUM anchored at the active cell: the
|
|
64
|
+
* run of numbers directly above, or directly to the left when there is nothing
|
|
65
|
+
* above. Returns null when neither direction has numbers to add.
|
|
66
|
+
*/
|
|
67
|
+
export declare function guessSumRange(cmd: GridCommandContext, isNumeric?: (value: unknown) => boolean): Rect | null;
|
|
68
|
+
/**
|
|
69
|
+
* How to find out what a cell actually EVALUATES to.
|
|
70
|
+
*
|
|
71
|
+
* Cells hold raw text, so a cell containing `=SUM(A1:A3)` reads as the string
|
|
72
|
+
* "=SUM(A1:A3)" and `looksNumeric` says no. AutoSum under a column of
|
|
73
|
+
* subtotals then finds no run and declines, which is the opposite of what
|
|
74
|
+
* Excel does: there, a formula that produces a number IS a number.
|
|
75
|
+
*
|
|
76
|
+
* Optional. Without one, a sheet with no engine behind it behaves as before
|
|
77
|
+
* and only literal numbers count.
|
|
78
|
+
*/
|
|
79
|
+
export type SheetValueProbe = (row: number, col: number) => unknown;
|
|
80
|
+
export declare function setSheetValueProbe(fn: SheetValueProbe | null): void;
|
|
81
|
+
export declare function getSheetValueProbe(): SheetValueProbe | null;
|
|
82
|
+
/**
|
|
83
|
+
* The numeric test AutoSum should use for the cell at (row, col): the
|
|
84
|
+
* evaluated value when an engine is attached, the raw text otherwise.
|
|
85
|
+
*/
|
|
86
|
+
export declare function numericAt(cmd: GridCommandContext, row: number, col: number): boolean;
|
|
87
|
+
/** Default numeric test for AutoSum: a finite number, or a string that parses
|
|
88
|
+
* as one. A blank is not a number, so a gap ends the run. */
|
|
89
|
+
export declare function looksNumeric(value: unknown): boolean;
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { isBlankValue } from './navigate.js';
|
|
2
|
+
const identity = (value) => value;
|
|
3
|
+
let translator = identity;
|
|
4
|
+
/** Install the formula-aware translator. The engine calls this in phase 2. */
|
|
5
|
+
export function setFillTranslator(fn) {
|
|
6
|
+
translator = fn ?? identity;
|
|
7
|
+
}
|
|
8
|
+
/** The rectangle a command should act on: the active range, or the active cell
|
|
9
|
+
* alone when nothing is selected. Returns null when there is no active cell. */
|
|
10
|
+
/**
|
|
11
|
+
* Whether a command may write a cell. `setCellValue` trusts its caller, so
|
|
12
|
+
* a fill over a protected sheet has to ask for itself and leave the locked
|
|
13
|
+
* cells as they are, the way the grid's own fill handle does.
|
|
14
|
+
*/
|
|
15
|
+
function writable(cmd, r, c) {
|
|
16
|
+
return cmd.canEdit?.(r, c) !== false;
|
|
17
|
+
}
|
|
18
|
+
export function targetRect(cmd) {
|
|
19
|
+
const last = cmd.ranges[cmd.ranges.length - 1];
|
|
20
|
+
if (last)
|
|
21
|
+
return last;
|
|
22
|
+
const active = cmd.activeCell;
|
|
23
|
+
if (!active)
|
|
24
|
+
return null;
|
|
25
|
+
return [active.rowIndex, active.colIndex, active.rowIndex, active.colIndex];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Ctrl+D. Copies the TOP row of the selection into every row below it.
|
|
29
|
+
*
|
|
30
|
+
* Excel has a second behaviour here: with only one cell selected it fills from
|
|
31
|
+
* the cell directly above instead, which is what makes Ctrl+D useful while
|
|
32
|
+
* typing down a column. Both are implemented.
|
|
33
|
+
*/
|
|
34
|
+
export function fillDown(cmd) {
|
|
35
|
+
const rect = targetRect(cmd);
|
|
36
|
+
if (!rect)
|
|
37
|
+
return false;
|
|
38
|
+
const [minRow, minCol, maxRow, maxCol] = rect;
|
|
39
|
+
if (minRow === maxRow) {
|
|
40
|
+
// Single row selected: pull from the row above.
|
|
41
|
+
if (minRow === 0)
|
|
42
|
+
return false;
|
|
43
|
+
return cmd.batch(() => {
|
|
44
|
+
for (let c = minCol; c <= maxCol; c += 1) {
|
|
45
|
+
if (!writable(cmd, minRow, c))
|
|
46
|
+
continue;
|
|
47
|
+
const value = cmd.getCellValue(minRow - 1, c);
|
|
48
|
+
cmd.setCellValue(minRow, c, translator(value, { rows: 1, cols: 0 }));
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return cmd.batch(() => {
|
|
54
|
+
for (let c = minCol; c <= maxCol; c += 1) {
|
|
55
|
+
const source = cmd.getCellValue(minRow, c);
|
|
56
|
+
for (let r = minRow + 1; r <= maxRow; r += 1) {
|
|
57
|
+
if (!writable(cmd, r, c))
|
|
58
|
+
continue;
|
|
59
|
+
cmd.setCellValue(r, c, translator(source, { rows: r - minRow, cols: 0 }));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/** Ctrl+R. The same shape as fillDown, across instead of down. */
|
|
66
|
+
export function fillRight(cmd) {
|
|
67
|
+
const rect = targetRect(cmd);
|
|
68
|
+
if (!rect)
|
|
69
|
+
return false;
|
|
70
|
+
const [minRow, minCol, maxRow, maxCol] = rect;
|
|
71
|
+
if (minCol === maxCol) {
|
|
72
|
+
if (minCol === 0)
|
|
73
|
+
return false;
|
|
74
|
+
return cmd.batch(() => {
|
|
75
|
+
for (let r = minRow; r <= maxRow; r += 1) {
|
|
76
|
+
if (!writable(cmd, r, minCol))
|
|
77
|
+
continue;
|
|
78
|
+
const value = cmd.getCellValue(r, minCol - 1);
|
|
79
|
+
cmd.setCellValue(r, minCol, translator(value, { rows: 0, cols: 1 }));
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return cmd.batch(() => {
|
|
85
|
+
for (let r = minRow; r <= maxRow; r += 1) {
|
|
86
|
+
const source = cmd.getCellValue(r, minCol);
|
|
87
|
+
for (let c = minCol + 1; c <= maxCol; c += 1) {
|
|
88
|
+
if (!writable(cmd, r, c))
|
|
89
|
+
continue;
|
|
90
|
+
cmd.setCellValue(r, c, translator(source, { rows: 0, cols: c - minCol }));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** Write one value into every cell of the selection. Excel's Ctrl+Enter. */
|
|
97
|
+
export function fillSelection(cmd, value) {
|
|
98
|
+
const rect = targetRect(cmd);
|
|
99
|
+
if (!rect)
|
|
100
|
+
return false;
|
|
101
|
+
const [minRow, minCol, maxRow, maxCol] = rect;
|
|
102
|
+
return cmd.batch(() => {
|
|
103
|
+
for (let r = minRow; r <= maxRow; r += 1) {
|
|
104
|
+
for (let c = minCol; c <= maxCol; c += 1) {
|
|
105
|
+
if (writable(cmd, r, c))
|
|
106
|
+
cmd.setCellValue(r, c, value);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/** Ctrl+; and Ctrl+Shift+;. ISO rather than locale-formatted, because the
|
|
113
|
+
* value goes into the data and a column's own `format` decides how it reads;
|
|
114
|
+
* stamping a localised string would put display text in the model. */
|
|
115
|
+
export function stampNow(kind, now = new Date()) {
|
|
116
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
117
|
+
const date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
118
|
+
const time = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
|
119
|
+
if (kind === 'date')
|
|
120
|
+
return date;
|
|
121
|
+
if (kind === 'time')
|
|
122
|
+
return time;
|
|
123
|
+
return `${date} ${time}`;
|
|
124
|
+
}
|
|
125
|
+
export function stampDate(cmd, kind, now) {
|
|
126
|
+
return fillSelection(cmd, stampNow(kind, now));
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Ctrl+'. Copies the cell above VERBATIM - no reference translation, which is
|
|
130
|
+
* the whole point of the shortcut: it is how you get a copy of the formula
|
|
131
|
+
* above to edit, rather than one that has already shifted.
|
|
132
|
+
*/
|
|
133
|
+
export function copyFromAbove(cmd) {
|
|
134
|
+
const active = cmd.activeCell;
|
|
135
|
+
if (!active || active.rowIndex === 0)
|
|
136
|
+
return false;
|
|
137
|
+
if (!writable(cmd, active.rowIndex, active.colIndex))
|
|
138
|
+
return false;
|
|
139
|
+
const value = cmd.getCellValue(active.rowIndex - 1, active.colIndex);
|
|
140
|
+
cmd.setCellValue(active.rowIndex, active.colIndex, value);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Ctrl+Shift+". The VALUE of the cell above: what a formula there shows,
|
|
145
|
+
* not the formula, so a running total can be frozen as a number. With an
|
|
146
|
+
* engine attached the evaluated value is what goes in; without one there is
|
|
147
|
+
* nothing but the text, which is what Ctrl+' copies. An error above copies
|
|
148
|
+
* nothing.
|
|
149
|
+
*/
|
|
150
|
+
export function copyValueFromAbove(cmd) {
|
|
151
|
+
const active = cmd.activeCell;
|
|
152
|
+
if (!active || active.rowIndex === 0)
|
|
153
|
+
return false;
|
|
154
|
+
if (!writable(cmd, active.rowIndex, active.colIndex))
|
|
155
|
+
return false;
|
|
156
|
+
const probe = valueProbe;
|
|
157
|
+
const raw = cmd.getCellValue(active.rowIndex - 1, active.colIndex);
|
|
158
|
+
let value = raw;
|
|
159
|
+
if (probe) {
|
|
160
|
+
const shown = probe(active.rowIndex - 1, active.colIndex);
|
|
161
|
+
if (shown !== null && typeof shown === 'object')
|
|
162
|
+
return false;
|
|
163
|
+
if (shown !== undefined && shown !== null)
|
|
164
|
+
value = typeof shown === 'boolean' ? (shown ? 'TRUE' : 'FALSE') : String(shown);
|
|
165
|
+
}
|
|
166
|
+
cmd.setCellValue(active.rowIndex, active.colIndex, value);
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Alt+=. The range Excel guesses for a SUM anchored at the active cell: the
|
|
171
|
+
* run of numbers directly above, or directly to the left when there is nothing
|
|
172
|
+
* above. Returns null when neither direction has numbers to add.
|
|
173
|
+
*/
|
|
174
|
+
export function guessSumRange(cmd, isNumeric = looksNumeric) {
|
|
175
|
+
const active = cmd.activeCell;
|
|
176
|
+
if (!active)
|
|
177
|
+
return null;
|
|
178
|
+
const { rowIndex: row, colIndex: col } = active;
|
|
179
|
+
// When an engine is attached the run is measured against evaluated values,
|
|
180
|
+
// so a column of SUM subtotals counts as numbers the way it does in Excel.
|
|
181
|
+
const numeric = valueProbe
|
|
182
|
+
? (r, c) => numericAt(cmd, r, c)
|
|
183
|
+
: (r, c) => isNumeric(cmd.getCellValue(r, c));
|
|
184
|
+
let top = row;
|
|
185
|
+
while (top > 0 && numeric(top - 1, col))
|
|
186
|
+
top -= 1;
|
|
187
|
+
if (top < row)
|
|
188
|
+
return [top, col, row - 1, col];
|
|
189
|
+
let left = col;
|
|
190
|
+
while (left > 0 && numeric(row, left - 1))
|
|
191
|
+
left -= 1;
|
|
192
|
+
if (left < col)
|
|
193
|
+
return [row, left, row, col - 1];
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
let valueProbe = null;
|
|
197
|
+
export function setSheetValueProbe(fn) {
|
|
198
|
+
valueProbe = fn;
|
|
199
|
+
}
|
|
200
|
+
export function getSheetValueProbe() {
|
|
201
|
+
return valueProbe;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The numeric test AutoSum should use for the cell at (row, col): the
|
|
205
|
+
* evaluated value when an engine is attached, the raw text otherwise.
|
|
206
|
+
*/
|
|
207
|
+
export function numericAt(cmd, row, col) {
|
|
208
|
+
const probe = valueProbe;
|
|
209
|
+
if (!probe)
|
|
210
|
+
return looksNumeric(cmd.getCellValue(row, col));
|
|
211
|
+
const value = probe(row, col);
|
|
212
|
+
// An engine reports an error as an object; that is not a number, and it
|
|
213
|
+
// should end the run rather than be counted as one.
|
|
214
|
+
if (value !== null && typeof value === 'object')
|
|
215
|
+
return false;
|
|
216
|
+
return looksNumeric(value);
|
|
217
|
+
}
|
|
218
|
+
/** Default numeric test for AutoSum: a finite number, or a string that parses
|
|
219
|
+
* as one. A blank is not a number, so a gap ends the run. */
|
|
220
|
+
export function looksNumeric(value) {
|
|
221
|
+
if (isBlankValue(value))
|
|
222
|
+
return false;
|
|
223
|
+
if (typeof value === 'number')
|
|
224
|
+
return Number.isFinite(value);
|
|
225
|
+
if (typeof value === 'string') {
|
|
226
|
+
const n = Number(value.trim());
|
|
227
|
+
return value.trim() !== '' && Number.isFinite(n);
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NotesMap } from './rects.js';
|
|
2
|
+
export type { NotesMap } from './rects.js';
|
|
3
|
+
/** The comment on (r, c), or undefined when there is none. */
|
|
4
|
+
export declare function commentAt(notes: NotesMap, r: number, c: number): string | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* The map with (r, c) set to `text`, or cleared when the text is blank.
|
|
7
|
+
* A new map, never the old one changed: the grid re-reads `notes` only
|
|
8
|
+
* when the object it is handed is a different one.
|
|
9
|
+
*/
|
|
10
|
+
export declare function withComment(notes: NotesMap, r: number, c: number, text: string): NotesMap;
|
|
11
|
+
/** Every comment, top to bottom then left to right. */
|
|
12
|
+
export declare function listComments(notes: NotesMap): Array<{
|
|
13
|
+
row: number;
|
|
14
|
+
col: number;
|
|
15
|
+
text: string;
|
|
16
|
+
}>;
|
|
17
|
+
/**
|
|
18
|
+
* The comment after (or before) `from`, reading the sheet row by row and
|
|
19
|
+
* wrapping at the end, as Excel's Next Comment and Previous Comment do. The
|
|
20
|
+
* cell itself is skipped, so pressing Next on a commented cell moves on;
|
|
21
|
+
* null when the sheet has no comments at all.
|
|
22
|
+
*/
|
|
23
|
+
export declare function nextComment(notes: NotesMap, from: {
|
|
24
|
+
row: number;
|
|
25
|
+
col: number;
|
|
26
|
+
}, dir: 1 | -1): {
|
|
27
|
+
row: number;
|
|
28
|
+
col: number;
|
|
29
|
+
} | null;
|