@svgrid/enterprise 3.0.2 → 3.0.3
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/LICENSE +94 -24
- package/README.md +36 -4
- package/dist/SvAdvancedFilter.svelte +1 -1
- package/dist/SvAlertsManager.svelte +2 -1
- package/dist/SvBoard.svelte +2 -1
- package/dist/SvExportMenu.svelte +4 -1
- package/dist/SvExportMenu.svelte.d.ts +0 -13
- package/dist/SvExpressionEditor.svelte +3 -3
- package/dist/SvFormulaBar.svelte +94 -20
- package/dist/SvFormulaBar.svelte.d.ts +7 -0
- package/dist/SvGridAlerts.svelte +49 -9
- package/dist/SvGridBoard.svelte +13 -8
- package/dist/SvGridBulkEditDrawer.svelte +26 -2
- package/dist/SvGridEditPanel.svelte +3 -0
- package/dist/SvGridScheduler.svelte +69 -40
- package/dist/SvGridSelectionBar.svelte +10 -3
- package/dist/SvPivotDesigner.svelte +198 -40
- package/dist/SvPivotDesigner.svelte.d.ts +27 -20
- package/dist/SvSheet.svelte +4043 -243
- package/dist/SvSheet.svelte.d.ts +76 -3
- package/dist/SvSheetChartSetup.svelte +151 -0
- package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
- package/dist/SvSheetComment.svelte +216 -31
- package/dist/SvSheetComment.svelte.d.ts +11 -11
- package/dist/SvSheetConditionalFormat.svelte +28 -31
- package/dist/SvSheetDataValidation.svelte +66 -42
- package/dist/SvSheetEditRanges.svelte +217 -0
- package/dist/SvSheetEditRanges.svelte.d.ts +15 -0
- package/dist/SvSheetErrors.svelte +125 -0
- package/dist/SvSheetErrors.svelte.d.ts +20 -0
- package/dist/SvSheetEvaluate.svelte +133 -0
- package/dist/SvSheetEvaluate.svelte.d.ts +15 -0
- package/dist/SvSheetFilterMenu.svelte +137 -34
- package/dist/SvSheetFilterMenu.svelte.d.ts +5 -0
- package/dist/SvSheetFindReplace.svelte +19 -19
- package/dist/SvSheetFormatCells.svelte +125 -81
- package/dist/SvSheetGoalSeek.svelte +17 -16
- package/dist/SvSheetInsertFunction.svelte +15 -13
- package/dist/SvSheetIteration.svelte +81 -0
- package/dist/SvSheetIteration.svelte.d.ts +10 -0
- package/dist/SvSheetLink.svelte +99 -0
- package/dist/SvSheetLink.svelte.d.ts +17 -0
- package/dist/SvSheetListPicker.svelte +4 -2
- package/dist/SvSheetListPicker.svelte.d.ts +0 -6
- package/dist/SvSheetManageRules.svelte +20 -18
- package/dist/SvSheetNameManager.svelte +17 -15
- package/dist/SvSheetPageSetup.svelte +159 -0
- package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
- package/dist/SvSheetPasteSpecial.svelte +22 -20
- package/dist/SvSheetPivot.svelte +220 -0
- package/dist/SvSheetPivot.svelte.d.ts +21 -0
- package/dist/SvSheetProtectSheet.svelte +81 -0
- package/dist/SvSheetProtectSheet.svelte.d.ts +11 -0
- package/dist/SvSheetRemoveDuplicates.svelte +13 -10
- package/dist/SvSheetRibbon.svelte +104 -51
- package/dist/SvSheetSizeDialog.svelte +4 -2
- package/dist/SvSheetSort.svelte +218 -0
- package/dist/SvSheetSort.svelte.d.ts +28 -0
- package/dist/SvSheetSparklines.svelte +135 -0
- package/dist/SvSheetSparklines.svelte.d.ts +14 -0
- package/dist/SvSheetTable.svelte +160 -0
- package/dist/SvSheetTable.svelte.d.ts +24 -0
- package/dist/SvSheetTabs.svelte +161 -31
- package/dist/SvSheetTabs.svelte.d.ts +22 -8
- package/dist/SvSheetTextToColumns.svelte +20 -20
- package/dist/SvSheetValidationAlert.svelte +8 -6
- package/dist/advanced-filter-enable.js +1 -1
- package/dist/alerts/alert-engine.d.ts +6 -0
- package/dist/alerts/alert-engine.js +21 -4
- package/dist/alerts/alert-formats.js +2 -0
- package/dist/alerts/alert-types.d.ts +1 -1
- package/dist/alerts.d.ts +1 -1
- package/dist/alerts.js +2 -2
- package/dist/board.js +2 -2
- package/dist/bulk-edit.d.ts +3 -1
- package/dist/bulk-edit.js +1 -1
- package/dist/cdn/svgrid-enterprise.svelte-external.js +39827 -16429
- package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
- package/dist/designer/assets/{SvChartMenu-D9hEeHar.js → SvChartMenu-BDoeqGz6.js} +1 -1
- package/dist/designer/assets/{SvDateTimePicker-DARvKUL2.js → SvDateTimePicker-DCPg7WGN.js} +1 -1
- package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
- package/dist/designer/assets/{SvGridChart-B8j1SSy3.js → SvGridChart-Cy1ATrWh.js} +2 -2
- package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
- package/dist/designer/assets/{SvGridChartPanel-pT6ITc2P.js → SvGridChartPanel-CATdVc9X.js} +3 -3
- package/dist/designer/assets/{SvGridChartView-bg281UA1.js → SvGridChartView-CmsZtCED.js} +1 -1
- package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
- package/dist/designer/assets/{SvTabs-UFCMTHXS.js → SvTabs-2mHC6oaz.js} +1 -1
- package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
- package/dist/designer/assets/{chart-cIPUsbM5.js → chart-Cn7MnNqA.js} +1 -1
- package/dist/designer/assets/{chart-panel-messages-DtTxpBUU.js → chart-panel-messages-Dz7PTIqT.js} +1 -1
- package/dist/designer/assets/{chart-summary-Czu_5epb.js → chart-summary-BD1qYB2R.js} +1 -1
- package/dist/designer/assets/{chart-trend-D5I5VEe8.js → chart-trend-B8xr5LuD.js} +1 -1
- package/dist/designer/assets/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
- package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
- package/dist/designer/assets/{focus-trap-CAreAhlU.js → focus-trap-V2-6Fy9I.js} +1 -1
- package/dist/designer/assets/{index-DwU7CAMm.js → index-D5bVbuzI.js} +317 -315
- package/dist/designer/assets/index-_JVFxt02.css +1 -0
- package/dist/designer/assets/row-resize-BInFWCpr.js +1 -0
- package/dist/designer/assets/server-block-cache-CXJKkJpy.js +1 -0
- package/dist/designer/assets/src-DUQ4xE3x.js +58 -0
- package/dist/designer/assets/validate-C3B8QKsM.js +1 -0
- package/dist/designer/index.html +17 -16
- package/dist/export-pdf.d.ts +75 -0
- package/dist/export-pdf.js +216 -15
- package/dist/export.js +10 -2
- package/dist/gantt/SvGridGantt.svelte +2890 -0
- package/dist/gantt/SvGridGantt.svelte.d.ts +30 -0
- package/dist/gantt/gantt-config.d.ts +73 -0
- package/dist/gantt/gantt-config.js +1 -0
- package/dist/gantt/gantt-critical-path.d.ts +67 -0
- package/dist/gantt/gantt-critical-path.js +207 -0
- package/dist/gantt/gantt-model.d.ts +257 -0
- package/dist/gantt/gantt-model.js +651 -0
- package/dist/gantt/gantt-resources.d.ts +59 -0
- package/dist/gantt/gantt-resources.js +71 -0
- package/dist/gantt/gantt.d.ts +7 -0
- package/dist/gantt/gantt.js +36 -0
- package/dist/gantt/index.d.ts +15 -0
- package/dist/gantt/index.js +22 -0
- package/dist/gantt/timeline-arrows.d.ts +102 -0
- package/dist/gantt/timeline-arrows.js +181 -0
- package/dist/import.d.ts +2 -2
- package/dist/import.js +1 -1
- package/dist/index.d.ts +34 -7
- package/dist/index.js +44 -7
- package/dist/install.js +8 -1
- package/dist/license-core.d.ts +17 -1
- package/dist/license-core.js +16 -5
- package/dist/license.d.ts +18 -2
- package/dist/license.js +71 -6
- package/dist/node/studio.js +140 -8
- package/dist/pivot-enable.js +2 -2
- package/dist/scheduler-dependencies.d.ts +35 -0
- package/dist/scheduler-dependencies.js +36 -1
- package/dist/scheduler.js +2 -2
- package/dist/selection-bar.js +2 -2
- package/dist/server/SvGroupCell.svelte +213 -0
- package/dist/server/SvGroupCell.svelte.d.ts +62 -0
- package/dist/server/SvRowGroupPanel.svelte +322 -0
- package/dist/server/SvRowGroupPanel.svelte.d.ts +37 -0
- package/dist/server/enable.d.ts +17 -0
- package/dist/server/enable.js +49 -0
- package/dist/server/index.d.ts +22 -0
- package/dist/server/index.js +24 -0
- package/dist/server/messages.d.ts +45 -0
- package/dist/server/messages.js +35 -0
- package/dist/server/server-group-model.d.ts +104 -0
- package/dist/server/server-group-model.js +272 -0
- package/dist/server/server-pivot.d.ts +46 -0
- package/dist/server/server-pivot.js +57 -0
- package/dist/server/server-row-model.d.ts +547 -0
- package/dist/server/server-row-model.js +1551 -0
- package/dist/server/server-selection.d.ts +99 -0
- package/dist/server/server-selection.js +215 -0
- package/dist/server/svgrid-adapter.d.ts +155 -0
- package/dist/server/svgrid-adapter.js +202 -0
- package/dist/sheet/ast.d.ts +45 -1
- package/dist/sheet/ast.js +14 -0
- package/dist/sheet/auto-filter.d.ts +58 -4
- package/dist/sheet/auto-filter.js +159 -11
- package/dist/sheet/autocomplete.d.ts +9 -0
- package/dist/sheet/autocomplete.js +90 -4
- package/dist/sheet/cell-images.d.ts +39 -0
- package/dist/sheet/cell-images.js +90 -0
- package/dist/sheet/cell-types.d.ts +58 -0
- package/dist/sheet/cell-types.js +96 -0
- package/dist/sheet/coerce.d.ts +40 -0
- package/dist/sheet/coerce.js +170 -3
- package/dist/sheet/comments.d.ts +43 -9
- package/dist/sheet/comments.js +85 -27
- package/dist/sheet/conditional-formats.d.ts +29 -6
- package/dist/sheet/conditional-formats.js +37 -12
- package/dist/sheet/csv.d.ts +32 -0
- package/dist/sheet/csv.js +158 -0
- package/dist/sheet/culture.d.ts +87 -0
- package/dist/sheet/culture.js +247 -0
- package/dist/sheet/delta.d.ts +102 -0
- package/dist/sheet/delta.js +203 -0
- package/dist/sheet/deps.d.ts +45 -1
- package/dist/sheet/deps.js +77 -2
- package/dist/sheet/document.d.ts +106 -4
- package/dist/sheet/document.js +204 -3
- package/dist/sheet/engine.d.ts +67 -0
- package/dist/sheet/engine.js +19 -0
- package/dist/sheet/entry.d.ts +8 -4
- package/dist/sheet/entry.js +171 -21
- package/dist/sheet/error-check.d.ts +49 -0
- package/dist/sheet/error-check.js +83 -0
- package/dist/sheet/evaluate-steps.d.ts +48 -0
- package/dist/sheet/evaluate-steps.js +196 -0
- package/dist/sheet/evaluate.d.ts +67 -0
- package/dist/sheet/evaluate.js +725 -13
- package/dist/sheet/filter-files.d.ts +37 -0
- package/dist/sheet/filter-files.js +465 -0
- package/dist/sheet/format-store.d.ts +15 -0
- package/dist/sheet/format-store.js +11 -1
- package/dist/sheet/from-rows.d.ts +14 -0
- package/dist/sheet/from-rows.js +50 -0
- package/dist/sheet/function-catalog.d.ts +1 -1
- package/dist/sheet/function-catalog.js +296 -5
- package/dist/sheet/functions.js +363 -91
- package/dist/sheet/index.d.ts +35 -8
- package/dist/sheet/index.js +35 -8
- package/dist/sheet/links.d.ts +57 -0
- package/dist/sheet/links.js +174 -0
- package/dist/sheet/messages.d.ts +778 -0
- package/dist/sheet/messages.js +806 -0
- package/dist/sheet/number-format.d.ts +52 -5
- package/dist/sheet/number-format.js +465 -68
- package/dist/sheet/objects.d.ts +106 -0
- package/dist/sheet/objects.js +149 -0
- package/dist/sheet/ods-document.d.ts +44 -0
- package/dist/sheet/ods-document.js +1275 -0
- package/dist/sheet/open-file.d.ts +26 -0
- package/dist/sheet/open-file.js +56 -0
- package/dist/sheet/outline.d.ts +82 -0
- package/dist/sheet/outline.js +228 -0
- package/dist/sheet/packs/array.d.ts +16 -0
- package/dist/sheet/packs/array.js +172 -0
- package/dist/sheet/packs/database.d.ts +42 -0
- package/dist/sheet/packs/database.js +142 -0
- package/dist/sheet/packs/engineering.d.ts +2 -0
- package/dist/sheet/packs/engineering.js +296 -0
- package/dist/sheet/packs/financial.d.ts +5 -0
- package/dist/sheet/packs/financial.js +220 -0
- package/dist/sheet/packs/math-stats.d.ts +2 -0
- package/dist/sheet/packs/math-stats.js +372 -0
- package/dist/sheet/packs/special.d.ts +44 -0
- package/dist/sheet/packs/special.js +187 -0
- package/dist/sheet/packs/stats-dist.d.ts +2 -0
- package/dist/sheet/packs/stats-dist.js +785 -0
- package/dist/sheet/packs/text-date.d.ts +2 -0
- package/dist/sheet/packs/text-date.js +332 -0
- package/dist/sheet/packs/trig.d.ts +2 -0
- package/dist/sheet/packs/trig.js +73 -0
- package/dist/sheet/page-setup.d.ts +73 -0
- package/dist/sheet/page-setup.js +73 -0
- package/dist/sheet/parse.js +42 -10
- package/dist/sheet/paste-special.d.ts +22 -0
- package/dist/sheet/paste-special.js +14 -5
- package/dist/sheet/pivot-range.d.ts +160 -0
- package/dist/sheet/pivot-range.js +333 -0
- package/dist/sheet/presence.d.ts +73 -0
- package/dist/sheet/presence.js +79 -0
- package/dist/sheet/print.d.ts +104 -0
- package/dist/sheet/print.js +169 -0
- package/dist/sheet/protection.d.ts +55 -1
- package/dist/sheet/protection.js +55 -2
- package/dist/sheet/rects.d.ts +1 -1
- package/dist/sheet/refs.d.ts +48 -0
- package/dist/sheet/refs.js +155 -8
- package/dist/sheet/ribbon-icons.d.ts +1 -1
- package/dist/sheet/ribbon-icons.js +186 -0
- package/dist/sheet/ribbon.d.ts +1 -1
- package/dist/sheet/ribbon.js +324 -23
- package/dist/sheet/sheet-kinds.d.ts +74 -0
- package/dist/sheet/sheet-kinds.js +91 -0
- package/dist/sheet/shortcuts.d.ts +13 -3
- package/dist/sheet/shortcuts.js +63 -12
- package/dist/sheet/sort.d.ts +51 -0
- package/dist/sheet/sort.js +107 -0
- package/dist/sheet/sparklines.d.ts +111 -0
- package/dist/sheet/sparklines.js +204 -0
- package/dist/sheet/table-styles.d.ts +74 -0
- package/dist/sheet/table-styles.js +152 -0
- package/dist/sheet/tables.d.ts +19 -0
- package/dist/sheet/tables.js +31 -0
- package/dist/sheet/tokenize.d.ts +18 -1
- package/dist/sheet/tokenize.js +60 -9
- package/dist/sheet/validation.d.ts +16 -0
- package/dist/sheet/validation.js +37 -0
- package/dist/sheet/workbook.d.ts +148 -3
- package/dist/sheet/workbook.js +742 -31
- package/dist/sheet/xls-cfb.d.ts +32 -0
- package/dist/sheet/xls-cfb.js +290 -0
- package/dist/sheet/xls-document.d.ts +10 -0
- package/dist/sheet/xls-document.js +1243 -0
- package/dist/sheet/xls-formula.d.ts +40 -0
- package/dist/sheet/xls-formula.js +569 -0
- package/dist/sheet/xlsx-document.d.ts +108 -0
- package/dist/sheet/xlsx-document.js +1849 -0
- package/dist/sheet/xlsx-drawing.d.ts +99 -0
- package/dist/sheet/xlsx-drawing.js +420 -0
- package/dist/sheet-enable.js +6 -7
- package/dist/sheet-text.d.ts +7 -0
- package/dist/sheet-text.js +29 -0
- package/dist/sources/auth-supabase.js +2 -2
- package/dist/sources/realtime-supabase.js +2 -2
- package/dist/sources/rest.d.ts +6 -2
- package/dist/sources/rest.js +42 -7
- package/dist/sources/supabase.d.ts +10 -1
- package/dist/sources/supabase.js +73 -40
- package/dist/studio/emit-project.js +14 -1
- package/dist/studio/index.js +1 -1
- package/dist/studio/project.d.ts +11 -2
- package/dist/studio/project.js +5 -2
- package/dist/studio/ui-components.generated.js +107 -2
- package/dist/sveltekit/in-memory.d.ts +2 -2
- package/dist/sveltekit/in-memory.js +125 -4
- package/dist/sveltekit/index.d.ts +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/dist/sveltekit/query-plan.d.ts +50 -4
- package/dist/sveltekit/query-plan.js +25 -3
- package/dist/sveltekit/sql-source.d.ts +6 -0
- package/dist/sveltekit/sql-source.js +34 -6
- package/dist/sveltekit/sql.d.ts +31 -0
- package/dist/sveltekit/sql.js +135 -25
- package/dist/sveltekit/transport.d.ts +10 -2
- package/dist/sveltekit/transport.js +30 -6
- package/dist/upgrade-prompt.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/watermark.js +35 -2
- package/dist/wc/GridMenus-By9vPuq0.js +1088 -0
- package/dist/wc/SvChartMenu-CQNrQGT2.js +308 -0
- package/dist/wc/SvDateRangeInput-DR6m7bSM.js +199 -0
- package/dist/wc/SvDateTimePicker-D-vRnaMo.js +771 -0
- package/dist/wc/SvField-B_kurx_P.js +149 -0
- package/dist/wc/SvGrid.helpers-BdVDtjUm.js +135 -0
- package/dist/wc/SvGridCellEditor-Bnf1Kr5C.js +560 -0
- package/dist/wc/SvGridChart-BqUJh2pG.js +3572 -0
- package/dist/wc/SvGridChartBuilder-CGycC5cn.js +988 -0
- package/dist/wc/SvGridChartPanel-CRnizsHD.js +1746 -0
- package/dist/wc/SvGridChartView-D1pa_xMy.js +47 -0
- package/dist/wc/SvGridDropdown-45WsObLL.js +259 -0
- package/dist/wc/SvModal-DrfOYYyX.js +189 -0
- package/dist/wc/cell-formatting-CBfgahv1.js +86 -0
- package/dist/wc/chart-6OXlybVT.js +4341 -0
- package/dist/wc/chart-export-CeSADGfi.js +135 -0
- package/dist/wc/chart-export-pdf-BGko7MER.js +104 -0
- package/dist/wc/chart-summary-2m3ia1-n.js +137 -0
- package/dist/wc/chart-trend-CQOQtTMl.js +50 -0
- package/dist/wc/chart-validate-CD6ptiwg.js +180 -0
- package/dist/wc/client-DQIzjDBG.js +3064 -0
- package/dist/wc/column-resize-DUPgynvc.js +101 -0
- package/dist/wc/date-format-DS-z_h9v.js +1130 -0
- package/dist/wc/dismissable-CQ6XFXsk.js +45 -0
- package/dist/wc/editor-contract-peBDxir_.js +22 -0
- package/dist/wc/editor-registry-DxGKqcvx.js +24 -0
- package/dist/wc/focus-trap-Dbb2tJxb.js +65 -0
- package/dist/wc/list-option-DrRyivWp.js +82 -0
- package/dist/wc/popover-WsGlvtQv.js +69 -0
- package/dist/wc/positioning-BiKLfu1E.js +112 -0
- package/dist/wc/react.d.ts +41 -0
- package/dist/wc/react.js +90 -0
- package/dist/wc/rolldown-runtime-Dy4uBu1J.js +11 -0
- package/dist/wc/row-drag-touch-CycRR65n.js +93 -0
- package/dist/wc/row-resize-limG_N1z.js +111 -0
- package/dist/wc/sv-sheet-element.d.ts +97 -0
- package/dist/wc/sv-sheet-element.js +44213 -0
- package/dist/wc/svelte-virtualizer.svelte-CXtQy2TQ.js +530 -0
- package/dist/wc/validate-BqDthkNr.js +88 -0
- package/dist/wc/vue.d.ts +31 -0
- package/dist/wc/vue.js +75 -0
- package/package.json +30 -5
- package/dist/designer/assets/GridMenus-BlsvL_aU.js +0 -8
- package/dist/designer/assets/SvGridCellEditor-C7uQXYds.js +0 -4
- package/dist/designer/assets/SvGridChartBuilder-kvyIU_Rl.js +0 -1
- package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
- package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
- package/dist/designer/assets/index-CMFgAoVV.css +0 -1
- package/dist/designer/assets/row-resize-DLktcqUK.js +0 -1
- package/dist/designer/assets/src-EdI3Xqds.js +0 -58
- package/dist/designer/assets/validate-h-aslRV9.js +0 -1
package/dist/sheet/ribbon.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { applyFormat, toggleFormat, preset, autoSum, structural, clearFormats, getFormatTarget, getWorkbook, withFormatUndo, nudgeFontSize, activeEntry, FONT_SIZES, DEFAULT_FONT_SIZE, applyBorders, formatAllowed, raiseRibbonAction, } from './shortcuts.js';
|
|
1
|
+
import { applyFormat, toggleFormat, preset, autoSum, structural, clearFormats, newSheet, getFormatTarget, getWorkbook, withFormatUndo, nudgeFontSize, activeEntry, FONT_SIZES, DEFAULT_FONT_SIZE, applyBorders, formatAllowed, raiseRibbonAction, } from './shortcuts.js';
|
|
2
2
|
export { FONT_SIZES, applyBorders } from './shortcuts.js';
|
|
3
|
-
import { insertRows, deleteRows, getStructureTarget } from './structure.js';
|
|
3
|
+
import { insertRows, deleteRows, insertColumns, deleteColumns, getStructureTarget } from './structure.js';
|
|
4
4
|
import { fillDown, fillRight, targetRect } from './commands.js';
|
|
5
|
-
import { FORMAT_PRESETS, formatCategory } from './number-format.js';
|
|
5
|
+
import { FORMAT_PRESETS, FORMAT_CATEGORY_PATTERNS, formatCategory, accountingParts, accountingPattern, formatWithPattern } from './number-format.js';
|
|
6
6
|
import { ALL_COLOURS } from './palette.js';
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
// Shared predicates
|
|
@@ -87,6 +87,21 @@ function alignItem(align, title) {
|
|
|
87
87
|
isEnabled: canFormat,
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
+
/** Excel's Top / Middle / Bottom Align. The middle is the sheet's default,
|
|
91
|
+
* so its button clears the field rather than storing it, and reads as on
|
|
92
|
+
* for a cell that has no vertical alignment of its own. */
|
|
93
|
+
function valignItem(valign, title) {
|
|
94
|
+
return {
|
|
95
|
+
id: `valign-${valign}`,
|
|
96
|
+
label: '≡',
|
|
97
|
+
icon: `valign-${valign}`,
|
|
98
|
+
title,
|
|
99
|
+
kind: 'toggle',
|
|
100
|
+
run: (cmd) => applyFormat(cmd, { valign: valign === 'center' ? undefined : valign }),
|
|
101
|
+
isOn: (cmd) => everyCellHas(cmd, (entry) => valign === 'center' ? entry?.valign === undefined || entry?.valign === 'center' : entry?.valign === valign),
|
|
102
|
+
isEnabled: canFormat,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
90
105
|
function presetItem(id, label, title, name, keys) {
|
|
91
106
|
const run = preset(name);
|
|
92
107
|
return {
|
|
@@ -110,7 +125,10 @@ function fromCommand(command) {
|
|
|
110
125
|
*
|
|
111
126
|
* Reads the active cell's current pattern rather than assuming one, so
|
|
112
127
|
* pressing it on a currency cell keeps the currency and only moves the point.
|
|
113
|
-
* A cell with no pattern
|
|
128
|
+
* A cell with no pattern is General, and Excel moves from the decimals the
|
|
129
|
+
* value SHOWS there, not from zero: Increase on 3.14159 goes to six places,
|
|
130
|
+
* not down to one, and Decrease actually trims a place. Only when the cell is
|
|
131
|
+
* empty, or its value is not a number, does General behave like `0`.
|
|
114
132
|
*/
|
|
115
133
|
function nudgeDecimals(delta) {
|
|
116
134
|
return (cmd) => {
|
|
@@ -123,10 +141,31 @@ function nudgeDecimals(delta) {
|
|
|
123
141
|
const current = rowId != null && columnId != null
|
|
124
142
|
? target.store.get(rowId, columnId)?.numFmt
|
|
125
143
|
: undefined;
|
|
126
|
-
|
|
144
|
+
let next;
|
|
145
|
+
if (current) {
|
|
146
|
+
next = withDecimals(current, delta);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// General: start from what the value displays, so the point moves the
|
|
150
|
+
// way Excel's does rather than resetting to a single place.
|
|
151
|
+
const count = generalDecimals(active.rowIndex, active.colIndex) + delta;
|
|
152
|
+
next = count < 0 || count > 30 ? null : count === 0 ? '0' : `0.${'0'.repeat(count)}`;
|
|
153
|
+
}
|
|
127
154
|
return next === null ? false : applyFormat(cmd, { numFmt: next });
|
|
128
155
|
};
|
|
129
156
|
}
|
|
157
|
+
/** The decimals a General cell currently shows, so Increase/Decrease Decimal
|
|
158
|
+
* moves from there. Zero for a blank cell or a non-numeric value. */
|
|
159
|
+
function generalDecimals(row, col) {
|
|
160
|
+
const wb = getWorkbook();
|
|
161
|
+
if (!wb)
|
|
162
|
+
return 0;
|
|
163
|
+
const value = wb.getValue(wb.active, row, col);
|
|
164
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
165
|
+
return 0;
|
|
166
|
+
const dot = formatWithPattern(value, 'General').indexOf('.');
|
|
167
|
+
return dot < 0 ? 0 : formatWithPattern(value, 'General').length - dot - 1;
|
|
168
|
+
}
|
|
130
169
|
/**
|
|
131
170
|
* Move the decimal count of a number-format pattern by `delta`.
|
|
132
171
|
*
|
|
@@ -141,9 +180,17 @@ export function withDecimals(pattern, delta) {
|
|
|
141
180
|
// first half would leave a sheet where -1234.5 printed to a different
|
|
142
181
|
// precision than 1234.5. Excel moves both, so this does too.
|
|
143
182
|
//
|
|
183
|
+
// An accounting pattern is rebuilt from its parts rather than edited:
|
|
184
|
+
// its zero section carries a `"-"??` whose question marks count the
|
|
185
|
+
// decimals too.
|
|
186
|
+
const accounting = accountingParts(pattern);
|
|
187
|
+
if (accounting) {
|
|
188
|
+
const next = accounting.decimals + delta;
|
|
189
|
+
return next < 0 || next > 30 ? null : accountingPattern(accounting.symbol, next);
|
|
190
|
+
}
|
|
144
191
|
// A quoted literal can contain a semicolon, which would make splitting on
|
|
145
192
|
// ';' cut a section in half, so a pattern with quotes declines instead of
|
|
146
|
-
// being mangled. Nothing in FORMAT_PRESETS has one.
|
|
193
|
+
// being mangled. Nothing else in FORMAT_PRESETS has one.
|
|
147
194
|
if (pattern.includes('"'))
|
|
148
195
|
return null;
|
|
149
196
|
const sections = pattern.split(';');
|
|
@@ -197,6 +244,7 @@ const NUMBER_FORMATS = [
|
|
|
197
244
|
{ value: 'general', label: 'General' },
|
|
198
245
|
{ value: 'number', label: 'Number' },
|
|
199
246
|
{ value: 'currency', label: 'Currency' },
|
|
247
|
+
{ value: 'accounting', label: 'Accounting' },
|
|
200
248
|
{ value: 'percent', label: 'Percentage' },
|
|
201
249
|
{ value: 'date', label: 'Date' },
|
|
202
250
|
{ value: 'time', label: 'Time' },
|
|
@@ -216,6 +264,118 @@ const BORDER_OPTIONS = [
|
|
|
216
264
|
// The tabs
|
|
217
265
|
// ---------------------------------------------------------------------------
|
|
218
266
|
const small = (row, item) => ({ ...item, row });
|
|
267
|
+
/**
|
|
268
|
+
* Excel's File tab, the part of it a document in a page can do: New, Open
|
|
269
|
+
* an .xlsx from disk, Save as .xlsx, and the active sheet as CSV. Every
|
|
270
|
+
* entry is raised for the shell, and through it for the host, so an app
|
|
271
|
+
* that keeps its workbooks on a server takes Open and Save over with
|
|
272
|
+
* `onAction` and the buttons still read as Excel's.
|
|
273
|
+
*/
|
|
274
|
+
const FILE = {
|
|
275
|
+
id: 'file',
|
|
276
|
+
label: 'File',
|
|
277
|
+
groups: [
|
|
278
|
+
{
|
|
279
|
+
id: 'file-new',
|
|
280
|
+
icon: 'file-new',
|
|
281
|
+
label: 'New',
|
|
282
|
+
items: [
|
|
283
|
+
{ id: 'file-new', label: 'New', title: 'New: start an empty workbook', icon: 'file-new', kind: 'button', size: 'large', emits: 'file-new' },
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: 'file-open',
|
|
288
|
+
icon: 'file-open',
|
|
289
|
+
label: 'Open',
|
|
290
|
+
items: [
|
|
291
|
+
{ id: 'file-open', label: 'Open', title: 'Open an .xlsx, .xls, .ods or .csv file', keys: 'Ctrl+O', icon: 'file-open', kind: 'button', size: 'large', emits: 'file-open' },
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: 'file-save',
|
|
296
|
+
icon: 'file-save',
|
|
297
|
+
label: 'Save',
|
|
298
|
+
items: [
|
|
299
|
+
{ id: 'file-save-xlsx', label: 'Save As', title: 'Save the workbook as an .xlsx file', keys: 'Ctrl+S', icon: 'file-save', kind: 'button', size: 'large', emits: 'file-save-xlsx' },
|
|
300
|
+
{ id: 'file-save-ods', label: 'Save As ODS', title: 'Save the workbook as an .ods file, which LibreOffice Calc opens', icon: 'file-save', kind: 'button', size: 'large', emits: 'file-save-ods' },
|
|
301
|
+
{ id: 'file-save-xls', label: 'Save As XLS', title: 'Save the workbook as an .xls file, which Excel 97-2003 opens', icon: 'file-save', kind: 'button', size: 'large', emits: 'file-save-xls' },
|
|
302
|
+
{ id: 'file-export-csv', label: 'Export CSV', title: 'Export the active sheet as CSV', icon: 'file-csv', kind: 'button', size: 'large', emits: 'file-export-csv' },
|
|
303
|
+
],
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
id: 'file-print',
|
|
307
|
+
icon: 'print',
|
|
308
|
+
label: 'Print',
|
|
309
|
+
items: [
|
|
310
|
+
{ id: 'file-print', label: 'Print', title: 'Print the active sheet as its Page Layout says', keys: 'Ctrl+P', icon: 'print', kind: 'button', size: 'large', emits: 'file-print' },
|
|
311
|
+
],
|
|
312
|
+
},
|
|
313
|
+
],
|
|
314
|
+
};
|
|
315
|
+
/**
|
|
316
|
+
* Excel's Page Layout tab, the part with something behind it: Page Setup
|
|
317
|
+
* (Margins, Orientation, Size, Print Area, Print Titles, with the dialog
|
|
318
|
+
* on the launcher) and Sheet Options (whether gridlines and headings
|
|
319
|
+
* print). Raised rather than run here: the shell keeps the setup per
|
|
320
|
+
* sheet in the document, and File > Print reads it.
|
|
321
|
+
*/
|
|
322
|
+
const PAGE_LAYOUT = {
|
|
323
|
+
id: 'page-layout',
|
|
324
|
+
label: 'Page Layout',
|
|
325
|
+
groups: [
|
|
326
|
+
{
|
|
327
|
+
id: 'page-setup',
|
|
328
|
+
icon: 'page-setup',
|
|
329
|
+
label: 'Page Setup',
|
|
330
|
+
launcher: 'page-setup',
|
|
331
|
+
items: [
|
|
332
|
+
{
|
|
333
|
+
id: 'margins', label: 'Margins', title: 'Margins', icon: 'margins', kind: 'dropdown', size: 'large',
|
|
334
|
+
options: [
|
|
335
|
+
{ value: 'normal', label: 'Normal', emits: 'margins-normal', toggle: true },
|
|
336
|
+
{ value: 'narrow', label: 'Narrow', emits: 'margins-narrow', toggle: true },
|
|
337
|
+
{ value: 'wide', label: 'Wide', emits: 'margins-wide', toggle: true },
|
|
338
|
+
],
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
id: 'orientation', label: 'Orientation', title: 'Orientation', icon: 'orientation', kind: 'dropdown', size: 'large',
|
|
342
|
+
options: [
|
|
343
|
+
{ value: 'portrait', label: 'Portrait', emits: 'page-portrait', toggle: true },
|
|
344
|
+
{ value: 'landscape', label: 'Landscape', emits: 'page-landscape', toggle: true },
|
|
345
|
+
],
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
id: 'paper', label: 'Size', title: 'Page Size', icon: 'paper', kind: 'dropdown', size: 'large',
|
|
349
|
+
options: [
|
|
350
|
+
{ value: 'letter', label: 'Letter', emits: 'paper-letter', toggle: true },
|
|
351
|
+
{ value: 'legal', label: 'Legal', emits: 'paper-legal', toggle: true },
|
|
352
|
+
{ value: 'tabloid', label: 'Tabloid', emits: 'paper-tabloid', toggle: true },
|
|
353
|
+
{ value: 'a3', label: 'A3', emits: 'paper-a3', toggle: true },
|
|
354
|
+
{ value: 'a4', label: 'A4', emits: 'paper-a4', toggle: true },
|
|
355
|
+
{ value: 'a5', label: 'A5', emits: 'paper-a5', toggle: true },
|
|
356
|
+
],
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
id: 'print-area', label: 'Print Area', title: 'Print Area', icon: 'print-area', kind: 'dropdown', size: 'large',
|
|
360
|
+
options: [
|
|
361
|
+
{ value: 'set', label: 'Set Print Area', emits: 'print-area-set' },
|
|
362
|
+
{ value: 'clear', label: 'Clear Print Area', emits: 'print-area-clear' },
|
|
363
|
+
],
|
|
364
|
+
},
|
|
365
|
+
{ id: 'print-titles', label: 'Print Titles', title: 'Print Titles: rows to repeat at the top of every page', icon: 'print-titles', kind: 'button', size: 'large', emits: 'print-titles' },
|
|
366
|
+
],
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
id: 'sheet-options',
|
|
370
|
+
icon: 'gridlines',
|
|
371
|
+
label: 'Sheet Options',
|
|
372
|
+
items: [
|
|
373
|
+
small(1, { id: 'print-gridlines', label: 'Print Gridlines', title: 'Print the gridlines', icon: 'gridlines', kind: 'toggle', wide: true, emits: 'print-gridlines' }),
|
|
374
|
+
small(2, { id: 'print-headings', label: 'Print Headings', title: 'Print the row numbers and column letters', icon: 'headings', kind: 'toggle', wide: true, emits: 'print-headings' }),
|
|
375
|
+
],
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
};
|
|
219
379
|
const HOME = {
|
|
220
380
|
id: 'home',
|
|
221
381
|
label: 'Home',
|
|
@@ -251,7 +411,15 @@ const HOME = {
|
|
|
251
411
|
small(1, {
|
|
252
412
|
id: 'cut', label: 'Cut', title: 'Cut', keys: 'Ctrl+X', icon: 'cut', kind: 'button',
|
|
253
413
|
isEnabled: hasTarget,
|
|
254
|
-
|
|
414
|
+
// Raised, so a spreadsheet shell can give it Excel's meaning: the
|
|
415
|
+
// cells stay where they are until the paste lands. A host that
|
|
416
|
+
// answers nothing falls back to the grid's cut, which clears now.
|
|
417
|
+
run: (cmd) => {
|
|
418
|
+
if (raiseRibbonAction('cut', cmd))
|
|
419
|
+
return true;
|
|
420
|
+
void cmd.cut();
|
|
421
|
+
return true;
|
|
422
|
+
},
|
|
255
423
|
}),
|
|
256
424
|
small(2, {
|
|
257
425
|
id: 'copy', label: 'Copy', title: 'Copy', keys: 'Ctrl+C', icon: 'copy', kind: 'button',
|
|
@@ -324,6 +492,9 @@ const HOME = {
|
|
|
324
492
|
layout: 'flow',
|
|
325
493
|
launcher: 'format-cells',
|
|
326
494
|
items: [
|
|
495
|
+
small(1, valignItem('top', 'Top Align')),
|
|
496
|
+
small(1, valignItem('center', 'Middle Align')),
|
|
497
|
+
small(1, valignItem('bottom', 'Bottom Align')),
|
|
327
498
|
small(1, {
|
|
328
499
|
id: 'wrap', label: 'Wrap Text', title: 'Wrap Text', icon: 'wrap', kind: 'toggle', wide: true,
|
|
329
500
|
run: (cmd) => toggleWrap(cmd),
|
|
@@ -367,11 +538,12 @@ const HOME = {
|
|
|
367
538
|
current: (cmd) => {
|
|
368
539
|
const fmt = activeEntry(cmd)?.numFmt;
|
|
369
540
|
const { category } = formatCategory(fmt);
|
|
370
|
-
return category === 'custom' ? fmt ?? 'general' : category;
|
|
541
|
+
return category === 'custom' || category === 'special' ? fmt ?? 'general' : category;
|
|
371
542
|
},
|
|
372
|
-
run: (cmd, value) => applyFormat(cmd, { numFmt:
|
|
543
|
+
run: (cmd, value) => applyFormat(cmd, { numFmt: FORMAT_CATEGORY_PATTERNS[value] }),
|
|
373
544
|
}),
|
|
374
|
-
|
|
545
|
+
// Excel's $ button applies Accounting; Ctrl+Shift+4 is Currency.
|
|
546
|
+
small(2, presetItem('fmt-currency', '$', 'Accounting Number Format', 'accounting')),
|
|
375
547
|
small(2, presetItem('fmt-percent', '%', 'Percent Style', 'percent', 'Ctrl+Shift+5')),
|
|
376
548
|
small(2, presetItem('fmt-number', ',', 'Comma Style', 'number', 'Ctrl+Shift+1')),
|
|
377
549
|
small(2, {
|
|
@@ -389,19 +561,36 @@ const HOME = {
|
|
|
389
561
|
icon: 'table',
|
|
390
562
|
label: 'Cells',
|
|
391
563
|
items: [
|
|
564
|
+
// Excel's split buttons: the face takes the selection's axis (a
|
|
565
|
+
// whole column inserts columns, anything else rows, which is what
|
|
566
|
+
// Excel does with a cell selected), and the arrow spells the axis
|
|
567
|
+
// out, so a column can be inserted from a cell without selecting
|
|
568
|
+
// the column first.
|
|
392
569
|
small(1, {
|
|
393
570
|
id: 'insert', label: 'Insert', title: 'Insert Cells', keys: 'Ctrl+Shift++',
|
|
394
|
-
icon: 'insert-cells', kind: '
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
571
|
+
icon: 'insert-cells', kind: 'dropdown', split: true, wide: true,
|
|
572
|
+
run: (cmd, value) => value === 'rows' ? insertRows(cmd)
|
|
573
|
+
: value === 'columns' ? insertColumns(cmd)
|
|
574
|
+
: value === 'sheet' ? newSheet()
|
|
575
|
+
: structural(cmd, 'insert') || insertRows(cmd),
|
|
576
|
+
options: [
|
|
577
|
+
{ value: 'rows', label: 'Insert Sheet Rows' },
|
|
578
|
+
{ value: 'columns', label: 'Insert Sheet Columns' },
|
|
579
|
+
{ value: 'sheet', label: 'Insert Sheet', keys: 'Shift+F11' },
|
|
580
|
+
],
|
|
399
581
|
isEnabled: canRestructure,
|
|
400
582
|
}),
|
|
401
583
|
small(2, {
|
|
402
584
|
id: 'delete', label: 'Delete', title: 'Delete Cells', keys: 'Ctrl+-',
|
|
403
|
-
icon: 'delete-cells', kind: '
|
|
404
|
-
run: (cmd) =>
|
|
585
|
+
icon: 'delete-cells', kind: 'dropdown', split: true, wide: true,
|
|
586
|
+
run: (cmd, value) => value === 'rows' ? deleteRows(cmd)
|
|
587
|
+
: value === 'columns' ? deleteColumns(cmd)
|
|
588
|
+
: structural(cmd, 'delete') || deleteRows(cmd),
|
|
589
|
+
options: [
|
|
590
|
+
{ value: 'rows', label: 'Delete Sheet Rows' },
|
|
591
|
+
{ value: 'columns', label: 'Delete Sheet Columns' },
|
|
592
|
+
{ value: 'sheet', label: 'Delete Sheet', emits: 'delete-sheet' },
|
|
593
|
+
],
|
|
405
594
|
isEnabled: canRestructure,
|
|
406
595
|
}),
|
|
407
596
|
// Excel's Format menu: Cell Size, Visibility, and Format Cells at
|
|
@@ -457,6 +646,8 @@ const HOME = {
|
|
|
457
646
|
{ value: 'cf-color-scale-3', label: 'Green - Yellow - Red Color Scale', icon: 'cf-scale', emits: 'cf-color-scale-3' },
|
|
458
647
|
{ value: 'cf-color-scale-2', label: 'Green - White Color Scale', icon: 'cf-scale', emits: 'cf-color-scale-2' },
|
|
459
648
|
{ value: 'cf-icon-set', label: 'Icon Set (3 Arrows)', icon: 'cf-icons', emits: 'cf-icon-set' },
|
|
649
|
+
{ value: 'n', label: 'New Rule', heading: true },
|
|
650
|
+
{ value: 'cf-formula', label: 'Use a Formula...', icon: 'cf-formula', emits: 'cf-formula' },
|
|
460
651
|
{ value: 'c', label: 'Clear Rules', heading: true },
|
|
461
652
|
{ value: 'cf-clear-selection', label: 'Clear Rules from Selected Cells', emits: 'cf-clear-selection' },
|
|
462
653
|
{ value: 'cf-clear-sheet', label: 'Clear Rules from Entire Sheet', emits: 'cf-clear-sheet' },
|
|
@@ -474,15 +665,17 @@ const HOME = {
|
|
|
474
665
|
// Undo and Redo open the group as a column of two small icons, the
|
|
475
666
|
// way Cut and Copy stand beside Paste; the owner wanted them here
|
|
476
667
|
// rather than in a group of their own.
|
|
668
|
+
// Raised rather than run: a step made on another sheet is undone
|
|
669
|
+
// THERE, which means switching sheets first, and only the shell can.
|
|
477
670
|
small(1, {
|
|
478
671
|
id: 'undo', label: 'Undo', title: 'Undo', keys: 'Ctrl+Z', icon: 'undo', kind: 'button',
|
|
479
672
|
isEnabled: (cmd) => cmd.api.canUndo(),
|
|
480
|
-
|
|
673
|
+
emits: 'undo',
|
|
481
674
|
}),
|
|
482
675
|
small(2, {
|
|
483
676
|
id: 'redo', label: 'Redo', title: 'Redo', keys: 'Ctrl+Y', icon: 'redo', kind: 'button',
|
|
484
677
|
isEnabled: (cmd) => cmd.api.canRedo(),
|
|
485
|
-
|
|
678
|
+
emits: 'redo',
|
|
486
679
|
}),
|
|
487
680
|
small(1, {
|
|
488
681
|
id: 'autosum', label: 'AutoSum', title: 'AutoSum', keys: 'Alt+=',
|
|
@@ -522,7 +715,14 @@ const INSERT = {
|
|
|
522
715
|
icon: 'table',
|
|
523
716
|
label: 'Tables',
|
|
524
717
|
items: [
|
|
718
|
+
// Excel's Tables group leads with PivotTable, and Refresh sits beside
|
|
719
|
+
// the pair for the pivot the cursor is in.
|
|
720
|
+
{ id: 'pivot-table', label: 'PivotTable', title: 'Summarise the selected block', icon: 'pivot', kind: 'button', size: 'large', emits: 'insert-pivot' },
|
|
525
721
|
{ id: 'table', label: 'Table', title: 'Format the selection as a table', keys: 'Ctrl+T', icon: 'table', kind: 'button', size: 'large', emits: 'insert-table' },
|
|
722
|
+
small(1, { id: 'pivot-refresh', label: 'Refresh', title: 'Rebuild the PivotTable here from its source', icon: 'calculate', kind: 'button', wide: true, emits: 'refresh-pivot' }),
|
|
723
|
+
small(1, { id: 'pivot-details', label: 'Show Details', title: 'Show Details: the source rows behind the number in this PivotTable cell, on a sheet of their own', icon: 'pivot', kind: 'button', wide: true, emits: 'pivot-details' }),
|
|
724
|
+
small(2, { id: 'table-remove', label: 'To Range', title: 'Convert the table here back to ordinary cells', icon: 'delete-cells', kind: 'button', wide: true, emits: 'remove-table' }),
|
|
725
|
+
small(3, { id: 'table-style', label: 'Table Styles', title: 'Pick the look of the table the cursor is in', icon: 'table', kind: 'button', wide: true, emits: 'table-style' }),
|
|
526
726
|
],
|
|
527
727
|
},
|
|
528
728
|
{
|
|
@@ -531,6 +731,54 @@ const INSERT = {
|
|
|
531
731
|
label: 'Charts',
|
|
532
732
|
items: [
|
|
533
733
|
{ id: 'chart', label: 'Chart', title: 'Chart the selected range', icon: 'chart', kind: 'button', size: 'large', emits: 'insert-chart' },
|
|
734
|
+
small(1, { id: 'chart-setup', label: 'Setup', title: 'Chart: type, title, labels and series', icon: 'chart-setup', kind: 'button', wide: true, emits: 'chart-setup' }),
|
|
735
|
+
small(2, { id: 'delete-object', label: 'Delete', title: 'Delete the selected chart or picture', icon: 'delete-cells', kind: 'button', wide: true, emits: 'delete-object' }),
|
|
736
|
+
],
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
// Excel's Sparklines group: the three kinds, each opening the Create
|
|
740
|
+
// Sparklines dialog on the selection, and Clear for the group under it.
|
|
741
|
+
id: 'sparklines',
|
|
742
|
+
icon: 'sparkline-line',
|
|
743
|
+
label: 'Sparklines',
|
|
744
|
+
items: [
|
|
745
|
+
{ id: 'sparkline-line', label: 'Line', title: 'A line sparkline in each cell of a range', icon: 'sparkline-line', kind: 'button', size: 'large', emits: 'sparkline-line' },
|
|
746
|
+
{ id: 'sparkline-column', label: 'Column', title: 'A column sparkline in each cell of a range', icon: 'sparkline-column', kind: 'button', size: 'large', emits: 'sparkline-column' },
|
|
747
|
+
{ id: 'sparkline-winloss', label: 'Win/Loss', title: 'A win/loss sparkline in each cell of a range', icon: 'sparkline-winloss', kind: 'button', size: 'large', emits: 'sparkline-winloss' },
|
|
748
|
+
small(1, { id: 'sparkline-setup', label: 'Edit', title: 'The sparkline group here: its ranges, kind and colours', icon: 'chart-setup', kind: 'button', wide: true, emits: 'sparkline-setup' }),
|
|
749
|
+
small(2, { id: 'sparkline-clear', label: 'Clear', title: 'Clear the sparklines in the selection', icon: 'delete-cells', kind: 'button', wide: true, emits: 'clear-sparklines' }),
|
|
750
|
+
],
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
// Excel's Links group: one dialog for the address, the text and the tip,
|
|
754
|
+
// and Remove Link beside it.
|
|
755
|
+
id: 'links',
|
|
756
|
+
icon: 'link',
|
|
757
|
+
label: 'Links',
|
|
758
|
+
items: [
|
|
759
|
+
{ id: 'link', label: 'Link', title: 'Link this cell to a page or an address', keys: 'Ctrl+K', icon: 'link', kind: 'button', size: 'large', emits: 'insert-link' },
|
|
760
|
+
small(1, { id: 'unlink', label: 'Remove', title: 'Remove the link from the selection', icon: 'unlink', kind: 'button', wide: true, emits: 'remove-link' }),
|
|
761
|
+
],
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
id: 'illustrations',
|
|
765
|
+
icon: 'picture',
|
|
766
|
+
label: 'Illustrations',
|
|
767
|
+
items: [
|
|
768
|
+
{ id: 'picture', label: 'Picture', title: 'Put a picture on the sheet', icon: 'picture', kind: 'button', size: 'large', emits: 'insert-picture' },
|
|
769
|
+
],
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
// Excel's Insert > Checkbox, with the two other controls a data-entry
|
|
773
|
+
// sheet asks for beside it. Each draws the cell as a control; the
|
|
774
|
+
// cell's own value is still what it means.
|
|
775
|
+
id: 'controls',
|
|
776
|
+
icon: 'checkbox',
|
|
777
|
+
label: 'Controls',
|
|
778
|
+
items: [
|
|
779
|
+
{ id: 'insert-checkbox', label: 'Checkbox', title: 'Draw the selected cells as checkboxes, over TRUE and FALSE', icon: 'checkbox', kind: 'button', size: 'large', emits: 'insert-checkbox' },
|
|
780
|
+
small(2, { id: 'insert-cell-button', label: 'Button', title: 'Draw the selected cells as buttons', icon: 'cell-button', kind: 'button', emits: 'insert-cell-button' }),
|
|
781
|
+
small(2, { id: 'clear-cell-type', label: 'Clear Control', title: 'Draw the selected cells as ordinary cells again', icon: 'clear-formats', kind: 'button', emits: 'clear-cell-type' }),
|
|
534
782
|
],
|
|
535
783
|
},
|
|
536
784
|
{
|
|
@@ -605,7 +853,12 @@ const FORMULAS = {
|
|
|
605
853
|
icon: 'show-formulas',
|
|
606
854
|
label: 'Formula Auditing',
|
|
607
855
|
items: [
|
|
856
|
+
small(1, { id: 'trace-precedents', label: 'Trace Precedents', title: 'Trace Precedents: arrows from the cells the active formula reads; again for the next level', icon: 'trace-precedents', kind: 'button', wide: true, emits: 'trace-precedents' }),
|
|
857
|
+
small(2, { id: 'trace-dependents', label: 'Trace Dependents', title: 'Trace Dependents: arrows to the formulas that read the active cell; again for the next level', icon: 'trace-dependents', kind: 'button', wide: true, emits: 'trace-dependents' }),
|
|
858
|
+
small(3, { id: 'remove-arrows', label: 'Remove Arrows', title: 'Remove Arrows', icon: 'remove-arrows', kind: 'button', wide: true, emits: 'remove-arrows' }),
|
|
608
859
|
small(1, { id: 'show-formulas', label: 'Show Formulas', title: 'Show formulas instead of their results', keys: 'Ctrl+`', icon: 'show-formulas', kind: 'toggle', wide: true, emits: 'toggle-formulas' }),
|
|
860
|
+
small(2, { id: 'evaluate-formula', label: 'Evaluate Formula', title: 'Evaluate Formula: work the active cell out one part at a time', icon: 'evaluate-formula', kind: 'button', wide: true, emits: 'evaluate-formula' }),
|
|
861
|
+
small(3, { id: 'error-checking', label: 'Error Checking', title: 'Error Checking: walk the cells on this sheet that report an error, and the formulas that break their column\'s pattern', icon: 'error-checking', kind: 'button', wide: true, emits: 'error-checking' }),
|
|
609
862
|
],
|
|
610
863
|
},
|
|
611
864
|
{
|
|
@@ -615,6 +868,7 @@ const FORMULAS = {
|
|
|
615
868
|
items: [
|
|
616
869
|
{ id: 'recalc', label: 'Calculate Now', title: 'Recalculate the workbook', keys: 'F9', icon: 'calculate', kind: 'button', size: 'large', emits: 'recalculate' },
|
|
617
870
|
small(1, { id: 'goal-seek-f', label: 'Goal Seek', title: 'Goal Seek', icon: 'goal-seek', kind: 'button', wide: true, emits: 'goal-seek' }),
|
|
871
|
+
small(2, { id: 'calc-options', label: 'Calculation Options', title: 'Iterative calculation: let a circular reference settle instead of showing #CYCLE!', icon: 'calculate', kind: 'button', wide: true, emits: 'calc-options' }),
|
|
618
872
|
],
|
|
619
873
|
},
|
|
620
874
|
],
|
|
@@ -630,6 +884,7 @@ const DATA = {
|
|
|
630
884
|
items: [
|
|
631
885
|
small(1, { id: 'sort-asc', label: 'Sort A to Z', title: 'Sort A to Z', icon: 'sort-asc', kind: 'button', emits: 'sort-asc' }),
|
|
632
886
|
small(2, { id: 'sort-desc', label: 'Sort Z to A', title: 'Sort Z to A', icon: 'sort-desc', kind: 'button', emits: 'sort-desc' }),
|
|
887
|
+
{ id: 'sort-custom', label: 'Sort', title: 'Sort: by several columns, each its own way', icon: 'sort', kind: 'button', size: 'large', emits: 'sort-custom' },
|
|
633
888
|
{ id: 'filter-data', label: 'Filter', title: 'Filter', keys: 'Ctrl+Shift+L', icon: 'filter', kind: 'toggle', size: 'large', emits: 'toggle-filter' },
|
|
634
889
|
],
|
|
635
890
|
},
|
|
@@ -640,7 +895,17 @@ const DATA = {
|
|
|
640
895
|
items: [
|
|
641
896
|
{ id: 'text-to-columns', label: 'Text to Columns', title: 'Split the selected column on a delimiter', icon: 'text-to-columns', kind: 'button', size: 'large', emits: 'text-to-columns' },
|
|
642
897
|
{ id: 'remove-duplicates', label: 'Remove Duplicates', title: 'Remove duplicate rows', icon: 'remove-duplicates', kind: 'button', size: 'large', emits: 'remove-duplicates' },
|
|
643
|
-
|
|
898
|
+
// Excel's menu: the dialog, then Circle Invalid Data and Clear
|
|
899
|
+
// Validation Circles, each raised for the shell.
|
|
900
|
+
{
|
|
901
|
+
id: 'data-validation', label: 'Data Validation', title: 'Data Validation: what may be typed into the selected cells',
|
|
902
|
+
icon: 'validation', kind: 'dropdown', size: 'large',
|
|
903
|
+
options: [
|
|
904
|
+
{ value: 'data-validation', label: 'Data Validation...', emits: 'data-validation' },
|
|
905
|
+
{ value: 'circle-invalid', label: 'Circle Invalid Data', emits: 'circle-invalid' },
|
|
906
|
+
{ value: 'clear-circles', label: 'Clear Validation Circles', emits: 'clear-circles' },
|
|
907
|
+
],
|
|
908
|
+
},
|
|
644
909
|
],
|
|
645
910
|
},
|
|
646
911
|
{
|
|
@@ -651,6 +916,36 @@ const DATA = {
|
|
|
651
916
|
{ id: 'goal-seek', label: 'Goal Seek', title: 'Change one input until a formula hits a target', icon: 'goal-seek', kind: 'button', size: 'large', emits: 'goal-seek' },
|
|
652
917
|
],
|
|
653
918
|
},
|
|
919
|
+
{
|
|
920
|
+
id: 'outline',
|
|
921
|
+
icon: 'group-rows',
|
|
922
|
+
label: 'Outline',
|
|
923
|
+
items: [
|
|
924
|
+
// Excel's Group and Ungroup are split buttons whose face acts on
|
|
925
|
+
// rows; the ribbon model forbids a dropdown that emits its own
|
|
926
|
+
// face, so each is a menu whose first entry is the face's action.
|
|
927
|
+
{
|
|
928
|
+
id: 'group', label: 'Group', title: 'Group the selected rows or columns',
|
|
929
|
+
icon: 'group-rows', kind: 'dropdown', size: 'large', wide: true,
|
|
930
|
+
options: [
|
|
931
|
+
{ value: 'group-rows', label: 'Group Rows', keys: 'Alt+Shift+Right', emits: 'group-rows' },
|
|
932
|
+
{ value: 'group-cols', label: 'Group Columns', emits: 'group-cols' },
|
|
933
|
+
{ value: 'auto-outline', label: 'Auto Outline', emits: 'auto-outline' },
|
|
934
|
+
],
|
|
935
|
+
},
|
|
936
|
+
{
|
|
937
|
+
id: 'ungroup', label: 'Ungroup', title: 'Ungroup the selected rows or columns',
|
|
938
|
+
icon: 'ungroup-rows', kind: 'dropdown', size: 'large', wide: true,
|
|
939
|
+
options: [
|
|
940
|
+
{ value: 'ungroup-rows', label: 'Ungroup Rows', keys: 'Alt+Shift+Left', emits: 'ungroup-rows' },
|
|
941
|
+
{ value: 'ungroup-cols', label: 'Ungroup Columns', emits: 'ungroup-cols' },
|
|
942
|
+
{ value: 'clear-outline', label: 'Clear Outline', emits: 'clear-outline' },
|
|
943
|
+
],
|
|
944
|
+
},
|
|
945
|
+
small(2, { id: 'show-detail', label: 'Show Detail', title: 'Expand the group at the selection', icon: 'show-detail', kind: 'button', emits: 'show-detail' }),
|
|
946
|
+
small(2, { id: 'hide-detail', label: 'Hide Detail', title: 'Collapse the group at the selection', icon: 'hide-detail', kind: 'button', emits: 'hide-detail' }),
|
|
947
|
+
],
|
|
948
|
+
},
|
|
654
949
|
],
|
|
655
950
|
};
|
|
656
951
|
function toggleWrap(cmd) {
|
|
@@ -671,8 +966,10 @@ function toggleWrap(cmd) {
|
|
|
671
966
|
* the sheet's notes: New Comment opens the editor on the active cell (and
|
|
672
967
|
* edits the one there), Delete, Previous and Next walk them, Show All
|
|
673
968
|
* Comments lists them. Protect Sheet and Unprotect Sheet are one slot, the
|
|
674
|
-
* shell leaving off whichever does not apply
|
|
675
|
-
*
|
|
969
|
+
* shell leaving off whichever does not apply; Protect Sheet opens Excel's
|
|
970
|
+
* dialog with its "allow all users to" list, and Allow Edit Ranges names
|
|
971
|
+
* the blocks that stay editable. There is no password, as the sheet
|
|
972
|
+
* documents.
|
|
676
973
|
*/
|
|
677
974
|
const REVIEW = {
|
|
678
975
|
id: 'review',
|
|
@@ -703,6 +1000,10 @@ const REVIEW = {
|
|
|
703
1000
|
id: 'unprotect-sheet', label: 'Unprotect Sheet', title: 'Unprotect Sheet',
|
|
704
1001
|
icon: 'unprotect', kind: 'button', size: 'large', emits: 'unprotect-sheet',
|
|
705
1002
|
},
|
|
1003
|
+
{
|
|
1004
|
+
id: 'allow-edit-ranges', label: 'Allow Edit Ranges', title: 'Allow Users to Edit Ranges: blocks that take an edit while the sheet is protected',
|
|
1005
|
+
icon: 'edit-ranges', kind: 'button', size: 'large', emits: 'allow-edit-ranges',
|
|
1006
|
+
},
|
|
706
1007
|
],
|
|
707
1008
|
},
|
|
708
1009
|
],
|
|
@@ -746,7 +1047,7 @@ const VIEW = {
|
|
|
746
1047
|
},
|
|
747
1048
|
],
|
|
748
1049
|
};
|
|
749
|
-
export const RIBBON_TABS = [HOME, INSERT, FORMULAS, DATA, REVIEW, VIEW];
|
|
1050
|
+
export const RIBBON_TABS = [FILE, HOME, INSERT, PAGE_LAYOUT, FORMULAS, DATA, REVIEW, VIEW];
|
|
750
1051
|
/** Every item across every tab, for tests and for a command palette. */
|
|
751
1052
|
export function ribbonItems() {
|
|
752
1053
|
return RIBBON_TABS.flatMap((tab) => tab.groups.flatMap((group) => group.items));
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What kind of thing a sheet tab is.
|
|
3
|
+
*
|
|
4
|
+
* A workbook's tabs have always been cell grids. A `grid` tab is the other
|
|
5
|
+
* thing a business workbook wants: a data-bound table, backed by records
|
|
6
|
+
* rather than by cells, sorted and filtered and edited as a grid rather
|
|
7
|
+
* than as a sheet.
|
|
8
|
+
*
|
|
9
|
+
* The trick that makes this cheap rather than a second engine: **a grid
|
|
10
|
+
* sheet PROJECTS its records into the workbook's cells.** The records are
|
|
11
|
+
* the truth, and after every change they are written into the same
|
|
12
|
+
* `string[][]` a cell sheet keeps, header row included. So
|
|
13
|
+
* `=SUM(Orders!D2:D99)` on a cell sheet reads a grid sheet with no new
|
|
14
|
+
* machinery at all: the formula engine, the dependency graph, the file
|
|
15
|
+
* writers and the printer never learn that this tab is different.
|
|
16
|
+
*
|
|
17
|
+
* The projection runs through `setRaw`, which ignores a write that changes
|
|
18
|
+
* nothing, so editing one field of one record rewrites one cell and
|
|
19
|
+
* recalculates what depended on it, not the sheet.
|
|
20
|
+
*
|
|
21
|
+
* What a grid sheet deliberately does NOT do: hold a formula of its own.
|
|
22
|
+
* Its cells are a rendering of its records, so anything typed into them
|
|
23
|
+
* would be overwritten by the next projection. A sheet that needs formulas
|
|
24
|
+
* beside the data is a cell sheet reading the grid one across.
|
|
25
|
+
*/
|
|
26
|
+
import { type SheetField } from './from-rows.js';
|
|
27
|
+
export type SheetKind = 'cells' | 'grid';
|
|
28
|
+
/** One column of a grid sheet, as the sheet describes it. */
|
|
29
|
+
export type GridSheetField = SheetField & {
|
|
30
|
+
/** Narrow the editor and the alignment, as the grid's own columns do. */
|
|
31
|
+
type?: 'text' | 'number' | 'date' | 'boolean';
|
|
32
|
+
width?: number;
|
|
33
|
+
editable?: boolean;
|
|
34
|
+
};
|
|
35
|
+
export type GridSheetSpec = {
|
|
36
|
+
fields: GridSheetField[];
|
|
37
|
+
/** The records. A grid sheet's truth; the cells are made from these. */
|
|
38
|
+
rows: Array<Record<string, unknown>>;
|
|
39
|
+
/** Rows may be edited in place. Off by default, as a report would want. */
|
|
40
|
+
editable?: boolean;
|
|
41
|
+
/** A totals row under the records, summing every numeric column. */
|
|
42
|
+
totals?: boolean;
|
|
43
|
+
};
|
|
44
|
+
export declare const emptyGridSheet: () => GridSheetSpec;
|
|
45
|
+
/** The cells a grid sheet stands for: the header, the records, the totals. */
|
|
46
|
+
export declare function projectGridSheet(spec: GridSheetSpec): string[][];
|
|
47
|
+
/**
|
|
48
|
+
* Where a record sits in the projection.
|
|
49
|
+
*
|
|
50
|
+
* Row 0 is the header, so record `i` is at row `i + 1`. Kept as a function
|
|
51
|
+
* rather than inlined so the offset is named in one place: getting it
|
|
52
|
+
* wrong reads the header as a record and is silent.
|
|
53
|
+
*/
|
|
54
|
+
export declare const rowOfRecord: (index: number) => number;
|
|
55
|
+
export declare const recordOfRow: (row: number) => number;
|
|
56
|
+
/** Is this row of the projection a record, rather than a header or total? */
|
|
57
|
+
export declare const isRecordRow: (spec: GridSheetSpec, row: number) => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* A field's column in the projection, or -1.
|
|
60
|
+
*
|
|
61
|
+
* Matched on the field name rather than the label, since two columns may
|
|
62
|
+
* share a label and the name is what the record is keyed by.
|
|
63
|
+
*/
|
|
64
|
+
export declare const columnOfField: (spec: GridSheetSpec, field: string) => number;
|
|
65
|
+
/** A deep-enough copy for a document snapshot. */
|
|
66
|
+
export declare const copyGridSheet: (spec: GridSheetSpec) => GridSheetSpec;
|
|
67
|
+
/**
|
|
68
|
+
* A value typed into a grid sheet, coerced to the field's type.
|
|
69
|
+
*
|
|
70
|
+
* The grid hands back whatever its editor produced, which for a number
|
|
71
|
+
* column typed into by hand is a string. Storing that would make the
|
|
72
|
+
* record's shape depend on how it was edited, so it is narrowed here once.
|
|
73
|
+
*/
|
|
74
|
+
export declare function coerceFieldValue(field: GridSheetField, value: unknown): unknown;
|