docx-vue-viewer 0.6.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +131 -14
  2. package/dist/index.js +305 -102
  3. package/package.json +4 -4
package/dist/index.d.ts CHANGED
@@ -2,9 +2,9 @@ import * as vue from 'vue';
2
2
  import { PropType, MaybeRefOrGetter } from 'vue';
3
3
  import { DocumentModel } from 'docx-core';
4
4
  export * from 'docx-core';
5
- import { EditorThemeMode, RibbonActionInput, RibbonAddInTab, EditorLocaleInput, PageChangeDetail, RibbonAddInCommandDetail, DocxEditorElement, WordToolbarProps } 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 { WordToolbarProps } from 'ooxml-ui/docx';
7
+ export { WordNavigationProps, WordStatusProps, WordToolbarProps } from 'ooxml-ui/docx';
8
8
  export { DocumentFormat, detectDocumentFormat, loadDocument } from 'ooxml-core/docx/load';
9
9
 
10
10
  declare const WordEditor: vue.DefineComponent<vue.ExtractPropTypes<{
@@ -19,9 +19,10 @@ declare const WordEditor: vue.DefineComponent<vue.ExtractPropTypes<{
19
19
  };
20
20
  hiddenActions: PropType<readonly RibbonActionInput[]>;
21
21
  ribbonAddIns: PropType<readonly RibbonAddInTab[]>;
22
+ collaboration: PropType<DocxCollaborationOptions | null>;
22
23
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
23
24
  [key: string]: any;
24
- }>, {}, {}, {}, 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<{
25
26
  documentModel: PropType<DocumentModel>;
26
27
  readOnly: BooleanConstructor;
27
28
  locale: StringConstructor;
@@ -33,11 +34,13 @@ declare const WordEditor: vue.DefineComponent<vue.ExtractPropTypes<{
33
34
  };
34
35
  hiddenActions: PropType<readonly RibbonActionInput[]>;
35
36
  ribbonAddIns: PropType<readonly RibbonAddInTab[]>;
37
+ collaboration: PropType<DocxCollaborationOptions | null>;
36
38
  }>> & Readonly<{
37
39
  "onDocument-change"?: (...args: any[]) => any;
38
40
  "onDocument-error"?: (...args: any[]) => any;
39
41
  "onPage-change"?: (...args: any[]) => any;
40
42
  "onDirty-change"?: (...args: any[]) => any;
43
+ "onCollaboration-change"?: (...args: any[]) => any;
41
44
  "onOffice-ribbon-add-in"?: (...args: any[]) => any;
42
45
  }>, {
43
46
  readOnly: boolean;
@@ -61,6 +64,11 @@ interface EditorProps {
61
64
  hiddenActions?: readonly RibbonActionInput[] | undefined;
62
65
  /** Tabs the host adds after Word's own, as an Office add-in does. */
63
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;
64
72
  }
65
73
  /** Editor callbacks; each is the framework-neutral form of one entry in `EDITOR_EVENT_NAMES`. */
66
74
  interface EditorEventOptions {
@@ -70,6 +78,8 @@ interface EditorEventOptions {
70
78
  onDirtyChange?: ((dirty: boolean) => void) | undefined;
71
79
  /** A command of a host tab (`ribbonAddIns`) was chosen. */
72
80
  onRibbonAddIn?: ((detail: RibbonAddInCommandDetail) => void) | undefined;
81
+ /** Sharing started, stopped, reconnected or the people in the room changed. */
82
+ onCollaborationChange?: ((state: DocxCollaborationState) => void) | undefined;
73
83
  }
74
84
  interface EditorOptions extends EditorProps, EditorEventOptions {
75
85
  }
@@ -87,18 +97,35 @@ interface EditorBinding extends EditorHandle {
87
97
  update(options: EditorOptions): void;
88
98
  destroy(): void;
89
99
  }
90
- /** Framework-neutral composition API, shared by every adapter. Choose before mount. */
91
- interface SurfaceOptions extends EditorOptions {
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 {
92
108
  canEdit?: boolean | undefined;
93
109
  }
94
110
  declare function mountEditorSurface(host: HTMLElement, initial?: SurfaceOptions): EditorBinding & {
95
111
  update: (options: SurfaceOptions) => void;
96
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;
97
124
  labels: {
98
125
  [k: string]: string;
99
126
  };
100
127
  canEdit: boolean;
101
- list: "bullet" | "decimal" | "other" | null;
128
+ list: WordListState;
102
129
  selection: {
103
130
  from: number;
104
131
  to: number;
@@ -108,7 +135,7 @@ declare function mountEditorSurface(host: HTMLElement, initial?: SurfaceOptions)
108
135
  underline: boolean | null;
109
136
  fontFamily: string | null;
110
137
  fontSize: number | null;
111
- alignment: string | null;
138
+ alignment: WordAlignment | null;
112
139
  canUndo: boolean;
113
140
  canRedo: boolean;
114
141
  onBold: () => boolean;
@@ -116,11 +143,36 @@ declare function mountEditorSurface(host: HTMLElement, initial?: SurfaceOptions)
116
143
  onUnderline: () => boolean;
117
144
  onFontFamilyChange: (family: string) => boolean;
118
145
  onFontSizeChange: (size: number) => boolean;
119
- onAlignmentChange: (alignment: "left" | "center" | "right" | "justify") => boolean;
120
- onListChange: (kind: "bullet" | "number" | "remove") => boolean;
146
+ onAlignmentChange: (alignment: WordAlignment) => boolean;
147
+ onListChange: (kind: WordListChoice | "remove") => boolean;
121
148
  onUndo: () => boolean;
122
149
  onRedo: () => boolean;
123
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
+ };
124
176
  subscribe: (listener: () => void) => () => void;
125
177
  };
126
178
 
@@ -138,11 +190,22 @@ declare function useViewerBuildingBlocks(options?: MaybeRefOrGetter<BuildingBloc
138
190
  };
139
191
  handle: EditorHandle;
140
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;
141
204
  labels: {
142
205
  [k: string]: string;
143
206
  };
144
207
  canEdit: boolean;
145
- list: "bullet" | "decimal" | "other" | null;
208
+ list: WordListState;
146
209
  selection: {
147
210
  from: number;
148
211
  to: number;
@@ -152,7 +215,7 @@ declare function useViewerBuildingBlocks(options?: MaybeRefOrGetter<BuildingBloc
152
215
  underline: boolean | null;
153
216
  fontFamily: string | null;
154
217
  fontSize: number | null;
155
- alignment: string | null;
218
+ alignment: WordAlignment | null;
156
219
  canUndo: boolean;
157
220
  canRedo: boolean;
158
221
  onBold: () => boolean;
@@ -160,11 +223,36 @@ declare function useViewerBuildingBlocks(options?: MaybeRefOrGetter<BuildingBloc
160
223
  onUnderline: () => boolean;
161
224
  onFontFamilyChange: (family: string) => boolean;
162
225
  onFontSizeChange: (size: number) => boolean;
163
- onAlignmentChange: (alignment: "left" | "center" | "right" | "justify") => boolean;
164
- onListChange: (kind: "bullet" | "number" | "remove") => boolean;
226
+ onAlignmentChange: (alignment: WordAlignment) => boolean;
227
+ onListChange: (kind: WordListChoice | "remove") => boolean;
165
228
  onUndo: () => boolean;
166
229
  onRedo: () => boolean;
167
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>;
168
256
  loading: vue.ComputedRef<boolean>;
169
257
  error: vue.ComputedRef<Error | null>;
170
258
  mode: vue.ComputedRef<"view" | "edit">;
@@ -182,6 +270,7 @@ declare const DocumentCanvas: vue.DefineComponent<vue.ExtractPropTypes<{
182
270
  required: true;
183
271
  };
184
272
  }>> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
273
+ /** Optional controls: history, font, formatting, alignment, lists and enabled host workflows. */
185
274
  declare const Toolbar: vue.DefineComponent<vue.ExtractPropTypes<{
186
275
  toolbarProps: {
187
276
  type: PropType<WordToolbarProps>;
@@ -195,6 +284,34 @@ declare const Toolbar: vue.DefineComponent<vue.ExtractPropTypes<{
195
284
  required: true;
196
285
  };
197
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>;
198
315
 
199
- export { DocumentCanvas, Toolbar, WordEditor, mountEditorSurface, useViewerBuildingBlocks };
316
+ export { DocumentCanvas, PageNavigation, StatusBar, Toolbar, WordEditor, mountEditorSurface, useViewerBuildingBlocks };
200
317
  export type { BuildingBlockOptions, CanvasProps, EditorBinding, EditorEventOptions, EditorHandle, EditorOptions, EditorProps, SurfaceOptions };
package/dist/index.js CHANGED
@@ -30,13 +30,15 @@ var C = [
30
30
  "showThumbnails",
31
31
  "showToolbar",
32
32
  "hiddenActions",
33
- "ribbonAddIns"
33
+ "ribbonAddIns",
34
+ "collaboration"
34
35
  ], w = [
35
36
  "document-change",
36
37
  "document-error",
37
38
  "page-change",
38
39
  "dirty-change",
39
- "office-ribbon-add-in"
40
+ "office-ribbon-add-in",
41
+ "collaboration-change"
40
42
  ];
41
43
  function T(e, t) {
42
44
  return e.length === t.length && e.every((e, n) => e === t[n]);
@@ -55,7 +57,8 @@ function O(e) {
55
57
  onDocumentError: e["document-error"],
56
58
  onPageChange: e["page-change"],
57
59
  onDirtyChange: e["dirty-change"],
58
- onRibbonAddIn: e["office-ribbon-add-in"]
60
+ onRibbonAddIn: e["office-ribbon-add-in"],
61
+ onCollaborationChange: e["collaboration-change"]
59
62
  };
60
63
  }
61
64
  function k(e, t = {}, n = !1) {
@@ -63,14 +66,14 @@ function k(e, t = {}, n = !1) {
63
66
  let r = e.ownerDocument.createElement("docx-editor");
64
67
  if (n && typeof r.getToolbarProps != "function") throw Error("Update ooxml-ui to use editor building blocks.");
65
68
  r.surfaceOnly = n;
66
- let i = {}, a, o, s, c = !1, l = (e) => {
69
+ let i = {}, a, o, s, c = null, l = !1, u = (e) => {
67
70
  o = e.detail, i.onDocumentChange?.(o);
68
- }, u = (e) => i.onDocumentError?.(e.detail), d = (e) => i.onPageChange?.(e.detail), f = (e) => i.onDirtyChange?.(e.detail), p = (e) => i.onRibbonAddIn?.(e.detail);
69
- r.addEventListener("document-change", l), r.addEventListener("document-error", u), r.addEventListener("page-change", d), r.addEventListener("dirty-change", f), r.addEventListener("office-ribbon-add-in", p);
70
- let m = {
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 = {
71
74
  element: r,
72
75
  update(e) {
73
- c || (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.documentModel && e.documentModel !== a && e.documentModel !== o && (r.documentModel = e.documentModel), a = 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);
74
77
  },
75
78
  load: (e) => r.load(e),
76
79
  save: () => r.save(),
@@ -80,20 +83,31 @@ function k(e, t = {}, n = !1) {
80
83
  return r.dirty;
81
84
  },
82
85
  destroy() {
83
- c || (c = !0, r.removeEventListener("document-change", l), r.removeEventListener("document-error", u), r.removeEventListener("page-change", d), r.removeEventListener("dirty-change", f), r.removeEventListener("office-ribbon-add-in", p), r.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());
84
87
  }
85
88
  };
86
- return m.update(t), e.append(r), m;
89
+ return g.update(t), e.append(r), g;
87
90
  }
88
91
  function A(e, t = {}) {
89
92
  let n = (e) => ({
90
93
  ...e,
91
- readOnly: e.canEdit === !1 || e.readOnly === !0
92
- }), r = k(e, n(t), !0), i = r.update;
93
- return Object.assign(r, {
94
- update: (e) => i(n(e)),
95
- getToolbarProps: () => r.element.getToolbarProps(),
96
- subscribe: (e) => r.element.subscribeEditorState(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)
97
111
  });
98
112
  }
99
113
  //#endregion
@@ -111,7 +125,8 @@ var j = t({
111
125
  default: !0
112
126
  },
113
127
  hiddenActions: Array,
114
- ribbonAddIns: Array
128
+ ribbonAddIns: Array,
129
+ collaboration: Object
115
130
  },
116
131
  emits: [...w],
117
132
  setup(e, { emit: t, expose: a }) {
@@ -122,7 +137,8 @@ var j = t({
122
137
  "document-error": (e) => t("document-error", e),
123
138
  "page-change": (e) => t("page-change", e),
124
139
  "dirty-change": (e) => t("dirty-change", e),
125
- "office-ribbon-add-in": (e) => t("office-ribbon-add-in", e)
140
+ "office-ribbon-add-in": (e) => t("office-ribbon-add-in", e),
141
+ "collaboration-change": (e) => t("collaboration-change", e)
126
142
  })
127
143
  });
128
144
  return i(() => {
@@ -160,75 +176,85 @@ b(M, x);
160
176
  //#endregion
161
177
  //#region packages/bindings/src/building-blocks.ts
162
178
  function N(e = {}) {
163
- let t = e, n, r, i, a = 0, o = null, s = {
179
+ let t = e, n, r, i, a = 0, o = null, s, c = {
164
180
  toolbarProps: null,
181
+ navigationProps: null,
182
+ statusProps: null,
165
183
  loading: !1,
166
184
  error: null,
167
- mode: "edit"
168
- }, c = /* @__PURE__ */ new Set(), l = (e) => {
169
- s = {
170
- ...s,
185
+ mode: "view"
186
+ }, l = /* @__PURE__ */ new Set(), u = (e) => {
187
+ let n = {
188
+ ...c,
171
189
  ...e,
172
- mode: t.canEdit === !1 || t.readOnly ? "view" : "edit"
190
+ mode: t.canEdit !== !0 || t.readOnly ? "view" : "edit"
173
191
  };
174
- for (let e of c) e(s);
175
- }, u = () => l({
176
- toolbarProps: n?.getToolbarProps() ?? null,
177
- loading: n?.element.loading ?? !1,
178
- ...n?.element.loading ? { error: null } : {}
179
- }), d = () => ({
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 = () => ({
180
206
  ...t,
181
207
  onDocumentError: (e) => {
182
- l({ error: e }), t.onDocumentError?.(e);
208
+ u({ error: e }), t.onDocumentError?.(e);
183
209
  }
184
- }), f = () => {
210
+ }), m = () => {
185
211
  if (!n) throw Error("Editor is not mounted");
186
212
  return n;
187
- }, p = async (e) => {
188
- let t = f(), r = ++a;
189
- l({
213
+ }, h = async (e) => {
214
+ let t = m(), r = ++a;
215
+ u({
190
216
  loading: !0,
191
217
  error: null
192
218
  });
193
219
  try {
194
220
  await t.load(e);
195
221
  } catch (e) {
196
- throw r === a && n === t && l({ error: e instanceof Error ? e : Error(String(e)) }), e;
222
+ throw r === a && n === t && u({ error: e instanceof Error ? e : Error(String(e)) }), e;
197
223
  } finally {
198
- r === a && n === t && u();
224
+ r === a && n === t && f();
199
225
  }
200
- }, m = () => {
201
- n && t.bytes && i !== t.bytes && (i = t.bytes, p(t.bytes).catch(() => {}));
202
- }, h = (e) => {
203
- e !== o && (o = e, ++a, r?.(), r = void 0, n?.destroy(), n = void 0, i = void 0, e && (n = A(e, d()), r = n.subscribe(u)), u(), m());
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());
204
230
  };
205
231
  return {
206
- canvasProps: { mount: h },
232
+ canvasProps: { mount: _ },
207
233
  handle: {
208
234
  get element() {
209
- return f().element;
235
+ return m().element;
210
236
  },
211
- load: p,
212
- save: () => f().save(),
213
- download: (e) => f().download(e),
214
- markClean: () => f().markClean(),
237
+ load: h,
238
+ save: () => m().save(),
239
+ download: (e) => m().download(e),
240
+ markClean: () => m().markClean(),
215
241
  get dirty() {
216
242
  return n?.dirty ?? !1;
217
243
  }
218
244
  },
219
245
  get state() {
220
- return s;
246
+ return c;
221
247
  },
222
248
  subscribe(e) {
223
- return c.add(e), e(s), () => {
224
- c.delete(e);
249
+ return l.add(e), e(c), () => {
250
+ l.delete(e);
225
251
  };
226
252
  },
227
253
  update(e) {
228
- t.documentModel !== e.documentModel && l({ error: null }), t = e, n?.update(d()), u(), m();
254
+ t.documentModel !== e.documentModel && u({ error: null }), t = e, n?.update(p()), f(), g();
229
255
  },
230
256
  destroy() {
231
- h(null), c.clear();
257
+ _(null), l.clear();
232
258
  }
233
259
  };
234
260
  }
@@ -238,8 +264,176 @@ function P(e) {
238
264
  typeof t == "function" ? t(e, "toolbar", "docx") : (p.installOfficeUiTheme(e.ownerDocument), e.setAttribute("data-office-block", "toolbar"), e.setAttribute("data-office-product", "docx"));
239
265
  }
240
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
241
435
  //#region packages/vue/src/building-blocks.ts
242
- function F(t = {}) {
436
+ function U(t = {}) {
243
437
  let n = N(), r = s(n.state), i = n.subscribe((e) => {
244
438
  r.value = e;
245
439
  });
@@ -249,12 +443,14 @@ function F(t = {}) {
249
443
  canvasProps: n.canvasProps,
250
444
  handle: n.handle,
251
445
  toolbarProps: e(() => r.value.toolbarProps),
446
+ navigationProps: e(() => r.value.navigationProps),
447
+ statusProps: e(() => r.value.statusProps),
252
448
  loading: e(() => r.value.loading),
253
449
  error: e(() => r.value.error),
254
450
  mode: e(() => r.value.mode)
255
451
  };
256
452
  }
257
- var I = t({
453
+ var W = t({
258
454
  name: "DocumentCanvas",
259
455
  inheritAttrs: !1,
260
456
  props: { mount: {
@@ -273,64 +469,71 @@ var I = t({
273
469
  ref: i
274
470
  });
275
471
  }
276
- }), L = t({
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({
277
506
  name: "WordToolbar",
278
507
  props: { toolbarProps: {
279
508
  type: Object,
280
509
  required: !0
281
510
  } },
282
- setup(e) {
283
- return () => n("div", {
284
- role: "toolbar",
285
- ref: (e) => P(e)
286
- }, [
287
- [
288
- "Bold",
289
- e.toolbarProps.bold,
290
- e.toolbarProps.onBold,
291
- !e.toolbarProps.canEdit
292
- ],
293
- [
294
- "Italic",
295
- e.toolbarProps.italic,
296
- e.toolbarProps.onItalic,
297
- !e.toolbarProps.canEdit
298
- ],
299
- [
300
- "Underline",
301
- e.toolbarProps.underline,
302
- e.toolbarProps.onUnderline,
303
- !e.toolbarProps.canEdit
304
- ],
305
- [
306
- "Undo",
307
- !1,
308
- e.toolbarProps.onUndo,
309
- !e.toolbarProps.canUndo
310
- ],
311
- [
312
- "Redo",
313
- !1,
314
- e.toolbarProps.onRedo,
315
- !e.toolbarProps.canRedo
316
- ]
317
- ].map(([t, r, i, a]) => n("button", {
318
- type: "button",
319
- disabled: a,
320
- "aria-pressed": r === null ? "mixed" : r,
321
- onMousedown: (e) => e.preventDefault(),
322
- onClick: i
323
- }, e.toolbarProps.labels[String(t)] ?? String(t))));
324
- }
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))
325
526
  });
326
527
  b(/* @__PURE__ */ v({
327
- DocumentCanvas: () => I,
328
- Toolbar: () => L,
528
+ DocumentCanvas: () => W,
529
+ PageNavigation: () => J,
530
+ StatusBar: () => Y,
531
+ Toolbar: () => q,
329
532
  WordEditor: () => j,
330
533
  detectDocumentFormat: () => d,
331
534
  loadDocument: () => f,
332
535
  mountEditorSurface: () => A,
333
- useViewerBuildingBlocks: () => F
536
+ useViewerBuildingBlocks: () => U
334
537
  }), M);
335
538
  //#endregion
336
- export { I as DocumentCanvas, L as Toolbar, j as WordEditor, d as detectDocumentFormat, f as loadDocument, A as mountEditorSurface, F as useViewerBuildingBlocks };
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.6.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.2.0",
44
- "ooxml-core": "^1.20.0",
45
- "ooxml-ui": "^1.19.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"