ooxml-excel-editor 1.1.0 → 1.3.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/CHANGELOG.md +154 -0
- package/README.md +206 -18
- package/dist/assets/exceljs.min-DH9BABny.js +23046 -0
- package/dist/assets/parse.worker-DIaMHX0x.js +2646 -0
- package/dist/chunks/plugin-overlay-DLb6sRhU.js +9005 -0
- package/dist/chunks/toolbar-icons-BcnMin5s.js +223 -0
- package/dist/components/ExcelViewer.vue.d.ts +172 -19
- package/dist/components/ExportProgressOverlay.vue.d.ts +11 -0
- package/dist/components/FilterPopup.vue.d.ts +4 -4
- package/dist/components/ViewerToolbar.vue.d.ts +2 -0
- package/dist/composables/useExcelDocument.d.ts +1 -0
- package/dist/core/edit/clipboard-html.d.ts +24 -0
- package/dist/core/edit/commands.d.ts +45 -1
- package/dist/core/edit/context-menu.d.ts +19 -0
- package/dist/core/edit/edit-controller.d.ts +70 -2
- package/dist/core/edit/editor-context.d.ts +18 -3
- package/dist/core/edit/editor-host.d.ts +6 -1
- package/dist/core/edit/permissions.d.ts +41 -2
- package/dist/core/edit/types.d.ts +62 -0
- package/dist/core/export/abort.d.ts +21 -0
- package/dist/core/export/exporter.d.ts +2 -1
- package/dist/core/export/types.d.ts +8 -0
- package/dist/core/export/wps-cellimages.d.ts +6 -0
- package/dist/core/export/xlsx-writer.d.ts +9 -0
- package/dist/core/format/color.d.ts +5 -0
- package/dist/core/format/number-format.d.ts +3 -0
- package/dist/core/layout/autofit.d.ts +3 -0
- package/dist/core/layout/grid-metrics.d.ts +14 -2
- package/dist/core/loader-json.d.ts +23 -0
- package/dist/core/model/clone.d.ts +3 -4
- package/dist/core/model/inspect.d.ts +43 -0
- package/dist/core/model/mutations.d.ts +16 -1
- package/dist/core/model/types.d.ts +44 -2
- package/dist/core/parser/cell-image-parser.d.ts +9 -0
- package/dist/core/parser/row-meta-parser.d.ts +3 -0
- package/dist/core/plugin.d.ts +144 -6
- package/dist/core/progress.d.ts +23 -0
- package/dist/core/render/canvas-renderer.d.ts +56 -2
- package/dist/core/render/conditional.d.ts +7 -0
- package/dist/core/template/style-overlay.d.ts +9 -0
- package/dist/core/viewer/controller.d.ts +209 -6
- package/dist/core/viewer/lightbox-host.d.ts +16 -0
- package/dist/core.js +1 -1
- package/dist/index.js +1169 -841
- package/dist/react/ExcelViewer.d.ts +143 -3
- package/dist/react/ExportProgressOverlay.d.ts +6 -0
- package/dist/react/use-excel-document.d.ts +2 -0
- package/dist/react.js +938 -335
- package/dist/style.css +1 -1
- package/dist/vue2.css +1 -0
- package/dist/vue2.js +10433 -0
- package/package.json +18 -6
- package/dist/chunks/plugin-overlay-Cfnn9EOi.js +0 -7144
- package/dist/chunks/worker-client.stub-BQVZfaLd.js +0 -7
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { i as p, p as R } from "./plugin-overlay-DLb6sRhU.js";
|
|
2
|
+
const A = Array(17).fill("#000000");
|
|
3
|
+
function I() {
|
|
4
|
+
return {
|
|
5
|
+
font: { name: "Calibri", size: 11, bold: !1, italic: !1, underline: !1, strike: !1, color: "#000000" },
|
|
6
|
+
fill: { type: "none" },
|
|
7
|
+
borders: {},
|
|
8
|
+
hAlign: "general",
|
|
9
|
+
vAlign: "bottom",
|
|
10
|
+
wrapText: !1,
|
|
11
|
+
shrinkToFit: !1,
|
|
12
|
+
textRotation: 0,
|
|
13
|
+
indent: 0,
|
|
14
|
+
numFmt: "General"
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function M(e, o) {
|
|
18
|
+
return {
|
|
19
|
+
name: e,
|
|
20
|
+
index: o,
|
|
21
|
+
state: "visible",
|
|
22
|
+
dimension: { rows: 0, cols: 0 },
|
|
23
|
+
cells: /* @__PURE__ */ new Map(),
|
|
24
|
+
styles: [I()],
|
|
25
|
+
merges: [],
|
|
26
|
+
columns: /* @__PURE__ */ new Map(),
|
|
27
|
+
rows: /* @__PURE__ */ new Map(),
|
|
28
|
+
defaultColWidth: 64,
|
|
29
|
+
defaultRowHeight: 20,
|
|
30
|
+
freeze: { frozenRows: 0, frozenCols: 0 },
|
|
31
|
+
conditional: [],
|
|
32
|
+
dataValidations: [],
|
|
33
|
+
images: [],
|
|
34
|
+
charts: [],
|
|
35
|
+
shapes: [],
|
|
36
|
+
sparklines: [],
|
|
37
|
+
showGridLines: !0
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function b(e, o) {
|
|
41
|
+
if (e == null || e === "") return { raw: null, type: "empty" };
|
|
42
|
+
if (typeof e == "number") return { raw: e, type: "number" };
|
|
43
|
+
if (typeof e == "boolean") return { raw: e, type: "boolean" };
|
|
44
|
+
if (e instanceof Date) return { raw: e, type: "date" };
|
|
45
|
+
if (typeof e != "string") return { raw: String(e), type: "string" };
|
|
46
|
+
if (!o) return { raw: e, type: "string" };
|
|
47
|
+
const t = e.trim();
|
|
48
|
+
if (/^[+-]?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(t)) {
|
|
49
|
+
const s = Number(t);
|
|
50
|
+
if (Number.isFinite(s)) return { raw: s, type: "number" };
|
|
51
|
+
}
|
|
52
|
+
if (/^(TRUE|FALSE)$/i.test(t)) return { raw: /^TRUE$/i.test(t), type: "boolean" };
|
|
53
|
+
if (/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?)?$/.test(t)) {
|
|
54
|
+
const s = new Date(t);
|
|
55
|
+
if (!isNaN(s.getTime())) return { raw: s, type: "date" };
|
|
56
|
+
}
|
|
57
|
+
return { raw: e, type: "string" };
|
|
58
|
+
}
|
|
59
|
+
function z(e, o) {
|
|
60
|
+
return o.map((t) => e[t]);
|
|
61
|
+
}
|
|
62
|
+
function k(e, o, t = {}) {
|
|
63
|
+
const s = t.startRow ?? 0, i = t.startCol ?? 0, c = t.autoInfer ?? !0;
|
|
64
|
+
let l = 0, y = 0, d = !1;
|
|
65
|
+
if (!o.length) return { lastRow: 0, lastCol: 0, wrote: !1 };
|
|
66
|
+
const r = o[0], h = r !== null && typeof r == "object" && !Array.isArray(r), x = h ? t.columns ?? Object.keys(r) : [];
|
|
67
|
+
let f = s;
|
|
68
|
+
if (h && (t.headerRow ?? !0)) {
|
|
69
|
+
for (let n = 0; n < x.length; n++) {
|
|
70
|
+
const a = f, m = i + n;
|
|
71
|
+
e.cells.set(p(a, m), { row: a, col: m, type: "string", raw: x[n], styleId: 0 }), l = Math.max(l, a), y = Math.max(y, m), d = !0;
|
|
72
|
+
}
|
|
73
|
+
f++;
|
|
74
|
+
}
|
|
75
|
+
for (let n = 0; n < o.length; n++) {
|
|
76
|
+
const a = o[n], m = Array.isArray(a) ? a : z(a, x);
|
|
77
|
+
for (let w = 0; w < m.length; w++) {
|
|
78
|
+
const u = f + n - (h && (t.headerRow ?? !0), 0), g = i + w, C = b(m[w], c);
|
|
79
|
+
C.type !== "empty" && (e.cells.set(p(u, g), { row: u, col: g, type: C.type, raw: C.raw, styleId: 0 }), l = Math.max(l, u), y = Math.max(y, g), d = !0);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { lastRow: l, lastCol: y, wrote: d };
|
|
83
|
+
}
|
|
84
|
+
function V(e, o = {}) {
|
|
85
|
+
const t = o.themeColors && o.themeColors.length === 17 ? o.themeColors : A, s = o.autoInfer ?? !0, i = o.headerRow ?? !0;
|
|
86
|
+
if (e && typeof e == "object" && !Array.isArray(e) && Array.isArray(e.sheets))
|
|
87
|
+
return { sheets: e.sheets.map((f, n) => {
|
|
88
|
+
const a = M(f.name || `Sheet${n + 1}`, n), { lastRow: m, lastCol: w, wrote: u } = k(a, f.rows ?? [], { headerRow: i, autoInfer: s });
|
|
89
|
+
return a.dimension = u ? { rows: m + 1, cols: w + 1 } : { rows: 0, cols: 0 }, a;
|
|
90
|
+
}), activeSheet: 0, themeColors: t, date1904: !1 };
|
|
91
|
+
const c = M(o.sheetName || "Sheet1", 0), l = e ?? [], { lastRow: y, lastCol: d, wrote: r } = k(c, l, { headerRow: i, autoInfer: s });
|
|
92
|
+
return c.dimension = r ? { rows: y + 1, cols: d + 1 } : { rows: 0, cols: 0 }, { sheets: [c], activeSheet: 0, themeColors: t, date1904: !1 };
|
|
93
|
+
}
|
|
94
|
+
function L(e) {
|
|
95
|
+
return !!e && typeof e == "object" && Array.isArray(e.sheets) && typeof e.activeSheet == "number" && Array.isArray(e.themeColors);
|
|
96
|
+
}
|
|
97
|
+
function S(e, o) {
|
|
98
|
+
const t = o.sheets[0], s = e.sheets[0];
|
|
99
|
+
if (!t) return e;
|
|
100
|
+
if (!s)
|
|
101
|
+
return {
|
|
102
|
+
sheets: [T(t, t.name)],
|
|
103
|
+
activeSheet: 0,
|
|
104
|
+
themeColors: o.themeColors,
|
|
105
|
+
date1904: e.date1904,
|
|
106
|
+
cellImages: e.cellImages
|
|
107
|
+
};
|
|
108
|
+
const i = {
|
|
109
|
+
name: s.name || t.name,
|
|
110
|
+
index: 0,
|
|
111
|
+
state: "visible",
|
|
112
|
+
dimension: { rows: 0, cols: 0 },
|
|
113
|
+
cells: /* @__PURE__ */ new Map(),
|
|
114
|
+
styles: t.styles.map((r) => ({ ...r })),
|
|
115
|
+
merges: t.merges.map((r) => ({ ...r })),
|
|
116
|
+
columns: new Map(t.columns),
|
|
117
|
+
rows: new Map(t.rows),
|
|
118
|
+
defaultColWidth: t.defaultColWidth,
|
|
119
|
+
defaultRowHeight: t.defaultRowHeight,
|
|
120
|
+
freeze: { ...t.freeze },
|
|
121
|
+
// 条件格式 / 数据验证 不带过来 —— 数据可能不在模板的目标列上, 套规则会误命中
|
|
122
|
+
conditional: [],
|
|
123
|
+
dataValidations: [],
|
|
124
|
+
// 模板的图 / 图表 / 形状 全部不带 —— 模板是"样式骨架", 不是内容
|
|
125
|
+
images: [],
|
|
126
|
+
charts: [],
|
|
127
|
+
shapes: [],
|
|
128
|
+
sparklines: [],
|
|
129
|
+
showGridLines: t.showGridLines
|
|
130
|
+
};
|
|
131
|
+
let c = 0, l = 0;
|
|
132
|
+
for (const r of s.cells.values()) {
|
|
133
|
+
const h = t.cells.get(p(r.row, r.col));
|
|
134
|
+
i.cells.set(p(r.row, r.col), {
|
|
135
|
+
row: r.row,
|
|
136
|
+
col: r.col,
|
|
137
|
+
type: r.type,
|
|
138
|
+
raw: r.raw,
|
|
139
|
+
rich: r.rich,
|
|
140
|
+
formula: r.formula,
|
|
141
|
+
hyperlink: r.hyperlink,
|
|
142
|
+
comment: r.comment,
|
|
143
|
+
styleId: (h == null ? void 0 : h.styleId) ?? 0,
|
|
144
|
+
dispImgId: r.dispImgId
|
|
145
|
+
}), r.row > c && (c = r.row), r.col > l && (l = r.col);
|
|
146
|
+
}
|
|
147
|
+
const y = t.columns.size ? Math.max(...t.columns.keys()) + 1 : 0, d = t.rows.size ? Math.max(...t.rows.keys()) + 1 : 0;
|
|
148
|
+
return i.dimension = {
|
|
149
|
+
rows: Math.max(s.dimension.rows, c + 1, d),
|
|
150
|
+
cols: Math.max(s.dimension.cols, l + 1, y)
|
|
151
|
+
}, {
|
|
152
|
+
sheets: [i],
|
|
153
|
+
activeSheet: 0,
|
|
154
|
+
themeColors: o.themeColors,
|
|
155
|
+
date1904: e.date1904,
|
|
156
|
+
cellImages: e.cellImages
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function T(e, o) {
|
|
160
|
+
return {
|
|
161
|
+
name: o,
|
|
162
|
+
index: 0,
|
|
163
|
+
state: "visible",
|
|
164
|
+
dimension: { rows: 0, cols: 0 },
|
|
165
|
+
cells: /* @__PURE__ */ new Map(),
|
|
166
|
+
styles: e.styles.map((t) => ({ ...t })),
|
|
167
|
+
merges: e.merges.map((t) => ({ ...t })),
|
|
168
|
+
columns: new Map(e.columns),
|
|
169
|
+
rows: new Map(e.rows),
|
|
170
|
+
defaultColWidth: e.defaultColWidth,
|
|
171
|
+
defaultRowHeight: e.defaultRowHeight,
|
|
172
|
+
freeze: { ...e.freeze },
|
|
173
|
+
conditional: [],
|
|
174
|
+
dataValidations: [],
|
|
175
|
+
images: [],
|
|
176
|
+
charts: [],
|
|
177
|
+
shapes: [],
|
|
178
|
+
sparklines: [],
|
|
179
|
+
showGridLines: e.showGridLines
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function E(e, o) {
|
|
183
|
+
return R(e, o);
|
|
184
|
+
}
|
|
185
|
+
const H = {
|
|
186
|
+
// 放大镜
|
|
187
|
+
find: '<circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>',
|
|
188
|
+
// 漏斗
|
|
189
|
+
filter: '<path d="M3 5h18l-7 8.5V20l-4-2.2V13.5z"/>',
|
|
190
|
+
// 漏斗 + 斜杠(清除筛选)
|
|
191
|
+
"clear-filter": '<path d="M3 5h18l-7 8.5V20l-4-2.2V13.5z"/><line x1="3" y1="3" x2="21" y2="21"/>',
|
|
192
|
+
// 上下箭头(排序)
|
|
193
|
+
sort: '<path d="M7 16l3 3 3-3"/><line x1="10" y1="19" x2="10" y2="5"/><path d="M17 8l-3-3-3 3"/><line x1="14" y1="5" x2="14" y2="19"/>',
|
|
194
|
+
// 下载(导出)
|
|
195
|
+
export: '<line x1="12" y1="3" x2="12" y2="15"/><path d="M8 11l4 4 4-4"/><path d="M4 19h16"/>',
|
|
196
|
+
// 放大镜带 +
|
|
197
|
+
zoom: '<circle cx="10" cy="10" r="6"/><line x1="20" y1="20" x2="14.5" y2="14.5"/><line x1="10" y1="7.5" x2="10" y2="12.5"/><line x1="7.5" y1="10" x2="12.5" y2="10"/>',
|
|
198
|
+
// 两个叠框(复制)
|
|
199
|
+
copy: '<rect x="9" y="9" width="11" height="11" rx="1.5"/><path d="M5 15H4V5a1 1 0 0 1 1-1h10v1"/>',
|
|
200
|
+
// 十字线(冻结行列)
|
|
201
|
+
freeze: '<line x1="3" y1="9" x2="21" y2="9"/><line x1="9" y1="3" x2="9" y2="21"/>',
|
|
202
|
+
// 自动换行:两条文本线 + 折回箭头
|
|
203
|
+
"wrap-text": '<line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="18" x2="10" y2="18"/><path d="M3 12h15a3 3 0 0 1 0 6h-3"/><polyline points="17 15 14 18 17 21"/>',
|
|
204
|
+
// 模板:文档 + 排版网格
|
|
205
|
+
template: '<rect x="4" y="3" width="16" height="18" rx="1.5"/><line x1="4" y1="8" x2="20" y2="8"/><line x1="8" y1="12" x2="16" y2="12"/><line x1="8" y1="16" x2="16" y2="16"/>',
|
|
206
|
+
// 图片工具:山+太阳的图片框 + 小齿轮(批量转换)
|
|
207
|
+
"image-tools": '<rect x="3" y="4" width="14" height="14" rx="1.5"/><circle cx="8" cy="9" r="1.5"/><polyline points="3 16 7 12 11 16 14 13 17 16"/><path d="M19 19l2 2M19 21l2-2"/>',
|
|
208
|
+
// 三点(更多)
|
|
209
|
+
more: '<circle cx="5" cy="12" r="1.6" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.6" fill="currentColor" stroke="none"/><circle cx="19" cy="12" r="1.6" fill="currentColor" stroke="none"/>',
|
|
210
|
+
// 下拉小箭头
|
|
211
|
+
caret: '<path d="M6 9l6 6 6-6"/>'
|
|
212
|
+
};
|
|
213
|
+
function G(e) {
|
|
214
|
+
return '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' + e + "</svg>";
|
|
215
|
+
}
|
|
216
|
+
export {
|
|
217
|
+
H as T,
|
|
218
|
+
S as a,
|
|
219
|
+
L as i,
|
|
220
|
+
V as j,
|
|
221
|
+
E as p,
|
|
222
|
+
G as s
|
|
223
|
+
};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { ExcelPlugin, ToolbarItem } from '../core/plugin';
|
|
1
|
+
import { ExcelPlugin, PermissionDeniedPayload, ToolbarItem } from '../core/plugin';
|
|
2
2
|
import { ExcelSource } from '../core/loader';
|
|
3
|
-
import {
|
|
3
|
+
import { JsonInput, JsonLoadOptions } from '../core/loader-json';
|
|
4
|
+
import { CellModel, CellStyleFn, CellStyleOverride, MergeRange, TransformModelFn, WorkbookModel } from '../core/model/types';
|
|
4
5
|
import { ParseProgress } from '../core/progress';
|
|
5
6
|
import { ReadOptions } from '../core/model/data-access';
|
|
6
7
|
import { ViewerTheme } from '../core/render/theme';
|
|
8
|
+
import { ContextMenuBeforePayload, ContextMenuShowPayload, ContextMenuTransform } from '../core/viewer/controller';
|
|
9
|
+
import { EditableTarget } from '../core/edit/types';
|
|
7
10
|
import { FormulaEngineFactory } from '../core/formula/engine';
|
|
8
11
|
import { CellChangePayload, DimChangePayload, DirtyChangePayload, ImageChangePayload, StructChangePayload } from '../core/edit/edit-controller';
|
|
9
12
|
import { EditorResolver } from '../core/edit/editor-context';
|
|
@@ -11,6 +14,27 @@ import { ImageExportOptions, PdfExportOptions, PrintOptions } from '../core/expo
|
|
|
11
14
|
import { ResolvedToolbarItem } from './toolbar-types';
|
|
12
15
|
type __VLS_Props = {
|
|
13
16
|
src?: ExcelSource;
|
|
17
|
+
/**
|
|
18
|
+
* 直接喂 WorkbookModel 或 JsonInput(P3):绕过 parser,常用于"从后端拿 JSON 直接渲染"或
|
|
19
|
+
* "前端构造好模型再渲染"。WorkbookModel-shape 直用,JsonInput(二维数组 / 对象数组 / `{sheets:[...]}`)
|
|
20
|
+
* 走 `jsonToWorkbook` 自动构造。优先级:`workbook` > `src`(两者都给时取 `workbook`)。
|
|
21
|
+
*/
|
|
22
|
+
workbook?: WorkbookModel | JsonInput;
|
|
23
|
+
/** JSON 直渲选项(`workbook` = JsonInput 时生效) */
|
|
24
|
+
jsonOptions?: JsonLoadOptions;
|
|
25
|
+
/**
|
|
26
|
+
* 渲染模板(P3 重设计 2026-06-08):一份 .xlsx 当**样式捐赠者** —— 模板的 styling
|
|
27
|
+
* (styles / merges / 列宽 / 行高 / freeze / theme)套到无格式数据源上,模板的 raw 文字 / 占位符
|
|
28
|
+
* / 图 / 图表 / 条件格式 全部丢弃。
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ **只在数据源是 :workbook(JSON / 模型)时生效**;`:src`(.xlsx)数据源自带格式,
|
|
31
|
+
* 给 `:templateFile` 会被忽略并 console.warn。
|
|
32
|
+
*
|
|
33
|
+
* 工具栏内置 `template` 项可在运行时切换/导入/清除,无需重新挂载。
|
|
34
|
+
*/
|
|
35
|
+
templateFile?: ExcelSource;
|
|
36
|
+
/** 模板显示名(标题栏 `· 模板: xxx` 后缀);不给则取运行时 File.name */
|
|
37
|
+
templateName?: string;
|
|
14
38
|
fileName?: string;
|
|
15
39
|
/** 外观主题(覆盖默认配色) */
|
|
16
40
|
theme?: Partial<ViewerTheme>;
|
|
@@ -18,6 +42,10 @@ type __VLS_Props = {
|
|
|
18
42
|
transformModel?: TransformModelFn;
|
|
19
43
|
/** 渲染钩子: 按单元格覆盖样式 */
|
|
20
44
|
cellStyle?: CellStyleFn;
|
|
45
|
+
/** WPS 单元格内嵌图(DISPIMG)贴合方式:contain 等比(默认,与 WPS 渲染一致)/ fill 拉伸铺满 / cover 等比裁剪 */
|
|
46
|
+
cellImageFit?: 'fill' | 'contain' | 'cover';
|
|
47
|
+
/** 图片点击放大灯箱(默认 true):只读模式单击图放大、编辑模式右键「查看大图」;false 关闭 */
|
|
48
|
+
imageLightbox?: boolean;
|
|
21
49
|
/** 单击超链接是否默认在新标签打开(false 时只派发 hyperlink-click 事件) */
|
|
22
50
|
openLinks?: boolean;
|
|
23
51
|
/** 插件列表(打包主题/钩子/事件/overlay) */
|
|
@@ -37,12 +65,52 @@ type __VLS_Props = {
|
|
|
37
65
|
}) => boolean | void;
|
|
38
66
|
/** 只读区域(0-based 闭区间);命中即只读 */
|
|
39
67
|
readOnlyRanges?: MergeRange[];
|
|
68
|
+
/**
|
|
69
|
+
* **可编辑白名单**(2026-06-08 新增) —— 设了就是白名单语义:默认只读,只有命中**任一**
|
|
70
|
+
* target 的格才可编辑。4 种 target 形状:`{row,col}` 单格 / `{row}` 整行 / `{col}` 整列 /
|
|
71
|
+
* `MergeRange` 矩形。可单值可数组,允许**不相邻**多个 target.
|
|
72
|
+
*
|
|
73
|
+
* `undefined`(不传)= 不启用白名单(老行为:默认全可编辑);`[]`(显式空数组)= 全只读.
|
|
74
|
+
* 与 `readOnlyRanges` / `cellReadOnly` 叠加 — 白名单命中后仍可被它们二次"黑"掉.
|
|
75
|
+
*/
|
|
76
|
+
editableTargets?: EditableTarget | EditableTarget[];
|
|
77
|
+
/**
|
|
78
|
+
* **严格尺寸闸门**(Phase B, 2026-06-08) —— 默认 `false`: setColumnWidth/setRowHeight/autoFit 仅受全局
|
|
79
|
+
* `editable` 控制(老行为). 设 `true` + `editableTargets` 启用了 → 该列/行至少有 1 格在白名单内才能改尺寸.
|
|
80
|
+
*/
|
|
81
|
+
strictDimensions?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* **只读单元格视觉钩子** (Phase C, 2026-06-08):
|
|
84
|
+
* - `false` (默认) = 无视觉差异 (老行为不变)
|
|
85
|
+
* - `true` = 套内置默认 (浅灰底 `#f5f7fa`,跟工具栏一致)
|
|
86
|
+
* - `CellStyleOverride` 对象 = 固定样式给所有只读格 (如黄底高亮)
|
|
87
|
+
* - `CellStyleFn` 函数 = 按格自定义
|
|
88
|
+
*
|
|
89
|
+
* 跟 `editableTargets` 配合: 白名单未覆盖的格自动套此视觉, 用户一眼看出哪些可编辑.
|
|
90
|
+
*/
|
|
91
|
+
readOnlyCellStyle?: boolean | CellStyleOverride | CellStyleFn;
|
|
40
92
|
/** 自定义单元格编辑器(按格返回工厂;覆盖插件 editor)。需 editable 开启 */
|
|
41
93
|
editor?: EditorResolver;
|
|
42
94
|
/** 公式重算(E4):默认 false 沿用缓存值。开启后编辑公式/被引用格 → 依赖格自动重算。需 editable */
|
|
43
95
|
recalc?: boolean;
|
|
44
96
|
/** 自定义/自研公式引擎工厂(可换引擎);不给则用默认 HyperFormula(需 npm i hyperformula) */
|
|
45
97
|
formulaEngine?: FormulaEngineFactory;
|
|
98
|
+
/**
|
|
99
|
+
* 内置导出进度遮罩(P1.5):默认 `true` —— 调 `viewer.downloadPdf` / `downloadImage` / `downloadXlsx` /
|
|
100
|
+
* `print` / 选区图片批量转换 时,壳自动建 `AbortController` + 接 `onProgress` →
|
|
101
|
+
* 显示居中模态(stage 标签 + 进度条 + 取消按钮)。**关闭** `:export-progress="false"` 走纯回调
|
|
102
|
+
* 路径(用户自己接 `opts.onProgress`/`opts.signal`)。**完全自渲染**用 `#export-progress` 插槽
|
|
103
|
+
* (拿到 `{ state, busy, cancel }`)。
|
|
104
|
+
*/
|
|
105
|
+
exportProgress?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* 右键菜单(Plan C):
|
|
108
|
+
* - `false` → 不弹内置菜单(`before-context-menu` / `context-menu` 事件仍触发,用户自渲染)
|
|
109
|
+
* - 函数 `(ctx, items) => MenuItem[] | undefined` → 在内置 items 上加 / 减 / 重排;返 `undefined` 用原样
|
|
110
|
+
* - 不传(默认)→ editable 时显示内置菜单,非 editable 走浏览器默认菜单
|
|
111
|
+
* 与 `@before-context-menu` / `@context-menu` 事件叠加使用。
|
|
112
|
+
*/
|
|
113
|
+
contextMenu?: boolean | ContextMenuTransform;
|
|
46
114
|
};
|
|
47
115
|
/** 单元格当前屏幕矩形(render-area 相对坐标);供 overlay slot / 命令式定位 */
|
|
48
116
|
declare function rectOf(row: number, col: number): {
|
|
@@ -58,6 +126,7 @@ declare function rectOfRange(range: MergeRange): {
|
|
|
58
126
|
w: number;
|
|
59
127
|
h: number;
|
|
60
128
|
} | null;
|
|
129
|
+
declare function cancelExport(): void;
|
|
61
130
|
declare function __VLS_template(): {
|
|
62
131
|
attrs: Partial<{}>;
|
|
63
132
|
slots: {
|
|
@@ -100,9 +169,21 @@ declare function __VLS_template(): {
|
|
|
100
169
|
} | null;
|
|
101
170
|
range: string;
|
|
102
171
|
}): any;
|
|
172
|
+
'export-progress'?(_: {
|
|
173
|
+
state: {
|
|
174
|
+
stage: import('../core/progress').ExportStage;
|
|
175
|
+
sheetIndex?: number | undefined;
|
|
176
|
+
pageIndex?: number | undefined;
|
|
177
|
+
ratio?: number | undefined;
|
|
178
|
+
label?: string | undefined;
|
|
179
|
+
} | null;
|
|
180
|
+
busy: boolean;
|
|
181
|
+
cancel: typeof cancelExport;
|
|
182
|
+
}): any;
|
|
103
183
|
};
|
|
104
184
|
refs: {
|
|
105
185
|
rootEl: HTMLDivElement;
|
|
186
|
+
fbEl: HTMLTextAreaElement;
|
|
106
187
|
renderAreaEl: HTMLDivElement;
|
|
107
188
|
canvasEl: HTMLCanvasElement;
|
|
108
189
|
ovMain: HTMLDivElement;
|
|
@@ -113,6 +194,7 @@ declare function __VLS_template(): {
|
|
|
113
194
|
spacerEl: HTMLDivElement;
|
|
114
195
|
pluginOvEl: HTMLDivElement;
|
|
115
196
|
editorSlotEl: HTMLDivElement;
|
|
197
|
+
templateInputEl: HTMLInputElement;
|
|
116
198
|
};
|
|
117
199
|
rootEl: HTMLDivElement;
|
|
118
200
|
};
|
|
@@ -128,6 +210,8 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {
|
|
|
128
210
|
rectOfRange(range: MergeRange): import('../core/plugin').Rect | null;
|
|
129
211
|
redraw(): void;
|
|
130
212
|
isCellEditable(row: number, col: number): boolean;
|
|
213
|
+
setEditableTargets(targets: EditableTarget | EditableTarget[] | undefined): void;
|
|
214
|
+
getEditableTargets(): EditableTarget | EditableTarget[] | undefined;
|
|
131
215
|
exportImage(opts?: ImageExportOptions): Promise<Blob>;
|
|
132
216
|
downloadImage(opts?: ImageExportOptions): Promise<void>;
|
|
133
217
|
exportPdf(opts?: PdfExportOptions): Promise<Blob>;
|
|
@@ -162,34 +246,85 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {
|
|
|
162
246
|
col: number;
|
|
163
247
|
} | null;
|
|
164
248
|
getCellSnapshot(row: number, col: number): import('../core').CellSnapshot | null;
|
|
249
|
+
inspectCell(row: number, col: number): import('../core/plugin').CellInspection | null;
|
|
165
250
|
beginEdit(row: number, col: number): boolean;
|
|
166
251
|
cancelEdit(): void;
|
|
167
252
|
isEditing(): boolean;
|
|
168
|
-
setStyle(range: MergeRange, patch:
|
|
253
|
+
setStyle(range: MergeRange, patch: CellStyleOverride): boolean;
|
|
254
|
+
getActiveFillColor(): string;
|
|
255
|
+
getActiveFontColor(): string;
|
|
256
|
+
setSelectionFill(color: string | null): boolean;
|
|
257
|
+
setSelectionFontColor(color: string): boolean;
|
|
258
|
+
getSelectionWrapState(): "all" | "none" | "mixed";
|
|
259
|
+
toggleWrapTextOnSelection(): boolean;
|
|
260
|
+
mergeCells(range: MergeRange): boolean;
|
|
261
|
+
unmergeCells(range: MergeRange): boolean;
|
|
262
|
+
pasteText(text: string, at?: {
|
|
263
|
+
row: number;
|
|
264
|
+
col: number;
|
|
265
|
+
}): boolean;
|
|
266
|
+
pasteRichHtml(html: string, at?: {
|
|
267
|
+
row: number;
|
|
268
|
+
col: number;
|
|
269
|
+
}): boolean;
|
|
270
|
+
pasteImageBlob(blob: Blob, at?: {
|
|
271
|
+
row: number;
|
|
272
|
+
col: number;
|
|
273
|
+
}): Promise<boolean>;
|
|
169
274
|
getImages(): import('../core/model/types').ImageAnchor[];
|
|
170
275
|
addImage(anchor: import('../core/model/types').ImageAnchor): number;
|
|
171
276
|
removeImage(index: number): boolean;
|
|
172
277
|
moveImage(index: number, dxPx: number, dyPx: number): boolean;
|
|
173
278
|
resizeImage(index: number, widthPx: number, heightPx: number): boolean;
|
|
279
|
+
getCellEditString(): string;
|
|
280
|
+
canEditActiveCell(): boolean;
|
|
281
|
+
commitActiveCellValue(value: string, move?: "down"): boolean;
|
|
282
|
+
getCellImages(): {
|
|
283
|
+
id: string;
|
|
284
|
+
src: string;
|
|
285
|
+
mime?: string;
|
|
286
|
+
}[];
|
|
287
|
+
getCellImageAt(row: number, col: number): {
|
|
288
|
+
id: string;
|
|
289
|
+
src: string;
|
|
290
|
+
mime?: string;
|
|
291
|
+
} | null;
|
|
292
|
+
openImageLightbox(src: string, fileName?: string, mime?: string): void;
|
|
293
|
+
setCellImageFit(fit: "fill" | "contain" | "cover"): void;
|
|
294
|
+
convertImageToCell(imageIndex: number, row: number, col: number): boolean;
|
|
295
|
+
convertImageToCellAuto(imageIndex: number): boolean;
|
|
296
|
+
convertAllImagesToCells(col?: number): number;
|
|
297
|
+
convertImagesInRangeToCell(range: MergeRange): Promise<number>;
|
|
298
|
+
convertCellImagesInRangeToFloat(range: MergeRange, size?: {
|
|
299
|
+
width: number;
|
|
300
|
+
height: number;
|
|
301
|
+
}): Promise<number>;
|
|
302
|
+
openContextMenu(x: number, y: number, items?: import('../core/plugin').MenuItem[]): void;
|
|
303
|
+
closeContextMenu(): void;
|
|
304
|
+
convertCellImageToFloat(row: number, col: number, size?: {
|
|
305
|
+
width: number;
|
|
306
|
+
height: number;
|
|
307
|
+
}): boolean;
|
|
174
308
|
insertRows(at: number, count?: number): boolean;
|
|
175
309
|
deleteRows(at: number, count?: number): boolean;
|
|
176
310
|
insertCols(at: number, count?: number): boolean;
|
|
177
311
|
deleteCols(at: number, count?: number): boolean;
|
|
178
|
-
setColumnWidth(
|
|
179
|
-
setRowHeight(
|
|
312
|
+
setColumnWidth(target: import('../core/edit/types').DimTarget, width: number): number;
|
|
313
|
+
setRowHeight(target: import('../core/edit/types').DimTarget, height: number): number;
|
|
314
|
+
autoFitColumns(target?: import('../core/edit/types').DimTarget): number;
|
|
315
|
+
autoFitRows(target?: import('../core/edit/types').DimTarget): number;
|
|
316
|
+
resetColumnWidth(target: import('../core/edit/types').DimTarget): number;
|
|
317
|
+
resetRowHeight(target: import('../core/edit/types').DimTarget): number;
|
|
180
318
|
isRecalcReady(): boolean;
|
|
319
|
+
getVirtualExtent(): {
|
|
320
|
+
rows: number;
|
|
321
|
+
cols: number;
|
|
322
|
+
};
|
|
181
323
|
isDirty(): boolean;
|
|
182
324
|
resetToOriginal(): boolean;
|
|
183
325
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
184
326
|
error: (message: string) => any;
|
|
185
327
|
progress: (progress: ParseProgress) => any;
|
|
186
|
-
"cell-change": (payload: CellChangePayload) => any;
|
|
187
|
-
"edit-start": (payload: unknown) => any;
|
|
188
|
-
"edit-commit": (payload: unknown) => any;
|
|
189
|
-
"dim-change": (payload: DimChangePayload) => any;
|
|
190
|
-
"dirty-change": (payload: DirtyChangePayload) => any;
|
|
191
|
-
"image-change": (payload: ImageChangePayload) => any;
|
|
192
|
-
"struct-change": (payload: StructChangePayload) => any;
|
|
193
328
|
"cell-click": (payload: {
|
|
194
329
|
row: number;
|
|
195
330
|
col: number;
|
|
@@ -218,17 +353,20 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {
|
|
|
218
353
|
col: number;
|
|
219
354
|
};
|
|
220
355
|
}) => any;
|
|
356
|
+
"cell-change": (payload: CellChangePayload) => any;
|
|
357
|
+
"edit-start": (payload: unknown) => any;
|
|
358
|
+
"edit-commit": (payload: unknown) => any;
|
|
359
|
+
"dim-change": (payload: DimChangePayload) => any;
|
|
360
|
+
"dirty-change": (payload: DirtyChangePayload) => any;
|
|
361
|
+
"image-change": (payload: ImageChangePayload) => any;
|
|
362
|
+
"struct-change": (payload: StructChangePayload) => any;
|
|
363
|
+
"permission-denied": (payload: PermissionDeniedPayload) => any;
|
|
221
364
|
rendered: (workbook: WorkbookModel) => any;
|
|
365
|
+
"before-context-menu": (payload: ContextMenuBeforePayload) => any;
|
|
366
|
+
"context-menu": (payload: ContextMenuShowPayload) => any;
|
|
222
367
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
223
368
|
onError?: ((message: string) => any) | undefined;
|
|
224
369
|
onProgress?: ((progress: ParseProgress) => any) | undefined;
|
|
225
|
-
"onCell-change"?: ((payload: CellChangePayload) => any) | undefined;
|
|
226
|
-
"onEdit-start"?: ((payload: unknown) => any) | undefined;
|
|
227
|
-
"onEdit-commit"?: ((payload: unknown) => any) | undefined;
|
|
228
|
-
"onDim-change"?: ((payload: DimChangePayload) => any) | undefined;
|
|
229
|
-
"onDirty-change"?: ((payload: DirtyChangePayload) => any) | undefined;
|
|
230
|
-
"onImage-change"?: ((payload: ImageChangePayload) => any) | undefined;
|
|
231
|
-
"onStruct-change"?: ((payload: StructChangePayload) => any) | undefined;
|
|
232
370
|
"onCell-click"?: ((payload: {
|
|
233
371
|
row: number;
|
|
234
372
|
col: number;
|
|
@@ -257,12 +395,26 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {
|
|
|
257
395
|
col: number;
|
|
258
396
|
};
|
|
259
397
|
}) => any) | undefined;
|
|
398
|
+
"onCell-change"?: ((payload: CellChangePayload) => any) | undefined;
|
|
399
|
+
"onEdit-start"?: ((payload: unknown) => any) | undefined;
|
|
400
|
+
"onEdit-commit"?: ((payload: unknown) => any) | undefined;
|
|
401
|
+
"onDim-change"?: ((payload: DimChangePayload) => any) | undefined;
|
|
402
|
+
"onDirty-change"?: ((payload: DirtyChangePayload) => any) | undefined;
|
|
403
|
+
"onImage-change"?: ((payload: ImageChangePayload) => any) | undefined;
|
|
404
|
+
"onStruct-change"?: ((payload: StructChangePayload) => any) | undefined;
|
|
405
|
+
"onPermission-denied"?: ((payload: PermissionDeniedPayload) => any) | undefined;
|
|
260
406
|
onRendered?: ((workbook: WorkbookModel) => any) | undefined;
|
|
407
|
+
"onBefore-context-menu"?: ((payload: ContextMenuBeforePayload) => any) | undefined;
|
|
408
|
+
"onContext-menu"?: ((payload: ContextMenuShowPayload) => any) | undefined;
|
|
261
409
|
}>, {
|
|
262
410
|
toolbar: boolean | Array<string | ToolbarItem>;
|
|
411
|
+
imageLightbox: boolean;
|
|
263
412
|
openLinks: boolean;
|
|
413
|
+
exportProgress: boolean;
|
|
414
|
+
contextMenu: boolean | ContextMenuTransform;
|
|
264
415
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
265
416
|
rootEl: HTMLDivElement;
|
|
417
|
+
fbEl: HTMLTextAreaElement;
|
|
266
418
|
renderAreaEl: HTMLDivElement;
|
|
267
419
|
canvasEl: HTMLCanvasElement;
|
|
268
420
|
ovMain: HTMLDivElement;
|
|
@@ -273,6 +425,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {
|
|
|
273
425
|
spacerEl: HTMLDivElement;
|
|
274
426
|
pluginOvEl: HTMLDivElement;
|
|
275
427
|
editorSlotEl: HTMLDivElement;
|
|
428
|
+
templateInputEl: HTMLInputElement;
|
|
276
429
|
}, HTMLDivElement>;
|
|
277
430
|
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
278
431
|
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ExportProgress } from '../core/progress';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
state: ExportProgress | null;
|
|
4
|
+
busy: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
7
|
+
cancel: () => any;
|
|
8
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
9
|
+
onCancel?: (() => any) | undefined;
|
|
10
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
export default _default;
|
|
@@ -6,14 +6,14 @@ type __VLS_Props = {
|
|
|
6
6
|
sortDir?: 'asc' | 'desc' | null;
|
|
7
7
|
};
|
|
8
8
|
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
9
|
-
sort: (dir: "
|
|
10
|
-
close: () => any;
|
|
9
|
+
sort: (dir: "desc" | "asc") => any;
|
|
11
10
|
apply: (checked: string[]) => any;
|
|
11
|
+
close: () => any;
|
|
12
12
|
clear: () => any;
|
|
13
13
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
-
onSort?: ((dir: "
|
|
15
|
-
onClose?: (() => any) | undefined;
|
|
14
|
+
onSort?: ((dir: "desc" | "asc") => any) | undefined;
|
|
16
15
|
onApply?: ((checked: string[]) => any) | undefined;
|
|
16
|
+
onClose?: (() => any) | undefined;
|
|
17
17
|
onClear?: (() => any) | undefined;
|
|
18
18
|
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
19
19
|
rootEl: HTMLDivElement;
|
|
@@ -6,6 +6,7 @@ export declare function useExcelDocument(): {
|
|
|
6
6
|
error: import('vue').Ref<string | null, string | null>;
|
|
7
7
|
workbook: import('vue').ShallowRef<WorkbookModel | null, WorkbookModel | null>;
|
|
8
8
|
load: (src: ExcelSource, transform?: TransformModelFn) => Promise<void>;
|
|
9
|
+
loadModel: (model: WorkbookModel, transform?: TransformModelFn) => void;
|
|
9
10
|
progress: import('vue').Ref<{
|
|
10
11
|
stage: "read" | "parse" | "build";
|
|
11
12
|
ratio?: number | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CellStyleOverride, MergeRange } from '../model/types';
|
|
2
|
+
import { CellValue } from '../model/data-access';
|
|
3
|
+
export interface ParsedClipboard {
|
|
4
|
+
/** 二维值(原始串/数字/公式,交 setCellValue 推断);稠密对齐 */
|
|
5
|
+
values: CellValue[][];
|
|
6
|
+
/** 逐格样式覆盖(只含解析出的字段) */
|
|
7
|
+
styles: {
|
|
8
|
+
row: number;
|
|
9
|
+
col: number;
|
|
10
|
+
patch: CellStyleOverride;
|
|
11
|
+
}[];
|
|
12
|
+
/** 合并区(rowspan/colspan>1) */
|
|
13
|
+
merges: MergeRange[];
|
|
14
|
+
/** data-uri 图片(row,col,dataUrl) */
|
|
15
|
+
images: {
|
|
16
|
+
row: number;
|
|
17
|
+
col: number;
|
|
18
|
+
dataUrl: string;
|
|
19
|
+
}[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 解析剪贴板 HTML → {values, styles, merges, images}。非浏览器环境 / 无 <table> 返 null(调用方回退 TSV)。
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseClipboardHtml(html: string): ParsedClipboard | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CellModel, CellStyleOverride, ColumnInfo, ImageAnchor, RowInfo, SheetModel, WorkbookModel } from '../model/types';
|
|
1
|
+
import { CellModel, CellStyleOverride, ColumnInfo, ImageAnchor, MergeRange, RowInfo, SheetModel, WorkbookModel } from '../model/types';
|
|
2
2
|
import { CellValue } from '../model/data-access';
|
|
3
3
|
import { StructOp } from '../model/structure';
|
|
4
4
|
export type CellPos = {
|
|
@@ -58,6 +58,50 @@ export type EditCommand = {
|
|
|
58
58
|
} | {
|
|
59
59
|
kind: 'restore-wb';
|
|
60
60
|
snapshot: WorkbookModel;
|
|
61
|
+
} | {
|
|
62
|
+
kind: 'merge-cells';
|
|
63
|
+
range: MergeRange;
|
|
64
|
+
} | {
|
|
65
|
+
kind: 'unmerge-cells';
|
|
66
|
+
range: MergeRange;
|
|
67
|
+
} | {
|
|
68
|
+
kind: 'restore-merges';
|
|
69
|
+
merges: MergeRange[];
|
|
70
|
+
cells: {
|
|
71
|
+
row: number;
|
|
72
|
+
col: number;
|
|
73
|
+
cell: CellModel | null;
|
|
74
|
+
}[];
|
|
75
|
+
} | {
|
|
76
|
+
kind: 'convert-to-cell';
|
|
77
|
+
imageIndex: number;
|
|
78
|
+
row: number;
|
|
79
|
+
col: number;
|
|
80
|
+
} | {
|
|
81
|
+
kind: 'convert-to-cells';
|
|
82
|
+
targets: {
|
|
83
|
+
imageIndex: number;
|
|
84
|
+
row: number;
|
|
85
|
+
col: number;
|
|
86
|
+
}[];
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'convert-to-float';
|
|
89
|
+
row: number;
|
|
90
|
+
col: number;
|
|
91
|
+
size?: {
|
|
92
|
+
width: number;
|
|
93
|
+
height: number;
|
|
94
|
+
};
|
|
95
|
+
} | {
|
|
96
|
+
kind: 'convert-to-floats';
|
|
97
|
+
cells: {
|
|
98
|
+
row: number;
|
|
99
|
+
col: number;
|
|
100
|
+
size?: {
|
|
101
|
+
width: number;
|
|
102
|
+
height: number;
|
|
103
|
+
};
|
|
104
|
+
}[];
|
|
61
105
|
};
|
|
62
106
|
/** dim 命令(列宽/行高)— 仅维度族,无格位置 */
|
|
63
107
|
export type DimCommand = Extract<EditCommand, {
|