@veltra/sheet 2.0.1 → 2.2.0
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/dist/components/report/binding-badge.js +76 -0
- package/dist/components/report/designer/cell-coords.js +46 -0
- package/dist/components/report/designer/col-widths.js +15 -0
- package/dist/components/report/designer/conditional-rules/helpers.js +139 -0
- package/dist/components/report/designer/drop-highlight-overlay.js +76 -0
- package/dist/components/report/designer/float-panel.js +385 -0
- package/dist/components/report/designer/role.js +17 -0
- package/dist/components/report/designer/rule-preview.js +33 -0
- package/dist/components/report/designer/rule-row.js +269 -0
- package/dist/components/report/designer/rules-dialog.js +135 -0
- package/dist/components/report/designer/topology-overlay.js +122 -0
- package/dist/components/report/designer/topology.js +64 -0
- package/dist/components/report/designer/use-grid-overlay.js +75 -0
- package/dist/components/report/designer-hub.js +177 -0
- package/dist/components/report/field-panel-helpers.js +33 -0
- package/dist/components/report/field-panel.js +132 -0
- package/dist/components/report/filter-bar.js +74 -0
- package/dist/components/report/hub-connection-form.js +145 -0
- package/dist/components/report/hub-dataset-editor.js +394 -0
- package/dist/components/report/report-designer.js +343 -0
- package/dist/components/report/report-viewer.js +111 -0
- package/dist/components/report/style.d.ts +17 -0
- package/dist/components/report/style.js +18 -0
- package/dist/components/report/style2.css +869 -0
- package/dist/components/report/use-report-designer.js +360 -0
- package/dist/components/report/use-report-viewer.js +50 -0
- package/dist/components/sheet/formula-bar.js +393 -0
- package/dist/components/sheet/formula-suggest-list.js +66 -0
- package/dist/components/sheet/import-file.js +140 -0
- package/dist/components/sheet/insert-count-menu-item.js +68 -0
- package/dist/components/sheet/insert-image.js +79 -0
- package/dist/components/sheet/popup-helpers.js +73 -0
- package/dist/components/sheet/popups/border-popup.js +75 -0
- package/dist/components/sheet/popups/border-preset-glyph.js +106 -0
- package/dist/components/sheet/popups/export-popup.js +51 -0
- package/dist/components/sheet/popups/fill-color-popup.js +37 -0
- package/dist/components/sheet/popups/find-popup.js +113 -0
- package/dist/components/sheet/popups/font-color-popup.js +37 -0
- package/dist/components/sheet/popups/font-size-popup.js +63 -0
- package/dist/components/sheet/popups/import.worker.d.ts +21 -0
- package/dist/components/sheet/popups/import.worker.js +41 -0
- package/dist/components/sheet/popups/insert-image-popup.js +38 -0
- package/dist/components/sheet/sheet-context-menu.js +200 -0
- package/dist/components/sheet/sheet-tabs.js +162 -0
- package/dist/components/sheet/sheet-toolbar.js +106 -0
- package/dist/components/sheet/sheet.js +198 -0
- package/dist/components/sheet/style.d.ts +11 -0
- package/dist/components/sheet/style.js +12 -0
- package/dist/components/sheet/style2.css +654 -0
- package/dist/components/sheet/use-find-replace.js +161 -0
- package/dist/components/sheet/use-formula-ref-select.js +37 -0
- package/dist/components/sheet/use-formula-suggest.js +126 -0
- package/dist/components/sheet/use-sheet-grid.js +188 -0
- package/dist/components/sheet/use-sheet-state.js +122 -0
- package/dist/components/sheet/use-sheet-tabs-bar.js +90 -0
- package/dist/components/sheet/use-tool-groups.js +42 -0
- package/dist/components/sheet/use-tool-popup.js +123 -0
- package/dist/components/sheet/use-toolbar-scroll.js +72 -0
- package/dist/index.d.ts +18 -26
- package/dist/index.js +14 -24
- package/dist/report/binding.d.ts +45 -0
- package/dist/report/binding.js +175 -0
- package/dist/report/connector.d.ts +66 -0
- package/dist/report/connector.js +159 -0
- package/dist/report/export-xlsx.d.ts +19 -0
- package/dist/report/export-xlsx.js +95 -0
- package/dist/report/filter-bar.d.ts +10 -0
- package/dist/report/filter-bar.js +31 -0
- package/dist/report/index.d.ts +12 -0
- package/dist/report/params.d.ts +13 -0
- package/dist/report/params.js +61 -0
- package/dist/report/render/aggregate.js +157 -0
- package/dist/report/render/builder.d.ts +12 -0
- package/dist/report/render/builder.js +139 -0
- package/dist/report/render/coordinate.d.ts +25 -0
- package/dist/report/render/coordinate.js +733 -0
- package/dist/report/render/index.d.ts +14 -0
- package/dist/report/render/index.js +21 -0
- package/dist/report/render/style-resolver.js +50 -0
- package/dist/report/render/template-index.d.ts +24 -0
- package/dist/report/render/template-index.js +137 -0
- package/dist/report/rules/evaluate.d.ts +25 -0
- package/dist/report/rules/evaluate.js +82 -0
- package/dist/report/rules/index.d.ts +2 -0
- package/dist/report/template.d.ts +59 -0
- package/dist/report/template.js +80 -0
- package/dist/report/types.d.ts +85 -0
- package/dist/tools/builtin.js +279 -8
- package/dist/tools/context.d.ts +54 -11
- package/dist/tools/context.js +28 -5
- package/dist/tools/download.js +68 -0
- package/dist/tools/export.worker.d.ts +16 -0
- package/dist/tools/export.worker.js +29 -0
- package/dist/tools/registry.d.ts +7 -4
- package/dist/tools/registry.js +1 -3
- package/dist/types/index.d.ts +3 -1
- package/dist/types/report-designer.d.ts +36 -0
- package/dist/types/report-viewer.d.ts +38 -0
- package/dist/types/sheet.d.ts +22 -5
- package/package.json +10 -7
- package/src/components/report/__test__/conditional-rules-helpers.test.ts +87 -0
- package/src/components/report/__test__/field-panel-helpers.test.ts +65 -0
- package/src/components/report/__test__/float-panel-position.test.ts +45 -0
- package/src/components/report/__test__/report-designer.test.ts +388 -0
- package/src/components/report/__test__/report-viewer.test.ts +334 -0
- package/src/components/report/__test__/topology.test.ts +143 -0
- package/src/components/report/__test__/use-report-designer.test.ts +565 -0
- package/src/components/report/binding-badge.ts +73 -0
- package/src/components/report/designer/cell-coords.ts +94 -0
- package/src/components/report/designer/col-widths.ts +33 -0
- package/src/components/report/designer/conditional-rules/helpers.ts +186 -0
- package/src/components/report/designer/drop-highlight-overlay.vue +74 -0
- package/src/components/report/designer/float-panel.vue +387 -0
- package/src/components/report/designer/role.ts +32 -0
- package/src/components/report/designer/rule-preview.vue +40 -0
- package/src/components/report/designer/rule-row.vue +252 -0
- package/src/components/report/designer/rules-dialog.vue +126 -0
- package/src/components/report/designer/topology-overlay.vue +127 -0
- package/src/components/report/designer/topology.ts +124 -0
- package/src/components/report/designer/use-grid-overlay.ts +113 -0
- package/src/components/report/designer-hub.vue +198 -0
- package/src/components/report/field-panel-helpers.ts +44 -0
- package/src/components/report/field-panel.vue +136 -0
- package/src/components/report/filter-bar.vue +77 -0
- package/src/components/report/hub-connection-form.vue +124 -0
- package/src/components/report/hub-dataset-editor.vue +369 -0
- package/src/components/report/index.ts +2 -0
- package/src/components/report/report-designer.vue +356 -0
- package/src/components/report/report-viewer.vue +128 -0
- package/src/components/report/style-designer.scss +583 -0
- package/src/components/report/style-hub.scss +292 -0
- package/src/components/report/style-viewer.scss +104 -0
- package/src/components/report/style.scss +3 -0
- package/src/components/report/style.ts +20 -0
- package/src/components/report/use-report-designer.ts +547 -0
- package/src/components/report/use-report-viewer.ts +79 -0
- package/src/components/sheet/__test__/formula-bar.test.ts +474 -0
- package/src/components/sheet/__test__/import-file.test.ts +183 -0
- package/src/components/sheet/__test__/insert-count-menu-item.test.ts +123 -0
- package/src/components/sheet/__test__/insert-image-popup.test.ts +89 -0
- package/src/components/sheet/__test__/insert-image.test.ts +100 -0
- package/src/components/sheet/__test__/sheet-component.test.ts +993 -0
- package/src/components/sheet/__test__/sheet-context-menu.test.ts +206 -0
- package/src/components/sheet/__test__/use-formula-ref-select.test.ts +35 -0
- package/src/components/sheet/__test__/use-formula-suggest.test.ts +83 -0
- package/src/components/sheet/formula-bar.vue +473 -0
- package/src/components/sheet/formula-suggest-list.vue +64 -0
- package/src/components/sheet/import-file.ts +173 -0
- package/src/components/sheet/insert-count-menu-item.vue +69 -0
- package/src/components/sheet/insert-image.ts +90 -0
- package/src/components/sheet/parsing.ts +11 -0
- package/src/components/sheet/popup-helpers.ts +50 -0
- package/src/components/sheet/popups/border-popup.vue +93 -0
- package/src/components/sheet/popups/border-preset-glyph.vue +111 -0
- package/src/components/sheet/popups/export-popup.vue +52 -0
- package/src/components/sheet/popups/fill-color-popup.vue +39 -0
- package/src/components/sheet/popups/find-popup.vue +111 -0
- package/src/components/sheet/popups/font-color-popup.vue +39 -0
- package/src/components/sheet/popups/font-size-popup.vue +52 -0
- package/src/components/sheet/popups/import.worker.ts +66 -0
- package/src/components/sheet/popups/insert-image-popup.vue +39 -0
- package/src/components/sheet/sheet-context-menu.ts +229 -0
- package/src/components/sheet/sheet-tabs.vue +162 -0
- package/src/components/sheet/sheet-toolbar.vue +91 -0
- package/src/components/sheet/sheet.vue +211 -0
- package/src/components/sheet/style.scss +737 -0
- package/src/components/sheet/style.ts +13 -0
- package/src/components/sheet/use-find-replace.ts +200 -0
- package/src/components/sheet/use-formula-ref-select.ts +34 -0
- package/src/components/sheet/use-formula-suggest.ts +150 -0
- package/src/components/sheet/use-sheet-grid.ts +247 -0
- package/src/components/sheet/use-sheet-state.ts +161 -0
- package/src/components/sheet/use-sheet-tabs-bar.ts +115 -0
- package/src/components/sheet/use-tool-groups.ts +61 -0
- package/src/components/sheet/use-tool-popup.ts +150 -0
- package/src/components/sheet/use-toolbar-scroll.ts +95 -0
- package/src/env.d.ts +11 -0
- package/src/index.ts +39 -14
- package/src/report/__test__/binding.test.ts +218 -0
- package/src/report/__test__/connector.test.ts +218 -0
- package/src/report/__test__/export-xlsx.test.ts +118 -0
- package/src/report/__test__/filter-bar.test.ts +58 -0
- package/src/report/__test__/params.test.ts +156 -0
- package/src/report/__test__/render.test.ts +728 -0
- package/src/report/__test__/rules.test.ts +131 -0
- package/src/report/__test__/template.test.ts +355 -0
- package/src/report/binding.ts +243 -0
- package/src/report/connector.ts +205 -0
- package/src/report/export-xlsx.ts +118 -0
- package/src/report/filter-bar.ts +36 -0
- package/src/report/index.ts +13 -0
- package/src/report/params.ts +96 -0
- package/src/report/render/__test__/aggregate.test.ts +16 -0
- package/src/report/render/__test__/coordinate.test.ts +405 -0
- package/src/report/render/aggregate.ts +240 -0
- package/src/report/render/builder.ts +211 -0
- package/src/report/render/coordinate.ts +1239 -0
- package/src/report/render/index.ts +30 -0
- package/src/report/render/style-resolver.ts +68 -0
- package/src/report/render/template-index.ts +200 -0
- package/src/report/rules/evaluate.ts +113 -0
- package/src/report/rules/index.ts +7 -0
- package/src/report/template.ts +141 -0
- package/src/report/types.ts +96 -0
- package/src/tools/__test__/builtin.test.ts +208 -66
- package/src/tools/__test__/context.test.ts +62 -2
- package/src/tools/builtin.ts +350 -6
- package/src/tools/context.ts +89 -11
- package/src/tools/download.ts +82 -0
- package/src/tools/export.worker.ts +61 -0
- package/src/tools/registry.ts +16 -1
- package/src/types/index.ts +2 -0
- package/src/types/report-designer.ts +36 -0
- package/src/types/report-viewer.ts +37 -0
- package/src/types/sheet.ts +26 -3
- package/dist/core/address.d.ts +0 -60
- package/dist/core/address.js +0 -142
- package/dist/core/address.js.map +0 -1
- package/dist/core/cell-store.d.ts +0 -61
- package/dist/core/cell-store.js +0 -135
- package/dist/core/cell-store.js.map +0 -1
- package/dist/core/command/default-registry.d.ts +0 -10
- package/dist/core/command/default-registry.js +0 -18
- package/dist/core/command/default-registry.js.map +0 -1
- package/dist/core/command/history.d.ts +0 -64
- package/dist/core/command/history.js +0 -127
- package/dist/core/command/history.js.map +0 -1
- package/dist/core/command/merge-cells.d.ts +0 -21
- package/dist/core/command/merge-cells.js +0 -74
- package/dist/core/command/merge-cells.js.map +0 -1
- package/dist/core/command/registry.d.ts +0 -17
- package/dist/core/command/registry.js +0 -26
- package/dist/core/command/registry.js.map +0 -1
- package/dist/core/command/set-cell-formula.d.ts +0 -17
- package/dist/core/command/set-cell-formula.js +0 -29
- package/dist/core/command/set-cell-formula.js.map +0 -1
- package/dist/core/command/set-cell-value.d.ts +0 -22
- package/dist/core/command/set-cell-value.js +0 -35
- package/dist/core/command/set-cell-value.js.map +0 -1
- package/dist/core/command/types.d.ts +0 -68
- package/dist/core/events.js +0 -29
- package/dist/core/events.js.map +0 -1
- package/dist/core/fill.d.ts +0 -34
- package/dist/core/fill.js +0 -320
- package/dist/core/fill.js.map +0 -1
- package/dist/core/formula/ast.d.ts +0 -58
- package/dist/core/formula/ast.js +0 -38
- package/dist/core/formula/ast.js.map +0 -1
- package/dist/core/formula/dependency-graph.d.ts +0 -70
- package/dist/core/formula/dependency-graph.js +0 -269
- package/dist/core/formula/dependency-graph.js.map +0 -1
- package/dist/core/formula/errors.d.ts +0 -25
- package/dist/core/formula/errors.js +0 -36
- package/dist/core/formula/errors.js.map +0 -1
- package/dist/core/formula/evaluator.d.ts +0 -41
- package/dist/core/formula/evaluator.js +0 -154
- package/dist/core/formula/evaluator.js.map +0 -1
- package/dist/core/formula/functions.d.ts +0 -30
- package/dist/core/formula/functions.js +0 -209
- package/dist/core/formula/functions.js.map +0 -1
- package/dist/core/formula/parser.d.ts +0 -7
- package/dist/core/formula/parser.js +0 -208
- package/dist/core/formula/parser.js.map +0 -1
- package/dist/core/formula/tokenizer.d.ts +0 -37
- package/dist/core/formula/tokenizer.js +0 -146
- package/dist/core/formula/tokenizer.js.map +0 -1
- package/dist/core/merge-manager.d.ts +0 -64
- package/dist/core/merge-manager.js +0 -111
- package/dist/core/merge-manager.js.map +0 -1
- package/dist/core/selection.d.ts +0 -31
- package/dist/core/selection.js +0 -62
- package/dist/core/selection.js.map +0 -1
- package/dist/core/sheet.d.ts +0 -116
- package/dist/core/sheet.js +0 -224
- package/dist/core/sheet.js.map +0 -1
- package/dist/core/workbook.d.ts +0 -43
- package/dist/core/workbook.js +0 -77
- package/dist/core/workbook.js.map +0 -1
- package/dist/grid/sheet-grid.d.ts +0 -81
- package/dist/grid/sheet-grid.js +0 -331
- package/dist/grid/sheet-grid.js.map +0 -1
- package/dist/grid/vtable-theme.js +0 -80
- package/dist/grid/vtable-theme.js.map +0 -1
- package/dist/tools/builtin.js.map +0 -1
- package/dist/tools/context.js.map +0 -1
- package/dist/tools/registry.js.map +0 -1
- package/dist/vue/index.d.ts +0 -2
- package/dist/vue/sheet.js +0 -211
- package/dist/vue/sheet.js.map +0 -1
- package/dist/vue/sheet.vue.d.ts +0 -24
- package/dist/vue/style.d.ts +0 -1
- package/dist/vue/style.js +0 -2
- package/dist/vue/style2.css +0 -93
- package/src/core/__test__/address.test.ts +0 -113
- package/src/core/__test__/cell-store.test.ts +0 -97
- package/src/core/__test__/command.test.ts +0 -377
- package/src/core/__test__/fill.test.ts +0 -140
- package/src/core/__test__/formula-adversarial.test.ts +0 -265
- package/src/core/__test__/formula-engine.test.ts +0 -470
- package/src/core/__test__/formula-functions.test.ts +0 -178
- package/src/core/__test__/formula-parser.test.ts +0 -160
- package/src/core/__test__/history.test.ts +0 -225
- package/src/core/__test__/merge-manager.test.ts +0 -106
- package/src/core/__test__/sheet.test.ts +0 -142
- package/src/core/address.ts +0 -166
- package/src/core/cell-store.ts +0 -173
- package/src/core/command/default-registry.ts +0 -15
- package/src/core/command/history.ts +0 -167
- package/src/core/command/index.ts +0 -7
- package/src/core/command/merge-cells.ts +0 -74
- package/src/core/command/registry.ts +0 -30
- package/src/core/command/set-cell-formula.ts +0 -29
- package/src/core/command/set-cell-value.ts +0 -38
- package/src/core/command/types.ts +0 -73
- package/src/core/events.ts +0 -37
- package/src/core/fill.ts +0 -314
- package/src/core/formula/ast.ts +0 -66
- package/src/core/formula/dependency-graph.ts +0 -329
- package/src/core/formula/errors.ts +0 -41
- package/src/core/formula/evaluator.ts +0 -219
- package/src/core/formula/functions.ts +0 -266
- package/src/core/formula/index.ts +0 -7
- package/src/core/formula/parser.ts +0 -198
- package/src/core/formula/tokenizer.ts +0 -160
- package/src/core/merge-manager.ts +0 -158
- package/src/core/selection.ts +0 -66
- package/src/core/sheet.ts +0 -282
- package/src/core/workbook.ts +0 -99
- package/src/grid/__test__/canvas-mock.ts +0 -49
- package/src/grid/__test__/setup.ts +0 -3
- package/src/grid/__test__/sheet-grid-formula.test.ts +0 -140
- package/src/grid/__test__/sheet-grid.test.ts +0 -275
- package/src/grid/sheet-grid.ts +0 -407
- package/src/grid/vtable-theme.ts +0 -61
- package/src/vue/__test__/sheet-component.test.ts +0 -267
- package/src/vue/sheet.vue +0 -235
- package/src/vue/style.scss +0 -94
- package/src/vue/style.ts +0 -2
- /package/src/{vue → components/sheet}/index.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vtable-theme.js","names":[],"sources":["../../src/grid/vtable-theme.ts"],"sourcesContent":["import { themes } from '@visactor/vtable'\n\n/** 行号 / 列头浅底(canvas 主题无法读 CSS 变量,固定色贴近 Excel) */\nconst CHROME_BG = '#F5F5F5'\n/** body 纯白,覆盖 DEFAULT 斑马底色 */\nconst BODY_BG = '#FFF'\n/** 网格线 / 外框:浅灰(勿用 DEFAULTBORDERCOLOR #000) */\nconst GRID_BORDER = '#E1E4E8'\n/** 选区边框:清晰蓝(覆盖 DEFAULT 的 #0000ff) */\nconst SELECTION_BORDER = '#2170E7'\n/** 选区填充 */\nconst SELECTION_BG = 'rgba(33, 112, 231, 0.12)'\n\n/**\n * 单元格内边距 [上, 右, 下, 左]。\n * VTable DEFAULT 为 `[10, 16, 10, 16]`,配合 `defaultRowHeight: 28` 会挤占文字区;\n * 收紧到贴近 Excel 的密度(仍留少量呼吸空间)。\n */\nexport const SHEET_CELL_PADDING = [2, 6, 2, 6] as const\n\n/**\n * Sheet 默认 VTable 主题。\n *\n * 必须基于 `themes.DEFAULT.extends`:传入裸对象时 VTable 不会继承 DEFAULT,\n * 缺省 `borderColor` 会回落到内部 `DEFAULTBORDERCOLOR = '#000'`,出现刺眼黑线。\n */\nexport const sheetVTableTheme = themes.DEFAULT.extends({\n underlayBackgroundColor: BODY_BG,\n defaultStyle: {\n bgColor: CHROME_BG,\n borderColor: GRID_BORDER,\n padding: [...SHEET_CELL_PADDING],\n textOverflow: 'clip'\n },\n headerStyle: { bgColor: CHROME_BG, borderColor: GRID_BORDER, textOverflow: 'clip' },\n cornerHeaderStyle: { bgColor: CHROME_BG, borderColor: GRID_BORDER, textOverflow: 'clip' },\n rowHeaderStyle: { bgColor: CHROME_BG, borderColor: GRID_BORDER, textOverflow: 'clip' },\n bodyStyle: { bgColor: BODY_BG, borderColor: GRID_BORDER, textOverflow: 'clip' },\n frameStyle: {\n borderColor: GRID_BORDER,\n borderLineWidth: 1,\n shadowBlur: 0,\n shadowColor: 'transparent'\n },\n selectionStyle: {\n cellBgColor: SELECTION_BG,\n cellBorderColor: SELECTION_BORDER,\n cellBorderLineWidth: 2\n }\n})\n\n/** 行号列默认样式(与主题 chrome 对齐) */\nexport const sheetRowSeriesNumberStyle = {\n bgColor: CHROME_BG,\n borderColor: GRID_BORDER,\n padding: [...SHEET_CELL_PADDING],\n textOverflow: 'clip' as const\n}\n\n/** 默认行高(比 VTable 默认 40 更接近表格密度;与 SHEET_CELL_PADDING 搭配) */\nexport const SHEET_DEFAULT_ROW_HEIGHT = 28\n"],"mappings":";;;AAGA,MAAM,YAAY;;AAElB,MAAM,UAAU;;AAEhB,MAAM,cAAc;;AAEpB,MAAM,mBAAmB;;AAEzB,MAAM,eAAe;;;;;;AAOrB,MAAa,qBAAqB;CAAC;CAAG;CAAG;CAAG;AAAC;;;;;;;AAQ7C,MAAa,mBAAmB,OAAO,QAAQ,QAAQ;CACrD,yBAAyB;CACzB,cAAc;EACZ,SAAS;EACT,aAAa;EACb,SAAS,CAAC,GAAG,kBAAkB;EAC/B,cAAc;CAChB;CACA,aAAa;EAAE,SAAS;EAAW,aAAa;EAAa,cAAc;CAAO;CAClF,mBAAmB;EAAE,SAAS;EAAW,aAAa;EAAa,cAAc;CAAO;CACxF,gBAAgB;EAAE,SAAS;EAAW,aAAa;EAAa,cAAc;CAAO;CACrF,WAAW;EAAE,SAAS;EAAS,aAAa;EAAa,cAAc;CAAO;CAC9E,YAAY;EACV,aAAa;EACb,iBAAiB;EACjB,YAAY;EACZ,aAAa;CACf;CACA,gBAAgB;EACd,aAAa;EACb,iBAAiB;EACjB,qBAAqB;CACvB;AACF,CAAC;;AAGD,MAAa,4BAA4B;CACvC,SAAS;CACT,aAAa;CACb,SAAS,CAAC,GAAG,kBAAkB;CAC/B,cAAc;AAChB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"builtin.js","names":[],"sources":["../../src/tools/builtin.ts"],"sourcesContent":["import { rangesEqual } from '../core/address'\nimport { registerTool } from './registry'\n\n/**\n * 内置工具(dogfood 扩展机制):undo/redo + 合并/取消合并。\n *\n * 与第三方工具走同一注册通道,可由宿主 unregisterTool 移除或同 id 覆盖。\n * 本模块由 tools/index.ts 引入(与 core/command 的 default-registry 同构):\n * 经包入口导入即完成注册,无头使用 core 深导入不涉及此全局副作用。\n */\n\nregisterTool({\n id: 'undo',\n title: '撤销',\n tooltip: '撤销(Ctrl/Cmd+Z)',\n group: 'history',\n order: 0,\n disabled: (ctx) => !ctx.canUndo,\n onClick: (ctx) => {\n ctx.undo()\n }\n})\n\nregisterTool({\n id: 'redo',\n title: '重做',\n tooltip: '重做(Ctrl/Cmd+Shift+Z 或 Ctrl+Y)',\n group: 'history',\n order: 1,\n disabled: (ctx) => !ctx.canRedo,\n onClick: (ctx) => {\n ctx.redo()\n }\n})\n\nregisterTool({\n id: 'merge',\n title: '合并',\n tooltip: '合并选中区域',\n group: 'cell',\n order: 0,\n disabled: (ctx) => {\n const { activeCell, ranges } = ctx.getSelection()\n const range = ranges[0]\n if (!activeCell || !range) return true\n // 单格无可合并\n if (range.start.row === range.end.row && range.start.col === range.end.col) return true\n // 选区恰好等于既有合并区域 → 无操作必要\n const mergeRange = ctx.getCellInfo(activeCell).mergeRange\n return !!mergeRange && rangesEqual(mergeRange, range)\n },\n onClick: (ctx) => {\n const range = ctx.getSelection().ranges[0]\n if (!range) return\n ctx.mergeCells(range)\n }\n})\n\nregisterTool({\n id: 'unmerge',\n title: '取消合并',\n tooltip: '取消活动格所在合并',\n group: 'cell',\n order: 1,\n disabled: (ctx) => {\n const { activeCell } = ctx.getSelection()\n if (!activeCell) return true\n return !ctx.getCellInfo(activeCell).mergeRange\n },\n onClick: (ctx) => {\n const { activeCell, ranges } = ctx.getSelection()\n if (!activeCell || !ranges[0]) return\n ctx.unmergeCells(ranges[0])\n }\n})\n"],"mappings":";;;;;;;;;;AAWA,aAAa;CACX,IAAI;CACJ,OAAO;CACP,SAAS;CACT,OAAO;CACP,OAAO;CACP,WAAW,QAAQ,CAAC,IAAI;CACxB,UAAU,QAAQ;EAChB,IAAI,KAAK;CACX;AACF,CAAC;AAED,aAAa;CACX,IAAI;CACJ,OAAO;CACP,SAAS;CACT,OAAO;CACP,OAAO;CACP,WAAW,QAAQ,CAAC,IAAI;CACxB,UAAU,QAAQ;EAChB,IAAI,KAAK;CACX;AACF,CAAC;AAED,aAAa;CACX,IAAI;CACJ,OAAO;CACP,SAAS;CACT,OAAO;CACP,OAAO;CACP,WAAW,QAAQ;EACjB,MAAM,EAAE,YAAY,WAAW,IAAI,aAAa;EAChD,MAAM,QAAQ,OAAO;EACrB,IAAI,CAAC,cAAc,CAAC,OAAO,OAAO;EAElC,IAAI,MAAM,MAAM,QAAQ,MAAM,IAAI,OAAO,MAAM,MAAM,QAAQ,MAAM,IAAI,KAAK,OAAO;EAEnF,MAAM,aAAa,IAAI,YAAY,UAAU,CAAC,CAAC;EAC/C,OAAO,CAAC,CAAC,cAAc,YAAY,YAAY,KAAK;CACtD;CACA,UAAU,QAAQ;EAChB,MAAM,QAAQ,IAAI,aAAa,CAAC,CAAC,OAAO;EACxC,IAAI,CAAC,OAAO;EACZ,IAAI,WAAW,KAAK;CACtB;AACF,CAAC;AAED,aAAa;CACX,IAAI;CACJ,OAAO;CACP,SAAS;CACT,OAAO;CACP,OAAO;CACP,WAAW,QAAQ;EACjB,MAAM,EAAE,eAAe,IAAI,aAAa;EACxC,IAAI,CAAC,YAAY,OAAO;EACxB,OAAO,CAAC,IAAI,YAAY,UAAU,CAAC,CAAC;CACtC;CACA,UAAU,QAAQ;EAChB,MAAM,EAAE,YAAY,WAAW,IAAI,aAAa;EAChD,IAAI,CAAC,cAAc,CAAC,OAAO,IAAI;EAC/B,IAAI,aAAa,OAAO,EAAE;CAC5B;AACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../../src/tools/context.ts"],"sourcesContent":["import type { CellAddress, CellRange } from '../core/address'\nimport type { CellData, CellValue } from '../core/cell-store'\nimport type { HistoryState } from '../core/command/history'\nimport type { SetCellValueItem } from '../core/command/set-cell-value'\nimport type { CellInfo } from '../core/merge-manager'\nimport type { SelectionState } from '../core/selection'\nimport type { Sheet } from '../core/sheet'\n\n/**\n * SheetContext:工具的唯一操作门面。\n *\n * 工具(内置与第三方)对表格的全部操作都经由此门面:\n * - 读方法直达当前活动 sheet(语义与 Sheet 同名方法一致)\n * - 写方法全部走命令系统,天然进入 undo 历史——扩展无法绕过命令系统\n * - 不暴露 Sheet 实例本身,保证门面就是扩展能力的全部边界\n * - USheet 切换 sheet tab 后,同一上下文自动指向新的活动 sheet\n */\nexport interface SheetContext {\n /** 当前活动 sheet 名 */\n readonly sheetName: string\n\n // ─── 选区 ────────────────────────────────────────────────\n getSelection(): SelectionState\n /** 选中单格(被覆盖格自动定位锚点) */\n selectCell(addr: CellAddress): void\n selectRange(range: CellRange): void\n\n // ─── 读取 ────────────────────────────────────────────────\n /** 原始存储语义读取(被合并覆盖格 → undefined) */\n getCellData(addr: CellAddress): CellData | undefined\n /** 锚点解析语义读取(被覆盖格 → 锚点的值) */\n getDisplayValue(addr: CellAddress): CellValue | undefined\n /** 合并语义下的单元格信息(普通格 / 合并锚点 / 被覆盖格) */\n getCellInfo(addr: CellAddress): CellInfo\n\n // ─── 写入(全部经命令系统,可 undo) ───────────────────────\n setCellValue(addr: CellAddress, value: CellValue): void\n setCellFormula(addr: CellAddress, formula: string): void\n /** 批量写入(一次调用 = 一个 undo 单元) */\n setCells(items: SetCellValueItem[]): void\n mergeCells(range: CellRange): CellRange\n unmergeCells(range: CellRange): void\n /** 执行命令注册表中的自定义命令(高级扩展点) */\n executeCommand<R = void>(commandId: string, params: unknown): R | undefined\n\n // ─── 事务(事务内多次写入合并为一个 undo 单元) ─────────────\n beginTransaction(): void\n commit(): void\n rollback(): void\n\n // ─── 历史 ────────────────────────────────────────────────\n undo(): boolean\n redo(): boolean\n readonly canUndo: boolean\n readonly canRedo: boolean\n\n // ─── 事件订阅(订阅时绑定到当前活动 sheet;tab 切换后需重新订阅) ──\n onSelectionChange(handler: (state: SelectionState) => void): () => void\n onHistoryChange(handler: (state: HistoryState) => void): () => void\n}\n\n/**\n * 创建工具上下文。\n * @param resolveSheet 活动 sheet 解析器(USheet 传 `() => activeSheet`,\n * tab 切换后上下文自动指向当前 sheet);也可直接传 Sheet 实例(无头 / 测试场景)\n */\nexport function createSheetContext(resolveSheet: Sheet | (() => Sheet)): SheetContext {\n const sheet = typeof resolveSheet === 'function' ? resolveSheet : () => resolveSheet\n return {\n get sheetName() {\n return sheet().name\n },\n\n getSelection: () => sheet().getSelection(),\n selectCell: (addr) => sheet().selectCell(addr),\n selectRange: (range) => sheet().selectRange(range),\n\n getCellData: (addr) => sheet().getCellData(addr),\n getDisplayValue: (addr) => sheet().getDisplayValue(addr),\n getCellInfo: (addr) => sheet().getCellInfo(addr),\n\n setCellValue: (addr, value) => sheet().setCellValue(addr, value),\n setCellFormula: (addr, formula) => sheet().setCellFormula(addr, formula),\n setCells: (items) => sheet().setCells(items),\n mergeCells: (range) => sheet().mergeCells(range),\n unmergeCells: (range) => sheet().unmergeCells(range),\n executeCommand: <R = void>(commandId: string, params: unknown): R | undefined =>\n sheet().executeCommand<R>(commandId, params),\n\n beginTransaction: () => sheet().beginTransaction(),\n commit: () => sheet().commit(),\n rollback: () => sheet().rollback(),\n\n undo: () => sheet().undo(),\n redo: () => sheet().redo(),\n get canUndo() {\n return sheet().canUndo\n },\n get canRedo() {\n return sheet().canRedo\n },\n\n onSelectionChange: (handler) => sheet().on('selection-change', handler),\n onHistoryChange: (handler) => sheet().on('history-change', handler)\n }\n}\n"],"mappings":";;;;;;AAkEA,SAAgB,mBAAmB,cAAmD;CACpF,MAAM,QAAQ,OAAO,iBAAiB,aAAa,qBAAqB;CACxE,OAAO;EACL,IAAI,YAAY;GACd,OAAO,MAAM,CAAC,CAAC;EACjB;EAEA,oBAAoB,MAAM,CAAC,CAAC,aAAa;EACzC,aAAa,SAAS,MAAM,CAAC,CAAC,WAAW,IAAI;EAC7C,cAAc,UAAU,MAAM,CAAC,CAAC,YAAY,KAAK;EAEjD,cAAc,SAAS,MAAM,CAAC,CAAC,YAAY,IAAI;EAC/C,kBAAkB,SAAS,MAAM,CAAC,CAAC,gBAAgB,IAAI;EACvD,cAAc,SAAS,MAAM,CAAC,CAAC,YAAY,IAAI;EAE/C,eAAe,MAAM,UAAU,MAAM,CAAC,CAAC,aAAa,MAAM,KAAK;EAC/D,iBAAiB,MAAM,YAAY,MAAM,CAAC,CAAC,eAAe,MAAM,OAAO;EACvE,WAAW,UAAU,MAAM,CAAC,CAAC,SAAS,KAAK;EAC3C,aAAa,UAAU,MAAM,CAAC,CAAC,WAAW,KAAK;EAC/C,eAAe,UAAU,MAAM,CAAC,CAAC,aAAa,KAAK;EACnD,iBAA2B,WAAmB,WAC5C,MAAM,CAAC,CAAC,eAAkB,WAAW,MAAM;EAE7C,wBAAwB,MAAM,CAAC,CAAC,iBAAiB;EACjD,cAAc,MAAM,CAAC,CAAC,OAAO;EAC7B,gBAAgB,MAAM,CAAC,CAAC,SAAS;EAEjC,YAAY,MAAM,CAAC,CAAC,KAAK;EACzB,YAAY,MAAM,CAAC,CAAC,KAAK;EACzB,IAAI,UAAU;GACZ,OAAO,MAAM,CAAC,CAAC;EACjB;EACA,IAAI,UAAU;GACZ,OAAO,MAAM,CAAC,CAAC;EACjB;EAEA,oBAAoB,YAAY,MAAM,CAAC,CAAC,GAAG,oBAAoB,OAAO;EACtE,kBAAkB,YAAY,MAAM,CAAC,CAAC,GAAG,kBAAkB,OAAO;CACpE;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":[],"sources":["../../src/tools/registry.ts"],"sourcesContent":["import { TypedEventEmitter } from '../core/events'\nimport type { SheetContext } from './context'\n\n/**\n * 工具注册表:USheet 工具栏的扩展点。\n *\n * - 工具是框架无关的纯定义(icon 由 vue 层渲染,故此处类型为 unknown)\n * - 分组渲染:同组工具连续排列,组间渲染分隔符;\n * 组序 = 各组最早注册位置,组内按 (order, 注册序) 升序\n * - 同 id 重复注册 = 替换定义并保留原注册位置(HMR / 覆盖内置工具友好)\n * - 默认注册表全局共享:所有 USheet 实例渲染同一组工具\n * (与 defaultCommandRegistry 同语义;每个实例的 SheetContext 各自绑定当前 sheet)\n */\n\n/** 工具定义 */\nexport interface SheetTool {\n /** 唯一 id;同 id 重复注册视为替换(保留原位置) */\n id: string\n /** 按钮文本 */\n title: string\n /** 图标(Vue 组件,由 USheet 渲染;tools 层不依赖 vue 故为 unknown) */\n icon?: unknown\n /** 悬浮提示;缺省用 title */\n tooltip?: string\n /** 分组名(组间渲染分隔符);缺省 'default' */\n group?: string\n /** 组内排序(升序,相同 order 按注册先后);缺省 0 */\n order?: number\n /** 是否可见(工具栏状态刷新时求值);缺省可见 */\n visible?(ctx: SheetContext): boolean\n /** 是否禁用(工具栏状态刷新时求值);缺省可用 */\n disabled?(ctx: SheetContext): boolean\n /** 点击执行;ctx 是唯一操作入口(写操作全走命令系统,天然可撤销) */\n onClick(ctx: SheetContext): void\n}\n\n/** 分组视图(供工具栏渲染) */\nexport interface SheetToolGroup {\n name: string\n tools: SheetTool[]\n}\n\n/** 缺省分组名 */\nexport const DEFAULT_TOOL_GROUP = 'default'\n\ntype ToolEntry = { tool: SheetTool; seq: number }\n\ntype ToolRegistryEvents = { change: null }\n\nexport class ToolRegistry {\n private entries = new Map<string, ToolEntry>()\n private seq = 0\n private emitter = new TypedEventEmitter<ToolRegistryEvents>()\n\n /** 注册工具;同 id 重复注册 = 替换定义并保留原注册位置 */\n register(tool: SheetTool): void {\n if (!tool.id) throw new Error('工具注册失败:id 不能为空')\n if (!tool.title) throw new Error(`工具注册失败:${tool.id} 缺少 title`)\n if (typeof tool.onClick !== 'function') {\n throw new Error(`工具注册失败:${tool.id} 缺少 onClick`)\n }\n const prev = this.entries.get(tool.id)\n this.entries.set(tool.id, { tool, seq: prev?.seq ?? this.seq++ })\n this.emitter.emit('change', null)\n }\n\n /** 注销工具;id 不存在时返回 false(不触发 change) */\n unregister(id: string): boolean {\n const existed = this.entries.delete(id)\n if (existed) this.emitter.emit('change', null)\n return existed\n }\n\n get(id: string): SheetTool | undefined {\n return this.entries.get(id)?.tool\n }\n\n has(id: string): boolean {\n return this.entries.has(id)\n }\n\n get size(): number {\n return this.entries.size\n }\n\n /** 分组视图:组序 = 各组最早注册位置;组内按 (order, 注册序) 升序 */\n getGroups(): SheetToolGroup[] {\n const groups = new Map<string, { entries: ToolEntry[]; firstSeq: number }>()\n for (const entry of this.entries.values()) {\n const name = entry.tool.group ?? DEFAULT_TOOL_GROUP\n let group = groups.get(name)\n if (!group) {\n group = { entries: [], firstSeq: entry.seq }\n groups.set(name, group)\n }\n group.entries.push(entry)\n }\n return [...groups.entries()]\n .sort((a, b) => a[1].firstSeq - b[1].firstSeq)\n .map(([name, group]) => ({\n name,\n tools: group.entries\n .slice()\n .sort((a, b) => (a.tool.order ?? 0) - (b.tool.order ?? 0) || a.seq - b.seq)\n .map((entry) => entry.tool)\n }))\n }\n\n /** 订阅注册表变化(register / unregister),返回取消订阅函数 */\n onChange(handler: () => void): () => void {\n return this.emitter.on('change', handler)\n }\n}\n\n/**\n * 全局默认注册表(USheet 默认渲染这里的工具;内置工具也注册于此)。\n * 工具是应用级扩展:注册一次,所有 USheet 实例共享。\n */\nexport const defaultToolRegistry = new ToolRegistry()\n\n/** 注册工具到默认注册表 */\nexport function registerTool(tool: SheetTool): void {\n defaultToolRegistry.register(tool)\n}\n\n/** 从默认注册表注销工具;id 不存在时返回 false */\nexport function unregisterTool(id: string): boolean {\n return defaultToolRegistry.unregister(id)\n}\n"],"mappings":";;;AA2CA,MAAa,qBAAqB;AAMlC,IAAa,eAAb,MAA0B;CACxB,0BAAkB,IAAI,IAAuB;CAC7C,MAAc;CACd,UAAkB,IAAI,kBAAsC;;CAG5D,SAAS,MAAuB;EAC9B,IAAI,CAAC,KAAK,IAAI,MAAM,IAAI,MAAM,gBAAgB;EAC9C,IAAI,CAAC,KAAK,OAAO,MAAM,IAAI,MAAM,UAAU,KAAK,GAAG,UAAU;EAC7D,IAAI,OAAO,KAAK,YAAY,YAC1B,MAAM,IAAI,MAAM,UAAU,KAAK,GAAG,YAAY;EAEhD,MAAM,OAAO,KAAK,QAAQ,IAAI,KAAK,EAAE;EACrC,KAAK,QAAQ,IAAI,KAAK,IAAI;GAAE;GAAM,KAAK,MAAM,OAAO,KAAK;EAAM,CAAC;EAChE,KAAK,QAAQ,KAAK,UAAU,IAAI;CAClC;;CAGA,WAAW,IAAqB;EAC9B,MAAM,UAAU,KAAK,QAAQ,OAAO,EAAE;EACtC,IAAI,SAAS,KAAK,QAAQ,KAAK,UAAU,IAAI;EAC7C,OAAO;CACT;CAEA,IAAI,IAAmC;EACrC,OAAO,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE;CAC/B;CAEA,IAAI,IAAqB;EACvB,OAAO,KAAK,QAAQ,IAAI,EAAE;CAC5B;CAEA,IAAI,OAAe;EACjB,OAAO,KAAK,QAAQ;CACtB;;CAGA,YAA8B;EAC5B,MAAM,yBAAS,IAAI,IAAwD;EAC3E,KAAK,MAAM,SAAS,KAAK,QAAQ,OAAO,GAAG;GACzC,MAAM,OAAO,MAAM,KAAK,SAAA;GACxB,IAAI,QAAQ,OAAO,IAAI,IAAI;GAC3B,IAAI,CAAC,OAAO;IACV,QAAQ;KAAE,SAAS,CAAC;KAAG,UAAU,MAAM;IAAI;IAC3C,OAAO,IAAI,MAAM,KAAK;GACxB;GACA,MAAM,QAAQ,KAAK,KAAK;EAC1B;EACA,OAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC,CACzB,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,CAC7C,KAAK,CAAC,MAAM,YAAY;GACvB;GACA,OAAO,MAAM,QACV,MAAM,CAAC,CACP,MAAM,GAAG,OAAO,EAAE,KAAK,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAC1E,KAAK,UAAU,MAAM,IAAI;EAC9B,EAAE;CACN;;CAGA,SAAS,SAAiC;EACxC,OAAO,KAAK,QAAQ,GAAG,UAAU,OAAO;CAC1C;AACF;;;;;AAMA,MAAa,sBAAsB,IAAI,aAAa;;AAGpD,SAAgB,aAAa,MAAuB;CAClD,oBAAoB,SAAS,IAAI;AACnC;;AAGA,SAAgB,eAAe,IAAqB;CAClD,OAAO,oBAAoB,WAAW,EAAE;AAC1C"}
|
package/dist/vue/index.d.ts
DELETED
package/dist/vue/sheet.js
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { rangeContainsAddress } from "../core/address.js";
|
|
2
|
-
import { defaultToolRegistry } from "../tools/registry.js";
|
|
3
|
-
import { Workbook } from "../core/workbook.js";
|
|
4
|
-
import { SheetGrid } from "../grid/sheet-grid.js";
|
|
5
|
-
import { createSheetContext } from "../tools/context.js";
|
|
6
|
-
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderList, resolveDynamicComponent, shallowRef, toDisplayString, unref, useTemplateRef, watch } from "vue";
|
|
7
|
-
import { contextmenu } from "@veltra/desktop";
|
|
8
|
-
import { bem } from "@veltra/utils";
|
|
9
|
-
//#region src/vue/sheet.vue
|
|
10
|
-
const _hoisted_1 = [
|
|
11
|
-
"disabled",
|
|
12
|
-
"title",
|
|
13
|
-
"onClick"
|
|
14
|
-
];
|
|
15
|
-
const _hoisted_2 = ["onClick"];
|
|
16
|
-
const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
17
|
-
name: "USheet",
|
|
18
|
-
__name: "sheet",
|
|
19
|
-
props: {
|
|
20
|
-
workbook: {},
|
|
21
|
-
rows: { default: 100 },
|
|
22
|
-
cols: { default: 26 },
|
|
23
|
-
showToolbar: {
|
|
24
|
-
type: Boolean,
|
|
25
|
-
default: true
|
|
26
|
-
},
|
|
27
|
-
showTabs: {
|
|
28
|
-
type: Boolean,
|
|
29
|
-
default: true
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
emits: ["active-sheet-change"],
|
|
33
|
-
setup(__props, { expose: __expose, emit: __emit }) {
|
|
34
|
-
const props = __props;
|
|
35
|
-
const emit = __emit;
|
|
36
|
-
const cls = bem("sheet");
|
|
37
|
-
/** 工作簿:外部传入或内部自建(单 sheet) */
|
|
38
|
-
const internalWorkbook = new Workbook();
|
|
39
|
-
const workbook = computed(() => props.workbook ?? internalWorkbook);
|
|
40
|
-
/** 激活 sheet 索引(镜像 workbook.activeSheetIndex,经事件同步) */
|
|
41
|
-
const activeIndex = ref(workbook.value.activeSheetIndex);
|
|
42
|
-
/** sheet 列表(tabs 渲染;由 sheets-change 同步) */
|
|
43
|
-
const sheetList = shallowRef(workbook.value.getSheets());
|
|
44
|
-
const activeSheet = computed(() => sheetList.value[activeIndex.value] ?? workbook.value.activeSheet);
|
|
45
|
-
/** 工具上下文:动态解析活动 sheet,tab 切换后自动指向当前 sheet */
|
|
46
|
-
const context = createSheetContext(() => activeSheet.value);
|
|
47
|
-
const gridRef = useTemplateRef("gridRef");
|
|
48
|
-
let grid;
|
|
49
|
-
const stateTick = ref(0);
|
|
50
|
-
const bump = () => {
|
|
51
|
-
stateTick.value++;
|
|
52
|
-
};
|
|
53
|
-
let disposeSheetEvents = [];
|
|
54
|
-
/** 订阅活动 sheet 的状态源(tab 切换 / 工作簿变更时重绑) */
|
|
55
|
-
function bindSheetEvents(sheet) {
|
|
56
|
-
for (const dispose of disposeSheetEvents) dispose();
|
|
57
|
-
disposeSheetEvents = [
|
|
58
|
-
sheet.on("selection-change", bump),
|
|
59
|
-
sheet.on("history-change", bump),
|
|
60
|
-
sheet.on("cell-change", bump),
|
|
61
|
-
sheet.on("merge-change", bump)
|
|
62
|
-
];
|
|
63
|
-
}
|
|
64
|
-
let disposeWorkbookEvents = [];
|
|
65
|
-
function bindWorkbookEvents(wb) {
|
|
66
|
-
for (const dispose of disposeWorkbookEvents) dispose();
|
|
67
|
-
disposeWorkbookEvents = [wb.on("sheets-change", ({ sheets }) => {
|
|
68
|
-
sheetList.value = sheets;
|
|
69
|
-
bump();
|
|
70
|
-
}), wb.on("active-sheet-change", ({ sheet, index }) => {
|
|
71
|
-
activeIndex.value = index;
|
|
72
|
-
bindSheetEvents(sheet);
|
|
73
|
-
rebuildGrid();
|
|
74
|
-
bump();
|
|
75
|
-
emit("active-sheet-change", {
|
|
76
|
-
sheet,
|
|
77
|
-
index
|
|
78
|
-
});
|
|
79
|
-
})];
|
|
80
|
-
}
|
|
81
|
-
const offRegistryChange = defaultToolRegistry.onChange(bump);
|
|
82
|
-
const toolGroups = computed(() => {
|
|
83
|
-
stateTick.value;
|
|
84
|
-
return defaultToolRegistry.getGroups().map((group) => ({
|
|
85
|
-
name: group.name,
|
|
86
|
-
tools: group.tools.map((tool) => ({
|
|
87
|
-
tool,
|
|
88
|
-
visible: tool.visible?.(context) ?? true,
|
|
89
|
-
disabled: tool.disabled?.(context) ?? false
|
|
90
|
-
})).filter((item) => item.visible)
|
|
91
|
-
})).filter((group) => group.tools.length > 0);
|
|
92
|
-
});
|
|
93
|
-
function handleToolClick(tool) {
|
|
94
|
-
if (tool.disabled?.(context)) return;
|
|
95
|
-
tool.onClick(context);
|
|
96
|
-
}
|
|
97
|
-
function handleTabClick(index) {
|
|
98
|
-
if (index === activeIndex.value) return;
|
|
99
|
-
const sheet = sheetList.value[index];
|
|
100
|
-
if (sheet) workbook.value.activateSheet(sheet.name);
|
|
101
|
-
}
|
|
102
|
-
function handleContextMenu(info) {
|
|
103
|
-
if (info.addr) {
|
|
104
|
-
if (!context.getSelection().ranges.some((range) => rangeContainsAddress(range, info.addr))) context.selectCell(info.addr);
|
|
105
|
-
}
|
|
106
|
-
const mergeTool = defaultToolRegistry.get("merge");
|
|
107
|
-
const unmergeTool = defaultToolRegistry.get("unmerge");
|
|
108
|
-
contextmenu.pop({
|
|
109
|
-
mousePosition: {
|
|
110
|
-
x: info.x,
|
|
111
|
-
y: info.y
|
|
112
|
-
},
|
|
113
|
-
width: 180,
|
|
114
|
-
menus: [{
|
|
115
|
-
label: "合并单元格",
|
|
116
|
-
disabled: mergeTool?.disabled?.(context) ?? true,
|
|
117
|
-
callback: () => mergeTool?.onClick(context)
|
|
118
|
-
}, {
|
|
119
|
-
label: "取消合并单元格",
|
|
120
|
-
disabled: unmergeTool?.disabled?.(context) ?? true,
|
|
121
|
-
callback: () => unmergeTool?.onClick(context)
|
|
122
|
-
}]
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
function rebuildGrid() {
|
|
126
|
-
const container = gridRef.value;
|
|
127
|
-
if (!container) return;
|
|
128
|
-
grid?.release();
|
|
129
|
-
grid = new SheetGrid({
|
|
130
|
-
container,
|
|
131
|
-
sheet: activeSheet.value,
|
|
132
|
-
rows: props.rows,
|
|
133
|
-
cols: props.cols,
|
|
134
|
-
onContextMenu: handleContextMenu
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
onMounted(() => {
|
|
138
|
-
bindWorkbookEvents(workbook.value);
|
|
139
|
-
bindSheetEvents(activeSheet.value);
|
|
140
|
-
rebuildGrid();
|
|
141
|
-
});
|
|
142
|
-
watch(() => [props.rows, props.cols], rebuildGrid);
|
|
143
|
-
watch(() => props.workbook, (wb, prev) => {
|
|
144
|
-
if (wb === prev) return;
|
|
145
|
-
activeIndex.value = workbook.value.activeSheetIndex;
|
|
146
|
-
sheetList.value = workbook.value.getSheets();
|
|
147
|
-
bindWorkbookEvents(workbook.value);
|
|
148
|
-
bindSheetEvents(activeSheet.value);
|
|
149
|
-
rebuildGrid();
|
|
150
|
-
bump();
|
|
151
|
-
});
|
|
152
|
-
onBeforeUnmount(() => {
|
|
153
|
-
offRegistryChange();
|
|
154
|
-
for (const dispose of disposeWorkbookEvents) dispose();
|
|
155
|
-
for (const dispose of disposeSheetEvents) dispose();
|
|
156
|
-
grid?.release();
|
|
157
|
-
grid = void 0;
|
|
158
|
-
});
|
|
159
|
-
__expose({
|
|
160
|
-
workbook,
|
|
161
|
-
getActiveSheet: () => activeSheet.value,
|
|
162
|
-
getContext: () => context,
|
|
163
|
-
getGrid: () => grid
|
|
164
|
-
});
|
|
165
|
-
return (_ctx, _cache) => {
|
|
166
|
-
return openBlock(), createElementBlock("div", { class: normalizeClass(unref(cls).b) }, [
|
|
167
|
-
__props.showToolbar ? (openBlock(), createElementBlock("div", {
|
|
168
|
-
key: 0,
|
|
169
|
-
class: normalizeClass(unref(cls).e("toolbar"))
|
|
170
|
-
}, [(openBlock(true), createElementBlock(Fragment, null, renderList(toolGroups.value, (group, groupIndex) => {
|
|
171
|
-
return openBlock(), createElementBlock(Fragment, { key: group.name }, [groupIndex > 0 ? (openBlock(), createElementBlock("span", {
|
|
172
|
-
key: 0,
|
|
173
|
-
class: normalizeClass(unref(cls).e("toolbar-divider"))
|
|
174
|
-
}, null, 2)) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(group.tools, (item) => {
|
|
175
|
-
return openBlock(), createElementBlock("button", {
|
|
176
|
-
key: item.tool.id,
|
|
177
|
-
type: "button",
|
|
178
|
-
class: normalizeClass(unref(cls).e("tool")),
|
|
179
|
-
disabled: item.disabled,
|
|
180
|
-
title: item.tool.tooltip ?? item.tool.title,
|
|
181
|
-
onClick: ($event) => handleToolClick(item.tool)
|
|
182
|
-
}, [item.tool.icon ? (openBlock(), createBlock(resolveDynamicComponent(item.tool.icon), {
|
|
183
|
-
key: 0,
|
|
184
|
-
class: normalizeClass(unref(cls).e("tool-icon"))
|
|
185
|
-
}, null, 8, ["class"])) : createCommentVNode("v-if", true), createElementVNode("span", null, toDisplayString(item.tool.title), 1)], 10, _hoisted_1);
|
|
186
|
-
}), 128))], 64);
|
|
187
|
-
}), 128))], 2)) : createCommentVNode("v-if", true),
|
|
188
|
-
createElementVNode("div", {
|
|
189
|
-
ref_key: "gridRef",
|
|
190
|
-
ref: gridRef,
|
|
191
|
-
class: normalizeClass(unref(cls).e("grid"))
|
|
192
|
-
}, null, 2),
|
|
193
|
-
__props.showTabs ? (openBlock(), createElementBlock("div", {
|
|
194
|
-
key: 1,
|
|
195
|
-
class: normalizeClass(unref(cls).e("tabs"))
|
|
196
|
-
}, [(openBlock(true), createElementBlock(Fragment, null, renderList(sheetList.value, (sheet, index) => {
|
|
197
|
-
return openBlock(), createElementBlock("button", {
|
|
198
|
-
key: sheet.name,
|
|
199
|
-
type: "button",
|
|
200
|
-
class: normalizeClass([unref(cls).e("tab"), unref(bem).is("active", index === activeIndex.value)]),
|
|
201
|
-
onClick: ($event) => handleTabClick(index)
|
|
202
|
-
}, toDisplayString(sheet.name), 11, _hoisted_2);
|
|
203
|
-
}), 128))], 2)) : createCommentVNode("v-if", true)
|
|
204
|
-
], 2);
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
//#endregion
|
|
209
|
-
export { _sfc_main as default };
|
|
210
|
-
|
|
211
|
-
//# sourceMappingURL=sheet.js.map
|
package/dist/vue/sheet.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sheet.js","names":[],"sources":["../../src/vue/sheet.vue"],"sourcesContent":["<template>\n <div :class=\"cls.b\">\n <div v-if=\"showToolbar\" :class=\"cls.e('toolbar')\">\n <template v-for=\"(group, groupIndex) in toolGroups\" :key=\"group.name\">\n <span v-if=\"groupIndex > 0\" :class=\"cls.e('toolbar-divider')\" />\n <button\n v-for=\"item in group.tools\"\n :key=\"item.tool.id\"\n type=\"button\"\n :class=\"cls.e('tool')\"\n :disabled=\"item.disabled\"\n :title=\"item.tool.tooltip ?? item.tool.title\"\n @click=\"handleToolClick(item.tool)\"\n >\n <component :is=\"item.tool.icon\" v-if=\"item.tool.icon\" :class=\"cls.e('tool-icon')\" />\n <span>{{ item.tool.title }}</span>\n </button>\n </template>\n </div>\n\n <div ref=\"gridRef\" :class=\"cls.e('grid')\" />\n\n <div v-if=\"showTabs\" :class=\"cls.e('tabs')\">\n <button\n v-for=\"(sheet, index) in sheetList\"\n :key=\"sheet.name\"\n type=\"button\"\n :class=\"[cls.e('tab'), bem.is('active', index === activeIndex)]\"\n @click=\"handleTabClick(index)\"\n >\n {{ sheet.name }}\n </button>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { contextmenu } from '@veltra/desktop'\nimport { bem } from '@veltra/utils'\nimport { computed, onBeforeUnmount, onMounted, ref, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport { rangeContainsAddress } from '../core/address'\nimport type { Sheet } from '../core/sheet'\nimport { Workbook } from '../core/workbook'\nimport { SheetGrid, type SheetGridContextMenuInfo } from '../grid/sheet-grid'\nimport { createSheetContext } from '../tools/context'\nimport { defaultToolRegistry, type SheetTool } from '../tools/registry'\nimport type { SheetEmits, SheetProps, _SheetExposed } from '../types'\n\ndefineOptions({ name: 'USheet' })\n\nconst props = withDefaults(defineProps<SheetProps>(), {\n rows: 100,\n cols: 26,\n showToolbar: true,\n showTabs: true\n})\n\nconst emit = defineEmits<SheetEmits>()\n\nconst cls = bem('sheet')\n\n/** 工作簿:外部传入或内部自建(单 sheet) */\nconst internalWorkbook = new Workbook()\nconst workbook = computed(() => props.workbook ?? internalWorkbook)\n\n/** 激活 sheet 索引(镜像 workbook.activeSheetIndex,经事件同步) */\nconst activeIndex = ref(workbook.value.activeSheetIndex)\n/** sheet 列表(tabs 渲染;由 sheets-change 同步) */\nconst sheetList = shallowRef<Sheet[]>(workbook.value.getSheets())\nconst activeSheet = computed(() => sheetList.value[activeIndex.value] ?? workbook.value.activeSheet)\n\n/** 工具上下文:动态解析活动 sheet,tab 切换后自动指向当前 sheet */\nconst context = createSheetContext(() => activeSheet.value)\n\nconst gridRef = useTemplateRef<HTMLElement>('gridRef')\nlet grid: SheetGrid | undefined\n\n// ─── 工具栏状态刷新 ─────────────────────────────────────────\n// 工具 visible/disabled 是 (ctx) => boolean 纯函数,状态源变化时 bump 触发重算\n\nconst stateTick = ref(0)\nconst bump = (): void => {\n stateTick.value++\n}\n\nlet disposeSheetEvents: (() => void)[] = []\n/** 订阅活动 sheet 的状态源(tab 切换 / 工作簿变更时重绑) */\nfunction bindSheetEvents(sheet: Sheet): void {\n for (const dispose of disposeSheetEvents) dispose()\n disposeSheetEvents = [\n sheet.on('selection-change', bump),\n sheet.on('history-change', bump),\n sheet.on('cell-change', bump),\n sheet.on('merge-change', bump)\n ]\n}\n\nlet disposeWorkbookEvents: (() => void)[] = []\nfunction bindWorkbookEvents(wb: Workbook): void {\n for (const dispose of disposeWorkbookEvents) dispose()\n disposeWorkbookEvents = [\n wb.on('sheets-change', ({ sheets }) => {\n sheetList.value = sheets\n bump()\n }),\n wb.on('active-sheet-change', ({ sheet, index }) => {\n activeIndex.value = index\n bindSheetEvents(sheet)\n rebuildGrid()\n bump()\n emit('active-sheet-change', { sheet, index })\n })\n ]\n}\n\nconst offRegistryChange = defaultToolRegistry.onChange(bump)\n\n// ─── 工具栏 ────────────────────────────────────────────────\n\nconst toolGroups = computed(() => {\n void stateTick.value // 依赖状态源:选区 / 历史 / 单元格 / 合并 / 注册表\n return defaultToolRegistry\n .getGroups()\n .map((group) => ({\n name: group.name,\n tools: group.tools\n .map((tool) => ({\n tool,\n visible: tool.visible?.(context) ?? true,\n disabled: tool.disabled?.(context) ?? false\n }))\n .filter((item) => item.visible)\n }))\n .filter((group) => group.tools.length > 0)\n})\n\nfunction handleToolClick(tool: SheetTool): void {\n if (tool.disabled?.(context)) return\n tool.onClick(context)\n}\n\n// ─── sheet tabs ─────────────────────────────────────────────\n\nfunction handleTabClick(index: number): void {\n if (index === activeIndex.value) return\n const sheet = sheetList.value[index]\n if (sheet) workbook.value.activateSheet(sheet.name)\n}\n\n// ─── 右键菜单(合并 / 取消合并,语义对齐内置工具)────────────\n\nfunction handleContextMenu(info: SheetGridContextMenuInfo): void {\n // body 格:若点击落在当前选区外则先选中该格;行号/列头保留当前选区\n if (info.addr) {\n const inSelection = context\n .getSelection()\n .ranges.some((range) => rangeContainsAddress(range, info.addr!))\n if (!inSelection) context.selectCell(info.addr)\n }\n\n const mergeTool = defaultToolRegistry.get('merge')\n const unmergeTool = defaultToolRegistry.get('unmerge')\n\n contextmenu.pop({\n mousePosition: { x: info.x, y: info.y },\n width: 180,\n menus: [\n {\n label: '合并单元格',\n disabled: mergeTool?.disabled?.(context) ?? true,\n callback: () => mergeTool?.onClick(context)\n },\n {\n label: '取消合并单元格',\n disabled: unmergeTool?.disabled?.(context) ?? true,\n callback: () => unmergeTool?.onClick(context)\n }\n ]\n })\n}\n\n// ─── grid 生命周期 ──────────────────────────────────────────\n\nfunction rebuildGrid(): void {\n const container = gridRef.value\n if (!container) return\n grid?.release()\n grid = new SheetGrid({\n container,\n sheet: activeSheet.value,\n rows: props.rows,\n cols: props.cols,\n onContextMenu: handleContextMenu\n })\n}\n\nonMounted(() => {\n bindWorkbookEvents(workbook.value)\n bindSheetEvents(activeSheet.value)\n rebuildGrid()\n})\n\nwatch(() => [props.rows, props.cols], rebuildGrid)\n\nwatch(\n () => props.workbook,\n (wb, prev) => {\n if (wb === prev) return\n activeIndex.value = workbook.value.activeSheetIndex\n sheetList.value = workbook.value.getSheets()\n bindWorkbookEvents(workbook.value)\n bindSheetEvents(activeSheet.value)\n rebuildGrid()\n bump()\n }\n)\n\nonBeforeUnmount(() => {\n offRegistryChange()\n for (const dispose of disposeWorkbookEvents) dispose()\n for (const dispose of disposeSheetEvents) dispose()\n grid?.release()\n grid = undefined\n})\n\nconst exposed: _SheetExposed = {\n workbook,\n getActiveSheet: () => activeSheet.value,\n getContext: () => context,\n getGrid: () => grid\n}\n\ndefineExpose(exposed)\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmDA,MAAM,QAAQ;EAOd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,OAAO;;EAGvB,MAAM,mBAAmB,IAAI,SAAS;EACtC,MAAM,WAAW,eAAe,MAAM,YAAY,gBAAgB;;EAGlE,MAAM,cAAc,IAAI,SAAS,MAAM,gBAAgB;;EAEvD,MAAM,YAAY,WAAoB,SAAS,MAAM,UAAU,CAAC;EAChE,MAAM,cAAc,eAAe,UAAU,MAAM,YAAY,UAAU,SAAS,MAAM,WAAW;;EAGnG,MAAM,UAAU,yBAAyB,YAAY,KAAK;EAE1D,MAAM,UAAU,eAA4B,SAAS;EACrD,IAAI;EAKJ,MAAM,YAAY,IAAI,CAAC;EACvB,MAAM,aAAmB;GACvB,UAAU;EACZ;EAEA,IAAI,qBAAqC,CAAC;;EAE1C,SAAS,gBAAgB,OAAoB;GAC3C,KAAK,MAAM,WAAW,oBAAoB,QAAQ;GAClD,qBAAqB;IACnB,MAAM,GAAG,oBAAoB,IAAI;IACjC,MAAM,GAAG,kBAAkB,IAAI;IAC/B,MAAM,GAAG,eAAe,IAAI;IAC5B,MAAM,GAAG,gBAAgB,IAAI;GAC/B;EACF;EAEA,IAAI,wBAAwC,CAAC;EAC7C,SAAS,mBAAmB,IAAoB;GAC9C,KAAK,MAAM,WAAW,uBAAuB,QAAQ;GACrD,wBAAwB,CACtB,GAAG,GAAG,kBAAkB,EAAE,aAAa;IACrC,UAAU,QAAQ;IAClB,KAAK;GACP,CAAC,GACD,GAAG,GAAG,wBAAwB,EAAE,OAAO,YAAY;IACjD,YAAY,QAAQ;IACpB,gBAAgB,KAAK;IACrB,YAAY;IACZ,KAAK;IACL,KAAK,uBAAuB;KAAE;KAAO;IAAM,CAAC;GAC9C,CAAC,CACH;EACF;EAEA,MAAM,oBAAoB,oBAAoB,SAAS,IAAI;EAI3D,MAAM,aAAa,eAAe;GAChC,UAAe;GACf,OAAO,oBACJ,UAAU,CAAA,CACV,KAAK,WAAW;IACf,MAAM,MAAM;IACZ,OAAO,MAAM,MACV,KAAK,UAAU;KACd;KACA,SAAS,KAAK,UAAU,OAAO,KAAK;KACpC,UAAU,KAAK,WAAW,OAAO,KAAK;IACxC,EAAE,CAAA,CACD,QAAQ,SAAS,KAAK,OAAO;GAClC,EAAE,CAAA,CACD,QAAQ,UAAU,MAAM,MAAM,SAAS,CAAC;EAC7C,CAAC;EAED,SAAS,gBAAgB,MAAuB;GAC9C,IAAI,KAAK,WAAW,OAAO,GAAG;GAC9B,KAAK,QAAQ,OAAO;EACtB;EAIA,SAAS,eAAe,OAAqB;GAC3C,IAAI,UAAU,YAAY,OAAO;GACjC,MAAM,QAAQ,UAAU,MAAM;GAC9B,IAAI,OAAO,SAAS,MAAM,cAAc,MAAM,IAAI;EACpD;EAIA,SAAS,kBAAkB,MAAsC;GAE/D,IAAI,KAAK;QAIH,CAHgB,QACjB,aAAa,CAAA,CACb,OAAO,MAAM,UAAU,qBAAqB,OAAO,KAAK,IAAK,CAC3D,GAAa,QAAQ,WAAW,KAAK,IAAI;GAAA;GAGhD,MAAM,YAAY,oBAAoB,IAAI,OAAO;GACjD,MAAM,cAAc,oBAAoB,IAAI,SAAS;GAErD,YAAY,IAAI;IACd,eAAe;KAAE,GAAG,KAAK;KAAG,GAAG,KAAK;IAAE;IACtC,OAAO;IACP,OAAO,CACL;KACE,OAAO;KACP,UAAU,WAAW,WAAW,OAAO,KAAK;KAC5C,gBAAgB,WAAW,QAAQ,OAAO;IAC5C,GACA;KACE,OAAO;KACP,UAAU,aAAa,WAAW,OAAO,KAAK;KAC9C,gBAAgB,aAAa,QAAQ,OAAO;IAC9C,CACF;GACF,CAAC;EACH;EAIA,SAAS,cAAoB;GAC3B,MAAM,YAAY,QAAQ;GAC1B,IAAI,CAAC,WAAW;GAChB,MAAM,QAAQ;GACd,OAAO,IAAI,UAAU;IACnB;IACA,OAAO,YAAY;IACnB,MAAM,MAAM;IACZ,MAAM,MAAM;IACZ,eAAe;GACjB,CAAC;EACH;EAEA,gBAAgB;GACd,mBAAmB,SAAS,KAAK;GACjC,gBAAgB,YAAY,KAAK;GACjC,YAAY;EACd,CAAC;EAED,YAAY,CAAC,MAAM,MAAM,MAAM,IAAI,GAAG,WAAW;EAEjD,YACQ,MAAM,WACX,IAAI,SAAS;GACZ,IAAI,OAAO,MAAM;GACjB,YAAY,QAAQ,SAAS,MAAM;GACnC,UAAU,QAAQ,SAAS,MAAM,UAAU;GAC3C,mBAAmB,SAAS,KAAK;GACjC,gBAAgB,YAAY,KAAK;GACjC,YAAY;GACZ,KAAK;EACP,CACF;EAEA,sBAAsB;GACpB,kBAAkB;GAClB,KAAK,MAAM,WAAW,uBAAuB,QAAQ;GACrD,KAAK,MAAM,WAAW,oBAAoB,QAAQ;GAClD,MAAM,QAAQ;GACd,OAAO,KAAA;EACT,CAAC;EASD,SAAa;GANX;GACA,sBAAsB,YAAY;GAClC,kBAAkB;GAClB,eAAe;EAGJ,CAAO;;uBAxOlB,mBAgCM,OAAA,EAhCA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,CAAC,EAAA,GAAA;IACL,QAAA,eAAA,UAAA,GAAX,mBAgBM,OAAA;;KAhBmB,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;0BACnC,mBAcW,UAAA,MAAA,WAd6B,WAAA,QAAtB,OAAO,eAAU;6DAAuB,MAAM,KAAA,GAAA,CAClD,aAAU,KAAA,UAAA,GAAtB,mBAAgE,QAAA;;MAAnC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,iBAAA,CAAA;wEACzC,mBAWS,UAAA,MAAA,WAVQ,MAAM,QAAd,SAAI;0BADb,mBAWS,UAAA;OATN,KAAK,KAAK,KAAK;OAChB,MAAK;OACJ,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA,CAAA;OACZ,UAAU,KAAK;OACf,OAAO,KAAK,KAAK,WAAW,KAAK,KAAK;OACtC,UAAK,WAAE,gBAAgB,KAAK,IAAI;UAEK,KAAK,KAAK,QAAA,UAAA,GAAhD,YAAoF,wBAApE,KAAK,KAAK,IAAI,GAAA;;OAAyB,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA;kEACnE,mBAAkC,QAAA,MAAA,gBAAzB,KAAK,KAAK,KAAK,GAAA,CAAA,CAAA,GAAA,IAAA,UAAA;;;IAK9B,mBAA4C,OAAA;cAAnC;KAAJ,KAAI;KAAW,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA,CAAA;;IAErB,QAAA,YAAA,UAAA,GAAX,mBAUM,OAAA;;KAVgB,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA,CAAA;0BAChC,mBAQS,UAAA,MAAA,WAPkB,UAAA,QAAjB,OAAO,UAAK;yBADtB,mBAQS,UAAA;MANN,KAAK,MAAM;MACZ,MAAK;MACJ,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,KAAA,GAAS,MAAA,GAAA,CAAG,CAAC,GAAE,UAAW,UAAU,YAAA,KAAW,CAAA,CAAA;MAC5D,UAAK,WAAE,eAAe,KAAK;wBAEzB,MAAM,IAAI,GAAA,IAAA,UAAA"}
|
package/dist/vue/sheet.vue.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Sheet } from "../core/sheet.js";
|
|
2
|
-
import { SheetProps, _SheetExposed } from "../types/sheet.js";
|
|
3
|
-
import "../types/index.js";
|
|
4
|
-
//#region src/vue/sheet.vue.d.ts
|
|
5
|
-
declare const __VLS_export: import("vue").DefineComponent<SheetProps, _SheetExposed, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
6
|
-
"active-sheet-change": (payload: {
|
|
7
|
-
sheet: Sheet;
|
|
8
|
-
index: number;
|
|
9
|
-
}) => any;
|
|
10
|
-
}, string, import("vue").PublicProps, Readonly<SheetProps> & Readonly<{
|
|
11
|
-
"onActive-sheet-change"?: ((payload: {
|
|
12
|
-
sheet: Sheet;
|
|
13
|
-
index: number;
|
|
14
|
-
}) => any) | undefined;
|
|
15
|
-
}>, {
|
|
16
|
-
rows: number;
|
|
17
|
-
cols: number;
|
|
18
|
-
showToolbar: boolean;
|
|
19
|
-
showTabs: boolean;
|
|
20
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
|
-
declare const _default: typeof __VLS_export;
|
|
22
|
-
//#endregion
|
|
23
|
-
export { _default as default };
|
|
24
|
-
//# sourceMappingURL=sheet.vue.d.ts.map
|
package/dist/vue/style.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "@veltra/desktop/components/contextmenu/style";
|
package/dist/vue/style.js
DELETED
package/dist/vue/style2.css
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
@charset "UTF-8";
|
|
2
|
-
/** flex布局 */
|
|
3
|
-
/**
|
|
4
|
-
* 设置css变量
|
|
5
|
-
* 参数1:变量前缀
|
|
6
|
-
* 参数2: 一个由值组成的列表或者由key, value组成的map
|
|
7
|
-
* css-var(height, (
|
|
8
|
-
* large: 40px
|
|
9
|
-
* default: 32px
|
|
10
|
-
* small: 24px
|
|
11
|
-
* ))
|
|
12
|
-
* 生成的css变量:
|
|
13
|
-
* --u-height-large: 40px;
|
|
14
|
-
* --u-height-default: 32px;
|
|
15
|
-
* --u-height-small: 24px;
|
|
16
|
-
*/
|
|
17
|
-
/** 暗色:data-theme 与系统偏好,与 UITheme.injectBuiltInThemes 选择器策略一致 */
|
|
18
|
-
.u-sheet {
|
|
19
|
-
display: flex;
|
|
20
|
-
flex-direction: column;
|
|
21
|
-
overflow: hidden;
|
|
22
|
-
border: var(--u-border);
|
|
23
|
-
border-radius: var(--u-radius-default);
|
|
24
|
-
background-color: var(--u-bg-color-top);
|
|
25
|
-
}
|
|
26
|
-
.u-sheet__toolbar {
|
|
27
|
-
display: flex;
|
|
28
|
-
align-items: center;
|
|
29
|
-
flex-wrap: wrap;
|
|
30
|
-
gap: var(--u-gap-small);
|
|
31
|
-
padding: var(--u-gap-small);
|
|
32
|
-
border-bottom: 1px solid var(--u-border-muted-color);
|
|
33
|
-
}
|
|
34
|
-
.u-sheet__toolbar-divider {
|
|
35
|
-
width: 1px;
|
|
36
|
-
align-self: stretch;
|
|
37
|
-
margin: 2px 0;
|
|
38
|
-
background-color: var(--u-border-muted-color);
|
|
39
|
-
}
|
|
40
|
-
.u-sheet__tool {
|
|
41
|
-
display: inline-flex;
|
|
42
|
-
align-items: center;
|
|
43
|
-
gap: 4px;
|
|
44
|
-
height: var(--u-form-component-height-small);
|
|
45
|
-
padding: 0 8px;
|
|
46
|
-
border: none;
|
|
47
|
-
border-radius: var(--u-radius-small);
|
|
48
|
-
background: transparent;
|
|
49
|
-
color: var(--u-text-color-main);
|
|
50
|
-
font-size: var(--u-font-size-main-small);
|
|
51
|
-
white-space: nowrap;
|
|
52
|
-
cursor: pointer;
|
|
53
|
-
transition: background-color var(--u-transition-fast) var(--u-transition-ease), color var(--u-transition-fast) var(--u-transition-ease);
|
|
54
|
-
}
|
|
55
|
-
.u-sheet__tool:hover:not(:disabled) {
|
|
56
|
-
background-color: var(--u-bg-color-hover);
|
|
57
|
-
}
|
|
58
|
-
.u-sheet__tool:disabled {
|
|
59
|
-
color: var(--u-text-color-disabled);
|
|
60
|
-
cursor: not-allowed;
|
|
61
|
-
}
|
|
62
|
-
.u-sheet__tool-icon {
|
|
63
|
-
font-size: calc(var(--u-font-size-main-small) + 2px);
|
|
64
|
-
}
|
|
65
|
-
.u-sheet__grid {
|
|
66
|
-
flex: 1;
|
|
67
|
-
min-height: 0;
|
|
68
|
-
}
|
|
69
|
-
.u-sheet__tabs {
|
|
70
|
-
display: flex;
|
|
71
|
-
align-items: center;
|
|
72
|
-
gap: 2px;
|
|
73
|
-
padding: 2px var(--u-gap-small);
|
|
74
|
-
border-top: 1px solid var(--u-border-muted-color);
|
|
75
|
-
background-color: var(--u-bg-color-middle);
|
|
76
|
-
}
|
|
77
|
-
.u-sheet__tab {
|
|
78
|
-
padding: 4px 12px;
|
|
79
|
-
border: none;
|
|
80
|
-
border-radius: var(--u-radius-small);
|
|
81
|
-
background: transparent;
|
|
82
|
-
color: var(--u-text-color-second);
|
|
83
|
-
font-size: var(--u-font-size-main-small);
|
|
84
|
-
cursor: pointer;
|
|
85
|
-
transition: background-color var(--u-transition-fast) var(--u-transition-ease), color var(--u-transition-fast) var(--u-transition-ease);
|
|
86
|
-
}
|
|
87
|
-
.u-sheet__tab:hover {
|
|
88
|
-
background-color: var(--u-bg-color-hover);
|
|
89
|
-
}
|
|
90
|
-
.u-sheet__tab.is-active {
|
|
91
|
-
background-color: var(--u-bg-color-top);
|
|
92
|
-
color: var(--u-color-primary);
|
|
93
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
boundingBox,
|
|
5
|
-
colIndexToName,
|
|
6
|
-
colNameToIndex,
|
|
7
|
-
formatAddress,
|
|
8
|
-
formatRange,
|
|
9
|
-
iterateRange,
|
|
10
|
-
parseAddress,
|
|
11
|
-
parseRange,
|
|
12
|
-
rangeContainsAddress,
|
|
13
|
-
rangeContainsRange,
|
|
14
|
-
rangesIntersect
|
|
15
|
-
} from '../address'
|
|
16
|
-
|
|
17
|
-
describe('colIndexToName / colNameToIndex', () => {
|
|
18
|
-
it('单列名', () => {
|
|
19
|
-
expect(colIndexToName(0)).toBe('A')
|
|
20
|
-
expect(colIndexToName(25)).toBe('Z')
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('多列名', () => {
|
|
24
|
-
expect(colIndexToName(26)).toBe('AA')
|
|
25
|
-
expect(colIndexToName(27)).toBe('AB')
|
|
26
|
-
expect(colIndexToName(701)).toBe('ZZ')
|
|
27
|
-
expect(colIndexToName(702)).toBe('AAA')
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('列名转列号', () => {
|
|
31
|
-
expect(colNameToIndex('A')).toBe(0)
|
|
32
|
-
expect(colNameToIndex('Z')).toBe(25)
|
|
33
|
-
expect(colNameToIndex('AA')).toBe(26)
|
|
34
|
-
expect(colNameToIndex('aA')).toBe(26)
|
|
35
|
-
expect(colNameToIndex('1')).toBe(-1)
|
|
36
|
-
})
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
describe('parseAddress / formatAddress', () => {
|
|
40
|
-
it('双向转换', () => {
|
|
41
|
-
const cases: [string, number, number][] = [
|
|
42
|
-
['A1', 0, 0],
|
|
43
|
-
['Z99', 98, 25],
|
|
44
|
-
['AA10', 9, 26]
|
|
45
|
-
]
|
|
46
|
-
for (const [text, row, col] of cases) {
|
|
47
|
-
expect(parseAddress(text)).toEqual({ row, col })
|
|
48
|
-
expect(formatAddress({ row, col })).toBe(text)
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('兼容绝对引用', () => {
|
|
53
|
-
expect(parseAddress('$B$2')).toEqual({ row: 1, col: 1 })
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('非法输入返回 null', () => {
|
|
57
|
-
expect(parseAddress('A0')).toBeNull()
|
|
58
|
-
expect(parseAddress('1A')).toBeNull()
|
|
59
|
-
expect(parseAddress('')).toBeNull()
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
describe('parseRange / formatRange', () => {
|
|
64
|
-
it('解析并规范化角点顺序', () => {
|
|
65
|
-
expect(parseRange('D5:B2')).toEqual({ start: { row: 1, col: 1 }, end: { row: 4, col: 3 } })
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('单格区域', () => {
|
|
69
|
-
const range = parseRange('B2')
|
|
70
|
-
expect(range).toEqual({ start: { row: 1, col: 1 }, end: { row: 1, col: 1 } })
|
|
71
|
-
expect(formatRange(range!)).toBe('B2')
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it('多格区域格式化', () => {
|
|
75
|
-
expect(formatRange(parseRange('B2:D5')!)).toBe('B2:D5')
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
it('非法输入返回 null', () => {
|
|
79
|
-
expect(parseRange('A1:B2:C3')).toBeNull()
|
|
80
|
-
expect(parseRange('A1:')).toBeNull()
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
describe('range 运算', () => {
|
|
85
|
-
const b2c3 = parseRange('B2:C3')!
|
|
86
|
-
|
|
87
|
-
it('相交判断', () => {
|
|
88
|
-
expect(rangesIntersect(b2c3, parseRange('C3:D4')!)).toBe(true)
|
|
89
|
-
expect(rangesIntersect(b2c3, parseRange('A1:B1')!)).toBe(false)
|
|
90
|
-
// 相邻但不重叠 → 不相交
|
|
91
|
-
expect(rangesIntersect(b2c3, parseRange('D2:D3')!)).toBe(false)
|
|
92
|
-
expect(rangesIntersect(b2c3, parseRange('B4:C4')!)).toBe(false)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
it('包含判断', () => {
|
|
96
|
-
expect(rangeContainsAddress(b2c3, { row: 2, col: 2 })).toBe(true)
|
|
97
|
-
expect(rangeContainsAddress(b2c3, { row: 3, col: 2 })).toBe(false)
|
|
98
|
-
expect(rangeContainsRange(b2c3, parseRange('B2:B2')!)).toBe(true)
|
|
99
|
-
expect(rangeContainsRange(b2c3, parseRange('B2:D3')!)).toBe(false)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('包围盒:跨区域合并场景', () => {
|
|
103
|
-
// 已有 B2:C3,再对 C3:D4 合并 → 包围盒 B2:D4
|
|
104
|
-
const box = boundingBox([parseRange('C3:D4')!, b2c3])
|
|
105
|
-
expect(box).toEqual({ start: { row: 1, col: 1 }, end: { row: 3, col: 3 } })
|
|
106
|
-
expect(formatRange(box)).toBe('B2:D4')
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('行主序遍历', () => {
|
|
110
|
-
const addrs = [...iterateRange(b2c3)].map(formatAddress)
|
|
111
|
-
expect(addrs).toEqual(['B2', 'C2', 'B3', 'C3'])
|
|
112
|
-
})
|
|
113
|
-
})
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { CellStore, inferCellType, isEmptyCellData } from '../cell-store'
|
|
4
|
-
|
|
5
|
-
describe('CellData 类型判别', () => {
|
|
6
|
-
it('按值推断类型', () => {
|
|
7
|
-
expect(inferCellType(42)).toBe('n')
|
|
8
|
-
expect(inferCellType('hello')).toBe('s')
|
|
9
|
-
expect(inferCellType(true)).toBe('b')
|
|
10
|
-
expect(inferCellType(null)).toBeUndefined()
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('写入读出保持类型', () => {
|
|
14
|
-
const store = new CellStore()
|
|
15
|
-
store.setCellValue({ row: 0, col: 0 }, 42)
|
|
16
|
-
store.setCellValue({ row: 0, col: 1 }, 'hello')
|
|
17
|
-
store.setCellValue({ row: 0, col: 2 }, true)
|
|
18
|
-
|
|
19
|
-
expect(store.getCell({ row: 0, col: 0 })).toEqual({ v: 42, t: 'n' })
|
|
20
|
-
expect(store.getCell({ row: 0, col: 1 })).toEqual({ v: 'hello', t: 's' })
|
|
21
|
-
expect(store.getCell({ row: 0, col: 2 })).toEqual({ v: true, t: 'b' })
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('空数据判定', () => {
|
|
25
|
-
expect(isEmptyCellData(undefined)).toBe(true)
|
|
26
|
-
expect(isEmptyCellData({})).toBe(true)
|
|
27
|
-
expect(isEmptyCellData({ v: null })).toBe(true)
|
|
28
|
-
expect(isEmptyCellData({ v: '' })).toBe(true)
|
|
29
|
-
expect(isEmptyCellData({ v: 0 })).toBe(false)
|
|
30
|
-
expect(isEmptyCellData({ f: 'SUM(A1:B2)' })).toBe(false)
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
describe('稀疏性', () => {
|
|
35
|
-
it('空值写入即删除', () => {
|
|
36
|
-
const store = new CellStore()
|
|
37
|
-
const addr = { row: 0, col: 0 }
|
|
38
|
-
store.setCellValue(addr, 1)
|
|
39
|
-
expect(store.size).toBe(1)
|
|
40
|
-
|
|
41
|
-
store.setCellValue(addr, null)
|
|
42
|
-
expect(store.size).toBe(0)
|
|
43
|
-
expect(store.getCell(addr)).toBeUndefined()
|
|
44
|
-
|
|
45
|
-
store.setCellValue(addr, 'x')
|
|
46
|
-
store.setCellValue(addr, '')
|
|
47
|
-
expect(store.size).toBe(0)
|
|
48
|
-
|
|
49
|
-
store.setCell(addr, { v: 1 })
|
|
50
|
-
store.setCell(addr, {})
|
|
51
|
-
expect(store.size).toBe(0)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('store 大小不随行列数增长', () => {
|
|
55
|
-
const store = new CellStore()
|
|
56
|
-
store.setCellValue({ row: 99_999, col: 100 }, 'sparse')
|
|
57
|
-
expect(store.rowCount).toBe(100_000)
|
|
58
|
-
expect(store.colCount).toBe(101)
|
|
59
|
-
expect(store.size).toBe(1)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('10⁵ 行高水位 + 200 个真实格:迭代与序列化只含 200 格', () => {
|
|
63
|
-
const store = new CellStore()
|
|
64
|
-
store.setCellValue({ row: 99_999, col: 0 }, 'tail')
|
|
65
|
-
for (let i = 0; i < 199; i++) {
|
|
66
|
-
store.setCellValue({ row: i, col: 0 }, i)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
expect(store.rowCount).toBe(100_000)
|
|
70
|
-
expect([...store.entries()]).toHaveLength(200)
|
|
71
|
-
expect(store.snapshot()).toHaveLength(200)
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
describe('snapshot / restore', () => {
|
|
76
|
-
it('往返一致并重算高水位', () => {
|
|
77
|
-
const store = new CellStore()
|
|
78
|
-
store.setCellValue({ row: 0, col: 0 }, 1)
|
|
79
|
-
store.setCell({ row: 2, col: 3 }, { v: 'x', f: 'A1' })
|
|
80
|
-
|
|
81
|
-
const restored = new CellStore()
|
|
82
|
-
restored.restore(store.snapshot())
|
|
83
|
-
|
|
84
|
-
expect(restored.getCell({ row: 0, col: 0 })).toEqual({ v: 1, t: 'n' })
|
|
85
|
-
expect(restored.getCell({ row: 2, col: 3 })).toEqual({ v: 'x', f: 'A1' })
|
|
86
|
-
expect(restored.rowCount).toBe(3)
|
|
87
|
-
expect(restored.colCount).toBe(4)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
it('读取返回副本,外部修改不影响存储', () => {
|
|
91
|
-
const store = new CellStore()
|
|
92
|
-
store.setCell({ row: 0, col: 0 }, { v: 1 })
|
|
93
|
-
const data = store.getCell({ row: 0, col: 0 })!
|
|
94
|
-
data.v = 999
|
|
95
|
-
expect(store.getCell({ row: 0, col: 0 })!.v).toBe(1)
|
|
96
|
-
})
|
|
97
|
-
})
|