visio-solid-viewer 0.8.0 → 1.0.1

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/README.md CHANGED
@@ -58,22 +58,34 @@ export function Diagram() {
58
58
 
59
59
  The shared properties are `document` (a parsed `VisioDocument`, or `null` to clear),
60
60
  `pageIndex` (zero-based), `zoom` (`1` means 100%), `showToolbar`, `ribbonAddIns` (tabs the host adds
61
- after Help) and `events`.
62
- The callback map uses `document-load`, `document-change`, `document-error`,
63
- `page-change`, `zoom-change` and `shape-select`. File loading uses the imperative
61
+ after Help), `canEdit` (editing permission; the viewer is editable unless you pass `false`),
62
+ `collaboration` (shares the open drawing in a room while set; `null` leaves it) and `events`.
63
+ The callback map uses `document-load`, `document-change` (`{ document, dirty, kind }` with kind
64
+ `edit`, `undo`, `redo`, `remote` or `save`), `document-error`, `page-change`, `zoom-change`,
65
+ `shape-select`, `selection-change`, `office-ribbon-add-in` and `collaboration-change`. File loading uses the imperative
64
66
  `load(File | Blob | Uint8Array | ArrayBuffer)` handle; `document` is not a file URL.
65
67
  Provide a height for the viewer host. Mount and load files in the browser.
66
68
 
67
69
  The handle supports `fit()`, `replacePlainText(pageId, shapeId, text)`,
68
70
  `applyEdits(edits)`, `undo()`, `redo()` and `exportVsdx()`.
69
71
  `exportVsdx()` returns `{ bytes, dirty, diagnostics }`; saving or downloading those
70
- bytes is the application's responsibility. Load original bytes through `load()`
72
+ bytes is the application's responsibility, and `handle.controller.markClean()` declares them saved.
73
+ Sharing state is on the handle's element: `collaborationState`, `reconnectCollaboration()` and
74
+ `stopCollaboration()`. Load original bytes through `load()`
71
75
  to enable source-backed editing and export. Handles are usable after mount.
72
76
 
73
77
  Every viewer package includes the same browser UI and re-exports the
74
78
  `visio-core` document API. Parsing and editing belong to `ooxml-core/visio`;
75
79
  framework bindings only manage lifecycle, properties and events.
76
80
 
81
+ ## Compose your own UI
82
+
83
+ To build a custom diagram UI instead of mounting the whole viewer, use the building blocks: `createViewerBuildingBlocks`, `DiagramCanvas`, `Toolbar`, `PageNavigation`, `Inspector` and `ShapesPane`. The factory returns accessors
84
+ for the flat `toolbarProps` (page, zoom, selection, search, enabled flags and callbacks), `mode`,
85
+ `loading`/`error` and `markClean()`. Hosts pass `canEdit` (read-only until `true`) and optional
86
+ `onOpenSettings`/`onOpenShareDialog`/`onOpenPageSetup`/`onOpenFile` callbacks for dialogs they own.
87
+ See [composable building blocks](https://github.com/ChristopherVR/ooxml/blob/main/viewers/visio/docs/building-blocks.md).
88
+
77
89
  ## Limitations
78
90
 
79
91
  Rendering and editing are beta features. Supported text and geometry edits are
@@ -83,7 +95,7 @@ Files stay in the browser unless your application sends them elsewhere.
83
95
 
84
96
  ## Documentation
85
97
 
86
- [Viewer guide](https://christophervr.github.io/ooxml/visio/docs/) |
98
+ [Viewer guide](https://christophervr.github.io/ooxml/visio/) |
87
99
  [Demo](https://christophervr.github.io/ooxml/visio/demo/) |
88
100
  [Source](https://github.com/ChristopherVR/ooxml/tree/main/viewers/visio)
89
101
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as ui from "ooxml-ui/visio";
2
2
  import { ViewerController, createWorkerParser, mountViewer, propertyKeys } from "ooxml-ui/visio";
3
- import { addEventListener, className, createComponent, delegateEvents, effect, insert, setAttribute, style, template, use } from "solid-js/web";
4
- import { For, createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js";
3
+ import { className, createComponent, delegateEvents, effect, insert, setAttribute, style, template, use } from "solid-js/web";
4
+ import { For, Index, Match, Switch, createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js";
5
5
  import * as officeTheme from "ooxml-ui/theme";
6
6
  export * from "ooxml-ui/visio";
7
7
  export * from "visio-core";
@@ -221,10 +221,15 @@ function buildingBlock(key) {
221
221
  if (typeof value !== "function") throw new Error("Update ooxml-ui to use Visio building blocks.");
222
222
  return value;
223
223
  }
224
+ /** The mode a host sees: 'edit' only when permission is granted and the file can be saved back. */
225
+ function effectiveMode(state) {
226
+ return buildingBlock("diagramMode")(state);
227
+ }
224
228
  /** Framework-neutral ownership only; each adapter supplies its own reactive state. */
225
- function createBuildingBlockSession() {
229
+ function createBuildingBlockSession(initial = {}) {
226
230
  const controller = new ViewerController(createWorkerParser());
227
- let options = {};
231
+ controller.canEdit = initial.canEdit === true;
232
+ let options = initial;
228
233
  let source;
229
234
  let host = null;
230
235
  let disposeCanvas;
@@ -248,13 +253,23 @@ function createBuildingBlockSession() {
248
253
  host = node;
249
254
  if (node) disposeCanvas = buildingBlock("mountDiagramCanvas")(node, controller);
250
255
  },
251
- toolbar(locale = options.locale) {
252
- return buildingBlock("diagramToolbarProps")(controller, fit, locale);
256
+ /** Flat control props; pass the framework's latest options so callbacks stay current. */
257
+ toolbar(latest = options) {
258
+ return buildingBlock("diagramToolbarProps")(controller, fit, latest.locale, {
259
+ onOpenFile: latest.onOpenFile,
260
+ onOpenPageSetup: latest.onOpenPageSetup,
261
+ onOpenSettings: latest.onOpenSettings,
262
+ onOpenShareDialog: latest.onOpenShareDialog
263
+ });
264
+ },
265
+ /** Acknowledge a host save: clears dirty and emits the dirty change. */
266
+ markClean() {
267
+ controller.markClean();
253
268
  },
254
269
  update(next) {
255
270
  if (destroyed) return;
256
271
  options = next;
257
- controller.canEdit = next.canEdit !== false;
272
+ controller.canEdit = next.canEdit === true;
258
273
  if (source === next.content) return;
259
274
  source = next.content;
260
275
  controller.cancelLoad();
@@ -283,13 +298,96 @@ function prepareDiagramBlock(host, kind) {
283
298
  prepare(host, kind, "visio");
284
299
  }
285
300
  //#endregion
301
+ //#region packages/bindings/src/toolbar-controls.ts
302
+ var TOOLBAR_GROUPS = [
303
+ "file",
304
+ "history",
305
+ "zoom",
306
+ "selection",
307
+ "clipboard",
308
+ "tools",
309
+ "search"
310
+ ];
311
+ var fire = (action) => () => {
312
+ Promise.resolve().then(action).catch(() => {});
313
+ };
314
+ var button = (id, label, enabled, action, pressed) => ({
315
+ kind: "button",
316
+ id,
317
+ label,
318
+ disabled: !enabled,
319
+ ...pressed === void 0 ? {} : { pressed },
320
+ run: fire(action)
321
+ });
322
+ /**
323
+ * What the library Toolbar shows, as plain data every framework maps onto its own elements.
324
+ * Every control reflects `toolbarProps`: edit actions are disabled while the diagram is read-only,
325
+ * viewing actions (zoom, fit, search) never are, and a host dialog button appears only when the
326
+ * host supplied its callback.
327
+ */
328
+ function toolbarGroups(props, include = TOOLBAR_GROUPS) {
329
+ const { labels } = props;
330
+ const has = props.pages.length > 0;
331
+ const groups = [];
332
+ const add = (id, controls) => {
333
+ if (include.includes(id) && controls.length) groups.push({
334
+ id,
335
+ controls
336
+ });
337
+ };
338
+ add("file", [
339
+ ...props.onOpenFile ? [button("open", labels.Open, true, props.onOpenFile)] : [],
340
+ ...props.onOpenPageSetup ? [button("page-setup", labels["Page Setup"], has, props.onOpenPageSetup)] : [],
341
+ ...props.onOpenShareDialog ? [button("share", labels.Share, has, props.onOpenShareDialog)] : [],
342
+ ...props.onOpenSettings ? [button("settings", labels.Options, true, props.onOpenSettings)] : []
343
+ ]);
344
+ add("history", [button("undo", labels.Undo, props.canUndo, props.onUndo), button("redo", labels.Redo, props.canRedo, props.onRedo)]);
345
+ add("zoom", [
346
+ button("zoom-out", labels["Zoom Out"], props.canZoomOut, props.onZoomOut),
347
+ {
348
+ kind: "text",
349
+ id: "zoom",
350
+ text: `${Math.round(props.zoom * 100)}%`
351
+ },
352
+ button("zoom-in", labels["Zoom In"], props.canZoomIn, props.onZoomIn),
353
+ button("fit", labels["Fit to Window"], has, props.onFit)
354
+ ]);
355
+ add("selection", [
356
+ button("duplicate", labels.Duplicate, props.canDuplicate, props.onDuplicate),
357
+ button("group", labels.Group, props.canGroup, props.onGroup),
358
+ button("ungroup", labels.Ungroup, props.canUngroup, props.onUngroup),
359
+ button("delete", labels.Delete, props.canDelete, props.onDelete)
360
+ ]);
361
+ add("clipboard", [
362
+ button("cut", labels.Cut, props.canCut, props.onCut),
363
+ button("copy", labels.Copy, props.canCopy, props.onCopy),
364
+ button("paste", labels.Paste, props.canPaste, props.onPaste)
365
+ ]);
366
+ add("tools", props.tools.map((tool) => button(`tool-${tool.id}`, tool.label, tool.id === "pointer" || props.canDraw, () => props.onToolChange(tool.id), tool.active)));
367
+ const { search } = props;
368
+ add("search", [{
369
+ kind: "search",
370
+ id: "search",
371
+ label: labels.Find,
372
+ query: search.query,
373
+ summary: search.query ? search.resultCount ? `${search.activeIndex >= 0 ? search.activeIndex + 1 : "-"} / ${search.resultCount}` : "0" : "",
374
+ previous: button("search-previous", labels["Previous Result"], search.resultCount > 0, props.onPreviousSearchResult),
375
+ next: button("search-next", labels["Next Result"], search.resultCount > 0, props.onNextSearchResult),
376
+ change: (query) => props.onSearchChange(query)
377
+ }]);
378
+ return groups;
379
+ }
380
+ //#endregion
286
381
  //#region packages/solid/src/building-blocks.tsx
287
382
  var _tmpl$ = /*#__PURE__*/ template(`<div>`);
288
- var _tmpl$2 = /*#__PURE__*/ template(`<div role=toolbar><button type=button></button><button type=button></button><button type=button>`);
289
- var _tmpl$3 = /*#__PURE__*/ template(`<select>`);
290
- var _tmpl$4 = /*#__PURE__*/ template(`<option>`);
383
+ var _tmpl$2 = /*#__PURE__*/ template(`<span>`);
384
+ var _tmpl$3 = /*#__PURE__*/ template(`<button type=button>`);
385
+ var _tmpl$4 = /*#__PURE__*/ template(`<span data-control=search><input type=search><span aria-live=polite>`);
386
+ var _tmpl$5 = /*#__PURE__*/ template(`<div role=toolbar>`);
387
+ var _tmpl$6 = /*#__PURE__*/ template(`<select>`);
388
+ var _tmpl$7 = /*#__PURE__*/ template(`<option>`);
291
389
  function createViewerBuildingBlocks(options = () => ({})) {
292
- const session = createBuildingBlockSession();
390
+ const session = createBuildingBlockSession(options());
293
391
  const [state, setState] = createSignal(session.controller.state);
294
392
  const stop = session.controller.subscribe((value) => setState(() => value));
295
393
  createEffect(() => session.update(options()));
@@ -299,7 +397,7 @@ function createViewerBuildingBlocks(options = () => ({})) {
299
397
  });
300
398
  const toolbarProps = createMemo(() => {
301
399
  state();
302
- return session.toolbar(options().locale);
400
+ return session.toolbar(options());
303
401
  });
304
402
  return {
305
403
  controller: session.controller,
@@ -307,9 +405,18 @@ function createViewerBuildingBlocks(options = () => ({})) {
307
405
  canvasProps: { mount: session.mount },
308
406
  toolbarProps,
309
407
  inspectorProps: { controller: session.controller },
408
+ shapesProps: {
409
+ controller: session.controller,
410
+ get locale() {
411
+ return options().locale;
412
+ }
413
+ },
414
+ /** Acknowledge a host save: clears dirty and fires `onDirtyChange(false)`. */
415
+ markClean: () => session.markClean(),
310
416
  loading: () => state().loading,
311
417
  error: () => state().error ?? state().edit.error,
312
- mode: () => state().canEdit ? "edit" : "view"
418
+ /** Effective permission: host `canEdit` and a drawing that can be saved back. */
419
+ mode: () => effectiveMode(state())
313
420
  };
314
421
  }
315
422
  function DiagramCanvas(props) {
@@ -327,47 +434,122 @@ function DiagramCanvas(props) {
327
434
  return _el$;
328
435
  })();
329
436
  }
437
+ /** Index-keyed, so the DOM (and focus) survives every state update; only attributes change. */
438
+ function Control(props) {
439
+ const kind = () => props.control.kind;
440
+ const asButton = () => props.control;
441
+ const asSearch = () => props.control;
442
+ return createComponent(Switch, { get children() {
443
+ return [
444
+ createComponent(Match, {
445
+ get when() {
446
+ return kind() === "text";
447
+ },
448
+ get children() {
449
+ var _el$2 = _tmpl$2();
450
+ insert(_el$2, () => props.control.text);
451
+ effect(() => setAttribute(_el$2, "data-control", props.control.id));
452
+ return _el$2;
453
+ }
454
+ }),
455
+ createComponent(Match, {
456
+ get when() {
457
+ return kind() === "button";
458
+ },
459
+ get children() {
460
+ var _el$3 = _tmpl$3();
461
+ _el$3.$$click = () => asButton().run();
462
+ insert(_el$3, () => asButton().label);
463
+ effect((_p$) => {
464
+ var _v$ = props.control.id, _v$2 = asButton().disabled, _v$3 = asButton().pressed;
465
+ _v$ !== _p$.e && setAttribute(_el$3, "data-control", _p$.e = _v$);
466
+ _v$2 !== _p$.t && (_el$3.disabled = _p$.t = _v$2);
467
+ _v$3 !== _p$.a && setAttribute(_el$3, "aria-pressed", _p$.a = _v$3);
468
+ return _p$;
469
+ }, {
470
+ e: void 0,
471
+ t: void 0,
472
+ a: void 0
473
+ });
474
+ return _el$3;
475
+ }
476
+ }),
477
+ createComponent(Match, {
478
+ get when() {
479
+ return kind() === "search";
480
+ },
481
+ get children() {
482
+ var _el$4 = _tmpl$4(), _el$5 = _el$4.firstChild, _el$6 = _el$5.nextSibling;
483
+ _el$5.$$input = (event) => asSearch().change(event.currentTarget.value);
484
+ insert(_el$6, () => asSearch().summary);
485
+ insert(_el$4, createComponent(Control, { get control() {
486
+ return asSearch().previous;
487
+ } }), null);
488
+ insert(_el$4, createComponent(Control, { get control() {
489
+ return asSearch().next;
490
+ } }), null);
491
+ effect((_p$) => {
492
+ var _v$4 = asSearch().label, _v$5 = asSearch().label;
493
+ _v$4 !== _p$.e && setAttribute(_el$5, "aria-label", _p$.e = _v$4);
494
+ _v$5 !== _p$.t && setAttribute(_el$5, "placeholder", _p$.t = _v$5);
495
+ return _p$;
496
+ }, {
497
+ e: void 0,
498
+ t: void 0
499
+ });
500
+ effect(() => _el$5.value = asSearch().query);
501
+ return _el$4;
502
+ }
503
+ })
504
+ ];
505
+ } });
506
+ }
507
+ /** Optional library toolbar; `include` picks groups. Hosts may build their own from toolbarProps. */
330
508
  function Toolbar(props) {
509
+ const groups = createMemo(() => toolbarGroups(props, props.include));
331
510
  return (() => {
332
- var _el$2 = _tmpl$2(), _el$3 = _el$2.firstChild, _el$4 = _el$3.nextSibling, _el$5 = _el$4.nextSibling;
333
- use((host) => prepareDiagramBlock(host, "toolbar"), _el$2);
334
- _el$3.$$click = () => void props.onUndo();
335
- insert(_el$3, () => props.labels.Undo);
336
- _el$4.$$click = () => void props.onRedo();
337
- insert(_el$4, () => props.labels.Redo);
338
- addEventListener(_el$5, "click", props.onFit, true);
339
- insert(_el$5, () => props.labels["Fit to Window"]);
340
- effect((_p$) => {
341
- var _v$ = !props.canUndo, _v$2 = !props.canRedo;
342
- _v$ !== _p$.e && (_el$3.disabled = _p$.e = _v$);
343
- _v$2 !== _p$.t && (_el$4.disabled = _p$.t = _v$2);
344
- return _p$;
345
- }, {
346
- e: void 0,
347
- t: void 0
348
- });
349
- return _el$2;
511
+ var _el$7 = _tmpl$5();
512
+ use((host) => prepareDiagramBlock(host, "toolbar"), _el$7);
513
+ insert(_el$7, createComponent(Index, {
514
+ get each() {
515
+ return groups();
516
+ },
517
+ children: (group) => (() => {
518
+ var _el$8 = _tmpl$2();
519
+ insert(_el$8, createComponent(Index, {
520
+ get each() {
521
+ return group().controls;
522
+ },
523
+ children: (control) => createComponent(Control, { get control() {
524
+ return control();
525
+ } })
526
+ }));
527
+ effect(() => setAttribute(_el$8, "data-group", group().id));
528
+ return _el$8;
529
+ })()
530
+ }));
531
+ return _el$7;
350
532
  })();
351
533
  }
352
534
  function PageNavigation(props) {
353
535
  return (() => {
354
- var _el$6 = _tmpl$3();
355
- _el$6.addEventListener("change", (event) => props.onPageChange(Number(event.currentTarget.value)));
356
- use((host) => prepareDiagramBlock(host, "tabs"), _el$6);
357
- insert(_el$6, createComponent(For, {
536
+ var _el$9 = _tmpl$6();
537
+ _el$9.addEventListener("change", (event) => props.onPageChange(Number(event.currentTarget.value)));
538
+ use((host) => prepareDiagramBlock(host, "tabs"), _el$9);
539
+ insert(_el$9, createComponent(For, {
358
540
  get each() {
359
541
  return props.pages;
360
542
  },
361
543
  children: (page, index) => (() => {
362
- var _el$7 = _tmpl$4();
363
- insert(_el$7, () => page.name);
364
- effect(() => _el$7.value = index());
365
- return _el$7;
544
+ var _el$0 = _tmpl$7();
545
+ insert(_el$0, () => page.name);
546
+ effect(() => _el$0.value = index());
547
+ return _el$0;
366
548
  })()
367
549
  }));
368
- effect(() => setAttribute(_el$6, "aria-label", props.labels.Page));
369
- effect(() => _el$6.value = props.pageIndex);
370
- return _el$6;
550
+ effect(() => setAttribute(_el$9, "aria-label", props.labels.Page));
551
+ effect(() => _el$9.value = props.pageIndex);
552
+ return _el$9;
371
553
  })();
372
554
  }
373
555
  function Inspector(props) {
@@ -377,12 +559,25 @@ function Inspector(props) {
377
559
  onCleanup(stop);
378
560
  });
379
561
  return (() => {
380
- var _el$8 = _tmpl$();
562
+ var _el$1 = _tmpl$();
381
563
  var _ref$2 = host;
382
- typeof _ref$2 === "function" ? use(_ref$2, _el$8) : host = _el$8;
383
- return _el$8;
564
+ typeof _ref$2 === "function" ? use(_ref$2, _el$1) : host = _el$1;
565
+ return _el$1;
566
+ })();
567
+ }
568
+ function ShapesPane(props) {
569
+ let host;
570
+ createEffect(() => {
571
+ const stop = buildingBlock("mountDiagramShapes")(host, props.controller, { locale: props.locale });
572
+ onCleanup(stop);
573
+ });
574
+ return (() => {
575
+ var _el$10 = _tmpl$();
576
+ var _ref$3 = host;
577
+ typeof _ref$3 === "function" ? use(_ref$3, _el$10) : host = _el$10;
578
+ return _el$10;
384
579
  })();
385
580
  }
386
- delegateEvents(["click"]);
581
+ delegateEvents(["click", "input"]);
387
582
  //#endregion
388
- export { DiagramCanvas, Inspector, PageNavigation, Toolbar, VisioViewer, createViewerBuildingBlocks, createVisioViewerState };
583
+ export { DiagramCanvas, Inspector, PageNavigation, ShapesPane, Toolbar, VisioViewer, createViewerBuildingBlocks, createVisioViewerState };
@@ -1,7 +1,7 @@
1
1
  import * as ui from "ooxml-ui/visio";
2
2
  import { ViewerController, createWorkerParser, mountViewer, propertyKeys } from "ooxml-ui/visio";
3
3
  import { createComponent, escape, ssr, ssrAttribute, ssrHydrationKey, ssrStyle } from "solid-js/web";
4
- import { For, createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js";
4
+ import { For, Index, Match, Switch, createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js";
5
5
  import "ooxml-ui/theme";
6
6
  export * from "ooxml-ui/visio";
7
7
  export * from "visio-core";
@@ -210,10 +210,15 @@ function buildingBlock(key) {
210
210
  if (typeof value !== "function") throw new Error("Update ooxml-ui to use Visio building blocks.");
211
211
  return value;
212
212
  }
213
+ /** The mode a host sees: 'edit' only when permission is granted and the file can be saved back. */
214
+ function effectiveMode(state) {
215
+ return buildingBlock("diagramMode")(state);
216
+ }
213
217
  /** Framework-neutral ownership only; each adapter supplies its own reactive state. */
214
- function createBuildingBlockSession() {
218
+ function createBuildingBlockSession(initial = {}) {
215
219
  const controller = new ViewerController(createWorkerParser());
216
- let options = {};
220
+ controller.canEdit = initial.canEdit === true;
221
+ let options = initial;
217
222
  let source;
218
223
  let host = null;
219
224
  let disposeCanvas;
@@ -237,13 +242,23 @@ function createBuildingBlockSession() {
237
242
  host = node;
238
243
  if (node) disposeCanvas = buildingBlock("mountDiagramCanvas")(node, controller);
239
244
  },
240
- toolbar(locale = options.locale) {
241
- return buildingBlock("diagramToolbarProps")(controller, fit, locale);
245
+ /** Flat control props; pass the framework's latest options so callbacks stay current. */
246
+ toolbar(latest = options) {
247
+ return buildingBlock("diagramToolbarProps")(controller, fit, latest.locale, {
248
+ onOpenFile: latest.onOpenFile,
249
+ onOpenPageSetup: latest.onOpenPageSetup,
250
+ onOpenSettings: latest.onOpenSettings,
251
+ onOpenShareDialog: latest.onOpenShareDialog
252
+ });
253
+ },
254
+ /** Acknowledge a host save: clears dirty and emits the dirty change. */
255
+ markClean() {
256
+ controller.markClean();
242
257
  },
243
258
  update(next) {
244
259
  if (destroyed) return;
245
260
  options = next;
246
- controller.canEdit = next.canEdit !== false;
261
+ controller.canEdit = next.canEdit === true;
247
262
  if (source === next.content) return;
248
263
  source = next.content;
249
264
  controller.cancelLoad();
@@ -265,29 +280,125 @@ function createBuildingBlockSession() {
265
280
  };
266
281
  }
267
282
  //#endregion
283
+ //#region packages/bindings/src/toolbar-controls.ts
284
+ var TOOLBAR_GROUPS = [
285
+ "file",
286
+ "history",
287
+ "zoom",
288
+ "selection",
289
+ "clipboard",
290
+ "tools",
291
+ "search"
292
+ ];
293
+ var fire = (action) => () => {
294
+ Promise.resolve().then(action).catch(() => {});
295
+ };
296
+ var button = (id, label, enabled, action, pressed) => ({
297
+ kind: "button",
298
+ id,
299
+ label,
300
+ disabled: !enabled,
301
+ ...pressed === void 0 ? {} : { pressed },
302
+ run: fire(action)
303
+ });
304
+ /**
305
+ * What the library Toolbar shows, as plain data every framework maps onto its own elements.
306
+ * Every control reflects `toolbarProps`: edit actions are disabled while the diagram is read-only,
307
+ * viewing actions (zoom, fit, search) never are, and a host dialog button appears only when the
308
+ * host supplied its callback.
309
+ */
310
+ function toolbarGroups(props, include = TOOLBAR_GROUPS) {
311
+ const { labels } = props;
312
+ const has = props.pages.length > 0;
313
+ const groups = [];
314
+ const add = (id, controls) => {
315
+ if (include.includes(id) && controls.length) groups.push({
316
+ id,
317
+ controls
318
+ });
319
+ };
320
+ add("file", [
321
+ ...props.onOpenFile ? [button("open", labels.Open, true, props.onOpenFile)] : [],
322
+ ...props.onOpenPageSetup ? [button("page-setup", labels["Page Setup"], has, props.onOpenPageSetup)] : [],
323
+ ...props.onOpenShareDialog ? [button("share", labels.Share, has, props.onOpenShareDialog)] : [],
324
+ ...props.onOpenSettings ? [button("settings", labels.Options, true, props.onOpenSettings)] : []
325
+ ]);
326
+ add("history", [button("undo", labels.Undo, props.canUndo, props.onUndo), button("redo", labels.Redo, props.canRedo, props.onRedo)]);
327
+ add("zoom", [
328
+ button("zoom-out", labels["Zoom Out"], props.canZoomOut, props.onZoomOut),
329
+ {
330
+ kind: "text",
331
+ id: "zoom",
332
+ text: `${Math.round(props.zoom * 100)}%`
333
+ },
334
+ button("zoom-in", labels["Zoom In"], props.canZoomIn, props.onZoomIn),
335
+ button("fit", labels["Fit to Window"], has, props.onFit)
336
+ ]);
337
+ add("selection", [
338
+ button("duplicate", labels.Duplicate, props.canDuplicate, props.onDuplicate),
339
+ button("group", labels.Group, props.canGroup, props.onGroup),
340
+ button("ungroup", labels.Ungroup, props.canUngroup, props.onUngroup),
341
+ button("delete", labels.Delete, props.canDelete, props.onDelete)
342
+ ]);
343
+ add("clipboard", [
344
+ button("cut", labels.Cut, props.canCut, props.onCut),
345
+ button("copy", labels.Copy, props.canCopy, props.onCopy),
346
+ button("paste", labels.Paste, props.canPaste, props.onPaste)
347
+ ]);
348
+ add("tools", props.tools.map((tool) => button(`tool-${tool.id}`, tool.label, tool.id === "pointer" || props.canDraw, () => props.onToolChange(tool.id), tool.active)));
349
+ const { search } = props;
350
+ add("search", [{
351
+ kind: "search",
352
+ id: "search",
353
+ label: labels.Find,
354
+ query: search.query,
355
+ summary: search.query ? search.resultCount ? `${search.activeIndex >= 0 ? search.activeIndex + 1 : "-"} / ${search.resultCount}` : "0" : "",
356
+ previous: button("search-previous", labels["Previous Result"], search.resultCount > 0, props.onPreviousSearchResult),
357
+ next: button("search-next", labels["Next Result"], search.resultCount > 0, props.onNextSearchResult),
358
+ change: (query) => props.onSearchChange(query)
359
+ }]);
360
+ return groups;
361
+ }
362
+ //#endregion
268
363
  //#region packages/solid/src/building-blocks.tsx
269
364
  var _tmpl$ = ["<div", "></div>"];
270
365
  var _tmpl$2 = [
271
- "<div",
272
- " role=\"toolbar\"><button type=\"button\"",
366
+ "<span",
273
367
  ">",
274
- "</button><button type=\"button\"",
275
- ">",
276
- "</button><button type=\"button\">",
277
- "</button></div>"
368
+ "</span>"
278
369
  ];
279
370
  var _tmpl$3 = [
371
+ "<button",
372
+ " type=\"button\"",
373
+ "",
374
+ ">",
375
+ "</button>"
376
+ ];
377
+ var _tmpl$4 = [
378
+ "<span",
379
+ " data-control=\"search\"><input type=\"search\"",
380
+ "><span aria-live=\"polite\">",
381
+ "</span><!--$-->",
382
+ "<!--/--><!--$-->",
383
+ "<!--/--></span>"
384
+ ];
385
+ var _tmpl$5 = [
386
+ "<div",
387
+ " role=\"toolbar\">",
388
+ "</div>"
389
+ ];
390
+ var _tmpl$6 = [
280
391
  "<select",
281
392
  ">",
282
393
  "</select>"
283
394
  ];
284
- var _tmpl$4 = [
395
+ var _tmpl$7 = [
285
396
  "<option",
286
397
  ">",
287
398
  "</option>"
288
399
  ];
289
400
  function createViewerBuildingBlocks(options = () => ({})) {
290
- const session = createBuildingBlockSession();
401
+ const session = createBuildingBlockSession(options());
291
402
  const [state, setState] = createSignal(session.controller.state);
292
403
  const stop = session.controller.subscribe((value) => setState(() => value));
293
404
  createEffect(() => session.update(options()));
@@ -297,7 +408,7 @@ function createViewerBuildingBlocks(options = () => ({})) {
297
408
  });
298
409
  const toolbarProps = createMemo(() => {
299
410
  state();
300
- return session.toolbar(options().locale);
411
+ return session.toolbar(options());
301
412
  });
302
413
  return {
303
414
  controller: session.controller,
@@ -305,9 +416,18 @@ function createViewerBuildingBlocks(options = () => ({})) {
305
416
  canvasProps: { mount: session.mount },
306
417
  toolbarProps,
307
418
  inspectorProps: { controller: session.controller },
419
+ shapesProps: {
420
+ controller: session.controller,
421
+ get locale() {
422
+ return options().locale;
423
+ }
424
+ },
425
+ /** Acknowledge a host save: clears dirty and fires `onDirtyChange(false)`. */
426
+ markClean: () => session.markClean(),
308
427
  loading: () => state().loading,
309
428
  error: () => state().error ?? state().edit.error,
310
- mode: () => state().canEdit ? "edit" : "view"
429
+ /** Effective permission: host `canEdit` and a drawing that can be saved back. */
430
+ mode: () => effectiveMode(state())
311
431
  };
312
432
  }
313
433
  function DiagramCanvas(props) {
@@ -319,15 +439,67 @@ function DiagramCanvas(props) {
319
439
  });
320
440
  return ssr(_tmpl$, ssrHydrationKey() + ssrAttribute("class", escape(props.class, true), false));
321
441
  }
442
+ /** Index-keyed, so the DOM (and focus) survives every state update; only attributes change. */
443
+ function Control(props) {
444
+ const kind = () => props.control.kind;
445
+ const asButton = () => props.control;
446
+ const asSearch = () => props.control;
447
+ return createComponent(Switch, { get children() {
448
+ return [
449
+ createComponent(Match, {
450
+ get when() {
451
+ return kind() === "text";
452
+ },
453
+ get children() {
454
+ return ssr(_tmpl$2, ssrHydrationKey() + ssrAttribute("data-control", escape(props.control.id, true), false), escape(props.control.text));
455
+ }
456
+ }),
457
+ createComponent(Match, {
458
+ get when() {
459
+ return kind() === "button";
460
+ },
461
+ get children() {
462
+ return ssr(_tmpl$3, ssrHydrationKey(), ssrAttribute("data-control", escape(props.control.id, true), false), ssrAttribute("disabled", asButton().disabled, true) + ssrAttribute("aria-pressed", escape(asButton().pressed, true), false), escape(asButton().label));
463
+ }
464
+ }),
465
+ createComponent(Match, {
466
+ get when() {
467
+ return kind() === "search";
468
+ },
469
+ get children() {
470
+ return ssr(_tmpl$4, ssrHydrationKey(), ssrAttribute("aria-label", escape(asSearch().label, true), false) + ssrAttribute("placeholder", escape(asSearch().label, true), false) + ssrAttribute("value", escape(asSearch().query, true), false), escape(asSearch().summary), escape(createComponent(Control, { get control() {
471
+ return asSearch().previous;
472
+ } })), escape(createComponent(Control, { get control() {
473
+ return asSearch().next;
474
+ } })));
475
+ }
476
+ })
477
+ ];
478
+ } });
479
+ }
480
+ /** Optional library toolbar; `include` picks groups. Hosts may build their own from toolbarProps. */
322
481
  function Toolbar(props) {
323
- return ssr(_tmpl$2, ssrHydrationKey(), ssrAttribute("disabled", !props.canUndo, true), escape(props.labels.Undo), ssrAttribute("disabled", !props.canRedo, true), escape(props.labels.Redo), escape(props.labels["Fit to Window"]));
482
+ const groups = createMemo(() => toolbarGroups(props, props.include));
483
+ return ssr(_tmpl$5, ssrHydrationKey(), escape(createComponent(Index, {
484
+ get each() {
485
+ return groups();
486
+ },
487
+ children: (group) => ssr(_tmpl$2, ssrHydrationKey() + ssrAttribute("data-group", escape(group().id, true), false), escape(createComponent(Index, {
488
+ get each() {
489
+ return group().controls;
490
+ },
491
+ children: (control) => createComponent(Control, { get control() {
492
+ return control();
493
+ } })
494
+ })))
495
+ })));
324
496
  }
325
497
  function PageNavigation(props) {
326
- return ssr(_tmpl$3, ssrHydrationKey() + ssrAttribute("aria-label", escape(props.labels.Page, true), false) + ssrAttribute("value", escape(props.pageIndex, true), false), escape(createComponent(For, {
498
+ return ssr(_tmpl$6, ssrHydrationKey() + ssrAttribute("aria-label", escape(props.labels.Page, true), false) + ssrAttribute("value", escape(props.pageIndex, true), false), escape(createComponent(For, {
327
499
  get each() {
328
500
  return props.pages;
329
501
  },
330
- children: (page, index) => ssr(_tmpl$4, ssrHydrationKey() + ssrAttribute("value", escape(index(), true), false), escape(page.name))
502
+ children: (page, index) => ssr(_tmpl$7, ssrHydrationKey() + ssrAttribute("value", escape(index(), true), false), escape(page.name))
331
503
  })));
332
504
  }
333
505
  function Inspector(props) {
@@ -338,5 +510,13 @@ function Inspector(props) {
338
510
  });
339
511
  return ssr(_tmpl$, ssrHydrationKey());
340
512
  }
513
+ function ShapesPane(props) {
514
+ let host;
515
+ createEffect(() => {
516
+ const stop = buildingBlock("mountDiagramShapes")(host, props.controller, { locale: props.locale });
517
+ onCleanup(stop);
518
+ });
519
+ return ssr(_tmpl$, ssrHydrationKey());
520
+ }
341
521
  //#endregion
342
- export { DiagramCanvas, Inspector, PageNavigation, Toolbar, VisioViewer, createViewerBuildingBlocks, createVisioViewerState };
522
+ export { DiagramCanvas, Inspector, PageNavigation, ShapesPane, Toolbar, VisioViewer, createViewerBuildingBlocks, createVisioViewerState };
@@ -1,23 +1,33 @@
1
1
  import { ViewerController, type VsdxSource } from 'ooxml-ui/visio';
2
2
  import * as ui from 'ooxml-ui/visio';
3
- export interface BuildingBlockOptions {
3
+ /** Host-owned dialogs, as in the PowerPoint building blocks; omitted ones report not-enabled. */
4
+ export interface BuildingBlockHostCallbacks {
5
+ onOpenFile?: (() => void) | undefined;
6
+ onOpenPageSetup?: (() => void) | undefined;
7
+ onOpenSettings?: (() => void) | undefined;
8
+ onOpenShareDialog?: (() => void) | undefined;
9
+ }
10
+ export interface BuildingBlockOptions extends BuildingBlockHostCallbacks {
4
11
  content?: VsdxSource | undefined;
12
+ /** Host edit permission. Read-only until it is `true`, so nothing is editable before the host says so. */
5
13
  canEdit?: boolean | undefined;
6
14
  locale?: string | undefined;
7
15
  onDocumentChange?: ((document: NonNullable<ViewerController['state']['document']>) => void) | undefined;
8
16
  onDirtyChange?: ((dirty: boolean) => void) | undefined;
9
17
  onDocumentError?: ((error: Error) => void) | undefined;
10
18
  }
11
- type Api = Pick<typeof ui, 'mountDiagramCanvas' | 'fitDiagramCanvas' | 'mountDiagramInspector' | 'diagramToolbarProps'>;
19
+ type Api = Pick<typeof ui, 'mountDiagramCanvas' | 'fitDiagramCanvas' | 'mountDiagramInspector' | 'mountDiagramShapes' | 'diagramToolbarProps' | 'diagramMode'>;
12
20
  export declare function buildingBlock<K extends keyof Api>(key: K): Api[K];
21
+ /** The mode a host sees: 'edit' only when permission is granted and the file can be saved back. */
22
+ export declare function effectiveMode(state: ViewerController['state']): 'edit' | 'view';
13
23
  /** Framework-neutral ownership only; each adapter supplies its own reactive state. */
14
- export declare function createBuildingBlockSession(): {
24
+ export declare function createBuildingBlockSession(initial?: BuildingBlockOptions): {
15
25
  controller: ViewerController;
16
26
  mount(node: HTMLElement | null): void;
17
- toolbar(locale?: string | undefined): {
18
- labels: {
19
- [k: string]: string;
20
- };
27
+ /** Flat control props; pass the framework's latest options so callbacks stay current. */
28
+ toolbar(latest?: BuildingBlockOptions): {
29
+ labels: Readonly<Record<"Arc" | "Connector" | "Copy" | "Cut" | "Delete" | "Duplicate" | "Ellipse" | "Find" | "Fit to Window" | "Freeform" | "Group" | "Line" | "Next Result" | "Open" | "Options" | "Page" | "Page Setup" | "Paste" | "Pencil" | "Pointer Tool" | "Previous Result" | "Rectangle" | "Redo" | "Shapes" | "Share" | "Text" | "Undo" | "Ungroup" | "Zoom In" | "Zoom Out", string>>;
30
+ mode: ui.DiagramMode;
21
31
  canEdit: boolean;
22
32
  pageIndex: number;
23
33
  pages: {
@@ -31,23 +41,55 @@ export declare function createBuildingBlockSession(): {
31
41
  canDuplicate: boolean;
32
42
  canGroup: boolean;
33
43
  canUngroup: boolean;
44
+ canDelete: boolean;
45
+ canCut: boolean;
46
+ canCopy: boolean;
47
+ canPaste: boolean;
48
+ canDraw: boolean;
49
+ canZoomIn: boolean;
50
+ canZoomOut: boolean;
51
+ tool: ui.DiagramTool;
52
+ tools: ui.DiagramToolSummary[];
53
+ search: {
54
+ query: string;
55
+ resultCount: number;
56
+ activeIndex: number;
57
+ truncated: boolean;
58
+ };
34
59
  onPageChange: (index: number) => void;
35
60
  onZoomChange: (zoom: number) => void;
61
+ onZoomIn: () => void;
62
+ onZoomOut: () => void;
36
63
  onFit: () => void;
37
64
  onUndo: () => Promise<void>;
38
65
  onRedo: () => Promise<void>;
39
66
  onDuplicate: () => Promise<void>;
40
67
  onGroup: () => Promise<void>;
41
68
  onUngroup: () => Promise<void>;
69
+ onDelete: () => Promise<void>;
70
+ onCut: () => Promise<void>;
71
+ onCopy: () => Promise<void>;
72
+ onPaste: () => Promise<void>;
73
+ onToolChange: (tool: ui.DiagramTool) => void;
42
74
  onTextChange: (pageId: string, shapeId: string, text: string) => Promise<void>;
43
75
  onSearchChange: (query: string) => void;
44
76
  onNextSearchResult: () => void;
45
77
  onPreviousSearchResult: () => void;
78
+ canOpenFile: boolean;
79
+ canOpenPageSetup: boolean;
80
+ canOpenSettings: boolean;
81
+ canOpenShareDialog: boolean;
82
+ onOpenFile?: () => void;
83
+ onOpenPageSetup?: () => void;
84
+ onOpenSettings?: () => void;
85
+ onOpenShareDialog?: () => void;
46
86
  };
87
+ /** Acknowledge a host save: clears dirty and emits the dirty change. */
88
+ markClean(): void;
47
89
  update(next: BuildingBlockOptions): void;
48
90
  destroy(): void;
49
91
  };
50
92
  export type BuildingBlockSession = ReturnType<typeof createBuildingBlockSession>;
51
- export type { DiagramToolbarProps, ViewerController } from 'ooxml-ui/visio';
93
+ export type { DiagramToolbarProps, DiagramToolbarLabels, DiagramToolbarHostCallbacks, DiagramMode, DiagramTool, ViewerController, } from 'ooxml-ui/visio';
52
94
  /** Resolve the new optional-control theme API only when that control is mounted. */
53
95
  export declare function prepareDiagramBlock(host: HTMLElement | null, kind: 'toolbar' | 'tabs'): void;
@@ -0,0 +1,41 @@
1
+ import type { DiagramToolbarProps } from 'ooxml-ui/visio';
2
+ /** The groups of the library toolbar; a host picks the ones it wants with `include`. */
3
+ export type ToolbarGroupId = 'file' | 'history' | 'zoom' | 'selection' | 'clipboard' | 'tools' | 'search';
4
+ export declare const TOOLBAR_GROUPS: readonly ToolbarGroupId[];
5
+ export interface ToolbarButton {
6
+ readonly kind: 'button';
7
+ readonly id: string;
8
+ readonly label: string;
9
+ readonly disabled: boolean;
10
+ /** Set for toggles such as the drawing tools. */
11
+ readonly pressed?: boolean;
12
+ run(): void;
13
+ }
14
+ export interface ToolbarText {
15
+ readonly kind: 'text';
16
+ readonly id: string;
17
+ readonly text: string;
18
+ }
19
+ export interface ToolbarSearch {
20
+ readonly kind: 'search';
21
+ readonly id: 'search';
22
+ readonly label: string;
23
+ readonly query: string;
24
+ /** Result summary for assistive technology, e.g. "2 of 5". */
25
+ readonly summary: string;
26
+ readonly previous: ToolbarButton;
27
+ readonly next: ToolbarButton;
28
+ change(query: string): void;
29
+ }
30
+ export type ToolbarControl = ToolbarButton | ToolbarText | ToolbarSearch;
31
+ export interface ToolbarGroup {
32
+ readonly id: ToolbarGroupId;
33
+ readonly controls: readonly ToolbarControl[];
34
+ }
35
+ /**
36
+ * What the library Toolbar shows, as plain data every framework maps onto its own elements.
37
+ * Every control reflects `toolbarProps`: edit actions are disabled while the diagram is read-only,
38
+ * viewing actions (zoom, fit, search) never are, and a host dialog button appears only when the
39
+ * host supplied its callback.
40
+ */
41
+ export declare function toolbarGroups(props: DiagramToolbarProps, include?: readonly ToolbarGroupId[]): ToolbarGroup[];
@@ -1,5 +1,6 @@
1
1
  import { type Accessor } from 'solid-js';
2
2
  import { type BuildingBlockOptions, type DiagramToolbarProps, type ViewerController } from '../../bindings/src/building-blocks.js';
3
+ import { type ToolbarGroupId } from '../../bindings/src/toolbar-controls.js';
3
4
  export declare function createViewerBuildingBlocks(options?: Accessor<BuildingBlockOptions>): {
4
5
  controller: ViewerController;
5
6
  state: Accessor<import("ooxml-ui/visio").ViewerState>;
@@ -7,9 +8,8 @@ export declare function createViewerBuildingBlocks(options?: Accessor<BuildingBl
7
8
  mount: (node: HTMLElement | null) => void;
8
9
  };
9
10
  toolbarProps: Accessor<{
10
- labels: {
11
- [k: string]: string;
12
- };
11
+ labels: Readonly<Record<"Arc" | "Connector" | "Copy" | "Cut" | "Delete" | "Duplicate" | "Ellipse" | "Find" | "Fit to Window" | "Freeform" | "Group" | "Line" | "Next Result" | "Open" | "Options" | "Page" | "Page Setup" | "Paste" | "Pencil" | "Pointer Tool" | "Previous Result" | "Rectangle" | "Redo" | "Shapes" | "Share" | "Text" | "Undo" | "Ungroup" | "Zoom In" | "Zoom Out", string>>;
12
+ mode: import("ooxml-ui/visio").DiagramMode;
13
13
  canEdit: boolean;
14
14
  pageIndex: number;
15
15
  pages: {
@@ -23,33 +23,78 @@ export declare function createViewerBuildingBlocks(options?: Accessor<BuildingBl
23
23
  canDuplicate: boolean;
24
24
  canGroup: boolean;
25
25
  canUngroup: boolean;
26
+ canDelete: boolean;
27
+ canCut: boolean;
28
+ canCopy: boolean;
29
+ canPaste: boolean;
30
+ canDraw: boolean;
31
+ canZoomIn: boolean;
32
+ canZoomOut: boolean;
33
+ tool: import("ooxml-ui/visio").DiagramTool;
34
+ tools: import("ooxml-ui/visio").DiagramToolSummary[];
35
+ search: {
36
+ query: string;
37
+ resultCount: number;
38
+ activeIndex: number;
39
+ truncated: boolean;
40
+ };
26
41
  onPageChange: (index: number) => void;
27
42
  onZoomChange: (zoom: number) => void;
43
+ onZoomIn: () => void;
44
+ onZoomOut: () => void;
28
45
  onFit: () => void;
29
46
  onUndo: () => Promise<void>;
30
47
  onRedo: () => Promise<void>;
31
48
  onDuplicate: () => Promise<void>;
32
49
  onGroup: () => Promise<void>;
33
50
  onUngroup: () => Promise<void>;
51
+ onDelete: () => Promise<void>;
52
+ onCut: () => Promise<void>;
53
+ onCopy: () => Promise<void>;
54
+ onPaste: () => Promise<void>;
55
+ onToolChange: (tool: import("ooxml-ui/visio").DiagramTool) => void;
34
56
  onTextChange: (pageId: string, shapeId: string, text: string) => Promise<void>;
35
57
  onSearchChange: (query: string) => void;
36
58
  onNextSearchResult: () => void;
37
59
  onPreviousSearchResult: () => void;
60
+ canOpenFile: boolean;
61
+ canOpenPageSetup: boolean;
62
+ canOpenSettings: boolean;
63
+ canOpenShareDialog: boolean;
64
+ onOpenFile?: () => void;
65
+ onOpenPageSetup?: () => void;
66
+ onOpenSettings?: () => void;
67
+ onOpenShareDialog?: () => void;
38
68
  }>;
39
69
  inspectorProps: {
40
70
  controller: ViewerController;
41
71
  };
72
+ shapesProps: {
73
+ controller: ViewerController;
74
+ readonly locale: string | undefined;
75
+ };
76
+ /** Acknowledge a host save: clears dirty and fires `onDirtyChange(false)`. */
77
+ markClean: () => void;
42
78
  loading: () => boolean;
43
79
  error: () => Error | null;
80
+ /** Effective permission: host `canEdit` and a drawing that can be saved back. */
44
81
  mode: () => "edit" | "view";
45
82
  };
46
83
  export declare function DiagramCanvas(props: {
47
84
  mount(node: HTMLElement | null): void;
48
85
  class?: string | undefined;
49
86
  }): import("solid-js").JSX.Element;
50
- export declare function Toolbar(props: DiagramToolbarProps): import("solid-js").JSX.Element;
87
+ /** Optional library toolbar; `include` picks groups. Hosts may build their own from toolbarProps. */
88
+ export declare function Toolbar(props: DiagramToolbarProps & {
89
+ include?: readonly ToolbarGroupId[];
90
+ }): import("solid-js").JSX.Element;
51
91
  export declare function PageNavigation(props: DiagramToolbarProps): import("solid-js").JSX.Element;
52
92
  export declare function Inspector(props: {
53
93
  controller: ViewerController;
54
94
  }): import("solid-js").JSX.Element;
55
- export type { BuildingBlockOptions, DiagramToolbarProps } from '../../bindings/src/building-blocks.js';
95
+ export declare function ShapesPane(props: {
96
+ controller: ViewerController;
97
+ locale?: string | undefined;
98
+ }): import("solid-js").JSX.Element;
99
+ export type { BuildingBlockOptions, BuildingBlockHostCallbacks, DiagramToolbarProps, } from '../../bindings/src/building-blocks.js';
100
+ export type { ToolbarGroupId } from '../../bindings/src/toolbar-controls.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "visio-solid-viewer",
3
- "version": "0.8.0",
3
+ "version": "1.0.1",
4
4
  "description": "Local-first Visio viewer for solid",
5
5
  "homepage": "https://christophervr.github.io/ooxml/visio/",
6
6
  "bugs": {
@@ -32,9 +32,9 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "emf-converter": "4.21.0",
35
- "ooxml-core": "^1.20.0",
36
- "ooxml-ui": "^1.19.0",
37
- "visio-core": "^0.5.0"
35
+ "ooxml-core": "^1.23.0",
36
+ "ooxml-ui": "^1.22.0",
37
+ "visio-core": "^1.0.1"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "solid-js": "^1.9.0"