@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,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formula lexer.
|
|
3
|
+
*
|
|
4
|
+
* The awkward part of spreadsheet lexing is that `A1`, `A1:B2`, `Sheet1!A1`,
|
|
5
|
+
* `'Price list'!A1:B2`, `SUM(` and `TRUE` all start life as the same run of
|
|
6
|
+
* letters and digits. Rather than guess, the lexer reads the whole word plus
|
|
7
|
+
* whatever qualifies it (a `!` before, a `:` after, a `(` after) and decides
|
|
8
|
+
* once, with all of it in hand.
|
|
9
|
+
*
|
|
10
|
+
* `$` is part of a word here and stays in the text handed to `parseA1`, which
|
|
11
|
+
* is what keeps absolute references absolute.
|
|
12
|
+
*/
|
|
13
|
+
import { parseA1 } from './address.js';
|
|
14
|
+
import { FormulaError } from './ast.js';
|
|
15
|
+
const WORD = /[A-Za-z0-9$_.]/;
|
|
16
|
+
const SPECIFIERS = {
|
|
17
|
+
'#all': '#All',
|
|
18
|
+
'#data': '#Data',
|
|
19
|
+
'#headers': '#Headers',
|
|
20
|
+
'#totals': '#Totals',
|
|
21
|
+
'#this row': '#ThisRow',
|
|
22
|
+
};
|
|
23
|
+
const TWO_CHAR_OPS = new Set(['<=', '>=', '<>']);
|
|
24
|
+
const ONE_CHAR_OPS = '+-*/^%&=<>';
|
|
25
|
+
export function tokenize(src) {
|
|
26
|
+
const out = [];
|
|
27
|
+
let i = 0;
|
|
28
|
+
/** Index of the next non-space character, without consuming anything. */
|
|
29
|
+
const skipSpace = () => {
|
|
30
|
+
let j = i;
|
|
31
|
+
while (j < src.length && /\s/.test(src[j]))
|
|
32
|
+
j += 1;
|
|
33
|
+
return j;
|
|
34
|
+
};
|
|
35
|
+
const readWord = () => {
|
|
36
|
+
const start = i;
|
|
37
|
+
while (i < src.length && WORD.test(src[i]))
|
|
38
|
+
i += 1;
|
|
39
|
+
return src.slice(start, i);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Read a structured reference's bracket, having just consumed the `[`.
|
|
43
|
+
*
|
|
44
|
+
* The grammar is small but irregular: `[Amount]` is a column, `[@Amount]`
|
|
45
|
+
* is this row of it, `[#Totals]` is a specifier, and
|
|
46
|
+
* `[[Qty]:[Amount]]` is a span whose inner brackets are part of the
|
|
47
|
+
* syntax rather than nesting. Reading it as balanced brackets and then
|
|
48
|
+
* picking the pieces apart handles all four without a special case each.
|
|
49
|
+
*/
|
|
50
|
+
const readTableBracket = (table) => {
|
|
51
|
+
let depth = 1;
|
|
52
|
+
const start = i;
|
|
53
|
+
while (i < src.length && depth > 0) {
|
|
54
|
+
if (src[i] === '[')
|
|
55
|
+
depth += 1;
|
|
56
|
+
else if (src[i] === ']')
|
|
57
|
+
depth -= 1;
|
|
58
|
+
if (depth > 0)
|
|
59
|
+
i += 1;
|
|
60
|
+
}
|
|
61
|
+
if (depth !== 0)
|
|
62
|
+
throw new FormulaError('#PARSE!');
|
|
63
|
+
const body = src.slice(start, i);
|
|
64
|
+
i += 1; // past the closing ]
|
|
65
|
+
let specifier = '#Data';
|
|
66
|
+
let column = null;
|
|
67
|
+
let columnTo = null;
|
|
68
|
+
// Split on top-level commas, so [#Data],[Amount] arrives as two parts.
|
|
69
|
+
const parts = [];
|
|
70
|
+
let current = '';
|
|
71
|
+
let inner = 0;
|
|
72
|
+
for (const ch of body) {
|
|
73
|
+
if (ch === '[')
|
|
74
|
+
inner += 1;
|
|
75
|
+
else if (ch === ']')
|
|
76
|
+
inner -= 1;
|
|
77
|
+
if (ch === ',' && inner === 0) {
|
|
78
|
+
parts.push(current);
|
|
79
|
+
current = '';
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
current += ch;
|
|
83
|
+
}
|
|
84
|
+
parts.push(current);
|
|
85
|
+
for (const rawPart of parts) {
|
|
86
|
+
let part = rawPart.trim();
|
|
87
|
+
if (part === '')
|
|
88
|
+
continue;
|
|
89
|
+
if (part.startsWith('@')) {
|
|
90
|
+
specifier = '#ThisRow';
|
|
91
|
+
part = part.slice(1).trim();
|
|
92
|
+
if (part === '')
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const known = SPECIFIERS[part.toLowerCase()];
|
|
96
|
+
if (known) {
|
|
97
|
+
specifier = known;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
// A span: [Qty]:[Amount]
|
|
101
|
+
const span = /^\[([^\]]*)\]\s*:\s*\[([^\]]*)\]$/.exec(part);
|
|
102
|
+
if (span) {
|
|
103
|
+
column = span[1].trim();
|
|
104
|
+
columnTo = span[2].trim();
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// A single bracketed part, which is how a name containing a space or a
|
|
108
|
+
// comma is written - and also how a specifier arrives inside a
|
|
109
|
+
// multi-part reference like [[#Headers],[Amount]], so unwrap FIRST
|
|
110
|
+
// and re-check before assuming it names a column.
|
|
111
|
+
const wrapped = /^\[([^\]]*)\]$/.exec(part);
|
|
112
|
+
const unwrapped = (wrapped ? wrapped[1] : part).trim();
|
|
113
|
+
const inner = SPECIFIERS[unwrapped.toLowerCase()];
|
|
114
|
+
if (inner) {
|
|
115
|
+
specifier = inner;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (unwrapped.startsWith('@')) {
|
|
119
|
+
specifier = '#ThisRow';
|
|
120
|
+
const rest = unwrapped.slice(1).trim();
|
|
121
|
+
if (rest !== '')
|
|
122
|
+
column = rest;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
column = unwrapped;
|
|
126
|
+
}
|
|
127
|
+
return columnTo === null
|
|
128
|
+
? { t: 'table', table, column, specifier }
|
|
129
|
+
: { t: 'table', table, column, columnTo, specifier };
|
|
130
|
+
};
|
|
131
|
+
/** Turn a word (and possibly `:word` after it) into a ref, range or name. */
|
|
132
|
+
const pushWord = (word, sheet) => {
|
|
133
|
+
const left = parseA1(word, sheet);
|
|
134
|
+
// Excel accepts whitespace around the range colon: `SUM(A1 : B2)`. Look
|
|
135
|
+
// past it before deciding this is a lone reference, or that formula comes
|
|
136
|
+
// back unparseable.
|
|
137
|
+
const afterSpace = skipSpace();
|
|
138
|
+
if (src[afterSpace] === ':') {
|
|
139
|
+
i = afterSpace + 1;
|
|
140
|
+
while (i < src.length && /\s/.test(src[i]))
|
|
141
|
+
i += 1;
|
|
142
|
+
const rightWord = readWord();
|
|
143
|
+
const right = parseA1(rightWord, sheet);
|
|
144
|
+
if (!left || !right)
|
|
145
|
+
throw new FormulaError('#PARSE!');
|
|
146
|
+
out.push({ t: 'range', from: left, to: right });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (!left)
|
|
150
|
+
throw new FormulaError('#PARSE!');
|
|
151
|
+
// A word with no row is a whole-column reference (`A:A` written as `A`),
|
|
152
|
+
// which is a range from row 0 to the end of the sheet.
|
|
153
|
+
if (left.row === null) {
|
|
154
|
+
// A bare word on a sheet-qualified ref is still a column. Unqualified,
|
|
155
|
+
// it could be a defined name - the parser decides using `name` tokens,
|
|
156
|
+
// so only emit a column range when the text looks like one.
|
|
157
|
+
if (sheet !== null) {
|
|
158
|
+
out.push({ t: 'range', from: { ...left, row: 0 }, to: { ...left, row: null } });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
out.push({ t: 'name', v: word });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
out.push({ t: 'ref', ref: left });
|
|
165
|
+
};
|
|
166
|
+
while (i < src.length) {
|
|
167
|
+
const ch = src[i];
|
|
168
|
+
if (/\s/.test(ch)) {
|
|
169
|
+
i += 1;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (ch === '(') {
|
|
173
|
+
out.push({ t: 'lparen' });
|
|
174
|
+
i += 1;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (ch === ')') {
|
|
178
|
+
out.push({ t: 'rparen' });
|
|
179
|
+
i += 1;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (ch === ',') {
|
|
183
|
+
out.push({ t: 'comma' });
|
|
184
|
+
i += 1;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
// String literal. Excel escapes a quote by doubling it.
|
|
188
|
+
if (ch === '"') {
|
|
189
|
+
i += 1;
|
|
190
|
+
let value = '';
|
|
191
|
+
for (;;) {
|
|
192
|
+
if (i >= src.length)
|
|
193
|
+
throw new FormulaError('#PARSE!');
|
|
194
|
+
if (src[i] === '"') {
|
|
195
|
+
if (src[i + 1] === '"') {
|
|
196
|
+
value += '"';
|
|
197
|
+
i += 2;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
i += 1;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
value += src[i];
|
|
204
|
+
i += 1;
|
|
205
|
+
}
|
|
206
|
+
out.push({ t: 'str', v: value });
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
// Quoted sheet name: 'Price list'!A1
|
|
210
|
+
if (ch === "'") {
|
|
211
|
+
i += 1;
|
|
212
|
+
let sheet = '';
|
|
213
|
+
for (;;) {
|
|
214
|
+
if (i >= src.length)
|
|
215
|
+
throw new FormulaError('#PARSE!');
|
|
216
|
+
if (src[i] === "'") {
|
|
217
|
+
if (src[i + 1] === "'") {
|
|
218
|
+
sheet += "'";
|
|
219
|
+
i += 2;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
i += 1;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
sheet += src[i];
|
|
226
|
+
i += 1;
|
|
227
|
+
}
|
|
228
|
+
if (src[i] !== '!')
|
|
229
|
+
throw new FormulaError('#PARSE!');
|
|
230
|
+
i += 1;
|
|
231
|
+
pushWord(readWord(), sheet);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (/[0-9]/.test(ch) || (ch === '.' && /[0-9]/.test(src[i + 1] ?? ''))) {
|
|
235
|
+
const start = i;
|
|
236
|
+
while (i < src.length && /[0-9.]/.test(src[i]))
|
|
237
|
+
i += 1;
|
|
238
|
+
// Scientific notation: 1e5, 2.5E-3.
|
|
239
|
+
if ((src[i] === 'e' || src[i] === 'E') && /[0-9+-]/.test(src[i + 1] ?? '')) {
|
|
240
|
+
i += 1;
|
|
241
|
+
if (src[i] === '+' || src[i] === '-')
|
|
242
|
+
i += 1;
|
|
243
|
+
while (i < src.length && /[0-9]/.test(src[i]))
|
|
244
|
+
i += 1;
|
|
245
|
+
}
|
|
246
|
+
const n = Number(src.slice(start, i));
|
|
247
|
+
if (!Number.isFinite(n))
|
|
248
|
+
throw new FormulaError('#PARSE!');
|
|
249
|
+
out.push({ t: 'num', v: n });
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (/[A-Za-z$_]/.test(ch)) {
|
|
253
|
+
const word = readWord();
|
|
254
|
+
const upper = word.toUpperCase();
|
|
255
|
+
// Unquoted sheet name: Orders!A1
|
|
256
|
+
if (src[i] === '!') {
|
|
257
|
+
i += 1;
|
|
258
|
+
pushWord(readWord(), word);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (upper === 'TRUE') {
|
|
262
|
+
out.push({ t: 'bool', v: true });
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
if (upper === 'FALSE') {
|
|
266
|
+
out.push({ t: 'bool', v: false });
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
// A word followed by `[` is a table: Orders[Amount].
|
|
270
|
+
if (src[i] === '[') {
|
|
271
|
+
i += 1;
|
|
272
|
+
out.push(readTableBracket(word));
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
// A word followed by `(` is a call, whatever else it might look like.
|
|
276
|
+
if (src[skipSpace()] === '(') {
|
|
277
|
+
out.push({ t: 'fn', v: upper });
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
pushWord(word, null);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
// A bare `[` is the unqualified form, which only means something in a
|
|
284
|
+
// formula sitting inside a table: [@Amount].
|
|
285
|
+
if (ch === '[') {
|
|
286
|
+
i += 1;
|
|
287
|
+
out.push(readTableBracket(null));
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const two = src.slice(i, i + 2);
|
|
291
|
+
if (TWO_CHAR_OPS.has(two)) {
|
|
292
|
+
out.push({ t: 'op', v: two });
|
|
293
|
+
i += 2;
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (ONE_CHAR_OPS.includes(ch)) {
|
|
297
|
+
out.push({ t: 'op', v: ch });
|
|
298
|
+
i += 1;
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
throw new FormulaError('#PARSE!');
|
|
302
|
+
}
|
|
303
|
+
return out;
|
|
304
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text to Columns and Remove Duplicates: the two one-shot transforms an Excel
|
|
3
|
+
* user reaches for on arriving data, before any formula work starts.
|
|
4
|
+
*
|
|
5
|
+
* Both are pure functions over cell text rather than commands that reach into
|
|
6
|
+
* a grid, because both are things a consumer may want to run from a button, a
|
|
7
|
+
* menu, a paste handler or a test, and none of those want a keystroke.
|
|
8
|
+
*/
|
|
9
|
+
export type SplitOptions = {
|
|
10
|
+
/**
|
|
11
|
+
* Split on these strings. Excel's dialog offers tab, semicolon, comma, space
|
|
12
|
+
* and "other"; passing several splits on any of them.
|
|
13
|
+
*/
|
|
14
|
+
delimiters?: ReadonlyArray<string>;
|
|
15
|
+
/** Treat runs of delimiters as one. Excel's "treat consecutive delimiters as
|
|
16
|
+
* one" checkbox, and what you want for space-separated text. */
|
|
17
|
+
collapse?: boolean;
|
|
18
|
+
/** Text inside these is not split, and the quotes come off. */
|
|
19
|
+
quote?: string;
|
|
20
|
+
/** Trim surrounding whitespace from each field. */
|
|
21
|
+
trim?: boolean;
|
|
22
|
+
/** Stop after this many fields, leaving the rest in the last one. Excel has
|
|
23
|
+
* no equivalent; it is here because "name: free text with: colons" is the
|
|
24
|
+
* common real case. */
|
|
25
|
+
limit?: number;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Split one string into fields.
|
|
29
|
+
*
|
|
30
|
+
* A scan rather than `String.split`, because a quoted field may contain a
|
|
31
|
+
* delimiter and a doubled quote is an escaped one. Splitting first and
|
|
32
|
+
* repairing afterwards is how CSV parsers get subtly wrong.
|
|
33
|
+
*/
|
|
34
|
+
export declare function splitText(text: string, options?: SplitOptions): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Split a column of text into a grid, padded so every row is the same width.
|
|
37
|
+
*
|
|
38
|
+
* Padding matters: writing a ragged result into a grid leaves whatever was
|
|
39
|
+
* already in the cell, so a row that split into two fields would keep stale
|
|
40
|
+
* text in the third column.
|
|
41
|
+
*/
|
|
42
|
+
export declare function textToColumns(column: ReadonlyArray<string>, options?: SplitOptions): {
|
|
43
|
+
rows: string[][];
|
|
44
|
+
width: number;
|
|
45
|
+
};
|
|
46
|
+
/** Guess which delimiter a column uses, the way Excel's wizard previews one. */
|
|
47
|
+
export declare function guessDelimiter(column: ReadonlyArray<string>, candidates?: ReadonlyArray<string>): string | null;
|
|
48
|
+
export type DuplicateOptions = {
|
|
49
|
+
/** Column indexes that decide identity. Default: every column given. */
|
|
50
|
+
columns?: ReadonlyArray<number>;
|
|
51
|
+
/** Compare case-sensitively. Excel's Remove Duplicates is case
|
|
52
|
+
* INSENSITIVE, which surprises people, so that is the default here too. */
|
|
53
|
+
matchCase?: boolean;
|
|
54
|
+
/** Keep the last of each group rather than the first. */
|
|
55
|
+
keep?: 'first' | 'last';
|
|
56
|
+
};
|
|
57
|
+
export type DuplicateReport = {
|
|
58
|
+
/** Indexes into the input, in order, of the rows to keep. */
|
|
59
|
+
keep: number[];
|
|
60
|
+
/** Indexes of the rows that duplicate another. */
|
|
61
|
+
remove: number[];
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Which rows are duplicates.
|
|
65
|
+
*
|
|
66
|
+
* Reports rather than removes, so the caller decides what removal means for
|
|
67
|
+
* its data structure, and so a UI can say "3 duplicates found, 5 unique values
|
|
68
|
+
* remain" before anything is written. That message is most of what Excel's
|
|
69
|
+
* dialog does.
|
|
70
|
+
*/
|
|
71
|
+
export declare function findDuplicates(rows: ReadonlyArray<ReadonlyArray<unknown>>, options?: DuplicateOptions): DuplicateReport;
|
|
72
|
+
/** The rows that survive, in their original order, and how many went. */
|
|
73
|
+
export declare function removeDuplicates<T>(rows: ReadonlyArray<T>, toCells: (row: T) => ReadonlyArray<unknown>, options?: DuplicateOptions): {
|
|
74
|
+
rows: T[];
|
|
75
|
+
removed: number;
|
|
76
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text to Columns and Remove Duplicates: the two one-shot transforms an Excel
|
|
3
|
+
* user reaches for on arriving data, before any formula work starts.
|
|
4
|
+
*
|
|
5
|
+
* Both are pure functions over cell text rather than commands that reach into
|
|
6
|
+
* a grid, because both are things a consumer may want to run from a button, a
|
|
7
|
+
* menu, a paste handler or a test, and none of those want a keystroke.
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULTS = {
|
|
10
|
+
delimiters: [','],
|
|
11
|
+
collapse: false,
|
|
12
|
+
quote: '"',
|
|
13
|
+
trim: false,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Split one string into fields.
|
|
17
|
+
*
|
|
18
|
+
* A scan rather than `String.split`, because a quoted field may contain a
|
|
19
|
+
* delimiter and a doubled quote is an escaped one. Splitting first and
|
|
20
|
+
* repairing afterwards is how CSV parsers get subtly wrong.
|
|
21
|
+
*/
|
|
22
|
+
export function splitText(text, options = {}) {
|
|
23
|
+
const { delimiters, collapse, quote, trim } = { ...DEFAULTS, ...options };
|
|
24
|
+
const limit = options.limit;
|
|
25
|
+
// Longest first, so ", " wins over "," when both are offered.
|
|
26
|
+
const seps = [...delimiters].filter((d) => d !== '').sort((a, b) => b.length - a.length);
|
|
27
|
+
if (seps.length === 0)
|
|
28
|
+
return [text];
|
|
29
|
+
const out = [];
|
|
30
|
+
let current = '';
|
|
31
|
+
let inQuote = false;
|
|
32
|
+
let i = 0;
|
|
33
|
+
const push = () => {
|
|
34
|
+
out.push(trim ? current.trim() : current);
|
|
35
|
+
current = '';
|
|
36
|
+
};
|
|
37
|
+
while (i < text.length) {
|
|
38
|
+
const ch = text[i];
|
|
39
|
+
if (quote && ch === quote) {
|
|
40
|
+
if (inQuote && text[i + 1] === quote) {
|
|
41
|
+
current += quote;
|
|
42
|
+
i += 2;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
inQuote = !inQuote;
|
|
46
|
+
i += 1;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (!inQuote && (limit === undefined || out.length < limit - 1)) {
|
|
50
|
+
const hit = seps.find((sep) => text.startsWith(sep, i));
|
|
51
|
+
if (hit) {
|
|
52
|
+
push();
|
|
53
|
+
i += hit.length;
|
|
54
|
+
if (collapse) {
|
|
55
|
+
// Swallow the run that follows, so "a b" on a space delimiter
|
|
56
|
+
// gives two fields rather than four.
|
|
57
|
+
for (;;) {
|
|
58
|
+
const more = seps.find((sep) => text.startsWith(sep, i));
|
|
59
|
+
if (!more)
|
|
60
|
+
break;
|
|
61
|
+
i += more.length;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
current += ch;
|
|
68
|
+
i += 1;
|
|
69
|
+
}
|
|
70
|
+
push();
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Split a column of text into a grid, padded so every row is the same width.
|
|
75
|
+
*
|
|
76
|
+
* Padding matters: writing a ragged result into a grid leaves whatever was
|
|
77
|
+
* already in the cell, so a row that split into two fields would keep stale
|
|
78
|
+
* text in the third column.
|
|
79
|
+
*/
|
|
80
|
+
export function textToColumns(column, options = {}) {
|
|
81
|
+
const rows = column.map((text) => splitText(text, options));
|
|
82
|
+
const width = rows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
83
|
+
for (const row of rows) {
|
|
84
|
+
while (row.length < width)
|
|
85
|
+
row.push('');
|
|
86
|
+
}
|
|
87
|
+
return { rows, width };
|
|
88
|
+
}
|
|
89
|
+
/** Guess which delimiter a column uses, the way Excel's wizard previews one. */
|
|
90
|
+
export function guessDelimiter(column, candidates = ['\t', ';', ',', '|', ' ']) {
|
|
91
|
+
let best = null;
|
|
92
|
+
for (const sep of candidates) {
|
|
93
|
+
// A good delimiter appears in most rows AND the same number of times in
|
|
94
|
+
// each. A comma in one row out of fifty is prose, not structure.
|
|
95
|
+
const counts = column.map((text) => text.split(sep).length - 1);
|
|
96
|
+
const present = counts.filter((n) => n > 0).length;
|
|
97
|
+
if (present === 0)
|
|
98
|
+
continue;
|
|
99
|
+
const first = counts.find((n) => n > 0) ?? 0;
|
|
100
|
+
const consistent = counts.every((n) => n === 0 || n === first);
|
|
101
|
+
const score = present * (consistent ? 2 : 1);
|
|
102
|
+
if (!best || score > best.score)
|
|
103
|
+
best = { sep, score };
|
|
104
|
+
}
|
|
105
|
+
return best ? best.sep : null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Which rows are duplicates.
|
|
109
|
+
*
|
|
110
|
+
* Reports rather than removes, so the caller decides what removal means for
|
|
111
|
+
* its data structure, and so a UI can say "3 duplicates found, 5 unique values
|
|
112
|
+
* remain" before anything is written. That message is most of what Excel's
|
|
113
|
+
* dialog does.
|
|
114
|
+
*/
|
|
115
|
+
export function findDuplicates(rows, options = {}) {
|
|
116
|
+
const keepWhich = options.keep ?? 'first';
|
|
117
|
+
const matchCase = options.matchCase ?? false;
|
|
118
|
+
const keyOf = (row) => {
|
|
119
|
+
const cols = options.columns ?? row.map((_v, i) => i);
|
|
120
|
+
return cols
|
|
121
|
+
.map((c) => {
|
|
122
|
+
const v = row[c];
|
|
123
|
+
const text = v === null || v === undefined ? '' : String(v);
|
|
124
|
+
return matchCase ? text : text.toLowerCase();
|
|
125
|
+
})
|
|
126
|
+
// A separator a cell cannot contain. Joining on a space would make
|
|
127
|
+
// ["a", "b"] and ["a b"] the same row.
|
|
128
|
+
.join('\u0000');
|
|
129
|
+
};
|
|
130
|
+
const seen = new Map();
|
|
131
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
132
|
+
const key = keyOf(rows[i]);
|
|
133
|
+
if (!seen.has(key) || keepWhich === 'last')
|
|
134
|
+
seen.set(key, i);
|
|
135
|
+
}
|
|
136
|
+
const kept = new Set(seen.values());
|
|
137
|
+
const keep = [];
|
|
138
|
+
const remove = [];
|
|
139
|
+
for (let i = 0; i < rows.length; i += 1) {
|
|
140
|
+
if (kept.has(i))
|
|
141
|
+
keep.push(i);
|
|
142
|
+
else
|
|
143
|
+
remove.push(i);
|
|
144
|
+
}
|
|
145
|
+
return { keep, remove };
|
|
146
|
+
}
|
|
147
|
+
/** The rows that survive, in their original order, and how many went. */
|
|
148
|
+
export function removeDuplicates(rows, toCells, options = {}) {
|
|
149
|
+
const report = findDuplicates(rows.map(toCells), options);
|
|
150
|
+
return {
|
|
151
|
+
rows: report.keep.map((i) => rows[i]),
|
|
152
|
+
removed: report.remove.length,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data validation, Excel's: a rule over some cells says what may be typed
|
|
3
|
+
* into them, and an entry that breaks it is stopped (or warned about)
|
|
4
|
+
* before it lands. Only typed entries are checked, as in Excel: paste, fill
|
|
5
|
+
* and the commands write what they are given.
|
|
6
|
+
*
|
|
7
|
+
* Rules keep their rectangles by position and move with an insert or
|
|
8
|
+
* delete; the last rule that covers a cell is the one that applies, which
|
|
9
|
+
* is what lets a later rule over a smaller block override an earlier one.
|
|
10
|
+
* Bounds and custom rules are text (a literal or a formula) evaluated in
|
|
11
|
+
* the sheet through the context the shell supplies, so `=$B$1` as a
|
|
12
|
+
* maximum follows B1.
|
|
13
|
+
*/
|
|
14
|
+
import { type CellValue } from './ast.js';
|
|
15
|
+
import type { StructuralEdit } from './refs.js';
|
|
16
|
+
import { type Rect } from './rects.js';
|
|
17
|
+
export type ValidationAllow = 'any' | 'whole' | 'decimal' | 'list' | 'date' | 'textLength' | 'custom';
|
|
18
|
+
export type ValidationOperator = 'between' | 'notBetween' | 'equal' | 'notEqual' | 'greater' | 'less' | 'greaterOrEqual' | 'lessOrEqual';
|
|
19
|
+
/** Everything a rule is but where it applies: what the dialog hands back. */
|
|
20
|
+
export type ValidationSpec = Omit<ValidationRule, 'id' | 'rects'>;
|
|
21
|
+
export type ValidationRule = {
|
|
22
|
+
id: string;
|
|
23
|
+
rects: ReadonlyArray<Rect>;
|
|
24
|
+
allow: ValidationAllow;
|
|
25
|
+
/** For whole, decimal, date and textLength. Default between. */
|
|
26
|
+
operator?: ValidationOperator;
|
|
27
|
+
/** The bound, the value, the list source or the custom formula: a
|
|
28
|
+
* literal, a comma list, or a formula starting with '='. */
|
|
29
|
+
value1?: string;
|
|
30
|
+
/** The upper bound of between / notBetween. */
|
|
31
|
+
value2?: string;
|
|
32
|
+
ignoreBlank: boolean;
|
|
33
|
+
/** List rules: show the arrow and the picker on the cell. */
|
|
34
|
+
inCellDropdown: boolean;
|
|
35
|
+
alert: {
|
|
36
|
+
style: 'stop' | 'warning';
|
|
37
|
+
title?: string;
|
|
38
|
+
message?: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/** How a rule reads the sheet: the shell wires the workbook in. */
|
|
42
|
+
export type ValidationContext = {
|
|
43
|
+
/**
|
|
44
|
+
* A formula or a literal, evaluated in the sheet. With `entry`, the
|
|
45
|
+
* cell being checked reads as that text: Excel's custom rules refer to
|
|
46
|
+
* the cell they guard (`=A1>B1` on A1), and the entry is not written yet.
|
|
47
|
+
*/
|
|
48
|
+
evaluate(text: string, entry?: {
|
|
49
|
+
row: number;
|
|
50
|
+
col: number;
|
|
51
|
+
text: string;
|
|
52
|
+
}): CellValue;
|
|
53
|
+
/** The values of a range reference or a name for one; null otherwise. */
|
|
54
|
+
range(text: string): CellValue[][] | null;
|
|
55
|
+
};
|
|
56
|
+
export type ValidationVerdict = {
|
|
57
|
+
ok: true;
|
|
58
|
+
} | {
|
|
59
|
+
ok: false;
|
|
60
|
+
style: 'stop' | 'warning';
|
|
61
|
+
title: string;
|
|
62
|
+
message: string;
|
|
63
|
+
};
|
|
64
|
+
/** Excel's own words when a rule has no message of its own. */
|
|
65
|
+
export declare const DEFAULT_ALERT_MESSAGE = "This value doesn't match the data validation restrictions defined for this cell.";
|
|
66
|
+
export declare const OPERATOR_LABELS: Record<ValidationOperator, string>;
|
|
67
|
+
export declare function validationId(): string;
|
|
68
|
+
/** The rule that applies to (r, c): the last one covering it. */
|
|
69
|
+
export declare function ruleAt(rules: ReadonlyArray<ValidationRule>, r: number, c: number): ValidationRule | undefined;
|
|
70
|
+
/** The rules touching any of the rectangles. */
|
|
71
|
+
export declare function rulesIn(rules: ReadonlyArray<ValidationRule>, rects: ReadonlyArray<Rect>): ValidationRule[];
|
|
72
|
+
/** A date as milliseconds: an ISO text, or an Excel serial. Null otherwise. */
|
|
73
|
+
export declare function dateValue(v: CellValue): number | null;
|
|
74
|
+
/**
|
|
75
|
+
* The choices a list rule offers: a comma list as written, or the cells of
|
|
76
|
+
* a range (or a name for one), blanks left out, as text.
|
|
77
|
+
*/
|
|
78
|
+
export declare function listChoices(rule: ValidationRule, ctx: ValidationContext): string[];
|
|
79
|
+
/**
|
|
80
|
+
* Whether `text`, typed into (row, col), passes the rule. The verdict
|
|
81
|
+
* carries the alert to show when it does not.
|
|
82
|
+
*/
|
|
83
|
+
export declare function checkEntry(rule: ValidationRule, text: string, at: {
|
|
84
|
+
row: number;
|
|
85
|
+
col: number;
|
|
86
|
+
}, ctx: ValidationContext): ValidationVerdict;
|
|
87
|
+
/** The rules after an insert or delete. */
|
|
88
|
+
export declare function shiftValidation(rules: ReadonlyArray<ValidationRule>, edit: StructuralEdit): ValidationRule[];
|
|
89
|
+
/** The rules with the rectangles cut out of them: Excel's Clear All. */
|
|
90
|
+
export declare function removeValidation(rules: ReadonlyArray<ValidationRule>, rects: ReadonlyArray<Rect>): ValidationRule[];
|
|
91
|
+
/** A short description for a rule, the way Excel's dialog title reads it. */
|
|
92
|
+
export declare function describeRule(rule: ValidationRule): string;
|