docx-vue-viewer 0.5.0 → 1.0.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/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import * as vue from 'vue';
2
- import { PropType } from 'vue';
2
+ import { PropType, MaybeRefOrGetter } from 'vue';
3
3
  import { DocumentModel } from 'docx-core';
4
4
  export * from 'docx-core';
5
- import { EditorThemeMode, RibbonActionInput, RibbonAddInTab, DocxEditorElement, EditorLocaleInput, PageChangeDetail, RibbonAddInCommandDetail } from 'ooxml-ui/docx';
5
+ import { EditorThemeMode, RibbonActionInput, RibbonAddInTab, DocxCollaborationOptions, EditorLocaleInput, PageChangeDetail, RibbonAddInCommandDetail, DocxCollaborationState, SurfaceHostActions, DocxEditorElement, WordListState, WordAlignment, WordListChoice, WordNavigationProps, WordStatusProps, WordToolbarProps } from 'ooxml-ui/docx';
6
6
  export * from 'ooxml-ui/docx';
7
+ export { WordNavigationProps, WordStatusProps, WordToolbarProps } from 'ooxml-ui/docx';
7
8
  export { DocumentFormat, detectDocumentFormat, loadDocument } from 'ooxml-core/docx/load';
8
9
 
9
10
  declare const WordEditor: vue.DefineComponent<vue.ExtractPropTypes<{
@@ -18,9 +19,10 @@ declare const WordEditor: vue.DefineComponent<vue.ExtractPropTypes<{
18
19
  };
19
20
  hiddenActions: PropType<readonly RibbonActionInput[]>;
20
21
  ribbonAddIns: PropType<readonly RibbonAddInTab[]>;
22
+ collaboration: PropType<DocxCollaborationOptions | null>;
21
23
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
22
24
  [key: string]: any;
23
- }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("document-change" | "document-error" | "page-change" | "dirty-change" | "office-ribbon-add-in")[], "document-change" | "document-error" | "page-change" | "dirty-change" | "office-ribbon-add-in", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
25
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("document-change" | "document-error" | "page-change" | "dirty-change" | "collaboration-change" | "office-ribbon-add-in")[], "document-change" | "document-error" | "page-change" | "dirty-change" | "collaboration-change" | "office-ribbon-add-in", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
24
26
  documentModel: PropType<DocumentModel>;
25
27
  readOnly: BooleanConstructor;
26
28
  locale: StringConstructor;
@@ -32,11 +34,13 @@ declare const WordEditor: vue.DefineComponent<vue.ExtractPropTypes<{
32
34
  };
33
35
  hiddenActions: PropType<readonly RibbonActionInput[]>;
34
36
  ribbonAddIns: PropType<readonly RibbonAddInTab[]>;
37
+ collaboration: PropType<DocxCollaborationOptions | null>;
35
38
  }>> & Readonly<{
36
39
  "onDocument-change"?: (...args: any[]) => any;
37
40
  "onDocument-error"?: (...args: any[]) => any;
38
41
  "onPage-change"?: (...args: any[]) => any;
39
42
  "onDirty-change"?: (...args: any[]) => any;
43
+ "onCollaboration-change"?: (...args: any[]) => any;
40
44
  "onOffice-ribbon-add-in"?: (...args: any[]) => any;
41
45
  }>, {
42
46
  readOnly: boolean;
@@ -60,6 +64,11 @@ interface EditorProps {
60
64
  hiddenActions?: readonly RibbonActionInput[] | undefined;
61
65
  /** Tabs the host adds after Word's own, as an Office add-in does. */
62
66
  ribbonAddIns?: readonly RibbonAddInTab[] | undefined;
67
+ /**
68
+ * Shares the loaded document in a room while set; `null` leaves (see `DocxCollaborationOptions`).
69
+ * Forwarded only when the object changes, so pass a stable object, not a new literal per render.
70
+ */
71
+ collaboration?: DocxCollaborationOptions | null | undefined;
63
72
  }
64
73
  /** Editor callbacks; each is the framework-neutral form of one entry in `EDITOR_EVENT_NAMES`. */
65
74
  interface EditorEventOptions {
@@ -69,6 +78,8 @@ interface EditorEventOptions {
69
78
  onDirtyChange?: ((dirty: boolean) => void) | undefined;
70
79
  /** A command of a host tab (`ribbonAddIns`) was chosen. */
71
80
  onRibbonAddIn?: ((detail: RibbonAddInCommandDetail) => void) | undefined;
81
+ /** Sharing started, stopped, reconnected or the people in the room changed. */
82
+ onCollaborationChange?: ((state: DocxCollaborationState) => void) | undefined;
72
83
  }
73
84
  interface EditorOptions extends EditorProps, EditorEventOptions {
74
85
  }
@@ -86,6 +97,221 @@ interface EditorBinding extends EditorHandle {
86
97
  update(options: EditorOptions): void;
87
98
  destroy(): void;
88
99
  }
100
+ /** Ribbon and chrome options that a surface, which draws none, would silently ignore. */
101
+ type RibbonOnlyOption = 'showToolbar' | 'showThumbnails' | 'hiddenActions' | 'ribbonAddIns' | 'onRibbonAddIn';
102
+ /**
103
+ * Framework-neutral composition API, shared by every adapter. Choose before mount. Ribbon-only
104
+ * options are not part of it. The `onOpen...` callbacks are the host's own dialogs: a workflow
105
+ * without its callback reports as not enabled.
106
+ */
107
+ interface SurfaceOptions extends Omit<EditorOptions, RibbonOnlyOption>, SurfaceHostActions {
108
+ canEdit?: boolean | undefined;
109
+ }
110
+ declare function mountEditorSurface(host: HTMLElement, initial?: SurfaceOptions): EditorBinding & {
111
+ update: (options: SurfaceOptions) => void;
112
+ getToolbarProps: () => {
113
+ hostWorkflows: {
114
+ hyperlink: boolean;
115
+ findReplace: boolean;
116
+ picture: boolean;
117
+ };
118
+ canInsertLink: boolean;
119
+ canFindReplace: boolean;
120
+ canInsertPicture: boolean;
121
+ openHyperlinkDialog: () => boolean;
122
+ openFindReplace: () => boolean;
123
+ openImagePicker: () => boolean;
124
+ labels: {
125
+ [k: string]: string;
126
+ };
127
+ canEdit: boolean;
128
+ list: WordListState;
129
+ selection: {
130
+ from: number;
131
+ to: number;
132
+ } | null;
133
+ bold: boolean | null;
134
+ italic: boolean | null;
135
+ underline: boolean | null;
136
+ fontFamily: string | null;
137
+ fontSize: number | null;
138
+ alignment: WordAlignment | null;
139
+ canUndo: boolean;
140
+ canRedo: boolean;
141
+ onBold: () => boolean;
142
+ onItalic: () => boolean;
143
+ onUnderline: () => boolean;
144
+ onFontFamilyChange: (family: string) => boolean;
145
+ onFontSizeChange: (size: number) => boolean;
146
+ onAlignmentChange: (alignment: WordAlignment) => boolean;
147
+ onListChange: (kind: WordListChoice | "remove") => boolean;
148
+ onUndo: () => boolean;
149
+ onRedo: () => boolean;
150
+ };
151
+ getNavigationProps: () => {
152
+ labels: Record<string, string>;
153
+ viewMode: "draft" | "print";
154
+ pagesAvailable: boolean;
155
+ page: number;
156
+ pageCount: number;
157
+ pageText: string;
158
+ canGoPrevious: boolean;
159
+ canGoNext: boolean;
160
+ onGoToPage: (target: number) => boolean;
161
+ onPreviousPage: () => boolean;
162
+ onNextPage: () => boolean;
163
+ onViewModeChange: (mode: "draft" | "print") => boolean;
164
+ };
165
+ getStatusProps: () => {
166
+ labels: Record<string, string>;
167
+ words: number;
168
+ wordText: string;
169
+ zoom: number;
170
+ minZoom: number;
171
+ maxZoom: number;
172
+ onZoomChange: (percent: number) => boolean;
173
+ onZoomIn: () => boolean;
174
+ onZoomOut: () => boolean;
175
+ };
176
+ subscribe: (listener: () => void) => () => void;
177
+ };
178
+
179
+ interface BuildingBlockOptions extends SurfaceOptions {
180
+ bytes?: Uint8Array | ArrayBuffer | undefined;
181
+ }
182
+ interface CanvasProps {
183
+ mount: (host: HTMLElement | null) => void;
184
+ className?: string | undefined;
185
+ }
186
+
187
+ declare function useViewerBuildingBlocks(options?: MaybeRefOrGetter<BuildingBlockOptions>): {
188
+ canvasProps: {
189
+ mount: (host: HTMLElement | null) => void;
190
+ };
191
+ handle: EditorHandle;
192
+ toolbarProps: vue.ComputedRef<{
193
+ hostWorkflows: {
194
+ hyperlink: boolean;
195
+ findReplace: boolean;
196
+ picture: boolean;
197
+ };
198
+ canInsertLink: boolean;
199
+ canFindReplace: boolean;
200
+ canInsertPicture: boolean;
201
+ openHyperlinkDialog: () => boolean;
202
+ openFindReplace: () => boolean;
203
+ openImagePicker: () => boolean;
204
+ labels: {
205
+ [k: string]: string;
206
+ };
207
+ canEdit: boolean;
208
+ list: WordListState;
209
+ selection: {
210
+ from: number;
211
+ to: number;
212
+ } | null;
213
+ bold: boolean | null;
214
+ italic: boolean | null;
215
+ underline: boolean | null;
216
+ fontFamily: string | null;
217
+ fontSize: number | null;
218
+ alignment: WordAlignment | null;
219
+ canUndo: boolean;
220
+ canRedo: boolean;
221
+ onBold: () => boolean;
222
+ onItalic: () => boolean;
223
+ onUnderline: () => boolean;
224
+ onFontFamilyChange: (family: string) => boolean;
225
+ onFontSizeChange: (size: number) => boolean;
226
+ onAlignmentChange: (alignment: WordAlignment) => boolean;
227
+ onListChange: (kind: WordListChoice | "remove") => boolean;
228
+ onUndo: () => boolean;
229
+ onRedo: () => boolean;
230
+ } | null>;
231
+ navigationProps: vue.ComputedRef<{
232
+ labels: Record<string, string>;
233
+ viewMode: "draft" | "print";
234
+ pagesAvailable: boolean;
235
+ page: number;
236
+ pageCount: number;
237
+ pageText: string;
238
+ canGoPrevious: boolean;
239
+ canGoNext: boolean;
240
+ onGoToPage: (target: number) => boolean;
241
+ onPreviousPage: () => boolean;
242
+ onNextPage: () => boolean;
243
+ onViewModeChange: (mode: "draft" | "print") => boolean;
244
+ } | null>;
245
+ statusProps: vue.ComputedRef<{
246
+ labels: Record<string, string>;
247
+ words: number;
248
+ wordText: string;
249
+ zoom: number;
250
+ minZoom: number;
251
+ maxZoom: number;
252
+ onZoomChange: (percent: number) => boolean;
253
+ onZoomIn: () => boolean;
254
+ onZoomOut: () => boolean;
255
+ } | null>;
256
+ loading: vue.ComputedRef<boolean>;
257
+ error: vue.ComputedRef<Error | null>;
258
+ mode: vue.ComputedRef<"view" | "edit">;
259
+ };
260
+ declare const DocumentCanvas: vue.DefineComponent<vue.ExtractPropTypes<{
261
+ mount: {
262
+ type: PropType<CanvasProps["mount"]>;
263
+ required: true;
264
+ };
265
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
266
+ [key: string]: any;
267
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
268
+ mount: {
269
+ type: PropType<CanvasProps["mount"]>;
270
+ required: true;
271
+ };
272
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
273
+ /** Optional controls: history, font, formatting, alignment, lists and enabled host workflows. */
274
+ declare const Toolbar: vue.DefineComponent<vue.ExtractPropTypes<{
275
+ toolbarProps: {
276
+ type: PropType<WordToolbarProps>;
277
+ required: true;
278
+ };
279
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
280
+ [key: string]: any;
281
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
282
+ toolbarProps: {
283
+ type: PropType<WordToolbarProps>;
284
+ required: true;
285
+ };
286
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
287
+ /** Optional page navigation for `navigationProps`. Pages exist in Print Layout only. */
288
+ declare const PageNavigation: vue.DefineComponent<vue.ExtractPropTypes<{
289
+ navigationProps: {
290
+ type: PropType<WordNavigationProps>;
291
+ required: true;
292
+ };
293
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
294
+ [key: string]: any;
295
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
296
+ navigationProps: {
297
+ type: PropType<WordNavigationProps>;
298
+ required: true;
299
+ };
300
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
301
+ /** Optional word count and zoom for `statusProps`. */
302
+ declare const StatusBar: vue.DefineComponent<vue.ExtractPropTypes<{
303
+ statusProps: {
304
+ type: PropType<WordStatusProps>;
305
+ required: true;
306
+ };
307
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
308
+ [key: string]: any;
309
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
310
+ statusProps: {
311
+ type: PropType<WordStatusProps>;
312
+ required: true;
313
+ };
314
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
89
315
 
90
- export { WordEditor };
91
- export type { EditorBinding, EditorEventOptions, EditorHandle, EditorOptions, EditorProps };
316
+ export { DocumentCanvas, PageNavigation, StatusBar, Toolbar, WordEditor, mountEditorSurface, useViewerBuildingBlocks };
317
+ export type { BuildingBlockOptions, CanvasProps, EditorBinding, EditorEventOptions, EditorHandle, EditorOptions, EditorProps, SurfaceOptions };
package/dist/index.js CHANGED
@@ -1,27 +1,28 @@
1
- import { defineComponent as e, h as t, onBeforeUnmount as n, onMounted as r, ref as i, watch as a } from "vue";
2
- import { detectDocumentFormat as o, loadDocument as s } from "ooxml-core/docx/load";
1
+ import { computed as e, defineComponent as t, h as n, onBeforeUnmount as r, onMounted as i, onScopeDispose as a, ref as o, shallowRef as s, toValue as c, watch as l, watchEffect as u } from "vue";
2
+ import { detectDocumentFormat as d, loadDocument as f } from "ooxml-core/docx/load";
3
+ import * as p from "ooxml-ui/theme";
3
4
  export * from "ooxml-ui/docx";
4
5
  export * from "docx-core";
5
6
  //#region \0rolldown/runtime.js
6
- var c = Object.defineProperty, l = Object.getOwnPropertyDescriptor, u = Object.getOwnPropertyNames, d = Object.prototype.hasOwnProperty, f = (e, t) => {
7
+ var m = Object.defineProperty, h = Object.getOwnPropertyDescriptor, g = Object.getOwnPropertyNames, _ = Object.prototype.hasOwnProperty, v = (e, t) => {
7
8
  let n = {};
8
- for (var r in e) c(n, r, {
9
+ for (var r in e) m(n, r, {
9
10
  get: e[r],
10
11
  enumerable: !0
11
12
  });
12
- return t || c(n, Symbol.toStringTag, { value: "Module" }), n;
13
- }, p = (e, t, n, r) => {
14
- if (t && typeof t == "object" || typeof t == "function") for (var i = u(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !d.call(e, s) && s !== n && c(e, s, {
13
+ return t || m(n, Symbol.toStringTag, { value: "Module" }), n;
14
+ }, y = (e, t, n, r) => {
15
+ if (t && typeof t == "object" || typeof t == "function") for (var i = g(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !_.call(e, s) && s !== n && m(e, s, {
15
16
  get: ((e) => t[e]).bind(null, s),
16
- enumerable: !(r = l(t, s)) || r.enumerable
17
+ enumerable: !(r = h(t, s)) || r.enumerable
17
18
  });
18
19
  return e;
19
- }, m = (e, t, n) => (p(e, t, "default"), n && p(n, t, "default")), h = /* @__PURE__ */ f({});
20
- import * as g from "ooxml-ui/docx";
21
- m(h, g);
20
+ }, b = (e, t, n) => (y(e, t, "default"), n && y(n, t, "default")), x = /* @__PURE__ */ v({});
21
+ import * as S from "ooxml-ui/docx";
22
+ b(x, S);
22
23
  //#endregion
23
24
  //#region packages/bindings/src/index.ts
24
- var _ = [
25
+ var C = [
25
26
  "documentModel",
26
27
  "readOnly",
27
28
  "locale",
@@ -29,61 +30,89 @@ var _ = [
29
30
  "showThumbnails",
30
31
  "showToolbar",
31
32
  "hiddenActions",
32
- "ribbonAddIns"
33
- ], v = [
33
+ "ribbonAddIns",
34
+ "collaboration"
35
+ ], w = [
34
36
  "document-change",
35
37
  "document-error",
36
38
  "page-change",
37
39
  "dirty-change",
38
- "office-ribbon-add-in"
40
+ "office-ribbon-add-in",
41
+ "collaboration-change"
39
42
  ];
40
- function y(e, t) {
43
+ function T(e, t) {
41
44
  return e.length === t.length && e.every((e, n) => e === t[n]);
42
45
  }
43
- function b(e, t, n) {
46
+ function E(e, t, n) {
44
47
  e[n] = t[n];
45
48
  }
46
- function x(e) {
49
+ function D(e) {
47
50
  let t = {};
48
- for (let n of _) b(t, e, n);
51
+ for (let n of C) E(t, e, n);
49
52
  return t;
50
53
  }
51
- function S(e) {
54
+ function O(e) {
52
55
  return {
53
56
  onDocumentChange: e["document-change"],
54
57
  onDocumentError: e["document-error"],
55
58
  onPageChange: e["page-change"],
56
59
  onDirtyChange: e["dirty-change"],
57
- onRibbonAddIn: e["office-ribbon-add-in"]
60
+ onRibbonAddIn: e["office-ribbon-add-in"],
61
+ onCollaborationChange: e["collaboration-change"]
58
62
  };
59
63
  }
60
- function C(e, t = {}) {
61
- (0, h.registerDocxEditor)();
62
- let n = e.ownerDocument.createElement("docx-editor"), r = {}, i, a, o, s = !1, c = (e) => {
63
- a = e.detail, r.onDocumentChange?.(a);
64
- }, l = (e) => r.onDocumentError?.(e.detail), u = (e) => r.onPageChange?.(e.detail), d = (e) => r.onDirtyChange?.(e.detail), f = (e) => r.onRibbonAddIn?.(e.detail);
65
- n.addEventListener("document-change", c), n.addEventListener("document-error", l), n.addEventListener("page-change", u), n.addEventListener("dirty-change", d), n.addEventListener("office-ribbon-add-in", f);
66
- let p = {
67
- element: n,
64
+ function k(e, t = {}, n = !1) {
65
+ (0, x.registerDocxEditor)();
66
+ let r = e.ownerDocument.createElement("docx-editor");
67
+ if (n && typeof r.getToolbarProps != "function") throw Error("Update ooxml-ui to use editor building blocks.");
68
+ r.surfaceOnly = n;
69
+ let i = {}, a, o, s, c = null, l = !1, u = (e) => {
70
+ o = e.detail, i.onDocumentChange?.(o);
71
+ }, d = (e) => i.onDocumentError?.(e.detail), f = (e) => i.onPageChange?.(e.detail), p = (e) => i.onDirtyChange?.(e.detail), m = (e) => i.onRibbonAddIn?.(e.detail), h = (e) => i.onCollaborationChange?.(e.detail);
72
+ r.addEventListener("document-change", u), r.addEventListener("document-error", d), r.addEventListener("page-change", f), r.addEventListener("dirty-change", p), r.addEventListener("office-ribbon-add-in", m), r.addEventListener("collaboration-change", h);
73
+ let g = {
74
+ element: r,
68
75
  update(e) {
69
- s || (r = e, n.locale = e.locale ?? "en", n.readOnly = e.readOnly ?? !1, n.theme = e.theme ?? "auto", n.showThumbnails = e.showThumbnails ?? !1, n.showToolbar = e.showToolbar ?? !0, y(n.hiddenActions, (0, h.normalizeRibbonActions)(e.hiddenActions ?? []).ids) || (n.hiddenActions = e.hiddenActions ?? []), e.ribbonAddIns !== o && (n.ribbonAddIns = e.ribbonAddIns ?? []), o = e.ribbonAddIns, e.documentModel && e.documentModel !== i && e.documentModel !== a && (n.documentModel = e.documentModel), i = e.documentModel);
76
+ l || (i = e, r.locale = e.locale ?? "en", r.readOnly = e.readOnly ?? !1, r.theme = e.theme ?? "auto", r.showThumbnails = e.showThumbnails ?? !1, r.showToolbar = e.showToolbar ?? !0, T(r.hiddenActions, (0, x.normalizeRibbonActions)(e.hiddenActions ?? []).ids) || (r.hiddenActions = e.hiddenActions ?? []), e.ribbonAddIns !== s && (r.ribbonAddIns = e.ribbonAddIns ?? []), s = e.ribbonAddIns, (e.collaboration ?? null) !== c && (c = e.collaboration ?? null, r.collaboration = c), e.documentModel && e.documentModel !== a && e.documentModel !== o && (r.documentModel = e.documentModel), a = e.documentModel);
70
77
  },
71
- load: (e) => n.load(e),
72
- save: () => n.save(),
73
- download: (e) => n.download(e),
74
- markClean: () => n.markClean(),
78
+ load: (e) => r.load(e),
79
+ save: () => r.save(),
80
+ download: (e) => r.download(e),
81
+ markClean: () => r.markClean(),
75
82
  get dirty() {
76
- return n.dirty;
83
+ return r.dirty;
77
84
  },
78
85
  destroy() {
79
- s || (s = !0, n.removeEventListener("document-change", c), n.removeEventListener("document-error", l), n.removeEventListener("page-change", u), n.removeEventListener("dirty-change", d), n.removeEventListener("office-ribbon-add-in", f), n.remove());
86
+ l || (l = !0, r.removeEventListener("document-change", u), r.removeEventListener("document-error", d), r.removeEventListener("page-change", f), r.removeEventListener("dirty-change", p), r.removeEventListener("office-ribbon-add-in", m), c && r.stopCollaboration(), r.removeEventListener("collaboration-change", h), r.remove());
80
87
  }
81
88
  };
82
- return p.update(t), e.append(n), p;
89
+ return g.update(t), e.append(r), g;
90
+ }
91
+ function A(e, t = {}) {
92
+ let n = (e) => ({
93
+ ...e,
94
+ readOnly: e.canEdit !== !0 || e.readOnly === !0
95
+ }), r = (e) => ({
96
+ ...e.onOpenHyperlinkDialog && { onOpenHyperlinkDialog: e.onOpenHyperlinkDialog },
97
+ ...e.onOpenFindReplace && { onOpenFindReplace: e.onOpenFindReplace },
98
+ ...e.onOpenImagePicker && { onOpenImagePicker: e.onOpenImagePicker }
99
+ }), i = k(e, n(t), !0), a = i.update, o = (e) => {
100
+ let t = r(e), n = i.element.surfaceActions;
101
+ [.../* @__PURE__ */ new Set([...Object.keys(n), ...Object.keys(t)])].some((e) => n[e] !== t[e]) && (i.element.surfaceActions = t);
102
+ };
103
+ return o(t), Object.assign(i, {
104
+ update: (e) => {
105
+ a(n(e)), o(e);
106
+ },
107
+ getToolbarProps: () => i.element.getToolbarProps(),
108
+ getNavigationProps: () => i.element.getNavigationProps(),
109
+ getStatusProps: () => i.element.getStatusProps(),
110
+ subscribe: (e) => i.element.subscribeEditorState(e)
111
+ });
83
112
  }
84
113
  //#endregion
85
114
  //#region packages/bindings/src/vue.ts
86
- var w = e({
115
+ var j = t({
87
116
  name: "WordEditor",
88
117
  props: {
89
118
  documentModel: Object,
@@ -96,54 +125,415 @@ var w = e({
96
125
  default: !0
97
126
  },
98
127
  hiddenActions: Array,
99
- ribbonAddIns: Array
128
+ ribbonAddIns: Array,
129
+ collaboration: Object
100
130
  },
101
- emits: [...v],
102
- setup(e, { emit: o, expose: s }) {
103
- let c = i(), l, u = () => ({
104
- ...x(e),
105
- ...S({
106
- "document-change": (e) => o("document-change", e),
107
- "document-error": (e) => o("document-error", e),
108
- "page-change": (e) => o("page-change", e),
109
- "dirty-change": (e) => o("dirty-change", e),
110
- "office-ribbon-add-in": (e) => o("office-ribbon-add-in", e)
131
+ emits: [...w],
132
+ setup(e, { emit: t, expose: a }) {
133
+ let s = o(), c, u = () => ({
134
+ ...D(e),
135
+ ...O({
136
+ "document-change": (e) => t("document-change", e),
137
+ "document-error": (e) => t("document-error", e),
138
+ "page-change": (e) => t("page-change", e),
139
+ "dirty-change": (e) => t("dirty-change", e),
140
+ "office-ribbon-add-in": (e) => t("office-ribbon-add-in", e),
141
+ "collaboration-change": (e) => t("collaboration-change", e)
111
142
  })
112
143
  });
113
- return r(() => {
114
- l = C(c.value, u());
115
- }), a(() => _.map((t) => e[t]), () => l?.update(u())), n(() => l?.destroy()), s({
144
+ return i(() => {
145
+ c = k(s.value, u());
146
+ }), l(() => C.map((t) => e[t]), () => c?.update(u())), r(() => c?.destroy()), a({
116
147
  get element() {
117
- return l?.element;
148
+ return c?.element;
118
149
  },
119
150
  async load(e) {
120
- if (!l) throw Error("Editor is not mounted");
121
- await l.load(e);
151
+ if (!c) throw Error("Editor is not mounted");
152
+ await c.load(e);
122
153
  },
123
154
  async save() {
124
- if (!l) throw Error("Editor is not mounted");
125
- return l.save();
155
+ if (!c) throw Error("Editor is not mounted");
156
+ return c.save();
126
157
  },
127
158
  async download(e) {
128
- if (!l) throw Error("Editor is not mounted");
129
- await l.download(e);
159
+ if (!c) throw Error("Editor is not mounted");
160
+ await c.download(e);
130
161
  },
131
162
  markClean() {
132
- l?.markClean();
163
+ c?.markClean();
133
164
  },
134
165
  get dirty() {
135
- return l?.dirty ?? !1;
166
+ return c?.dirty ?? !1;
136
167
  }
137
- }), () => t("div", { ref: c });
168
+ }), () => n("div", { ref: s });
138
169
  }
139
- }), T = /* @__PURE__ */ f({
140
- detectDocumentFormat: () => o,
141
- loadDocument: () => s
170
+ }), M = /* @__PURE__ */ v({
171
+ detectDocumentFormat: () => d,
172
+ loadDocument: () => f,
173
+ mountEditorSurface: () => A
174
+ });
175
+ b(M, x);
176
+ //#endregion
177
+ //#region packages/bindings/src/building-blocks.ts
178
+ function N(e = {}) {
179
+ let t = e, n, r, i, a = 0, o = null, s, c = {
180
+ toolbarProps: null,
181
+ navigationProps: null,
182
+ statusProps: null,
183
+ loading: !1,
184
+ error: null,
185
+ mode: "view"
186
+ }, l = /* @__PURE__ */ new Set(), u = (e) => {
187
+ let n = {
188
+ ...c,
189
+ ...e,
190
+ mode: t.canEdit !== !0 || t.readOnly ? "view" : "edit"
191
+ };
192
+ if (!Object.keys(n).every((e) => n[e] === c[e])) {
193
+ c = n;
194
+ for (let e of l) e(c);
195
+ }
196
+ }, d = (e, t, n) => e && t && n && JSON.stringify(e) === JSON.stringify(t) ? e : t, f = () => {
197
+ let e = n?.element ?? null, t = s === e;
198
+ s = e, u({
199
+ toolbarProps: d(c.toolbarProps, n?.getToolbarProps() ?? null, t),
200
+ navigationProps: d(c.navigationProps, n?.getNavigationProps() ?? null, t),
201
+ statusProps: d(c.statusProps, n?.getStatusProps() ?? null, t),
202
+ loading: n?.element.loading ?? !1,
203
+ ...n?.element.loading ? { error: null } : {}
204
+ });
205
+ }, p = () => ({
206
+ ...t,
207
+ onDocumentError: (e) => {
208
+ u({ error: e }), t.onDocumentError?.(e);
209
+ }
210
+ }), m = () => {
211
+ if (!n) throw Error("Editor is not mounted");
212
+ return n;
213
+ }, h = async (e) => {
214
+ let t = m(), r = ++a;
215
+ u({
216
+ loading: !0,
217
+ error: null
218
+ });
219
+ try {
220
+ await t.load(e);
221
+ } catch (e) {
222
+ throw r === a && n === t && u({ error: e instanceof Error ? e : Error(String(e)) }), e;
223
+ } finally {
224
+ r === a && n === t && f();
225
+ }
226
+ }, g = () => {
227
+ n && t.bytes && i !== t.bytes && (i = t.bytes, h(t.bytes).catch(() => {}));
228
+ }, _ = (e) => {
229
+ e !== o && (o = e, ++a, r?.(), r = void 0, n?.destroy(), n = void 0, i = void 0, e && (n = A(e, p()), r = n.subscribe(f)), f(), g());
230
+ };
231
+ return {
232
+ canvasProps: { mount: _ },
233
+ handle: {
234
+ get element() {
235
+ return m().element;
236
+ },
237
+ load: h,
238
+ save: () => m().save(),
239
+ download: (e) => m().download(e),
240
+ markClean: () => m().markClean(),
241
+ get dirty() {
242
+ return n?.dirty ?? !1;
243
+ }
244
+ },
245
+ get state() {
246
+ return c;
247
+ },
248
+ subscribe(e) {
249
+ return l.add(e), e(c), () => {
250
+ l.delete(e);
251
+ };
252
+ },
253
+ update(e) {
254
+ t.documentModel !== e.documentModel && u({ error: null }), t = e, n?.update(p()), f(), g();
255
+ },
256
+ destroy() {
257
+ _(null), l.clear();
258
+ }
259
+ };
260
+ }
261
+ function P(e) {
262
+ if (!e) return;
263
+ let t = Reflect.get(p, "prepareOfficeUiBlock");
264
+ typeof t == "function" ? t(e, "toolbar", "docx") : (p.installOfficeUiTheme(e.ownerDocument), e.setAttribute("data-office-block", "toolbar"), e.setAttribute("data-office-product", "docx"));
265
+ }
266
+ //#endregion
267
+ //#region packages/bindings/src/controls.ts
268
+ var F = [
269
+ "Calibri",
270
+ "Arial",
271
+ "Cambria",
272
+ "Courier New",
273
+ "Georgia",
274
+ "Segoe UI",
275
+ "Times New Roman",
276
+ "Verdana"
277
+ ], I = [
278
+ 8,
279
+ 9,
280
+ 10,
281
+ 11,
282
+ 12,
283
+ 14,
284
+ 16,
285
+ 18,
286
+ 20,
287
+ 24,
288
+ 28,
289
+ 36,
290
+ 48,
291
+ 72
292
+ ], L = [
293
+ 50,
294
+ 75,
295
+ 100,
296
+ 125,
297
+ 150,
298
+ 200
299
+ ];
300
+ function R(e, t) {
301
+ let n = typeof e[0] == "number", r = (t === null || e.includes(t) ? [...e] : [...e, t]).map(String).sort((e, t) => n ? Number(e) - Number(t) : e.localeCompare(t)).map((e) => ({
302
+ value: e,
303
+ label: e
304
+ }));
305
+ return t === null ? [{
306
+ value: "",
307
+ label: ""
308
+ }, ...r] : r;
309
+ }
310
+ var z = (e, t) => e[t] ?? t;
311
+ function B(e) {
312
+ let { labels: t } = e, n = !e.canEdit, r = (e, r, i, a) => ({
313
+ kind: "toggle",
314
+ id: e,
315
+ label: z(t, r),
316
+ disabled: n,
317
+ pressed: i === null ? "mixed" : i,
318
+ run: () => void a()
319
+ }), i = (e, n, r, i) => ({
320
+ kind: "action",
321
+ id: e,
322
+ label: z(t, n),
323
+ disabled: r,
324
+ run: () => void i()
325
+ }), a = (r, i, a) => ({
326
+ kind: "toggle",
327
+ id: r,
328
+ label: z(t, i),
329
+ disabled: n,
330
+ pressed: e.alignment === null ? "mixed" : e.alignment === a,
331
+ run: () => void e.onAlignmentChange(a)
332
+ }), o = (r, i, a) => ({
333
+ kind: "toggle",
334
+ id: r,
335
+ label: z(t, i),
336
+ disabled: n,
337
+ pressed: e.list === a,
338
+ run: () => void e.onListChange(e.list === a ? "remove" : a)
339
+ }), s = [
340
+ [i("undo", "Undo", !e.canUndo, e.onUndo), i("redo", "Redo", !e.canRedo, e.onRedo)],
341
+ [{
342
+ kind: "select",
343
+ id: "fontFamily",
344
+ label: z(t, "Font"),
345
+ disabled: n,
346
+ value: e.fontFamily ?? "",
347
+ options: R(F, e.fontFamily),
348
+ change: (t) => void e.onFontFamilyChange(t)
349
+ }, {
350
+ kind: "select",
351
+ id: "fontSize",
352
+ label: z(t, "Font size"),
353
+ disabled: n,
354
+ value: e.fontSize === null ? "" : String(e.fontSize),
355
+ options: R(I, e.fontSize),
356
+ change: (t) => void e.onFontSizeChange(Number(t))
357
+ }],
358
+ [
359
+ r("bold", "Bold", e.bold, e.onBold),
360
+ r("italic", "Italic", e.italic, e.onItalic),
361
+ r("underline", "Underline", e.underline, e.onUnderline)
362
+ ],
363
+ [
364
+ a("alignLeft", "Align left", "left"),
365
+ a("alignCenter", "Align center", "center"),
366
+ a("alignRight", "Align right", "right"),
367
+ a("alignJustify", "Justify", "justify")
368
+ ],
369
+ [o("bulletList", "Bulleted list", "bullet"), o("numberList", "Numbered list", "number")]
370
+ ], c = [], { hyperlink: l, findReplace: u, picture: d } = e.hostWorkflows;
371
+ return l && c.push(i("link", "Insert link", !e.canInsertLink, e.openHyperlinkDialog)), u && c.push(i("find", "Find", !e.canFindReplace, e.openFindReplace)), d && c.push(i("picture", "Insert picture", !e.canInsertPicture, e.openImagePicker)), c.length && s.push(c), s;
372
+ }
373
+ function V(e) {
374
+ let { labels: t } = e;
375
+ return [[
376
+ {
377
+ kind: "action",
378
+ id: "previousPage",
379
+ label: z(t, "Previous page"),
380
+ disabled: !e.canGoPrevious,
381
+ run: () => void e.onPreviousPage()
382
+ },
383
+ {
384
+ kind: "text",
385
+ id: "pageText",
386
+ label: "",
387
+ text: e.pageText,
388
+ disabled: !1
389
+ },
390
+ {
391
+ kind: "action",
392
+ id: "nextPage",
393
+ label: z(t, "Next page"),
394
+ disabled: !e.canGoNext,
395
+ run: () => void e.onNextPage()
396
+ }
397
+ ], [{
398
+ kind: "select",
399
+ id: "viewMode",
400
+ label: z(t, "Layout view"),
401
+ disabled: !1,
402
+ value: e.viewMode,
403
+ options: [{
404
+ value: "draft",
405
+ label: z(t, "Draft")
406
+ }, {
407
+ value: "print",
408
+ label: z(t, "Print Layout")
409
+ }],
410
+ change: (t) => void e.onViewModeChange(t === "print" ? "print" : "draft")
411
+ }]];
412
+ }
413
+ function H(e) {
414
+ let t = R(L, e.zoom).map((e) => ({
415
+ value: e.value,
416
+ label: `${e.label}%`
417
+ }));
418
+ return [[{
419
+ kind: "text",
420
+ id: "wordText",
421
+ label: "",
422
+ text: e.wordText,
423
+ disabled: !1
424
+ }], [{
425
+ kind: "select",
426
+ id: "zoom",
427
+ label: z(e.labels, "Zoom"),
428
+ disabled: !1,
429
+ value: String(e.zoom),
430
+ options: t,
431
+ change: (t) => void e.onZoomChange(Number(t))
432
+ }]];
433
+ }
434
+ //#endregion
435
+ //#region packages/vue/src/building-blocks.ts
436
+ function U(t = {}) {
437
+ let n = N(), r = s(n.state), i = n.subscribe((e) => {
438
+ r.value = e;
439
+ });
440
+ return u(() => n.update(c(t))), a(() => {
441
+ i(), n.destroy();
442
+ }), {
443
+ canvasProps: n.canvasProps,
444
+ handle: n.handle,
445
+ toolbarProps: e(() => r.value.toolbarProps),
446
+ navigationProps: e(() => r.value.navigationProps),
447
+ statusProps: e(() => r.value.statusProps),
448
+ loading: e(() => r.value.loading),
449
+ error: e(() => r.value.error),
450
+ mode: e(() => r.value.mode)
451
+ };
452
+ }
453
+ var W = t({
454
+ name: "DocumentCanvas",
455
+ inheritAttrs: !1,
456
+ props: { mount: {
457
+ type: Function,
458
+ required: !0
459
+ } },
460
+ setup(e, { attrs: t }) {
461
+ let r = null, i = (t) => {
462
+ let n = t;
463
+ r !== n && (r = n, e.mount(n));
464
+ };
465
+ return l(() => e.mount, (e, t) => {
466
+ t(null), r && e(r);
467
+ }), a(() => e.mount(null)), () => n("div", {
468
+ ...t,
469
+ ref: i
470
+ });
471
+ }
472
+ });
473
+ function G(e) {
474
+ return e.kind === "text" ? n("span", {
475
+ key: e.id,
476
+ role: "status"
477
+ }, e.text) : e.kind === "select" ? n("select", {
478
+ key: e.id,
479
+ "aria-label": e.label,
480
+ disabled: e.disabled,
481
+ value: e.value,
482
+ onChange: (t) => e.change(t.target.value)
483
+ }, e.options.map((e) => n("option", {
484
+ key: e.value,
485
+ value: e.value
486
+ }, e.label))) : n("button", {
487
+ key: e.id,
488
+ type: "button",
489
+ "aria-label": e.label,
490
+ disabled: e.disabled,
491
+ ...e.kind === "toggle" ? { "aria-pressed": e.pressed } : {},
492
+ onMousedown: (e) => e.preventDefault(),
493
+ onClick: e.run
494
+ }, e.label);
495
+ }
496
+ function K(e, t) {
497
+ return n("div", {
498
+ role: e,
499
+ ref: (e) => P(e)
500
+ }, t.map((e, t) => n("span", {
501
+ key: t,
502
+ role: "group"
503
+ }, e.map(G))));
504
+ }
505
+ var q = t({
506
+ name: "WordToolbar",
507
+ props: { toolbarProps: {
508
+ type: Object,
509
+ required: !0
510
+ } },
511
+ setup: (e) => () => K("toolbar", B(e.toolbarProps))
512
+ }), J = t({
513
+ name: "WordPageNavigation",
514
+ props: { navigationProps: {
515
+ type: Object,
516
+ required: !0
517
+ } },
518
+ setup: (e) => () => K("group", V(e.navigationProps))
519
+ }), Y = t({
520
+ name: "WordStatusBar",
521
+ props: { statusProps: {
522
+ type: Object,
523
+ required: !0
524
+ } },
525
+ setup: (e) => () => K("group", H(e.statusProps))
142
526
  });
143
- m(T, h), m(/* @__PURE__ */ f({
144
- WordEditor: () => w,
145
- detectDocumentFormat: () => o,
146
- loadDocument: () => s
147
- }), T);
527
+ b(/* @__PURE__ */ v({
528
+ DocumentCanvas: () => W,
529
+ PageNavigation: () => J,
530
+ StatusBar: () => Y,
531
+ Toolbar: () => q,
532
+ WordEditor: () => j,
533
+ detectDocumentFormat: () => d,
534
+ loadDocument: () => f,
535
+ mountEditorSurface: () => A,
536
+ useViewerBuildingBlocks: () => U
537
+ }), M);
148
538
  //#endregion
149
- export { w as WordEditor, o as detectDocumentFormat, s as loadDocument };
539
+ export { W as DocumentCanvas, J as PageNavigation, Y as StatusBar, q as Toolbar, j as WordEditor, d as detectDocumentFormat, f as loadDocument, A as mountEditorSurface, U as useViewerBuildingBlocks };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docx-vue-viewer",
3
- "version": "0.5.0",
3
+ "version": "1.0.0",
4
4
  "description": "Vue 3 component for the DOCX editor. Self-contained: includes the editor, layout engine and legacy .doc reader.",
5
5
  "keywords": [
6
6
  "doc",
@@ -40,9 +40,9 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
- "docx-core": "^0.1.13",
44
- "ooxml-core": "^1.8.0",
45
- "ooxml-ui": "^1.8.0"
43
+ "docx-core": "^0.3.0",
44
+ "ooxml-core": "^1.22.0",
45
+ "ooxml-ui": "^1.21.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "vue": "^3.5.0"