visio-svelte-viewer 0.8.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/DiagramCanvas.svelte.d.ts +1 -1
- package/dist/Inspector.svelte.d.ts +1 -1
- package/dist/PageNavigation.svelte.d.ts +1 -1
- package/dist/ShapesPane.svelte +7 -0
- package/dist/ShapesPane.svelte.d.ts +4 -0
- package/dist/Toolbar.svelte +21 -4
- package/dist/Toolbar.svelte.d.ts +2 -2
- package/dist/VisioViewer.svelte +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +206 -39
- package/dist/index.server.js +141 -14
- package/dist/index.svelte.js +1 -0
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.js +113 -11
- package/dist/types/packages/bindings/src/building-blocks.d.ts +50 -8
- package/dist/types/packages/bindings/src/toolbar-controls.d.ts +41 -0
- package/dist/types/packages/svelte/src/building-blocks.d.ts +41 -4
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
|
-
import type { ViewerController, DiagramToolbarProps } from './runtime.js';
|
|
2
|
+
import type { ViewerController, DiagramToolbarProps, ToolbarGroupId } from './runtime.js';
|
|
3
3
|
declare const component: Component<{ mount(node: HTMLElement | null): void; class?: string }>;
|
|
4
4
|
export default component;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
|
-
import type { ViewerController, DiagramToolbarProps } from './runtime.js';
|
|
2
|
+
import type { ViewerController, DiagramToolbarProps, ToolbarGroupId } from './runtime.js';
|
|
3
3
|
declare const component: Component<{ controller: ViewerController }>;
|
|
4
4
|
export default component;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
|
-
import type { ViewerController, DiagramToolbarProps } from './runtime.js';
|
|
2
|
+
import type { ViewerController, DiagramToolbarProps, ToolbarGroupId } from './runtime.js';
|
|
3
3
|
declare const component: Component<{ toolbarProps: DiagramToolbarProps }>;
|
|
4
4
|
export default component;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { buildingBlock, type ViewerController } from './runtime.js';
|
|
3
|
+
let { controller, locale }: { controller: ViewerController; locale?: string | undefined } = $props();
|
|
4
|
+
let host: HTMLDivElement;
|
|
5
|
+
$effect(() => buildingBlock('mountDiagramShapes')(host, controller, { locale }));
|
|
6
|
+
</script>
|
|
7
|
+
<div bind:this={host}></div>
|
package/dist/Toolbar.svelte
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { prepareDiagramBlock } from './runtime.js';
|
|
3
|
+
import { toolbarGroups, type ToolbarGroupId } from './runtime.js';
|
|
3
4
|
function theme(host: HTMLElement) { prepareDiagramBlock(host, 'toolbar'); }
|
|
4
5
|
import type { DiagramToolbarProps } from './runtime.js';
|
|
5
|
-
let { toolbarProps }: { toolbarProps: DiagramToolbarProps } = $props();
|
|
6
|
+
let { toolbarProps, include }: { toolbarProps: DiagramToolbarProps; include?: readonly ToolbarGroupId[] } = $props();
|
|
7
|
+
const groups = $derived(toolbarGroups(toolbarProps, include));
|
|
6
8
|
</script>
|
|
7
9
|
<div role="toolbar" use:theme>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
{#each groups as group (group.id)}
|
|
11
|
+
<span data-group={group.id}>
|
|
12
|
+
{#each group.controls as control (control.id)}
|
|
13
|
+
{#if control.kind === 'text'}
|
|
14
|
+
<span data-control={control.id}>{control.text}</span>
|
|
15
|
+
{:else if control.kind === 'button'}
|
|
16
|
+
<button type="button" data-control={control.id} disabled={control.disabled} aria-pressed={control.pressed} onclick={() => control.run()}>{control.label}</button>
|
|
17
|
+
{:else}
|
|
18
|
+
<span data-control="search">
|
|
19
|
+
<input type="search" aria-label={control.label} placeholder={control.label} value={control.query} oninput={(event) => control.change(event.currentTarget.value)} />
|
|
20
|
+
<span aria-live="polite">{control.summary}</span>
|
|
21
|
+
<button type="button" data-control={control.previous.id} disabled={control.previous.disabled} onclick={() => control.previous.run()}>{control.previous.label}</button>
|
|
22
|
+
<button type="button" data-control={control.next.id} disabled={control.next.disabled} onclick={() => control.next.run()}>{control.next.label}</button>
|
|
23
|
+
</span>
|
|
24
|
+
{/if}
|
|
25
|
+
{/each}
|
|
26
|
+
</span>
|
|
27
|
+
{/each}
|
|
11
28
|
</div>
|
package/dist/Toolbar.svelte.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
|
-
import type { ViewerController, DiagramToolbarProps } from './runtime.js';
|
|
3
|
-
declare const component: Component<{ toolbarProps: DiagramToolbarProps }>;
|
|
2
|
+
import type { ViewerController, DiagramToolbarProps, ToolbarGroupId } from './runtime.js';
|
|
3
|
+
declare const component: Component<{ toolbarProps: DiagramToolbarProps; include?: readonly ToolbarGroupId[] }>;
|
|
4
4
|
export default component;
|
package/dist/VisioViewer.svelte
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import { readonly, writable } from 'svelte/store';
|
|
4
4
|
import { mountFrameworkViewer, viewerHandle, viewerOptions, viewerStateSource, type ViewerState, type MountedViewer, type ViewerProps, type VsdxSource, type VisioEdit, type VisioShapeSelection, type SvgExportOptions, type CurrentPagePrintSnapshotOptions } from './runtime.js';
|
|
5
5
|
type Props = ViewerProps & { class?: string; style?: string; 'aria-label'?: string };
|
|
6
|
-
let { document, pageIndex, zoom, showToolbar, canEdit, ribbonAddIns, events, class: className, style, 'aria-label': ariaLabel }: Props = $props();
|
|
7
|
-
const options = $derived({ document, pageIndex, zoom, showToolbar, canEdit, ribbonAddIns, events } satisfies Required<ViewerProps>);
|
|
6
|
+
let { document, pageIndex, zoom, showToolbar, canEdit, ribbonAddIns, collaboration, events, class: className, style, 'aria-label': ariaLabel }: Props = $props();
|
|
7
|
+
const options = $derived({ document, pageIndex, zoom, showToolbar, canEdit, ribbonAddIns, collaboration, events } satisfies Required<ViewerProps>);
|
|
8
8
|
let binding: MountedViewer | undefined;
|
|
9
9
|
const handle = viewerHandle(() => binding);
|
|
10
10
|
// The component owns its state store, so subscribers made before mount still see updates.
|
package/dist/index.d.ts
CHANGED
|
@@ -6,3 +6,4 @@ export { default as DiagramCanvas } from './DiagramCanvas.svelte';
|
|
|
6
6
|
export { default as Toolbar } from './Toolbar.svelte';
|
|
7
7
|
export { default as PageNavigation } from './PageNavigation.svelte';
|
|
8
8
|
export { default as Inspector } from './Inspector.svelte';
|
|
9
|
+
export { default as ShapesPane } from './ShapesPane.svelte';
|
package/dist/index.js
CHANGED
|
@@ -149,7 +149,7 @@ function viewerStateSource(current) {
|
|
|
149
149
|
}
|
|
150
150
|
//#endregion
|
|
151
151
|
//#region packages/bindings/src/VisioViewer.svelte
|
|
152
|
-
var root$
|
|
152
|
+
var root$5 = $.from_html(`<div></div>`);
|
|
153
153
|
function VisioViewer($$anchor, $$props) {
|
|
154
154
|
$.push($$props, true);
|
|
155
155
|
const options = $.derived(() => ({
|
|
@@ -159,6 +159,7 @@ function VisioViewer($$anchor, $$props) {
|
|
|
159
159
|
showToolbar: $$props.showToolbar,
|
|
160
160
|
canEdit: $$props.canEdit,
|
|
161
161
|
ribbonAddIns: $$props.ribbonAddIns,
|
|
162
|
+
collaboration: $$props.collaboration,
|
|
162
163
|
events: $$props.events
|
|
163
164
|
}));
|
|
164
165
|
let binding;
|
|
@@ -273,7 +274,7 @@ function VisioViewer($$anchor, $$props) {
|
|
|
273
274
|
exportSvg,
|
|
274
275
|
createPrintSnapshot
|
|
275
276
|
};
|
|
276
|
-
var div = root$
|
|
277
|
+
var div = root$5();
|
|
277
278
|
$.action(div, ($$node, $$action_arg) => attach?.($$node, $$action_arg), () => $.get(options));
|
|
278
279
|
$.template_effect(() => {
|
|
279
280
|
$.set_class(div, 1, $.clsx($$props.class));
|
|
@@ -290,10 +291,15 @@ function buildingBlock(key) {
|
|
|
290
291
|
if (typeof value !== "function") throw new Error("Update ooxml-ui to use Visio building blocks.");
|
|
291
292
|
return value;
|
|
292
293
|
}
|
|
294
|
+
/** The mode a host sees: 'edit' only when permission is granted and the file can be saved back. */
|
|
295
|
+
function effectiveMode(state) {
|
|
296
|
+
return buildingBlock("diagramMode")(state);
|
|
297
|
+
}
|
|
293
298
|
/** Framework-neutral ownership only; each adapter supplies its own reactive state. */
|
|
294
|
-
function createBuildingBlockSession() {
|
|
299
|
+
function createBuildingBlockSession(initial = {}) {
|
|
295
300
|
const controller = new ViewerController(createWorkerParser());
|
|
296
|
-
|
|
301
|
+
controller.canEdit = initial.canEdit === true;
|
|
302
|
+
let options = initial;
|
|
297
303
|
let source;
|
|
298
304
|
let host = null;
|
|
299
305
|
let disposeCanvas;
|
|
@@ -317,13 +323,23 @@ function createBuildingBlockSession() {
|
|
|
317
323
|
host = node;
|
|
318
324
|
if (node) disposeCanvas = buildingBlock("mountDiagramCanvas")(node, controller);
|
|
319
325
|
},
|
|
320
|
-
|
|
321
|
-
|
|
326
|
+
/** Flat control props; pass the framework's latest options so callbacks stay current. */
|
|
327
|
+
toolbar(latest = options) {
|
|
328
|
+
return buildingBlock("diagramToolbarProps")(controller, fit, latest.locale, {
|
|
329
|
+
onOpenFile: latest.onOpenFile,
|
|
330
|
+
onOpenPageSetup: latest.onOpenPageSetup,
|
|
331
|
+
onOpenSettings: latest.onOpenSettings,
|
|
332
|
+
onOpenShareDialog: latest.onOpenShareDialog
|
|
333
|
+
});
|
|
334
|
+
},
|
|
335
|
+
/** Acknowledge a host save: clears dirty and emits the dirty change. */
|
|
336
|
+
markClean() {
|
|
337
|
+
controller.markClean();
|
|
322
338
|
},
|
|
323
339
|
update(next) {
|
|
324
340
|
if (destroyed) return;
|
|
325
341
|
options = next;
|
|
326
|
-
controller.canEdit = next.canEdit
|
|
342
|
+
controller.canEdit = next.canEdit === true;
|
|
327
343
|
if (source === next.content) return;
|
|
328
344
|
source = next.content;
|
|
329
345
|
controller.cancelLoad();
|
|
@@ -357,9 +373,9 @@ function prepareDiagramBlock(host, kind) {
|
|
|
357
373
|
function createViewerBuildingBlocks(options = {}) {
|
|
358
374
|
const source = "subscribe" in options ? options : void 0;
|
|
359
375
|
const initial = source ? get(source) : options;
|
|
360
|
-
const session = createBuildingBlockSession();
|
|
376
|
+
const session = createBuildingBlockSession(initial);
|
|
361
377
|
const state = writable(session.controller.state);
|
|
362
|
-
const
|
|
378
|
+
const latest = writable(initial);
|
|
363
379
|
const stop = session.controller.subscribe((value) => state.set(value));
|
|
364
380
|
let stopOptions = () => {};
|
|
365
381
|
onDestroy(() => {
|
|
@@ -368,7 +384,7 @@ function createViewerBuildingBlocks(options = {}) {
|
|
|
368
384
|
session.destroy();
|
|
369
385
|
});
|
|
370
386
|
const update = (next) => {
|
|
371
|
-
|
|
387
|
+
latest.set(next);
|
|
372
388
|
session.update(next);
|
|
373
389
|
};
|
|
374
390
|
if (source) stopOptions = source.subscribe(update);
|
|
@@ -376,18 +392,25 @@ function createViewerBuildingBlocks(options = {}) {
|
|
|
376
392
|
return {
|
|
377
393
|
controller: session.controller,
|
|
378
394
|
state: { subscribe: state.subscribe },
|
|
379
|
-
toolbarProps: derived([state,
|
|
395
|
+
toolbarProps: derived([state, latest], ([, next]) => session.toolbar(next)),
|
|
380
396
|
loading: derived(state, (value) => value.loading),
|
|
381
397
|
error: derived(state, (value) => value.error ?? value.edit.error),
|
|
382
|
-
|
|
398
|
+
/** Effective permission: host `canEdit` and a drawing that can be saved back. */
|
|
399
|
+
mode: derived(state, (value) => effectiveMode(value)),
|
|
383
400
|
canvasProps: { mount: session.mount },
|
|
384
401
|
inspectorProps: { controller: session.controller },
|
|
402
|
+
shapesProps: derived(latest, (next) => ({
|
|
403
|
+
controller: session.controller,
|
|
404
|
+
locale: next.locale
|
|
405
|
+
})),
|
|
406
|
+
/** Acknowledge a host save: clears dirty and fires `onDirtyChange(false)`. */
|
|
407
|
+
markClean: () => session.markClean(),
|
|
385
408
|
update
|
|
386
409
|
};
|
|
387
410
|
}
|
|
388
411
|
//#endregion
|
|
389
412
|
//#region packages/svelte/src/DiagramCanvas.svelte
|
|
390
|
-
var root$
|
|
413
|
+
var root$4 = $.from_html(`<div></div>`);
|
|
391
414
|
function DiagramCanvas($$anchor, $$props) {
|
|
392
415
|
$.push($$props, true);
|
|
393
416
|
let host;
|
|
@@ -396,48 +419,180 @@ function DiagramCanvas($$anchor, $$props) {
|
|
|
396
419
|
current(host);
|
|
397
420
|
return () => current(null);
|
|
398
421
|
});
|
|
399
|
-
var div = root$
|
|
422
|
+
var div = root$4();
|
|
400
423
|
$.bind_this(div, ($$value) => host = $$value, () => host);
|
|
401
424
|
$.template_effect(() => $.set_class(div, 1, $.clsx($$props.class)));
|
|
402
425
|
$.append($$anchor, div);
|
|
403
426
|
$.pop();
|
|
404
427
|
}
|
|
405
428
|
//#endregion
|
|
429
|
+
//#region packages/bindings/src/toolbar-controls.ts
|
|
430
|
+
var TOOLBAR_GROUPS = [
|
|
431
|
+
"file",
|
|
432
|
+
"history",
|
|
433
|
+
"zoom",
|
|
434
|
+
"selection",
|
|
435
|
+
"clipboard",
|
|
436
|
+
"tools",
|
|
437
|
+
"search"
|
|
438
|
+
];
|
|
439
|
+
var fire = (action) => () => {
|
|
440
|
+
Promise.resolve().then(action).catch(() => {});
|
|
441
|
+
};
|
|
442
|
+
var button = (id, label, enabled, action, pressed) => ({
|
|
443
|
+
kind: "button",
|
|
444
|
+
id,
|
|
445
|
+
label,
|
|
446
|
+
disabled: !enabled,
|
|
447
|
+
...pressed === void 0 ? {} : { pressed },
|
|
448
|
+
run: fire(action)
|
|
449
|
+
});
|
|
450
|
+
/**
|
|
451
|
+
* What the library Toolbar shows, as plain data every framework maps onto its own elements.
|
|
452
|
+
* Every control reflects `toolbarProps`: edit actions are disabled while the diagram is read-only,
|
|
453
|
+
* viewing actions (zoom, fit, search) never are, and a host dialog button appears only when the
|
|
454
|
+
* host supplied its callback.
|
|
455
|
+
*/
|
|
456
|
+
function toolbarGroups(props, include = TOOLBAR_GROUPS) {
|
|
457
|
+
const { labels } = props;
|
|
458
|
+
const has = props.pages.length > 0;
|
|
459
|
+
const groups = [];
|
|
460
|
+
const add = (id, controls) => {
|
|
461
|
+
if (include.includes(id) && controls.length) groups.push({
|
|
462
|
+
id,
|
|
463
|
+
controls
|
|
464
|
+
});
|
|
465
|
+
};
|
|
466
|
+
add("file", [
|
|
467
|
+
...props.onOpenFile ? [button("open", labels.Open, true, props.onOpenFile)] : [],
|
|
468
|
+
...props.onOpenPageSetup ? [button("page-setup", labels["Page Setup"], has, props.onOpenPageSetup)] : [],
|
|
469
|
+
...props.onOpenShareDialog ? [button("share", labels.Share, has, props.onOpenShareDialog)] : [],
|
|
470
|
+
...props.onOpenSettings ? [button("settings", labels.Options, true, props.onOpenSettings)] : []
|
|
471
|
+
]);
|
|
472
|
+
add("history", [button("undo", labels.Undo, props.canUndo, props.onUndo), button("redo", labels.Redo, props.canRedo, props.onRedo)]);
|
|
473
|
+
add("zoom", [
|
|
474
|
+
button("zoom-out", labels["Zoom Out"], props.canZoomOut, props.onZoomOut),
|
|
475
|
+
{
|
|
476
|
+
kind: "text",
|
|
477
|
+
id: "zoom",
|
|
478
|
+
text: `${Math.round(props.zoom * 100)}%`
|
|
479
|
+
},
|
|
480
|
+
button("zoom-in", labels["Zoom In"], props.canZoomIn, props.onZoomIn),
|
|
481
|
+
button("fit", labels["Fit to Window"], has, props.onFit)
|
|
482
|
+
]);
|
|
483
|
+
add("selection", [
|
|
484
|
+
button("duplicate", labels.Duplicate, props.canDuplicate, props.onDuplicate),
|
|
485
|
+
button("group", labels.Group, props.canGroup, props.onGroup),
|
|
486
|
+
button("ungroup", labels.Ungroup, props.canUngroup, props.onUngroup),
|
|
487
|
+
button("delete", labels.Delete, props.canDelete, props.onDelete)
|
|
488
|
+
]);
|
|
489
|
+
add("clipboard", [
|
|
490
|
+
button("cut", labels.Cut, props.canCut, props.onCut),
|
|
491
|
+
button("copy", labels.Copy, props.canCopy, props.onCopy),
|
|
492
|
+
button("paste", labels.Paste, props.canPaste, props.onPaste)
|
|
493
|
+
]);
|
|
494
|
+
add("tools", props.tools.map((tool) => button(`tool-${tool.id}`, tool.label, tool.id === "pointer" || props.canDraw, () => props.onToolChange(tool.id), tool.active)));
|
|
495
|
+
const { search } = props;
|
|
496
|
+
add("search", [{
|
|
497
|
+
kind: "search",
|
|
498
|
+
id: "search",
|
|
499
|
+
label: labels.Find,
|
|
500
|
+
query: search.query,
|
|
501
|
+
summary: search.query ? search.resultCount ? `${search.activeIndex >= 0 ? search.activeIndex + 1 : "-"} / ${search.resultCount}` : "0" : "",
|
|
502
|
+
previous: button("search-previous", labels["Previous Result"], search.resultCount > 0, props.onPreviousSearchResult),
|
|
503
|
+
next: button("search-next", labels["Next Result"], search.resultCount > 0, props.onNextSearchResult),
|
|
504
|
+
change: (query) => props.onSearchChange(query)
|
|
505
|
+
}]);
|
|
506
|
+
return groups;
|
|
507
|
+
}
|
|
508
|
+
//#endregion
|
|
406
509
|
//#region packages/svelte/src/Toolbar.svelte
|
|
407
|
-
var root$
|
|
510
|
+
var root$3 = $.from_html(`<span> </span>`);
|
|
511
|
+
var root_1$1 = $.from_html(`<button type="button"> </button>`);
|
|
512
|
+
var root_2 = $.from_html(`<span data-control="search"><input type="search"/> <span aria-live="polite"> </span> <button type="button"> </button> <button type="button"> </button></span>`);
|
|
513
|
+
var root_3 = $.from_html(`<span></span>`);
|
|
514
|
+
var root_4 = $.from_html(`<div role="toolbar"></div>`);
|
|
408
515
|
function Toolbar($$anchor, $$props) {
|
|
409
516
|
$.push($$props, true);
|
|
410
517
|
function theme(host) {
|
|
411
518
|
prepareDiagramBlock(host, "toolbar");
|
|
412
519
|
}
|
|
413
|
-
|
|
414
|
-
var
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
520
|
+
const groups = $.derived(() => toolbarGroups($$props.toolbarProps, $$props.include));
|
|
521
|
+
var div = root_4();
|
|
522
|
+
$.each(div, 21, () => $.get(groups), (group) => group.id, ($$anchor, group) => {
|
|
523
|
+
var span = root_3();
|
|
524
|
+
$.each(span, 21, () => $.get(group).controls, (control) => control.id, ($$anchor, control) => {
|
|
525
|
+
var fragment = $.comment();
|
|
526
|
+
var node = $.first_child(fragment);
|
|
527
|
+
var consequent = ($$anchor) => {
|
|
528
|
+
var span_1 = root$3();
|
|
529
|
+
var text = $.only_child(span_1, true);
|
|
530
|
+
$.template_effect(() => {
|
|
531
|
+
$.set_attribute(span_1, "data-control", $.get(control).id);
|
|
532
|
+
$.set_text(text, $.get(control).text);
|
|
533
|
+
});
|
|
534
|
+
$.append($$anchor, span_1);
|
|
535
|
+
};
|
|
536
|
+
var consequent_1 = ($$anchor) => {
|
|
537
|
+
var button = root_1$1();
|
|
538
|
+
var text_1 = $.only_child(button, true);
|
|
539
|
+
$.template_effect(() => {
|
|
540
|
+
$.set_attribute(button, "data-control", $.get(control).id);
|
|
541
|
+
button.disabled = $.get(control).disabled;
|
|
542
|
+
$.set_attribute(button, "aria-pressed", $.get(control).pressed);
|
|
543
|
+
$.set_text(text_1, $.get(control).label);
|
|
544
|
+
});
|
|
545
|
+
$.delegated("click", button, () => $.get(control).run());
|
|
546
|
+
$.append($$anchor, button);
|
|
547
|
+
};
|
|
548
|
+
var alternate = ($$anchor) => {
|
|
549
|
+
var span_2 = root_2();
|
|
550
|
+
var input = $.child(span_2);
|
|
551
|
+
$.remove_input_defaults(input);
|
|
552
|
+
var span_3 = $.sibling(input, 2);
|
|
553
|
+
var text_2 = $.only_child(span_3, true);
|
|
554
|
+
var button_1 = $.sibling(span_3, 2);
|
|
555
|
+
var text_3 = $.only_child(button_1, true);
|
|
556
|
+
var button_2 = $.sibling(button_1, 2);
|
|
557
|
+
var text_4 = $.only_child(button_2, true);
|
|
558
|
+
$.reset(span_2);
|
|
559
|
+
$.template_effect(() => {
|
|
560
|
+
$.set_attribute(input, "aria-label", $.get(control).label);
|
|
561
|
+
$.set_attribute(input, "placeholder", $.get(control).label);
|
|
562
|
+
$.set_value(input, $.get(control).query);
|
|
563
|
+
$.set_text(text_2, $.get(control).summary);
|
|
564
|
+
$.set_attribute(button_1, "data-control", $.get(control).previous.id);
|
|
565
|
+
button_1.disabled = $.get(control).previous.disabled;
|
|
566
|
+
$.set_text(text_3, $.get(control).previous.label);
|
|
567
|
+
$.set_attribute(button_2, "data-control", $.get(control).next.id);
|
|
568
|
+
button_2.disabled = $.get(control).next.disabled;
|
|
569
|
+
$.set_text(text_4, $.get(control).next.label);
|
|
570
|
+
});
|
|
571
|
+
$.delegated("input", input, (event) => $.get(control).change(event.currentTarget.value));
|
|
572
|
+
$.delegated("click", button_1, () => $.get(control).previous.run());
|
|
573
|
+
$.delegated("click", button_2, () => $.get(control).next.run());
|
|
574
|
+
$.append($$anchor, span_2);
|
|
575
|
+
};
|
|
576
|
+
$.if(node, ($$render) => {
|
|
577
|
+
if ($.get(control).kind === "text") $$render(consequent);
|
|
578
|
+
else if ($.get(control).kind === "button") $$render(consequent_1, 1);
|
|
579
|
+
else $$render(alternate, -1);
|
|
580
|
+
});
|
|
581
|
+
$.append($$anchor, fragment);
|
|
582
|
+
});
|
|
583
|
+
$.reset(span);
|
|
584
|
+
$.template_effect(() => $.set_attribute(span, "data-group", $.get(group).id));
|
|
585
|
+
$.append($$anchor, span);
|
|
586
|
+
});
|
|
420
587
|
$.reset(div);
|
|
421
588
|
$.action(div, ($$node) => theme?.($$node));
|
|
422
|
-
$.template_effect(() => {
|
|
423
|
-
button.disabled = !$$props.toolbarProps.canUndo;
|
|
424
|
-
$.set_text(text, $$props.toolbarProps.labels.Undo);
|
|
425
|
-
button_1.disabled = !$$props.toolbarProps.canRedo;
|
|
426
|
-
$.set_text(text_1, $$props.toolbarProps.labels.Redo);
|
|
427
|
-
$.set_text(text_2, $$props.toolbarProps.labels["Fit to Window"]);
|
|
428
|
-
});
|
|
429
|
-
$.delegated("click", button, () => void $$props.toolbarProps.onUndo());
|
|
430
|
-
$.delegated("click", button_1, () => void $$props.toolbarProps.onRedo());
|
|
431
|
-
$.delegated("click", button_2, function(...$$args) {
|
|
432
|
-
$$props.toolbarProps.onFit?.apply(this, $$args);
|
|
433
|
-
});
|
|
434
589
|
$.append($$anchor, div);
|
|
435
590
|
$.pop();
|
|
436
591
|
}
|
|
437
|
-
$.delegate(["click"]);
|
|
592
|
+
$.delegate(["click", "input"]);
|
|
438
593
|
//#endregion
|
|
439
594
|
//#region packages/svelte/src/PageNavigation.svelte
|
|
440
|
-
var root$
|
|
595
|
+
var root$2 = $.from_html(`<option> </option>`);
|
|
441
596
|
var root_1 = $.from_html(`<select></select>`);
|
|
442
597
|
function PageNavigation($$anchor, $$props) {
|
|
443
598
|
$.push($$props, true);
|
|
@@ -446,7 +601,7 @@ function PageNavigation($$anchor, $$props) {
|
|
|
446
601
|
}
|
|
447
602
|
var select = root_1();
|
|
448
603
|
$.each(select, 23, () => $$props.toolbarProps.pages, (page) => page.id, ($$anchor, page, index) => {
|
|
449
|
-
var option = root$
|
|
604
|
+
var option = root$2();
|
|
450
605
|
var text = $.only_child(option, true);
|
|
451
606
|
var option_value = {};
|
|
452
607
|
$.template_effect(() => {
|
|
@@ -470,15 +625,27 @@ function PageNavigation($$anchor, $$props) {
|
|
|
470
625
|
$.delegate(["change"]);
|
|
471
626
|
//#endregion
|
|
472
627
|
//#region packages/svelte/src/Inspector.svelte
|
|
473
|
-
var root = $.from_html(`<div></div>`);
|
|
628
|
+
var root$1 = $.from_html(`<div></div>`);
|
|
474
629
|
function Inspector($$anchor, $$props) {
|
|
475
630
|
$.push($$props, true);
|
|
476
631
|
let host;
|
|
477
632
|
$.user_effect(() => buildingBlock("mountDiagramInspector")(host, $$props.controller));
|
|
633
|
+
var div = root$1();
|
|
634
|
+
$.bind_this(div, ($$value) => host = $$value, () => host);
|
|
635
|
+
$.append($$anchor, div);
|
|
636
|
+
$.pop();
|
|
637
|
+
}
|
|
638
|
+
//#endregion
|
|
639
|
+
//#region packages/svelte/src/ShapesPane.svelte
|
|
640
|
+
var root = $.from_html(`<div></div>`);
|
|
641
|
+
function ShapesPane($$anchor, $$props) {
|
|
642
|
+
$.push($$props, true);
|
|
643
|
+
let host;
|
|
644
|
+
$.user_effect(() => buildingBlock("mountDiagramShapes")(host, $$props.controller, { locale: $$props.locale }));
|
|
478
645
|
var div = root();
|
|
479
646
|
$.bind_this(div, ($$value) => host = $$value, () => host);
|
|
480
647
|
$.append($$anchor, div);
|
|
481
648
|
$.pop();
|
|
482
649
|
}
|
|
483
650
|
//#endregion
|
|
484
|
-
export { DiagramCanvas, Inspector, PageNavigation, Toolbar, VisioViewer, VisioViewer as default, createViewerBuildingBlocks };
|
|
651
|
+
export { DiagramCanvas, Inspector, PageNavigation, ShapesPane, Toolbar, VisioViewer, VisioViewer as default, createViewerBuildingBlocks };
|
package/dist/index.server.js
CHANGED
|
@@ -87,7 +87,7 @@ function viewerHandle(current) {
|
|
|
87
87
|
//#region packages/bindings/src/VisioViewer.svelte
|
|
88
88
|
function VisioViewer($$renderer, $$props) {
|
|
89
89
|
$$renderer.component(($$renderer) => {
|
|
90
|
-
let { document, pageIndex, zoom, showToolbar, canEdit, ribbonAddIns, events, class: className, style, "aria-label": ariaLabel } = $$props;
|
|
90
|
+
let { document, pageIndex, zoom, showToolbar, canEdit, ribbonAddIns, collaboration, events, class: className, style, "aria-label": ariaLabel } = $$props;
|
|
91
91
|
$.derived(() => ({
|
|
92
92
|
document,
|
|
93
93
|
pageIndex,
|
|
@@ -95,6 +95,7 @@ function VisioViewer($$renderer, $$props) {
|
|
|
95
95
|
showToolbar,
|
|
96
96
|
canEdit,
|
|
97
97
|
ribbonAddIns,
|
|
98
|
+
collaboration,
|
|
98
99
|
events
|
|
99
100
|
}));
|
|
100
101
|
let binding;
|
|
@@ -201,10 +202,15 @@ function buildingBlock(key) {
|
|
|
201
202
|
if (typeof value !== "function") throw new Error("Update ooxml-ui to use Visio building blocks.");
|
|
202
203
|
return value;
|
|
203
204
|
}
|
|
205
|
+
/** The mode a host sees: 'edit' only when permission is granted and the file can be saved back. */
|
|
206
|
+
function effectiveMode(state) {
|
|
207
|
+
return buildingBlock("diagramMode")(state);
|
|
208
|
+
}
|
|
204
209
|
/** Framework-neutral ownership only; each adapter supplies its own reactive state. */
|
|
205
|
-
function createBuildingBlockSession() {
|
|
210
|
+
function createBuildingBlockSession(initial = {}) {
|
|
206
211
|
const controller = new ViewerController(createWorkerParser());
|
|
207
|
-
|
|
212
|
+
controller.canEdit = initial.canEdit === true;
|
|
213
|
+
let options = initial;
|
|
208
214
|
let source;
|
|
209
215
|
let host = null;
|
|
210
216
|
let disposeCanvas;
|
|
@@ -228,13 +234,23 @@ function createBuildingBlockSession() {
|
|
|
228
234
|
host = node;
|
|
229
235
|
if (node) disposeCanvas = buildingBlock("mountDiagramCanvas")(node, controller);
|
|
230
236
|
},
|
|
231
|
-
|
|
232
|
-
|
|
237
|
+
/** Flat control props; pass the framework's latest options so callbacks stay current. */
|
|
238
|
+
toolbar(latest = options) {
|
|
239
|
+
return buildingBlock("diagramToolbarProps")(controller, fit, latest.locale, {
|
|
240
|
+
onOpenFile: latest.onOpenFile,
|
|
241
|
+
onOpenPageSetup: latest.onOpenPageSetup,
|
|
242
|
+
onOpenSettings: latest.onOpenSettings,
|
|
243
|
+
onOpenShareDialog: latest.onOpenShareDialog
|
|
244
|
+
});
|
|
245
|
+
},
|
|
246
|
+
/** Acknowledge a host save: clears dirty and emits the dirty change. */
|
|
247
|
+
markClean() {
|
|
248
|
+
controller.markClean();
|
|
233
249
|
},
|
|
234
250
|
update(next) {
|
|
235
251
|
if (destroyed) return;
|
|
236
252
|
options = next;
|
|
237
|
-
controller.canEdit = next.canEdit
|
|
253
|
+
controller.canEdit = next.canEdit === true;
|
|
238
254
|
if (source === next.content) return;
|
|
239
255
|
source = next.content;
|
|
240
256
|
controller.cancelLoad();
|
|
@@ -261,9 +277,9 @@ function createBuildingBlockSession() {
|
|
|
261
277
|
function createViewerBuildingBlocks(options = {}) {
|
|
262
278
|
const source = "subscribe" in options ? options : void 0;
|
|
263
279
|
const initial = source ? get(source) : options;
|
|
264
|
-
const session = createBuildingBlockSession();
|
|
280
|
+
const session = createBuildingBlockSession(initial);
|
|
265
281
|
const state = writable(session.controller.state);
|
|
266
|
-
const
|
|
282
|
+
const latest = writable(initial);
|
|
267
283
|
const stop = session.controller.subscribe((value) => state.set(value));
|
|
268
284
|
let stopOptions = () => {};
|
|
269
285
|
onDestroy(() => {
|
|
@@ -272,7 +288,7 @@ function createViewerBuildingBlocks(options = {}) {
|
|
|
272
288
|
session.destroy();
|
|
273
289
|
});
|
|
274
290
|
const update = (next) => {
|
|
275
|
-
|
|
291
|
+
latest.set(next);
|
|
276
292
|
session.update(next);
|
|
277
293
|
};
|
|
278
294
|
if (source) stopOptions = source.subscribe(update);
|
|
@@ -280,12 +296,19 @@ function createViewerBuildingBlocks(options = {}) {
|
|
|
280
296
|
return {
|
|
281
297
|
controller: session.controller,
|
|
282
298
|
state: { subscribe: state.subscribe },
|
|
283
|
-
toolbarProps: derived([state,
|
|
299
|
+
toolbarProps: derived([state, latest], ([, next]) => session.toolbar(next)),
|
|
284
300
|
loading: derived(state, (value) => value.loading),
|
|
285
301
|
error: derived(state, (value) => value.error ?? value.edit.error),
|
|
286
|
-
|
|
302
|
+
/** Effective permission: host `canEdit` and a drawing that can be saved back. */
|
|
303
|
+
mode: derived(state, (value) => effectiveMode(value)),
|
|
287
304
|
canvasProps: { mount: session.mount },
|
|
288
305
|
inspectorProps: { controller: session.controller },
|
|
306
|
+
shapesProps: derived(latest, (next) => ({
|
|
307
|
+
controller: session.controller,
|
|
308
|
+
locale: next.locale
|
|
309
|
+
})),
|
|
310
|
+
/** Acknowledge a host save: clears dirty and fires `onDirtyChange(false)`. */
|
|
311
|
+
markClean: () => session.markClean(),
|
|
289
312
|
update
|
|
290
313
|
};
|
|
291
314
|
}
|
|
@@ -298,11 +321,107 @@ function DiagramCanvas($$renderer, $$props) {
|
|
|
298
321
|
});
|
|
299
322
|
}
|
|
300
323
|
//#endregion
|
|
324
|
+
//#region packages/bindings/src/toolbar-controls.ts
|
|
325
|
+
var TOOLBAR_GROUPS = [
|
|
326
|
+
"file",
|
|
327
|
+
"history",
|
|
328
|
+
"zoom",
|
|
329
|
+
"selection",
|
|
330
|
+
"clipboard",
|
|
331
|
+
"tools",
|
|
332
|
+
"search"
|
|
333
|
+
];
|
|
334
|
+
var fire = (action) => () => {
|
|
335
|
+
Promise.resolve().then(action).catch(() => {});
|
|
336
|
+
};
|
|
337
|
+
var button = (id, label, enabled, action, pressed) => ({
|
|
338
|
+
kind: "button",
|
|
339
|
+
id,
|
|
340
|
+
label,
|
|
341
|
+
disabled: !enabled,
|
|
342
|
+
...pressed === void 0 ? {} : { pressed },
|
|
343
|
+
run: fire(action)
|
|
344
|
+
});
|
|
345
|
+
/**
|
|
346
|
+
* What the library Toolbar shows, as plain data every framework maps onto its own elements.
|
|
347
|
+
* Every control reflects `toolbarProps`: edit actions are disabled while the diagram is read-only,
|
|
348
|
+
* viewing actions (zoom, fit, search) never are, and a host dialog button appears only when the
|
|
349
|
+
* host supplied its callback.
|
|
350
|
+
*/
|
|
351
|
+
function toolbarGroups(props, include = TOOLBAR_GROUPS) {
|
|
352
|
+
const { labels } = props;
|
|
353
|
+
const has = props.pages.length > 0;
|
|
354
|
+
const groups = [];
|
|
355
|
+
const add = (id, controls) => {
|
|
356
|
+
if (include.includes(id) && controls.length) groups.push({
|
|
357
|
+
id,
|
|
358
|
+
controls
|
|
359
|
+
});
|
|
360
|
+
};
|
|
361
|
+
add("file", [
|
|
362
|
+
...props.onOpenFile ? [button("open", labels.Open, true, props.onOpenFile)] : [],
|
|
363
|
+
...props.onOpenPageSetup ? [button("page-setup", labels["Page Setup"], has, props.onOpenPageSetup)] : [],
|
|
364
|
+
...props.onOpenShareDialog ? [button("share", labels.Share, has, props.onOpenShareDialog)] : [],
|
|
365
|
+
...props.onOpenSettings ? [button("settings", labels.Options, true, props.onOpenSettings)] : []
|
|
366
|
+
]);
|
|
367
|
+
add("history", [button("undo", labels.Undo, props.canUndo, props.onUndo), button("redo", labels.Redo, props.canRedo, props.onRedo)]);
|
|
368
|
+
add("zoom", [
|
|
369
|
+
button("zoom-out", labels["Zoom Out"], props.canZoomOut, props.onZoomOut),
|
|
370
|
+
{
|
|
371
|
+
kind: "text",
|
|
372
|
+
id: "zoom",
|
|
373
|
+
text: `${Math.round(props.zoom * 100)}%`
|
|
374
|
+
},
|
|
375
|
+
button("zoom-in", labels["Zoom In"], props.canZoomIn, props.onZoomIn),
|
|
376
|
+
button("fit", labels["Fit to Window"], has, props.onFit)
|
|
377
|
+
]);
|
|
378
|
+
add("selection", [
|
|
379
|
+
button("duplicate", labels.Duplicate, props.canDuplicate, props.onDuplicate),
|
|
380
|
+
button("group", labels.Group, props.canGroup, props.onGroup),
|
|
381
|
+
button("ungroup", labels.Ungroup, props.canUngroup, props.onUngroup),
|
|
382
|
+
button("delete", labels.Delete, props.canDelete, props.onDelete)
|
|
383
|
+
]);
|
|
384
|
+
add("clipboard", [
|
|
385
|
+
button("cut", labels.Cut, props.canCut, props.onCut),
|
|
386
|
+
button("copy", labels.Copy, props.canCopy, props.onCopy),
|
|
387
|
+
button("paste", labels.Paste, props.canPaste, props.onPaste)
|
|
388
|
+
]);
|
|
389
|
+
add("tools", props.tools.map((tool) => button(`tool-${tool.id}`, tool.label, tool.id === "pointer" || props.canDraw, () => props.onToolChange(tool.id), tool.active)));
|
|
390
|
+
const { search } = props;
|
|
391
|
+
add("search", [{
|
|
392
|
+
kind: "search",
|
|
393
|
+
id: "search",
|
|
394
|
+
label: labels.Find,
|
|
395
|
+
query: search.query,
|
|
396
|
+
summary: search.query ? search.resultCount ? `${search.activeIndex >= 0 ? search.activeIndex + 1 : "-"} / ${search.resultCount}` : "0" : "",
|
|
397
|
+
previous: button("search-previous", labels["Previous Result"], search.resultCount > 0, props.onPreviousSearchResult),
|
|
398
|
+
next: button("search-next", labels["Next Result"], search.resultCount > 0, props.onNextSearchResult),
|
|
399
|
+
change: (query) => props.onSearchChange(query)
|
|
400
|
+
}]);
|
|
401
|
+
return groups;
|
|
402
|
+
}
|
|
403
|
+
//#endregion
|
|
301
404
|
//#region packages/svelte/src/Toolbar.svelte
|
|
302
405
|
function Toolbar($$renderer, $$props) {
|
|
303
406
|
$$renderer.component(($$renderer) => {
|
|
304
|
-
let { toolbarProps } = $$props;
|
|
305
|
-
|
|
407
|
+
let { toolbarProps, include } = $$props;
|
|
408
|
+
const groups = $.derived(() => toolbarGroups(toolbarProps, include));
|
|
409
|
+
$$renderer.push(`<div role="toolbar"><!--[-->`);
|
|
410
|
+
const each_array = $.ensure_array_like(groups());
|
|
411
|
+
for (let $$index_1 = 0, $$length = each_array.length; $$index_1 < $$length; $$index_1++) {
|
|
412
|
+
let group = each_array[$$index_1];
|
|
413
|
+
$$renderer.push(`<span${$.attr("data-group", group.id)}><!--[-->`);
|
|
414
|
+
const each_array_1 = $.ensure_array_like(group.controls);
|
|
415
|
+
for (let $$index = 0, $$length = each_array_1.length; $$index < $$length; $$index++) {
|
|
416
|
+
let control = each_array_1[$$index];
|
|
417
|
+
if (control.kind === "text") $$renderer.push(`<!--[0--><span${$.attr("data-control", control.id)}>${$.escape(control.text)}</span>`);
|
|
418
|
+
else if (control.kind === "button") $$renderer.push(`<!--[1--><button type="button"${$.attr("data-control", control.id)}${$.attr("disabled", control.disabled, true)}${$.attr("aria-pressed", control.pressed)}>${$.escape(control.label)}</button>`);
|
|
419
|
+
else $$renderer.push(`<!--[-1--><span data-control="search"><input type="search"${$.attr("aria-label", control.label)}${$.attr("placeholder", control.label)}${$.attr("value", control.query)}/> <span aria-live="polite">${$.escape(control.summary)}</span> <button type="button"${$.attr("data-control", control.previous.id)}${$.attr("disabled", control.previous.disabled, true)}>${$.escape(control.previous.label)}</button> <button type="button"${$.attr("data-control", control.next.id)}${$.attr("disabled", control.next.disabled, true)}>${$.escape(control.next.label)}</button></span>`);
|
|
420
|
+
$$renderer.push(`<!--]-->`);
|
|
421
|
+
}
|
|
422
|
+
$$renderer.push(`<!--]--></span>`);
|
|
423
|
+
}
|
|
424
|
+
$$renderer.push(`<!--]--></div>`);
|
|
306
425
|
});
|
|
307
426
|
}
|
|
308
427
|
//#endregion
|
|
@@ -336,4 +455,12 @@ function Inspector($$renderer, $$props) {
|
|
|
336
455
|
});
|
|
337
456
|
}
|
|
338
457
|
//#endregion
|
|
339
|
-
|
|
458
|
+
//#region packages/svelte/src/ShapesPane.svelte
|
|
459
|
+
function ShapesPane($$renderer, $$props) {
|
|
460
|
+
$$renderer.component(($$renderer) => {
|
|
461
|
+
let { controller, locale } = $$props;
|
|
462
|
+
$$renderer.push(`<div></div>`);
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
//#endregion
|
|
466
|
+
export { DiagramCanvas, Inspector, PageNavigation, ShapesPane, Toolbar, VisioViewer, VisioViewer as default, createViewerBuildingBlocks };
|
package/dist/index.svelte.js
CHANGED
|
@@ -5,3 +5,4 @@ export { default as DiagramCanvas } from './DiagramCanvas.svelte';
|
|
|
5
5
|
export { default as Toolbar } from './Toolbar.svelte';
|
|
6
6
|
export { default as PageNavigation } from './PageNavigation.svelte';
|
|
7
7
|
export { default as Inspector } from './Inspector.svelte';
|
|
8
|
+
export { default as ShapesPane } from './ShapesPane.svelte';
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './types/packages/bindings/src/common.js';
|
|
2
2
|
export * from './types/packages/bindings/src/building-blocks.js';
|
|
3
|
+
export * from './types/packages/bindings/src/toolbar-controls.js';
|
|
3
4
|
export * from './types/packages/svelte/src/building-blocks.js';
|
|
4
5
|
export * from './types/src/index.js';
|
|
5
6
|
export * from 'visio-core';
|
package/dist/runtime.js
CHANGED
|
@@ -168,10 +168,15 @@ function buildingBlock(key) {
|
|
|
168
168
|
if (typeof value !== "function") throw new Error("Update ooxml-ui to use Visio building blocks.");
|
|
169
169
|
return value;
|
|
170
170
|
}
|
|
171
|
+
/** The mode a host sees: 'edit' only when permission is granted and the file can be saved back. */
|
|
172
|
+
function effectiveMode(state) {
|
|
173
|
+
return buildingBlock("diagramMode")(state);
|
|
174
|
+
}
|
|
171
175
|
/** Framework-neutral ownership only; each adapter supplies its own reactive state. */
|
|
172
|
-
function createBuildingBlockSession() {
|
|
176
|
+
function createBuildingBlockSession(initial = {}) {
|
|
173
177
|
const controller = new ViewerController$1(createWorkerParser());
|
|
174
|
-
|
|
178
|
+
controller.canEdit = initial.canEdit === true;
|
|
179
|
+
let options = initial;
|
|
175
180
|
let source;
|
|
176
181
|
let host = null;
|
|
177
182
|
let disposeCanvas;
|
|
@@ -195,13 +200,23 @@ function createBuildingBlockSession() {
|
|
|
195
200
|
host = node;
|
|
196
201
|
if (node) disposeCanvas = buildingBlock("mountDiagramCanvas")(node, controller);
|
|
197
202
|
},
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
/** Flat control props; pass the framework's latest options so callbacks stay current. */
|
|
204
|
+
toolbar(latest = options) {
|
|
205
|
+
return buildingBlock("diagramToolbarProps")(controller, fit, latest.locale, {
|
|
206
|
+
onOpenFile: latest.onOpenFile,
|
|
207
|
+
onOpenPageSetup: latest.onOpenPageSetup,
|
|
208
|
+
onOpenSettings: latest.onOpenSettings,
|
|
209
|
+
onOpenShareDialog: latest.onOpenShareDialog
|
|
210
|
+
});
|
|
211
|
+
},
|
|
212
|
+
/** Acknowledge a host save: clears dirty and emits the dirty change. */
|
|
213
|
+
markClean() {
|
|
214
|
+
controller.markClean();
|
|
200
215
|
},
|
|
201
216
|
update(next) {
|
|
202
217
|
if (destroyed) return;
|
|
203
218
|
options = next;
|
|
204
|
-
controller.canEdit = next.canEdit
|
|
219
|
+
controller.canEdit = next.canEdit === true;
|
|
205
220
|
if (source === next.content) return;
|
|
206
221
|
source = next.content;
|
|
207
222
|
controller.cancelLoad();
|
|
@@ -230,14 +245,94 @@ function prepareDiagramBlock(host, kind) {
|
|
|
230
245
|
prepare(host, kind, "visio");
|
|
231
246
|
}
|
|
232
247
|
//#endregion
|
|
248
|
+
//#region packages/bindings/src/toolbar-controls.ts
|
|
249
|
+
var TOOLBAR_GROUPS = [
|
|
250
|
+
"file",
|
|
251
|
+
"history",
|
|
252
|
+
"zoom",
|
|
253
|
+
"selection",
|
|
254
|
+
"clipboard",
|
|
255
|
+
"tools",
|
|
256
|
+
"search"
|
|
257
|
+
];
|
|
258
|
+
var fire = (action) => () => {
|
|
259
|
+
Promise.resolve().then(action).catch(() => {});
|
|
260
|
+
};
|
|
261
|
+
var button = (id, label, enabled, action, pressed) => ({
|
|
262
|
+
kind: "button",
|
|
263
|
+
id,
|
|
264
|
+
label,
|
|
265
|
+
disabled: !enabled,
|
|
266
|
+
...pressed === void 0 ? {} : { pressed },
|
|
267
|
+
run: fire(action)
|
|
268
|
+
});
|
|
269
|
+
/**
|
|
270
|
+
* What the library Toolbar shows, as plain data every framework maps onto its own elements.
|
|
271
|
+
* Every control reflects `toolbarProps`: edit actions are disabled while the diagram is read-only,
|
|
272
|
+
* viewing actions (zoom, fit, search) never are, and a host dialog button appears only when the
|
|
273
|
+
* host supplied its callback.
|
|
274
|
+
*/
|
|
275
|
+
function toolbarGroups(props, include = TOOLBAR_GROUPS) {
|
|
276
|
+
const { labels } = props;
|
|
277
|
+
const has = props.pages.length > 0;
|
|
278
|
+
const groups = [];
|
|
279
|
+
const add = (id, controls) => {
|
|
280
|
+
if (include.includes(id) && controls.length) groups.push({
|
|
281
|
+
id,
|
|
282
|
+
controls
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
add("file", [
|
|
286
|
+
...props.onOpenFile ? [button("open", labels.Open, true, props.onOpenFile)] : [],
|
|
287
|
+
...props.onOpenPageSetup ? [button("page-setup", labels["Page Setup"], has, props.onOpenPageSetup)] : [],
|
|
288
|
+
...props.onOpenShareDialog ? [button("share", labels.Share, has, props.onOpenShareDialog)] : [],
|
|
289
|
+
...props.onOpenSettings ? [button("settings", labels.Options, true, props.onOpenSettings)] : []
|
|
290
|
+
]);
|
|
291
|
+
add("history", [button("undo", labels.Undo, props.canUndo, props.onUndo), button("redo", labels.Redo, props.canRedo, props.onRedo)]);
|
|
292
|
+
add("zoom", [
|
|
293
|
+
button("zoom-out", labels["Zoom Out"], props.canZoomOut, props.onZoomOut),
|
|
294
|
+
{
|
|
295
|
+
kind: "text",
|
|
296
|
+
id: "zoom",
|
|
297
|
+
text: `${Math.round(props.zoom * 100)}%`
|
|
298
|
+
},
|
|
299
|
+
button("zoom-in", labels["Zoom In"], props.canZoomIn, props.onZoomIn),
|
|
300
|
+
button("fit", labels["Fit to Window"], has, props.onFit)
|
|
301
|
+
]);
|
|
302
|
+
add("selection", [
|
|
303
|
+
button("duplicate", labels.Duplicate, props.canDuplicate, props.onDuplicate),
|
|
304
|
+
button("group", labels.Group, props.canGroup, props.onGroup),
|
|
305
|
+
button("ungroup", labels.Ungroup, props.canUngroup, props.onUngroup),
|
|
306
|
+
button("delete", labels.Delete, props.canDelete, props.onDelete)
|
|
307
|
+
]);
|
|
308
|
+
add("clipboard", [
|
|
309
|
+
button("cut", labels.Cut, props.canCut, props.onCut),
|
|
310
|
+
button("copy", labels.Copy, props.canCopy, props.onCopy),
|
|
311
|
+
button("paste", labels.Paste, props.canPaste, props.onPaste)
|
|
312
|
+
]);
|
|
313
|
+
add("tools", props.tools.map((tool) => button(`tool-${tool.id}`, tool.label, tool.id === "pointer" || props.canDraw, () => props.onToolChange(tool.id), tool.active)));
|
|
314
|
+
const { search } = props;
|
|
315
|
+
add("search", [{
|
|
316
|
+
kind: "search",
|
|
317
|
+
id: "search",
|
|
318
|
+
label: labels.Find,
|
|
319
|
+
query: search.query,
|
|
320
|
+
summary: search.query ? search.resultCount ? `${search.activeIndex >= 0 ? search.activeIndex + 1 : "-"} / ${search.resultCount}` : "0" : "",
|
|
321
|
+
previous: button("search-previous", labels["Previous Result"], search.resultCount > 0, props.onPreviousSearchResult),
|
|
322
|
+
next: button("search-next", labels["Next Result"], search.resultCount > 0, props.onNextSearchResult),
|
|
323
|
+
change: (query) => props.onSearchChange(query)
|
|
324
|
+
}]);
|
|
325
|
+
return groups;
|
|
326
|
+
}
|
|
327
|
+
//#endregion
|
|
233
328
|
//#region packages/svelte/src/building-blocks.ts
|
|
234
329
|
/** Call during component initialization. Reactive option changes use blocks.update(options). */
|
|
235
330
|
function createViewerBuildingBlocks(options = {}) {
|
|
236
331
|
const source = "subscribe" in options ? options : void 0;
|
|
237
332
|
const initial = source ? get(source) : options;
|
|
238
|
-
const session = createBuildingBlockSession();
|
|
333
|
+
const session = createBuildingBlockSession(initial);
|
|
239
334
|
const state = writable(session.controller.state);
|
|
240
|
-
const
|
|
335
|
+
const latest = writable(initial);
|
|
241
336
|
const stop = session.controller.subscribe((value) => state.set(value));
|
|
242
337
|
let stopOptions = () => {};
|
|
243
338
|
onDestroy(() => {
|
|
@@ -246,7 +341,7 @@ function createViewerBuildingBlocks(options = {}) {
|
|
|
246
341
|
session.destroy();
|
|
247
342
|
});
|
|
248
343
|
const update = (next) => {
|
|
249
|
-
|
|
344
|
+
latest.set(next);
|
|
250
345
|
session.update(next);
|
|
251
346
|
};
|
|
252
347
|
if (source) stopOptions = source.subscribe(update);
|
|
@@ -254,14 +349,21 @@ function createViewerBuildingBlocks(options = {}) {
|
|
|
254
349
|
return {
|
|
255
350
|
controller: session.controller,
|
|
256
351
|
state: { subscribe: state.subscribe },
|
|
257
|
-
toolbarProps: derived([state,
|
|
352
|
+
toolbarProps: derived([state, latest], ([, next]) => session.toolbar(next)),
|
|
258
353
|
loading: derived(state, (value) => value.loading),
|
|
259
354
|
error: derived(state, (value) => value.error ?? value.edit.error),
|
|
260
|
-
|
|
355
|
+
/** Effective permission: host `canEdit` and a drawing that can be saved back. */
|
|
356
|
+
mode: derived(state, (value) => effectiveMode(value)),
|
|
261
357
|
canvasProps: { mount: session.mount },
|
|
262
358
|
inspectorProps: { controller: session.controller },
|
|
359
|
+
shapesProps: derived(latest, (next) => ({
|
|
360
|
+
controller: session.controller,
|
|
361
|
+
locale: next.locale
|
|
362
|
+
})),
|
|
363
|
+
/** Acknowledge a host save: clears dirty and fires `onDirtyChange(false)`. */
|
|
364
|
+
markClean: () => session.markClean(),
|
|
263
365
|
update
|
|
264
366
|
};
|
|
265
367
|
}
|
|
266
368
|
//#endregion
|
|
267
|
-
export { ViewerController, buildingBlock, createBuildingBlockSession, createViewerBuildingBlocks, eventKeys, mountFrameworkViewer, mountViewer, prepareDiagramBlock, propertyKeys, viewerHandle, viewerOptions, viewerStateSource, withEventEmitter };
|
|
369
|
+
export { TOOLBAR_GROUPS, ViewerController, buildingBlock, createBuildingBlockSession, createViewerBuildingBlocks, effectiveMode, eventKeys, mountFrameworkViewer, mountViewer, prepareDiagramBlock, propertyKeys, toolbarGroups, viewerHandle, viewerOptions, viewerStateSource, withEventEmitter };
|
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
import { ViewerController, type VsdxSource } from 'ooxml-ui/visio';
|
|
2
2
|
import * as ui from 'ooxml-ui/visio';
|
|
3
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
/** Flat control props; pass the framework's latest options so callbacks stay current. */
|
|
28
|
+
toolbar(latest?: BuildingBlockOptions): {
|
|
29
|
+
labels: Readonly<Record<"Arc" | "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" | "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[];
|
|
@@ -7,9 +7,8 @@ export declare function createViewerBuildingBlocks(options?: BuildingBlockOption
|
|
|
7
7
|
subscribe: (this: void, run: import("svelte/store").Subscriber<import("ooxml-ui/visio").ViewerState>, invalidate?: () => void) => import("svelte/store").Unsubscriber;
|
|
8
8
|
};
|
|
9
9
|
toolbarProps: Readable<{
|
|
10
|
-
labels:
|
|
11
|
-
|
|
12
|
-
};
|
|
10
|
+
labels: Readonly<Record<"Arc" | "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" | "Undo" | "Ungroup" | "Zoom In" | "Zoom Out", string>>;
|
|
11
|
+
mode: import("ooxml-ui/visio").DiagramMode;
|
|
13
12
|
canEdit: boolean;
|
|
14
13
|
pageIndex: number;
|
|
15
14
|
pages: {
|
|
@@ -23,21 +22,52 @@ export declare function createViewerBuildingBlocks(options?: BuildingBlockOption
|
|
|
23
22
|
canDuplicate: boolean;
|
|
24
23
|
canGroup: boolean;
|
|
25
24
|
canUngroup: boolean;
|
|
25
|
+
canDelete: boolean;
|
|
26
|
+
canCut: boolean;
|
|
27
|
+
canCopy: boolean;
|
|
28
|
+
canPaste: boolean;
|
|
29
|
+
canDraw: boolean;
|
|
30
|
+
canZoomIn: boolean;
|
|
31
|
+
canZoomOut: boolean;
|
|
32
|
+
tool: import("ooxml-ui/visio").DiagramTool;
|
|
33
|
+
tools: import("ooxml-ui/visio").DiagramToolSummary[];
|
|
34
|
+
search: {
|
|
35
|
+
query: string;
|
|
36
|
+
resultCount: number;
|
|
37
|
+
activeIndex: number;
|
|
38
|
+
truncated: boolean;
|
|
39
|
+
};
|
|
26
40
|
onPageChange: (index: number) => void;
|
|
27
41
|
onZoomChange: (zoom: number) => void;
|
|
42
|
+
onZoomIn: () => void;
|
|
43
|
+
onZoomOut: () => void;
|
|
28
44
|
onFit: () => void;
|
|
29
45
|
onUndo: () => Promise<void>;
|
|
30
46
|
onRedo: () => Promise<void>;
|
|
31
47
|
onDuplicate: () => Promise<void>;
|
|
32
48
|
onGroup: () => Promise<void>;
|
|
33
49
|
onUngroup: () => Promise<void>;
|
|
50
|
+
onDelete: () => Promise<void>;
|
|
51
|
+
onCut: () => Promise<void>;
|
|
52
|
+
onCopy: () => Promise<void>;
|
|
53
|
+
onPaste: () => Promise<void>;
|
|
54
|
+
onToolChange: (tool: import("ooxml-ui/visio").DiagramTool) => void;
|
|
34
55
|
onTextChange: (pageId: string, shapeId: string, text: string) => Promise<void>;
|
|
35
56
|
onSearchChange: (query: string) => void;
|
|
36
57
|
onNextSearchResult: () => void;
|
|
37
58
|
onPreviousSearchResult: () => void;
|
|
59
|
+
canOpenFile: boolean;
|
|
60
|
+
canOpenPageSetup: boolean;
|
|
61
|
+
canOpenSettings: boolean;
|
|
62
|
+
canOpenShareDialog: boolean;
|
|
63
|
+
onOpenFile?: () => void;
|
|
64
|
+
onOpenPageSetup?: () => void;
|
|
65
|
+
onOpenSettings?: () => void;
|
|
66
|
+
onOpenShareDialog?: () => void;
|
|
38
67
|
}>;
|
|
39
68
|
loading: Readable<boolean>;
|
|
40
69
|
error: Readable<Error | null>;
|
|
70
|
+
/** Effective permission: host `canEdit` and a drawing that can be saved back. */
|
|
41
71
|
mode: Readable<"edit" | "view">;
|
|
42
72
|
canvasProps: {
|
|
43
73
|
mount: (node: HTMLElement | null) => void;
|
|
@@ -45,6 +75,13 @@ export declare function createViewerBuildingBlocks(options?: BuildingBlockOption
|
|
|
45
75
|
inspectorProps: {
|
|
46
76
|
controller: import("ooxml-ui/visio").ViewerController;
|
|
47
77
|
};
|
|
78
|
+
shapesProps: Readable<{
|
|
79
|
+
controller: import("ooxml-ui/visio").ViewerController;
|
|
80
|
+
locale: string | undefined;
|
|
81
|
+
}>;
|
|
82
|
+
/** Acknowledge a host save: clears dirty and fires `onDirtyChange(false)`. */
|
|
83
|
+
markClean: () => void;
|
|
48
84
|
update: (next: BuildingBlockOptions) => void;
|
|
49
85
|
};
|
|
50
|
-
export type { BuildingBlockOptions, DiagramToolbarProps } from '../../bindings/src/building-blocks.js';
|
|
86
|
+
export type { BuildingBlockOptions, BuildingBlockHostCallbacks, DiagramToolbarProps, } from '../../bindings/src/building-blocks.js';
|
|
87
|
+
export type { ToolbarGroupId } from '../../bindings/src/toolbar-controls.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "visio-svelte-viewer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Local-first Visio viewer for svelte",
|
|
5
5
|
"homepage": "https://christophervr.github.io/ooxml/visio/",
|
|
6
6
|
"bugs": {
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"emf-converter": "4.21.0",
|
|
41
|
-
"ooxml-core": "^1.
|
|
42
|
-
"ooxml-ui": "^1.
|
|
43
|
-
"visio-core": "^0.
|
|
41
|
+
"ooxml-core": "^1.22.0",
|
|
42
|
+
"ooxml-ui": "^1.21.0",
|
|
43
|
+
"visio-core": "^1.0.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"svelte": "^5.0.0"
|