visio-solid-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/index.js +242 -47
- package/dist/index.server.js +200 -20
- 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/solid/src/building-blocks.d.ts +50 -5
- package/package.json +4 -4
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 {
|
|
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
|
-
|
|
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
|
-
|
|
252
|
-
|
|
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
|
|
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(`<
|
|
289
|
-
var _tmpl$3 = /*#__PURE__*/ template(`<
|
|
290
|
-
var _tmpl$4 = /*#__PURE__*/ template(`<
|
|
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()
|
|
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
|
-
|
|
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$
|
|
333
|
-
use((host) => prepareDiagramBlock(host, "toolbar"), _el$
|
|
334
|
-
_el$
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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$
|
|
355
|
-
_el$
|
|
356
|
-
use((host) => prepareDiagramBlock(host, "tabs"), _el$
|
|
357
|
-
insert(_el$
|
|
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$
|
|
363
|
-
insert(_el$
|
|
364
|
-
effect(() => _el$
|
|
365
|
-
return _el$
|
|
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$
|
|
369
|
-
effect(() => _el$
|
|
370
|
-
return _el$
|
|
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$
|
|
562
|
+
var _el$1 = _tmpl$();
|
|
381
563
|
var _ref$2 = host;
|
|
382
|
-
typeof _ref$2 === "function" ? use(_ref$2, _el$
|
|
383
|
-
return _el$
|
|
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 };
|
package/dist/index.server.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
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
|
-
|
|
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
|
-
|
|
241
|
-
|
|
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
|
|
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
|
-
"<
|
|
272
|
-
" role=\"toolbar\"><button type=\"button\"",
|
|
366
|
+
"<span",
|
|
273
367
|
">",
|
|
274
|
-
"</
|
|
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$
|
|
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()
|
|
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
|
-
|
|
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
|
-
|
|
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$
|
|
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$
|
|
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
|
-
|
|
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[];
|
|
@@ -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
|
-
|
|
12
|
-
};
|
|
11
|
+
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>>;
|
|
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
|
-
|
|
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
|
|
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.
|
|
3
|
+
"version": "1.0.0",
|
|
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.
|
|
36
|
-
"ooxml-ui": "^1.
|
|
37
|
-
"visio-core": "^0.
|
|
35
|
+
"ooxml-core": "^1.22.0",
|
|
36
|
+
"ooxml-ui": "^1.21.0",
|
|
37
|
+
"visio-core": "^1.0.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"solid-js": "^1.9.0"
|