@svgrid/enterprise 3.0.1 → 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 +680 -0
- package/dist/SvFormulaBar.svelte.d.ts +69 -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 +263 -54
- package/dist/SvPivotDesigner.svelte.d.ts +27 -20
- package/dist/SvRibbonIcon.svelte +46 -0
- package/dist/SvRibbonIcon.svelte.d.ts +17 -0
- package/dist/SvSchemaChart.svelte +4 -2
- package/dist/SvSheet.svelte +7914 -0
- package/dist/SvSheet.svelte.d.ts +215 -0
- package/dist/SvSheetChartSetup.svelte +151 -0
- package/dist/SvSheetChartSetup.svelte.d.ts +18 -0
- package/dist/SvSheetComment.svelte +283 -0
- package/dist/SvSheetComment.svelte.d.ts +22 -0
- package/dist/SvSheetConditionalFormat.svelte +159 -0
- package/dist/SvSheetConditionalFormat.svelte.d.ts +14 -0
- package/dist/SvSheetDataValidation.svelte +273 -0
- package/dist/SvSheetDataValidation.svelte.d.ts +14 -0
- 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 +320 -0
- package/dist/SvSheetFilterMenu.svelte.d.ts +22 -0
- package/dist/SvSheetFindReplace.svelte +132 -0
- package/dist/SvSheetFindReplace.svelte.d.ts +10 -0
- package/dist/SvSheetFormatCells.svelte +465 -0
- package/dist/SvSheetFormatCells.svelte.d.ts +17 -0
- package/dist/SvSheetGoalSeek.svelte +145 -0
- package/dist/SvSheetGoalSeek.svelte.d.ts +12 -0
- package/dist/SvSheetInsertFunction.svelte +149 -0
- package/dist/SvSheetInsertFunction.svelte.d.ts +8 -0
- 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 +91 -0
- package/dist/SvSheetListPicker.svelte.d.ts +10 -0
- package/dist/SvSheetManageRules.svelte +187 -0
- package/dist/SvSheetManageRules.svelte.d.ts +16 -0
- package/dist/SvSheetNameManager.svelte +227 -0
- package/dist/SvSheetNameManager.svelte.d.ts +11 -0
- package/dist/SvSheetPageSetup.svelte +159 -0
- package/dist/SvSheetPageSetup.svelte.d.ts +13 -0
- package/dist/SvSheetPasteSpecial.svelte +107 -0
- package/dist/SvSheetPasteSpecial.svelte.d.ts +12 -0
- 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 +152 -0
- package/dist/SvSheetRemoveDuplicates.svelte.d.ts +12 -0
- package/dist/SvSheetRibbon.svelte +1254 -0
- package/dist/SvSheetRibbon.svelte.d.ts +34 -0
- package/dist/SvSheetSizeDialog.svelte +60 -0
- package/dist/SvSheetSizeDialog.svelte.d.ts +11 -0
- 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 +571 -0
- package/dist/SvSheetTabs.svelte.d.ts +50 -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 +85 -0
- package/dist/SvSheetValidationAlert.svelte.d.ts +15 -0
- 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 +43538 -6539
- package/dist/designer/assets/GridMenus-8gTNssgV.js +8 -0
- package/dist/designer/assets/SvChartMenu-BDoeqGz6.js +1 -0
- package/dist/designer/assets/SvChartMenu-BYO9cYdy.css +1 -0
- package/dist/designer/assets/SvDateRangeInput-BBRzrQeg.js +1 -0
- package/dist/designer/assets/SvDateTimePicker-DCPg7WGN.js +1 -0
- package/dist/designer/assets/SvGridCellEditor-DMoWJjEI.js +4 -0
- package/dist/designer/assets/SvGridChart-BgLuPO7I.css +1 -0
- package/dist/designer/assets/SvGridChart-Cy1ATrWh.js +3 -0
- package/dist/designer/assets/SvGridChartBuilder-08YWWeqY.css +1 -0
- package/dist/designer/assets/SvGridChartBuilder-eQ3mn0L9.js +1 -0
- package/dist/designer/assets/SvGridChartPanel-4Pc8y5yO.css +1 -0
- package/dist/designer/assets/SvGridChartPanel-CATdVc9X.js +4 -0
- package/dist/designer/assets/{SvGridChartView-DUc-1RUf.css → SvGridChartView-7msfnWZT.css} +1 -1
- package/dist/designer/assets/SvGridChartView-CmsZtCED.js +1 -0
- package/dist/designer/assets/SvGridDropdown-Cjz0H-fI.js +1 -0
- package/dist/designer/assets/SvListBox-BDS66lmZ.js +110 -0
- package/dist/designer/assets/SvMenuList-DJ47ba1h.css +1 -0
- package/dist/designer/assets/SvMenuList-Dgq2D5VN.js +1 -0
- package/dist/designer/assets/SvTabs-2mHC6oaz.js +1 -0
- package/dist/designer/assets/SvTabs-DKmwb5p1.css +1 -0
- package/dist/designer/assets/cell-formatting-BbubJTVz.js +1 -0
- package/dist/designer/assets/chart-Cn7MnNqA.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-Dz7PTIqT.js +1 -0
- package/dist/designer/assets/chart-summary-BD1qYB2R.js +1 -0
- package/dist/designer/assets/chart-trend-B8xr5LuD.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/{dismissable-BO547MH9.js → dismissable-ChWRPkoa.js} +1 -1
- package/dist/designer/assets/editor-contract-Bpoa7A5g.js +1 -0
- package/dist/designer/assets/{export-format-D-eP4b2l.js → export-format-DGckmgKr.js} +1 -1
- package/dist/designer/assets/focus-trap-V2-6Fy9I.js +1 -0
- package/dist/designer/assets/{index-C_a9Cj8Y.js → index-D5bVbuzI.js} +318 -315
- package/dist/designer/assets/index-_JVFxt02.css +1 -0
- package/dist/designer/assets/list-option-BP_dWS66.js +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-CITpcm6b.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 +29 -19
- package/dist/export-pdf.d.ts +164 -0
- package/dist/export-pdf.js +346 -15
- package/dist/export.js +25 -10
- 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 +93 -3
- package/dist/index.js +107 -3
- package/dist/install.js +13 -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 +203 -9
- package/dist/pivot-chart.d.ts +25 -1
- package/dist/pivot-chart.js +25 -69
- 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/address.d.ts +43 -0
- package/dist/sheet/address.js +81 -0
- package/dist/sheet/ast.d.ts +138 -0
- package/dist/sheet/ast.js +70 -0
- package/dist/sheet/auto-filter.d.ts +120 -0
- package/dist/sheet/auto-filter.js +295 -0
- package/dist/sheet/autocomplete.d.ts +51 -0
- package/dist/sheet/autocomplete.js +248 -0
- 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 +71 -0
- package/dist/sheet/coerce.js +289 -0
- package/dist/sheet/commands.d.ts +89 -0
- package/dist/sheet/commands.js +230 -0
- package/dist/sheet/comments.d.ts +63 -0
- package/dist/sheet/comments.js +131 -0
- package/dist/sheet/conditional-formats.d.ts +167 -0
- package/dist/sheet/conditional-formats.js +341 -0
- 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 +104 -0
- package/dist/sheet/deps.js +274 -0
- package/dist/sheet/document.d.ts +252 -0
- package/dist/sheet/document.js +465 -0
- package/dist/sheet/edit-keys.d.ts +14 -0
- package/dist/sheet/edit-keys.js +40 -0
- package/dist/sheet/engine.d.ts +67 -0
- package/dist/sheet/engine.js +19 -0
- package/dist/sheet/entry.d.ts +35 -0
- package/dist/sheet/entry.js +226 -0
- 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 +128 -0
- package/dist/sheet/evaluate.js +1049 -0
- package/dist/sheet/filter-files.d.ts +37 -0
- package/dist/sheet/filter-files.js +465 -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 +114 -0
- package/dist/sheet/format-store.js +243 -0
- package/dist/sheet/freeze.d.ts +54 -0
- package/dist/sheet/freeze.js +58 -0
- package/dist/sheet/from-rows.d.ts +14 -0
- package/dist/sheet/from-rows.js +50 -0
- package/dist/sheet/function-catalog.d.ts +10 -0
- package/dist/sheet/function-catalog.js +385 -0
- package/dist/sheet/functions.d.ts +28 -0
- package/dist/sheet/functions.js +634 -0
- package/dist/sheet/goal-seek.d.ts +73 -0
- package/dist/sheet/goal-seek.js +153 -0
- package/dist/sheet/index.d.ts +80 -0
- package/dist/sheet/index.js +80 -0
- package/dist/sheet/links.d.ts +57 -0
- package/dist/sheet/links.js +174 -0
- package/dist/sheet/merges.d.ts +71 -0
- package/dist/sheet/merges.js +137 -0
- package/dist/sheet/messages.d.ts +778 -0
- package/dist/sheet/messages.js +806 -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 +110 -0
- package/dist/sheet/number-format.js +905 -0
- 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/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 +140 -0
- package/dist/sheet/paste-special.d.ts +186 -0
- package/dist/sheet/paste-special.js +601 -0
- 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 +75 -0
- package/dist/sheet/protection.js +101 -0
- package/dist/sheet/rects.d.ts +45 -0
- package/dist/sheet/rects.js +112 -0
- package/dist/sheet/refs.d.ts +130 -0
- package/dist/sheet/refs.js +413 -0
- package/dist/sheet/ribbon-icons.d.ts +31 -0
- package/dist/sheet/ribbon-icons.js +536 -0
- package/dist/sheet/ribbon.d.ts +173 -0
- package/dist/sheet/ribbon.js +1054 -0
- package/dist/sheet/sheet-kinds.d.ts +74 -0
- package/dist/sheet/sheet-kinds.js +91 -0
- package/dist/sheet/shortcuts.d.ts +174 -0
- package/dist/sheet/shortcuts.js +674 -0
- 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/structure.d.ts +87 -0
- package/dist/sheet/structure.js +166 -0
- package/dist/sheet/table-styles.d.ts +74 -0
- package/dist/sheet/table-styles.js +152 -0
- package/dist/sheet/tables.d.ts +89 -0
- package/dist/sheet/tables.js +178 -0
- package/dist/sheet/tokenize.d.ts +71 -0
- package/dist/sheet/tokenize.js +355 -0
- package/dist/sheet/transforms.d.ts +76 -0
- package/dist/sheet/transforms.js +154 -0
- package/dist/sheet/validation.d.ts +108 -0
- package/dist/sheet/validation.js +278 -0
- package/dist/sheet/workbook.d.ts +217 -0
- package/dist/sheet/workbook.js +1120 -0
- 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.d.ts +6 -0
- package/dist/sheet-enable.js +45 -0
- 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 +170 -3
- 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 +36 -6
- package/dist/designer/assets/GridMenus-B1JtIN21.js +0 -8
- package/dist/designer/assets/SvDateRangeInput-CjO7nn_x.js +0 -1
- package/dist/designer/assets/SvDateTimePicker-ByBD_ov6.js +0 -1
- package/dist/designer/assets/SvField-YDLipR6O.css +0 -1
- package/dist/designer/assets/SvField-cj1PFNgZ.js +0 -1
- package/dist/designer/assets/SvGridCellEditor-0W1L2hJ1.js +0 -2
- package/dist/designer/assets/SvGridChart-DBOR4xcz.js +0 -2
- package/dist/designer/assets/SvGridChart-fkMWeh1J.css +0 -1
- package/dist/designer/assets/SvGridChartPanel-symrhNnR.js +0 -11
- package/dist/designer/assets/SvGridChartView-BmRxq6mU.js +0 -1
- package/dist/designer/assets/SvGridDropdown-Bb3HH2Aj.js +0 -1
- package/dist/designer/assets/SvListBox-1oUF6Iav.js +0 -110
- package/dist/designer/assets/cell-formatting-wr5wm7US.js +0 -1
- package/dist/designer/assets/chart-DXFganU8.js +0 -1
- package/dist/designer/assets/column-resize-C_inr5zT.js +0 -1
- package/dist/designer/assets/date-format-DGagAqRc.css +0 -1
- package/dist/designer/assets/date-format-onlYDsrY.js +0 -1
- package/dist/designer/assets/easing-zaypKrr0.js +0 -3
- package/dist/designer/assets/index-k2stW6L8.css +0 -1
- package/dist/designer/assets/row-resize-B0FWHcNr.js +0 -1
- package/dist/designer/assets/src-D9p27OGC.js +0 -58
- package/dist/designer/assets/validate-h-aslRV9.js +0 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Rect } from './sheet/format-store.js';
|
|
2
|
+
type Props = {
|
|
3
|
+
open?: boolean;
|
|
4
|
+
/** The block the table covers, header row included. */
|
|
5
|
+
range: Rect;
|
|
6
|
+
name: string;
|
|
7
|
+
headers?: boolean;
|
|
8
|
+
totals?: boolean;
|
|
9
|
+
existing?: boolean;
|
|
10
|
+
/** The look, by Excel's name for it, or `'None'`. */
|
|
11
|
+
style?: string;
|
|
12
|
+
onApply: (table: {
|
|
13
|
+
range: Rect;
|
|
14
|
+
name: string;
|
|
15
|
+
headers: boolean;
|
|
16
|
+
totals: boolean;
|
|
17
|
+
style: string;
|
|
18
|
+
}) => void;
|
|
19
|
+
onRemove?: () => void;
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
};
|
|
22
|
+
declare const SvSheetTable: import("svelte").Component<Props, {}, "open">;
|
|
23
|
+
type SvSheetTable = ReturnType<typeof SvSheetTable>;
|
|
24
|
+
export default SvSheetTable;
|
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* The sheet tab strip along the bottom of a workbook.
|
|
4
|
+
*
|
|
5
|
+
* Owns no workbook state of its own: it renders what the workbook reports
|
|
6
|
+
* and calls back, so the keyboard shortcuts and the tabs cannot disagree
|
|
7
|
+
* about which sheet is active.
|
|
8
|
+
*/
|
|
9
|
+
import { tick } from 'svelte'
|
|
10
|
+
import { SvModal } from '@svgrid/grid'
|
|
11
|
+
import type { Workbook } from './sheet/workbook'
|
|
12
|
+
import { isValidSheetName } from './sheet/workbook'
|
|
13
|
+
import { useSheetText } from './sheet-text'
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
workbook: Workbook
|
|
17
|
+
/** Called after any change, so the consumer can re-render. */
|
|
18
|
+
onChange?: () => void
|
|
19
|
+
/**
|
|
20
|
+
* Called after a sheet is renamed or removed, before `onChange`. Anything
|
|
21
|
+
* the consumer keeps per sheet and keys by name - the shell keeps a
|
|
22
|
+
* format store per sheet - has to follow the rename or drop the entry,
|
|
23
|
+
* and the workbook itself has no event for either.
|
|
24
|
+
*/
|
|
25
|
+
onRename?: (from: string, to: string) => void
|
|
26
|
+
onRemove?: (name: string) => void
|
|
27
|
+
/**
|
|
28
|
+
* Called when a pointer action on the strip is over: a tab clicked, the
|
|
29
|
+
* add button, an entry of the tab menu, a delete confirmed. Each leaves
|
|
30
|
+
* the focus on a button or nowhere; a consumer whose cells should keep
|
|
31
|
+
* the keyboard, as a spreadsheet's do, puts it back from here. Not
|
|
32
|
+
* called for the arrow keys inside the strip, which keep the focus on
|
|
33
|
+
* the tab they moved to, nor after a rename ends, which goes to its tab.
|
|
34
|
+
*/
|
|
35
|
+
onReturnFocus?: () => void
|
|
36
|
+
/**
|
|
37
|
+
* The sheets that are hidden: their tabs are not drawn and the menu
|
|
38
|
+
* offers Unhide for each. The consumer keeps the list (the shell keeps
|
|
39
|
+
* it in the document) and answers `onHide` / `onUnhide`.
|
|
40
|
+
*/
|
|
41
|
+
hidden?: ReadonlyArray<string>
|
|
42
|
+
onHide?: (name: string) => void
|
|
43
|
+
onUnhide?: (name: string) => void
|
|
44
|
+
/** Excel's Move or Copy > Create a copy. Without it the entry is not offered. */
|
|
45
|
+
onDuplicate?: (name: string) => void
|
|
46
|
+
/** Off hides the add button and the context actions. */
|
|
47
|
+
editable?: boolean
|
|
48
|
+
/**
|
|
49
|
+
* Bump this whenever the workbook is mutated from OUTSIDE the strip - the
|
|
50
|
+
* Ctrl+PageUp/PageDown shortcuts, or app code calling `addSheet`.
|
|
51
|
+
*
|
|
52
|
+
* A `Workbook` is a plain object, not `$state`, so reading `workbook.sheets`
|
|
53
|
+
* creates no reactive dependency and the strip would otherwise render once
|
|
54
|
+
* and then show whatever the sheet list was at mount. Pass the same counter
|
|
55
|
+
* `onChange` increments.
|
|
56
|
+
*/
|
|
57
|
+
version?: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let { workbook, onChange, onRename, onRemove, onReturnFocus, hidden = [], onHide, onUnhide, onDuplicate, editable = true, version = 0 }: Props = $props()
|
|
61
|
+
|
|
62
|
+
const t = useSheetText()
|
|
63
|
+
|
|
64
|
+
let renaming = $state<string | null>(null)
|
|
65
|
+
let draft = $state('')
|
|
66
|
+
let error = $state<string | null>(null)
|
|
67
|
+
let dragging = $state<string | null>(null)
|
|
68
|
+
|
|
69
|
+
// The strip's own mutations do not go through the consumer's counter, so it
|
|
70
|
+
// keeps one of its own and reads both.
|
|
71
|
+
let localVersion = $state(0)
|
|
72
|
+
|
|
73
|
+
const isHidden = (name: string) => hidden.some((h) => h.toLowerCase() === name.toLowerCase())
|
|
74
|
+
/** The tabs drawn: the workbook's sheets less the hidden ones. */
|
|
75
|
+
const sheets = $derived.by(() => {
|
|
76
|
+
void version
|
|
77
|
+
void localVersion
|
|
78
|
+
return workbook.sheets.filter((name) => !isHidden(name))
|
|
79
|
+
})
|
|
80
|
+
const hiddenSheets = $derived.by(() => {
|
|
81
|
+
void version
|
|
82
|
+
void localVersion
|
|
83
|
+
return workbook.sheets.filter((name) => isHidden(name))
|
|
84
|
+
})
|
|
85
|
+
const activeSheet = $derived.by(() => {
|
|
86
|
+
void version
|
|
87
|
+
void localVersion
|
|
88
|
+
return workbook.active
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
function changed() {
|
|
92
|
+
localVersion += 1
|
|
93
|
+
onChange?.()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function select(name: string) {
|
|
97
|
+
workbook.setActive(name)
|
|
98
|
+
changed()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let renameInput = $state<HTMLInputElement | null>(null)
|
|
102
|
+
function startRename(name: string) {
|
|
103
|
+
if (!editable) return
|
|
104
|
+
renaming = name
|
|
105
|
+
draft = name
|
|
106
|
+
error = null
|
|
107
|
+
// Focused by hand rather than with `autofocus`, which only takes when
|
|
108
|
+
// nothing has the focus: the consumer may have just put it back on its
|
|
109
|
+
// cells after the click that preceded this double-click.
|
|
110
|
+
void tick().then(() => { renameInput?.focus(); renameInput?.select() })
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function commitRename() {
|
|
114
|
+
const from = renaming
|
|
115
|
+
if (from === null) return
|
|
116
|
+
const to = draft.trim()
|
|
117
|
+
renaming = null
|
|
118
|
+
if (to === '' || to === from) return
|
|
119
|
+
if (!isValidSheetName(to)) {
|
|
120
|
+
error = t('invalidSheetName', { name: to })
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
if (!workbook.renameSheet(from, to)) {
|
|
124
|
+
error = t('duplicateSheetName', { name: to })
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
error = null
|
|
128
|
+
onRename?.(from, to)
|
|
129
|
+
changed()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function focusActiveTab() {
|
|
133
|
+
void tick().then(() => strip?.querySelector<HTMLElement>('[role="tab"][aria-selected="true"]')?.focus())
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function add() {
|
|
137
|
+
workbook.addSheet()
|
|
138
|
+
changed()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Delete, once confirmed when the sheet holds anything, as Excel asks. */
|
|
142
|
+
let confirmDelete = $state<string | null>(null)
|
|
143
|
+
|
|
144
|
+
function hasContent(name: string): boolean {
|
|
145
|
+
for (let r = 0; r < workbook.rowCount(name); r += 1) {
|
|
146
|
+
for (let c = 0; c < workbook.colCount(name); c += 1) {
|
|
147
|
+
if (workbook.getRaw(name, r, c).trim() !== '') return true
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return false
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function askRemove(name: string) {
|
|
154
|
+
if (workbook.sheets.length < 2) return
|
|
155
|
+
if (hasContent(name)) confirmDelete = name
|
|
156
|
+
else remove(name)
|
|
157
|
+
}
|
|
158
|
+
/** The ribbon's Delete Sheet: the tab menu's Delete for the active sheet,
|
|
159
|
+
* with the same question first when the sheet holds anything. */
|
|
160
|
+
export function deleteSheet(name: string = workbook.active): void {
|
|
161
|
+
askRemove(name)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function remove(name: string) {
|
|
165
|
+
confirmDelete = null
|
|
166
|
+
// The workbook refuses to remove the last sheet; reflect that rather than
|
|
167
|
+
// showing a button that does nothing.
|
|
168
|
+
if (!workbook.removeSheet(name)) return
|
|
169
|
+
onRemove?.(name)
|
|
170
|
+
changed()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function hide(name: string) {
|
|
174
|
+
// Excel refuses to hide the last visible sheet.
|
|
175
|
+
if (sheets.length < 2) return
|
|
176
|
+
onHide?.(name)
|
|
177
|
+
changed()
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function unhide(name: string) {
|
|
181
|
+
onUnhide?.(name)
|
|
182
|
+
changed()
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function duplicate(name: string) {
|
|
186
|
+
onDuplicate?.(name)
|
|
187
|
+
changed()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ---- Excel's right-click menu on a tab ------------------------------------
|
|
191
|
+
let menu = $state<{ name: string; x: number; y: number } | null>(null)
|
|
192
|
+
|
|
193
|
+
function openMenu(event: MouseEvent, name: string) {
|
|
194
|
+
if (!editable) return
|
|
195
|
+
event.preventDefault()
|
|
196
|
+
select(name)
|
|
197
|
+
menu = { name, x: event.clientX, y: event.clientY }
|
|
198
|
+
}
|
|
199
|
+
/** An entry was taken: the menu goes, and the keyboard goes back to the
|
|
200
|
+
* consumer's cells, unless the entry opened something of its own (the
|
|
201
|
+
* rename input, the delete question), which hands it on itself. */
|
|
202
|
+
function closeMenu() {
|
|
203
|
+
menu = null
|
|
204
|
+
if (renaming === null && confirmDelete === null) onReturnFocus?.()
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The tabs sit at the foot of the sheet, so a menu dropped from the click
|
|
208
|
+
* runs off the bottom of the window; it opens upward from the click, as
|
|
209
|
+
* Excel's does, and is pulled back inside at the right edge.
|
|
210
|
+
*/
|
|
211
|
+
function keepMenuInView(node: HTMLElement, _at: { x: number; y: number } | null) {
|
|
212
|
+
const fit = () => {
|
|
213
|
+
const box = node.getBoundingClientRect()
|
|
214
|
+
if (!menu) return
|
|
215
|
+
const x = Math.max(8, Math.min(menu.x, window.innerWidth - box.width - 8))
|
|
216
|
+
const y = menu.y + box.height > window.innerHeight - 8 ? Math.max(8, menu.y - box.height) : menu.y
|
|
217
|
+
if (x !== menu.x || y !== menu.y) menu = { ...menu, x, y }
|
|
218
|
+
}
|
|
219
|
+
fit()
|
|
220
|
+
return { update: fit }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function moveBy(name: string, delta: -1 | 1) {
|
|
224
|
+
const at = workbook.sheets.indexOf(name)
|
|
225
|
+
const to = at + delta
|
|
226
|
+
if (at < 0 || to < 0 || to >= workbook.sheets.length) return
|
|
227
|
+
workbook.moveSheet(name, to)
|
|
228
|
+
changed()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function insertBefore(name: string) {
|
|
232
|
+
const at = workbook.sheets.indexOf(name)
|
|
233
|
+
const added = workbook.addSheet(undefined, Math.max(at, 0))
|
|
234
|
+
workbook.setActive(added)
|
|
235
|
+
changed()
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ---- the scroll arrows, for more tabs than fit --------------------------
|
|
239
|
+
// Excel greys each arrow until it can move something: with every tab in
|
|
240
|
+
// view both are grey, and at either end of a long strip the arrow that
|
|
241
|
+
// points off it is. Read from the strip's scroll box after every scroll,
|
|
242
|
+
// resize and tab change.
|
|
243
|
+
let strip = $state<HTMLDivElement | null>(null)
|
|
244
|
+
let canLeft = $state(false)
|
|
245
|
+
let canRight = $state(false)
|
|
246
|
+
function measureStrip() {
|
|
247
|
+
const el = strip
|
|
248
|
+
if (!el) { canLeft = false; canRight = false; return }
|
|
249
|
+
canLeft = el.scrollLeft > 1
|
|
250
|
+
canRight = el.scrollLeft + el.clientWidth < el.scrollWidth - 1
|
|
251
|
+
}
|
|
252
|
+
$effect(() => {
|
|
253
|
+
const el = strip
|
|
254
|
+
if (!el) return
|
|
255
|
+
void version
|
|
256
|
+
void sheets
|
|
257
|
+
measureStrip()
|
|
258
|
+
const ro = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(measureStrip)
|
|
259
|
+
ro?.observe(el)
|
|
260
|
+
el.addEventListener('scroll', measureStrip)
|
|
261
|
+
return () => { ro?.disconnect(); el.removeEventListener('scroll', measureStrip) }
|
|
262
|
+
})
|
|
263
|
+
function scrollTabs(delta: number) {
|
|
264
|
+
strip?.scrollBy({ left: delta, behavior: 'smooth' })
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function onDrop(target: string) {
|
|
268
|
+
const moved = dragging
|
|
269
|
+
dragging = null
|
|
270
|
+
if (!moved || moved === target) return
|
|
271
|
+
const to = workbook.sheets.indexOf(target)
|
|
272
|
+
if (to < 0) return
|
|
273
|
+
workbook.moveSheet(moved, to)
|
|
274
|
+
changed()
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** The arrows move between tabs and Home and End reach the ends, which is
|
|
278
|
+
* what a tablist owes a keyboard user; the shortcut layer's
|
|
279
|
+
* Ctrl+PageUp/Down does the same from anywhere in the grid. Focus follows
|
|
280
|
+
* the selection, and the arrows are mirrored on a right-to-left strip. */
|
|
281
|
+
function onTabKey(event: KeyboardEvent, name: string) {
|
|
282
|
+
if (event.key === 'F2') {
|
|
283
|
+
event.preventDefault()
|
|
284
|
+
startRename(name)
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
const at = sheets.indexOf(name)
|
|
288
|
+
const list = (event.currentTarget as HTMLElement).closest<HTMLElement>('[role="tablist"]')
|
|
289
|
+
const rtl = list ? getComputedStyle(list).direction === 'rtl' : false
|
|
290
|
+
const forward = rtl ? 'ArrowLeft' : 'ArrowRight'
|
|
291
|
+
const back = rtl ? 'ArrowRight' : 'ArrowLeft'
|
|
292
|
+
let next = -1
|
|
293
|
+
if (event.key === forward && at < sheets.length - 1) next = at + 1
|
|
294
|
+
else if (event.key === back && at > 0) next = at - 1
|
|
295
|
+
else if (event.key === 'Home') next = 0
|
|
296
|
+
else if (event.key === 'End') next = sheets.length - 1
|
|
297
|
+
if (next < 0 || next === at) return
|
|
298
|
+
event.preventDefault()
|
|
299
|
+
select(sheets[next]!)
|
|
300
|
+
void tick().then(() => list?.querySelector<HTMLElement>('[role="tab"][aria-selected="true"]')?.focus())
|
|
301
|
+
}
|
|
302
|
+
</script>
|
|
303
|
+
|
|
304
|
+
<svelte:window
|
|
305
|
+
onpointerdown={(e) => { if (menu && !(e.target as HTMLElement).closest('.sheet-menu')) menu = null }}
|
|
306
|
+
onkeydown={(e) => { if (e.key === 'Escape') menu = null }}
|
|
307
|
+
/>
|
|
308
|
+
|
|
309
|
+
<div class="sv-sheet-tabs">
|
|
310
|
+
<!-- Excel's tab-scrolling arrows: always drawn, greyed until they can move something. -->
|
|
311
|
+
<div class="nav">
|
|
312
|
+
<button type="button" class="nav-btn" tabindex="-1" aria-label={t('scrollTabsLeft')} disabled={!canLeft} onclick={() => scrollTabs(-120)}>
|
|
313
|
+
<svg viewBox="0 0 8 8" width="8" height="8"><path d="M5.5 1L2.5 4l3 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" /></svg>
|
|
314
|
+
</button>
|
|
315
|
+
<button type="button" class="nav-btn" tabindex="-1" aria-label={t('scrollTabsRight')} disabled={!canRight} onclick={() => scrollTabs(120)}>
|
|
316
|
+
<svg viewBox="0 0 8 8" width="8" height="8"><path d="M2.5 1l3 3-3 3" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" /></svg>
|
|
317
|
+
</button>
|
|
318
|
+
</div>
|
|
319
|
+
|
|
320
|
+
<div role="tablist" aria-label={t('sheets')} class="tabs" bind:this={strip}>
|
|
321
|
+
{#each sheets as name (name)}
|
|
322
|
+
{@const isActive = name === activeSheet}
|
|
323
|
+
<!-- role="presentation" so the tablist still OWNS the role="tab"
|
|
324
|
+
button: an unmarked wrapper div between them breaks the ARIA
|
|
325
|
+
tablist / tab relationship. -->
|
|
326
|
+
<div
|
|
327
|
+
role="presentation"
|
|
328
|
+
class="tab"
|
|
329
|
+
class:active={isActive}
|
|
330
|
+
class:dragging={dragging === name}
|
|
331
|
+
draggable={editable}
|
|
332
|
+
ondragstart={() => (dragging = name)}
|
|
333
|
+
ondragover={(e) => e.preventDefault()}
|
|
334
|
+
ondrop={() => onDrop(name)}
|
|
335
|
+
ondragend={() => (dragging = null)}
|
|
336
|
+
oncontextmenu={(e) => openMenu(e, name)}
|
|
337
|
+
>
|
|
338
|
+
{#if renaming === name}
|
|
339
|
+
<input
|
|
340
|
+
class="rename"
|
|
341
|
+
aria-label={t('sheetName')}
|
|
342
|
+
bind:this={renameInput}
|
|
343
|
+
value={draft}
|
|
344
|
+
oninput={(e) => (draft = e.currentTarget.value)}
|
|
345
|
+
onblur={commitRename}
|
|
346
|
+
onkeydown={(e) => {
|
|
347
|
+
// Enter and Escape hand the focus to the active tab, where a
|
|
348
|
+
// keyboard user came from; a click elsewhere keeps its own.
|
|
349
|
+
if (e.key === 'Enter') { e.preventDefault(); commitRename(); focusActiveTab() }
|
|
350
|
+
if (e.key === 'Escape') { e.preventDefault(); renaming = null; focusActiveTab() }
|
|
351
|
+
}}
|
|
352
|
+
/>
|
|
353
|
+
{:else}
|
|
354
|
+
<button
|
|
355
|
+
type="button"
|
|
356
|
+
role="tab"
|
|
357
|
+
aria-selected={isActive}
|
|
358
|
+
tabindex={isActive ? 0 : -1}
|
|
359
|
+
onclick={() => { select(name); onReturnFocus?.() }}
|
|
360
|
+
ondblclick={() => startRename(name)}
|
|
361
|
+
onkeydown={(e) => onTabKey(e, name)}
|
|
362
|
+
>{name}</button>
|
|
363
|
+
{/if}
|
|
364
|
+
</div>
|
|
365
|
+
{/each}
|
|
366
|
+
</div>
|
|
367
|
+
|
|
368
|
+
{#if editable}
|
|
369
|
+
<button type="button" class="add" aria-label={t('newSheet')} title={`${t('newSheet')} (Shift+F11)`} onclick={() => { add(); onReturnFocus?.() }}>
|
|
370
|
+
<svg viewBox="0 0 10 10" width="10" height="10" aria-hidden="true"><path d="M5 1.5v7M1.5 5h7" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" /></svg>
|
|
371
|
+
</button>
|
|
372
|
+
{/if}
|
|
373
|
+
|
|
374
|
+
{#if error}
|
|
375
|
+
<span class="error" role="alert">{error}</span>
|
|
376
|
+
{/if}
|
|
377
|
+
</div>
|
|
378
|
+
|
|
379
|
+
{#if menu}
|
|
380
|
+
<!--
|
|
381
|
+
The sheet menu Excel opens on right-click. Delete lives here and nowhere
|
|
382
|
+
on the tab face, so a stray click cannot remove a sheet.
|
|
383
|
+
-->
|
|
384
|
+
<div class="sheet-menu" role="menu" aria-label={`${menu.name} sheet`} style:left={`${menu.x}px`} style:top={`${menu.y}px`} use:keepMenuInView={menu}>
|
|
385
|
+
<button type="button" role="menuitem" onclick={() => { insertBefore(menu!.name); closeMenu() }}>{t('tabInsert')}</button>
|
|
386
|
+
<button type="button" role="menuitem" disabled={workbook.sheets.length < 2} onclick={() => { askRemove(menu!.name); closeMenu() }}>{t('tabDelete')}</button>
|
|
387
|
+
<button type="button" role="menuitem" onclick={() => { startRename(menu!.name); menu = null }}>{t('tabRename')}</button>
|
|
388
|
+
{#if onDuplicate}
|
|
389
|
+
<button type="button" role="menuitem" onclick={() => { duplicate(menu!.name); closeMenu() }}>{t('tabDuplicate')}</button>
|
|
390
|
+
{/if}
|
|
391
|
+
<div class="sep" role="separator"></div>
|
|
392
|
+
<button type="button" role="menuitem" disabled={sheets.indexOf(menu.name) === 0} onclick={() => { moveBy(menu!.name, -1); closeMenu() }}>{t('tabMoveLeft')}</button>
|
|
393
|
+
<button type="button" role="menuitem" disabled={sheets.indexOf(menu.name) === sheets.length - 1} onclick={() => { moveBy(menu!.name, 1); closeMenu() }}>{t('tabMoveRight')}</button>
|
|
394
|
+
{#if onHide}
|
|
395
|
+
<div class="sep" role="separator"></div>
|
|
396
|
+
<button type="button" role="menuitem" disabled={sheets.length < 2} onclick={() => { hide(menu!.name); closeMenu() }}>{t('tabHide')}</button>
|
|
397
|
+
{#if hiddenSheets.length}
|
|
398
|
+
<!-- Excel's Unhide opens a list; here each hidden sheet is an entry. -->
|
|
399
|
+
<div class="heading" role="presentation">{t('tabUnhide')}</div>
|
|
400
|
+
{#each hiddenSheets as name (name)}
|
|
401
|
+
<button type="button" role="menuitem" class="indent" onclick={() => { unhide(name); closeMenu() }}>{name}</button>
|
|
402
|
+
{/each}
|
|
403
|
+
{/if}
|
|
404
|
+
{/if}
|
|
405
|
+
</div>
|
|
406
|
+
{/if}
|
|
407
|
+
|
|
408
|
+
<SvModal open={confirmDelete !== null} title={t('deleteSheetTitle')} size="sm" onClose={() => (confirmDelete = null)}>
|
|
409
|
+
<div class="sv-sheet-dialog">
|
|
410
|
+
<p class="note">{t('deleteSheetMessage', { name: confirmDelete ?? '' })}</p>
|
|
411
|
+
</div>
|
|
412
|
+
{#snippet footer()}
|
|
413
|
+
<div class="sv-sheet-dialog-buttons">
|
|
414
|
+
<button type="button" class="btn primary" onclick={() => { if (confirmDelete) remove(confirmDelete); onReturnFocus?.() }}>{t('delete')}</button>
|
|
415
|
+
<button type="button" class="btn" onclick={() => { confirmDelete = null; onReturnFocus?.() }}>{t('cancel')}</button>
|
|
416
|
+
</div>
|
|
417
|
+
{/snippet}
|
|
418
|
+
</SvModal>
|
|
419
|
+
|
|
420
|
+
<style>
|
|
421
|
+
.sv-sheet-tabs {
|
|
422
|
+
display: flex;
|
|
423
|
+
align-items: stretch;
|
|
424
|
+
height: 26px;
|
|
425
|
+
font-family: var(--sg-font, "Segoe UI", system-ui, sans-serif);
|
|
426
|
+
font-size: 12px;
|
|
427
|
+
background: var(--sg-header-bg, #f3f3f3);
|
|
428
|
+
border-top: 1px solid var(--sg-border, #d1d1d1);
|
|
429
|
+
color: var(--sg-fg, #242424);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.nav {
|
|
433
|
+
display: flex;
|
|
434
|
+
align-items: center;
|
|
435
|
+
padding: 0 4px 0 6px;
|
|
436
|
+
gap: 2px;
|
|
437
|
+
color: var(--sg-muted, #616161);
|
|
438
|
+
}
|
|
439
|
+
.nav-btn {
|
|
440
|
+
display: inline-flex;
|
|
441
|
+
align-items: center;
|
|
442
|
+
justify-content: center;
|
|
443
|
+
width: 14px;
|
|
444
|
+
height: 18px;
|
|
445
|
+
padding: 0;
|
|
446
|
+
border: 0;
|
|
447
|
+
border-radius: 2px;
|
|
448
|
+
background: transparent;
|
|
449
|
+
color: inherit;
|
|
450
|
+
cursor: pointer;
|
|
451
|
+
}
|
|
452
|
+
.nav-btn:hover:not(:disabled) { background: var(--sg-row-hover-bg, #e6e6e6); color: var(--sg-fg, #242424); }
|
|
453
|
+
.nav-btn:disabled { opacity: 0.35; cursor: default; }
|
|
454
|
+
|
|
455
|
+
.tabs {
|
|
456
|
+
display: flex;
|
|
457
|
+
align-items: stretch;
|
|
458
|
+
overflow-x: auto;
|
|
459
|
+
scrollbar-width: none;
|
|
460
|
+
}
|
|
461
|
+
.tabs::-webkit-scrollbar { display: none; }
|
|
462
|
+
|
|
463
|
+
/* Excel's tabs: grey strip, the active one lifted to white with the accent
|
|
464
|
+
drawn as a line along its bottom edge and its name in the accent. */
|
|
465
|
+
.tab {
|
|
466
|
+
position: relative;
|
|
467
|
+
display: flex;
|
|
468
|
+
align-items: stretch;
|
|
469
|
+
min-width: 64px;
|
|
470
|
+
border-right: 1px solid var(--sg-border, #d1d1d1);
|
|
471
|
+
}
|
|
472
|
+
.tab:first-child { border-left: 1px solid var(--sg-border, #d1d1d1); }
|
|
473
|
+
.tab.active {
|
|
474
|
+
background: var(--sg-bg, #fff);
|
|
475
|
+
box-shadow: inset 0 -2px 0 0 var(--sg-accent, #107c41);
|
|
476
|
+
}
|
|
477
|
+
.tab.active button {
|
|
478
|
+
/* Mixed toward the text colour: the raw accent under 4.5:1 on the
|
|
479
|
+
lifted white tab is what axe finds and a low-vision reader feels.
|
|
480
|
+
The line along the bottom edge above keeps the accent pure. */
|
|
481
|
+
color: color-mix(in srgb, var(--sg-accent, #107c41) 72%, var(--sg-fg, #242424));
|
|
482
|
+
font-weight: 600;
|
|
483
|
+
}
|
|
484
|
+
.tab:not(.active):hover { background: var(--sg-row-hover-bg, #e9e9e9); }
|
|
485
|
+
.tab.dragging { opacity: 0.5; }
|
|
486
|
+
button[role='tab'] {
|
|
487
|
+
flex: 1 1 auto;
|
|
488
|
+
font: inherit;
|
|
489
|
+
border: 0;
|
|
490
|
+
background: transparent;
|
|
491
|
+
color: var(--sg-muted, #444);
|
|
492
|
+
padding: 0 12px;
|
|
493
|
+
cursor: pointer;
|
|
494
|
+
white-space: nowrap;
|
|
495
|
+
text-align: center;
|
|
496
|
+
}
|
|
497
|
+
button[role='tab']:focus-visible {
|
|
498
|
+
outline: 2px solid var(--sg-focus-ring, var(--sg-accent, #107c41));
|
|
499
|
+
outline-offset: -2px;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.add {
|
|
503
|
+
align-self: center;
|
|
504
|
+
display: inline-flex;
|
|
505
|
+
align-items: center;
|
|
506
|
+
justify-content: center;
|
|
507
|
+
width: 18px;
|
|
508
|
+
height: 18px;
|
|
509
|
+
margin-left: 6px;
|
|
510
|
+
padding: 0;
|
|
511
|
+
border: 1px solid var(--sg-border, #c8c6c4);
|
|
512
|
+
border-radius: 50%;
|
|
513
|
+
background: var(--sg-bg, #fff);
|
|
514
|
+
color: var(--sg-muted, #616161);
|
|
515
|
+
cursor: pointer;
|
|
516
|
+
}
|
|
517
|
+
.add:hover { color: var(--sg-fg, #242424); border-color: var(--sg-muted, #8a8886); }
|
|
518
|
+
.add:focus-visible {
|
|
519
|
+
outline: 2px solid var(--sg-focus-ring, var(--sg-accent, #107c41));
|
|
520
|
+
outline-offset: 1px;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.rename {
|
|
524
|
+
font: inherit;
|
|
525
|
+
width: 92px;
|
|
526
|
+
margin: 2px 4px;
|
|
527
|
+
border: 1px solid var(--sg-accent, #107c41);
|
|
528
|
+
border-radius: 2px;
|
|
529
|
+
padding: 1px 4px;
|
|
530
|
+
background: var(--sg-input-bg, var(--sg-bg, #fff));
|
|
531
|
+
color: var(--sg-fg, #242424);
|
|
532
|
+
}
|
|
533
|
+
.error {
|
|
534
|
+
align-self: center;
|
|
535
|
+
margin-left: 8px;
|
|
536
|
+
color: var(--sg-danger, #dc2626);
|
|
537
|
+
font-size: 12px;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.sheet-menu {
|
|
541
|
+
position: fixed;
|
|
542
|
+
z-index: 1000;
|
|
543
|
+
min-width: 150px;
|
|
544
|
+
padding: 4px;
|
|
545
|
+
font-family: var(--sg-font, "Segoe UI", system-ui, sans-serif);
|
|
546
|
+
font-size: 12px;
|
|
547
|
+
background: var(--sg-bg, #fff);
|
|
548
|
+
color: var(--sg-fg, #242424);
|
|
549
|
+
border: 1px solid var(--sg-border, #d1d1d1);
|
|
550
|
+
border-radius: 4px;
|
|
551
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 0.14);
|
|
552
|
+
}
|
|
553
|
+
.sheet-menu button {
|
|
554
|
+
display: block;
|
|
555
|
+
width: 100%;
|
|
556
|
+
padding: 5px 10px;
|
|
557
|
+
font: inherit;
|
|
558
|
+
text-align: left;
|
|
559
|
+
border: 0;
|
|
560
|
+
border-radius: 3px;
|
|
561
|
+
background: transparent;
|
|
562
|
+
color: inherit;
|
|
563
|
+
cursor: pointer;
|
|
564
|
+
}
|
|
565
|
+
.sheet-menu button:hover:not(:disabled) { background: var(--sg-row-hover-bg, #f0f0f0); }
|
|
566
|
+
.sheet-menu button:disabled { opacity: 0.4; cursor: default; }
|
|
567
|
+
.sheet-menu .sep { height: 1px; margin: 4px 6px; background: var(--sg-border, #e0e0e0); }
|
|
568
|
+
.sheet-menu .heading { padding: 4px 10px 2px; color: var(--sg-muted, #616161); font-size: 11px; }
|
|
569
|
+
.sheet-menu button.indent { padding-left: 22px; }
|
|
570
|
+
.note { margin: 0; }
|
|
571
|
+
</style>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Workbook } from './sheet/workbook.js';
|
|
2
|
+
type Props = {
|
|
3
|
+
workbook: Workbook;
|
|
4
|
+
/** Called after any change, so the consumer can re-render. */
|
|
5
|
+
onChange?: () => void;
|
|
6
|
+
/**
|
|
7
|
+
* Called after a sheet is renamed or removed, before `onChange`. Anything
|
|
8
|
+
* the consumer keeps per sheet and keys by name - the shell keeps a
|
|
9
|
+
* format store per sheet - has to follow the rename or drop the entry,
|
|
10
|
+
* and the workbook itself has no event for either.
|
|
11
|
+
*/
|
|
12
|
+
onRename?: (from: string, to: string) => void;
|
|
13
|
+
onRemove?: (name: string) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Called when a pointer action on the strip is over: a tab clicked, the
|
|
16
|
+
* add button, an entry of the tab menu, a delete confirmed. Each leaves
|
|
17
|
+
* the focus on a button or nowhere; a consumer whose cells should keep
|
|
18
|
+
* the keyboard, as a spreadsheet's do, puts it back from here. Not
|
|
19
|
+
* called for the arrow keys inside the strip, which keep the focus on
|
|
20
|
+
* the tab they moved to, nor after a rename ends, which goes to its tab.
|
|
21
|
+
*/
|
|
22
|
+
onReturnFocus?: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* The sheets that are hidden: their tabs are not drawn and the menu
|
|
25
|
+
* offers Unhide for each. The consumer keeps the list (the shell keeps
|
|
26
|
+
* it in the document) and answers `onHide` / `onUnhide`.
|
|
27
|
+
*/
|
|
28
|
+
hidden?: ReadonlyArray<string>;
|
|
29
|
+
onHide?: (name: string) => void;
|
|
30
|
+
onUnhide?: (name: string) => void;
|
|
31
|
+
/** Excel's Move or Copy > Create a copy. Without it the entry is not offered. */
|
|
32
|
+
onDuplicate?: (name: string) => void;
|
|
33
|
+
/** Off hides the add button and the context actions. */
|
|
34
|
+
editable?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Bump this whenever the workbook is mutated from OUTSIDE the strip - the
|
|
37
|
+
* Ctrl+PageUp/PageDown shortcuts, or app code calling `addSheet`.
|
|
38
|
+
*
|
|
39
|
+
* A `Workbook` is a plain object, not `$state`, so reading `workbook.sheets`
|
|
40
|
+
* creates no reactive dependency and the strip would otherwise render once
|
|
41
|
+
* and then show whatever the sheet list was at mount. Pass the same counter
|
|
42
|
+
* `onChange` increments.
|
|
43
|
+
*/
|
|
44
|
+
version?: number;
|
|
45
|
+
};
|
|
46
|
+
declare const SvSheetTabs: import("svelte").Component<Props, {
|
|
47
|
+
deleteSheet: (name?: string) => void;
|
|
48
|
+
}, "">;
|
|
49
|
+
type SvSheetTabs = ReturnType<typeof SvSheetTabs>;
|
|
50
|
+
export default SvSheetTabs;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test-only harness for SvSheetTabs.
|
|
3
|
+
*
|
|
4
|
+
* `mount()` takes a plain props object, and a plain object's fields are not
|
|
5
|
+
* reactive, so a test cannot change a prop after mounting and see the
|
|
6
|
+
* component respond. This box holds the props in `$state` so it can - which is
|
|
7
|
+
* what proves the strip follows an OUTSIDE workbook mutation (Ctrl+PageUp and
|
|
8
|
+
* friends) rather than only its own button clicks.
|
|
9
|
+
*
|
|
10
|
+
* Runes only compile in `.svelte.ts`, hence the separate file. The `.test.`
|
|
11
|
+
* segment keeps it out of the published tarball (tools/strip-dist-tests.mjs)
|
|
12
|
+
* and out of vitest's `*.dom.test.ts` include.
|
|
13
|
+
*/
|
|
14
|
+
export declare function reactiveProps<T extends Record<string, unknown>>(initial: T): {
|
|
15
|
+
props: T;
|
|
16
|
+
set(patch: Partial<T>): void;
|
|
17
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test-only harness for SvSheetTabs.
|
|
3
|
+
*
|
|
4
|
+
* `mount()` takes a plain props object, and a plain object's fields are not
|
|
5
|
+
* reactive, so a test cannot change a prop after mounting and see the
|
|
6
|
+
* component respond. This box holds the props in `$state` so it can - which is
|
|
7
|
+
* what proves the strip follows an OUTSIDE workbook mutation (Ctrl+PageUp and
|
|
8
|
+
* friends) rather than only its own button clicks.
|
|
9
|
+
*
|
|
10
|
+
* Runes only compile in `.svelte.ts`, hence the separate file. The `.test.`
|
|
11
|
+
* segment keeps it out of the published tarball (tools/strip-dist-tests.mjs)
|
|
12
|
+
* and out of vitest's `*.dom.test.ts` include.
|
|
13
|
+
*/
|
|
14
|
+
export function reactiveProps(initial) {
|
|
15
|
+
const box = $state({ ...initial });
|
|
16
|
+
return {
|
|
17
|
+
props: box,
|
|
18
|
+
set(patch) {
|
|
19
|
+
Object.assign(box, patch);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|