@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,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell comments, Excel's notes: a text on a cell, shown as a corner mark
|
|
3
|
+
* and read on hover. They live in the sheet document in the grid's own
|
|
4
|
+
* `notes` shape (`r4` -> `B` -> text), so the grid draws the mark and the
|
|
5
|
+
* tooltip and the document moves them with an insert or delete
|
|
6
|
+
* (`remapNotes`). This module is the pure part: reading, writing, and
|
|
7
|
+
* walking them the way Review > Previous / Next do.
|
|
8
|
+
*/
|
|
9
|
+
import { colToLetters, lettersToCol } from './address.js';
|
|
10
|
+
/** The comment on (r, c), or undefined when there is none. */
|
|
11
|
+
export function commentAt(notes, r, c) {
|
|
12
|
+
const text = notes[`r${r}`]?.[colToLetters(c)];
|
|
13
|
+
return text && text.trim() ? text : undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The map with (r, c) set to `text`, or cleared when the text is blank.
|
|
17
|
+
* A new map, never the old one changed: the grid re-reads `notes` only
|
|
18
|
+
* when the object it is handed is a different one.
|
|
19
|
+
*/
|
|
20
|
+
export function withComment(notes, r, c, text) {
|
|
21
|
+
const rowId = `r${r}`;
|
|
22
|
+
const columnId = colToLetters(c);
|
|
23
|
+
const out = {};
|
|
24
|
+
for (const [id, line] of Object.entries(notes))
|
|
25
|
+
out[id] = { ...line };
|
|
26
|
+
if (text.trim()) {
|
|
27
|
+
out[rowId] = { ...(out[rowId] ?? {}), [columnId]: text };
|
|
28
|
+
}
|
|
29
|
+
else if (out[rowId]) {
|
|
30
|
+
delete out[rowId][columnId];
|
|
31
|
+
if (Object.keys(out[rowId]).length === 0)
|
|
32
|
+
delete out[rowId];
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/** Every comment, top to bottom then left to right. */
|
|
37
|
+
export function listComments(notes) {
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const [rowId, line] of Object.entries(notes)) {
|
|
40
|
+
const row = Number(rowId.slice(1));
|
|
41
|
+
if (!Number.isInteger(row) || row < 0)
|
|
42
|
+
continue;
|
|
43
|
+
for (const [columnId, text] of Object.entries(line)) {
|
|
44
|
+
const col = lettersToCol(columnId);
|
|
45
|
+
if (col < 0 || !text || !text.trim())
|
|
46
|
+
continue;
|
|
47
|
+
out.push({ row, col, text });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out.sort((a, b) => a.row - b.row || a.col - b.col);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The comment after (or before) `from`, reading the sheet row by row and
|
|
54
|
+
* wrapping at the end, as Excel's Next Comment and Previous Comment do. The
|
|
55
|
+
* cell itself is skipped, so pressing Next on a commented cell moves on;
|
|
56
|
+
* null when the sheet has no comments at all.
|
|
57
|
+
*/
|
|
58
|
+
export function nextComment(notes, from, dir) {
|
|
59
|
+
const all = listComments(notes);
|
|
60
|
+
if (!all.length)
|
|
61
|
+
return null;
|
|
62
|
+
const after = (a, b) => a.row > b.row || (a.row === b.row && a.col > b.col);
|
|
63
|
+
const at = (entry) => ({ row: entry.row, col: entry.col });
|
|
64
|
+
if (dir === 1) {
|
|
65
|
+
const hit = all.find((entry) => after(entry, from));
|
|
66
|
+
return at(hit ?? all[0]);
|
|
67
|
+
}
|
|
68
|
+
for (let i = all.length - 1; i >= 0; i -= 1) {
|
|
69
|
+
if (after(from, all[i]))
|
|
70
|
+
return at(all[i]);
|
|
71
|
+
}
|
|
72
|
+
return at(all[all.length - 1]);
|
|
73
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conditional formatting, Excel's: rules over cells that colour them by
|
|
3
|
+
* what they hold. Highlight Cells Rules (greater than, between, text that
|
|
4
|
+
* contains, duplicates), Top/Bottom Rules (top 10, above average), Data
|
|
5
|
+
* Bars, Color Scales and Icon Sets, each over rectangles that move with
|
|
6
|
+
* an insert or delete.
|
|
7
|
+
*
|
|
8
|
+
* Rules are evaluated over COMPUTED values (what a formula shows, not its
|
|
9
|
+
* text), which is why the model lives here beside the workbook rather than
|
|
10
|
+
* in the grid's own value-driven rules. The statistics a rule needs over
|
|
11
|
+
* its range (min, max, mean, rank, counts) are computed once per repaint by
|
|
12
|
+
* the shell and handed in, so a thousand cells cost one pass.
|
|
13
|
+
*
|
|
14
|
+
* Priority is array order, first rule first, as Excel's Manage Rules lists
|
|
15
|
+
* them: the first rule that decides a property wins it, and a rule with
|
|
16
|
+
* Stop If True stops the rules below it for the cells it matches.
|
|
17
|
+
*/
|
|
18
|
+
import { type CellValue } from './ast.js';
|
|
19
|
+
import type { StructuralEdit } from './refs.js';
|
|
20
|
+
import { type Rect } from './rects.js';
|
|
21
|
+
import type { CellFormatEntry } from './format-store.js';
|
|
22
|
+
export type CfStyle = Pick<CellFormatEntry, 'fill' | 'color' | 'bold' | 'italic' | 'underline' | 'strike' | 'numFmt'>;
|
|
23
|
+
export type CfOperator = 'greater' | 'less' | 'between' | 'notBetween' | 'equal' | 'notEqual' | 'greaterOrEqual' | 'lessOrEqual';
|
|
24
|
+
export type CfTextMatch = 'contains' | 'notContains' | 'beginsWith' | 'endsWith';
|
|
25
|
+
export type CfIconSet = 'arrows' | 'traffic' | 'flags' | 'symbols';
|
|
26
|
+
export type CfScaleColors = readonly [string, string] | readonly [string, string, string];
|
|
27
|
+
export type CfRule = {
|
|
28
|
+
id: string;
|
|
29
|
+
rects: ReadonlyArray<Rect>;
|
|
30
|
+
stopIfTrue?: boolean;
|
|
31
|
+
} & ({
|
|
32
|
+
kind: 'cellIs';
|
|
33
|
+
operator: CfOperator;
|
|
34
|
+
value1: string;
|
|
35
|
+
value2?: string;
|
|
36
|
+
style: CfStyle;
|
|
37
|
+
} | {
|
|
38
|
+
kind: 'text';
|
|
39
|
+
match: CfTextMatch;
|
|
40
|
+
value: string;
|
|
41
|
+
style: CfStyle;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'duplicates';
|
|
44
|
+
unique?: boolean;
|
|
45
|
+
style: CfStyle;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'topBottom';
|
|
48
|
+
top: boolean;
|
|
49
|
+
rank: number;
|
|
50
|
+
percent?: boolean;
|
|
51
|
+
style: CfStyle;
|
|
52
|
+
} | {
|
|
53
|
+
kind: 'average';
|
|
54
|
+
above: boolean;
|
|
55
|
+
style: CfStyle;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'dataBar';
|
|
58
|
+
color: string;
|
|
59
|
+
} | {
|
|
60
|
+
kind: 'colorScale';
|
|
61
|
+
colors: CfScaleColors;
|
|
62
|
+
} | {
|
|
63
|
+
kind: 'iconSet';
|
|
64
|
+
set: CfIconSet;
|
|
65
|
+
});
|
|
66
|
+
export type CfKind = CfRule['kind'];
|
|
67
|
+
/** A rule that carries a style: what the small dialogs make. */
|
|
68
|
+
export type CfStyledRule = Extract<CfRule, {
|
|
69
|
+
style: CfStyle;
|
|
70
|
+
}>;
|
|
71
|
+
/** Omit that keeps a union a union, one member at a time. */
|
|
72
|
+
type DistributiveOmit<T, K extends keyof never> = T extends unknown ? Omit<T, K> : never;
|
|
73
|
+
/** Any rule without its id and rectangles: what a new rule is made from. */
|
|
74
|
+
export type CfRuleBody = DistributiveOmit<CfRule, 'id' | 'rects'>;
|
|
75
|
+
/** A styled rule without its id and rectangles: what the dialog hands back. */
|
|
76
|
+
export type CfBody = DistributiveOmit<CfStyledRule, 'id' | 'rects'>;
|
|
77
|
+
/** The small dialogs, one per ribbon entry. */
|
|
78
|
+
export type CfPreset = 'greater' | 'less' | 'between' | 'equal' | 'text' | 'duplicates' | 'top10' | 'bottom10' | 'aboveAverage' | 'belowAverage';
|
|
79
|
+
/** What one rule knows about the numbers in its rectangles. */
|
|
80
|
+
export type CfStats = {
|
|
81
|
+
/** Numbers, sorted ascending. */
|
|
82
|
+
sorted: number[];
|
|
83
|
+
min: number;
|
|
84
|
+
max: number;
|
|
85
|
+
mean: number;
|
|
86
|
+
/** How often each display text occurs, for Duplicate Values. */
|
|
87
|
+
counts: Map<string, number>;
|
|
88
|
+
};
|
|
89
|
+
/** What the rules say about one cell. */
|
|
90
|
+
export type CfResult = {
|
|
91
|
+
style?: CfStyle;
|
|
92
|
+
/** A bar across the cell, 0..1 of its width. */
|
|
93
|
+
dataBar?: {
|
|
94
|
+
ratio: number;
|
|
95
|
+
color: string;
|
|
96
|
+
};
|
|
97
|
+
/** The icon set and which of its three icons: 0 = the top one. */
|
|
98
|
+
icon?: {
|
|
99
|
+
set: CfIconSet;
|
|
100
|
+
index: 0 | 1 | 2;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
/** How a rule reads the sheet: the shell wires the workbook in. */
|
|
104
|
+
export type CfContext = {
|
|
105
|
+
/** A formula or a literal, evaluated in the sheet. */
|
|
106
|
+
evaluate(text: string): CellValue;
|
|
107
|
+
};
|
|
108
|
+
/** The six "with" styles of Excel's Highlight Cells dialogs. */
|
|
109
|
+
export declare const CF_PRESET_STYLES: ReadonlyArray<{
|
|
110
|
+
id: string;
|
|
111
|
+
label: string;
|
|
112
|
+
style: CfStyle;
|
|
113
|
+
}>;
|
|
114
|
+
export declare const DATA_BAR_COLOR = "#638EC6";
|
|
115
|
+
export declare const COLOR_SCALES: Record<'green-yellow-red' | 'red-yellow-green' | 'green-white' | 'white-red', CfScaleColors>;
|
|
116
|
+
export declare function cfId(): string;
|
|
117
|
+
/**
|
|
118
|
+
* The numbers and the texts a rule's rectangles hold. One pass; the shell
|
|
119
|
+
* caches the result per rule until the next repaint.
|
|
120
|
+
*/
|
|
121
|
+
export declare function ruleStats(rule: CfRule, valueAt: (r: number, c: number) => CellValue, displayAt: (r: number, c: number) => string): CfStats;
|
|
122
|
+
/** The colour a scale gives a position 0..1. */
|
|
123
|
+
export declare function scaleColor(colors: CfScaleColors, t: number): string;
|
|
124
|
+
/** Which of an icon set's three icons a position 0..1 gets: Excel's thirds. */
|
|
125
|
+
export declare function iconIndex(t: number): 0 | 1 | 2;
|
|
126
|
+
/**
|
|
127
|
+
* What the rules say about (r, c). Array order is priority; the first rule
|
|
128
|
+
* that decides a property (the fill, the text colour, the bar, the icon)
|
|
129
|
+
* keeps it; a matching rule with Stop If True ends the walk.
|
|
130
|
+
*/
|
|
131
|
+
export declare function evaluateCf(rules: ReadonlyArray<CfRule>, r: number, c: number, value: CellValue, display: string, statsFor: (rule: CfRule) => CfStats, ctx: CfContext): CfResult | null;
|
|
132
|
+
/** The rules after an insert or delete. */
|
|
133
|
+
export declare function shiftCf(rules: ReadonlyArray<CfRule>, edit: StructuralEdit): CfRule[];
|
|
134
|
+
/** The rules with the rectangles cut out of them: Clear Rules from Selected Cells. */
|
|
135
|
+
export declare function removeCf(rules: ReadonlyArray<CfRule>, rects: ReadonlyArray<Rect>): CfRule[];
|
|
136
|
+
/** The rules touching any of the rectangles. */
|
|
137
|
+
export declare function cfIn(rules: ReadonlyArray<CfRule>, rects: ReadonlyArray<Rect>): CfRule[];
|
|
138
|
+
/** A rule in words, the way Excel's Manage Rules lists it. */
|
|
139
|
+
export declare function describeCf(rule: CfRule): string;
|
|
140
|
+
/** Whether a rule carries a style the dialog can edit. */
|
|
141
|
+
export declare function hasStyle(rule: CfRule): rule is Extract<CfRule, {
|
|
142
|
+
style: CfStyle;
|
|
143
|
+
}>;
|
|
144
|
+
export {};
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conditional formatting, Excel's: rules over cells that colour them by
|
|
3
|
+
* what they hold. Highlight Cells Rules (greater than, between, text that
|
|
4
|
+
* contains, duplicates), Top/Bottom Rules (top 10, above average), Data
|
|
5
|
+
* Bars, Color Scales and Icon Sets, each over rectangles that move with
|
|
6
|
+
* an insert or delete.
|
|
7
|
+
*
|
|
8
|
+
* Rules are evaluated over COMPUTED values (what a formula shows, not its
|
|
9
|
+
* text), which is why the model lives here beside the workbook rather than
|
|
10
|
+
* in the grid's own value-driven rules. The statistics a rule needs over
|
|
11
|
+
* its range (min, max, mean, rank, counts) are computed once per repaint by
|
|
12
|
+
* the shell and handed in, so a thousand cells cost one pass.
|
|
13
|
+
*
|
|
14
|
+
* Priority is array order, first rule first, as Excel's Manage Rules lists
|
|
15
|
+
* them: the first rule that decides a property wins it, and a rule with
|
|
16
|
+
* Stop If True stops the rules below it for the cells it matches.
|
|
17
|
+
*/
|
|
18
|
+
import { isError } from './ast.js';
|
|
19
|
+
import { toText } from './coerce.js';
|
|
20
|
+
import { rectContains, shiftRects, subtractRect, rectsIntersect } from './rects.js';
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Excel's palettes
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/** The six "with" styles of Excel's Highlight Cells dialogs. */
|
|
25
|
+
export const CF_PRESET_STYLES = [
|
|
26
|
+
{ id: 'light-red', label: 'Light Red Fill with Dark Red Text', style: { fill: '#FFC7CE', color: '#9C0006' } },
|
|
27
|
+
{ id: 'yellow', label: 'Yellow Fill with Dark Yellow Text', style: { fill: '#FFEB9C', color: '#9C5700' } },
|
|
28
|
+
{ id: 'green', label: 'Green Fill with Dark Green Text', style: { fill: '#C6EFCE', color: '#006100' } },
|
|
29
|
+
{ id: 'red-fill', label: 'Light Red Fill', style: { fill: '#FFC7CE' } },
|
|
30
|
+
{ id: 'red-text', label: 'Red Text', style: { color: '#9C0006' } },
|
|
31
|
+
];
|
|
32
|
+
export const DATA_BAR_COLOR = '#638EC6';
|
|
33
|
+
export const COLOR_SCALES = {
|
|
34
|
+
'green-yellow-red': ['#63BE7B', '#FFEB84', '#F8696B'],
|
|
35
|
+
'red-yellow-green': ['#F8696B', '#FFEB84', '#63BE7B'],
|
|
36
|
+
'green-white': ['#63BE7B', '#FCFCFF'],
|
|
37
|
+
'white-red': ['#FCFCFF', '#F8696B'],
|
|
38
|
+
};
|
|
39
|
+
let nextId = 1;
|
|
40
|
+
export function cfId() {
|
|
41
|
+
nextId += 1;
|
|
42
|
+
return `cf${Date.now().toString(36)}${nextId}`;
|
|
43
|
+
}
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Statistics
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
/**
|
|
48
|
+
* The numbers and the texts a rule's rectangles hold. One pass; the shell
|
|
49
|
+
* caches the result per rule until the next repaint.
|
|
50
|
+
*/
|
|
51
|
+
export function ruleStats(rule, valueAt, displayAt) {
|
|
52
|
+
const numbers = [];
|
|
53
|
+
const counts = new Map();
|
|
54
|
+
let sum = 0;
|
|
55
|
+
for (const [r1, c1, r2, c2] of rule.rects) {
|
|
56
|
+
for (let r = r1; r <= r2; r += 1) {
|
|
57
|
+
for (let c = c1; c <= c2; c += 1) {
|
|
58
|
+
const v = valueAt(r, c);
|
|
59
|
+
if (typeof v === 'number' && Number.isFinite(v)) {
|
|
60
|
+
numbers.push(v);
|
|
61
|
+
sum += v;
|
|
62
|
+
}
|
|
63
|
+
if (rule.kind === 'duplicates') {
|
|
64
|
+
const shown = displayAt(r, c);
|
|
65
|
+
if (shown !== '')
|
|
66
|
+
counts.set(shown, (counts.get(shown) ?? 0) + 1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
numbers.sort((a, b) => a - b);
|
|
72
|
+
return {
|
|
73
|
+
sorted: numbers,
|
|
74
|
+
min: numbers[0] ?? 0,
|
|
75
|
+
max: numbers[numbers.length - 1] ?? 0,
|
|
76
|
+
mean: numbers.length ? sum / numbers.length : 0,
|
|
77
|
+
counts,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Evaluation
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
function numberOf(text, ctx) {
|
|
84
|
+
const v = ctx.evaluate(text);
|
|
85
|
+
if (isError(v) || typeof v === 'boolean')
|
|
86
|
+
return null;
|
|
87
|
+
const n = typeof v === 'number' ? v : Number(v);
|
|
88
|
+
return Number.isFinite(n) ? n : null;
|
|
89
|
+
}
|
|
90
|
+
function textOf(text, ctx) {
|
|
91
|
+
const t = text.trim();
|
|
92
|
+
if (!t.startsWith('='))
|
|
93
|
+
return t;
|
|
94
|
+
const v = ctx.evaluate(t);
|
|
95
|
+
return isError(v) ? '' : toText(v);
|
|
96
|
+
}
|
|
97
|
+
function cellIs(value, operator, a, b) {
|
|
98
|
+
if (a === null)
|
|
99
|
+
return false;
|
|
100
|
+
switch (operator) {
|
|
101
|
+
case 'greater': return value > a;
|
|
102
|
+
case 'less': return value < a;
|
|
103
|
+
case 'greaterOrEqual': return value >= a;
|
|
104
|
+
case 'lessOrEqual': return value <= a;
|
|
105
|
+
case 'equal': return value === a;
|
|
106
|
+
case 'notEqual': return value !== a;
|
|
107
|
+
case 'between': return b !== null && value >= Math.min(a, b) && value <= Math.max(a, b);
|
|
108
|
+
case 'notBetween': return b !== null && (value < Math.min(a, b) || value > Math.max(a, b));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Whether a styling rule matches the cell. */
|
|
112
|
+
function matches(rule, value, display, stats, ctx) {
|
|
113
|
+
switch (rule.kind) {
|
|
114
|
+
case 'cellIs': {
|
|
115
|
+
const isEquality = rule.operator === 'equal' || rule.operator === 'notEqual';
|
|
116
|
+
const a = numberOf(rule.value1, ctx);
|
|
117
|
+
if (typeof value === 'number' && (a !== null || !isEquality)) {
|
|
118
|
+
return cellIs(value, rule.operator, a, rule.value2 === undefined ? null : numberOf(rule.value2, ctx));
|
|
119
|
+
}
|
|
120
|
+
// Equal to / not equal to compare as text where either side is text,
|
|
121
|
+
// as Excel does: 5 is not equal to 'Paid', and 'paid' is equal to it.
|
|
122
|
+
if (!isEquality)
|
|
123
|
+
return false;
|
|
124
|
+
const same = display !== '' && display.toLowerCase() === textOf(rule.value1, ctx).toLowerCase();
|
|
125
|
+
return rule.operator === 'equal' ? same : display !== '' && !same;
|
|
126
|
+
}
|
|
127
|
+
case 'text': {
|
|
128
|
+
if (display === '')
|
|
129
|
+
return false;
|
|
130
|
+
const hay = display.toLowerCase();
|
|
131
|
+
const needle = textOf(rule.value, ctx).toLowerCase();
|
|
132
|
+
if (needle === '')
|
|
133
|
+
return false;
|
|
134
|
+
switch (rule.match) {
|
|
135
|
+
case 'contains': return hay.includes(needle);
|
|
136
|
+
case 'notContains': return !hay.includes(needle);
|
|
137
|
+
case 'beginsWith': return hay.startsWith(needle);
|
|
138
|
+
case 'endsWith': return hay.endsWith(needle);
|
|
139
|
+
default: return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
case 'duplicates': {
|
|
143
|
+
if (display === '')
|
|
144
|
+
return false;
|
|
145
|
+
const n = stats.counts.get(display) ?? 0;
|
|
146
|
+
return rule.unique ? n === 1 : n > 1;
|
|
147
|
+
}
|
|
148
|
+
case 'topBottom': {
|
|
149
|
+
if (typeof value !== 'number' || !stats.sorted.length)
|
|
150
|
+
return false;
|
|
151
|
+
const count = rule.percent
|
|
152
|
+
? Math.max(1, Math.round((stats.sorted.length * rule.rank) / 100))
|
|
153
|
+
: rule.rank;
|
|
154
|
+
if (count <= 0)
|
|
155
|
+
return false;
|
|
156
|
+
// The cut is the count-th value from the top (or bottom); ties keep
|
|
157
|
+
// every cell at that value in, as Excel's do.
|
|
158
|
+
const sorted = stats.sorted;
|
|
159
|
+
const cut = rule.top
|
|
160
|
+
? sorted[Math.max(sorted.length - count, 0)]
|
|
161
|
+
: sorted[Math.min(count - 1, sorted.length - 1)];
|
|
162
|
+
return rule.top ? value >= cut : value <= cut;
|
|
163
|
+
}
|
|
164
|
+
case 'average': {
|
|
165
|
+
if (typeof value !== 'number' || !stats.sorted.length)
|
|
166
|
+
return false;
|
|
167
|
+
return rule.above ? value > stats.mean : value < stats.mean;
|
|
168
|
+
}
|
|
169
|
+
default:
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* A data bar's share of the cell, 0..1. Excel measures from zero when the
|
|
175
|
+
* range is non-negative (10, 20, 40 draw a quarter, a half and the whole
|
|
176
|
+
* width), so the smallest value keeps a bar; a range with negatives runs
|
|
177
|
+
* from its minimum instead, since there is no negative axis here.
|
|
178
|
+
*/
|
|
179
|
+
function barRatio(value, stats) {
|
|
180
|
+
const lo = Math.min(0, stats.min);
|
|
181
|
+
const hi = Math.max(0, stats.max);
|
|
182
|
+
if (hi === lo)
|
|
183
|
+
return 0;
|
|
184
|
+
return Math.min(1, Math.max(0, (value - lo) / (hi - lo)));
|
|
185
|
+
}
|
|
186
|
+
/** Where a number sits in a range, 0..1; 0.5 for a flat range. */
|
|
187
|
+
function ratioOf(value, stats) {
|
|
188
|
+
if (stats.max === stats.min)
|
|
189
|
+
return 0.5;
|
|
190
|
+
return Math.min(1, Math.max(0, (value - stats.min) / (stats.max - stats.min)));
|
|
191
|
+
}
|
|
192
|
+
/** Linear interpolate two hex colours. */
|
|
193
|
+
function lerp(a, b, t) {
|
|
194
|
+
const pa = parseHex(a);
|
|
195
|
+
const pb = parseHex(b);
|
|
196
|
+
if (!pa || !pb)
|
|
197
|
+
return a;
|
|
198
|
+
const k = Math.min(1, Math.max(0, t));
|
|
199
|
+
const ch = (i) => Math.round(pa[i] + (pb[i] - pa[i]) * k).toString(16).padStart(2, '0');
|
|
200
|
+
return `#${ch(0)}${ch(1)}${ch(2)}`;
|
|
201
|
+
}
|
|
202
|
+
function parseHex(hex) {
|
|
203
|
+
const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
|
|
204
|
+
if (!m)
|
|
205
|
+
return null;
|
|
206
|
+
const n = parseInt(m[1], 16);
|
|
207
|
+
return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
|
|
208
|
+
}
|
|
209
|
+
/** The colour a scale gives a position 0..1. */
|
|
210
|
+
export function scaleColor(colors, t) {
|
|
211
|
+
if (colors.length === 2)
|
|
212
|
+
return lerp(colors[0], colors[1], t);
|
|
213
|
+
return t <= 0.5 ? lerp(colors[0], colors[1], t * 2) : lerp(colors[1], colors[2], (t - 0.5) * 2);
|
|
214
|
+
}
|
|
215
|
+
/** Which of an icon set's three icons a position 0..1 gets: Excel's thirds. */
|
|
216
|
+
export function iconIndex(t) {
|
|
217
|
+
return t >= 2 / 3 ? 0 : t >= 1 / 3 ? 1 : 2;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* What the rules say about (r, c). Array order is priority; the first rule
|
|
221
|
+
* that decides a property (the fill, the text colour, the bar, the icon)
|
|
222
|
+
* keeps it; a matching rule with Stop If True ends the walk.
|
|
223
|
+
*/
|
|
224
|
+
export function evaluateCf(rules, r, c, value, display, statsFor, ctx) {
|
|
225
|
+
let out = null;
|
|
226
|
+
for (const rule of rules) {
|
|
227
|
+
if (!rule.rects.some((rect) => rectContains(rect, r, c)))
|
|
228
|
+
continue;
|
|
229
|
+
let hit = false;
|
|
230
|
+
if (rule.kind === 'dataBar') {
|
|
231
|
+
if (typeof value === 'number' && !(out?.dataBar)) {
|
|
232
|
+
const stats = statsFor(rule);
|
|
233
|
+
out = { ...(out ?? {}), dataBar: { ratio: barRatio(value, stats), color: rule.color } };
|
|
234
|
+
hit = true;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else if (rule.kind === 'colorScale') {
|
|
238
|
+
const current = out ?? {};
|
|
239
|
+
if (typeof value === 'number' && current.style?.fill === undefined) {
|
|
240
|
+
const stats = statsFor(rule);
|
|
241
|
+
out = { ...current, style: { ...(current.style ?? {}), fill: scaleColor(rule.colors, ratioOf(value, stats)) } };
|
|
242
|
+
hit = true;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
else if (rule.kind === 'iconSet') {
|
|
246
|
+
if (typeof value === 'number' && !(out?.icon)) {
|
|
247
|
+
const stats = statsFor(rule);
|
|
248
|
+
out = { ...(out ?? {}), icon: { set: rule.set, index: iconIndex(ratioOf(value, stats)) } };
|
|
249
|
+
hit = true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else if (hasStyle(rule) && matches(rule, value, display, statsFor(rule), ctx)) {
|
|
253
|
+
const style = { ...(out?.style ?? {}) };
|
|
254
|
+
const own = rule.style;
|
|
255
|
+
for (const key of Object.keys(own)) {
|
|
256
|
+
if (style[key] === undefined && own[key] !== undefined)
|
|
257
|
+
style[key] = own[key];
|
|
258
|
+
}
|
|
259
|
+
out = { ...(out ?? {}), style };
|
|
260
|
+
hit = true;
|
|
261
|
+
}
|
|
262
|
+
if (hit && rule.stopIfTrue)
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
return out;
|
|
266
|
+
}
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
// Bookkeeping
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
/** The rules after an insert or delete. */
|
|
271
|
+
export function shiftCf(rules, edit) {
|
|
272
|
+
return shiftRects(rules, edit);
|
|
273
|
+
}
|
|
274
|
+
/** The rules with the rectangles cut out of them: Clear Rules from Selected Cells. */
|
|
275
|
+
export function removeCf(rules, rects) {
|
|
276
|
+
const out = [];
|
|
277
|
+
for (const rule of rules) {
|
|
278
|
+
let kept = [...rule.rects];
|
|
279
|
+
for (const hole of rects)
|
|
280
|
+
kept = kept.flatMap((rect) => subtractRect(rect, hole));
|
|
281
|
+
if (kept.length)
|
|
282
|
+
out.push({ ...rule, rects: kept });
|
|
283
|
+
}
|
|
284
|
+
return out;
|
|
285
|
+
}
|
|
286
|
+
/** The rules touching any of the rectangles. */
|
|
287
|
+
export function cfIn(rules, rects) {
|
|
288
|
+
return rules.filter((rule) => rule.rects.some((a) => rects.some((b) => rectsIntersect(a, b))));
|
|
289
|
+
}
|
|
290
|
+
const OPERATOR_WORDS = {
|
|
291
|
+
greater: 'greater than', less: 'less than', between: 'between', notBetween: 'not between',
|
|
292
|
+
equal: 'equal to', notEqual: 'not equal to', greaterOrEqual: 'greater than or equal to', lessOrEqual: 'less than or equal to',
|
|
293
|
+
};
|
|
294
|
+
const MATCH_WORDS = {
|
|
295
|
+
contains: 'contains', notContains: 'does not contain', beginsWith: 'begins with', endsWith: 'ends with',
|
|
296
|
+
};
|
|
297
|
+
/** A rule in words, the way Excel's Manage Rules lists it. */
|
|
298
|
+
export function describeCf(rule) {
|
|
299
|
+
switch (rule.kind) {
|
|
300
|
+
case 'cellIs':
|
|
301
|
+
return rule.operator === 'between' || rule.operator === 'notBetween'
|
|
302
|
+
? `Cell Value ${OPERATOR_WORDS[rule.operator]} ${rule.value1} and ${rule.value2 ?? ''}`
|
|
303
|
+
: `Cell Value ${OPERATOR_WORDS[rule.operator]} ${rule.value1}`;
|
|
304
|
+
case 'text': return `Cell Value ${MATCH_WORDS[rule.match]} '${rule.value}'`;
|
|
305
|
+
case 'duplicates': return rule.unique ? 'Unique Values' : 'Duplicate Values';
|
|
306
|
+
case 'topBottom': return `${rule.top ? 'Top' : 'Bottom'} ${rule.rank}${rule.percent ? '%' : ''}`;
|
|
307
|
+
case 'average': return rule.above ? 'Above Average' : 'Below Average';
|
|
308
|
+
case 'dataBar': return 'Data Bar';
|
|
309
|
+
case 'colorScale': return rule.colors.length === 3 ? 'Graded Color Scale' : 'Two-Color Scale';
|
|
310
|
+
case 'iconSet': return 'Icon Set';
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/** Whether a rule carries a style the dialog can edit. */
|
|
314
|
+
export function hasStyle(rule) {
|
|
315
|
+
return 'style' in rule;
|
|
316
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency graph, so a recalc costs what the edit actually affects.
|
|
3
|
+
*
|
|
4
|
+
* The demo engines call `computeSheet`, which resolves every cell on every
|
|
5
|
+
* keystroke. On a small budget sheet nobody notices; on demo 211's 360-row
|
|
6
|
+
* amortisation schedule, typing one digit in an input cell walks every cell in
|
|
7
|
+
* the sheet and re-parses every formula among them.
|
|
8
|
+
*
|
|
9
|
+
* This tracks which cells each formula reads, inverts that into "who reads
|
|
10
|
+
* me", and walks forward from an edit in topological order.
|
|
11
|
+
*
|
|
12
|
+
* Cycles are reported rather than thrown. A cycle is a normal thing to type on
|
|
13
|
+
* the way to something correct, and every cell in one shows #CYCLE! while the
|
|
14
|
+
* rest of the sheet keeps working.
|
|
15
|
+
*/
|
|
16
|
+
import { type Node } from './ast.js';
|
|
17
|
+
export type CellKey = string;
|
|
18
|
+
/**
|
|
19
|
+
* Cells are keyed "row col sheet", in that order deliberately.
|
|
20
|
+
*
|
|
21
|
+
* Row and column are numbers and contain no separator, so the first two fields
|
|
22
|
+
* are unambiguous and EVERYTHING after the second space is the sheet name.
|
|
23
|
+
* Putting the sheet first would let a name like `Price list` collide with a
|
|
24
|
+
* different cell, and a ':' or '!' separator has the same problem the moment
|
|
25
|
+
* someone names a sheet after a range.
|
|
26
|
+
*/
|
|
27
|
+
export declare function cellKey(sheet: string | null, row: number, col: number): CellKey;
|
|
28
|
+
export declare function parseCellKey(key: CellKey): {
|
|
29
|
+
sheet: string | null;
|
|
30
|
+
row: number;
|
|
31
|
+
col: number;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Every cell a formula reads. A range contributes each cell inside it, which
|
|
35
|
+
* is why `lastRow` is needed: a whole-column reference has no upper bound of
|
|
36
|
+
* its own.
|
|
37
|
+
*/
|
|
38
|
+
export declare function precedentsOf(ast: Node, self: {
|
|
39
|
+
sheet: string | null;
|
|
40
|
+
}, lastRow: (sheet: string | null) => number,
|
|
41
|
+
/**
|
|
42
|
+
* The reference behind a defined name. Without it a formula that reads
|
|
43
|
+
* `=Subtotal*Tax` records no precedents at all, so editing the cell behind
|
|
44
|
+
* `Tax` leaves the formula showing its old value until something else
|
|
45
|
+
* forces a recalculation.
|
|
46
|
+
*/
|
|
47
|
+
resolveName?: (name: string) => Node | null, depth?: number): CellKey[];
|
|
48
|
+
export type DependencyGraph = {
|
|
49
|
+
/** Record (or clear, with null) what one cell reads. */
|
|
50
|
+
setPrecedents(cell: CellKey, precedents: ReadonlyArray<CellKey> | null): void;
|
|
51
|
+
/** Cells that must recompute after `changed`, ordered so every cell comes
|
|
52
|
+
* after everything it reads. Excludes the changed cells themselves. */
|
|
53
|
+
dirtyFrom(changed: ReadonlyArray<CellKey>): CellKey[];
|
|
54
|
+
/** Every cell taking part in a dependency cycle. */
|
|
55
|
+
cycles(): CellKey[];
|
|
56
|
+
/** Direct readers of a cell. */
|
|
57
|
+
dependentsOf(cell: CellKey): CellKey[];
|
|
58
|
+
clear(): void;
|
|
59
|
+
};
|
|
60
|
+
export declare function createDependencyGraph(): DependencyGraph;
|