@miragon/modeler-shell 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +1051 -84
- package/README.md +162 -31
- package/dist/appearance-BBaM_4bD.d.ts +323 -0
- package/dist/appearance-XX3JC3pI.d.cts +323 -0
- package/dist/{chunk-6LQOFACK.js → chunk-A4YGKH4Y.js} +1252 -31
- package/dist/chunk-A4YGKH4Y.js.map +1 -0
- package/dist/{chunk-RJRFR6N3.js → chunk-KYDG5DMX.js} +2 -2
- package/dist/{chunk-5JSZ4VGA.js → chunk-OADW3GPA.js} +240 -6
- package/dist/chunk-OADW3GPA.js.map +1 -0
- package/dist/core.cjs +260 -6
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +81 -6
- package/dist/core.d.ts +81 -6
- package/dist/core.js +43 -3
- package/dist/diagram-js.cjs +34 -2
- package/dist/diagram-js.cjs.map +1 -1
- package/dist/diagram-js.d.cts +10 -3
- package/dist/diagram-js.d.ts +10 -3
- package/dist/diagram-js.js +14 -2
- package/dist/diagram-js.js.map +1 -1
- package/dist/index.cjs +1658 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -9
- package/dist/index.d.ts +18 -9
- package/dist/index.js +44 -4
- package/dist/shell.css +692 -3
- package/dist/testing-vscode-stub.js +2 -2
- package/dist/testing.cjs +2849 -550
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +75 -9
- package/dist/testing.d.ts +75 -9
- package/dist/testing.js +2744 -558
- package/dist/testing.js.map +1 -1
- package/dist/toasts-Bp0REqdq.d.cts +142 -0
- package/dist/toasts-Bp0REqdq.d.ts +142 -0
- package/dist/{types-OuFlqZp0.d.cts → types-CnRrINRs.d.cts} +170 -9
- package/dist/{types-DnZn9CPw.d.ts → types-PuDZczzy.d.ts} +170 -9
- package/dist/vscode-extension.js +2 -2
- package/dist/vscode-webview.cjs +1546 -178
- package/dist/vscode-webview.cjs.map +1 -1
- package/dist/vscode-webview.d.cts +6 -4
- package/dist/vscode-webview.d.ts +6 -4
- package/dist/vscode-webview.js +11 -2
- package/dist/vscode-webview.js.map +1 -1
- package/package.json +2 -2
- package/src/core/feedback/appearance.ts +141 -0
- package/src/core/feedback/problems.ts +23 -0
- package/src/core/feedback/toasts.ts +118 -0
- package/src/core/fit.ts +18 -3
- package/src/core/index.ts +43 -0
- package/src/core/keymap.ts +20 -0
- package/src/core/messages.ts +71 -0
- package/src/core/types.ts +24 -2
- package/src/core/web-chrome/bottom-row.ts +37 -0
- package/src/core/web-chrome/drop.ts +78 -0
- package/src/core/web-chrome/top-row.ts +66 -0
- package/src/diagram-js/service.ts +4 -1
- package/src/diagram-js/viewport.ts +19 -0
- package/src/dom/buttons.css +124 -0
- package/src/dom/feedback/appearance.ts +184 -0
- package/src/dom/feedback/feedback.css +435 -0
- package/src/dom/feedback/problems-popover.ts +287 -0
- package/src/dom/feedback/toasts.ts +431 -0
- package/src/dom/index.ts +13 -0
- package/src/dom/keys.ts +8 -0
- package/src/dom/menu.ts +28 -17
- package/src/dom/mount.ts +290 -20
- package/src/dom/problems.ts +5 -4
- package/src/dom/shell-dom.css +7 -4
- package/src/dom/tooltip.ts +10 -0
- package/src/dom/types.ts +188 -6
- package/src/dom/web/drop-zone.ts +181 -0
- package/src/dom/web/empty-state.ts +144 -0
- package/src/dom/web/legal.ts +75 -0
- package/src/dom/web/menu-groups.ts +69 -0
- package/src/dom/web/primary.ts +124 -0
- package/src/dom/web/web.css +386 -0
- package/src/shell.css +3 -0
- package/src/testing/case-tools.ts +164 -0
- package/src/testing/cases.ts +209 -144
- package/src/testing/checks.ts +51 -15
- package/src/testing/facts.ts +56 -2
- package/src/testing/geometry.ts +206 -26
- package/src/testing/harness.ts +56 -7
- package/src/testing/index.ts +4 -0
- package/src/testing/page-tools.ts +24 -1
- package/src/testing/page.ts +10 -0
- package/src/testing/web-cases.ts +913 -0
- package/src/testing/web-checks.ts +1049 -0
- package/src/testing/web-facts.ts +713 -0
- package/src/vscode/webview/mount.ts +13 -1
- package/dist/chunk-5JSZ4VGA.js.map +0 -1
- package/dist/chunk-6LQOFACK.js.map +0 -1
- package/dist/keymap-CObQE6q6.d.cts +0 -151
- package/dist/keymap-DORzHnK-.d.ts +0 -151
- package/dist/types-B6NfkiUG.d.cts +0 -66
- package/dist/types-B6NfkiUG.d.ts +0 -66
- /package/dist/{chunk-RJRFR6N3.js.map → chunk-KYDG5DMX.js.map} +0 -0
package/dist/diagram-js.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
isUndoRedoKey,
|
|
17
17
|
matchChromeKey,
|
|
18
18
|
sameView
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-OADW3GPA.js";
|
|
20
20
|
|
|
21
21
|
// src/diagram-js/palette-skin.ts
|
|
22
22
|
var TOOLS_GROUP = "tools";
|
|
@@ -369,7 +369,8 @@ var ShellDiagramService = class {
|
|
|
369
369
|
onKeyboardKeydown = (context) => {
|
|
370
370
|
const event = context.keyEvent;
|
|
371
371
|
if (!event) return void 0;
|
|
372
|
-
if (matchChromeKey(event))
|
|
372
|
+
if (matchChromeKey(event))
|
|
373
|
+
return !isTextField(event.target) && this.shell?.isEmptyStateShown?.() !== true;
|
|
373
374
|
if (this.shell?.host === "ide" && isUndoRedoKey(event)) return false;
|
|
374
375
|
return void 0;
|
|
375
376
|
};
|
|
@@ -535,6 +536,17 @@ var DiagramViewport = class {
|
|
|
535
536
|
}
|
|
536
537
|
this.notify();
|
|
537
538
|
}
|
|
539
|
+
newDocument() {
|
|
540
|
+
if (this.destroyed) return;
|
|
541
|
+
this.cancelAnimation();
|
|
542
|
+
this.userMoved = false;
|
|
543
|
+
this.firstFitPending = true;
|
|
544
|
+
this.emptyViewPending = true;
|
|
545
|
+
this.emptyViewDue = false;
|
|
546
|
+
this.autoFitDue = false;
|
|
547
|
+
this.pendingView = void 0;
|
|
548
|
+
this.fittable = void 0;
|
|
549
|
+
}
|
|
538
550
|
restore(viewbox) {
|
|
539
551
|
if (this.destroyed) return;
|
|
540
552
|
this.importing = false;
|
package/dist/diagram-js.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/diagram-js/palette-skin.ts","../src/diagram-js/service.ts","../src/diagram-js/module.ts","../src/diagram-js/viewport.ts","../src/diagram-js/connect.ts"],"sourcesContent":["import { ariaKeyShortcutsFromLabel, defaultMessages } from \"../core/index.js\";\nimport type { PaletteReadOnlyState, TooltipContent } from \"../dom/index.js\";\n\n/** The diagram-js palette group of the tools (`Palette#updateToolHighlight` looks for it). */\nexport const TOOLS_GROUP = \"tools\";\n\n/**\n * The entries that stay active on a read-only canvas (guide §13.5: Lasso and Hand). Every other\n * entry changes the diagram, also tools such as drawing, space or connect.\n */\nexport const READ_ONLY_ACTIONS: ReadonlySet<string> = new Set([\"lasso-tool\", \"hand-tool\"]);\n\nconst TOOL_ACTION_SUFFIX = \"-tool\";\nconst ENTRIES_SELECTOR = \".djs-palette-entries\";\nconst ENTRY_SELECTOR = \".entry\";\n\n/** One entry of `palette.getEntries()`, as far as the skin reads it. */\nexport interface PaletteEntryLike {\n title?: string | undefined;\n shortcut?: string | undefined;\n /** `aria-keyshortcuts` (WAI-ARIA names); default `ariaKeyShortcutsFromLabel(shortcut)`. */\n ariaKeyShortcuts?: string | undefined;\n group?: string | undefined;\n}\n\n/**\n * The shell's additions to the diagram-js palette container (guide §5.5): `data-chrome`, the\n * toolbar semantics of the entries, the roving tab stop with its keys, `aria-pressed` for the\n * active tool and `aria-disabled` in read-only. diagram-js clears and rebuilds every entry on each\n * change, so `refresh()` re-applies all of it after every `palette.changed`.\n */\nexport class PaletteSkin {\n private label = defaultMessages.tools;\n private activeTool: string | null = null;\n /** The veto of a read-only canvas, at once with the invalid import. */\n private locked = false;\n /** The `aria-disabled` marks of a read-only canvas, once the shell's delay has passed. */\n private readOnlyShown = false;\n private entries: Readonly<Record<string, PaletteEntryLike>> = {};\n private rovingAction: string | undefined;\n private focusedEntry: HTMLElement | undefined;\n /** The `aria-disabled` an entry had before read-only marked it (`null`: none). */\n private readonly disabledEntries = new WeakMap<Element, string | null>();\n\n constructor(\n readonly element: HTMLElement,\n private readonly readEntries: () => Readonly<Record<string, PaletteEntryLike>>,\n ) {\n element.setAttribute(\"data-chrome\", \"palette\");\n element.addEventListener(\"keydown\", this.onKeydown);\n element.addEventListener(\"focusin\", this.onFocusIn);\n element.addEventListener(\"focusout\", this.onFocusOut);\n this.refresh();\n }\n\n setLabel(label: string): void {\n this.label = label;\n this.apply();\n }\n\n setActiveTool(tool: string | null): void {\n this.activeTool = tool;\n this.apply();\n }\n\n setReadOnly(state: PaletteReadOnlyState): void {\n this.locked = state.locked;\n this.readOnlyShown = state.locked && state.shown;\n this.apply();\n }\n\n /**\n * Whether `palette.trigger` must refuse `entry`: on a locked canvas every entry but Lasso and\n * Hand, also before their marks show. `palette.trigger` carries the entry definition without its\n * id, so the entry element is found through the DOM event; without one, only the tools group\n * passes.\n */\n vetoes(entry: PaletteEntryLike, event: Event | undefined): boolean {\n if (!this.locked) return false;\n const element = this.entryOf(\n (event as { delegateTarget?: EventTarget } | undefined)?.delegateTarget ?? event?.target ?? null,\n );\n if (element) return !staysActive(element);\n return entry.group !== TOOLS_GROUP;\n }\n\n /** After `palette.changed`: re-read the entries and re-apply every attribute. */\n refresh(): void {\n this.entries = this.readEntries();\n this.apply();\n }\n\n entryTooltip(entry: HTMLElement): TooltipContent | null {\n const action = entry.getAttribute(\"data-action\");\n const definition = action === null ? undefined : this.entries[action];\n if (!definition?.title) return null;\n return definition.shortcut\n ? { label: definition.title, shortcut: definition.shortcut }\n : { label: definition.title };\n }\n\n destroy(): void {\n this.element.removeEventListener(\"keydown\", this.onKeydown);\n this.element.removeEventListener(\"focusin\", this.onFocusIn);\n this.element.removeEventListener(\"focusout\", this.onFocusOut);\n this.focusedEntry = undefined;\n }\n\n private apply(): void {\n const container = this.element.querySelector<HTMLElement>(ENTRIES_SELECTOR);\n if (container) {\n container.setAttribute(\"role\", \"toolbar\");\n container.setAttribute(\"aria-label\", this.label);\n }\n const entries = this.entryElements();\n for (const entry of entries) {\n if (!entry.hasAttribute(\"role\")) entry.setAttribute(\"role\", \"button\");\n this.applyKeyShortcuts(entry);\n this.applyPressed(entry);\n this.applyDisabled(entry);\n }\n this.applyTabStops(entries);\n this.restoreFocus(entries);\n }\n\n // Guide §5.6: a button with a shortcut names it for assistive technology, not only in the chip.\n private applyKeyShortcuts(entry: HTMLElement): void {\n const action = actionOf(entry);\n const definition = action === undefined ? undefined : this.entries[action];\n const keyShortcuts =\n definition?.ariaKeyShortcuts ??\n (definition?.shortcut ? ariaKeyShortcutsFromLabel(definition.shortcut) : undefined);\n if (keyShortcuts) entry.setAttribute(\"aria-keyshortcuts\", keyShortcuts);\n }\n\n private applyPressed(entry: HTMLElement): void {\n const action = actionOf(entry);\n if (groupOf(entry) !== TOOLS_GROUP || !action?.endsWith(TOOL_ACTION_SUFFIX)) return;\n const tool = action.slice(0, -TOOL_ACTION_SUFFIX.length);\n entry.setAttribute(\"aria-pressed\", String(tool === this.activeTool));\n }\n\n private applyDisabled(entry: HTMLElement): void {\n if (this.readOnlyShown && !staysActive(entry)) {\n if (!this.disabledEntries.has(entry)) {\n this.disabledEntries.set(entry, entry.getAttribute(\"aria-disabled\"));\n }\n entry.setAttribute(\"aria-disabled\", \"true\");\n return;\n }\n if (!this.disabledEntries.has(entry)) return;\n const previous = this.disabledEntries.get(entry);\n this.disabledEntries.delete(entry);\n if (previous === null || previous === undefined) entry.removeAttribute(\"aria-disabled\");\n else entry.setAttribute(\"aria-disabled\", previous);\n }\n\n private applyTabStops(entries: readonly HTMLElement[]): void {\n const stop = entries.find((entry) => actionOf(entry) === this.rovingAction) ?? entries[0];\n for (const entry of entries) entry.tabIndex = entry === stop ? 0 : -1;\n }\n\n // A rebuild removes the focused entry; without this the focus would fall back to <body>.\n private restoreFocus(entries: readonly HTMLElement[]): void {\n const lost = this.focusedEntry;\n if (!lost || lost.isConnected) return;\n this.focusedEntry = undefined;\n const replacement = entries.find((entry) => actionOf(entry) === actionOf(lost));\n const active = this.element.ownerDocument.activeElement;\n const focusIsNowhere = !active || active === this.element.ownerDocument.body;\n if (replacement && focusIsNowhere) replacement.focus();\n }\n\n private entryElements(): HTMLElement[] {\n const container = this.element.querySelector(ENTRIES_SELECTOR);\n return container ? Array.from(container.querySelectorAll<HTMLElement>(ENTRY_SELECTOR)) : [];\n }\n\n private entryOf(target: EventTarget | null): HTMLElement | undefined {\n if (!(target instanceof Element)) return undefined;\n const entry = target.closest<HTMLElement>(ENTRY_SELECTOR);\n return entry && this.element.contains(entry) ? entry : undefined;\n }\n\n private readonly onFocusIn = (event: FocusEvent): void => {\n const entry = this.entryOf(event.target);\n if (!entry) return;\n this.focusedEntry = entry;\n this.rovingAction = actionOf(entry);\n this.applyTabStops(this.entryElements());\n };\n\n private readonly onFocusOut = (event: FocusEvent): void => {\n const entry = this.entryOf(event.target);\n if (!entry || entry !== this.focusedEntry || !entry.isConnected) return;\n const next = event.relatedTarget;\n if (!(next instanceof Node) || !this.element.contains(next)) this.focusedEntry = undefined;\n };\n\n private readonly onKeydown = (event: KeyboardEvent): void => {\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n const entry = this.entryOf(event.target);\n if (!entry) return;\n const entries = this.entryElements();\n const index = entries.indexOf(entry);\n const last = entries.length - 1;\n let next: HTMLElement | undefined;\n switch (event.key) {\n case \"ArrowLeft\":\n next = entries[index <= 0 ? last : index - 1];\n break;\n case \"ArrowRight\":\n next = entries[index >= last ? 0 : index + 1];\n break;\n case \"Home\":\n next = entries[0];\n break;\n case \"End\":\n next = entries[last];\n break;\n case \"Enter\":\n case \" \":\n event.preventDefault();\n event.stopPropagation();\n if (!event.repeat) activate(entry);\n return;\n default:\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n if (!next) return;\n this.rovingAction = actionOf(next);\n this.applyTabStops(entries);\n next.focus();\n };\n}\n\nfunction actionOf(entry: Element): string | undefined {\n return entry.getAttribute(\"data-action\") ?? undefined;\n}\n\nfunction staysActive(entry: Element): boolean {\n const action = actionOf(entry);\n return action !== undefined && READ_ONLY_ACTIONS.has(action);\n}\n\nfunction groupOf(entry: Element): string | undefined {\n return entry.closest(\".group\")?.getAttribute(\"data-group\") ?? undefined;\n}\n\n// Enter and Space activate an entry with a synthetic click: `detail` 0, clientX/Y at the entry's\n// centre. A creating entry tells it from a pointer click (`detail` ≥ 1) by that and places its\n// element at `viewport.freeRectCenter()` (guide §5.5). diagram-js handles entry clicks through a\n// delegate on the palette container, so it goes through `palette.trigger` and its read-only veto\n// exactly like a pointer click.\nfunction activate(entry: HTMLElement): void {\n const bounds = entry.getBoundingClientRect();\n entry.dispatchEvent(\n new MouseEvent(\"click\", {\n bubbles: true,\n cancelable: true,\n clientX: bounds.left + bounds.width / 2,\n clientY: bounds.top + bounds.height / 2,\n }),\n );\n}\n","import { TEXT_FIELD_SELECTOR, defaultMessages, isUndoRedoKey, matchChromeKey } from \"../core/index.js\";\nimport type { ShellHandle } from \"../dom/index.js\";\nimport { PaletteSkin, type PaletteEntryLike } from \"./palette-skin.js\";\nimport type {\n CanvasLike,\n DiagramEventListener,\n EventBusLike,\n InjectorLike,\n KeyboardLike,\n PaletteLike,\n} from \"./types.js\";\n\n/** The didi name of the service `shellModule` registers. */\nexport const SHELL_SERVICE = \"modelerShell\";\n\n/** Above `KeyboardBindings` and the modelers' keyboard modules (default priority 1000). */\nexport const KEYBOARD_PRIORITY = 2000;\n\n/** Ahead of every default-priority `palette.trigger` listener, so the read-only veto comes first. */\nconst TRIGGER_PRIORITY = 2000;\n\n/** A palette without a shell is editable. */\nconst EDITABLE = { locked: false, shown: false } as const;\n\n/** What the shell sets on the canvas `<svg>` while a shell is attached, restored on detach. */\nconst CANVAS_ATTRIBUTES = [\"role\", \"aria-label\"] as const;\n\nfunction isTextField(target: EventTarget | null): boolean {\n if (!target || typeof (target as Element).closest !== \"function\") return false;\n return (\n (target as HTMLElement).isContentEditable === true ||\n (target as Element).closest(TEXT_FIELD_SELECTOR) !== null\n );\n}\n\n/** didi's injector, which resolves a missing service to `null` with `strict: false`. */\ninterface DidiInjectorLike {\n get(name: string, strict?: boolean): unknown;\n}\n\ninterface KeyboardEventContext {\n keyEvent?: KeyboardEvent;\n}\n\ninterface PaletteTriggerEvent {\n entry?: PaletteEntryLike;\n event?: Event;\n}\n\n/**\n * The diagram-side half of `shellModule`: the palette skin, the chrome-key guard on the diagram-js\n * keyboard and the buffer that holds the palette until `connectDiagramJs` hands it to a shell.\n */\nexport class ShellDiagramService {\n static $inject = [\"eventBus\", \"injector\"];\n\n private svg: Element | undefined;\n /** The canvas `<svg>`'s own `role` and `aria-label` before the shell named it. */\n private canvasOriginals: Map<string, string | null> | undefined;\n private skin: PaletteSkin | undefined;\n private activeTool: string | null = null;\n private shell: ShellHandle | undefined;\n private unregisterPalette: (() => void) | undefined;\n private readonly subscriptions: Array<readonly [string, DiagramEventListener]> = [];\n private destroyed = false;\n\n constructor(\n private readonly eventBus: EventBusLike,\n private readonly injector: DidiInjectorLike,\n ) {\n this.subscribe(\"canvas.init\", (event: { svg?: Element }) => {\n this.svg = event.svg;\n this.nameCanvas();\n });\n this.subscribe(\"palette.create\", (event: { container: HTMLElement }) =>\n this.onPaletteCreate(event.container),\n );\n this.subscribe(\"palette.changed\", () => this.skin?.refresh());\n this.subscribe(\"tool-manager.update\", (event: { tool?: string | null }) => {\n this.activeTool = event.tool ?? null;\n this.skin?.setActiveTool(this.activeTool);\n });\n this.subscribe(\"palette.trigger\", this.onPaletteTrigger, TRIGGER_PRIORITY);\n this.subscribe(\"diagram.destroy\", () => this.destroy());\n\n const keyboard = injector.get(\"keyboard\", false) as KeyboardLike | null;\n if (keyboard) {\n keyboard.addListener(KEYBOARD_PRIORITY, this.onKeyboardKeydown);\n this.subscriptions.push([\"keyboard.keydown\", this.onKeyboardKeydown]);\n }\n }\n\n /**\n * Hands the palette (now or once diagram-js creates it) to `shell`; returns the detach\n * function. A later call replaces the earlier shell.\n */\n attachShell(shell: ShellHandle): () => void {\n this.detachShell();\n if (this.destroyed) return () => undefined;\n this.shell = shell;\n this.skin?.setLabel(shell.messages.tools);\n this.nameCanvas();\n this.registerPalette();\n return () => {\n if (this.shell === shell) this.detachShell();\n };\n }\n\n private registerPalette(): void {\n const { shell, skin } = this;\n if (!shell || !skin) return;\n this.unregisterPalette?.();\n this.unregisterPalette = shell.registerPalette({\n element: skin.element,\n entryTooltip: (entry) => skin.entryTooltip(entry),\n setReadOnly: (state) => skin.setReadOnly(state),\n });\n }\n\n private detachShell(): void {\n const unregister = this.unregisterPalette;\n this.unregisterPalette = undefined;\n this.shell = undefined;\n unregister?.();\n this.unnameCanvas();\n this.skin?.setReadOnly(EDITABLE);\n this.skin?.setLabel(defaultMessages.tools);\n }\n\n /**\n * The focusable canvas is an application with a name (WCAG 4.1.2): screen readers switch to focus\n * mode, so the canvas's single-key commands reach it. A role or name the modeler set stays.\n */\n private nameCanvas(): void {\n const { svg, shell } = this;\n if (!svg || !shell || this.canvasOriginals) return;\n this.canvasOriginals = new Map(CANVAS_ATTRIBUTES.map((name) => [name, svg.getAttribute(name)]));\n if (!svg.hasAttribute(\"role\")) svg.setAttribute(\"role\", \"application\");\n if (!svg.hasAttribute(\"aria-label\") && !svg.hasAttribute(\"aria-labelledby\")) {\n svg.setAttribute(\"aria-label\", shell.messages.canvas);\n }\n }\n\n private unnameCanvas(): void {\n const { svg, canvasOriginals } = this;\n this.canvasOriginals = undefined;\n if (!svg || !canvasOriginals) return;\n for (const [name, value] of canvasOriginals) {\n if (value === null) svg.removeAttribute(name);\n else svg.setAttribute(name, value);\n }\n }\n\n private onPaletteCreate(container: HTMLElement): void {\n this.skin?.destroy();\n const palette = this.injector.get(\"palette\", false) as PaletteLike | null;\n const skin = new PaletteSkin(container, () => palette?.getEntries() ?? {});\n this.skin = skin;\n skin.setActiveTool(this.activeTool);\n if (this.shell) skin.setLabel(this.shell.messages.tools);\n this.moveBeforeCanvas(container);\n this.registerPalette();\n }\n\n // Palette#_init appends the palette after the <svg>; in front of it the palette comes first in\n // the tab order (guide §5.14).\n private moveBeforeCanvas(container: HTMLElement): void {\n const parent = container.parentElement ?? this.canvasContainer();\n if (!parent) return;\n const svg =\n this.svg?.parentNode === parent\n ? this.svg\n : Array.from(parent.children).find((child) => child.localName === \"svg\");\n if (svg) parent.insertBefore(container, svg);\n }\n\n private canvasContainer(): HTMLElement | undefined {\n const canvas = this.injector.get(\"canvas\", false) as CanvasLike | null;\n return canvas?.getContainer();\n }\n\n private readonly onPaletteTrigger = (event: PaletteTriggerEvent): false | undefined => {\n if (!event.entry || !this.skin?.vetoes(event.entry, event.event)) return undefined;\n // A vetoed dragstart would otherwise still start the browser's native drag of the entry.\n event.event?.preventDefault();\n return false;\n };\n\n /**\n * `true` stops the diagram-js keyboard (and makes it call `preventDefault`), `false` stops it\n * without: a chrome key in a text field inside the `<svg>` stays the field's (Shift+1 types \"!\"),\n * and in the IDE host undo and redo stay the document's (guide §13.5), so they reach VS Code\n * instead of the canvas `commandStack`.\n */\n private readonly onKeyboardKeydown = (context: KeyboardEventContext): boolean | undefined => {\n const event = context.keyEvent;\n if (!event) return undefined;\n if (matchChromeKey(event)) return !isTextField(event.target);\n if (this.shell?.host === \"ide\" && isUndoRedoKey(event)) return false;\n return undefined;\n };\n\n private subscribe<E>(name: string, listener: (event: E) => unknown, priority?: number): void {\n const handler = listener as DiagramEventListener;\n if (priority === undefined) this.eventBus.on(name, handler);\n else this.eventBus.on(name, priority, handler);\n this.subscriptions.push([name, handler]);\n }\n\n private destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.detachShell();\n this.skin?.destroy();\n this.skin = undefined;\n this.svg = undefined;\n for (const [name, listener] of this.subscriptions.splice(0)) this.eventBus.off(name, listener);\n }\n}\n\n/** The service of `shellModule` in `diagram`; throws when the modeler was built without it. */\nexport function shellServiceOf(diagram: InjectorLike): ShellDiagramService {\n let service: unknown;\n try {\n service = diagram.get<unknown>(SHELL_SERVICE);\n } catch {\n service = undefined;\n }\n if (!isShellService(service)) {\n throw new Error(\n \"@miragon/modeler-shell: connectDiagramJs needs shellModule in the modeler's modules (additionalModules: [shellModule])\",\n );\n }\n return service;\n}\n\n// Duck-typed rather than `instanceof`, so a shellModule from the CJS build connects to the ESM one.\nfunction isShellService(value: unknown): value is ShellDiagramService {\n return typeof (value as Partial<ShellDiagramService> | null)?.attachShell === \"function\";\n}\n","import { SHELL_SERVICE, ShellDiagramService } from \"./service.js\";\nimport type { ModuleDeclarationLike } from \"./types.js\";\n\n/**\n * Add to the modeler's modules (`additionalModules`, after the renderer's own modules):\n * - `paletteTooltip: [\"value\", null]` removes diagram-js's (or the renderer's) palette tooltip; the\n * chrome tooltip takes over;\n * - the palette skin: on `palette.create` it sets `data-chrome=\"palette\"` and moves the palette\n * before the canvas `<svg>`; after every `palette.changed` it re-applies `role=\"toolbar\"`,\n * `aria-label`, roving `tabindex` and `aria-pressed` (from `tool-manager.update`);\n * - `keyboard.addListener(2000, …)` returning `true` for every chrome key, so `KeyboardBindings` and\n * the modeler's keyboard modules (priority 1000) never act on them.\n * It buffers the palette until `connectDiagramJs` hands it to a shell, so the diagram may be\n * constructed before `mountShell`.\n */\nexport const shellModule: ModuleDeclarationLike = {\n __init__: [SHELL_SERVICE],\n [SHELL_SERVICE]: [\"type\", ShellDiagramService],\n paletteTooltip: [\"value\", null],\n};\n","import {\n FIT_ANIMATION_MS,\n REDUCED_MOTION_CLASS,\n VIEW_TOLERANCE,\n ZOOM_MAX,\n ZOOM_MIN,\n canZoomIn,\n canZoomOut,\n easeStandard,\n fitViewbox,\n freeRectCenter,\n interpolateViewbox,\n matchChromeKey,\n sameView,\n type Bounds,\n type Insets,\n type Point,\n type ScaledViewbox,\n type Size,\n type ViewportState,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport type {\n CanvasLike,\n DiagramEventListener,\n DiagramViewbox,\n EventBusLike,\n InjectorLike,\n ZoomScrollLike,\n} from \"./types.js\";\n\nexport interface ViewportOptions {\n /**\n * Content bounds in diagram coordinates, tight around the content: the fit insets are the only\n * margin (guide §5.9). `undefined` = nothing to fit (empty file).\n */\n contentBounds(): Bounds | undefined;\n /** Fit insets at the moment of a fit (`shell.fitInsets()`). */\n insets(): Insets;\n /**\n * Default: `matchMedia(\"(prefers-reduced-motion: reduce)\").matches`, or `<html>` carries\n * `REDUCED_MOTION_CLASS` (VS Code's `workbench.reduceMotion`, mirrored by `mountVsCodeShell`).\n */\n prefersReducedMotion?: (() => boolean) | undefined;\n}\n\n/**\n * The view of one diagram (guide §5.8, §5.9): zoom steps through `zoomScroll.stepZoom`, fit with\n * insets and the 100 % cap, automatic refit on container resize until the user moves the view,\n * user-move detection by comparison with the last box the viewport set itself.\n */\nexport interface Viewport extends ZoomTarget {\n /** Explicit fit; animated (250ms) unless `animate: false` or reduced motion. View becomes automatic. */\n fit(options?: { animate?: boolean }): void;\n /**\n * Call after every successful import: fits (jump) the first time the content bounds are\n * non-empty, unless a persisted view was set (`setState`) or the user moved it. When the first\n * import is empty, under the same conditions, it shows 100 % around the centre of the free\n * rectangle instead, whatever zoom the renderer's import left (an empty file opens at 100 %);\n * that view is the viewport's own, not a user move, so the first content still fits. Otherwise\n * a no-op. A `restore` keeps the view of an empty file, so its first content still fits; content\n * the user created on the canvas does not (guide §5.9), so the next import keeps the view.\n */\n afterImport(): void;\n /** Restores a viewbox after a re-import (external change): reference updated, user-move state kept. */\n restore(viewbox: Bounds): void;\n /** The current viewbox (x, y, width, height), `undefined` before the canvas has a size. */\n getViewbox(): Bounds | undefined;\n /**\n * The centre of the free rectangle (the container minus `insets()`, guide §5.9) in diagram\n * coordinates, where keyboard creation from the palette places an element (guide §5.5).\n * `undefined` while the container is 0 × 0 and after `destroy`.\n */\n freeRectCenter(): Point | undefined;\n /** True until the user zoomed or panned; a resize then refits. */\n isAutomatic(): boolean;\n /** For VS Code `setState`; `undefined` before the first import. */\n getState(): ViewportState | undefined;\n /** Restores a persisted view (it wins over the first automatic fit). */\n setState(state: ViewportState): void;\n /** Disconnects observers, listeners and a running animation; also runs on `diagram.destroy`. */\n destroy(): void;\n}\n\n/** A viewport over `canvas` and `zoomScroll` of `diagram`, observing `canvas.getContainer()`. */\nexport function createViewport(diagram: InjectorLike, options: ViewportOptions): Viewport {\n return new DiagramViewport(diagram, options);\n}\n\ntype View = Pick<ScaledViewbox, \"x\" | \"y\" | \"scale\">;\n\n/**\n * Renderers replace the content between these events and may set the viewbox while doing so\n * (Event Storming frames its board); those changes are not the user's.\n */\nconst IMPORT_START_EVENTS = [\"import.parse.start\", \"import.render.start\"];\nconst IMPORT_DONE_EVENT = \"import.done\";\n\n/** Events after which the content bounds may differ (importers add shapes without `elements.changed`). */\nconst CONTENT_EVENTS = [\n \"shape.added\",\n \"shape.removed\",\n \"connection.added\",\n \"connection.removed\",\n \"diagram.clear\",\n];\n\n/** diagram-js `ZoomScroll`: `NUM_STEPS = 10` over `RANGE`, in log space. */\nconst ZOOM_STEP = Math.log10(ZOOM_MAX / ZOOM_MIN) / 10;\n\nconst CAPTURE = { capture: true } as const;\n\nexport class DiagramViewport implements Viewport {\n private readonly canvas: CanvasLike;\n private readonly eventBus: EventBusLike;\n private readonly container: HTMLElement;\n private readonly listeners = new Set<() => void>();\n private readonly subscriptions: Array<readonly [string | string[], DiagramEventListener]> = [];\n private readonly observer: ResizeObserver | undefined;\n private zoomScrollService: ZoomScrollLike | null | undefined;\n\n /** The last view the viewport set as its own (fit target, restore); user moves differ from it. */\n private reference: View | undefined;\n /** The last view written, animation frames included. */\n private lastWritten: View | undefined;\n /** The container size the current view was set or last resized for. */\n private lastSize: Size | undefined;\n private writing = 0;\n private userMoved = false;\n private importing = false;\n private imported = false;\n private firstFitPending = true;\n /** Nothing has decided the view yet, so an empty first import shows 100 %. */\n private emptyViewPending = true;\n /** The 100 % of an empty first import waits for the container to get a size (hidden tab). */\n private emptyViewDue = false;\n /** `canFit()` of the current content; the zoom panel asks every frame, `contentBounds` may be costly. */\n private fittable: boolean | undefined;\n private lastZoom = 1;\n /** An automatic fit is due but the container had no size yet (hidden tab). */\n private autoFitDue = false;\n /** A restored view waits for the container to get a size. */\n private pendingView: Bounds | undefined;\n private animation: { frame: number } | undefined;\n private resizeFrame: number | undefined;\n private destroyed = false;\n\n constructor(\n private readonly diagram: InjectorLike,\n private readonly options: ViewportOptions,\n ) {\n this.canvas = diagram.get<CanvasLike>(\"canvas\");\n this.eventBus = diagram.get<EventBusLike>(\"eventBus\");\n this.container = this.canvas.getContainer();\n\n this.subscribe(\"canvas.viewbox.changing\", this.notify);\n this.subscribe(\"canvas.viewbox.changed\", this.onViewboxChanged);\n this.subscribe(IMPORT_START_EVENTS, this.onImportStart);\n this.subscribe(IMPORT_DONE_EVENT, this.onImportDone);\n this.subscribe(\"elements.changed\", this.onElementsChanged);\n this.subscribe(CONTENT_EVENTS, this.onContentChanged);\n this.subscribe(\"diagram.destroy\", () => this.destroy());\n\n this.container.addEventListener(\"wheel\", this.onPointerInput, { capture: true, passive: true });\n this.container.addEventListener(\"pointerdown\", this.onPointerInput, CAPTURE);\n this.container.addEventListener(\"keydown\", this.onKeyInput, CAPTURE);\n\n if (typeof ResizeObserver === \"function\") {\n this.observer = new ResizeObserver(this.onResizeObserved);\n this.observer.observe(this.container);\n }\n }\n\n zoom(): number {\n if (!this.destroyed) this.lastZoom = this.canvas.zoom();\n return this.lastZoom;\n }\n\n stepZoom(direction: 1 | -1): void {\n if (this.destroyed) return;\n this.beforeUserChange();\n // Below 20 % ZoomScroll caps a step out to 20 %, which zooms in (guide §5.8).\n const zoom = this.canvas.zoom();\n if (direction < 0 ? !canZoomOut(zoom) : !canZoomIn(zoom)) return;\n const zoomScroll = this.zoomScroll();\n if (zoomScroll) zoomScroll.stepZoom(direction);\n else this.canvas.zoom(stepOnRaster(zoom, direction));\n }\n\n zoomToActual(): void {\n if (this.destroyed) return;\n this.beforeUserChange();\n this.canvas.zoom(1);\n }\n\n fit(options?: { animate?: boolean }): void {\n if (this.destroyed) return;\n this.importing = false;\n this.fitTo(options?.animate !== false && !this.prefersReducedMotion());\n }\n\n canFit(): boolean {\n if (this.destroyed) return false;\n this.fittable ??= hasExtent(this.options.contentBounds());\n return this.fittable;\n }\n\n onChange(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n afterImport(): void {\n if (this.destroyed) return;\n this.importing = false;\n this.imported = true;\n this.fittable = undefined;\n if (this.firstFitPending && this.canFit()) {\n this.firstFitPending = false;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n if (!this.userMoved && !this.fitTo(false)) this.autoFitDue = true;\n } else if (this.firstFitPending && this.emptyViewPending) {\n this.emptyViewPending = false;\n if (!this.userMoved && !this.showActualSize()) this.emptyViewDue = true;\n }\n this.notify();\n }\n\n restore(viewbox: Bounds): void {\n if (this.destroyed) return;\n this.importing = false;\n this.imported = true;\n this.fittable = undefined;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n this.cancelAnimation();\n this.show(viewbox);\n this.notify();\n }\n\n freeRectCenter(): Point | undefined {\n if (this.destroyed) return undefined;\n const centre = freeRectCenter(this.canvas.getSize(), this.options.insets());\n const view = this.currentView();\n if (!centre || !view) return undefined;\n return { x: view.x + centre.x / view.scale, y: view.y + centre.y / view.scale };\n }\n\n getViewbox(): Bounds | undefined {\n if (this.destroyed) return undefined;\n if (this.pendingView) return { ...this.pendingView };\n const size = this.canvas.getSize();\n if (!hasSize(size)) return undefined;\n const { x, y, scale } = this.canvas.viewbox();\n // The getter caches `outer` until the next change; the size is read fresh.\n return { x, y, width: size.width / scale, height: size.height / scale };\n }\n\n isAutomatic(): boolean {\n return !this.userMoved;\n }\n\n getState(): ViewportState | undefined {\n if (!this.imported) return undefined;\n const viewbox = this.getViewbox();\n return viewbox ? { viewbox, userMoved: this.userMoved } : undefined;\n }\n\n setState(state: ViewportState): void {\n if (this.destroyed) return;\n this.importing = false;\n this.imported = true;\n this.fittable = undefined;\n this.cancelAnimation();\n this.userMoved = state.userMoved;\n this.autoFitDue = false;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n if (this.canFit()) this.firstFitPending = false;\n this.show(state.viewbox);\n this.notify();\n }\n\n /** `canvas.resized()`; viewbox changes it causes (keep-selection-visible) are not user moves. */\n resized(): void {\n if (this.destroyed) return;\n this.writing++;\n try {\n this.canvas.resized();\n } finally {\n this.writing--;\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.cancelAnimation();\n if (this.resizeFrame !== undefined) cancelAnimationFrame(this.resizeFrame);\n this.resizeFrame = undefined;\n this.observer?.disconnect();\n this.container.removeEventListener(\"wheel\", this.onPointerInput, CAPTURE);\n this.container.removeEventListener(\"pointerdown\", this.onPointerInput, CAPTURE);\n this.container.removeEventListener(\"keydown\", this.onKeyInput, CAPTURE);\n for (const [events, listener] of this.subscriptions.splice(0)) this.eventBus.off(events, listener);\n this.listeners.clear();\n }\n\n /** Fits now (jump) or animated; false when there is nothing to fit or no container size. */\n private fitTo(animate: boolean): boolean {\n this.cancelAnimation();\n const bounds = this.options.contentBounds();\n if (!bounds) return false;\n const target = fitViewbox(bounds, this.canvas.getSize(), this.options.insets());\n if (!target) return false;\n this.userMoved = false;\n this.firstFitPending = false;\n this.autoFitDue = false;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n this.pendingView = undefined;\n const from = this.currentView();\n if (animate && from && !sameView(from, target) && typeof requestAnimationFrame === \"function\") {\n this.animate(from, target);\n } else {\n this.write(target);\n }\n return true;\n }\n\n private animate(from: ScaledViewbox, target: ScaledViewbox): void {\n this.reference = toView(target);\n const animation = { frame: 0 };\n const startedAt = performance.now();\n const step = (timestamp: number): void => {\n if (this.animation !== animation) return;\n if (!hasSize(this.canvas.getSize())) {\n // Hidden mid-animation: fit again once the container is back.\n this.cancelAnimation();\n this.autoFitDue = true;\n return;\n }\n const progress = Math.min(1, Math.max(0, (timestamp - startedAt) / FIT_ANIMATION_MS));\n if (progress >= 1) {\n this.animation = undefined;\n this.write(target);\n return;\n }\n this.write(interpolateViewbox(from, target, easeStandard(progress)), false);\n animation.frame = requestAnimationFrame(step);\n };\n this.animation = animation;\n animation.frame = requestAnimationFrame(step);\n }\n\n private cancelAnimation(): void {\n const animation = this.animation;\n if (!animation) return;\n this.animation = undefined;\n cancelAnimationFrame(animation.frame);\n if (this.lastWritten) this.reference = this.lastWritten;\n }\n\n /**\n * 100 % around the centre of the free rectangle, written as the viewport's own view; true when\n * the view is at 100 % afterwards, false while the container has no size.\n */\n private showActualSize(): boolean {\n const size = this.canvas.getSize();\n const centre = freeRectCenter(size, this.options.insets());\n const view = this.currentView();\n if (!centre || !view) return false;\n if (Math.abs(view.scale - 1) <= VIEW_TOLERANCE) return true;\n this.cancelAnimation();\n this.write({\n x: view.x + centre.x / view.scale - centre.x,\n y: view.y + centre.y / view.scale - centre.y,\n width: size.width,\n height: size.height,\n });\n return true;\n }\n\n /** Shows a restored view now, or once the container has a size. */\n private show(viewbox: Bounds): void {\n if (hasSize(this.canvas.getSize())) {\n this.pendingView = undefined;\n this.write(viewbox);\n } else {\n this.pendingView = { x: viewbox.x, y: viewbox.y, width: viewbox.width, height: viewbox.height };\n }\n }\n\n /** Callers make sure the container has a size: diagram-js would set a scale of 0 otherwise. */\n private write(box: Bounds, asReference = true): void {\n const size = this.canvas.getSize();\n // The scale diagram-js's setter derives from the box (`Canvas#viewbox`).\n const view: View = {\n x: box.x,\n y: box.y,\n scale: Math.min(size.width / box.width, size.height / box.height),\n };\n this.writing++;\n try {\n this.canvas.viewbox({ x: box.x, y: box.y, width: box.width, height: box.height });\n } finally {\n this.writing--;\n }\n this.lastWritten = view;\n if (asReference) this.reference = view;\n this.lastSize = { width: size.width, height: size.height };\n }\n\n private currentView(): ScaledViewbox | undefined {\n const size = this.canvas.getSize();\n const { x, y, scale } = this.canvas.viewbox();\n if (!(scale > 0 && Number.isFinite(scale))) return undefined;\n return { x, y, width: size.width / scale, height: size.height / scale, scale };\n }\n\n private beforeUserChange(): void {\n this.importing = false;\n this.cancelAnimation();\n }\n\n private zoomScroll(): ZoomScrollLike | null {\n if (this.zoomScrollService === undefined) {\n try {\n this.zoomScrollService = this.diagram.get<ZoomScrollLike | null>(\"zoomScroll\") ?? null;\n } catch {\n this.zoomScrollService = null;\n }\n }\n return this.zoomScrollService;\n }\n\n private prefersReducedMotion(): boolean {\n if (this.options.prefersReducedMotion) return this.options.prefersReducedMotion();\n if (this.container.ownerDocument.documentElement.classList.contains(REDUCED_MOTION_CLASS)) return true;\n return typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n }\n\n private isOwnView(current: View): boolean {\n if (this.reference && sameView(current, this.reference)) return true;\n return (\n this.animation !== undefined && this.lastWritten !== undefined && sameView(current, this.lastWritten)\n );\n }\n\n // Not a flag around the own writes alone: with `canvas.deferUpdate` the event of an own change\n // arrives up to 300ms later, so it is recognised by its view.\n private readonly onViewboxChanged = (event?: { viewbox?: DiagramViewbox }): void => {\n if (this.writing === 0 && !this.importing) {\n const current = event?.viewbox ?? this.canvas.viewbox();\n if (!this.isOwnView(current)) {\n this.cancelAnimation();\n this.userMoved = true;\n this.autoFitDue = false;\n this.emptyViewDue = false;\n }\n }\n this.notify();\n };\n\n private readonly onImportStart = (): void => {\n this.importing = true;\n };\n\n private readonly onImportDone = (): void => {\n this.importing = false;\n this.fittable = undefined;\n this.notify();\n };\n\n private readonly onContentChanged = (): void => {\n this.fittable = undefined;\n };\n\n // Guide §5.9: an element the user creates on the canvas never fits. Once such content exists,\n // only imports that keep the view follow, so the first automatic fit is no longer due.\n private readonly onElementsChanged = (): void => {\n this.fittable = undefined;\n if (this.imported && !this.importing && this.firstFitPending && this.canFit()) {\n this.firstFitPending = false;\n }\n this.notify();\n };\n\n // User input also ends an import window a failed import never closed with `import.done`.\n private readonly onPointerInput = (): void => {\n this.importing = false;\n this.cancelAnimation();\n };\n\n private readonly onKeyInput = (event: KeyboardEvent): void => {\n this.importing = false;\n if (matchChromeKey(event)) this.cancelAnimation();\n };\n\n private readonly onResizeObserved = (): void => {\n if (this.destroyed || this.resizeFrame !== undefined) return;\n if (typeof requestAnimationFrame !== \"function\") {\n this.onResize();\n return;\n }\n this.resizeFrame = requestAnimationFrame(() => {\n this.resizeFrame = undefined;\n this.onResize();\n });\n };\n\n private onResize(): void {\n if (this.destroyed) return;\n const size = this.canvas.getSize();\n if (!hasSize(size)) return;\n const changed = this.lastSize?.width !== size.width || this.lastSize.height !== size.height;\n if (!changed && !this.pendingView && !this.autoFitDue && !this.emptyViewDue) return;\n this.lastSize = { width: size.width, height: size.height };\n this.resized();\n const restored = this.pendingView;\n if (restored) {\n this.pendingView = undefined;\n this.write(restored);\n }\n if (this.userMoved) return;\n if (this.emptyViewDue) {\n this.emptyViewDue = false;\n this.showActualSize();\n return;\n }\n // A view restored for this very moment is not refitted; a fit that was due still runs.\n if (this.autoFitDue || (!restored && !this.firstFitPending)) this.fitTo(false);\n }\n\n private subscribe(events: string | string[], listener: (event: never) => unknown): void {\n this.eventBus.on(events, listener);\n this.subscriptions.push([events, listener]);\n }\n\n private readonly notify = (): void => {\n for (const listener of [...this.listeners]) listener();\n };\n}\n\nfunction toView(box: ScaledViewbox): View {\n return { x: box.x, y: box.y, scale: box.scale };\n}\n\nfunction hasSize(size: Size): boolean {\n return size.width > 0 && size.height > 0;\n}\n\nfunction hasExtent(bounds: Bounds | undefined): boolean {\n return bounds !== undefined && (bounds.width > 0 || bounds.height > 0);\n}\n\n/** `ZoomScroll#_zoom` for a diagram without `zoomScroll`: snap to the raster, one step, cap. */\nfunction stepOnRaster(zoom: number, direction: 1 | -1): number {\n const level = Math.round(Math.log10(zoom) / ZOOM_STEP) * ZOOM_STEP + ZOOM_STEP * direction;\n return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, 10 ** level));\n}\n","import type { Bounds } from \"../core/index.js\";\nimport type { ShellHandle } from \"../dom/index.js\";\nimport { shellServiceOf } from \"./service.js\";\nimport type { DiagramEventListener, EventBusLike, InjectorLike } from \"./types.js\";\nimport { DiagramViewport, type Viewport } from \"./viewport.js\";\n\nexport interface ConnectOptions {\n /**\n * Content bounds in diagram coordinates, tight around the content: the fit insets are the only\n * margin (guide §5.9). `undefined` = nothing to fit (empty file).\n */\n contentBounds(): Bounds | undefined;\n /**\n * An empty file (guide §13.5: no element, only whitespace, comments or a title), which shows the\n * empty-file hint. Default: `contentBounds()` is empty. A notation whose bounds are never empty\n * (Wardley's plot) passes its own test.\n */\n isEmpty?: (() => boolean) | undefined;\n prefersReducedMotion?: (() => boolean) | undefined;\n}\n\nexport interface DiagramJsConnection {\n readonly viewport: Viewport;\n /**\n * Unbinds viewport, palette, keys and the hint sync from the shell; destroys neither the diagram\n * nor the shell. Runs by itself on `diagram.destroy`.\n */\n destroy(): void;\n}\n\n/** After the viewport's own listeners, so its content state is fresh when the hint reads it. */\nconst HINT_SYNC_PRIORITY = 500;\n\n/**\n * Connects a diagram built with `shellModule` to a mounted shell: creates the viewport with\n * `shell.fitInsets`, binds it with `shell.setZoomTarget`, registers the palette\n * (`shell.registerPalette`), keeps the empty-file hint in sync with the diagram (after every\n * `import.done` and `elements.changed`, so the first element created on the canvas hides it) and\n * calls `canvas.resized()`. Throws when `shellModule` is missing.\n */\nexport function connectDiagramJs(\n shell: ShellHandle,\n diagram: InjectorLike,\n options: ConnectOptions,\n): DiagramJsConnection {\n const service = shellServiceOf(diagram);\n const eventBus = diagram.get<EventBusLike>(\"eventBus\");\n const prefersReducedMotion = options.prefersReducedMotion?.bind(options);\n const viewport = new DiagramViewport(diagram, {\n contentBounds: () => options.contentBounds(),\n insets: () => shell.fitInsets(),\n ...(prefersReducedMotion ? { prefersReducedMotion } : {}),\n });\n shell.setZoomTarget(viewport);\n const detachPalette = service.attachShell(shell);\n // The shell has moved the canvas element into its slot; diagram-js caches the old size.\n viewport.resized();\n\n const isEmpty = options.isEmpty ? () => options.isEmpty?.() === true : () => !viewport.canFit();\n const syncHint: DiagramEventListener = () => shell.setEmptyHint(isEmpty());\n eventBus.on([\"import.done\", \"elements.changed\"], HINT_SYNC_PRIORITY, syncHint);\n\n let destroyed = false;\n const destroy = (): void => {\n if (destroyed) return;\n destroyed = true;\n eventBus.off([\"import.done\", \"elements.changed\"], syncHint);\n eventBus.off(\"diagram.destroy\", destroy);\n detachPalette();\n shell.setZoomTarget(null);\n viewport.destroy();\n };\n eventBus.on(\"diagram.destroy\", destroy);\n return { viewport, destroy };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/diagram-js/palette-skin.ts","../src/diagram-js/service.ts","../src/diagram-js/module.ts","../src/diagram-js/viewport.ts","../src/diagram-js/connect.ts"],"sourcesContent":["import { ariaKeyShortcutsFromLabel, defaultMessages } from \"../core/index.js\";\nimport type { PaletteReadOnlyState, TooltipContent } from \"../dom/index.js\";\n\n/** The diagram-js palette group of the tools (`Palette#updateToolHighlight` looks for it). */\nexport const TOOLS_GROUP = \"tools\";\n\n/**\n * The entries that stay active on a read-only canvas (guide §13.5: Lasso and Hand). Every other\n * entry changes the diagram, also tools such as drawing, space or connect.\n */\nexport const READ_ONLY_ACTIONS: ReadonlySet<string> = new Set([\"lasso-tool\", \"hand-tool\"]);\n\nconst TOOL_ACTION_SUFFIX = \"-tool\";\nconst ENTRIES_SELECTOR = \".djs-palette-entries\";\nconst ENTRY_SELECTOR = \".entry\";\n\n/** One entry of `palette.getEntries()`, as far as the skin reads it. */\nexport interface PaletteEntryLike {\n title?: string | undefined;\n shortcut?: string | undefined;\n /** `aria-keyshortcuts` (WAI-ARIA names); default `ariaKeyShortcutsFromLabel(shortcut)`. */\n ariaKeyShortcuts?: string | undefined;\n group?: string | undefined;\n}\n\n/**\n * The shell's additions to the diagram-js palette container (guide §5.5): `data-chrome`, the\n * toolbar semantics of the entries, the roving tab stop with its keys, `aria-pressed` for the\n * active tool and `aria-disabled` in read-only. diagram-js clears and rebuilds every entry on each\n * change, so `refresh()` re-applies all of it after every `palette.changed`.\n */\nexport class PaletteSkin {\n private label = defaultMessages.tools;\n private activeTool: string | null = null;\n /** The veto of a read-only canvas, at once with the invalid import. */\n private locked = false;\n /** The `aria-disabled` marks of a read-only canvas, once the shell's delay has passed. */\n private readOnlyShown = false;\n private entries: Readonly<Record<string, PaletteEntryLike>> = {};\n private rovingAction: string | undefined;\n private focusedEntry: HTMLElement | undefined;\n /** The `aria-disabled` an entry had before read-only marked it (`null`: none). */\n private readonly disabledEntries = new WeakMap<Element, string | null>();\n\n constructor(\n readonly element: HTMLElement,\n private readonly readEntries: () => Readonly<Record<string, PaletteEntryLike>>,\n ) {\n element.setAttribute(\"data-chrome\", \"palette\");\n element.addEventListener(\"keydown\", this.onKeydown);\n element.addEventListener(\"focusin\", this.onFocusIn);\n element.addEventListener(\"focusout\", this.onFocusOut);\n this.refresh();\n }\n\n setLabel(label: string): void {\n this.label = label;\n this.apply();\n }\n\n setActiveTool(tool: string | null): void {\n this.activeTool = tool;\n this.apply();\n }\n\n setReadOnly(state: PaletteReadOnlyState): void {\n this.locked = state.locked;\n this.readOnlyShown = state.locked && state.shown;\n this.apply();\n }\n\n /**\n * Whether `palette.trigger` must refuse `entry`: on a locked canvas every entry but Lasso and\n * Hand, also before their marks show. `palette.trigger` carries the entry definition without its\n * id, so the entry element is found through the DOM event; without one, only the tools group\n * passes.\n */\n vetoes(entry: PaletteEntryLike, event: Event | undefined): boolean {\n if (!this.locked) return false;\n const element = this.entryOf(\n (event as { delegateTarget?: EventTarget } | undefined)?.delegateTarget ?? event?.target ?? null,\n );\n if (element) return !staysActive(element);\n return entry.group !== TOOLS_GROUP;\n }\n\n /** After `palette.changed`: re-read the entries and re-apply every attribute. */\n refresh(): void {\n this.entries = this.readEntries();\n this.apply();\n }\n\n entryTooltip(entry: HTMLElement): TooltipContent | null {\n const action = entry.getAttribute(\"data-action\");\n const definition = action === null ? undefined : this.entries[action];\n if (!definition?.title) return null;\n return definition.shortcut\n ? { label: definition.title, shortcut: definition.shortcut }\n : { label: definition.title };\n }\n\n destroy(): void {\n this.element.removeEventListener(\"keydown\", this.onKeydown);\n this.element.removeEventListener(\"focusin\", this.onFocusIn);\n this.element.removeEventListener(\"focusout\", this.onFocusOut);\n this.focusedEntry = undefined;\n }\n\n private apply(): void {\n const container = this.element.querySelector<HTMLElement>(ENTRIES_SELECTOR);\n if (container) {\n container.setAttribute(\"role\", \"toolbar\");\n container.setAttribute(\"aria-label\", this.label);\n }\n const entries = this.entryElements();\n for (const entry of entries) {\n if (!entry.hasAttribute(\"role\")) entry.setAttribute(\"role\", \"button\");\n this.applyKeyShortcuts(entry);\n this.applyPressed(entry);\n this.applyDisabled(entry);\n }\n this.applyTabStops(entries);\n this.restoreFocus(entries);\n }\n\n // Guide §5.6: a button with a shortcut names it for assistive technology, not only in the chip.\n private applyKeyShortcuts(entry: HTMLElement): void {\n const action = actionOf(entry);\n const definition = action === undefined ? undefined : this.entries[action];\n const keyShortcuts =\n definition?.ariaKeyShortcuts ??\n (definition?.shortcut ? ariaKeyShortcutsFromLabel(definition.shortcut) : undefined);\n if (keyShortcuts) entry.setAttribute(\"aria-keyshortcuts\", keyShortcuts);\n }\n\n private applyPressed(entry: HTMLElement): void {\n const action = actionOf(entry);\n if (groupOf(entry) !== TOOLS_GROUP || !action?.endsWith(TOOL_ACTION_SUFFIX)) return;\n const tool = action.slice(0, -TOOL_ACTION_SUFFIX.length);\n entry.setAttribute(\"aria-pressed\", String(tool === this.activeTool));\n }\n\n private applyDisabled(entry: HTMLElement): void {\n if (this.readOnlyShown && !staysActive(entry)) {\n if (!this.disabledEntries.has(entry)) {\n this.disabledEntries.set(entry, entry.getAttribute(\"aria-disabled\"));\n }\n entry.setAttribute(\"aria-disabled\", \"true\");\n return;\n }\n if (!this.disabledEntries.has(entry)) return;\n const previous = this.disabledEntries.get(entry);\n this.disabledEntries.delete(entry);\n if (previous === null || previous === undefined) entry.removeAttribute(\"aria-disabled\");\n else entry.setAttribute(\"aria-disabled\", previous);\n }\n\n private applyTabStops(entries: readonly HTMLElement[]): void {\n const stop = entries.find((entry) => actionOf(entry) === this.rovingAction) ?? entries[0];\n for (const entry of entries) entry.tabIndex = entry === stop ? 0 : -1;\n }\n\n // A rebuild removes the focused entry; without this the focus would fall back to <body>.\n private restoreFocus(entries: readonly HTMLElement[]): void {\n const lost = this.focusedEntry;\n if (!lost || lost.isConnected) return;\n this.focusedEntry = undefined;\n const replacement = entries.find((entry) => actionOf(entry) === actionOf(lost));\n const active = this.element.ownerDocument.activeElement;\n const focusIsNowhere = !active || active === this.element.ownerDocument.body;\n if (replacement && focusIsNowhere) replacement.focus();\n }\n\n private entryElements(): HTMLElement[] {\n const container = this.element.querySelector(ENTRIES_SELECTOR);\n return container ? Array.from(container.querySelectorAll<HTMLElement>(ENTRY_SELECTOR)) : [];\n }\n\n private entryOf(target: EventTarget | null): HTMLElement | undefined {\n if (!(target instanceof Element)) return undefined;\n const entry = target.closest<HTMLElement>(ENTRY_SELECTOR);\n return entry && this.element.contains(entry) ? entry : undefined;\n }\n\n private readonly onFocusIn = (event: FocusEvent): void => {\n const entry = this.entryOf(event.target);\n if (!entry) return;\n this.focusedEntry = entry;\n this.rovingAction = actionOf(entry);\n this.applyTabStops(this.entryElements());\n };\n\n private readonly onFocusOut = (event: FocusEvent): void => {\n const entry = this.entryOf(event.target);\n if (!entry || entry !== this.focusedEntry || !entry.isConnected) return;\n const next = event.relatedTarget;\n if (!(next instanceof Node) || !this.element.contains(next)) this.focusedEntry = undefined;\n };\n\n private readonly onKeydown = (event: KeyboardEvent): void => {\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;\n const entry = this.entryOf(event.target);\n if (!entry) return;\n const entries = this.entryElements();\n const index = entries.indexOf(entry);\n const last = entries.length - 1;\n let next: HTMLElement | undefined;\n switch (event.key) {\n case \"ArrowLeft\":\n next = entries[index <= 0 ? last : index - 1];\n break;\n case \"ArrowRight\":\n next = entries[index >= last ? 0 : index + 1];\n break;\n case \"Home\":\n next = entries[0];\n break;\n case \"End\":\n next = entries[last];\n break;\n case \"Enter\":\n case \" \":\n event.preventDefault();\n event.stopPropagation();\n if (!event.repeat) activate(entry);\n return;\n default:\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n if (!next) return;\n this.rovingAction = actionOf(next);\n this.applyTabStops(entries);\n next.focus();\n };\n}\n\nfunction actionOf(entry: Element): string | undefined {\n return entry.getAttribute(\"data-action\") ?? undefined;\n}\n\nfunction staysActive(entry: Element): boolean {\n const action = actionOf(entry);\n return action !== undefined && READ_ONLY_ACTIONS.has(action);\n}\n\nfunction groupOf(entry: Element): string | undefined {\n return entry.closest(\".group\")?.getAttribute(\"data-group\") ?? undefined;\n}\n\n// Enter and Space activate an entry with a synthetic click: `detail` 0, clientX/Y at the entry's\n// centre. A creating entry tells it from a pointer click (`detail` ≥ 1) by that and places its\n// element at `viewport.freeRectCenter()` (guide §5.5). diagram-js handles entry clicks through a\n// delegate on the palette container, so it goes through `palette.trigger` and its read-only veto\n// exactly like a pointer click.\nfunction activate(entry: HTMLElement): void {\n const bounds = entry.getBoundingClientRect();\n entry.dispatchEvent(\n new MouseEvent(\"click\", {\n bubbles: true,\n cancelable: true,\n clientX: bounds.left + bounds.width / 2,\n clientY: bounds.top + bounds.height / 2,\n }),\n );\n}\n","import { TEXT_FIELD_SELECTOR, defaultMessages, isUndoRedoKey, matchChromeKey } from \"../core/index.js\";\nimport type { ShellHandle } from \"../dom/index.js\";\nimport { PaletteSkin, type PaletteEntryLike } from \"./palette-skin.js\";\nimport type {\n CanvasLike,\n DiagramEventListener,\n EventBusLike,\n InjectorLike,\n KeyboardLike,\n PaletteLike,\n} from \"./types.js\";\n\n/** The didi name of the service `shellModule` registers. */\nexport const SHELL_SERVICE = \"modelerShell\";\n\n/** Above `KeyboardBindings` and the modelers' keyboard modules (default priority 1000). */\nexport const KEYBOARD_PRIORITY = 2000;\n\n/** Ahead of every default-priority `palette.trigger` listener, so the read-only veto comes first. */\nconst TRIGGER_PRIORITY = 2000;\n\n/** A palette without a shell is editable. */\nconst EDITABLE = { locked: false, shown: false } as const;\n\n/** What the shell sets on the canvas `<svg>` while a shell is attached, restored on detach. */\nconst CANVAS_ATTRIBUTES = [\"role\", \"aria-label\"] as const;\n\nfunction isTextField(target: EventTarget | null): boolean {\n if (!target || typeof (target as Element).closest !== \"function\") return false;\n return (\n (target as HTMLElement).isContentEditable === true ||\n (target as Element).closest(TEXT_FIELD_SELECTOR) !== null\n );\n}\n\n/** didi's injector, which resolves a missing service to `null` with `strict: false`. */\ninterface DidiInjectorLike {\n get(name: string, strict?: boolean): unknown;\n}\n\ninterface KeyboardEventContext {\n keyEvent?: KeyboardEvent;\n}\n\ninterface PaletteTriggerEvent {\n entry?: PaletteEntryLike;\n event?: Event;\n}\n\n/**\n * The diagram-side half of `shellModule`: the palette skin, the chrome-key guard on the diagram-js\n * keyboard and the buffer that holds the palette until `connectDiagramJs` hands it to a shell.\n */\nexport class ShellDiagramService {\n static $inject = [\"eventBus\", \"injector\"];\n\n private svg: Element | undefined;\n /** The canvas `<svg>`'s own `role` and `aria-label` before the shell named it. */\n private canvasOriginals: Map<string, string | null> | undefined;\n private skin: PaletteSkin | undefined;\n private activeTool: string | null = null;\n private shell: ShellHandle | undefined;\n private unregisterPalette: (() => void) | undefined;\n private readonly subscriptions: Array<readonly [string, DiagramEventListener]> = [];\n private destroyed = false;\n\n constructor(\n private readonly eventBus: EventBusLike,\n private readonly injector: DidiInjectorLike,\n ) {\n this.subscribe(\"canvas.init\", (event: { svg?: Element }) => {\n this.svg = event.svg;\n this.nameCanvas();\n });\n this.subscribe(\"palette.create\", (event: { container: HTMLElement }) =>\n this.onPaletteCreate(event.container),\n );\n this.subscribe(\"palette.changed\", () => this.skin?.refresh());\n this.subscribe(\"tool-manager.update\", (event: { tool?: string | null }) => {\n this.activeTool = event.tool ?? null;\n this.skin?.setActiveTool(this.activeTool);\n });\n this.subscribe(\"palette.trigger\", this.onPaletteTrigger, TRIGGER_PRIORITY);\n this.subscribe(\"diagram.destroy\", () => this.destroy());\n\n const keyboard = injector.get(\"keyboard\", false) as KeyboardLike | null;\n if (keyboard) {\n keyboard.addListener(KEYBOARD_PRIORITY, this.onKeyboardKeydown);\n this.subscriptions.push([\"keyboard.keydown\", this.onKeyboardKeydown]);\n }\n }\n\n /**\n * Hands the palette (now or once diagram-js creates it) to `shell`; returns the detach\n * function. A later call replaces the earlier shell.\n */\n attachShell(shell: ShellHandle): () => void {\n this.detachShell();\n if (this.destroyed) return () => undefined;\n this.shell = shell;\n this.skin?.setLabel(shell.messages.tools);\n this.nameCanvas();\n this.registerPalette();\n return () => {\n if (this.shell === shell) this.detachShell();\n };\n }\n\n private registerPalette(): void {\n const { shell, skin } = this;\n if (!shell || !skin) return;\n this.unregisterPalette?.();\n this.unregisterPalette = shell.registerPalette({\n element: skin.element,\n entryTooltip: (entry) => skin.entryTooltip(entry),\n setReadOnly: (state) => skin.setReadOnly(state),\n });\n }\n\n private detachShell(): void {\n const unregister = this.unregisterPalette;\n this.unregisterPalette = undefined;\n this.shell = undefined;\n unregister?.();\n this.unnameCanvas();\n this.skin?.setReadOnly(EDITABLE);\n this.skin?.setLabel(defaultMessages.tools);\n }\n\n /**\n * The focusable canvas is an application with a name (WCAG 4.1.2): screen readers switch to focus\n * mode, so the canvas's single-key commands reach it. A role or name the modeler set stays.\n */\n private nameCanvas(): void {\n const { svg, shell } = this;\n if (!svg || !shell || this.canvasOriginals) return;\n this.canvasOriginals = new Map(CANVAS_ATTRIBUTES.map((name) => [name, svg.getAttribute(name)]));\n if (!svg.hasAttribute(\"role\")) svg.setAttribute(\"role\", \"application\");\n if (!svg.hasAttribute(\"aria-label\") && !svg.hasAttribute(\"aria-labelledby\")) {\n svg.setAttribute(\"aria-label\", shell.messages.canvas);\n }\n }\n\n private unnameCanvas(): void {\n const { svg, canvasOriginals } = this;\n this.canvasOriginals = undefined;\n if (!svg || !canvasOriginals) return;\n for (const [name, value] of canvasOriginals) {\n if (value === null) svg.removeAttribute(name);\n else svg.setAttribute(name, value);\n }\n }\n\n private onPaletteCreate(container: HTMLElement): void {\n this.skin?.destroy();\n const palette = this.injector.get(\"palette\", false) as PaletteLike | null;\n const skin = new PaletteSkin(container, () => palette?.getEntries() ?? {});\n this.skin = skin;\n skin.setActiveTool(this.activeTool);\n if (this.shell) skin.setLabel(this.shell.messages.tools);\n this.moveBeforeCanvas(container);\n this.registerPalette();\n }\n\n // Palette#_init appends the palette after the <svg>; in front of it the palette comes first in\n // the tab order (guide §5.14).\n private moveBeforeCanvas(container: HTMLElement): void {\n const parent = container.parentElement ?? this.canvasContainer();\n if (!parent) return;\n const svg =\n this.svg?.parentNode === parent\n ? this.svg\n : Array.from(parent.children).find((child) => child.localName === \"svg\");\n if (svg) parent.insertBefore(container, svg);\n }\n\n private canvasContainer(): HTMLElement | undefined {\n const canvas = this.injector.get(\"canvas\", false) as CanvasLike | null;\n return canvas?.getContainer();\n }\n\n private readonly onPaletteTrigger = (event: PaletteTriggerEvent): false | undefined => {\n if (!event.entry || !this.skin?.vetoes(event.entry, event.event)) return undefined;\n // A vetoed dragstart would otherwise still start the browser's native drag of the entry.\n event.event?.preventDefault();\n return false;\n };\n\n /**\n * `true` stops the diagram-js keyboard (and makes it call `preventDefault`), `false` stops it\n * without: a chrome key in a text field inside the `<svg>` stays the field's (Shift+1 types \"!\"),\n * and in the IDE host undo and redo stay the document's (guide §13.5), so they reach VS Code\n * instead of the canvas `commandStack`.\n */\n private readonly onKeyboardKeydown = (context: KeyboardEventContext): boolean | undefined => {\n const event = context.keyEvent;\n if (!event) return undefined;\n // `false` keeps every other diagram-js listener off the key without preventing it: in a text\n // field the field keeps it, behind the web app's start screen the browser zooms the page.\n if (matchChromeKey(event))\n return !isTextField(event.target) && this.shell?.isEmptyStateShown?.() !== true;\n if (this.shell?.host === \"ide\" && isUndoRedoKey(event)) return false;\n return undefined;\n };\n\n private subscribe<E>(name: string, listener: (event: E) => unknown, priority?: number): void {\n const handler = listener as DiagramEventListener;\n if (priority === undefined) this.eventBus.on(name, handler);\n else this.eventBus.on(name, priority, handler);\n this.subscriptions.push([name, handler]);\n }\n\n private destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.detachShell();\n this.skin?.destroy();\n this.skin = undefined;\n this.svg = undefined;\n for (const [name, listener] of this.subscriptions.splice(0)) this.eventBus.off(name, listener);\n }\n}\n\n/** The service of `shellModule` in `diagram`; throws when the modeler was built without it. */\nexport function shellServiceOf(diagram: InjectorLike): ShellDiagramService {\n let service: unknown;\n try {\n service = diagram.get<unknown>(SHELL_SERVICE);\n } catch {\n service = undefined;\n }\n if (!isShellService(service)) {\n throw new Error(\n \"@miragon/modeler-shell: connectDiagramJs needs shellModule in the modeler's modules (additionalModules: [shellModule])\",\n );\n }\n return service;\n}\n\n// Duck-typed rather than `instanceof`, so a shellModule from the CJS build connects to the ESM one.\nfunction isShellService(value: unknown): value is ShellDiagramService {\n return typeof (value as Partial<ShellDiagramService> | null)?.attachShell === \"function\";\n}\n","import { SHELL_SERVICE, ShellDiagramService } from \"./service.js\";\nimport type { ModuleDeclarationLike } from \"./types.js\";\n\n/**\n * Add to the modeler's modules (`additionalModules`, after the renderer's own modules):\n * - `paletteTooltip: [\"value\", null]` removes diagram-js's (or the renderer's) palette tooltip; the\n * chrome tooltip takes over;\n * - the palette skin: on `palette.create` it sets `data-chrome=\"palette\"` and moves the palette\n * before the canvas `<svg>`; after every `palette.changed` it re-applies `role=\"toolbar\"`,\n * `aria-label`, roving `tabindex` and `aria-pressed` (from `tool-manager.update`);\n * - `keyboard.addListener(2000, …)` returning `true` for every chrome key, so `KeyboardBindings` and\n * the modeler's keyboard modules (priority 1000) never act on them.\n * It buffers the palette until `connectDiagramJs` hands it to a shell, so the diagram may be\n * constructed before `mountShell`.\n */\nexport const shellModule: ModuleDeclarationLike = {\n __init__: [SHELL_SERVICE],\n [SHELL_SERVICE]: [\"type\", ShellDiagramService],\n paletteTooltip: [\"value\", null],\n};\n","import {\n FIT_ANIMATION_MS,\n REDUCED_MOTION_CLASS,\n VIEW_TOLERANCE,\n ZOOM_MAX,\n ZOOM_MIN,\n canZoomIn,\n canZoomOut,\n easeStandard,\n fitViewbox,\n freeRectCenter,\n interpolateViewbox,\n matchChromeKey,\n sameView,\n type Bounds,\n type Insets,\n type Point,\n type ScaledViewbox,\n type Size,\n type ViewportState,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport type {\n CanvasLike,\n DiagramEventListener,\n DiagramViewbox,\n EventBusLike,\n InjectorLike,\n ZoomScrollLike,\n} from \"./types.js\";\n\nexport interface ViewportOptions {\n /**\n * Content bounds in diagram coordinates, tight around the content: the fit insets are the only\n * margin (guide §5.9). `undefined` = nothing to fit (empty file).\n */\n contentBounds(): Bounds | undefined;\n /** Fit insets at the moment of a fit (`shell.fitInsets()`). */\n insets(): Insets;\n /**\n * Default: `matchMedia(\"(prefers-reduced-motion: reduce)\").matches`, or `<html>` carries\n * `REDUCED_MOTION_CLASS` (VS Code's `workbench.reduceMotion`, mirrored by `mountVsCodeShell`).\n */\n prefersReducedMotion?: (() => boolean) | undefined;\n}\n\n/**\n * The view of one diagram (guide §5.8, §5.9): zoom steps through `zoomScroll.stepZoom`, fit with\n * insets and the 100 % cap, automatic refit on container resize until the user moves the view,\n * user-move detection by comparison with the last box the viewport set itself.\n */\nexport interface Viewport extends ZoomTarget {\n /** Explicit fit; animated (250ms) unless `animate: false` or reduced motion. View becomes automatic. */\n fit(options?: { animate?: boolean }): void;\n /**\n * Call after every successful import: fits (jump) the first time the content bounds are\n * non-empty, unless a persisted view was set (`setState`) or the user moved it. When the first\n * import is empty, under the same conditions, it shows 100 % around the centre of the free\n * rectangle instead, whatever zoom the renderer's import left (an empty file opens at 100 %);\n * that view is the viewport's own, not a user move, so the first content still fits. Otherwise\n * a no-op. A `restore` keeps the view of an empty file, so its first content still fits; content\n * the user created on the canvas does not (guide §5.9), so the next import keeps the view.\n */\n afterImport(): void;\n /**\n * The web app opens another document (New diagram, Open…, Import…, Show example, a shared link,\n * a dropped file): the next `afterImport()` counts as the first again (guide §5.9). Forgets the\n * user's moves, a stored view and a pending restore, and stops a running fit animation, so\n * non-empty content fits (jump) and an empty document shows 100 %. Call it before the import.\n */\n newDocument(): void;\n /** Restores a viewbox after a re-import (external change): reference updated, user-move state kept. */\n restore(viewbox: Bounds): void;\n /** The current viewbox (x, y, width, height), `undefined` before the canvas has a size. */\n getViewbox(): Bounds | undefined;\n /**\n * The centre of the free rectangle (the container minus `insets()`, guide §5.9) in diagram\n * coordinates, where keyboard creation from the palette places an element (guide §5.5).\n * `undefined` while the container is 0 × 0 and after `destroy`.\n */\n freeRectCenter(): Point | undefined;\n /** True until the user zoomed or panned; a resize then refits. */\n isAutomatic(): boolean;\n /** For VS Code `setState`; `undefined` before the first import. */\n getState(): ViewportState | undefined;\n /** Restores a persisted view (it wins over the first automatic fit). */\n setState(state: ViewportState): void;\n /** Disconnects observers, listeners and a running animation; also runs on `diagram.destroy`. */\n destroy(): void;\n}\n\n/** A viewport over `canvas` and `zoomScroll` of `diagram`, observing `canvas.getContainer()`. */\nexport function createViewport(diagram: InjectorLike, options: ViewportOptions): Viewport {\n return new DiagramViewport(diagram, options);\n}\n\ntype View = Pick<ScaledViewbox, \"x\" | \"y\" | \"scale\">;\n\n/**\n * Renderers replace the content between these events and may set the viewbox while doing so\n * (Event Storming frames its board); those changes are not the user's.\n */\nconst IMPORT_START_EVENTS = [\"import.parse.start\", \"import.render.start\"];\nconst IMPORT_DONE_EVENT = \"import.done\";\n\n/** Events after which the content bounds may differ (importers add shapes without `elements.changed`). */\nconst CONTENT_EVENTS = [\n \"shape.added\",\n \"shape.removed\",\n \"connection.added\",\n \"connection.removed\",\n \"diagram.clear\",\n];\n\n/** diagram-js `ZoomScroll`: `NUM_STEPS = 10` over `RANGE`, in log space. */\nconst ZOOM_STEP = Math.log10(ZOOM_MAX / ZOOM_MIN) / 10;\n\nconst CAPTURE = { capture: true } as const;\n\nexport class DiagramViewport implements Viewport {\n private readonly canvas: CanvasLike;\n private readonly eventBus: EventBusLike;\n private readonly container: HTMLElement;\n private readonly listeners = new Set<() => void>();\n private readonly subscriptions: Array<readonly [string | string[], DiagramEventListener]> = [];\n private readonly observer: ResizeObserver | undefined;\n private zoomScrollService: ZoomScrollLike | null | undefined;\n\n /** The last view the viewport set as its own (fit target, restore); user moves differ from it. */\n private reference: View | undefined;\n /** The last view written, animation frames included. */\n private lastWritten: View | undefined;\n /** The container size the current view was set or last resized for. */\n private lastSize: Size | undefined;\n private writing = 0;\n private userMoved = false;\n private importing = false;\n private imported = false;\n private firstFitPending = true;\n /** Nothing has decided the view yet, so an empty first import shows 100 %. */\n private emptyViewPending = true;\n /** The 100 % of an empty first import waits for the container to get a size (hidden tab). */\n private emptyViewDue = false;\n /** `canFit()` of the current content; the zoom panel asks every frame, `contentBounds` may be costly. */\n private fittable: boolean | undefined;\n private lastZoom = 1;\n /** An automatic fit is due but the container had no size yet (hidden tab). */\n private autoFitDue = false;\n /** A restored view waits for the container to get a size. */\n private pendingView: Bounds | undefined;\n private animation: { frame: number } | undefined;\n private resizeFrame: number | undefined;\n private destroyed = false;\n\n constructor(\n private readonly diagram: InjectorLike,\n private readonly options: ViewportOptions,\n ) {\n this.canvas = diagram.get<CanvasLike>(\"canvas\");\n this.eventBus = diagram.get<EventBusLike>(\"eventBus\");\n this.container = this.canvas.getContainer();\n\n this.subscribe(\"canvas.viewbox.changing\", this.notify);\n this.subscribe(\"canvas.viewbox.changed\", this.onViewboxChanged);\n this.subscribe(IMPORT_START_EVENTS, this.onImportStart);\n this.subscribe(IMPORT_DONE_EVENT, this.onImportDone);\n this.subscribe(\"elements.changed\", this.onElementsChanged);\n this.subscribe(CONTENT_EVENTS, this.onContentChanged);\n this.subscribe(\"diagram.destroy\", () => this.destroy());\n\n this.container.addEventListener(\"wheel\", this.onPointerInput, { capture: true, passive: true });\n this.container.addEventListener(\"pointerdown\", this.onPointerInput, CAPTURE);\n this.container.addEventListener(\"keydown\", this.onKeyInput, CAPTURE);\n\n if (typeof ResizeObserver === \"function\") {\n this.observer = new ResizeObserver(this.onResizeObserved);\n this.observer.observe(this.container);\n }\n }\n\n zoom(): number {\n if (!this.destroyed) this.lastZoom = this.canvas.zoom();\n return this.lastZoom;\n }\n\n stepZoom(direction: 1 | -1): void {\n if (this.destroyed) return;\n this.beforeUserChange();\n // Below 20 % ZoomScroll caps a step out to 20 %, which zooms in (guide §5.8).\n const zoom = this.canvas.zoom();\n if (direction < 0 ? !canZoomOut(zoom) : !canZoomIn(zoom)) return;\n const zoomScroll = this.zoomScroll();\n if (zoomScroll) zoomScroll.stepZoom(direction);\n else this.canvas.zoom(stepOnRaster(zoom, direction));\n }\n\n zoomToActual(): void {\n if (this.destroyed) return;\n this.beforeUserChange();\n this.canvas.zoom(1);\n }\n\n fit(options?: { animate?: boolean }): void {\n if (this.destroyed) return;\n this.importing = false;\n this.fitTo(options?.animate !== false && !this.prefersReducedMotion());\n }\n\n canFit(): boolean {\n if (this.destroyed) return false;\n this.fittable ??= hasExtent(this.options.contentBounds());\n return this.fittable;\n }\n\n onChange(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n afterImport(): void {\n if (this.destroyed) return;\n this.importing = false;\n this.imported = true;\n this.fittable = undefined;\n if (this.firstFitPending && this.canFit()) {\n this.firstFitPending = false;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n if (!this.userMoved && !this.fitTo(false)) this.autoFitDue = true;\n } else if (this.firstFitPending && this.emptyViewPending) {\n this.emptyViewPending = false;\n if (!this.userMoved && !this.showActualSize()) this.emptyViewDue = true;\n }\n this.notify();\n }\n\n newDocument(): void {\n if (this.destroyed) return;\n this.cancelAnimation();\n this.userMoved = false;\n this.firstFitPending = true;\n this.emptyViewPending = true;\n this.emptyViewDue = false;\n this.autoFitDue = false;\n this.pendingView = undefined;\n this.fittable = undefined;\n }\n\n restore(viewbox: Bounds): void {\n if (this.destroyed) return;\n this.importing = false;\n this.imported = true;\n this.fittable = undefined;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n this.cancelAnimation();\n this.show(viewbox);\n this.notify();\n }\n\n freeRectCenter(): Point | undefined {\n if (this.destroyed) return undefined;\n const centre = freeRectCenter(this.canvas.getSize(), this.options.insets());\n const view = this.currentView();\n if (!centre || !view) return undefined;\n return { x: view.x + centre.x / view.scale, y: view.y + centre.y / view.scale };\n }\n\n getViewbox(): Bounds | undefined {\n if (this.destroyed) return undefined;\n if (this.pendingView) return { ...this.pendingView };\n const size = this.canvas.getSize();\n if (!hasSize(size)) return undefined;\n const { x, y, scale } = this.canvas.viewbox();\n // The getter caches `outer` until the next change; the size is read fresh.\n return { x, y, width: size.width / scale, height: size.height / scale };\n }\n\n isAutomatic(): boolean {\n return !this.userMoved;\n }\n\n getState(): ViewportState | undefined {\n if (!this.imported) return undefined;\n const viewbox = this.getViewbox();\n return viewbox ? { viewbox, userMoved: this.userMoved } : undefined;\n }\n\n setState(state: ViewportState): void {\n if (this.destroyed) return;\n this.importing = false;\n this.imported = true;\n this.fittable = undefined;\n this.cancelAnimation();\n this.userMoved = state.userMoved;\n this.autoFitDue = false;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n if (this.canFit()) this.firstFitPending = false;\n this.show(state.viewbox);\n this.notify();\n }\n\n /** `canvas.resized()`; viewbox changes it causes (keep-selection-visible) are not user moves. */\n resized(): void {\n if (this.destroyed) return;\n this.writing++;\n try {\n this.canvas.resized();\n } finally {\n this.writing--;\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.cancelAnimation();\n if (this.resizeFrame !== undefined) cancelAnimationFrame(this.resizeFrame);\n this.resizeFrame = undefined;\n this.observer?.disconnect();\n this.container.removeEventListener(\"wheel\", this.onPointerInput, CAPTURE);\n this.container.removeEventListener(\"pointerdown\", this.onPointerInput, CAPTURE);\n this.container.removeEventListener(\"keydown\", this.onKeyInput, CAPTURE);\n for (const [events, listener] of this.subscriptions.splice(0)) this.eventBus.off(events, listener);\n this.listeners.clear();\n }\n\n /** Fits now (jump) or animated; false when there is nothing to fit or no container size. */\n private fitTo(animate: boolean): boolean {\n this.cancelAnimation();\n const bounds = this.options.contentBounds();\n if (!bounds) return false;\n const target = fitViewbox(bounds, this.canvas.getSize(), this.options.insets());\n if (!target) return false;\n this.userMoved = false;\n this.firstFitPending = false;\n this.autoFitDue = false;\n this.emptyViewPending = false;\n this.emptyViewDue = false;\n this.pendingView = undefined;\n const from = this.currentView();\n if (animate && from && !sameView(from, target) && typeof requestAnimationFrame === \"function\") {\n this.animate(from, target);\n } else {\n this.write(target);\n }\n return true;\n }\n\n private animate(from: ScaledViewbox, target: ScaledViewbox): void {\n this.reference = toView(target);\n const animation = { frame: 0 };\n const startedAt = performance.now();\n const step = (timestamp: number): void => {\n if (this.animation !== animation) return;\n if (!hasSize(this.canvas.getSize())) {\n // Hidden mid-animation: fit again once the container is back.\n this.cancelAnimation();\n this.autoFitDue = true;\n return;\n }\n const progress = Math.min(1, Math.max(0, (timestamp - startedAt) / FIT_ANIMATION_MS));\n if (progress >= 1) {\n this.animation = undefined;\n this.write(target);\n return;\n }\n this.write(interpolateViewbox(from, target, easeStandard(progress)), false);\n animation.frame = requestAnimationFrame(step);\n };\n this.animation = animation;\n animation.frame = requestAnimationFrame(step);\n }\n\n private cancelAnimation(): void {\n const animation = this.animation;\n if (!animation) return;\n this.animation = undefined;\n cancelAnimationFrame(animation.frame);\n if (this.lastWritten) this.reference = this.lastWritten;\n }\n\n /**\n * 100 % around the centre of the free rectangle, written as the viewport's own view; true when\n * the view is at 100 % afterwards, false while the container has no size.\n */\n private showActualSize(): boolean {\n const size = this.canvas.getSize();\n const centre = freeRectCenter(size, this.options.insets());\n const view = this.currentView();\n if (!centre || !view) return false;\n if (Math.abs(view.scale - 1) <= VIEW_TOLERANCE) return true;\n this.cancelAnimation();\n this.write({\n x: view.x + centre.x / view.scale - centre.x,\n y: view.y + centre.y / view.scale - centre.y,\n width: size.width,\n height: size.height,\n });\n return true;\n }\n\n /** Shows a restored view now, or once the container has a size. */\n private show(viewbox: Bounds): void {\n if (hasSize(this.canvas.getSize())) {\n this.pendingView = undefined;\n this.write(viewbox);\n } else {\n this.pendingView = { x: viewbox.x, y: viewbox.y, width: viewbox.width, height: viewbox.height };\n }\n }\n\n /** Callers make sure the container has a size: diagram-js would set a scale of 0 otherwise. */\n private write(box: Bounds, asReference = true): void {\n const size = this.canvas.getSize();\n // The scale diagram-js's setter derives from the box (`Canvas#viewbox`).\n const view: View = {\n x: box.x,\n y: box.y,\n scale: Math.min(size.width / box.width, size.height / box.height),\n };\n this.writing++;\n try {\n this.canvas.viewbox({ x: box.x, y: box.y, width: box.width, height: box.height });\n } finally {\n this.writing--;\n }\n this.lastWritten = view;\n if (asReference) this.reference = view;\n this.lastSize = { width: size.width, height: size.height };\n }\n\n private currentView(): ScaledViewbox | undefined {\n const size = this.canvas.getSize();\n const { x, y, scale } = this.canvas.viewbox();\n if (!(scale > 0 && Number.isFinite(scale))) return undefined;\n return { x, y, width: size.width / scale, height: size.height / scale, scale };\n }\n\n private beforeUserChange(): void {\n this.importing = false;\n this.cancelAnimation();\n }\n\n private zoomScroll(): ZoomScrollLike | null {\n if (this.zoomScrollService === undefined) {\n try {\n this.zoomScrollService = this.diagram.get<ZoomScrollLike | null>(\"zoomScroll\") ?? null;\n } catch {\n this.zoomScrollService = null;\n }\n }\n return this.zoomScrollService;\n }\n\n private prefersReducedMotion(): boolean {\n if (this.options.prefersReducedMotion) return this.options.prefersReducedMotion();\n if (this.container.ownerDocument.documentElement.classList.contains(REDUCED_MOTION_CLASS)) return true;\n return typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n }\n\n private isOwnView(current: View): boolean {\n if (this.reference && sameView(current, this.reference)) return true;\n return (\n this.animation !== undefined && this.lastWritten !== undefined && sameView(current, this.lastWritten)\n );\n }\n\n // Not a flag around the own writes alone: with `canvas.deferUpdate` the event of an own change\n // arrives up to 300ms later, so it is recognised by its view.\n private readonly onViewboxChanged = (event?: { viewbox?: DiagramViewbox }): void => {\n if (this.writing === 0 && !this.importing) {\n const current = event?.viewbox ?? this.canvas.viewbox();\n if (!this.isOwnView(current)) {\n this.cancelAnimation();\n this.userMoved = true;\n this.autoFitDue = false;\n this.emptyViewDue = false;\n }\n }\n this.notify();\n };\n\n private readonly onImportStart = (): void => {\n this.importing = true;\n };\n\n private readonly onImportDone = (): void => {\n this.importing = false;\n this.fittable = undefined;\n this.notify();\n };\n\n private readonly onContentChanged = (): void => {\n this.fittable = undefined;\n };\n\n // Guide §5.9: an element the user creates on the canvas never fits. Once such content exists,\n // only imports that keep the view follow, so the first automatic fit is no longer due.\n private readonly onElementsChanged = (): void => {\n this.fittable = undefined;\n if (this.imported && !this.importing && this.firstFitPending && this.canFit()) {\n this.firstFitPending = false;\n }\n this.notify();\n };\n\n // User input also ends an import window a failed import never closed with `import.done`.\n private readonly onPointerInput = (): void => {\n this.importing = false;\n this.cancelAnimation();\n };\n\n private readonly onKeyInput = (event: KeyboardEvent): void => {\n this.importing = false;\n if (matchChromeKey(event)) this.cancelAnimation();\n };\n\n private readonly onResizeObserved = (): void => {\n if (this.destroyed || this.resizeFrame !== undefined) return;\n if (typeof requestAnimationFrame !== \"function\") {\n this.onResize();\n return;\n }\n this.resizeFrame = requestAnimationFrame(() => {\n this.resizeFrame = undefined;\n this.onResize();\n });\n };\n\n private onResize(): void {\n if (this.destroyed) return;\n const size = this.canvas.getSize();\n if (!hasSize(size)) return;\n const changed = this.lastSize?.width !== size.width || this.lastSize.height !== size.height;\n if (!changed && !this.pendingView && !this.autoFitDue && !this.emptyViewDue) return;\n this.lastSize = { width: size.width, height: size.height };\n this.resized();\n const restored = this.pendingView;\n if (restored) {\n this.pendingView = undefined;\n this.write(restored);\n }\n if (this.userMoved) return;\n if (this.emptyViewDue) {\n this.emptyViewDue = false;\n this.showActualSize();\n return;\n }\n // A view restored for this very moment is not refitted; a fit that was due still runs.\n if (this.autoFitDue || (!restored && !this.firstFitPending)) this.fitTo(false);\n }\n\n private subscribe(events: string | string[], listener: (event: never) => unknown): void {\n this.eventBus.on(events, listener);\n this.subscriptions.push([events, listener]);\n }\n\n private readonly notify = (): void => {\n for (const listener of [...this.listeners]) listener();\n };\n}\n\nfunction toView(box: ScaledViewbox): View {\n return { x: box.x, y: box.y, scale: box.scale };\n}\n\nfunction hasSize(size: Size): boolean {\n return size.width > 0 && size.height > 0;\n}\n\nfunction hasExtent(bounds: Bounds | undefined): boolean {\n return bounds !== undefined && (bounds.width > 0 || bounds.height > 0);\n}\n\n/** `ZoomScroll#_zoom` for a diagram without `zoomScroll`: snap to the raster, one step, cap. */\nfunction stepOnRaster(zoom: number, direction: 1 | -1): number {\n const level = Math.round(Math.log10(zoom) / ZOOM_STEP) * ZOOM_STEP + ZOOM_STEP * direction;\n return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, 10 ** level));\n}\n","import type { Bounds } from \"../core/index.js\";\nimport type { ShellHandle } from \"../dom/index.js\";\nimport { shellServiceOf } from \"./service.js\";\nimport type { DiagramEventListener, EventBusLike, InjectorLike } from \"./types.js\";\nimport { DiagramViewport, type Viewport } from \"./viewport.js\";\n\nexport interface ConnectOptions {\n /**\n * Content bounds in diagram coordinates, tight around the content: the fit insets are the only\n * margin (guide §5.9). `undefined` = nothing to fit (empty file).\n */\n contentBounds(): Bounds | undefined;\n /**\n * An empty file (guide §13.5: no element, only whitespace, comments or a title), which shows the\n * empty-file hint. Default: `contentBounds()` is empty. A notation whose bounds are never empty\n * (Wardley's plot) passes its own test.\n */\n isEmpty?: (() => boolean) | undefined;\n prefersReducedMotion?: (() => boolean) | undefined;\n}\n\nexport interface DiagramJsConnection {\n readonly viewport: Viewport;\n /**\n * Unbinds viewport, palette, keys and the hint sync from the shell; destroys neither the diagram\n * nor the shell. Runs by itself on `diagram.destroy`.\n */\n destroy(): void;\n}\n\n/** After the viewport's own listeners, so its content state is fresh when the hint reads it. */\nconst HINT_SYNC_PRIORITY = 500;\n\n/**\n * Connects a diagram built with `shellModule` to a mounted shell: creates the viewport with\n * `shell.fitInsets`, binds it with `shell.setZoomTarget`, registers the palette\n * (`shell.registerPalette`), keeps the empty-file hint in sync with the diagram (after every\n * `import.done` and `elements.changed`, so the first element created on the canvas hides it) and\n * calls `canvas.resized()`. Throws when `shellModule` is missing.\n */\nexport function connectDiagramJs(\n shell: ShellHandle,\n diagram: InjectorLike,\n options: ConnectOptions,\n): DiagramJsConnection {\n const service = shellServiceOf(diagram);\n const eventBus = diagram.get<EventBusLike>(\"eventBus\");\n const prefersReducedMotion = options.prefersReducedMotion?.bind(options);\n const viewport = new DiagramViewport(diagram, {\n contentBounds: () => options.contentBounds(),\n insets: () => shell.fitInsets(),\n ...(prefersReducedMotion ? { prefersReducedMotion } : {}),\n });\n shell.setZoomTarget(viewport);\n const detachPalette = service.attachShell(shell);\n // The shell has moved the canvas element into its slot; diagram-js caches the old size.\n viewport.resized();\n\n const isEmpty = options.isEmpty ? () => options.isEmpty?.() === true : () => !viewport.canFit();\n const syncHint: DiagramEventListener = () => shell.setEmptyHint(isEmpty());\n eventBus.on([\"import.done\", \"elements.changed\"], HINT_SYNC_PRIORITY, syncHint);\n\n let destroyed = false;\n const destroy = (): void => {\n if (destroyed) return;\n destroyed = true;\n eventBus.off([\"import.done\", \"elements.changed\"], syncHint);\n eventBus.off(\"diagram.destroy\", destroy);\n detachPalette();\n shell.setZoomTarget(null);\n viewport.destroy();\n };\n eventBus.on(\"diagram.destroy\", destroy);\n return { viewport, destroy };\n}\n"],"mappings":"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","names":[]}
|