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.
Files changed (54) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/README.md +206 -18
  3. package/dist/assets/exceljs.min-DH9BABny.js +23046 -0
  4. package/dist/assets/parse.worker-DIaMHX0x.js +2646 -0
  5. package/dist/chunks/plugin-overlay-DLb6sRhU.js +9005 -0
  6. package/dist/chunks/toolbar-icons-BcnMin5s.js +223 -0
  7. package/dist/components/ExcelViewer.vue.d.ts +172 -19
  8. package/dist/components/ExportProgressOverlay.vue.d.ts +11 -0
  9. package/dist/components/FilterPopup.vue.d.ts +4 -4
  10. package/dist/components/ViewerToolbar.vue.d.ts +2 -0
  11. package/dist/composables/useExcelDocument.d.ts +1 -0
  12. package/dist/core/edit/clipboard-html.d.ts +24 -0
  13. package/dist/core/edit/commands.d.ts +45 -1
  14. package/dist/core/edit/context-menu.d.ts +19 -0
  15. package/dist/core/edit/edit-controller.d.ts +70 -2
  16. package/dist/core/edit/editor-context.d.ts +18 -3
  17. package/dist/core/edit/editor-host.d.ts +6 -1
  18. package/dist/core/edit/permissions.d.ts +41 -2
  19. package/dist/core/edit/types.d.ts +62 -0
  20. package/dist/core/export/abort.d.ts +21 -0
  21. package/dist/core/export/exporter.d.ts +2 -1
  22. package/dist/core/export/types.d.ts +8 -0
  23. package/dist/core/export/wps-cellimages.d.ts +6 -0
  24. package/dist/core/export/xlsx-writer.d.ts +9 -0
  25. package/dist/core/format/color.d.ts +5 -0
  26. package/dist/core/format/number-format.d.ts +3 -0
  27. package/dist/core/layout/autofit.d.ts +3 -0
  28. package/dist/core/layout/grid-metrics.d.ts +14 -2
  29. package/dist/core/loader-json.d.ts +23 -0
  30. package/dist/core/model/clone.d.ts +3 -4
  31. package/dist/core/model/inspect.d.ts +43 -0
  32. package/dist/core/model/mutations.d.ts +16 -1
  33. package/dist/core/model/types.d.ts +44 -2
  34. package/dist/core/parser/cell-image-parser.d.ts +9 -0
  35. package/dist/core/parser/row-meta-parser.d.ts +3 -0
  36. package/dist/core/plugin.d.ts +144 -6
  37. package/dist/core/progress.d.ts +23 -0
  38. package/dist/core/render/canvas-renderer.d.ts +56 -2
  39. package/dist/core/render/conditional.d.ts +7 -0
  40. package/dist/core/template/style-overlay.d.ts +9 -0
  41. package/dist/core/viewer/controller.d.ts +209 -6
  42. package/dist/core/viewer/lightbox-host.d.ts +16 -0
  43. package/dist/core.js +1 -1
  44. package/dist/index.js +1169 -841
  45. package/dist/react/ExcelViewer.d.ts +143 -3
  46. package/dist/react/ExportProgressOverlay.d.ts +6 -0
  47. package/dist/react/use-excel-document.d.ts +2 -0
  48. package/dist/react.js +938 -335
  49. package/dist/style.css +1 -1
  50. package/dist/vue2.css +1 -0
  51. package/dist/vue2.js +10433 -0
  52. package/package.json +18 -6
  53. package/dist/chunks/plugin-overlay-Cfnn9EOi.js +0 -7144
  54. 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 { CellModel, CellStyleFn, MergeRange, TransformModelFn, WorkbookModel } from '../core/model/types';
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: import('../core/model/types').CellStyleOverride): boolean;
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(col: number, width: number): boolean;
179
- setRowHeight(row: number, height: number): boolean;
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: "asc" | "desc") => any;
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: "asc" | "desc") => any) | undefined;
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;
@@ -1,5 +1,7 @@
1
1
  type __VLS_Props = {
2
2
  fileName?: string;
3
+ /** 模板名(运行时或 prop 给出);非空时拼接到标题尾部 ` · 模板: <name>` */
4
+ templateName?: string;
3
5
  sheetCount: number;
4
6
  zoom: number;
5
7
  };
@@ -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, {