@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,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goal Seek: find the input value that makes a formula cell hit a target.
|
|
3
|
+
*
|
|
4
|
+
* "What interest rate makes the monthly payment 1500?" You know the answer
|
|
5
|
+
* you want and one cell you are willing to change; the solver finds it.
|
|
6
|
+
*
|
|
7
|
+
* The method is secant with a bisection fallback, not Newton. Newton needs a
|
|
8
|
+
* derivative, and the function here is "recalculate a spreadsheet", which has
|
|
9
|
+
* no analytic one. Secant approximates the slope from two evaluations, which
|
|
10
|
+
* is the same information a numerical derivative would cost anyway.
|
|
11
|
+
*
|
|
12
|
+
* Bisection is the fallback because secant is fast but not safe: it can step
|
|
13
|
+
* to infinity on a flat stretch or oscillate on a kink. When a bracket is
|
|
14
|
+
* known - two inputs whose results straddle the target - bisection cannot
|
|
15
|
+
* fail, only be slow. Trying secant first and falling back keeps the common
|
|
16
|
+
* case quick and the awkward case terminating.
|
|
17
|
+
*/
|
|
18
|
+
const DEFAULTS = {
|
|
19
|
+
tolerance: 1e-7,
|
|
20
|
+
maxIterations: 100,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Solve `evaluate(input) = target` for `input`.
|
|
24
|
+
*
|
|
25
|
+
* `evaluate` sets the input cell, recalculates, and returns the formula
|
|
26
|
+
* cell's value. It is called many times, so it should be the workbook's own
|
|
27
|
+
* recalculation rather than anything that touches the DOM.
|
|
28
|
+
*
|
|
29
|
+
* The caller owns the input cell: this never writes. It reports the value it
|
|
30
|
+
* found and lets the caller decide whether to keep it, which is what makes
|
|
31
|
+
* Excel's "Goal Seek found a solution / OK or Cancel" dialog possible.
|
|
32
|
+
*/
|
|
33
|
+
export function goalSeek(evaluate, target, start, options = {}) {
|
|
34
|
+
const tolerance = options.tolerance ?? DEFAULTS.tolerance;
|
|
35
|
+
const maxIterations = options.maxIterations ?? DEFAULTS.maxIterations;
|
|
36
|
+
const min = options.min ?? Number.NEGATIVE_INFINITY;
|
|
37
|
+
const max = options.max ?? Number.POSITIVE_INFINITY;
|
|
38
|
+
let iterations = 0;
|
|
39
|
+
const clamp = (x) => Math.min(Math.max(x, min), max);
|
|
40
|
+
/** The signed distance from the target. Zero is the answer. */
|
|
41
|
+
const f = (x) => {
|
|
42
|
+
iterations += 1;
|
|
43
|
+
const raw = evaluate(x);
|
|
44
|
+
const n = typeof raw === 'number' ? raw : Number(raw);
|
|
45
|
+
return Number.isFinite(n) ? n - target : null;
|
|
46
|
+
};
|
|
47
|
+
let x0 = clamp(options.initialGuess ?? start);
|
|
48
|
+
let f0 = f(x0);
|
|
49
|
+
if (f0 === null) {
|
|
50
|
+
return { converged: false, value: x0, result: NaN, iterations, reason: 'notNumeric' };
|
|
51
|
+
}
|
|
52
|
+
if (Math.abs(f0) <= tolerance) {
|
|
53
|
+
return { converged: true, value: x0, result: f0 + target, iterations };
|
|
54
|
+
}
|
|
55
|
+
// A second point, offset enough to see a slope. Scaling with the guess
|
|
56
|
+
// matters: a fixed step of 1 is enormous next to an interest rate of 0.05
|
|
57
|
+
// and invisible next to a loan of 300000.
|
|
58
|
+
let x1 = clamp(x0 !== 0 ? x0 * 1.1 : 1);
|
|
59
|
+
if (x1 === x0)
|
|
60
|
+
x1 = clamp(x0 + 1);
|
|
61
|
+
let f1 = f(x1);
|
|
62
|
+
if (f1 === null) {
|
|
63
|
+
return { converged: false, value: x0, result: f0 + target, iterations, reason: 'notNumeric' };
|
|
64
|
+
}
|
|
65
|
+
/** Best seen so far, so a failure still reports the closest attempt. */
|
|
66
|
+
let best = Math.abs(f0) <= Math.abs(f1) ? { x: x0, fx: f0 } : { x: x1, fx: f1 };
|
|
67
|
+
const bracket = { lo: null, hi: null };
|
|
68
|
+
const noteBracket = (a, b) => {
|
|
69
|
+
if (a.fx === 0 || b.fx === 0)
|
|
70
|
+
return;
|
|
71
|
+
if ((a.fx < 0) !== (b.fx < 0)) {
|
|
72
|
+
bracket.lo = a.fx < 0 ? a : b;
|
|
73
|
+
bracket.hi = a.fx < 0 ? b : a;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
noteBracket({ x: x0, fx: f0 }, { x: x1, fx: f1 });
|
|
77
|
+
while (iterations < maxIterations) {
|
|
78
|
+
if (Math.abs(f1) <= tolerance) {
|
|
79
|
+
return { converged: true, value: x1, result: f1 + target, iterations };
|
|
80
|
+
}
|
|
81
|
+
let next;
|
|
82
|
+
const slope = f1 - f0;
|
|
83
|
+
if (slope === 0) {
|
|
84
|
+
// Flat between the two points. Secant divides by this, so bisect if a
|
|
85
|
+
// bracket exists and give up if not - a genuinely flat function has no
|
|
86
|
+
// solution to find.
|
|
87
|
+
const { lo, hi } = bracket;
|
|
88
|
+
if (!lo || !hi) {
|
|
89
|
+
return { converged: false, value: best.x, result: best.fx + target, iterations, reason: 'flat' };
|
|
90
|
+
}
|
|
91
|
+
next = (lo.x + hi.x) / 2;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
next = x1 - f1 * ((x1 - x0) / slope);
|
|
95
|
+
// Secant can step anywhere, including outside a bracket we already
|
|
96
|
+
// trust. Bisect instead when it does.
|
|
97
|
+
const { lo, hi } = bracket;
|
|
98
|
+
const outside = !Number.isFinite(next) ||
|
|
99
|
+
(lo !== null && hi !== null && (next < Math.min(lo.x, hi.x) || next > Math.max(lo.x, hi.x)));
|
|
100
|
+
if (outside)
|
|
101
|
+
next = lo && hi ? (lo.x + hi.x) / 2 : clamp(next);
|
|
102
|
+
}
|
|
103
|
+
next = clamp(next);
|
|
104
|
+
if (next === x1) {
|
|
105
|
+
// Clamped against a bound and cannot move.
|
|
106
|
+
return {
|
|
107
|
+
converged: false, value: best.x, result: best.fx + target, iterations,
|
|
108
|
+
reason: Number.isFinite(min) || Number.isFinite(max) ? 'outOfBounds' : 'flat',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const fNext = f(next);
|
|
112
|
+
if (fNext === null) {
|
|
113
|
+
return { converged: false, value: best.x, result: best.fx + target, iterations, reason: 'notNumeric' };
|
|
114
|
+
}
|
|
115
|
+
if (Math.abs(fNext) < Math.abs(best.fx))
|
|
116
|
+
best = { x: next, fx: fNext };
|
|
117
|
+
noteBracket({ x: x1, fx: f1 }, { x: next, fx: fNext });
|
|
118
|
+
x0 = x1;
|
|
119
|
+
f0 = f1;
|
|
120
|
+
x1 = next;
|
|
121
|
+
f1 = fNext;
|
|
122
|
+
}
|
|
123
|
+
if (Math.abs(f1) <= tolerance) {
|
|
124
|
+
return { converged: true, value: x1, result: f1 + target, iterations };
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
converged: false, value: best.x, result: best.fx + target,
|
|
128
|
+
iterations, reason: 'maxIterations',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Goal Seek over a workbook: change `input` until `formula` reads `target`.
|
|
133
|
+
*
|
|
134
|
+
* The input cell is RESTORED before returning, whatever the outcome. The
|
|
135
|
+
* solver writes to it dozens of times while searching, and leaving the last
|
|
136
|
+
* probe behind would be worse than not running: Excel shows you the answer
|
|
137
|
+
* and asks before keeping it, which it cannot do if the sheet has already
|
|
138
|
+
* moved. Apply `result.value` yourself once the user says yes.
|
|
139
|
+
*/
|
|
140
|
+
export function goalSeekCell(book, formula, input, target, options = {}) {
|
|
141
|
+
const original = book.getRaw(input.sheet, input.row, input.col);
|
|
142
|
+
const startText = original.trim();
|
|
143
|
+
const start = Number(startText);
|
|
144
|
+
try {
|
|
145
|
+
return goalSeek((x) => {
|
|
146
|
+
book.setRaw(input.sheet, input.row, input.col, String(x));
|
|
147
|
+
return book.getValue(formula.sheet, formula.row, formula.col);
|
|
148
|
+
}, target, Number.isFinite(start) ? start : 0, options);
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
book.setRaw(input.sheet, input.row, input.col, original);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@svgrid/enterprise/sheet` - the Excel keyboard layer on its own subpath.
|
|
3
|
+
*
|
|
4
|
+
* Importing the package barrel pulls every module it reaches into the chunk
|
|
5
|
+
* (the package sets no `sideEffects` flag), which for an app that only wants
|
|
6
|
+
* the shortcuts would mean shipping export, pivot, the scheduler and the board
|
|
7
|
+
* as well. This subpath is the shortcuts and nothing else. It matters more once
|
|
8
|
+
* the formula engine lands beside them in phase 2.
|
|
9
|
+
*/
|
|
10
|
+
export { enableSheet } from '../sheet-enable.js';
|
|
11
|
+
export { createTableRegistry, isValidTableName, resolveTableRange, columnIndexOf, rowCountOf, type TableRegion, type TableRegistry, type TableRange, type TableSpecifier, } from './tables.js';
|
|
12
|
+
export { goalSeek, goalSeekCell, type GoalSeekOptions, type GoalSeekResult, type GoalSeekSheet, type CellAddress as GoalSeekCellAddress, } from './goal-seek.js';
|
|
13
|
+
export { default as SvSheetTabs } from '../SvSheetTabs.svelte';
|
|
14
|
+
export { createWorkbook, isValidSheetName, type Workbook, type SheetData, type WorkbookOptions, } from './workbook.js';
|
|
15
|
+
export { setWorkbook, getWorkbook } from './shortcuts.js';
|
|
16
|
+
export { createSheetDocument, type SheetDocument, type SheetDocumentInit, type SheetState, type SheetStateEntry, type PerSheetState, type SheetChangeReason, } from './document.js';
|
|
17
|
+
export { shiftRect, shiftRects, subtractRect, rectContains, rectsIntersect, remapNotes, lineShift, type NotesMap } from './rects.js';
|
|
18
|
+
export { isLocked, rectsHaveLocked, rectsMixLocked, PROTECTED_MESSAGE } from './protection.js';
|
|
19
|
+
export { commentAt, withComment, listComments, nextComment } from './comments.js';
|
|
20
|
+
export { ruleAt, rulesIn, checkEntry, listChoices, shiftValidation, removeValidation, describeRule, dateValue, validationId, DEFAULT_ALERT_MESSAGE, OPERATOR_LABELS, type ValidationRule, type ValidationAllow, type ValidationOperator, type ValidationContext, type ValidationVerdict, type ValidationSpec, } from './validation.js';
|
|
21
|
+
export { ruleStats, evaluateCf, shiftCf, removeCf, cfIn, describeCf, scaleColor, iconIndex, hasStyle, cfId, CF_PRESET_STYLES, COLOR_SCALES, DATA_BAR_COLOR, type CfRule, type CfRuleBody, type CfStyledRule, type CfBody, type CfPreset, type CfStyle, type CfStats, type CfResult, type CfContext, type CfOperator, type CfTextMatch, type CfIconSet, type CfScaleColors, type CfKind, } from './conditional-formats.js';
|
|
22
|
+
export { mergePlan, unmergePlan, mergeDropsValues, mergesIn, mergeAt as sheetMergeAt, isCoveredCell, selectionMerged, toGridMerges, sortBlockedByMerges, reorderMerges, normalRect, type MergeKind, type MergePlan, } from './merges.js';
|
|
23
|
+
export { distinctValues, hiddenRowsFor, passesFilter, isFiltering, withColumnFilter, valuesFilter, shiftAutoFilter, describeFilter, type AutoFilterState, type ColumnFilter, type FilterCondition, type FilterValue, } from './auto-filter.js';
|
|
24
|
+
export { splitText, textToColumns, guessDelimiter, findDuplicates, removeDuplicates, type SplitOptions, type DuplicateOptions, type DuplicateReport, } from './transforms.js';
|
|
25
|
+
export { insertRows, deleteRows, insertColumns, deleteColumns, axisForSelection, setStructureTarget, getStructureTarget, rewriteFormulas, type StructureTarget, } from './structure.js';
|
|
26
|
+
export { findAll, findNext, replaceOne, replaceAll, replaceInText, cellMatches, setFindTarget, getFindTarget, type FindOptions, type FindHit, type FindTarget, } from './find-replace.js';
|
|
27
|
+
export { splitFrozenRows, frozenColumnIds, applyFreeze, freezeAtActiveCell, freezeTopRow, freezeFirstColumn, unfreeze, type FreezeState, type FreezeSplit, } from './freeze.js';
|
|
28
|
+
export { buildClipboardPayload, parseClipboard, parseClipboardText, parseClipboardHtml, readClipboardOrigin, anchorForeignFormulas, resolvePasteCell, planPaste, msoNumberFormat, numFmtFromMso, isR1C1, r1c1ToA1, type PasteSpecialOptions, type PasteWhat, type PasteOperation, type ClipboardCell, type ClipboardGrid, type PasteResolution, } from './paste-special.js';
|
|
29
|
+
export { setFindReplaceHandler, setPasteSpecialHandler } from './shortcuts.js';
|
|
30
|
+
export { default as SvFormulaBar } from '../SvFormulaBar.svelte';
|
|
31
|
+
export { default as SvSheet } from '../SvSheet.svelte';
|
|
32
|
+
export { default as SvSheetRibbon } from '../SvSheetRibbon.svelte';
|
|
33
|
+
export { RIBBON_TABS, ribbonItems, withDecimals, applyBorders, type RibbonTab, type RibbonGroup, type RibbonItem, type RibbonOption, type RibbonItemKind, type RibbonActionId, type BorderPreset, } from './ribbon.js';
|
|
34
|
+
export { RIBBON_ICONS, RIBBON_ICON_NAMES, type RibbonIconName, type IconPath } from './ribbon-icons.js';
|
|
35
|
+
export { THEME_COLOURS, STANDARD_COLOURS, ALL_COLOURS, tint, type PaletteColour } from './palette.js';
|
|
36
|
+
export { default as SvRibbonIcon } from '../SvRibbonIcon.svelte';
|
|
37
|
+
export { move, selectRegion, selectLine, applyFormat, toggleFormat, preset, autoSum, structural, switchSheet, gridOf, } from './shortcuts.js';
|
|
38
|
+
export { compileNumberFormat, formatWithPattern, FORMAT_PRESETS, type CompiledFormat, type FormatPresetName, } from './number-format.js';
|
|
39
|
+
export { createFormatStore, entryToStyle, type SheetFormatStore, type CellFormatEntry, type CellAddressLookup, } from './format-store.js';
|
|
40
|
+
export { createNames, isValidName, type SheetNames, type DefinedName, } from './names.js';
|
|
41
|
+
export { suggestFunctions, applySuggestion, signatureAt, partialAt, SIGNATURES, type FunctionSuggestion, } from './autocomplete.js';
|
|
42
|
+
export { setFormatTarget, getFormatTarget, setFormatDialogHandler, type SheetFormatTarget, } from './shortcuts.js';
|
|
43
|
+
export { parseFormula, parse, } from './parse.js';
|
|
44
|
+
export { tokenize, type Token } from './tokenize.js';
|
|
45
|
+
export { evaluate, formatValue, type EvalContext } from './evaluate.js';
|
|
46
|
+
export { FUNCTIONS, withCustomFunctions, type SheetFunction, type FnArgs, } from './functions.js';
|
|
47
|
+
export { translateFormula, fixupReferences, renameSheetReferences, formatFormula, referenceSpans, REFERENCE_COLOURS, type StructuralEdit, type EditScope, type ReferenceSpan, } from './refs.js';
|
|
48
|
+
export { createDependencyGraph, precedentsOf, cellKey, parseCellKey, type DependencyGraph, type CellKey, } from './deps.js';
|
|
49
|
+
export { parseA1, formatA1, colToLetters, lettersToCol, type CellRef, } from './address.js';
|
|
50
|
+
export { isError, type CellValue, type SheetError, type Node as FormulaNode, } from './ast.js';
|
|
51
|
+
export { SHEET_BINDINGS, handleSheetKey, type SheetBinding, type SheetCommand, } from './shortcuts.js';
|
|
52
|
+
export { edgeOfRegion, currentRegion, isWholeSheet, wholeSheet, isBlankValue, type Direction, type Grid, type Cell, type Rect, } from './navigate.js';
|
|
53
|
+
export { fillDown, fillRight, fillSelection, stampDate, stampNow, copyFromAbove, copyValueFromAbove, guessSumRange, looksNumeric, numericAt, targetRect, setFillTranslator, setSheetValueProbe, getSheetValueProbe, type FillTranslator, type SheetValueProbe, } from './commands.js';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@svgrid/enterprise/sheet` - the Excel keyboard layer on its own subpath.
|
|
3
|
+
*
|
|
4
|
+
* Importing the package barrel pulls every module it reaches into the chunk
|
|
5
|
+
* (the package sets no `sideEffects` flag), which for an app that only wants
|
|
6
|
+
* the shortcuts would mean shipping export, pivot, the scheduler and the board
|
|
7
|
+
* as well. This subpath is the shortcuts and nothing else. It matters more once
|
|
8
|
+
* the formula engine lands beside them in phase 2.
|
|
9
|
+
*/
|
|
10
|
+
export { enableSheet } from '../sheet-enable.js';
|
|
11
|
+
export { createTableRegistry, isValidTableName, resolveTableRange, columnIndexOf, rowCountOf, } from './tables.js';
|
|
12
|
+
export { goalSeek, goalSeekCell, } from './goal-seek.js';
|
|
13
|
+
export { default as SvSheetTabs } from '../SvSheetTabs.svelte';
|
|
14
|
+
export { createWorkbook, isValidSheetName, } from './workbook.js';
|
|
15
|
+
export { setWorkbook, getWorkbook } from './shortcuts.js';
|
|
16
|
+
export { createSheetDocument, } from './document.js';
|
|
17
|
+
export { shiftRect, shiftRects, subtractRect, rectContains, rectsIntersect, remapNotes, lineShift } from './rects.js';
|
|
18
|
+
export { isLocked, rectsHaveLocked, rectsMixLocked, PROTECTED_MESSAGE } from './protection.js';
|
|
19
|
+
export { commentAt, withComment, listComments, nextComment } from './comments.js';
|
|
20
|
+
export { ruleAt, rulesIn, checkEntry, listChoices, shiftValidation, removeValidation, describeRule, dateValue, validationId, DEFAULT_ALERT_MESSAGE, OPERATOR_LABELS, } from './validation.js';
|
|
21
|
+
export { ruleStats, evaluateCf, shiftCf, removeCf, cfIn, describeCf, scaleColor, iconIndex, hasStyle, cfId, CF_PRESET_STYLES, COLOR_SCALES, DATA_BAR_COLOR, } from './conditional-formats.js';
|
|
22
|
+
export { mergePlan, unmergePlan, mergeDropsValues, mergesIn, mergeAt as sheetMergeAt, isCoveredCell, selectionMerged, toGridMerges, sortBlockedByMerges, reorderMerges, normalRect, } from './merges.js';
|
|
23
|
+
export { distinctValues, hiddenRowsFor, passesFilter, isFiltering, withColumnFilter, valuesFilter, shiftAutoFilter, describeFilter, } from './auto-filter.js';
|
|
24
|
+
export { splitText, textToColumns, guessDelimiter, findDuplicates, removeDuplicates, } from './transforms.js';
|
|
25
|
+
export { insertRows, deleteRows, insertColumns, deleteColumns, axisForSelection, setStructureTarget, getStructureTarget, rewriteFormulas, } from './structure.js';
|
|
26
|
+
export { findAll, findNext, replaceOne, replaceAll, replaceInText, cellMatches, setFindTarget, getFindTarget, } from './find-replace.js';
|
|
27
|
+
export { splitFrozenRows, frozenColumnIds, applyFreeze, freezeAtActiveCell, freezeTopRow, freezeFirstColumn, unfreeze, } from './freeze.js';
|
|
28
|
+
export { buildClipboardPayload, parseClipboard, parseClipboardText, parseClipboardHtml, readClipboardOrigin, anchorForeignFormulas, resolvePasteCell, planPaste, msoNumberFormat, numFmtFromMso, isR1C1, r1c1ToA1, } from './paste-special.js';
|
|
29
|
+
export { setFindReplaceHandler, setPasteSpecialHandler } from './shortcuts.js';
|
|
30
|
+
export { default as SvFormulaBar } from '../SvFormulaBar.svelte';
|
|
31
|
+
export { default as SvSheet } from '../SvSheet.svelte';
|
|
32
|
+
export { default as SvSheetRibbon } from '../SvSheetRibbon.svelte';
|
|
33
|
+
export { RIBBON_TABS, ribbonItems, withDecimals, applyBorders, } from './ribbon.js';
|
|
34
|
+
export { RIBBON_ICONS, RIBBON_ICON_NAMES } from './ribbon-icons.js';
|
|
35
|
+
export { THEME_COLOURS, STANDARD_COLOURS, ALL_COLOURS, tint } from './palette.js';
|
|
36
|
+
export { default as SvRibbonIcon } from '../SvRibbonIcon.svelte';
|
|
37
|
+
export { move, selectRegion, selectLine, applyFormat, toggleFormat, preset, autoSum, structural, switchSheet, gridOf, } from './shortcuts.js';
|
|
38
|
+
export { compileNumberFormat, formatWithPattern, FORMAT_PRESETS, } from './number-format.js';
|
|
39
|
+
export { createFormatStore, entryToStyle, } from './format-store.js';
|
|
40
|
+
export { createNames, isValidName, } from './names.js';
|
|
41
|
+
export { suggestFunctions, applySuggestion, signatureAt, partialAt, SIGNATURES, } from './autocomplete.js';
|
|
42
|
+
export { setFormatTarget, getFormatTarget, setFormatDialogHandler, } from './shortcuts.js';
|
|
43
|
+
export { parseFormula, parse, } from './parse.js';
|
|
44
|
+
export { tokenize } from './tokenize.js';
|
|
45
|
+
export { evaluate, formatValue } from './evaluate.js';
|
|
46
|
+
export { FUNCTIONS, withCustomFunctions, } from './functions.js';
|
|
47
|
+
export { translateFormula, fixupReferences, renameSheetReferences, formatFormula, referenceSpans, REFERENCE_COLOURS, } from './refs.js';
|
|
48
|
+
export { createDependencyGraph, precedentsOf, cellKey, parseCellKey, } from './deps.js';
|
|
49
|
+
export { parseA1, formatA1, colToLetters, lettersToCol, } from './address.js';
|
|
50
|
+
export { isError, } from './ast.js';
|
|
51
|
+
export { SHEET_BINDINGS, handleSheetKey, } from './shortcuts.js';
|
|
52
|
+
export { edgeOfRegion, currentRegion, isWholeSheet, wholeSheet, isBlankValue, } from './navigate.js';
|
|
53
|
+
export { fillDown, fillRight, fillSelection, stampDate, stampNow, copyFromAbove, copyValueFromAbove, guessSumRange, looksNumeric, numericAt, targetRect, setFillTranslator, setSheetValueProbe, getSheetValueProbe, } from './commands.js';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merged cells in the sheet: Excel's Merge & Center, Merge Across, Merge
|
|
3
|
+
* Cells and Unmerge Cells over the document's per-sheet `merges`, which
|
|
4
|
+
* are rectangles `[minRow, minCol, maxRow, maxCol]`. The grid draws them
|
|
5
|
+
* through its `mergedCells` prop; this module is the pure part: what a
|
|
6
|
+
* command does to the rectangles and to the cells under them.
|
|
7
|
+
*
|
|
8
|
+
* As in Excel, a merge keeps the top-left cell's value and drops the
|
|
9
|
+
* rest, so `mergePlan` says which cells to clear; the shell writes them
|
|
10
|
+
* through the command context so the merge and the clears are one undo.
|
|
11
|
+
*/
|
|
12
|
+
import { type Rect } from './rects.js';
|
|
13
|
+
export type MergeKind = 'center' | 'across' | 'cells';
|
|
14
|
+
export type MergePlan = {
|
|
15
|
+
/** The rectangles after the command. */
|
|
16
|
+
merges: Rect[];
|
|
17
|
+
/** Cells to clear, top-left cells of each new merge excluded. */
|
|
18
|
+
clear: Array<[row: number, col: number]>;
|
|
19
|
+
/** Whether Merge & Center also centres: the shell sets `align`. */
|
|
20
|
+
center: boolean;
|
|
21
|
+
/** The new merges' top-left cells, where the centre alignment goes. */
|
|
22
|
+
origins: Array<[row: number, col: number]>;
|
|
23
|
+
};
|
|
24
|
+
/** Normalise a rectangle to top-left / bottom-right. */
|
|
25
|
+
export declare function normalRect(rect: Rect): Rect;
|
|
26
|
+
/** The merges touching any of the rectangles. */
|
|
27
|
+
export declare function mergesIn(merges: ReadonlyArray<Rect>, rects: ReadonlyArray<Rect>): Rect[];
|
|
28
|
+
/** The merge covering (r, c), or undefined. */
|
|
29
|
+
export declare function mergeAt(merges: ReadonlyArray<Rect>, r: number, c: number): Rect | undefined;
|
|
30
|
+
/** Whether (r, c) is inside a merge without being its top-left cell. */
|
|
31
|
+
export declare function isCoveredCell(merges: ReadonlyArray<Rect>, r: number, c: number): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Merge the selection: one merge per rectangle (Merge & Center, Merge
|
|
34
|
+
* Cells) or one per row of each rectangle (Merge Across). Merges already
|
|
35
|
+
* inside the selection are replaced, as Excel replaces them. A single
|
|
36
|
+
* cell merges nothing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function mergePlan(merges: ReadonlyArray<Rect>, rects: ReadonlyArray<Rect>, kind: MergeKind, isBlank: (r: number, c: number) => boolean): MergePlan;
|
|
39
|
+
/**
|
|
40
|
+
* Whether merging the selection would drop a value: Excel warns that
|
|
41
|
+
* "merging cells only keeps the upper-left value". The shell asks before
|
|
42
|
+
* it merges.
|
|
43
|
+
*/
|
|
44
|
+
export declare function mergeDropsValues(rects: ReadonlyArray<Rect>, kind: MergeKind, isBlank: (r: number, c: number) => boolean): boolean;
|
|
45
|
+
/** Unmerge: every merge the selection touches goes. */
|
|
46
|
+
export declare function unmergePlan(merges: ReadonlyArray<Rect>, rects: ReadonlyArray<Rect>): Rect[];
|
|
47
|
+
/**
|
|
48
|
+
* A rectangle grown to hold every merge it touches, to a fixed point: the
|
|
49
|
+
* grid selects this way (a click on a merged cell takes the whole merge),
|
|
50
|
+
* so the header shading and anything else that reads the selection's
|
|
51
|
+
* columns and rows has to see the same rectangle.
|
|
52
|
+
*/
|
|
53
|
+
export declare function expandToMerges(merges: ReadonlyArray<Rect>, rect: Rect): Rect;
|
|
54
|
+
/** Whether the selection holds a merge, for the button's state. */
|
|
55
|
+
export declare function selectionMerged(merges: ReadonlyArray<Rect>, rects: ReadonlyArray<Rect>): boolean;
|
|
56
|
+
/** The merges as the grid takes them. */
|
|
57
|
+
export declare function toGridMerges(merges: ReadonlyArray<Rect>): Array<{
|
|
58
|
+
rowIndex: number;
|
|
59
|
+
colIndex: number;
|
|
60
|
+
rowSpan: number;
|
|
61
|
+
colSpan: number;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Whether a sort of `rect` can go ahead: Excel refuses when a merge
|
|
65
|
+
* crosses the range's edge ("all merged cells need to be the same size"),
|
|
66
|
+
* and the shell moves whole merges with their rows only when every merge
|
|
67
|
+
* in the range is one row tall and sits inside it.
|
|
68
|
+
*/
|
|
69
|
+
export declare function sortBlockedByMerges(merges: ReadonlyArray<Rect>, rect: Rect): boolean;
|
|
70
|
+
/** The merges of a sorted region, each moved with the row it sat on. */
|
|
71
|
+
export declare function reorderMerges(merges: ReadonlyArray<Rect>, rect: Rect, rowFor: (oldRow: number) => number): Rect[];
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merged cells in the sheet: Excel's Merge & Center, Merge Across, Merge
|
|
3
|
+
* Cells and Unmerge Cells over the document's per-sheet `merges`, which
|
|
4
|
+
* are rectangles `[minRow, minCol, maxRow, maxCol]`. The grid draws them
|
|
5
|
+
* through its `mergedCells` prop; this module is the pure part: what a
|
|
6
|
+
* command does to the rectangles and to the cells under them.
|
|
7
|
+
*
|
|
8
|
+
* As in Excel, a merge keeps the top-left cell's value and drops the
|
|
9
|
+
* rest, so `mergePlan` says which cells to clear; the shell writes them
|
|
10
|
+
* through the command context so the merge and the clears are one undo.
|
|
11
|
+
*/
|
|
12
|
+
import { rectContains, rectsIntersect } from './rects.js';
|
|
13
|
+
/** Normalise a rectangle to top-left / bottom-right. */
|
|
14
|
+
export function normalRect(rect) {
|
|
15
|
+
return [Math.min(rect[0], rect[2]), Math.min(rect[1], rect[3]), Math.max(rect[0], rect[2]), Math.max(rect[1], rect[3])];
|
|
16
|
+
}
|
|
17
|
+
/** The merges touching any of the rectangles. */
|
|
18
|
+
export function mergesIn(merges, rects) {
|
|
19
|
+
return merges.filter((m) => rects.some((r) => rectsIntersect(m, normalRect(r))));
|
|
20
|
+
}
|
|
21
|
+
/** The merge covering (r, c), or undefined. */
|
|
22
|
+
export function mergeAt(merges, r, c) {
|
|
23
|
+
return merges.find((m) => rectContains(m, r, c));
|
|
24
|
+
}
|
|
25
|
+
/** Whether (r, c) is inside a merge without being its top-left cell. */
|
|
26
|
+
export function isCoveredCell(merges, r, c) {
|
|
27
|
+
const m = mergeAt(merges, r, c);
|
|
28
|
+
return !!m && (m[0] !== r || m[1] !== c);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Merge the selection: one merge per rectangle (Merge & Center, Merge
|
|
32
|
+
* Cells) or one per row of each rectangle (Merge Across). Merges already
|
|
33
|
+
* inside the selection are replaced, as Excel replaces them. A single
|
|
34
|
+
* cell merges nothing.
|
|
35
|
+
*/
|
|
36
|
+
export function mergePlan(merges, rects, kind, isBlank) {
|
|
37
|
+
const targets = [];
|
|
38
|
+
for (const raw of rects) {
|
|
39
|
+
const rect = normalRect(raw);
|
|
40
|
+
if (kind === 'across') {
|
|
41
|
+
if (rect[1] === rect[3])
|
|
42
|
+
continue;
|
|
43
|
+
for (let r = rect[0]; r <= rect[2]; r += 1)
|
|
44
|
+
targets.push([r, rect[1], r, rect[3]]);
|
|
45
|
+
}
|
|
46
|
+
else if (rect[0] !== rect[2] || rect[1] !== rect[3]) {
|
|
47
|
+
targets.push(rect);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const kept = merges.filter((m) => !targets.some((t) => rectsIntersect(m, t)));
|
|
51
|
+
const clear = [];
|
|
52
|
+
const origins = [];
|
|
53
|
+
for (const t of targets) {
|
|
54
|
+
origins.push([t[0], t[1]]);
|
|
55
|
+
for (let r = t[0]; r <= t[2]; r += 1) {
|
|
56
|
+
for (let c = t[1]; c <= t[3]; c += 1) {
|
|
57
|
+
if (r === t[0] && c === t[1])
|
|
58
|
+
continue;
|
|
59
|
+
if (!isBlank(r, c))
|
|
60
|
+
clear.push([r, c]);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { merges: [...kept, ...targets], clear, center: kind === 'center', origins };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Whether merging the selection would drop a value: Excel warns that
|
|
68
|
+
* "merging cells only keeps the upper-left value". The shell asks before
|
|
69
|
+
* it merges.
|
|
70
|
+
*/
|
|
71
|
+
export function mergeDropsValues(rects, kind, isBlank) {
|
|
72
|
+
return mergePlan([], rects, kind, isBlank).clear.length > 0;
|
|
73
|
+
}
|
|
74
|
+
/** Unmerge: every merge the selection touches goes. */
|
|
75
|
+
export function unmergePlan(merges, rects) {
|
|
76
|
+
const touched = mergesIn(merges, rects);
|
|
77
|
+
return merges.filter((m) => !touched.includes(m));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A rectangle grown to hold every merge it touches, to a fixed point: the
|
|
81
|
+
* grid selects this way (a click on a merged cell takes the whole merge),
|
|
82
|
+
* so the header shading and anything else that reads the selection's
|
|
83
|
+
* columns and rows has to see the same rectangle.
|
|
84
|
+
*/
|
|
85
|
+
export function expandToMerges(merges, rect) {
|
|
86
|
+
let out = normalRect(rect);
|
|
87
|
+
for (let guard = 0; guard < 64; guard += 1) {
|
|
88
|
+
let grown = false;
|
|
89
|
+
for (const m of merges) {
|
|
90
|
+
if (!rectsIntersect(m, out))
|
|
91
|
+
continue;
|
|
92
|
+
const next = [Math.min(out[0], m[0]), Math.min(out[1], m[1]), Math.max(out[2], m[2]), Math.max(out[3], m[3])];
|
|
93
|
+
if (next[0] !== out[0] || next[1] !== out[1] || next[2] !== out[2] || next[3] !== out[3]) {
|
|
94
|
+
out = next;
|
|
95
|
+
grown = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!grown)
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** Whether the selection holds a merge, for the button's state. */
|
|
104
|
+
export function selectionMerged(merges, rects) {
|
|
105
|
+
return mergesIn(merges, rects).length > 0;
|
|
106
|
+
}
|
|
107
|
+
/** The merges as the grid takes them. */
|
|
108
|
+
export function toGridMerges(merges) {
|
|
109
|
+
return merges.map((m) => ({ rowIndex: m[0], colIndex: m[1], rowSpan: m[2] - m[0] + 1, colSpan: m[3] - m[1] + 1 }));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Whether a sort of `rect` can go ahead: Excel refuses when a merge
|
|
113
|
+
* crosses the range's edge ("all merged cells need to be the same size"),
|
|
114
|
+
* and the shell moves whole merges with their rows only when every merge
|
|
115
|
+
* in the range is one row tall and sits inside it.
|
|
116
|
+
*/
|
|
117
|
+
export function sortBlockedByMerges(merges, rect) {
|
|
118
|
+
const range = normalRect(rect);
|
|
119
|
+
for (const m of merges) {
|
|
120
|
+
if (!rectsIntersect(m, range))
|
|
121
|
+
continue;
|
|
122
|
+
const inside = m[0] >= range[0] && m[2] <= range[2] && m[1] >= range[1] && m[3] <= range[3];
|
|
123
|
+
if (!inside || m[0] !== m[2])
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
/** The merges of a sorted region, each moved with the row it sat on. */
|
|
129
|
+
export function reorderMerges(merges, rect, rowFor) {
|
|
130
|
+
const range = normalRect(rect);
|
|
131
|
+
return merges.map((m) => {
|
|
132
|
+
if (!rectsIntersect(m, range))
|
|
133
|
+
return m;
|
|
134
|
+
const row = rowFor(m[0]);
|
|
135
|
+
return [row, m[1], row, m[3]];
|
|
136
|
+
});
|
|
137
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Node } from './ast.js';
|
|
2
|
+
export type DefinedName = {
|
|
3
|
+
name: string;
|
|
4
|
+
/** What it refers to, e.g. `=Sheet1!$B$1` or `=$A$1:$C$9`. */
|
|
5
|
+
refersTo: string;
|
|
6
|
+
};
|
|
7
|
+
export type SheetNames = {
|
|
8
|
+
define(name: string, refersTo: string): void;
|
|
9
|
+
remove(name: string): void;
|
|
10
|
+
has(name: string): boolean;
|
|
11
|
+
/** The parsed reference behind a name, or null when undefined or unparseable. */
|
|
12
|
+
resolve(name: string): Node | null;
|
|
13
|
+
list(): DefinedName[];
|
|
14
|
+
serialize(): Record<string, string>;
|
|
15
|
+
hydrate(entries: Record<string, string>): void;
|
|
16
|
+
clear(): void;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Excel's rules, and the ones worth enforcing because a name that looks like a
|
|
20
|
+
* reference makes every formula containing it ambiguous:
|
|
21
|
+
* - starts with a letter or underscore
|
|
22
|
+
* - letters, digits, underscores and dots after that
|
|
23
|
+
* - not something that reads as a CELL reference (`A1`, `$A$1`)
|
|
24
|
+
* - not `R` or `C`, which Excel reserves for R1C1 notation
|
|
25
|
+
*
|
|
26
|
+
* A bare word like `Tax` is fine even though `TAX` is a valid column label:
|
|
27
|
+
* the tokenizer only reads a word as a column when it is qualified by a sheet
|
|
28
|
+
* or followed by a colon, so `=Tax` is never ambiguous.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isValidName(name: string): boolean;
|
|
31
|
+
export declare function createNames(initial?: Record<string, string>): SheetNames;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defined names: `Tax` resolving to `Sheet1!$B$1`, so a formula can say
|
|
3
|
+
* `=Subtotal*Tax` instead of `=D5*$B$1`.
|
|
4
|
+
*
|
|
5
|
+
* Names are stored as the TEXT they refer to rather than a parsed reference,
|
|
6
|
+
* because that is what the user typed and what round-trips to xlsx. Resolution
|
|
7
|
+
* parses on demand and caches nothing: names change rarely and resolving is
|
|
8
|
+
* cheap next to evaluating the formula that asked.
|
|
9
|
+
*/
|
|
10
|
+
import { parseFormula } from './parse.js';
|
|
11
|
+
/**
|
|
12
|
+
* Excel's rules, and the ones worth enforcing because a name that looks like a
|
|
13
|
+
* reference makes every formula containing it ambiguous:
|
|
14
|
+
* - starts with a letter or underscore
|
|
15
|
+
* - letters, digits, underscores and dots after that
|
|
16
|
+
* - not something that reads as a CELL reference (`A1`, `$A$1`)
|
|
17
|
+
* - not `R` or `C`, which Excel reserves for R1C1 notation
|
|
18
|
+
*
|
|
19
|
+
* A bare word like `Tax` is fine even though `TAX` is a valid column label:
|
|
20
|
+
* the tokenizer only reads a word as a column when it is qualified by a sheet
|
|
21
|
+
* or followed by a colon, so `=Tax` is never ambiguous.
|
|
22
|
+
*/
|
|
23
|
+
export function isValidName(name) {
|
|
24
|
+
if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(name))
|
|
25
|
+
return false;
|
|
26
|
+
if (name.length > 255)
|
|
27
|
+
return false;
|
|
28
|
+
// Letters followed by digits is a cell reference, whatever else it spells.
|
|
29
|
+
if (/^\$?[A-Za-z]{1,3}\$?\d+$/.test(name))
|
|
30
|
+
return false;
|
|
31
|
+
if (/^[RC]$/i.test(name))
|
|
32
|
+
return false;
|
|
33
|
+
if (/^(TRUE|FALSE)$/i.test(name))
|
|
34
|
+
return false;
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
export function createNames(initial) {
|
|
38
|
+
// Names are case-insensitive in Excel but keep the case they were defined
|
|
39
|
+
// with, so the map keys on the uppercase form and the entry holds the
|
|
40
|
+
// original.
|
|
41
|
+
const byUpper = new Map();
|
|
42
|
+
const api = {
|
|
43
|
+
define(name, refersTo) {
|
|
44
|
+
if (!isValidName(name)) {
|
|
45
|
+
throw new Error(`"${name}" is not a valid defined name: it must start with a letter ` +
|
|
46
|
+
'or underscore and must not look like a cell reference.');
|
|
47
|
+
}
|
|
48
|
+
byUpper.set(name.toUpperCase(), { name, refersTo });
|
|
49
|
+
},
|
|
50
|
+
remove(name) {
|
|
51
|
+
byUpper.delete(name.toUpperCase());
|
|
52
|
+
},
|
|
53
|
+
has(name) {
|
|
54
|
+
return byUpper.has(name.toUpperCase());
|
|
55
|
+
},
|
|
56
|
+
resolve(name) {
|
|
57
|
+
const entry = byUpper.get(name.toUpperCase());
|
|
58
|
+
if (!entry)
|
|
59
|
+
return null;
|
|
60
|
+
try {
|
|
61
|
+
return parseFormula(entry.refersTo);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
list() {
|
|
68
|
+
return [...byUpper.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
69
|
+
},
|
|
70
|
+
serialize() {
|
|
71
|
+
return Object.fromEntries([...byUpper.values()].map((e) => [e.name, e.refersTo]));
|
|
72
|
+
},
|
|
73
|
+
hydrate(entries) {
|
|
74
|
+
byUpper.clear();
|
|
75
|
+
for (const [name, refersTo] of Object.entries(entries)) {
|
|
76
|
+
if (isValidName(name))
|
|
77
|
+
byUpper.set(name.toUpperCase(), { name, refersTo });
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
clear() {
|
|
81
|
+
byUpper.clear();
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
if (initial)
|
|
85
|
+
api.hydrate(initial);
|
|
86
|
+
return api;
|
|
87
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel's jump-to-edge navigation, as pure functions over a cell-value lookup.
|
|
3
|
+
*
|
|
4
|
+
* `Ctrl+Arrow` is not "move a long way". It is a run-boundary search, and the
|
|
5
|
+
* rule flips depending on what you are standing on:
|
|
6
|
+
*
|
|
7
|
+
* - Standing on a FILLED cell with a filled neighbour: run to the LAST filled
|
|
8
|
+
* cell before the next blank. This is how you get from the top of a column
|
|
9
|
+
* to its bottom in one press.
|
|
10
|
+
* - Standing on a FILLED cell whose neighbour is blank: skip the blank run
|
|
11
|
+
* and land on the NEXT filled cell. This is how you hop between blocks.
|
|
12
|
+
* - Standing on a BLANK cell: skip to the next filled cell.
|
|
13
|
+
* - Nothing filled ahead in either case: land on the last cell of the sheet
|
|
14
|
+
* in that direction, which is what Ctrl+Down does on an empty column.
|
|
15
|
+
*
|
|
16
|
+
* Getting this wrong in the obvious way (always run to the end of the filled
|
|
17
|
+
* block) means the shortcut stops working the moment there is a gap, which is
|
|
18
|
+
* most real spreadsheets.
|
|
19
|
+
*/
|
|
20
|
+
/** What counts as empty. Excel treats a cell holding an empty string as blank
|
|
21
|
+
* for navigation, and so does this: a column of `''` should not trap the
|
|
22
|
+
* cursor. A zero, a `false` and a whitespace-only string are all content. */
|
|
23
|
+
export declare function isBlankValue(value: unknown): boolean;
|
|
24
|
+
export type Direction = 'up' | 'down' | 'left' | 'right';
|
|
25
|
+
export type Grid = {
|
|
26
|
+
rowCount: number;
|
|
27
|
+
colCount: number;
|
|
28
|
+
isBlank(row: number, col: number): boolean;
|
|
29
|
+
};
|
|
30
|
+
export type Cell = {
|
|
31
|
+
row: number;
|
|
32
|
+
col: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Where `Ctrl+Arrow` lands from `from`, going `dir`. Never returns a cell off
|
|
36
|
+
* the sheet, and returns `from` unchanged when it is already on the edge.
|
|
37
|
+
*/
|
|
38
|
+
export declare function edgeOfRegion(grid: Grid, from: Cell, dir: Direction): Cell;
|
|
39
|
+
export type Rect = readonly [minRow: number, minCol: number, maxRow: number, maxCol: number];
|
|
40
|
+
/**
|
|
41
|
+
* Excel's `Ctrl+A` first press: the contiguous block of non-blank cells around
|
|
42
|
+
* `from`, grown outward until every bounding edge is blank.
|
|
43
|
+
*
|
|
44
|
+
* Grown as a rectangle rather than flood-filled, because that is what Excel
|
|
45
|
+
* selects: a block with a notch in it still comes back as the rectangle that
|
|
46
|
+
* encloses it. Returns the single cell when `from` sits alone in white space.
|
|
47
|
+
*/
|
|
48
|
+
export declare function currentRegion(grid: Grid, from: Cell): Rect;
|
|
49
|
+
/** Whether `rect` already covers every cell, so `Ctrl+A` should stop growing. */
|
|
50
|
+
export declare function isWholeSheet(grid: Grid, rect: Rect): boolean;
|
|
51
|
+
/** The whole sheet as a rectangle. */
|
|
52
|
+
export declare function wholeSheet(grid: Grid): Rect;
|