ooxml-excel-editor 1.1.0 → 1.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +148 -4
  3. package/dist/chunks/plugin-overlay-BBrNby8v.js +8965 -0
  4. package/dist/chunks/worker-client.stub-CJlmpAgJ.js +190 -0
  5. package/dist/components/ExcelViewer.vue.d.ts +170 -19
  6. package/dist/components/ExportProgressOverlay.vue.d.ts +11 -0
  7. package/dist/components/FilterPopup.vue.d.ts +4 -4
  8. package/dist/components/ViewerToolbar.vue.d.ts +2 -0
  9. package/dist/composables/useExcelDocument.d.ts +1 -0
  10. package/dist/core/edit/clipboard-html.d.ts +24 -0
  11. package/dist/core/edit/commands.d.ts +45 -1
  12. package/dist/core/edit/context-menu.d.ts +19 -0
  13. package/dist/core/edit/edit-controller.d.ts +70 -2
  14. package/dist/core/edit/permissions.d.ts +41 -2
  15. package/dist/core/edit/types.d.ts +62 -0
  16. package/dist/core/export/abort.d.ts +21 -0
  17. package/dist/core/export/exporter.d.ts +2 -1
  18. package/dist/core/export/types.d.ts +8 -0
  19. package/dist/core/export/wps-cellimages.d.ts +6 -0
  20. package/dist/core/export/xlsx-writer.d.ts +9 -0
  21. package/dist/core/format/color.d.ts +5 -0
  22. package/dist/core/format/number-format.d.ts +3 -0
  23. package/dist/core/layout/autofit.d.ts +3 -0
  24. package/dist/core/layout/grid-metrics.d.ts +14 -2
  25. package/dist/core/loader-json.d.ts +23 -0
  26. package/dist/core/model/clone.d.ts +3 -4
  27. package/dist/core/model/inspect.d.ts +43 -0
  28. package/dist/core/model/mutations.d.ts +16 -1
  29. package/dist/core/model/types.d.ts +44 -2
  30. package/dist/core/parser/cell-image-parser.d.ts +9 -0
  31. package/dist/core/parser/row-meta-parser.d.ts +3 -0
  32. package/dist/core/plugin.d.ts +144 -6
  33. package/dist/core/progress.d.ts +23 -0
  34. package/dist/core/render/canvas-renderer.d.ts +56 -2
  35. package/dist/core/render/conditional.d.ts +7 -0
  36. package/dist/core/template/style-overlay.d.ts +9 -0
  37. package/dist/core/viewer/controller.d.ts +209 -6
  38. package/dist/core/viewer/lightbox-host.d.ts +16 -0
  39. package/dist/core.js +1 -1
  40. package/dist/index.js +1169 -821
  41. package/dist/react/ExcelViewer.d.ts +134 -3
  42. package/dist/react/ExportProgressOverlay.d.ts +6 -0
  43. package/dist/react/use-excel-document.d.ts +2 -0
  44. package/dist/react.js +718 -281
  45. package/dist/style.css +1 -1
  46. package/package.json +1 -1
  47. package/dist/chunks/plugin-overlay-Cfnn9EOi.js +0 -7144
  48. package/dist/chunks/worker-client.stub-BQVZfaLd.js +0 -7
@@ -1,8 +1,12 @@
1
1
  import { CSSProperties } from 'react';
2
2
  import { CellModel, CellStyleFn, CellStyleOverride, ImageAnchor, MergeRange, TransformModelFn, WorkbookModel } from '../core/model/types';
3
+ import { EditableTarget } from '../core/edit/types';
3
4
  import { FormulaEngineFactory } from '../core/formula/engine';
4
5
  import { CellChangePayload, DimChangePayload, DirtyChangePayload, ImageChangePayload, StructChangePayload } from '../core/edit/edit-controller';
5
6
  import { CellSnapshot } from '../core/model/snapshot';
7
+ import { CellInspection } from '../core/model/inspect';
8
+ import { JsonInput, JsonLoadOptions } from '../core/loader-json';
9
+ import { ExportProgress } from '../core/progress';
6
10
  import { CellValue, getCellValue, getSheetData, getRangeData, sheetToJSON, ReadOptions, SheetToJSONOptions } from '../core/model/data-access';
7
11
  import { EditorResolver } from '../core/edit/editor-context';
8
12
  import { ViewerTheme } from '../core/render/theme';
@@ -10,15 +14,60 @@ import { ExcelSource } from '../core/loader';
10
14
  import { ImageExportOptions, PdfExportOptions, PrintOptions } from '../core/export';
11
15
  import { XlsxExportOptions } from '../core/export/xlsx-writer';
12
16
  import { Cell } from '../core/viewer/controller';
13
- import { ExcelPlugin } from '../core/plugin';
17
+ import { ContextMenuBeforePayload, ContextMenuShowPayload, ContextMenuTransform, ExcelPlugin, MenuItem, PermissionDeniedPayload } from '../core/plugin';
14
18
  export interface ExcelViewerProps {
15
19
  src?: ExcelSource;
20
+ /**
21
+ * 直接喂 WorkbookModel 或 JsonInput(P3):绕过 parser。优先级 workbook > src。
22
+ * WorkbookModel 直用;JsonInput(二维数组 / 对象数组 / `{sheets:[...]}`)走 jsonToWorkbook。
23
+ */
24
+ workbook?: WorkbookModel | JsonInput;
25
+ /** JSON 直渲选项(workbook = JsonInput 时生效) */
26
+ jsonOptions?: JsonLoadOptions;
27
+ /**
28
+ * 渲染模板(P3 重设计 2026-06-08):一份 .xlsx 当**样式捐赠者** —— 模板的 styling
29
+ * (styles / merges / 列宽 / 行高 / freeze / theme)套到无格式数据源上,模板的 raw 文字 / 占位符 /
30
+ * 图 / 图表 / 条件格式 全部丢弃。
31
+ *
32
+ * ⚠️ **只在数据源是 `workbook`(JSON / 模型)时生效**;`src`(.xlsx)数据源自带格式,
33
+ * 给 `templateFile` 会被忽略并 console.warn.
34
+ */
35
+ templateFile?: ExcelSource;
36
+ /** 模板显示名(标题栏 `· 模板: xxx` 后缀);不给则取运行时 File.name */
37
+ templateName?: string;
38
+ /**
39
+ * 内置导出进度遮罩(P1.5):默认 `true` —— 调 `viewer.downloadPdf/exportImage/...` /
40
+ * 选区图片批量转换 时,壳自动建 AbortController + 接 onProgress → 显示居中模态 + 取消。
41
+ * `false` 关闭(走纯回调);`renderExportProgress` 自渲染(覆盖内置 UI)。
42
+ */
43
+ exportProgress?: boolean;
44
+ /** 完全自渲染遮罩:返回任意 ReactNode 替代内置 UI。`exportProgress=false` 时此项也不渲染。 */
45
+ renderExportProgress?: (ctx: {
46
+ state: ExportProgress | null;
47
+ busy: boolean;
48
+ cancel: () => void;
49
+ }) => React.ReactNode;
50
+ /**
51
+ * 右键菜单(Plan C):
52
+ * - `false` → 不弹内置菜单(`onBeforeContextMenu` / `onContextMenuShow` 仍触发,壳可自渲染)
53
+ * - 函数 `(ctx, items) => MenuItem[] | undefined` → 在内置 items 上加 / 减 / 重排;返 undefined 不动
54
+ * - 不传(默认)→ editable 时显示内置菜单,非 editable 走浏览器默认
55
+ */
56
+ contextMenu?: boolean | ContextMenuTransform;
57
+ /** 右键菜单触发前:`payload.preventDefault()` 阻止内置菜单(自渲染替代) */
58
+ onBeforeContextMenu?: (payload: ContextMenuBeforePayload) => void;
59
+ /** 右键菜单展示通知:无论内置是否弹都触发,供自渲染或事件流串到业务 */
60
+ onContextMenuShow?: (payload: ContextMenuShowPayload) => void;
16
61
  fileName?: string;
17
62
  theme?: Partial<ViewerTheme>;
18
63
  /** 单击超链接是否自动打开(默认 true) */
19
64
  openLinks?: boolean;
20
65
  transformModel?: TransformModelFn;
21
66
  cellStyle?: CellStyleFn;
67
+ /** WPS 单元格内嵌图(DISPIMG)贴合方式:contain 等比(默认,与 WPS 渲染一致)/ fill 拉伸铺满 / cover 等比裁剪 */
68
+ cellImageFit?: 'fill' | 'contain' | 'cover';
69
+ /** 图片点击放大灯箱(默认 true):只读模式单击图放大、编辑模式右键「查看大图」;false 关闭 */
70
+ imageLightbox?: boolean;
22
71
  /** 插件(与 Vue 通用):theme/transformModel/cellStyle/events/overlay/setup 全跨框架可用 */
23
72
  plugins?: ExcelPlugin[];
24
73
  /** 编辑总开关:默认 false = 只读(行为不变)。开启后才能进入编辑(E0:闸门) */
@@ -30,6 +79,23 @@ export interface ExcelViewerProps {
30
79
  }) => boolean | void;
31
80
  /** 只读区域(0-based 闭区间);命中即只读 */
32
81
  readOnlyRanges?: MergeRange[];
82
+ /**
83
+ * **可编辑白名单**(2026-06-08 新增):设了就是白名单语义,只命中**任一** target 的格才可编辑.
84
+ * 4 种 target 形状自动识别:`{row,col}` 单格 / `{row}` 整行 / `{col}` 整列 / `MergeRange` 矩形.
85
+ * 单值或数组都支持;允许**不相邻**多 target. `undefined`=默认全可编辑(老行为),`[]`=全只读.
86
+ */
87
+ editableTargets?: EditableTarget | EditableTarget[];
88
+ /**
89
+ * **严格尺寸闸门**(Phase B, 2026-06-08) —— 默认 `false`: 尺寸 API 仅受全局 editable 控制. 设 `true` +
90
+ * editableTargets 启用了 → 该列/行至少有 1 格在白名单内才能改尺寸.
91
+ */
92
+ strictDimensions?: boolean;
93
+ /**
94
+ * **只读单元格视觉钩子** (Phase C, 2026-06-08):
95
+ * `false`(默认) 无视觉差异;`true` 内置浅灰底 `#f5f7fa`;`CellStyleOverride` 固定样式;`CellStyleFn` 按格自定义.
96
+ * 跟 editableTargets 配合 → 白名单外的格自动套此视觉.
97
+ */
98
+ readOnlyCellStyle?: boolean | CellStyleOverride | CellStyleFn;
33
99
  /** 自定义单元格编辑器(按格返回工厂;覆盖插件 editor)。需 editable 开启 */
34
100
  editor?: EditorResolver;
35
101
  /** 公式重算(E4):默认 false 沿用缓存值。开启后编辑公式/被引用格 → 依赖格自动重算。需 editable */
@@ -74,6 +140,8 @@ export interface ExcelViewerProps {
74
140
  onImageChange?: (p: ImageChangePayload) => void;
75
141
  /** 行列结构变更(增删行列) */
76
142
  onStructChange?: (p: StructChangePayload) => void;
143
+ /** 权限拒绝(Phase A, 2026-06-08):粘贴/合并/图片落点等命中只读 → 默认 skip + 此事件通知 */
144
+ onPermissionDenied?: (p: PermissionDeniedPayload) => void;
77
145
  }
78
146
  /** 命令式句柄(与 Vue ref / ViewerApi 对齐) */
79
147
  export interface ExcelViewerHandle {
@@ -97,15 +165,69 @@ export interface ExcelViewerHandle {
97
165
  } | null;
98
166
  redraw: () => void;
99
167
  isCellEditable: (row: number, col: number) => boolean;
168
+ setEditableTargets: (targets: EditableTarget | EditableTarget[] | undefined) => void;
169
+ getEditableTargets: () => EditableTarget | EditableTarget[] | undefined;
100
170
  editCell: (row: number, col: number, value: CellValue) => boolean;
101
171
  editRange: (range: MergeRange, values: CellValue[][]) => boolean;
102
172
  clearRange: (range: MergeRange) => boolean;
103
173
  setStyle: (range: MergeRange, patch: CellStyleOverride) => boolean;
174
+ getActiveFillColor: () => string;
175
+ getActiveFontColor: () => string;
176
+ setSelectionFill: (color: string | null) => boolean;
177
+ setSelectionFontColor: (color: string) => boolean;
178
+ getSelectionWrapState: () => 'all' | 'none' | 'mixed';
179
+ toggleWrapTextOnSelection: () => boolean;
180
+ mergeCells: (range: MergeRange) => boolean;
181
+ unmergeCells: (range: MergeRange) => boolean;
182
+ pasteText: (text: string, at?: {
183
+ row: number;
184
+ col: number;
185
+ }) => boolean;
186
+ pasteRichHtml: (html: string, at?: {
187
+ row: number;
188
+ col: number;
189
+ }) => boolean;
190
+ pasteImageBlob: (blob: Blob, at?: {
191
+ row: number;
192
+ col: number;
193
+ }) => Promise<boolean>;
104
194
  getImages: () => ImageAnchor[];
105
195
  addImage: (anchor: ImageAnchor) => number;
106
196
  removeImage: (index: number) => boolean;
107
197
  moveImage: (index: number, dxPx: number, dyPx: number) => boolean;
108
198
  resizeImage: (index: number, widthPx: number, heightPx: number) => boolean;
199
+ getCellImages: () => {
200
+ id: string;
201
+ src: string;
202
+ mime?: string;
203
+ }[];
204
+ getCellImageAt: (row: number, col: number) => {
205
+ id: string;
206
+ src: string;
207
+ mime?: string;
208
+ } | null;
209
+ openImageLightbox: (src: string, fileName?: string, mime?: string) => void;
210
+ /** 活动格在公式栏里的可编辑字符串(公式→=…,数值→原始数字串) */
211
+ getCellEditString: () => string;
212
+ /** 活动格此刻是否可经公式栏编辑(editable + 非只读) */
213
+ canEditActiveCell: () => boolean;
214
+ /** 经公式栏提交活动格的值(move='down' 提交后下移) */
215
+ commitActiveCellValue: (value: string, move?: 'down') => boolean;
216
+ setCellImageFit: (fit: 'fill' | 'contain' | 'cover') => void;
217
+ convertImageToCell: (imageIndex: number, row: number, col: number) => boolean;
218
+ convertImageToCellAuto: (imageIndex: number) => boolean;
219
+ convertAllImagesToCells: (col?: number) => number;
220
+ convertImagesInRangeToCell: (range: MergeRange) => Promise<number>;
221
+ convertCellImagesInRangeToFloat: (range: MergeRange, size?: {
222
+ width: number;
223
+ height: number;
224
+ }) => Promise<number>;
225
+ openContextMenu: (x: number, y: number, items?: MenuItem[]) => void;
226
+ closeContextMenu: () => void;
227
+ convertCellImageToFloat: (row: number, col: number, size?: {
228
+ width: number;
229
+ height: number;
230
+ }) => boolean;
109
231
  insertRows: (at: number, count?: number) => boolean;
110
232
  deleteRows: (at: number, count?: number) => boolean;
111
233
  insertCols: (at: number, count?: number) => boolean;
@@ -119,12 +241,21 @@ export interface ExcelViewerHandle {
119
241
  col: number;
120
242
  } | null;
121
243
  getCellSnapshot: (row: number, col: number) => CellSnapshot | null;
244
+ inspectCell: (row: number, col: number) => CellInspection | null;
122
245
  beginEdit: (row: number, col: number) => boolean;
123
246
  cancelEdit: () => void;
124
247
  isEditing: () => boolean;
125
- setColumnWidth: (col: number, width: number) => boolean;
126
- setRowHeight: (row: number, height: number) => boolean;
248
+ setColumnWidth: (target: import('../core/edit/types').DimTarget, width: number) => number;
249
+ setRowHeight: (target: import('../core/edit/types').DimTarget, height: number) => number;
250
+ autoFitColumns: (target?: import('../core/edit/types').DimTarget) => number;
251
+ autoFitRows: (target?: import('../core/edit/types').DimTarget) => number;
252
+ resetColumnWidth: (target: import('../core/edit/types').DimTarget) => number;
253
+ resetRowHeight: (target: import('../core/edit/types').DimTarget) => number;
127
254
  isRecalcReady: () => boolean;
255
+ getVirtualExtent: () => {
256
+ rows: number;
257
+ cols: number;
258
+ };
128
259
  isDirty: () => boolean;
129
260
  resetToOriginal: () => boolean;
130
261
  exportImage: (opts?: ImageExportOptions) => Promise<Blob>;
@@ -0,0 +1,6 @@
1
+ import { ExportProgress } from '../core/progress';
2
+ export declare function ExportProgressOverlay({ state, busy, onCancel, }: {
3
+ state: ExportProgress | null;
4
+ busy: boolean;
5
+ onCancel: () => void;
6
+ }): import("react").JSX.Element | null;
@@ -7,6 +7,8 @@ export interface ExcelDocument {
7
7
  workbook: WorkbookModel | null;
8
8
  progress: ParseProgress | null;
9
9
  load: (src: ExcelSource, transform?: TransformModelFn) => Promise<void>;
10
+ /** 直接喂模型(JSON 直渲 / 模板已应用),跳过 parser */
11
+ loadModel: (model: WorkbookModel, transform?: TransformModelFn) => void;
10
12
  /** 原始字节(高保真 overlay 导出用) */
11
13
  sourceBuffer: ArrayBuffer | null;
12
14
  }