@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/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/core/types.ts","../src/core/sizes.ts","../src/core/fit.ts","../src/core/zoom.ts","../src/core/keymap.ts","../src/core/appearance.ts","../src/core/messages.ts","../src/core/layout.ts","../src/dom/element.ts","../src/dom/hint.ts","../src/dom/inspector.ts","../src/dom/keys.ts","../src/dom/ledger.ts","../src/dom/icons.ts","../src/dom/legend.ts","../src/dom/menu.ts","../src/dom/problems.ts","../src/dom/status.ts","../src/dom/tooltip.ts","../src/dom/zoom-panel.ts","../src/dom/mount.ts"],"sourcesContent":["// \"@miragon/modeler-shell\": the DOM chrome plus everything DOM-free from \"./core\".\nexport * from \"./core/index.js\";\nexport * from \"./dom/index.js\";\n","/** A point in pixels or diagram coordinates, as the context says. */\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** A rectangle; content bounds and viewboxes are in diagram coordinates. */\nexport interface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A viewbox together with the scale diagram-js shows it at (`canvas.viewbox().scale`). */\nexport interface ScaledViewbox extends Bounds {\n scale: number;\n}\n\n/** Distances in pixels from the edges of the modeler's container. */\nexport interface Insets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/**\n * The host column of guide §5.2: `ide` is a VS Code webview (later IntelliJ), `web` a Miragon web\n * app that owns its page, `embedded` a modeler inside a foreign page (designIQ, modeler-api hosts).\n */\nexport type ShellHost = \"ide\" | \"web\" | \"embedded\";\n\n/** The `data-chrome` names of the islands (guide §5.2, §13.4). `primary` is reserved for the web app. */\nexport type ChromeIsland =\n \"menu\" | \"palette\" | \"primary\" | \"zoom\" | \"problems\" | \"legend\" | \"inspector\" | \"status\";\n\nexport const CHROME_ISLANDS: readonly ChromeIsland[] = [\n \"menu\",\n \"palette\",\n \"primary\",\n \"zoom\",\n \"problems\",\n \"legend\",\n \"inspector\",\n \"status\",\n];\n\n/** Where the palette sits: in the top row, or in the second row below it (guide §5.15). */\nexport type PaletteRow = \"top\" | \"second-row\";\n\n/**\n * What the zoom panel and the chrome keys act on. The diagram-js viewport implements it; the DOM\n * shell only talks to this interface.\n */\nexport interface ZoomTarget {\n /** The current zoom, 1 = 100 % (diagram-js `canvas.zoom()`, rounded to three decimals). */\n zoom(): number;\n /** One step on the zoom raster around the container centre (diagram-js `zoomScroll.stepZoom`). */\n stepZoom(direction: 1 | -1): void;\n /** 100 % around the container centre. Counts as a user move. */\n zoomToActual(): void;\n /** Explicit fit (button, Shift+1, command): animated unless reduced motion, makes the view automatic. */\n fit(): void;\n /** False while there is nothing to fit (the content bounds are empty). */\n canFit(): boolean;\n /**\n * Calls `listener` after every viewbox change and whenever `canFit()` may have changed, possibly\n * several times per frame. Returns the unsubscribe function.\n */\n onChange(listener: () => void): () => void;\n}\n\n/** The persisted view (VS Code `setState`): JSON-serializable. */\nexport interface ViewportState {\n viewbox: Bounds;\n /** The user zoomed or panned since the last fit; a resize no longer refits. */\n userMoved: boolean;\n}\n","/**\n * The shell dimensions of the design system (guide §5.1, `shell` group of\n * `cd-tokens.generated.json`), keyed by a readable name. Scripts use `SHELL`; CSS uses the\n * `var(--cd-shell-*)` variables the consumer vendors. A drift test pins `SHELL` to the token JSON.\n */\nexport const SHELL_TOKENS = {\n edge: \"--cd-shell-rand\",\n gap: \"--cd-shell-luecke\",\n row: \"--cd-shell-zeile\",\n target: \"--cd-shell-ziel\",\n entry: \"--cd-shell-eintrag\",\n free: \"--cd-shell-frei\",\n menuMinWidth: \"--cd-shell-menue-breite\",\n inspectorWidth: \"--cd-shell-inspector-breite\",\n fitInsetTop: \"--cd-shell-einpassen-oben\",\n fitInsetTopSecondRow: \"--cd-shell-einpassen-oben-schmal\",\n fitInsetSide: \"--cd-shell-einpassen-seite\",\n fitInsetBottom: \"--cd-shell-einpassen-unten\",\n fitInsetBottomWeb: \"--cd-shell-einpassen-unten-web\",\n narrow: \"--cd-shell-schmal\",\n veryNarrow: \"--cd-shell-sehr-schmal\",\n low: \"--cd-shell-niedrig\",\n layerIslands: \"--cd-shell-ebene-inseln\",\n layerInspector: \"--cd-shell-ebene-inspector\",\n layerTopRow: \"--cd-shell-ebene-reihe\",\n layerPopups: \"--cd-shell-ebene-aufklapper\",\n layerDialog: \"--cd-shell-ebene-dialog\",\n layerToast: \"--cd-shell-ebene-toast\",\n} as const;\n\nexport type ShellSizeName = keyof typeof SHELL_TOKENS;\n\nexport type ShellSizes = Readonly<Record<ShellSizeName, number>>;\n\n/** Pixels (layers: plain z-index numbers), equal to `parseFloat` of the token JSON values. */\nexport const SHELL: ShellSizes = {\n edge: 12,\n gap: 8,\n row: 40,\n target: 32,\n entry: 36,\n free: 64,\n menuMinWidth: 248,\n inspectorWidth: 288,\n fitInsetTop: 88,\n fitInsetTopSecondRow: 140,\n fitInsetSide: 24,\n fitInsetBottom: 64,\n fitInsetBottomWeb: 92,\n narrow: 760,\n veryNarrow: 440,\n low: 820,\n layerIslands: 20,\n layerInspector: 25,\n layerTopRow: 30,\n layerPopups: 40,\n layerDialog: 50,\n layerToast: 60,\n};\n\n// Shell sizes are pixels (\"12px\") or plain z-index numbers (\"20\"); any other unit would make\n// parseFloat silently return a number with the wrong meaning.\nconst PIXEL_OR_PLAIN_NUMBER = /^\\s*-?(?:\\d+\\.?\\d*|\\.\\d+)(?:px)?\\s*$/;\n\n/**\n * Reads the `shell` group of `cd-tokens.generated.json` (`{ \"--cd-shell-rand\": \"12px\", … }`) into\n * numbers. Throws when a size of `SHELL_TOKENS` is missing or not a number.\n */\nexport function shellSizesFromTokens(shellGroup: Readonly<Record<string, string>>): ShellSizes {\n const sizes = {} as Record<ShellSizeName, number>;\n for (const name of Object.keys(SHELL_TOKENS) as ShellSizeName[]) {\n const token = SHELL_TOKENS[name];\n const raw: unknown = Object.hasOwn(shellGroup, token) ? shellGroup[token] : undefined;\n if (raw === undefined) {\n throw new Error(`@miragon/modeler-shell: the shell token ${token} is missing`);\n }\n if (typeof raw !== \"string\" || !PIXEL_OR_PLAIN_NUMBER.test(raw)) {\n throw new Error(\n `@miragon/modeler-shell: the shell token ${token} is not a number: ${JSON.stringify(raw)}`,\n );\n }\n sizes[name] = Number.parseFloat(raw);\n }\n return sizes;\n}\n","import { SHELL } from \"./sizes.js\";\nimport type { Bounds, Insets, PaletteRow, Point, ScaledViewbox, ShellHost, Size } from \"./types.js\";\n\n/** Fit never zooms above 100 % (guide §5.9). */\nexport const MAX_FIT_ZOOM = 1;\n\n/** Duration of the explicit, animated fit (`--cd-motion-base`). */\nexport const FIT_ANIMATION_MS = 250;\n\n/**\n * The viewbox that shows `bounds` centred in the free rectangle (`container` minus `insets`) at the\n * largest scale that fits, capped at `maxZoom`. The box has the container's aspect ratio, so\n * diagram-js's `canvas.viewbox(box)` sets exactly this view. Returns `undefined` when the container\n * is 0 × 0 or `bounds` has neither width nor height; a zero width or height scales by the other\n * dimension. Where the insets leave no free room on an axis (a container lower or narrower than\n * its chrome), that axis centres in the whole container instead.\n */\nexport function fitViewbox(\n bounds: Bounds,\n container: Size,\n insets: Insets,\n maxZoom: number = MAX_FIT_ZOOM,\n): ScaledViewbox | undefined {\n if (!(container.width > 0 && container.height > 0)) return undefined;\n const hasWidth = bounds.width > 0;\n const hasHeight = bounds.height > 0;\n if (!hasWidth && !hasHeight) return undefined;\n\n const horizontal = freeExtent(container.width, insets.left, insets.right);\n const vertical = freeExtent(container.height, insets.top, insets.bottom);\n const contentWidth = hasWidth ? bounds.width : 0;\n const contentHeight = hasHeight ? bounds.height : 0;\n const scale = Math.min(\n maxZoom,\n hasWidth ? horizontal.extent / contentWidth : Infinity,\n hasHeight ? vertical.extent / contentHeight : Infinity,\n );\n const box: ScaledViewbox = {\n x: bounds.x + contentWidth / 2 - (horizontal.start + horizontal.extent / 2) / scale,\n y: bounds.y + contentHeight / 2 - (vertical.start + vertical.extent / 2) / scale,\n width: container.width / scale,\n height: container.height / scale,\n scale,\n };\n return Object.values(box).every(Number.isFinite) && scale > 0 ? box : undefined;\n}\n\nfunction freeExtent(total: number, before: number, after: number): { start: number; extent: number } {\n const extent = total - before - after;\n return extent > 0 ? { start: before, extent } : { start: 0, extent: total };\n}\n\n/**\n * The centre of the free rectangle (`container` minus `insets`) in pixels from the container's top\n * left, where `fitViewbox` centres the content and keyboard creation places an element (guide\n * §5.5). An axis the insets leave no room on centres in the whole container, as in `fitViewbox`.\n * Returns `undefined` when the container is 0 × 0.\n */\nexport function freeRectCenter(container: Size, insets: Insets): Point | undefined {\n if (!(container.width > 0 && container.height > 0)) return undefined;\n const horizontal = freeExtent(container.width, insets.left, insets.right);\n const vertical = freeExtent(container.height, insets.top, insets.bottom);\n return {\n x: horizontal.start + horizontal.extent / 2,\n y: vertical.start + vertical.extent / 2,\n };\n}\n\n/** What is open or shown when a fit runs (guide §5.9: every fit counts what is open right now). */\nexport interface FitLayout {\n container: Size;\n host: ShellHost;\n paletteRow: PaletteRow;\n /** The problems pill is shown (only the web app reserves room for it). */\n problemsVisible: boolean;\n /** Rendered width of the open legend; `undefined` when it is closed or the modeler has none. */\n legendWidth?: number | undefined;\n /**\n * The open inspector; `undefined` when closed. Above `SHELL.narrow` it is the side panel; up to it\n * a bottom sheet whose top edge (`sheetTop`, px from the container top) must be measured.\n */\n inspector?: { sheetTop?: number | undefined } | undefined;\n}\n\n/**\n * The fit insets of guide §5.9: top 88 (second row 140), sides 24, bottom 64 (web app with pill 92),\n * right 324 with an open side inspector, left 12 + legend width + 24 with an open legend above\n * `SHELL.veryNarrow`, bottom = distance to the sheet's top edge + 12 with an open bottom sheet.\n */\nexport function fitInsets(layout: FitLayout): Insets {\n const { container, host, paletteRow, problemsVisible, legendWidth, inspector } = layout;\n const insets: Insets = {\n top: paletteRow === \"second-row\" ? SHELL.fitInsetTopSecondRow : SHELL.fitInsetTop,\n right: SHELL.fitInsetSide,\n bottom: host === \"web\" && problemsVisible ? SHELL.fitInsetBottomWeb : SHELL.fitInsetBottom,\n left: SHELL.fitInsetSide,\n };\n\n const bottomSheetOpen = inspector !== undefined && container.width <= SHELL.narrow;\n if (inspector !== undefined && !bottomSheetOpen) {\n insets.right = SHELL.edge + SHELL.inspectorWidth + SHELL.fitInsetSide;\n }\n if (bottomSheetOpen) {\n // Guide §5.11: the sheet hides zoom panel, pill and legend, so only the sheet itself counts.\n insets.bottom =\n inspector.sheetTop === undefined\n ? SHELL.fitInsetBottom\n : container.height - inspector.sheetTop + SHELL.edge;\n } else if (legendWidth !== undefined && legendWidth > 0 && container.width > SHELL.veryNarrow) {\n insets.left = SHELL.edge + legendWidth + SHELL.fitInsetSide;\n }\n return insets;\n}\n\n/** Relative tolerance of `sameView` (diagram-js rounds the transform to three decimals). */\nexport const VIEW_TOLERANCE = 1e-3;\n\n/**\n * True when two views are the same within `tolerance`: the scale and the translation in screen\n * pixels (`x · scale`, `y · scale`) agree relative to `max(1, |value|)`. Width and height are\n * ignored, so a container resize is never a difference.\n */\nexport function sameView(\n a: Pick<ScaledViewbox, \"x\" | \"y\" | \"scale\">,\n b: Pick<ScaledViewbox, \"x\" | \"y\" | \"scale\">,\n tolerance: number = VIEW_TOLERANCE,\n): boolean {\n const close = (first: number, second: number): boolean =>\n Math.abs(first - second) <= tolerance * Math.max(1, Math.abs(first), Math.abs(second));\n return (\n close(a.scale, b.scale) && close(a.x * a.scale, b.x * b.scale) && close(a.y * a.scale, b.y * b.scale)\n );\n}\n\n/**\n * The view at `progress` (0…1) between two viewboxes of the same container: the scale is\n * interpolated in log space, the centre linearly. Used per animation frame by the animated fit.\n */\nexport function interpolateViewbox(from: ScaledViewbox, to: ScaledViewbox, progress: number): ScaledViewbox {\n if (!(progress > 0)) return { ...from };\n if (progress >= 1) return { ...to };\n const linear = (start: number, end: number): number => start + (end - start) * progress;\n const scale =\n from.scale > 0 && to.scale > 0\n ? Math.exp(linear(Math.log(from.scale), Math.log(to.scale)))\n : linear(from.scale, to.scale);\n const centreX = linear(from.x + from.width / 2, to.x + to.width / 2);\n const centreY = linear(from.y + from.height / 2, to.y + to.height / 2);\n const width = linear(from.width * from.scale, to.width * to.scale) / scale;\n const height = linear(from.height * from.scale, to.height * to.scale) / scale;\n return { x: centreX - width / 2, y: centreY - height / 2, width, height, scale };\n}\n\n/** `--cd-ease`, `cubic-bezier(0.4, 0, 0.2, 1)`, as a function of time 0…1. */\nexport function easeStandard(progress: number): number {\n return STANDARD_EASING(progress);\n}\n\nconst STANDARD_EASING = cubicBezier(0.4, 0, 0.2, 1);\n\n/** A CSS `cubic-bezier(x1, y1, x2, y2)` timing function (`x1`, `x2` within 0…1, so x(t) is monotone). */\nfunction cubicBezier(x1: number, y1: number, x2: number, y2: number): (progress: number) => number {\n const polynomial = (first: number, second: number) => {\n const c = 3 * first;\n const b = 3 * (second - first) - c;\n const a = 1 - c - b;\n return {\n at: (t: number): number => ((a * t + b) * t + c) * t,\n slope: (t: number): number => (3 * a * t + 2 * b) * t + c,\n };\n };\n const curveX = polynomial(x1, x2);\n const curveY = polynomial(y1, y2);\n const precision = 1e-7;\n\n const parameterFor = (x: number): number => {\n let t = x;\n for (let iteration = 0; iteration < 8; iteration++) {\n const error = curveX.at(t) - x;\n if (Math.abs(error) < precision) return t;\n const slope = curveX.slope(t);\n if (Math.abs(slope) < 1e-6) break;\n t -= error / slope;\n if (t < 0 || t > 1) break;\n }\n // Newton left the curve or stalled on a flat stretch: bisection always converges.\n let low = 0;\n let high = 1;\n t = x;\n for (let iteration = 0; iteration < 60; iteration++) {\n const value = curveX.at(t);\n if (Math.abs(value - x) < precision) break;\n if (value < x) low = t;\n else high = t;\n t = (low + high) / 2;\n }\n return t;\n };\n\n return (progress) => {\n if (!(progress > 0)) return 0;\n if (progress >= 1) return 1;\n return curveY.at(parameterFor(progress));\n };\n}\n","import type { ShellMessages } from \"./messages.js\";\n\n/** diagram-js `ZoomScroll` RANGE (not configurable): 20 % … 400 %. */\nexport const ZOOM_MIN = 0.2;\nexport const ZOOM_MAX = 4;\n\n/** Zoom out is disabled at 20 % and below (`zoom <= 0.2 · 1.001`), so it never zooms in. */\nexport function canZoomOut(zoom: number): boolean {\n return zoom > ZOOM_MIN * 1.001;\n}\n\n/** Zoom in is disabled at 400 % (`zoom >= 4 · 0.999`). */\nexport function canZoomIn(zoom: number): boolean {\n return zoom < ZOOM_MAX * 0.999;\n}\n\n/**\n * A zoom as a whole percentage in the UI language: `Intl.NumberFormat(lang, { style: \"percent\",\n * maximumFractionDigits: 0 })`, so English \"86%\", German \"86 %\" (with U+00A0).\n */\nexport function formatPercent(zoom: number, lang: string): string {\n return numberFormat(lang, \"percent\").format(zoom);\n}\n\n/** Any other number in the chrome (\"2 problems\"), via `Intl.NumberFormat(lang)`. */\nexport function formatNumber(value: number, lang: string): string {\n return numberFormat(lang, \"decimal\").format(value);\n}\n\nconst FALLBACK_LANG = \"en\";\nconst formats = new Map<string, Intl.NumberFormat>();\n\n// The readout formats on every animation frame of a zoom, so each formatter is built once. A\n// language tag Intl rejects (an empty `lang=\"\"`, a typo) falls back to English, the shell's default\n// language, instead of breaking the chrome.\nfunction numberFormat(lang: string, style: \"percent\" | \"decimal\"): Intl.NumberFormat {\n const key = `${style}|${lang}`;\n let format = formats.get(key);\n if (!format) {\n const options: Intl.NumberFormatOptions =\n style === \"percent\" ? { style, maximumFractionDigits: 0 } : { style };\n try {\n format = new Intl.NumberFormat(lang, options);\n } catch {\n format = new Intl.NumberFormat(FALLBACK_LANG, options);\n }\n formats.set(key, format);\n }\n return format;\n}\n\nexport interface ZoomReadout {\n /** \"86%\" */\n text: string;\n /** \"Zoom to 100% (now 86%)\" */\n ariaLabel: string;\n canZoomOut: boolean;\n canZoomIn: boolean;\n}\n\n/** Everything the zoom panel shows for a zoom: readout text, its accessible name and the limits. */\nexport function zoomReadout(\n zoom: number,\n lang: string,\n messages: Pick<ShellMessages, \"zoomToActualNow\">,\n): ZoomReadout {\n const text = formatPercent(zoom, lang);\n return {\n text,\n ariaLabel: messages.zoomToActualNow(formatPercent(1, lang), text),\n canZoomOut: canZoomOut(zoom),\n canZoomIn: canZoomIn(zoom),\n };\n}\n","import type { ShellMessages } from \"./messages.js\";\nimport type { ShellHost } from \"./types.js\";\n\n/** The only keys the chrome handles (guide §5.8). */\nexport type ChromeKey = \"zoomIn\" | \"zoomOut\" | \"zoomToActual\" | \"fit\";\n\n/** The `KeyboardEvent` fields the keymap reads. */\nexport interface KeyLike {\n key: string;\n code: string;\n metaKey: boolean;\n ctrlKey: boolean;\n shiftKey: boolean;\n altKey: boolean;\n isComposing?: boolean | undefined;\n}\n\n/**\n * Which chrome key `event` is, ignoring where it was pressed:\n * - `zoomIn`: Cmd/Ctrl + `+` or `=` (by `key`, with or without Shift), or `NumpadAdd` (by `code`);\n * - `zoomOut`: Cmd/Ctrl + `-` or `_`, or `NumpadSubtract`;\n * - `zoomToActual`: Cmd/Ctrl + `0`, or `Numpad0` (also with NumLock off);\n * - `fit`: Shift + `Digit1` (by `code`, every layout) without Cmd, Ctrl or Alt.\n * Cmd/Ctrl is `metaKey || ctrlKey` on every platform; nothing matches with `altKey` (AltGr).\n */\nexport function matchChromeKey(event: KeyLike): ChromeKey | undefined {\n if (event.altKey) return undefined;\n if (isCommand(event)) {\n if (event.key === \"+\" || event.key === \"=\" || event.code === \"NumpadAdd\") return \"zoomIn\";\n if (event.key === \"-\" || event.key === \"_\" || event.code === \"NumpadSubtract\") return \"zoomOut\";\n if (event.key === \"0\" || event.code === \"Numpad0\") return \"zoomToActual\";\n return undefined;\n }\n return event.shiftKey && event.code === \"Digit1\" ? \"fit\" : undefined;\n}\n\nfunction isCommand(event: KeyLike): boolean {\n return event.metaKey || event.ctrlKey;\n}\n\n/**\n * Cmd/Ctrl + Z, Cmd/Ctrl + Shift + Z or Cmd/Ctrl + Y, without Alt (by `key`, `code` as fallback).\n * Cmd/Ctrl + Shift + Y is not redo (VS Code toggles its Debug Console with it).\n */\nexport function isUndoRedoKey(event: KeyLike): boolean {\n if (event.altKey || !isCommand(event)) return false;\n const letter = undoRedoLetter(event);\n return letter === \"z\" || (letter === \"y\" && !event.shiftKey);\n}\n\n// The produced character decides on Latin layouts (QWERTZ swaps the Y and Z keys); only where the\n// layout produces no ASCII character (Cyrillic, Greek, …) the physical key stands in.\nfunction undoRedoLetter(event: KeyLike): string | undefined {\n if (event.key.length === 1 && event.key.charCodeAt(0) < 0x80) return event.key.toLowerCase();\n if (event.code === \"KeyZ\") return \"z\";\n if (event.code === \"KeyY\") return \"y\";\n return undefined;\n}\n\n/** A text field: every input, select list and editable text (label editor, inspector, dialogs). */\nexport const TEXT_FIELD_SELECTOR =\n \"input, textarea, select, [contenteditable]:not([contenteditable='false'])\";\n\n/** Where a key was pressed, as the shell's one `keydown` listener sees it. */\nexport interface KeyContext {\n host: ShellHost;\n /** The event target matches `TEXT_FIELD_SELECTOR` or is `isContentEditable`. */\n inTextField: boolean;\n /** The shell's menu dropdown is open. */\n menuOpen: boolean;\n /** A popover or dialog (`[role=\"dialog\"]`, modal or not) is open. */\n dialogOpen: boolean;\n /** A modal dialog (`[role=\"dialog\"][aria-modal=\"true\"]`) is open: chrome keys do not act. */\n modalOpen: boolean;\n /** `event.defaultPrevented` when the listener ran: the canvas (or the modeler) handled the key. */\n defaultPrevented: boolean;\n}\n\nexport type KeyAction = ChromeKey | \"closeMenu\";\n\nexport interface KeyDecision {\n /** What the shell executes; `undefined` = nothing. */\n action?: KeyAction;\n preventDefault: boolean;\n stopPropagation: boolean;\n}\n\n/**\n * The key rules of guide §5.8 and §13.5 in one place:\n * 1. Escape with the menu open: `closeMenu`, prevented; in the IDE host stopped whenever the menu\n * or a dialog/popover is open. During IME composition Escape belongs to the IME: no `closeMenu`.\n * 2. Zoom keys: executed and prevented unless composing, in a text field or with a modal dialog;\n * in the IDE host always stopped, also when not executed (VS Code must never zoom the window).\n * 3. Shift+1: `fit` under the same conditions; otherwise untouched (it types \"!\").\n * 4. IDE host, text field, undo/redo key: stopped only (the field keeps its native undo).\n * 5. IDE host, `defaultPrevented`: stopped (the canvas handled it; VS Code must not run it again).\n * Everything else passes untouched. `stopPropagation` is only ever true in the IDE host.\n */\nexport function decideKey(event: KeyLike, context: KeyContext): KeyDecision {\n const stop = context.host === \"ide\";\n const composing = event.isComposing === true;\n\n if (event.key === \"Escape\" && !event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey) {\n if (context.menuOpen && !composing) {\n return { action: \"closeMenu\", preventDefault: true, stopPropagation: stop };\n }\n if (context.menuOpen || context.dialogOpen) return { preventDefault: false, stopPropagation: stop };\n }\n\n const chromeKey = matchChromeKey(event);\n if (chromeKey !== undefined) {\n const blocked = composing || context.inTextField || context.modalOpen;\n if (!blocked) return { action: chromeKey, preventDefault: true, stopPropagation: stop };\n // Blocked zoom keys are still kept from VS Code (it would zoom the window); a blocked Shift+1\n // is a character and travels on like any other.\n return { preventDefault: false, stopPropagation: chromeKey === \"fit\" ? false : stop };\n }\n\n if (context.inTextField && isUndoRedoKey(event)) return { preventDefault: false, stopPropagation: stop };\n if (context.defaultPrevented) return { preventDefault: false, stopPropagation: stop };\n return { preventDefault: false, stopPropagation: false };\n}\n\n/** The keyboard the user sits at; decides the shortcut labels (guide §5.8). */\nexport type Platform = \"mac\" | \"other\";\n\n/** The `navigator` fields `detectPlatform` reads. */\nexport interface NavigatorLike {\n platform?: string | undefined;\n userAgentData?: { platform?: string | undefined } | undefined;\n}\n\n/**\n * `mac` when `userAgentData.platform ?? platform` matches `/mac/i`, else `other`; `other` without a\n * navigator. Read it in the webview or page itself, never from the extension host (VS Code Remote).\n */\nexport function detectPlatform(navigator?: NavigatorLike | undefined): Platform {\n // An empty userAgentData.platform means \"unknown\", not \"not a Mac\": fall back to navigator.platform.\n const platform = navigator?.userAgentData?.platform || navigator?.platform || \"\";\n return /mac/i.test(platform) ? \"mac\" : \"other\";\n}\n\n/**\n * The tooltip chip text: macOS `⌘+`, `⌘−` (U+2212), `⌘0`, `⇧1`; elsewhere `Ctrl+Plus`,\n * `Ctrl+Minus`, `Ctrl+0`, `Shift+1` with the key names of the messages table.\n */\nexport function shortcutLabel(\n key: ChromeKey,\n platform: Platform,\n keyNames: ShellMessages[\"keyNames\"],\n): string {\n if (platform === \"mac\") return MAC_SHORTCUT_LABELS[key];\n switch (key) {\n case \"zoomIn\":\n return `${keyNames.ctrl}+${keyNames.plus}`;\n case \"zoomOut\":\n return `${keyNames.ctrl}+${keyNames.minus}`;\n case \"zoomToActual\":\n return `${keyNames.ctrl}+0`;\n case \"fit\":\n return `${keyNames.shift}+1`;\n }\n}\n\nconst MAC_SHORTCUT_LABELS: Readonly<Record<ChromeKey, string>> = {\n zoomIn: \"⌘+\",\n zoomOut: \"⌘\\u2212\",\n zoomToActual: \"⌘0\",\n fit: \"⇧1\",\n};\n\n/**\n * The `aria-keyshortcuts` value (WAI-ARIA names): zoom in `Meta+= Meta+Plus`, zoom out `Meta+-`,\n * 100 % `Meta+0`, fit `Shift+1`; outside macOS `Control` instead of `Meta`.\n */\nexport function ariaKeyShortcuts(key: ChromeKey, platform: Platform): string {\n const command = platform === \"mac\" ? \"Meta\" : \"Control\";\n switch (key) {\n case \"zoomIn\":\n return `${command}+= ${command}+Plus`;\n case \"zoomOut\":\n return `${command}+-`;\n case \"zoomToActual\":\n return `${command}+0`;\n case \"fit\":\n return \"Shift+1\";\n }\n}\n\nconst MAC_MODIFIER_SYMBOLS: Readonly<Record<string, string>> = {\n \"⌘\": \"Meta\",\n \"⇧\": \"Shift\",\n \"⌥\": \"Alt\",\n \"⌃\": \"Control\",\n};\n\nconst MODIFIER_NAMES: Readonly<Record<string, string>> = {\n cmd: \"Meta\",\n command: \"Meta\",\n meta: \"Meta\",\n ctrl: \"Control\",\n control: \"Control\",\n strg: \"Control\",\n shift: \"Shift\",\n umschalt: \"Shift\",\n alt: \"Alt\",\n option: \"Alt\",\n opt: \"Alt\",\n};\n\nconst NAMED_KEYS: Readonly<Record<string, string>> = {\n esc: \"Escape\",\n escape: \"Escape\",\n del: \"Delete\",\n delete: \"Delete\",\n entf: \"Delete\",\n backspace: \"Backspace\",\n enter: \"Enter\",\n return: \"Enter\",\n tab: \"Tab\",\n space: \"Space\",\n home: \"Home\",\n end: \"End\",\n pageup: \"PageUp\",\n pagedown: \"PageDown\",\n arrowup: \"ArrowUp\",\n arrowdown: \"ArrowDown\",\n arrowleft: \"ArrowLeft\",\n arrowright: \"ArrowRight\",\n \"↑\": \"ArrowUp\",\n \"↓\": \"ArrowDown\",\n \"←\": \"ArrowLeft\",\n \"→\": \"ArrowRight\",\n plus: \"Plus\",\n};\n\nfunction ariaKeyName(key: string): string | undefined {\n const named = NAMED_KEYS[key.toLowerCase()];\n if (named) return named;\n if (/^f\\d{1,2}$/i.test(key)) return key.toUpperCase();\n if (key.length !== 1 || MAC_MODIFIER_SYMBOLS[key]) return undefined;\n if (key === \"+\") return \"Plus\";\n if (key === \" \") return \"Space\";\n return key.toUpperCase();\n}\n\n/**\n * The `aria-keyshortcuts` value (WAI-ARIA names, guide §5.6) for a shortcut chip label: `\"L\"` →\n * `\"L\"`, `\"⇧L\"` → `\"Shift+L\"`, `\"⌘⇧Z\"` → `\"Meta+Shift+Z\"`, `\"Ctrl+Shift+E\"` → `\"Control+Shift+E\"`,\n * `\"Del\"` → `\"Delete\"`, `\"Ctrl++\"` → `\"Control+Plus\"`. `undefined` for a label that is not one key\n * combination (`\"G then D\"`, `\"1–9\"`, empty).\n */\nexport function ariaKeyShortcutsFromLabel(label: string): string | undefined {\n let rest = label.trim();\n const modifiers: string[] = [];\n for (let symbol = MAC_MODIFIER_SYMBOLS[rest.charAt(0)]; symbol && rest.length > 1;) {\n modifiers.push(symbol);\n rest = rest.slice(1).trim();\n symbol = MAC_MODIFIER_SYMBOLS[rest.charAt(0)];\n }\n if (!rest || /\\s/.test(rest.replace(/\\s*\\+\\s*/g, \"+\"))) return undefined;\n const parts = rest.split(\"+\").map((part) => part.trim());\n let key = parts.pop() ?? \"\";\n if (key === \"\" && parts.at(-1) === \"\") {\n parts.pop();\n key = \"+\";\n }\n for (const part of parts) {\n const modifier = MODIFIER_NAMES[part.toLowerCase()];\n if (!modifier) return undefined;\n modifiers.push(modifier);\n }\n const name = ariaKeyName(key);\n return name ? [...new Set(modifiers), name].join(\"+\") : undefined;\n}\n","/** The modes a Miragon modeler can show (guide §13.3). */\nexport type Theme = \"light\" | \"dark\";\n\n/** High contrast; written as `data-cd-kontrast=\"hoch\"` on the same element as `data-cd-theme`. */\nexport type Kontrast = \"hoch\";\n\nexport interface Appearance {\n theme: Theme;\n kontrast?: Kontrast | undefined;\n}\n\n/**\n * The one appearance decision of guide §13.5: a theme the modeler cannot show is never shown\n * (`themes[0]` wins, so `[\"light\"]` stays light whatever the host requests); `kontrast` always\n * passes through. Throws when `themes` is empty.\n */\nexport function resolveAppearance(requested: Appearance, themes: readonly Theme[]): Appearance {\n const [fallback] = themes;\n if (fallback === undefined) {\n throw new Error(\n \"@miragon/modeler-shell: resolveAppearance needs at least one theme the modeler can show\",\n );\n }\n const theme = themes.includes(requested.theme) ? requested.theme : fallback;\n return withKontrast(theme, requested.kontrast);\n}\n\n// Appearances arrive through postMessage and settings, so only the one known value passes.\nfunction withKontrast(theme: Theme, kontrast: unknown): Appearance {\n return kontrast === \"hoch\" ? { theme, kontrast } : { theme };\n}\n\n/**\n * The appearance VS Code requests for `vscode.window.activeColorTheme.kind`:\n * 1 Light → light, 2 Dark → dark, 3 HighContrast → dark + hoch, 4 HighContrastLight → light + hoch;\n * any other value → light.\n */\nexport function appearanceFromColorThemeKind(kind: number): Appearance {\n switch (kind) {\n case 2:\n return { theme: \"dark\" };\n case 3:\n return { theme: \"dark\", kontrast: \"hoch\" };\n case 4:\n return { theme: \"light\", kontrast: \"hoch\" };\n default:\n return { theme: \"light\" };\n }\n}\n\n/** The values of the setting `miragon.<modeler>.colorTheme` (it ships once a modeler can show dark). */\nexport type ColorThemeSetting = \"automatic\" | \"light\" | \"dark\";\n\n/**\n * The requested appearance in an IDE host: the setting's theme unless it is `automatic` (or\n * missing), the contrast always from the color theme kind.\n */\nexport function requestedAppearance(kind: number, setting?: ColorThemeSetting | undefined): Appearance {\n const fromKind = appearanceFromColorThemeKind(kind);\n const theme = setting === \"light\" || setting === \"dark\" ? setting : fromKind.theme;\n return withKontrast(theme, fromKind.kontrast);\n}\n\n/**\n * The fallback signal inside a VS Code webview: the body classes `vscode-high-contrast-light`\n * (checked first, VS Code adds `vscode-high-contrast` to it as well), `vscode-high-contrast`,\n * `vscode-dark`, `vscode-light`. `undefined` when none is set. Never use them for styling.\n */\nexport function appearanceFromBodyClasses(classes: Iterable<string>): Appearance | undefined {\n const present = new Set(classes);\n if (present.has(\"vscode-high-contrast-light\")) return { theme: \"light\", kontrast: \"hoch\" };\n if (present.has(\"vscode-high-contrast\")) return { theme: \"dark\", kontrast: \"hoch\" };\n if (present.has(\"vscode-dark\")) return { theme: \"dark\" };\n if (present.has(\"vscode-light\")) return { theme: \"light\" };\n return undefined;\n}\n\n/**\n * VS Code's `workbench.reduceMotion` as the webview sees it: the body class `vscode-reduce-motion`\n * (the webview host page sets it). Never use it for styling; the shell mirrors it as\n * `REDUCED_MOTION_CLASS` on `<html>`.\n */\nexport function reducedMotionFromBodyClasses(classes: Iterable<string>): boolean {\n return new Set(classes).has(\"vscode-reduce-motion\");\n}\n\n/**\n * On `<html>` while the host asks for reduced motion although the OS does not (VS Code's\n * `workbench.reduceMotion`): the shell's animations stop as under `prefers-reduced-motion`, and an\n * explicit fit jumps.\n */\nexport const REDUCED_MOTION_CLASS = \"cd-shell-reduce-motion\";\n\nexport interface AppearanceAttributes {\n \"data-cd-theme\": Theme;\n \"data-cd-kontrast\"?: Kontrast;\n}\n\n/** The attributes for `<html>` (own document) or the modeler container (foreign page). */\nexport function appearanceAttributes(appearance: Appearance): AppearanceAttributes {\n return appearance.kontrast === \"hoch\"\n ? { \"data-cd-theme\": appearance.theme, \"data-cd-kontrast\": \"hoch\" }\n : { \"data-cd-theme\": appearance.theme };\n}\n","/**\n * Every text the shell shows or announces, in one table (guide §2, shared terms). English by\n * default; a localized modeler overrides the whole table in its language, numbers arrive already\n * formatted through `Intl` in that language.\n */\nexport interface ShellMessages {\n /** Menu trigger `aria-label` and tooltip, dropdown `aria-label`. */\n menu: string;\n /** Palette `aria-label`. */\n tools: string;\n /** `aria-label` of the focusable canvas `<svg>` (`role=\"application\"`); a modeler names its notation. */\n canvas: string;\n /** Zoom panel `aria-label`. */\n zoom: string;\n zoomOut: string;\n zoomIn: string;\n /** Tooltip of the readout, e.g. `(percent) => \"Zoom to \" + percent` with percent \"100%\". */\n zoomToActual(percent: string): string;\n /** `aria-label` of the readout: \"Zoom to 100% (now 86%)\". */\n zoomToActualNow(percent: string, now: string): string;\n fit: string;\n /** Legend title and the Model-group checkbox. */\n legend: string;\n closeLegend: string;\n /** Pill text: \"1 problem\", \"2 problems\". */\n problems(count: number, formattedCount: string): string;\n /** Pill `aria-label`: \"2 problems, 1 error\", \"2 problems, no errors\". */\n problemsLabel(count: number, errors: number, formattedCount: string, formattedErrors: string): string;\n /** Pill tooltip in the IDE host. */\n showProblems: string;\n /** Empty-file hint (guide §13.5). */\n emptyHint: string;\n insertExample: string;\n /** Status box for an invalid file; `diagram` names the notation (\"Event Storming board\"). */\n invalidFile(diagram: string): string;\n /** Key names in shortcut chips outside macOS (German: Strg, Umschalt, Plus, Minus). */\n keyNames: { ctrl: string; shift: string; plus: string; minus: string };\n}\n\n/** Every key optional; an `undefined` value keeps the default (a conditional override). */\nexport type ShellMessageOverrides = {\n [Key in Exclude<keyof ShellMessages, \"keyNames\">]?: ShellMessages[Key] | undefined;\n} & {\n keyNames?: { [Key in keyof ShellMessages[\"keyNames\"]]?: string | undefined } | undefined;\n};\n\nexport const defaultMessages: ShellMessages = {\n menu: \"Menu\",\n tools: \"Tools\",\n canvas: \"Diagram\",\n zoom: \"Zoom\",\n zoomOut: \"Zoom out\",\n zoomIn: \"Zoom in\",\n zoomToActual: (percent) => `Zoom to ${percent}`,\n zoomToActualNow: (percent, now) => `Zoom to ${percent} (now ${now})`,\n fit: \"Fit to view\",\n legend: \"Legend\",\n closeLegend: \"Close legend\",\n problems: (count, formattedCount) => `${formattedCount} ${count === 1 ? \"problem\" : \"problems\"}`,\n problemsLabel: (count, errors, formattedCount, formattedErrors) =>\n `${formattedCount} ${count === 1 ? \"problem\" : \"problems\"}, ${\n errors === 0 ? \"no errors\" : `${formattedErrors} ${errors === 1 ? \"error\" : \"errors\"}`\n }`,\n showProblems: \"Show in Problems view\",\n emptyHint: \"Pick a tool from the palette to start.\",\n insertExample: \"Insert example\",\n invalidFile: (diagram) =>\n `This file isn't a valid ${diagram} right now. The diagram shows the last valid version and is read-only until you fix the text.`,\n keyNames: { ctrl: \"Ctrl\", shift: \"Shift\", plus: \"Plus\", minus: \"Minus\" },\n};\n\n/** `defaultMessages` with `overrides` applied (`keyNames` merged key by key). */\nexport function resolveMessages(overrides?: ShellMessageOverrides | undefined): ShellMessages {\n const { keyNames, ...texts } = overrides ?? {};\n return {\n ...defaultMessages,\n ...definedEntries(texts),\n keyNames: { ...defaultMessages.keyNames, ...definedEntries(keyNames ?? {}) },\n };\n}\n\n// `{ menu: undefined }` (a spread of optional fields, a conditional override) keeps the default\n// instead of blanking the text.\nfunction definedEntries<T extends object>(partial: T): { [Key in keyof T]?: Exclude<T[Key], undefined> } {\n return Object.fromEntries(Object.entries(partial).filter(([, value]) => value !== undefined)) as {\n [Key in keyof T]?: Exclude<T[Key], undefined>;\n };\n}\n","import { SHELL } from \"./sizes.js\";\nimport type { Bounds, PaletteRow, Point, Size } from \"./types.js\";\n\n/** Free space the top row needs between the palette and a neighbouring island (guide §5.15). */\nexport const PALETTE_CLEARANCE = 16;\n\n/** Hover delay of the chrome tooltip, equal to diagram-js `HoverTooltip` `SHOW_DELAY`. */\nexport const TOOLTIP_DELAY_MS = 300;\n\n/** The status box for an invalid file shows after this long without a valid import (guide §5.12). */\nexport const INVALID_STATUS_DELAY_MS = 800;\n\nexport interface PaletteRowInput {\n containerWidth: number;\n /**\n * The palette's intrinsic border-box width (`scrollWidth` plus its borders), so the decision does\n * not flip once the second row clips it.\n */\n paletteWidth: number;\n /** Right edge of the menu trigger, relative to the shell root. */\n menuRight: number;\n /** Left edge of the primary action (web app), relative to the shell root; absent in IDE hosts. */\n primaryLeft?: number | undefined;\n}\n\n/**\n * `second-row` when the container is at most `SHELL.narrow` wide or a centred palette would keep\n * less than `PALETTE_CLEARANCE` to the menu trigger (or the primary action); `top` otherwise.\n */\nexport function decidePaletteRow(input: PaletteRowInput): PaletteRow {\n const { containerWidth, paletteWidth, menuRight, primaryLeft } = input;\n if (containerWidth <= SHELL.narrow) return \"second-row\";\n const paletteLeft = (containerWidth - paletteWidth) / 2;\n const paletteRight = (containerWidth + paletteWidth) / 2;\n if (paletteLeft < menuRight + PALETTE_CLEARANCE) return \"second-row\";\n if (primaryLeft !== undefined && paletteRight > primaryLeft - PALETTE_CLEARANCE) return \"second-row\";\n return \"top\";\n}\n\n/** The legend starts open unless the container is at most `SHELL.low` high (guide §5.10). */\nexport function legendStartsOpen(containerHeight: number): boolean {\n return containerHeight > SHELL.low;\n}\n\nexport interface TooltipPlacementInput {\n /** The hovered or focused control, relative to the shell root (horizontal centre). */\n anchor: Bounds;\n /** The island the control sits in, relative to the shell root (vertical placement). */\n island: Bounds;\n tooltip: Size;\n container: Size;\n}\n\n/**\n * The tooltip's top-left corner relative to the shell root (guide §5.6): below an island in the\n * upper half (`island.bottom + 8`: top row 60, second row 112), above one in the lower half\n * (`island.top − 8 − height`: bottom row ends at `bottom: 60px`); centred on the anchor, shifted to\n * keep `SHELL.edge` to the container's sides.\n */\nexport function placeTooltip(input: TooltipPlacementInput): Point {\n const { anchor, island, tooltip, container } = input;\n const inUpperHalf = island.y + island.height / 2 < container.height / 2;\n const y = inUpperHalf ? island.y + island.height + SHELL.gap : island.y - SHELL.gap - tooltip.height;\n const centred = anchor.x + anchor.width / 2 - tooltip.width / 2;\n const rightmost = container.width - SHELL.edge - tooltip.width;\n // In a container narrower than the tooltip plus both edges, the left edge wins.\n const x = Math.max(SHELL.edge, Math.min(centred, rightmost));\n return { x, y };\n}\n","type Child = Node | string | undefined | null | false;\n\n/** `document.createElement` with attributes and children; `undefined` attribute values are skipped. */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n ownerDocument: Document,\n tag: K,\n attributes: Readonly<Record<string, string | undefined>> = {},\n ...children: Child[]\n): HTMLElementTagNameMap[K] {\n const element = ownerDocument.createElement(tag);\n for (const [name, value] of Object.entries(attributes)) {\n if (value !== undefined) element.setAttribute(name, value);\n }\n for (const child of children) {\n if (child === undefined || child === null || child === false) continue;\n element.append(child);\n }\n return element;\n}\n\n/** Sets an attribute, or removes it for `null`/`false`. */\nexport function toggleAttribute(element: Element, name: string, value: string | null | false): void {\n if (value === null || value === false) element.removeAttribute(name);\n else element.setAttribute(name, value);\n}\n\n/** The element's box relative to the padding box of `root` (the containing block of the islands). */\nexport function boxRelativeTo(element: Element, root: HTMLElement) {\n const box = element.getBoundingClientRect();\n const origin = root.getBoundingClientRect();\n return {\n x: box.left - origin.left - root.clientLeft,\n y: box.top - origin.top - root.clientTop,\n width: box.width,\n height: box.height,\n };\n}\n\n/** The accessible name a control shows without its tooltip: `aria-label`, else its text. */\nexport function accessibleName(control: Element): string {\n return (control.getAttribute(\"aria-label\") ?? control.textContent ?? \"\").trim();\n}\n\n/** True for keyboard focus (`:focus-visible`); engines without the selector count every focus. */\nexport function hasVisibleFocus(element: Element): boolean {\n try {\n return element.matches(\":focus-visible\");\n } catch {\n return true;\n }\n}\n","import type { Insets, ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport type { EmptyHintOptions } from \"./types.js\";\n\nexport interface EmptyHint {\n readonly element: HTMLElement;\n isShown(): boolean;\n setShown(shown: boolean): void;\n /** Centres the hint in the free rectangle of the fit (guide §13.5). */\n place(insets: Insets): void;\n destroy(): void;\n}\n\nexport function createEmptyHint(\n ownerDocument: Document,\n messages: ShellMessages,\n options: EmptyHintOptions,\n): EmptyHint {\n const { onInsertExample } = options;\n const action = onInsertExample\n ? createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-hint-action\" },\n messages.insertExample,\n )\n : undefined;\n action?.addEventListener(\"click\", () => onInsertExample?.());\n const element = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-hint\" },\n createElement(ownerDocument, \"p\", { class: \"cd-shell-hint-text\" }, messages.emptyHint),\n action,\n );\n element.hidden = true;\n\n return {\n element,\n isShown: () => !element.hidden,\n setShown(shown) {\n element.hidden = !shown;\n },\n place({ top, right, bottom, left }) {\n element.style.inset = `${top}px ${right}px ${bottom}px ${left}px`;\n },\n destroy() {\n element.remove();\n },\n };\n}\n","import { createElement } from \"./element.js\";\nimport type { InspectorHandle, InspectorOptions } from \"./types.js\";\n\nexport interface InspectorController extends InspectorHandle {\n destroy(): void;\n}\n\nexport function createInspector(\n ownerDocument: Document,\n options: InspectorOptions,\n onChange: (open: boolean) => void,\n): InspectorController {\n const element = createElement(ownerDocument, \"aside\", {\n class: \"cd-shell-inspector\",\n \"data-chrome\": \"inspector\",\n \"aria-label\": options.label,\n });\n element.hidden = true;\n\n function setOpen(open: boolean): void {\n if (open === !element.hidden) return;\n element.hidden = !open;\n onChange(open);\n }\n\n return {\n element,\n isOpen: () => !element.hidden,\n open: () => setOpen(true),\n close: () => setOpen(false),\n destroy() {\n element.remove();\n },\n };\n}\n","import { TEXT_FIELD_SELECTOR, decideKey, type ChromeKey, type ShellHost } from \"../core/index.js\";\n\nexport interface KeyListenerContext {\n host: ShellHost;\n /** Where dialogs and popovers count: the document in an own document, else the shell root. */\n dialogScope: ParentNode;\n menuOpen(): boolean;\n closeMenu(): void;\n hideTooltip(): void;\n run(key: ChromeKey): void;\n}\n\nfunction isTextField(target: EventTarget | null): boolean {\n if (!target || typeof (target as Element).closest !== \"function\") return false;\n const element = target as HTMLElement;\n return element.isContentEditable === true || element.closest(TEXT_FIELD_SELECTOR) !== null;\n}\n\n// A dialog a modeler hides through CSS (a class with display: none) is closed as well.\nfunction isShown(element: Element): boolean {\n if (element.localName === \"dialog\" && !element.hasAttribute(\"open\")) return false;\n if (element.closest(\"[hidden]\")) return false;\n return (\n typeof element.checkVisibility !== \"function\" || element.checkVisibility({ visibilityProperty: true })\n );\n}\n\nfunction isModal(element: Element): boolean {\n if (element.getAttribute(\"aria-modal\") === \"true\") return true;\n try {\n return element.matches(\":modal\");\n } catch {\n return false;\n }\n}\n\nfunction openDialogs(scope: ParentNode): Element[] {\n return [...scope.querySelectorAll('[role=\"dialog\"], [role=\"alertdialog\"], dialog')].filter(isShown);\n}\n\n/** The shell's one `keydown` listener (bubble phase): applies `decideKey` (guide §5.8, §13.5). */\nexport function createKeyListener(context: KeyListenerContext): (event: KeyboardEvent) => void {\n return (event) => {\n if (event.key === \"Escape\") context.hideTooltip();\n const dialogs = openDialogs(context.dialogScope);\n const decision = decideKey(event, {\n host: context.host,\n inTextField: isTextField(event.target),\n menuOpen: context.menuOpen(),\n dialogOpen: dialogs.length > 0,\n modalOpen: dialogs.some(isModal),\n defaultPrevented: event.defaultPrevented,\n });\n if (decision.preventDefault) event.preventDefault();\n if (decision.stopPropagation) event.stopPropagation();\n if (decision.action === \"closeMenu\") context.closeMenu();\n else if (decision.action) context.run(decision.action);\n };\n}\n","/**\n * Everything the shell changes outside the elements it creates (classes and attributes on the root,\n * `<html>` and a passed canvas, listeners, observers, timers), recorded so `destroy()` puts it back\n * exactly as it was before `mountShell`.\n */\nexport class Ledger {\n private readonly undo: (() => void)[] = [];\n private readonly originalAttributes = new Map<Element, Map<string, string | null>>();\n private closed = false;\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n /** Runs `task` on `close()`, in reverse order of registration. */\n defer(task: () => void): void {\n this.undo.push(task);\n }\n\n /** Adds `className` unless present; `close()` removes it only if this ledger added it. */\n addClass(element: Element, className: string): void {\n if (element.classList.contains(className)) return;\n const hadClassAttribute = element.hasAttribute(\"class\");\n element.classList.add(className);\n this.defer(() => {\n element.classList.remove(className);\n if (!hadClassAttribute && element.classList.length === 0) element.removeAttribute(\"class\");\n });\n }\n\n /** Sets (string) or removes (`null`) an attribute; `close()` restores the value before the first change. */\n attribute(element: Element, name: string, value: string | null): void {\n let originals = this.originalAttributes.get(element);\n if (!originals) {\n originals = new Map();\n this.originalAttributes.set(element, originals);\n }\n if (!originals.has(name)) {\n originals.set(name, element.getAttribute(name));\n this.defer(() => {\n const original = originals.get(name) ?? null;\n if (original === null) element.removeAttribute(name);\n else element.setAttribute(name, original);\n });\n }\n if (value === null) element.removeAttribute(name);\n else element.setAttribute(name, value);\n }\n\n listen<K extends keyof DocumentEventMap>(\n target: Document,\n type: K,\n listener: (event: DocumentEventMap[K]) => void,\n options?: AddEventListenerOptions,\n ): void;\n listen<K extends keyof HTMLElementEventMap>(\n target: HTMLElement,\n type: K,\n listener: (event: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n ): void;\n listen(\n target: EventTarget,\n type: string,\n listener: (event: never) => void,\n options?: AddEventListenerOptions,\n ): void {\n const handler = listener as EventListener;\n target.addEventListener(type, handler, options);\n this.defer(() => target.removeEventListener(type, handler, options));\n }\n\n /** Runs every undo task once; later calls are no-ops. */\n close(): void {\n if (this.closed) return;\n this.closed = true;\n for (const task of this.undo.reverse()) {\n try {\n task();\n } catch {\n // one failing undo (an element the modeler already removed) must not keep the rest\n }\n }\n this.undo.length = 0;\n this.originalAttributes.clear();\n }\n}\n","/*! @miragon/modeler-shell icon geometry\n * Lucide (lucide-static 1.59.0) @license ISC\n * Copyright (c) 2026 Lucide Icons and Contributors\n * Derived from Feather, as Lucide's LICENSE lists them: check, circle-x (x-circle), maximize,\n * minus, plus, triangle-alert (alert-triangle) and x. Feather @license MIT\n * Copyright (c) 2013-present Cole Bemis\n * Full notices: THIRD_PARTY_NOTICES.md of @miragon/modeler-shell */\n\n/*\n * The common Lucide set of the chrome (guide §5.14), inlined so the package has no icon runtime\n * dependency, copied unchanged from `icon-nodes.json`. One exception: `line-segment` (Draw) is\n * Lucide's `spline` with a straight segment between its end points, because the curve read as a\n * telephone receiver at 20px. The comment above is a legal comment, so\n * esbuild keeps it in the bundle chunk that carries this geometry.\n */\n\n/** One Lucide icon: its SVG child elements on the 24 × 24 grid. */\nexport type IconNode = ReadonlyArray<readonly [tag: string, attributes: Readonly<Record<string, string>>]>;\n\nexport type ShellIconName =\n | \"menu\"\n | \"minus\"\n | \"plus\"\n | \"maximize\"\n | \"check\"\n | \"x\"\n | \"file-plus\"\n | \"folder-open\"\n | \"import\"\n | \"file-image\"\n | \"file-code-corner\"\n | \"keyboard\"\n | \"share-2\"\n | \"circle-x\"\n | \"triangle-alert\"\n | \"square-dashed-mouse-pointer\"\n | \"hand\"\n | \"line-segment\"\n | \"unfold-horizontal\"\n | \"workflow\";\n\nexport const ICONS: Readonly<Record<ShellIconName, IconNode>> = {\n menu: [\n [\"path\", { d: \"M4 5h16\" }],\n [\"path\", { d: \"M4 12h16\" }],\n [\"path\", { d: \"M4 19h16\" }],\n ],\n minus: [[\"path\", { d: \"M5 12h14\" }]],\n plus: [\n [\"path\", { d: \"M5 12h14\" }],\n [\"path\", { d: \"M12 5v14\" }],\n ],\n maximize: [\n [\"path\", { d: \"M8 3H5a2 2 0 0 0-2 2v3\" }],\n [\"path\", { d: \"M21 8V5a2 2 0 0 0-2-2h-3\" }],\n [\"path\", { d: \"M3 16v3a2 2 0 0 0 2 2h3\" }],\n [\"path\", { d: \"M16 21h3a2 2 0 0 0 2-2v-3\" }],\n ],\n check: [[\"path\", { d: \"M20 6 9 17l-5-5\" }]],\n x: [\n [\"path\", { d: \"M18 6 6 18\" }],\n [\"path\", { d: \"m6 6 12 12\" }],\n ],\n \"file-plus\": [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n },\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\" }],\n [\"path\", { d: \"M9 15h6\" }],\n [\"path\", { d: \"M12 18v-6\" }],\n ],\n \"folder-open\": [\n [\n \"path\",\n {\n d: \"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\",\n },\n ],\n ],\n import: [\n [\"path\", { d: \"M12 3v12\" }],\n [\"path\", { d: \"m8 11 4 4 4-4\" }],\n [\"path\", { d: \"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4\" }],\n ],\n \"file-image\": [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n },\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\" }],\n [\"circle\", { cx: \"10\", cy: \"12\", r: \"2\" }],\n [\"path\", { d: \"m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22\" }],\n ],\n \"file-code-corner\": [\n [\n \"path\",\n {\n d: \"M4 12.15V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-3.35\",\n },\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\" }],\n [\"path\", { d: \"m5 16-3 3 3 3\" }],\n [\"path\", { d: \"m9 22 3-3-3-3\" }],\n ],\n keyboard: [\n [\"path\", { d: \"M10 8h.01\" }],\n [\"path\", { d: \"M12 12h.01\" }],\n [\"path\", { d: \"M14 8h.01\" }],\n [\"path\", { d: \"M16 12h.01\" }],\n [\"path\", { d: \"M18 8h.01\" }],\n [\"path\", { d: \"M6 8h.01\" }],\n [\"path\", { d: \"M7 16h10\" }],\n [\"path\", { d: \"M8 12h.01\" }],\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\" }],\n ],\n \"share-2\": [\n [\"circle\", { cx: \"18\", cy: \"5\", r: \"3\" }],\n [\"circle\", { cx: \"6\", cy: \"12\", r: \"3\" }],\n [\"circle\", { cx: \"18\", cy: \"19\", r: \"3\" }],\n [\"line\", { x1: \"8.59\", x2: \"15.42\", y1: \"13.51\", y2: \"17.49\" }],\n [\"line\", { x1: \"15.41\", x2: \"8.59\", y1: \"6.51\", y2: \"10.49\" }],\n ],\n \"circle-x\": [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\" }],\n [\"path\", { d: \"m15 9-6 6\" }],\n [\"path\", { d: \"m9 9 6 6\" }],\n ],\n \"triangle-alert\": [\n [\"path\", { d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" }],\n [\"path\", { d: \"M12 9v4\" }],\n [\"path\", { d: \"M12 17h.01\" }],\n ],\n \"square-dashed-mouse-pointer\": [\n [\n \"path\",\n {\n d: \"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z\",\n },\n ],\n [\"path\", { d: \"M5 3a2 2 0 0 0-2 2\" }],\n [\"path\", { d: \"M19 3a2 2 0 0 1 2 2\" }],\n [\"path\", { d: \"M5 21a2 2 0 0 1-2-2\" }],\n [\"path\", { d: \"M9 3h1\" }],\n [\"path\", { d: \"M9 21h2\" }],\n [\"path\", { d: \"M14 3h1\" }],\n [\"path\", { d: \"M3 9v1\" }],\n [\"path\", { d: \"M21 9v2\" }],\n [\"path\", { d: \"M3 14v1\" }],\n ],\n hand: [\n [\"path\", { d: \"M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2\" }],\n [\"path\", { d: \"M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2\" }],\n [\"path\", { d: \"M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8\" }],\n [\n \"path\",\n {\n d: \"M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15\",\n },\n ],\n ],\n \"line-segment\": [\n [\"circle\", { cx: \"19\", cy: \"5\", r: \"2\" }],\n [\"circle\", { cx: \"5\", cy: \"19\", r: \"2\" }],\n [\"path\", { d: \"M6.5 17.5 17.5 6.5\" }],\n ],\n \"unfold-horizontal\": [\n [\"path\", { d: \"M16 12h6\" }],\n [\"path\", { d: \"M8 12H2\" }],\n [\"path\", { d: \"M12 2v2\" }],\n [\"path\", { d: \"M12 8v2\" }],\n [\"path\", { d: \"M12 14v2\" }],\n [\"path\", { d: \"M12 20v2\" }],\n [\"path\", { d: \"m19 15 3-3-3-3\" }],\n [\"path\", { d: \"m5 9-3 3 3 3\" }],\n ],\n workflow: [\n [\"rect\", { width: \"8\", height: \"8\", x: \"3\", y: \"3\", rx: \"2\" }],\n [\"path\", { d: \"M7 11v4a2 2 0 0 0 2 2h4\" }],\n [\"rect\", { width: \"8\", height: \"8\", x: \"13\", y: \"13\", rx: \"2\" }],\n ],\n};\n\nexport interface IconOptions {\n /** Rendered width and height in px; default 16 (chrome). */\n size?: number;\n /** Stroke width on the 24 grid; default 2.5. */\n strokeWidth?: number;\n className?: string;\n}\n\n/** Palette tool icons: 20px with stroke 2 (guide §5.5), as heavy as the 16px chrome icons. */\nexport const PALETTE_TOOL_ICON: Readonly<IconOptions> = { size: 20, strokeWidth: 2 };\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_STROKE_WIDTH = 2.5;\nconst SVG_NAMESPACE = \"http://www.w3.org/2000/svg\";\n\n// Everything Lucide icon nodes are made of. Markup goes into innerHTML (palette entry `html`), so\n// any other element or attribute (a <script>, an onload, an href) is dropped.\nconst ICON_ELEMENTS: ReadonlySet<string> = new Set([\n \"path\",\n \"circle\",\n \"ellipse\",\n \"line\",\n \"polyline\",\n \"polygon\",\n \"rect\",\n]);\nconst GEOMETRY_ATTRIBUTES: ReadonlySet<string> = new Set([\n \"d\",\n \"cx\",\n \"cy\",\n \"r\",\n \"rx\",\n \"ry\",\n \"x\",\n \"y\",\n \"x1\",\n \"y1\",\n \"x2\",\n \"y2\",\n \"width\",\n \"height\",\n \"points\",\n]);\n\ninterface SanitizedIcon {\n root: [name: string, value: string][];\n children: [tag: string, attributes: [name: string, value: string][]][];\n}\n\nfunction positiveOr(value: number | undefined, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nfunction iconNodeOf(icon: ShellIconName | IconNode): IconNode {\n if (typeof icon !== \"string\") return icon;\n return Object.prototype.hasOwnProperty.call(ICONS, icon) ? ICONS[icon] : [];\n}\n\nfunction sanitize(icon: ShellIconName | IconNode, options: IconOptions = {}): SanitizedIcon {\n const size = String(positiveOr(options.size, DEFAULT_SIZE));\n const root: SanitizedIcon[\"root\"] = [];\n if (options.className) root.push([\"class\", options.className]);\n root.push(\n [\"width\", size],\n [\"height\", size],\n [\"viewBox\", \"0 0 24 24\"],\n [\"fill\", \"none\"],\n [\"stroke\", \"currentColor\"],\n [\"stroke-width\", String(positiveOr(options.strokeWidth, DEFAULT_STROKE_WIDTH))],\n [\"stroke-linecap\", \"round\"],\n [\"stroke-linejoin\", \"round\"],\n [\"aria-hidden\", \"true\"],\n [\"focusable\", \"false\"],\n );\n const children: SanitizedIcon[\"children\"] = [];\n for (const node of iconNodeOf(icon)) {\n const [tag, attributes] = node;\n if (!ICON_ELEMENTS.has(tag)) continue;\n const kept = Object.entries(attributes)\n .filter(([name]) => GEOMETRY_ATTRIBUTES.has(name))\n .map(([name, value]): [string, string] => [name, String(value)]);\n children.push([tag, kept]);\n }\n return { root, children };\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction attributeList(attributes: readonly [string, string][]): string {\n return attributes.map(([name, value]) => ` ${name}=\"${escapeAttribute(value)}\"`).join(\"\");\n}\n\n/**\n * Decorative inline SVG markup (`aria-hidden=\"true\"`, `focusable=\"false\"`, `fill=\"none\"`,\n * `stroke=\"currentColor\"`, round caps and joins). Only Lucide's elements and geometry attributes\n * pass, so the result is safe for `innerHTML` (palette entry `html`).\n */\nexport function iconMarkup(icon: ShellIconName | IconNode, options?: IconOptions): string {\n const { root, children } = sanitize(icon, options);\n const content = children.map(([tag, attributes]) => `<${tag}${attributeList(attributes)}/>`).join(\"\");\n return `<svg xmlns=\"${SVG_NAMESPACE}\"${attributeList(root)}>${content}</svg>`;\n}\n\n/** The same icon as an `SVGSVGElement`. */\nexport function iconElement(icon: ShellIconName | IconNode, options?: IconOptions): SVGSVGElement {\n const { root, children } = sanitize(icon, options);\n const svg = document.createElementNS(SVG_NAMESPACE, \"svg\");\n for (const [name, value] of root) svg.setAttribute(name, value);\n for (const [tag, attributes] of children) {\n const child = document.createElementNS(SVG_NAMESPACE, tag);\n for (const [name, value] of attributes) child.setAttribute(name, value);\n svg.append(child);\n }\n return svg;\n}\n","import type { ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { LegendHandle, LegendOptions } from \"./types.js\";\n\nexport interface LegendController extends LegendHandle {\n /** The start state once the container height is known; never reported through `onToggle`. */\n start(open: boolean): void;\n isStarted(): boolean;\n destroy(): void;\n}\n\nexport interface LegendContext {\n ownerDocument: Document;\n messages: ShellMessages;\n tooltip: TooltipController;\n titleId: string;\n options: LegendOptions;\n onChange(open: boolean): void;\n /** Where the focus goes when the close button hides the legend under it. */\n focusAfterClose(): void;\n}\n\nexport function createLegend(context: LegendContext): LegendController {\n const { ownerDocument, messages, tooltip, titleId, options } = context;\n const close = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: \"cd-shell-legend-close\",\n \"aria-label\": messages.closeLegend,\n });\n close.append(iconElement(\"x\"));\n const body = createElement(ownerDocument, \"div\", { class: \"cd-shell-legend-body\" });\n const element = createElement(\n ownerDocument,\n \"section\",\n { class: \"cd-shell-legend cd-shell-island\", \"data-chrome\": \"legend\", \"aria-labelledby\": titleId },\n createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-legend-header\" },\n createElement(ownerDocument, \"div\", { class: \"cd-shell-legend-title\", id: titleId }, messages.legend),\n close,\n ),\n body,\n );\n element.hidden = true;\n options.render(body);\n\n let open = false;\n let started = false;\n const detachTooltip = tooltip.attach(close, { label: messages.closeLegend });\n\n function apply(next: boolean): boolean {\n started = true;\n if (next === open) return false;\n open = next;\n element.hidden = !open;\n if (!open && element.contains(ownerDocument.activeElement)) context.focusAfterClose();\n context.onChange(open);\n return true;\n }\n\n function setOpen(next: boolean): void {\n if (apply(next)) options.onToggle?.(next);\n }\n\n close.addEventListener(\"click\", () => setOpen(false));\n\n return {\n element,\n body,\n isOpen: () => open,\n setOpen,\n toggle: () => setOpen(!open),\n start(initial) {\n if (!started) apply(initial);\n },\n isStarted: () => started,\n destroy() {\n detachTooltip();\n element.remove();\n },\n };\n}\n","import { ariaKeyShortcutsFromLabel, matchChromeKey, type ShellMessages } from \"../core/index.js\";\nimport { createElement, toggleAttribute } from \"./element.js\";\nimport { iconElement, type ShellIconName } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { MenuCheckboxEntry, MenuEntry, MenuGroups, MenuHandle, MenuRadioGroup } from \"./types.js\";\n\ntype GroupName = keyof MenuGroups;\nconst GROUP_ORDER: readonly GroupName[] = [\"model\", \"export\", \"help\"];\n\ninterface Item {\n /** Stable across renders, so a re-render keeps the focus on the same entry. */\n key: string;\n element: HTMLButtonElement;\n label: string;\n disabled: boolean;\n activate(): void;\n}\n\nexport interface MenuContext {\n root: HTMLElement;\n layer: HTMLElement;\n id: string;\n messages: ShellMessages;\n tooltip: TooltipController;\n groups: MenuGroups;\n /** Entries the shell appends to the Model group (the Legend checkbox). */\n shellModelEntries(): readonly MenuCheckboxEntry[];\n isReadOnly(): boolean;\n}\n\nexport interface MenuController extends MenuHandle {\n destroy(): void;\n}\n\nfunction isPrintable(event: KeyboardEvent): boolean {\n return event.key.length === 1 && /\\S/.test(event.key) && !event.ctrlKey && !event.metaKey && !event.altKey;\n}\n\nexport function createMenu(context: MenuContext): MenuController {\n const { root, layer, id, messages, tooltip } = context;\n const ownerDocument = root.ownerDocument;\n let groups = context.groups;\n let items: Item[] = [];\n let destroyed = false;\n\n const trigger = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: \"cd-shell-menu-trigger cd-shell-island\",\n \"data-chrome\": \"menu\",\n \"aria-label\": messages.menu,\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": \"false\",\n \"aria-controls\": id,\n });\n trigger.append(iconElement(\"menu\"));\n\n const dropdown = createElement(ownerDocument, \"div\", {\n class: \"cd-shell-menu\",\n id,\n role: \"menu\",\n \"aria-label\": messages.menu,\n });\n dropdown.hidden = true;\n layer.prepend(dropdown);\n\n const isOpen = (): boolean => !dropdown.hidden;\n\n function entriesOf(name: GroupName): readonly MenuEntry[] {\n const own = groups[name] ?? [];\n return name === \"model\" ? [...own, ...context.shellModelEntries()] : own;\n }\n\n function hasEntries(): boolean {\n return GROUP_ORDER.some((name) => entriesOf(name).length > 0);\n }\n\n function updateTriggerVisibility(): void {\n trigger.hidden = !hasEntries();\n if (trigger.hidden) close();\n }\n\n // Guide §13.5: on a read-only canvas the Model entries that change the document are aria-disabled.\n // View-only toggles (the shell's Legend, a modeler's Type captions) opt out and stay usable.\n function isDisabled(entry: MenuEntry, group: GroupName): boolean {\n if (group === \"model\" && context.isReadOnly() && entry.keepEnabledWhenReadOnly !== true) return true;\n return entry.disabled?.() ?? false;\n }\n\n function itemElement(\n role: \"menuitem\" | \"menuitemcheckbox\" | \"menuitemradio\",\n label: string,\n options: {\n icon?: ShellIconName | undefined;\n end?: Node | undefined;\n disabled: boolean;\n checked?: boolean;\n },\n ): HTMLButtonElement {\n const iconSlot = createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-icon\" });\n if (options.icon) iconSlot.append(iconElement(options.icon));\n const element = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-menu-item\", role, tabindex: \"-1\" },\n iconSlot,\n createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-label\" }, label),\n options.end && createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-end\" }, options.end),\n );\n toggleAttribute(element, \"aria-disabled\", options.disabled && \"true\");\n if (options.checked !== undefined) element.setAttribute(\"aria-checked\", String(options.checked));\n return element;\n }\n\n function checkMark(): SVGSVGElement {\n return iconElement(\"check\", { className: \"cd-shell-menu-check\" });\n }\n\n function renderEntry(entry: Exclude<MenuEntry, MenuRadioGroup>, group: GroupName): Item {\n const disabled = isDisabled(entry, group);\n if (entry.kind === \"checkbox\") {\n const checked = entry.checked();\n const element = itemElement(\"menuitemcheckbox\", entry.label, {\n icon: entry.icon,\n end: checkMark(),\n disabled,\n checked,\n });\n element.dataset.menuId = entry.id;\n element.dataset.menuGroup = group;\n return {\n key: entry.id,\n element,\n label: entry.label,\n disabled,\n activate() {\n entry.onToggle(!entry.checked());\n refresh();\n },\n };\n }\n const shortcut =\n entry.kind === \"action\" && entry.shortcut\n ? createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-shortcut\" }, entry.shortcut)\n : undefined;\n const element = itemElement(\"menuitem\", entry.label, { icon: entry.icon, end: shortcut, disabled });\n element.dataset.menuId = entry.id;\n element.dataset.menuGroup = group;\n if (entry.kind === \"action\") {\n const keyShortcuts =\n entry.ariaKeyShortcuts ?? (entry.shortcut ? ariaKeyShortcutsFromLabel(entry.shortcut) : undefined);\n toggleAttribute(element, \"aria-keyshortcuts\", keyShortcuts || null);\n }\n if (entry.kind === \"dialog\") element.setAttribute(\"aria-haspopup\", \"dialog\");\n if (entry.kind === \"action\" && entry.danger) element.dataset.danger = \"\";\n return {\n key: entry.id,\n element,\n label: entry.label,\n disabled,\n activate() {\n close({ restoreFocus: true });\n entry.onSelect();\n },\n };\n }\n\n function renderRadioGroup(\n entry: MenuRadioGroup,\n group: GroupName,\n ): { element: HTMLElement; items: Item[] } {\n const disabled = isDisabled(entry, group);\n const value = entry.value();\n const container = createElement(\n ownerDocument,\n \"div\",\n {\n class: \"cd-shell-menu-group\",\n role: \"group\",\n \"aria-label\": entry.label,\n \"data-menu-id\": entry.id,\n \"data-menu-group\": group,\n },\n // The group's aria-label carries the heading; a menu holds no loose text.\n createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-menu-heading\", \"aria-hidden\": \"true\" },\n entry.label,\n ),\n );\n const radioItems = entry.options.map((option): Item => {\n const element = itemElement(\"menuitemradio\", option.label, {\n end: checkMark(),\n disabled,\n checked: option.value === value,\n });\n element.dataset.menuValue = option.value;\n container.append(element);\n return {\n key: `${entry.id}\\u0000${option.value}`,\n element,\n label: option.label,\n disabled,\n activate() {\n if (entry.value() !== option.value) entry.onSelect(option.value);\n refresh();\n },\n };\n });\n return { element: container, items: radioItems };\n }\n\n function render(): void {\n const focusedKey = items.find((item) => item.element === ownerDocument.activeElement)?.key;\n const nodes: HTMLElement[] = [];\n const rendered: Item[] = [];\n for (const name of GROUP_ORDER) {\n const entries = entriesOf(name);\n if (entries.length === 0) continue;\n if (nodes.length > 0) {\n nodes.push(\n createElement(ownerDocument, \"div\", { class: \"cd-shell-menu-separator\", role: \"separator\" }),\n );\n }\n for (const entry of entries) {\n if (entry.kind === \"radio\") {\n const radio = renderRadioGroup(entry, name);\n nodes.push(radio.element);\n rendered.push(...radio.items);\n } else {\n const item = renderEntry(entry, name);\n nodes.push(item.element);\n rendered.push(item);\n }\n }\n }\n for (const item of rendered) {\n item.element.addEventListener(\"click\", () => {\n if (!item.disabled) item.activate();\n });\n }\n dropdown.replaceChildren(...nodes);\n items = rendered;\n if (focusedKey !== undefined && isOpen()) {\n (items.find((item) => item.key === focusedKey) ?? items[0])?.element.focus();\n }\n }\n\n function focusAt(index: number): void {\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.element.focus();\n }\n\n function currentIndex(): number {\n return items.findIndex((item) => item.element === ownerDocument.activeElement);\n }\n\n function typeAhead(character: string): void {\n const start = currentIndex();\n const lower = character.toLowerCase();\n for (let step = 1; step <= items.length; step++) {\n const index = (Math.max(start, -1) + step) % items.length;\n if (items[index]?.label.toLowerCase().startsWith(lower)) {\n focusAt(index);\n return;\n }\n }\n }\n\n const onOutsidePointerDown = (event: PointerEvent): void => {\n const target = event.target as Node | null;\n if (target && (dropdown.contains(target) || trigger.contains(target))) return;\n close();\n };\n\n // The focus left the document (a click into the VS Code workbench, another iframe): from the\n // user's view a click outside, so the menu closes without moving the focus (guide §5.4).\n const onWindowBlur = (): void => close();\n\n function open(focus: \"first\" | \"last\" = \"first\"): void {\n if (destroyed || !hasEntries()) return;\n tooltip.hide();\n const wasOpen = isOpen();\n render();\n if (!wasOpen) {\n dropdown.hidden = false;\n trigger.setAttribute(\"aria-expanded\", \"true\");\n // Capture phase: diagram-js stops pointer events on palette, context pad and canvas.\n ownerDocument.addEventListener(\"pointerdown\", onOutsidePointerDown, true);\n ownerDocument.defaultView?.addEventListener(\"blur\", onWindowBlur);\n }\n focusAt(focus === \"last\" ? items.length - 1 : 0);\n }\n\n function close(options: { restoreFocus?: boolean } = {}): void {\n if (!isOpen()) return;\n dropdown.hidden = true;\n trigger.setAttribute(\"aria-expanded\", \"false\");\n ownerDocument.removeEventListener(\"pointerdown\", onOutsidePointerDown, true);\n ownerDocument.defaultView?.removeEventListener(\"blur\", onWindowBlur);\n if (options.restoreFocus && !trigger.hidden) trigger.focus();\n }\n\n function refresh(): void {\n if (isOpen()) render();\n }\n\n trigger.addEventListener(\"click\", () => {\n if (isOpen()) close();\n else open(\"first\");\n });\n\n // Keys the menu consumes stop here, in every host like the palette's: a modeler's keyboard on\n // document (Event Storming moves the selection on ↑/↓, deletes it on Delete, creates a sticky on\n // E) must never act on them, and VS Code never sees them.\n function consume(event: KeyboardEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n\n trigger.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\" || event.key === \" \" || event.key === \"ArrowDown\") {\n consume(event);\n open(\"first\");\n } else if (event.key === \"ArrowUp\") {\n consume(event);\n open(\"last\");\n }\n });\n\n dropdown.addEventListener(\"keydown\", (event) => {\n // Zoom and fit keys still act with the menu open; the shell's key listener runs them.\n if (matchChromeKey(event)) return;\n switch (event.key) {\n case \"ArrowDown\":\n focusAt(currentIndex() + 1);\n break;\n case \"ArrowUp\": {\n const index = currentIndex();\n focusAt(index < 0 ? items.length - 1 : index - 1);\n break;\n }\n case \"Home\":\n focusAt(0);\n break;\n case \"End\":\n focusAt(items.length - 1);\n break;\n case \"Tab\":\n // The browser's Tab runs after this handler from wherever the focus is then: from the\n // trigger it moves on to the palette instead of leaving the shell from the layer.\n close({ restoreFocus: true });\n return;\n case \"Escape\":\n // The shell's key listener closes the menu (and keeps Escape from VS Code in the IDE host).\n return;\n case \"Enter\":\n case \" \":\n case \"Delete\":\n case \"Backspace\":\n // The entry's native click handles Enter and Space; nothing else may act on these keys.\n event.stopPropagation();\n return;\n default:\n if (!isPrintable(event)) return;\n typeAhead(event.key);\n }\n consume(event);\n });\n\n updateTriggerVisibility();\n\n return {\n trigger,\n dropdown,\n isOpen,\n open,\n close,\n refresh,\n setGroups(next) {\n groups = next;\n updateTriggerVisibility();\n refresh();\n },\n destroy() {\n if (destroyed) return;\n close();\n destroyed = true;\n trigger.remove();\n dropdown.remove();\n },\n };\n}\n","import { formatNumber, type ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { ProblemSummary, ProblemsOptions } from \"./types.js\";\n\nexport interface ProblemsPill {\n readonly element: HTMLButtonElement;\n isShown(): boolean;\n set(summary: ProblemSummary): void;\n destroy(): void;\n}\n\nexport interface ProblemsContext {\n ownerDocument: Document;\n messages: ShellMessages;\n lang: string;\n tooltip: TooltipController;\n /** The IDE host opens its Problems view, so only there the pill explains itself. */\n showTooltip: boolean;\n options: ProblemsOptions;\n}\n\nexport function createProblemsPill(context: ProblemsContext): ProblemsPill {\n const { ownerDocument, messages, lang, tooltip, options } = context;\n const icon = createElement(ownerDocument, \"span\", { class: \"cd-shell-problems-icon\" });\n const text = createElement(ownerDocument, \"span\", { class: \"cd-shell-problems-text\" });\n const element = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-problems cd-shell-island\", \"data-chrome\": \"problems\" },\n icon,\n text,\n );\n element.hidden = true;\n element.addEventListener(\"click\", () => options.onActivate());\n const detachTooltip = context.showTooltip\n ? tooltip.attach(element, { label: messages.showProblems })\n : undefined;\n\n let severity: \"danger\" | \"warning\" | undefined;\n\n return {\n element,\n isShown: () => !element.hidden,\n set({ count, errors }) {\n const shown = count > 0;\n element.hidden = !shown;\n if (!shown) {\n tooltip.hide();\n return;\n }\n const formattedCount = formatNumber(count, lang);\n text.textContent = messages.problems(count, formattedCount);\n element.setAttribute(\n \"aria-label\",\n messages.problemsLabel(count, errors, formattedCount, formatNumber(errors, lang)),\n );\n // The shape carries the severity as well, colour is never the only signal (guide §5.10).\n const next = errors > 0 ? \"danger\" : \"warning\";\n if (next !== severity) {\n severity = next;\n element.dataset.severity = next;\n icon.replaceChildren(iconElement(next === \"danger\" ? \"circle-x\" : \"triangle-alert\"));\n }\n },\n destroy() {\n detachTooltip?.();\n element.remove();\n },\n };\n}\n","import { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { StatusMessage } from \"./types.js\";\n\nexport interface StatusBox {\n readonly element: HTMLElement;\n set(status: StatusMessage | null, delayMs: number): void;\n destroy(): void;\n}\n\nexport function createStatusBox(ownerDocument: Document): StatusBox {\n const icon = createElement(ownerDocument, \"span\", { class: \"cd-shell-status-icon\" });\n const text = createElement(ownerDocument, \"p\", { class: \"cd-shell-status-text\" });\n const element = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-status\", \"data-chrome\": \"status\" },\n icon,\n text,\n );\n element.hidden = true;\n\n let pending: { status: StatusMessage; timer: ReturnType<typeof setTimeout> } | undefined;\n\n function cancelPending(): void {\n if (pending) clearTimeout(pending.timer);\n pending = undefined;\n }\n\n function show(status: StatusMessage): void {\n pending = undefined;\n if (element.dataset.severity !== status.severity) {\n element.dataset.severity = status.severity;\n element.setAttribute(\"role\", status.severity === \"danger\" ? \"alert\" : \"status\");\n icon.replaceChildren(iconElement(status.severity === \"danger\" ? \"circle-x\" : \"triangle-alert\"));\n }\n // An unchanged text is not written again, so role=\"alert\" does not announce it again.\n if (text.textContent !== status.text) text.textContent = status.text;\n element.hidden = false;\n }\n\n return {\n element,\n set(status, delayMs) {\n if (status === null) {\n cancelPending();\n element.hidden = true;\n return;\n }\n if (!element.hidden) {\n show(status);\n return;\n }\n // Repeated invalid imports while typing keep the first timer: the box shows once the text\n // stayed invalid for the delay, not the delay after the last keystroke (guide §5.12).\n if (pending) {\n pending.status = status;\n return;\n }\n if (delayMs > 0) {\n const entry = { status, timer: setTimeout(() => show(entry.status), delayMs) };\n pending = entry;\n } else {\n show(status);\n }\n },\n destroy() {\n cancelPending();\n element.remove();\n },\n };\n}\n","import { TOOLTIP_DELAY_MS, placeTooltip } from \"../core/index.js\";\nimport { accessibleName, boxRelativeTo, createElement, hasVisibleFocus } from \"./element.js\";\nimport type { TooltipContent, TooltipHandle } from \"./types.js\";\n\ntype ContentSource = TooltipContent | (() => TooltipContent | null);\n\ninterface Shown {\n control: HTMLElement;\n describedBy: string | null;\n}\n\nexport interface TooltipController extends TooltipHandle {\n readonly element: HTMLElement;\n /** One tooltip for every `selector` match inside `container` (palette entries are rebuilt often). */\n delegate(\n container: HTMLElement,\n selector: string,\n content: (control: HTMLElement) => TooltipContent | null,\n ): () => void;\n destroy(): void;\n}\n\nexport interface TooltipContext {\n root: HTMLElement;\n layer: HTMLElement;\n id: string;\n}\n\nexport function createTooltip({ root, layer, id }: TooltipContext): TooltipController {\n const ownerDocument = root.ownerDocument;\n const label = createElement(ownerDocument, \"span\", { class: \"cd-shell-tooltip-label\" });\n const shortcut = createElement(ownerDocument, \"kbd\", { class: \"cd-shell-kbd\" });\n const element = createElement(ownerDocument, \"div\", { class: \"cd-shell-tooltip\", role: \"tooltip\", id });\n element.hidden = true;\n element.append(label, shortcut);\n layer.append(element);\n\n let shown: Shown | undefined;\n let pending: { control: HTMLElement; timer: ReturnType<typeof setTimeout> } | undefined;\n // After a pointer leaves a control the next one shows at once, so moving along a row of\n // buttons does not wait 300ms for every neighbour (guide §5.6).\n let warmUntil = 0;\n // A clicked control keeps its tooltip hidden until the pointer leaves it.\n let pressed: HTMLElement | undefined;\n const detachers = new Set<() => void>();\n\n function cancelPending(): void {\n if (pending) clearTimeout(pending.timer);\n pending = undefined;\n }\n\n function resolve(source: ContentSource): TooltipContent | null {\n return typeof source === \"function\" ? source() : source;\n }\n\n function place(control: HTMLElement): void {\n const island = control.closest<HTMLElement>(\"[data-chrome]\") ?? control;\n const point = placeTooltip({\n anchor: boxRelativeTo(control, root),\n island: boxRelativeTo(island, root),\n tooltip: { width: element.offsetWidth, height: element.offsetHeight },\n container: { width: root.clientWidth, height: root.clientHeight },\n });\n element.style.left = `${point.x}px`;\n element.style.top = `${point.y}px`;\n }\n\n function hide(): void {\n cancelPending();\n if (!shown) return;\n const { control, describedBy } = shown;\n shown = undefined;\n element.hidden = true;\n if (describedBy === null) control.removeAttribute(\"aria-describedby\");\n else control.setAttribute(\"aria-describedby\", describedBy);\n }\n\n function show(control: HTMLElement, source: ContentSource): void {\n cancelPending();\n const content = resolve(source);\n if (!content || !control.isConnected) {\n if (shown?.control === control) hide();\n return;\n }\n if (shown && shown.control !== control) hide();\n label.textContent = content.label;\n shortcut.textContent = content.shortcut ?? \"\";\n shortcut.hidden = !content.shortcut;\n element.hidden = false;\n if (!shown) {\n const describedBy = control.getAttribute(\"aria-describedby\");\n shown = { control, describedBy };\n // Only a tooltip that says more than the control's name describes it (guide §5.6); a shortcut\n // chip does, unless the control names its keys in aria-keyshortcuts.\n const saysMore =\n !accessibleName(control).includes(content.label) ||\n (Boolean(content.shortcut) && !control.hasAttribute(\"aria-keyshortcuts\"));\n if (saysMore) {\n control.setAttribute(\"aria-describedby\", [describedBy, id].filter(Boolean).join(\" \"));\n }\n }\n place(control);\n }\n\n function onEnter(control: HTMLElement, source: ContentSource, event: PointerEvent): void {\n if (event.pointerType === \"touch\" || pressed === control) return;\n if (shown || Date.now() < warmUntil) {\n show(control, source);\n return;\n }\n cancelPending();\n pending = { control, timer: setTimeout(() => show(control, source), TOOLTIP_DELAY_MS) };\n }\n\n function onLeave(control: HTMLElement): void {\n if (pressed === control) pressed = undefined;\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) {\n hide();\n warmUntil = Date.now() + TOOLTIP_DELAY_MS;\n }\n }\n\n function onFocus(control: HTMLElement, source: ContentSource): void {\n if (hasVisibleFocus(control)) show(control, source);\n }\n\n function onBlur(control: HTMLElement): void {\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) hide();\n }\n\n function onPress(control: HTMLElement, event: Event): void {\n if (event.type === \"pointerdown\") pressed = control;\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) hide();\n }\n\n function attach(control: HTMLElement, source: ContentSource): () => void {\n const enter = (event: PointerEvent) => onEnter(control, source, event);\n const leave = () => onLeave(control);\n const focus = () => onFocus(control, source);\n const blur = () => onBlur(control);\n const press = (event: Event) => onPress(control, event);\n control.addEventListener(\"pointerenter\", enter);\n control.addEventListener(\"pointerleave\", leave);\n control.addEventListener(\"focus\", focus);\n control.addEventListener(\"blur\", blur);\n control.addEventListener(\"pointerdown\", press);\n control.addEventListener(\"click\", press);\n const detach = () => {\n if (!detachers.delete(detach)) return;\n control.removeEventListener(\"pointerenter\", enter);\n control.removeEventListener(\"pointerleave\", leave);\n control.removeEventListener(\"focus\", focus);\n control.removeEventListener(\"blur\", blur);\n control.removeEventListener(\"pointerdown\", press);\n control.removeEventListener(\"click\", press);\n if (shown?.control === control || pending?.control === control) hide();\n if (pressed === control) pressed = undefined;\n };\n detachers.add(detach);\n return detach;\n }\n\n function delegate(\n container: HTMLElement,\n selector: string,\n content: (control: HTMLElement) => TooltipContent | null,\n ): () => void {\n let hovered: HTMLElement | undefined;\n const controlOf = (target: EventTarget | null): HTMLElement | undefined => {\n if (!target || typeof (target as Element).closest !== \"function\") return undefined;\n const match = (target as Element).closest<HTMLElement>(selector);\n return match && container.contains(match) ? match : undefined;\n };\n const sourceOf = (control: HTMLElement) => () => content(control);\n const over = (event: PointerEvent) => {\n const control = controlOf(event.target);\n if (control === hovered) return;\n if (hovered) onLeave(hovered);\n hovered = control;\n if (control) onEnter(control, sourceOf(control), event);\n };\n const out = (event: PointerEvent) => {\n if (!hovered) return;\n if (controlOf(event.relatedTarget) === hovered) return;\n onLeave(hovered);\n hovered = undefined;\n };\n const focusIn = (event: FocusEvent) => {\n const control = controlOf(event.target);\n if (control) onFocus(control, sourceOf(control));\n };\n const focusOut = (event: FocusEvent) => {\n const control = controlOf(event.target);\n if (control) onBlur(control);\n };\n const press = (event: Event) => {\n const control = controlOf(event.target);\n if (control) onPress(control, event);\n };\n container.addEventListener(\"pointerover\", over);\n container.addEventListener(\"pointerout\", out);\n container.addEventListener(\"focusin\", focusIn);\n container.addEventListener(\"focusout\", focusOut);\n container.addEventListener(\"pointerdown\", press);\n container.addEventListener(\"click\", press);\n const detach = () => {\n if (!detachers.delete(detach)) return;\n container.removeEventListener(\"pointerover\", over);\n container.removeEventListener(\"pointerout\", out);\n container.removeEventListener(\"focusin\", focusIn);\n container.removeEventListener(\"focusout\", focusOut);\n container.removeEventListener(\"pointerdown\", press);\n container.removeEventListener(\"click\", press);\n if ((shown && container.contains(shown.control)) || (pending && container.contains(pending.control))) {\n hide();\n }\n hovered = undefined;\n };\n detachers.add(detach);\n return detach;\n }\n\n return {\n element,\n attach,\n delegate,\n hide,\n destroy() {\n hide();\n for (const detach of [...detachers]) detach();\n element.remove();\n },\n };\n}\n","import {\n ariaKeyShortcuts,\n canZoomIn,\n canZoomOut,\n formatPercent,\n shortcutLabel,\n zoomReadout,\n type ChromeKey,\n type Platform,\n type ShellMessages,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport { createElement, toggleAttribute } from \"./element.js\";\nimport { iconElement, type ShellIconName } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\n\nexport interface ZoomPanelContext {\n ownerDocument: Document;\n messages: ShellMessages;\n lang: string;\n platform: Platform;\n tooltip: TooltipController;\n}\n\nexport interface ZoomPanel {\n readonly element: HTMLElement;\n setTarget(target: ZoomTarget | null): void;\n /** Runs a chrome key on the bound target; zoom out never zooms in (guide §5.8). */\n run(key: ChromeKey): void;\n destroy(): void;\n}\n\nexport function createZoomPanel(context: ZoomPanelContext): ZoomPanel {\n const { ownerDocument, messages, lang, platform, tooltip } = context;\n let target: ZoomTarget | null = null;\n let unsubscribe: (() => void) | undefined;\n let frame: number | undefined;\n const detachers: (() => void)[] = [];\n\n function button(\n zoom: \"out\" | \"actual\" | \"in\" | \"fit\",\n key: ChromeKey,\n tooltipLabel: string,\n options: { label?: string; icon?: ShellIconName; className?: string },\n ): HTMLButtonElement {\n const element = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: options.className ?? \"cd-shell-target\",\n \"data-zoom\": zoom,\n \"aria-label\": options.label,\n \"aria-keyshortcuts\": ariaKeyShortcuts(key, platform),\n });\n if (options.icon) element.append(iconElement(options.icon));\n element.addEventListener(\"click\", () => run(key));\n detachers.push(\n tooltip.attach(element, {\n label: tooltipLabel,\n shortcut: shortcutLabel(key, platform, messages.keyNames),\n }),\n );\n return element;\n }\n\n const zoomOut = button(\"out\", \"zoomOut\", messages.zoomOut, { label: messages.zoomOut, icon: \"minus\" });\n const readout = button(\"actual\", \"zoomToActual\", messages.zoomToActual(formatPercent(1, lang)), {\n className: \"cd-shell-target cd-shell-zoom-readout\",\n });\n const zoomIn = button(\"in\", \"zoomIn\", messages.zoomIn, { label: messages.zoomIn, icon: \"plus\" });\n const fit = button(\"fit\", \"fit\", messages.fit, { label: messages.fit, icon: \"maximize\" });\n const separator = createElement(ownerDocument, \"span\", {\n class: \"cd-shell-zoom-separator\",\n \"aria-hidden\": \"true\",\n });\n\n const element = createElement(\n ownerDocument,\n \"div\",\n {\n class: \"cd-shell-zoom cd-shell-island\",\n \"data-chrome\": \"zoom\",\n role: \"group\",\n \"aria-label\": messages.zoom,\n },\n zoomOut,\n readout,\n zoomIn,\n separator,\n fit,\n );\n\n function render(): void {\n frame = undefined;\n const zoom = target?.zoom() ?? 1;\n const state = zoomReadout(zoom, lang, messages);\n if (readout.textContent !== state.text) readout.textContent = state.text;\n readout.setAttribute(\"aria-label\", state.ariaLabel);\n // aria-disabled, not disabled: a button pressed up to the limit keeps the focus (guide §5.8).\n toggleAttribute(zoomOut, \"aria-disabled\", (!target || !state.canZoomOut) && \"true\");\n toggleAttribute(zoomIn, \"aria-disabled\", (!target || !state.canZoomIn) && \"true\");\n toggleAttribute(fit, \"aria-disabled\", (!target || !target.canFit()) && \"true\");\n // The readout is never disabled (guide §5.8); without a target its click does nothing.\n }\n\n function schedule(): void {\n if (frame === undefined) frame = requestAnimationFrame(render);\n }\n\n function cancelFrame(): void {\n if (frame !== undefined) cancelAnimationFrame(frame);\n frame = undefined;\n }\n\n function run(key: ChromeKey): void {\n if (!target) return;\n const zoom = target.zoom();\n switch (key) {\n case \"zoomIn\":\n if (canZoomIn(zoom)) target.stepZoom(1);\n break;\n case \"zoomOut\":\n if (canZoomOut(zoom)) target.stepZoom(-1);\n break;\n case \"zoomToActual\":\n if (zoom !== 1) target.zoomToActual();\n break;\n case \"fit\":\n if (target.canFit()) target.fit();\n break;\n }\n }\n\n render();\n\n return {\n element,\n run,\n setTarget(next) {\n unsubscribe?.();\n unsubscribe = undefined;\n cancelFrame();\n target = next;\n if (next) unsubscribe = next.onChange(schedule);\n render();\n },\n destroy() {\n unsubscribe?.();\n unsubscribe = undefined;\n cancelFrame();\n target = null;\n for (const detach of detachers) detach();\n element.remove();\n },\n };\n}\n","import {\n SHELL,\n decidePaletteRow,\n detectPlatform,\n fitInsets,\n legendStartsOpen,\n resolveMessages,\n type FitLayout,\n type Insets,\n type PaletteRow,\n type Size,\n type Theme,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport { boxRelativeTo, createElement } from \"./element.js\";\nimport { createEmptyHint } from \"./hint.js\";\nimport { createInspector } from \"./inspector.js\";\nimport { createKeyListener } from \"./keys.js\";\nimport { Ledger } from \"./ledger.js\";\nimport { createLegend } from \"./legend.js\";\nimport { createMenu } from \"./menu.js\";\nimport { createProblemsPill } from \"./problems.js\";\nimport { createStatusBox } from \"./status.js\";\nimport { createTooltip } from \"./tooltip.js\";\nimport type {\n InspectorHandle,\n LegendHandle,\n MenuCheckboxEntry,\n MenuHandle,\n PaletteReadOnlyState,\n PaletteRegistration,\n ShellHandle,\n ShellOptions,\n TooltipHandle,\n} from \"./types.js\";\nimport { createZoomPanel } from \"./zoom-panel.js\";\n\n// Page-global: every modeler bundles its own copy of the shell (and the CJS entries inline one each),\n// and two shells on one foreign page must not share element ids.\nconst MOUNT_COUNTER = Symbol.for(\"@miragon/modeler-shell.mounts\");\n\nfunction nextMountIndex(): number {\n const scope = globalThis as unknown as Record<symbol, number | undefined>;\n const index = (scope[MOUNT_COUNTER] ?? 0) + 1;\n scope[MOUNT_COUNTER] = index;\n return index;\n}\n\nconst DEFAULT_THEMES: readonly Theme[] = [\"light\"];\n\n// In a foreign page the closest [lang] is the page's language, not the tool's (guide §2).\nfunction languageOf(root: HTMLElement, host: ShellOptions[\"host\"], requested: string | undefined): string {\n if (requested) return requested;\n const declared =\n host === \"embedded\" ? root.getAttribute(\"lang\") : root.closest(\"[lang]\")?.getAttribute(\"lang\");\n return declared || \"en\";\n}\n\n/** The contrast of the host page around an embedded root: the nearest mode carrier above it. */\nfunction hostKontrast(root: HTMLElement): \"hoch\" | null {\n const carrier = root.parentElement?.closest(\"[data-cd-theme], [data-cd-kontrast]\");\n return carrier?.getAttribute(\"data-cd-kontrast\") === \"hoch\" ? \"hoch\" : null;\n}\n\n/**\n * Turns `root` into the shell (`.cd-shell`, container `cd-shell`) and renders the chrome in the\n * DOM order of guide §5.14: menu trigger, canvas slot, status box, empty-file hint, inspector,\n * problems pill, legend, zoom panel, then the layer for dropdown and tooltip. Installs the one\n * `keydown` listener (see `ShellOptions.keyScope`) and the root `ResizeObserver`.\n *\n * `root` must get its size from outside (`container-type: size`): `height: 100%` in an own\n * document, an explicitly sized element in a foreign page. When rendering throws (a modeler's\n * `legend.render`), everything added so far is removed again before the error propagates.\n */\nexport function mountShell(root: HTMLElement, options: ShellOptions): ShellHandle {\n const themes = options.themes ?? DEFAULT_THEMES;\n if (themes.length === 0) throw new Error(\"@miragon/modeler-shell: mountShell needs at least one theme\");\n const ledger = new Ledger();\n try {\n return renderShell(root, options, themes, ledger);\n } catch (error) {\n ledger.close();\n throw error;\n }\n}\n\nfunction renderShell(\n root: HTMLElement,\n options: ShellOptions,\n themes: readonly Theme[],\n ledger: Ledger,\n): ShellHandle {\n const ownerDocument = root.ownerDocument;\n const { host } = options;\n const index = nextMountIndex();\n const messages = resolveMessages(options.messages);\n const platform = options.platform ?? detectPlatform(globalThis.navigator);\n const lang = languageOf(root, host, options.lang);\n const keyScope = options.keyScope ?? (host === \"embedded\" ? \"root\" : \"document\");\n\n ledger.addClass(root, \"cd-shell\");\n ledger.attribute(root, \"data-cd-shell-host\", host);\n ledger.attribute(root, \"data-palette\", \"top\");\n if (host === \"embedded\") {\n ledger.attribute(root, \"lang\", lang);\n carryOwnMode(root, themes[0] ?? \"light\", ledger);\n } else {\n ledger.addClass(ownerDocument.documentElement, \"cd-shell-document\");\n }\n\n const setState = (name: string, value: string | null): void => {\n if (!ledger.isClosed) ledger.attribute(root, name, value);\n };\n\n const layer = createElement(ownerDocument, \"div\", { class: \"cd-shell-layer\" });\n ledger.defer(() => layer.remove());\n const tooltip = createTooltip({ root, layer, id: `cd-shell-tooltip-${index}` });\n ledger.defer(() => tooltip.destroy());\n\n /** The lock of `setReadOnly(true)`; `readOnlyShown` its marks, which may follow after a delay. */\n let readOnly = false;\n let readOnlyShown = false;\n let readOnlyTimer: ReturnType<typeof setTimeout> | undefined;\n ledger.defer(() => clearTimeout(readOnlyTimer));\n\n const legend = options.legend\n ? createLegend({\n ownerDocument,\n messages,\n tooltip,\n titleId: `cd-shell-legend-title-${index}`,\n options: options.legend,\n onChange(open) {\n setState(\"data-legend\", open ? \"open\" : null);\n placeHint();\n menu.refresh();\n },\n focusAfterClose: () => menu.trigger.focus(),\n })\n : undefined;\n if (legend) ledger.defer(() => legend.destroy());\n\n const legendEntry: MenuCheckboxEntry | undefined =\n legend && options.legend?.menuEntry !== false\n ? {\n kind: \"checkbox\",\n id: \"legend\",\n label: messages.legend,\n checked: () => legend.isOpen(),\n onToggle: (checked) => legend.setOpen(checked),\n keepEnabledWhenReadOnly: true,\n }\n : undefined;\n const shellModelEntries: readonly MenuCheckboxEntry[] = legendEntry ? [legendEntry] : [];\n\n const menu = createMenu({\n root,\n layer,\n id: `cd-shell-menu-${index}`,\n messages,\n tooltip,\n groups: options.menu ?? {},\n shellModelEntries: () => shellModelEntries,\n isReadOnly: () => readOnly,\n });\n ledger.defer(() => menu.destroy());\n ledger.defer(tooltip.attach(menu.trigger, () => (menu.isOpen() ? null : { label: messages.menu })));\n\n const canvas = options.canvas ?? createElement(ownerDocument, \"div\");\n ledger.addClass(canvas, \"cd-shell-canvas\");\n if (!options.canvas) ledger.defer(() => canvas.remove());\n\n /** Where the focus goes when the island holding it hides: the canvas, else the menu trigger. */\n function moveFocusOutOf(island: HTMLElement): void {\n if (!island.contains(ownerDocument.activeElement)) return;\n const canvasTarget = canvas.querySelector<HTMLElement | SVGElement>(\"svg[tabindex]\");\n canvasTarget?.focus({ preventScroll: true });\n if (canvasTarget && ownerDocument.activeElement === canvasTarget) return;\n if (!menu.trigger.hidden) menu.trigger.focus({ preventScroll: true });\n }\n\n const status = createStatusBox(ownerDocument);\n ledger.defer(() => status.destroy());\n const hint = options.emptyHint ? createEmptyHint(ownerDocument, messages, options.emptyHint) : undefined;\n if (hint) ledger.defer(() => hint.destroy());\n const inspector = options.inspector\n ? createInspector(ownerDocument, options.inspector, (open) => {\n setState(\"data-inspector\", open ? \"open\" : null);\n placeHint();\n })\n : undefined;\n if (inspector) ledger.defer(() => inspector.destroy());\n const pill = options.problems\n ? createProblemsPill({\n ownerDocument,\n messages,\n lang,\n tooltip,\n showTooltip: host === \"ide\",\n options: options.problems,\n })\n : undefined;\n if (pill) ledger.defer(() => pill.destroy());\n const zoomPanel = createZoomPanel({ ownerDocument, messages, lang, platform, tooltip });\n ledger.defer(() => zoomPanel.destroy());\n\n root.prepend(menu.trigger, canvas);\n root.append(\n ...[\n status.element,\n hint?.element,\n inspector?.element,\n pill?.element,\n legend?.element,\n zoomPanel.element,\n ].filter((element): element is HTMLElement => element !== undefined),\n layer,\n );\n\n let palette: { registration: PaletteRegistration; detachTooltip: () => void } | undefined;\n let paletteRow: PaletteRow = \"top\";\n\n function containerSize(): Size {\n return { width: root.clientWidth, height: root.clientHeight };\n }\n\n function menuRight(): number {\n const box = boxRelativeTo(menu.trigger, root);\n return box.width > 0 ? box.x + box.width : SHELL.edge + SHELL.row;\n }\n\n /** The palette's intrinsic border-box width: it does not shrink once the second row clips it. */\n function paletteWidth(): number {\n const element = palette?.registration.element;\n return element ? element.offsetWidth - element.clientWidth + element.scrollWidth : 0;\n }\n\n function currentFitInsets(): Insets {\n const container = containerSize();\n const layout: FitLayout = {\n container,\n host,\n paletteRow,\n problemsVisible: pill?.isShown() ?? false,\n };\n if (legend?.isOpen()) layout.legendWidth = legend.element.getBoundingClientRect().width;\n if (inspector?.isOpen()) {\n layout.inspector =\n container.width > SHELL.narrow ? {} : { sheetTop: boxRelativeTo(inspector.element, root).y };\n }\n return fitInsets(layout);\n }\n\n function placeHint(): void {\n if (hint?.isShown()) hint.place(currentFitInsets());\n }\n\n function updateLayout(): void {\n if (ledger.isClosed) return;\n const size = containerSize();\n // A hidden tab reports 0 × 0; it neither measures nor decides anything (guide §5.9).\n if (size.width === 0 || size.height === 0) return;\n paletteRow = decidePaletteRow({\n containerWidth: size.width,\n paletteWidth: paletteWidth(),\n menuRight: menuRight(),\n });\n setState(\"data-palette\", paletteRow);\n if (legend && !legend.isStarted()) legend.start(options.legend?.open ?? legendStartsOpen(size.height));\n placeHint();\n }\n\n const ResizeObserverClass = globalThis.ResizeObserver;\n const resizeObserver = ResizeObserverClass ? new ResizeObserverClass(() => updateLayout()) : undefined;\n resizeObserver?.observe(root);\n ledger.defer(() => resizeObserver?.disconnect());\n\n if (legend && options.legend?.open !== undefined) legend.start(options.legend.open);\n updateLayout();\n\n const keyTarget: HTMLElement | Document = keyScope === \"root\" ? root : ownerDocument;\n const onKeydown = createKeyListener({\n host,\n dialogScope: keyTarget,\n menuOpen: () => menu.isOpen(),\n closeMenu() {\n const active = ownerDocument.activeElement;\n menu.close({ restoreFocus: active === menu.trigger || menu.dropdown.contains(active) });\n },\n hideTooltip: () => tooltip.hide(),\n run: (key) => zoomPanel.run(key),\n });\n keyTarget.addEventListener(\"keydown\", onKeydown as EventListener);\n ledger.defer(() => keyTarget.removeEventListener(\"keydown\", onKeydown as EventListener));\n\n function readOnlyState(): PaletteReadOnlyState {\n return { locked: readOnly, shown: readOnlyShown };\n }\n\n function applyReadOnly(): void {\n setState(\"data-readonly\", readOnlyShown ? \"\" : null);\n palette?.registration.setReadOnly(readOnlyState());\n menu.refresh();\n }\n\n function showReadOnly(): void {\n readOnlyTimer = undefined;\n if (ledger.isClosed || !readOnly) return;\n readOnlyShown = true;\n applyReadOnly();\n }\n\n function unregisterPalette(): void {\n if (!palette) return;\n palette.detachTooltip();\n resizeObserver?.unobserve(palette.registration.element);\n palette = undefined;\n }\n ledger.defer(unregisterPalette);\n\n const menuHandle: MenuHandle = {\n trigger: menu.trigger,\n dropdown: menu.dropdown,\n isOpen: () => menu.isOpen(),\n open: (focus) => menu.open(focus),\n close: (closeOptions) => menu.close(closeOptions),\n refresh: () => menu.refresh(),\n setGroups: (groups) => {\n if (!ledger.isClosed) menu.setGroups(groups);\n },\n };\n\n const tooltipHandle: TooltipHandle = {\n attach: (control, content) => (ledger.isClosed ? () => {} : tooltip.attach(control, content)),\n hide: () => tooltip.hide(),\n };\n\n const legendHandle: LegendHandle | undefined = legend && {\n element: legend.element,\n body: legend.body,\n isOpen: () => legend.isOpen(),\n setOpen: (open) => {\n if (!ledger.isClosed) legend.setOpen(open);\n },\n toggle: () => {\n if (!ledger.isClosed) legend.toggle();\n },\n };\n\n const inspectorHandle: InspectorHandle | undefined = inspector && {\n element: inspector.element,\n isOpen: () => inspector.isOpen(),\n open: () => {\n if (!ledger.isClosed) inspector.open();\n },\n close: () => {\n if (ledger.isClosed) return;\n if (inspector.isOpen()) moveFocusOutOf(inspector.element);\n inspector.close();\n },\n };\n\n return {\n root,\n canvas,\n host,\n lang,\n platform,\n messages,\n menu: menuHandle,\n tooltip: tooltipHandle,\n legend: legendHandle,\n inspector: inspectorHandle,\n setZoomTarget(target: ZoomTarget | null) {\n if (!ledger.isClosed) zoomPanel.setTarget(target);\n },\n fitInsets: currentFitInsets,\n registerPalette(registration) {\n if (ledger.isClosed) return () => {};\n unregisterPalette();\n palette = {\n registration,\n detachTooltip: tooltip.delegate(registration.element, \".entry\", (entry) =>\n registration.entryTooltip(entry),\n ),\n };\n resizeObserver?.observe(registration.element);\n registration.setReadOnly(readOnlyState());\n updateLayout();\n const registered = palette;\n return () => {\n if (palette !== registered) return;\n unregisterPalette();\n updateLayout();\n };\n },\n setProblems(summary) {\n if (ledger.isClosed || !pill) return;\n pill.set(summary);\n setState(\"data-problems\", pill.isShown() ? \"shown\" : null);\n placeHint();\n },\n setStatus(next, statusOptions) {\n if (!ledger.isClosed) status.set(next, statusOptions?.delayMs ?? 0);\n },\n setEmptyHint(visible) {\n if (ledger.isClosed || !hint) return;\n if (!visible && hint.isShown()) moveFocusOutOf(hint.element);\n hint.setShown(visible);\n placeHint();\n },\n setReadOnly(next, readOnlyOptions) {\n if (ledger.isClosed) return;\n if (!next) {\n clearTimeout(readOnlyTimer);\n readOnlyTimer = undefined;\n readOnly = false;\n readOnlyShown = false;\n } else {\n readOnly = true;\n const delayMs = readOnlyOptions?.delayMs ?? 0;\n // Repeated invalid imports while typing keep the first timer, like the status box.\n if (!readOnlyShown && readOnlyTimer === undefined) {\n if (delayMs > 0) readOnlyTimer = setTimeout(showReadOnly, delayMs);\n else readOnlyShown = true;\n }\n }\n applyReadOnly();\n },\n isReadOnly: () => readOnly,\n destroy() {\n ledger.close();\n },\n };\n}\n\n/**\n * An embedded root carries its own mode (guide §13.3): the token CSS resolves the roles on the\n * nearest `[data-cd-theme]`, so without it a light-only modeler would inherit a dark host page and\n * be half-dark against its light-drawn diagram. The root's own `data-cd-theme` would also drop the\n * host's high contrast, so `data-cd-kontrast` is mirrored from the host for as long as it lives.\n */\nfunction carryOwnMode(root: HTMLElement, theme: Theme, ledger: Ledger): void {\n ledger.attribute(root, \"data-cd-theme\", theme);\n const mirror = (): void => {\n if (ledger.isClosed) return;\n const kontrast = hostKontrast(root);\n if (root.getAttribute(\"data-cd-kontrast\") !== kontrast)\n ledger.attribute(root, \"data-cd-kontrast\", kontrast);\n };\n mirror();\n const MutationObserverClass = globalThis.MutationObserver;\n if (!MutationObserverClass) return;\n const observer = new MutationObserverClass(mirror);\n observer.observe(root.ownerDocument.documentElement, {\n attributes: true,\n attributeFilter: [\"data-cd-theme\", \"data-cd-kontrast\"],\n subtree: true,\n });\n ledger.defer(() => observer.disconnect());\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC0CO,IAAM,iBAA0C;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC9CO,IAAM,eAAe;AAAA,EAC1B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AACd;AAOO,IAAM,QAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AACd;AAIA,IAAM,wBAAwB;AAMvB,SAAS,qBAAqB,YAA0D;AAC7F,QAAM,QAAQ,CAAC;AACf,aAAW,QAAQ,OAAO,KAAK,YAAY,GAAsB;AAC/D,UAAM,QAAQ,aAAa,IAAI;AAC/B,UAAM,MAAe,OAAO,OAAO,YAAY,KAAK,IAAI,WAAW,KAAK,IAAI;AAC5E,QAAI,QAAQ,QAAW;AACrB,YAAM,IAAI,MAAM,2CAA2C,KAAK,aAAa;AAAA,IAC/E;AACA,QAAI,OAAO,QAAQ,YAAY,CAAC,sBAAsB,KAAK,GAAG,GAAG;AAC/D,YAAM,IAAI;AAAA,QACR,2CAA2C,KAAK,qBAAqB,KAAK,UAAU,GAAG,CAAC;AAAA,MAC1F;AAAA,IACF;AACA,UAAM,IAAI,IAAI,OAAO,WAAW,GAAG;AAAA,EACrC;AACA,SAAO;AACT;;;AChFO,IAAM,eAAe;AAGrB,IAAM,mBAAmB;AAUzB,SAAS,WACd,QACA,WACA,QACA,UAAkB,cACS;AAC3B,MAAI,EAAE,UAAU,QAAQ,KAAK,UAAU,SAAS,GAAI,QAAO;AAC3D,QAAM,WAAW,OAAO,QAAQ;AAChC,QAAM,YAAY,OAAO,SAAS;AAClC,MAAI,CAAC,YAAY,CAAC,UAAW,QAAO;AAEpC,QAAM,aAAa,WAAW,UAAU,OAAO,OAAO,MAAM,OAAO,KAAK;AACxE,QAAM,WAAW,WAAW,UAAU,QAAQ,OAAO,KAAK,OAAO,MAAM;AACvE,QAAM,eAAe,WAAW,OAAO,QAAQ;AAC/C,QAAM,gBAAgB,YAAY,OAAO,SAAS;AAClD,QAAM,QAAQ,KAAK;AAAA,IACjB;AAAA,IACA,WAAW,WAAW,SAAS,eAAe;AAAA,IAC9C,YAAY,SAAS,SAAS,gBAAgB;AAAA,EAChD;AACA,QAAM,MAAqB;AAAA,IACzB,GAAG,OAAO,IAAI,eAAe,KAAK,WAAW,QAAQ,WAAW,SAAS,KAAK;AAAA,IAC9E,GAAG,OAAO,IAAI,gBAAgB,KAAK,SAAS,QAAQ,SAAS,SAAS,KAAK;AAAA,IAC3E,OAAO,UAAU,QAAQ;AAAA,IACzB,QAAQ,UAAU,SAAS;AAAA,IAC3B;AAAA,EACF;AACA,SAAO,OAAO,OAAO,GAAG,EAAE,MAAM,OAAO,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACxE;AAEA,SAAS,WAAW,OAAe,QAAgB,OAAkD;AACnG,QAAM,SAAS,QAAQ,SAAS;AAChC,SAAO,SAAS,IAAI,EAAE,OAAO,QAAQ,OAAO,IAAI,EAAE,OAAO,GAAG,QAAQ,MAAM;AAC5E;AAQO,SAAS,eAAe,WAAiB,QAAmC;AACjF,MAAI,EAAE,UAAU,QAAQ,KAAK,UAAU,SAAS,GAAI,QAAO;AAC3D,QAAM,aAAa,WAAW,UAAU,OAAO,OAAO,MAAM,OAAO,KAAK;AACxE,QAAM,WAAW,WAAW,UAAU,QAAQ,OAAO,KAAK,OAAO,MAAM;AACvE,SAAO;AAAA,IACL,GAAG,WAAW,QAAQ,WAAW,SAAS;AAAA,IAC1C,GAAG,SAAS,QAAQ,SAAS,SAAS;AAAA,EACxC;AACF;AAuBO,SAAS,UAAU,QAA2B;AACnD,QAAM,EAAE,WAAW,MAAM,YAAY,iBAAiB,aAAa,UAAU,IAAI;AACjF,QAAM,SAAiB;AAAA,IACrB,KAAK,eAAe,eAAe,MAAM,uBAAuB,MAAM;AAAA,IACtE,OAAO,MAAM;AAAA,IACb,QAAQ,SAAS,SAAS,kBAAkB,MAAM,oBAAoB,MAAM;AAAA,IAC5E,MAAM,MAAM;AAAA,EACd;AAEA,QAAM,kBAAkB,cAAc,UAAa,UAAU,SAAS,MAAM;AAC5E,MAAI,cAAc,UAAa,CAAC,iBAAiB;AAC/C,WAAO,QAAQ,MAAM,OAAO,MAAM,iBAAiB,MAAM;AAAA,EAC3D;AACA,MAAI,iBAAiB;AAEnB,WAAO,SACL,UAAU,aAAa,SACnB,MAAM,iBACN,UAAU,SAAS,UAAU,WAAW,MAAM;AAAA,EACtD,WAAW,gBAAgB,UAAa,cAAc,KAAK,UAAU,QAAQ,MAAM,YAAY;AAC7F,WAAO,OAAO,MAAM,OAAO,cAAc,MAAM;AAAA,EACjD;AACA,SAAO;AACT;AAGO,IAAM,iBAAiB;AAOvB,SAAS,SACd,GACA,GACA,YAAoB,gBACX;AACT,QAAM,QAAQ,CAAC,OAAe,WAC5B,KAAK,IAAI,QAAQ,MAAM,KAAK,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,GAAG,KAAK,IAAI,MAAM,CAAC;AACvF,SACE,MAAM,EAAE,OAAO,EAAE,KAAK,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK;AAExG;AAMO,SAAS,mBAAmB,MAAqB,IAAmB,UAAiC;AAC1G,MAAI,EAAE,WAAW,GAAI,QAAO,EAAE,GAAG,KAAK;AACtC,MAAI,YAAY,EAAG,QAAO,EAAE,GAAG,GAAG;AAClC,QAAM,SAAS,CAAC,OAAe,QAAwB,SAAS,MAAM,SAAS;AAC/E,QAAM,QACJ,KAAK,QAAQ,KAAK,GAAG,QAAQ,IACzB,KAAK,IAAI,OAAO,KAAK,IAAI,KAAK,KAAK,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,CAAC,IACzD,OAAO,KAAK,OAAO,GAAG,KAAK;AACjC,QAAM,UAAU,OAAO,KAAK,IAAI,KAAK,QAAQ,GAAG,GAAG,IAAI,GAAG,QAAQ,CAAC;AACnE,QAAM,UAAU,OAAO,KAAK,IAAI,KAAK,SAAS,GAAG,GAAG,IAAI,GAAG,SAAS,CAAC;AACrE,QAAM,QAAQ,OAAO,KAAK,QAAQ,KAAK,OAAO,GAAG,QAAQ,GAAG,KAAK,IAAI;AACrE,QAAM,SAAS,OAAO,KAAK,SAAS,KAAK,OAAO,GAAG,SAAS,GAAG,KAAK,IAAI;AACxE,SAAO,EAAE,GAAG,UAAU,QAAQ,GAAG,GAAG,UAAU,SAAS,GAAG,OAAO,QAAQ,MAAM;AACjF;AAGO,SAAS,aAAa,UAA0B;AACrD,SAAO,gBAAgB,QAAQ;AACjC;AAEA,IAAM,kBAAkB,YAAY,KAAK,GAAG,KAAK,CAAC;AAGlD,SAAS,YAAY,IAAY,IAAY,IAAY,IAA0C;AACjG,QAAM,aAAa,CAAC,OAAe,WAAmB;AACpD,UAAM,IAAI,IAAI;AACd,UAAM,IAAI,KAAK,SAAS,SAAS;AACjC,UAAM,IAAI,IAAI,IAAI;AAClB,WAAO;AAAA,MACL,IAAI,CAAC,QAAwB,IAAI,IAAI,KAAK,IAAI,KAAK;AAAA,MACnD,OAAO,CAAC,OAAuB,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI;AAAA,IAC1D;AAAA,EACF;AACA,QAAM,SAAS,WAAW,IAAI,EAAE;AAChC,QAAM,SAAS,WAAW,IAAI,EAAE;AAChC,QAAM,YAAY;AAElB,QAAM,eAAe,CAAC,MAAsB;AAC1C,QAAI,IAAI;AACR,aAAS,YAAY,GAAG,YAAY,GAAG,aAAa;AAClD,YAAM,QAAQ,OAAO,GAAG,CAAC,IAAI;AAC7B,UAAI,KAAK,IAAI,KAAK,IAAI,UAAW,QAAO;AACxC,YAAM,QAAQ,OAAO,MAAM,CAAC;AAC5B,UAAI,KAAK,IAAI,KAAK,IAAI,KAAM;AAC5B,WAAK,QAAQ;AACb,UAAI,IAAI,KAAK,IAAI,EAAG;AAAA,IACtB;AAEA,QAAI,MAAM;AACV,QAAI,OAAO;AACX,QAAI;AACJ,aAAS,YAAY,GAAG,YAAY,IAAI,aAAa;AACnD,YAAM,QAAQ,OAAO,GAAG,CAAC;AACzB,UAAI,KAAK,IAAI,QAAQ,CAAC,IAAI,UAAW;AACrC,UAAI,QAAQ,EAAG,OAAM;AAAA,UAChB,QAAO;AACZ,WAAK,MAAM,QAAQ;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,aAAa;AACnB,QAAI,EAAE,WAAW,GAAI,QAAO;AAC5B,QAAI,YAAY,EAAG,QAAO;AAC1B,WAAO,OAAO,GAAG,aAAa,QAAQ,CAAC;AAAA,EACzC;AACF;;;ACzMO,IAAM,WAAW;AACjB,IAAM,WAAW;AAGjB,SAAS,WAAW,MAAuB;AAChD,SAAO,OAAO,WAAW;AAC3B;AAGO,SAAS,UAAU,MAAuB;AAC/C,SAAO,OAAO,WAAW;AAC3B;AAMO,SAAS,cAAc,MAAc,MAAsB;AAChE,SAAO,aAAa,MAAM,SAAS,EAAE,OAAO,IAAI;AAClD;AAGO,SAAS,aAAa,OAAe,MAAsB;AAChE,SAAO,aAAa,MAAM,SAAS,EAAE,OAAO,KAAK;AACnD;AAEA,IAAM,gBAAgB;AACtB,IAAM,UAAU,oBAAI,IAA+B;AAKnD,SAAS,aAAa,MAAc,OAAiD;AACnF,QAAM,MAAM,GAAG,KAAK,IAAI,IAAI;AAC5B,MAAI,SAAS,QAAQ,IAAI,GAAG;AAC5B,MAAI,CAAC,QAAQ;AACX,UAAM,UACJ,UAAU,YAAY,EAAE,OAAO,uBAAuB,EAAE,IAAI,EAAE,MAAM;AACtE,QAAI;AACF,eAAS,IAAI,KAAK,aAAa,MAAM,OAAO;AAAA,IAC9C,QAAQ;AACN,eAAS,IAAI,KAAK,aAAa,eAAe,OAAO;AAAA,IACvD;AACA,YAAQ,IAAI,KAAK,MAAM;AAAA,EACzB;AACA,SAAO;AACT;AAYO,SAAS,YACd,MACA,MACA,UACa;AACb,QAAM,OAAO,cAAc,MAAM,IAAI;AACrC,SAAO;AAAA,IACL;AAAA,IACA,WAAW,SAAS,gBAAgB,cAAc,GAAG,IAAI,GAAG,IAAI;AAAA,IAChE,YAAY,WAAW,IAAI;AAAA,IAC3B,WAAW,UAAU,IAAI;AAAA,EAC3B;AACF;;;AChDO,SAAS,eAAe,OAAuC;AACpE,MAAI,MAAM,OAAQ,QAAO;AACzB,MAAI,UAAU,KAAK,GAAG;AACpB,QAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,OAAO,MAAM,SAAS,YAAa,QAAO;AACjF,QAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,OAAO,MAAM,SAAS,iBAAkB,QAAO;AACtF,QAAI,MAAM,QAAQ,OAAO,MAAM,SAAS,UAAW,QAAO;AAC1D,WAAO;AAAA,EACT;AACA,SAAO,MAAM,YAAY,MAAM,SAAS,WAAW,QAAQ;AAC7D;AAEA,SAAS,UAAU,OAAyB;AAC1C,SAAO,MAAM,WAAW,MAAM;AAChC;AAMO,SAAS,cAAc,OAAyB;AACrD,MAAI,MAAM,UAAU,CAAC,UAAU,KAAK,EAAG,QAAO;AAC9C,QAAM,SAAS,eAAe,KAAK;AACnC,SAAO,WAAW,OAAQ,WAAW,OAAO,CAAC,MAAM;AACrD;AAIA,SAAS,eAAe,OAAoC;AAC1D,MAAI,MAAM,IAAI,WAAW,KAAK,MAAM,IAAI,WAAW,CAAC,IAAI,IAAM,QAAO,MAAM,IAAI,YAAY;AAC3F,MAAI,MAAM,SAAS,OAAQ,QAAO;AAClC,MAAI,MAAM,SAAS,OAAQ,QAAO;AAClC,SAAO;AACT;AAGO,IAAM,sBACX;AAqCK,SAAS,UAAU,OAAgB,SAAkC;AAC1E,QAAM,OAAO,QAAQ,SAAS;AAC9B,QAAM,YAAY,MAAM,gBAAgB;AAExC,MAAI,MAAM,QAAQ,YAAY,CAAC,MAAM,WAAW,CAAC,MAAM,WAAW,CAAC,MAAM,UAAU,CAAC,MAAM,UAAU;AAClG,QAAI,QAAQ,YAAY,CAAC,WAAW;AAClC,aAAO,EAAE,QAAQ,aAAa,gBAAgB,MAAM,iBAAiB,KAAK;AAAA,IAC5E;AACA,QAAI,QAAQ,YAAY,QAAQ,WAAY,QAAO,EAAE,gBAAgB,OAAO,iBAAiB,KAAK;AAAA,EACpG;AAEA,QAAM,YAAY,eAAe,KAAK;AACtC,MAAI,cAAc,QAAW;AAC3B,UAAM,UAAU,aAAa,QAAQ,eAAe,QAAQ;AAC5D,QAAI,CAAC,QAAS,QAAO,EAAE,QAAQ,WAAW,gBAAgB,MAAM,iBAAiB,KAAK;AAGtF,WAAO,EAAE,gBAAgB,OAAO,iBAAiB,cAAc,QAAQ,QAAQ,KAAK;AAAA,EACtF;AAEA,MAAI,QAAQ,eAAe,cAAc,KAAK,EAAG,QAAO,EAAE,gBAAgB,OAAO,iBAAiB,KAAK;AACvG,MAAI,QAAQ,iBAAkB,QAAO,EAAE,gBAAgB,OAAO,iBAAiB,KAAK;AACpF,SAAO,EAAE,gBAAgB,OAAO,iBAAiB,MAAM;AACzD;AAeO,SAAS,eAAe,WAAiD;AAE9E,QAAM,WAAW,WAAW,eAAe,YAAY,WAAW,YAAY;AAC9E,SAAO,OAAO,KAAK,QAAQ,IAAI,QAAQ;AACzC;AAMO,SAAS,cACd,KACA,UACA,UACQ;AACR,MAAI,aAAa,MAAO,QAAO,oBAAoB,GAAG;AACtD,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,GAAG,SAAS,IAAI,IAAI,SAAS,IAAI;AAAA,IAC1C,KAAK;AACH,aAAO,GAAG,SAAS,IAAI,IAAI,SAAS,KAAK;AAAA,IAC3C,KAAK;AACH,aAAO,GAAG,SAAS,IAAI;AAAA,IACzB,KAAK;AACH,aAAO,GAAG,SAAS,KAAK;AAAA,EAC5B;AACF;AAEA,IAAM,sBAA2D;AAAA,EAC/D,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,cAAc;AAAA,EACd,KAAK;AACP;AAMO,SAAS,iBAAiB,KAAgB,UAA4B;AAC3E,QAAM,UAAU,aAAa,QAAQ,SAAS;AAC9C,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,GAAG,OAAO,MAAM,OAAO;AAAA,IAChC,KAAK;AACH,aAAO,GAAG,OAAO;AAAA,IACnB,KAAK;AACH,aAAO,GAAG,OAAO;AAAA,IACnB,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEA,IAAM,uBAAyD;AAAA,EAC7D,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AACP;AAEA,IAAM,iBAAmD;AAAA,EACvD,KAAK;AAAA,EACL,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,KAAK;AACP;AAEA,IAAM,aAA+C;AAAA,EACnD,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,UAAK;AAAA,EACL,MAAM;AACR;AAEA,SAAS,YAAY,KAAiC;AACpD,QAAM,QAAQ,WAAW,IAAI,YAAY,CAAC;AAC1C,MAAI,MAAO,QAAO;AAClB,MAAI,cAAc,KAAK,GAAG,EAAG,QAAO,IAAI,YAAY;AACpD,MAAI,IAAI,WAAW,KAAK,qBAAqB,GAAG,EAAG,QAAO;AAC1D,MAAI,QAAQ,IAAK,QAAO;AACxB,MAAI,QAAQ,IAAK,QAAO;AACxB,SAAO,IAAI,YAAY;AACzB;AAQO,SAAS,0BAA0B,OAAmC;AAC3E,MAAI,OAAO,MAAM,KAAK;AACtB,QAAM,YAAsB,CAAC;AAC7B,WAAS,SAAS,qBAAqB,KAAK,OAAO,CAAC,CAAC,GAAG,UAAU,KAAK,SAAS,KAAI;AAClF,cAAU,KAAK,MAAM;AACrB,WAAO,KAAK,MAAM,CAAC,EAAE,KAAK;AAC1B,aAAS,qBAAqB,KAAK,OAAO,CAAC,CAAC;AAAA,EAC9C;AACA,MAAI,CAAC,QAAQ,KAAK,KAAK,KAAK,QAAQ,aAAa,GAAG,CAAC,EAAG,QAAO;AAC/D,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AACvD,MAAI,MAAM,MAAM,IAAI,KAAK;AACzB,MAAI,QAAQ,MAAM,MAAM,GAAG,EAAE,MAAM,IAAI;AACrC,UAAM,IAAI;AACV,UAAM;AAAA,EACR;AACA,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,eAAe,KAAK,YAAY,CAAC;AAClD,QAAI,CAAC,SAAU,QAAO;AACtB,cAAU,KAAK,QAAQ;AAAA,EACzB;AACA,QAAM,OAAO,YAAY,GAAG;AAC5B,SAAO,OAAO,CAAC,GAAG,IAAI,IAAI,SAAS,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI;AAC1D;;;AClQO,SAAS,kBAAkB,WAAuB,QAAsC;AAC7F,QAAM,CAAC,QAAQ,IAAI;AACnB,MAAI,aAAa,QAAW;AAC1B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAAQ,OAAO,SAAS,UAAU,KAAK,IAAI,UAAU,QAAQ;AACnE,SAAO,aAAa,OAAO,UAAU,QAAQ;AAC/C;AAGA,SAAS,aAAa,OAAc,UAA+B;AACjE,SAAO,aAAa,SAAS,EAAE,OAAO,SAAS,IAAI,EAAE,MAAM;AAC7D;AAOO,SAAS,6BAA6B,MAA0B;AACrE,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,EAAE,OAAO,OAAO;AAAA,IACzB,KAAK;AACH,aAAO,EAAE,OAAO,QAAQ,UAAU,OAAO;AAAA,IAC3C,KAAK;AACH,aAAO,EAAE,OAAO,SAAS,UAAU,OAAO;AAAA,IAC5C;AACE,aAAO,EAAE,OAAO,QAAQ;AAAA,EAC5B;AACF;AASO,SAAS,oBAAoB,MAAc,SAAqD;AACrG,QAAM,WAAW,6BAA6B,IAAI;AAClD,QAAM,QAAQ,YAAY,WAAW,YAAY,SAAS,UAAU,SAAS;AAC7E,SAAO,aAAa,OAAO,SAAS,QAAQ;AAC9C;AAOO,SAAS,0BAA0B,SAAmD;AAC3F,QAAM,UAAU,IAAI,IAAI,OAAO;AAC/B,MAAI,QAAQ,IAAI,4BAA4B,EAAG,QAAO,EAAE,OAAO,SAAS,UAAU,OAAO;AACzF,MAAI,QAAQ,IAAI,sBAAsB,EAAG,QAAO,EAAE,OAAO,QAAQ,UAAU,OAAO;AAClF,MAAI,QAAQ,IAAI,aAAa,EAAG,QAAO,EAAE,OAAO,OAAO;AACvD,MAAI,QAAQ,IAAI,cAAc,EAAG,QAAO,EAAE,OAAO,QAAQ;AACzD,SAAO;AACT;AAOO,SAAS,6BAA6B,SAAoC;AAC/E,SAAO,IAAI,IAAI,OAAO,EAAE,IAAI,sBAAsB;AACpD;AAOO,IAAM,uBAAuB;AAQ7B,SAAS,qBAAqB,YAA8C;AACjF,SAAO,WAAW,aAAa,SAC3B,EAAE,iBAAiB,WAAW,OAAO,oBAAoB,OAAO,IAChE,EAAE,iBAAiB,WAAW,MAAM;AAC1C;;;ACzDO,IAAM,kBAAiC;AAAA,EAC5C,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,cAAc,CAAC,YAAY,WAAW,OAAO;AAAA,EAC7C,iBAAiB,CAAC,SAAS,QAAQ,WAAW,OAAO,SAAS,GAAG;AAAA,EACjE,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,UAAU,CAAC,OAAO,mBAAmB,GAAG,cAAc,IAAI,UAAU,IAAI,YAAY,UAAU;AAAA,EAC9F,eAAe,CAAC,OAAO,QAAQ,gBAAgB,oBAC7C,GAAG,cAAc,IAAI,UAAU,IAAI,YAAY,UAAU,KACvD,WAAW,IAAI,cAAc,GAAG,eAAe,IAAI,WAAW,IAAI,UAAU,QAAQ,EACtF;AAAA,EACF,cAAc;AAAA,EACd,WAAW;AAAA,EACX,eAAe;AAAA,EACf,aAAa,CAAC,YACZ,2BAA2B,OAAO;AAAA,EACpC,UAAU,EAAE,MAAM,QAAQ,OAAO,SAAS,MAAM,QAAQ,OAAO,QAAQ;AACzE;AAGO,SAAS,gBAAgB,WAA8D;AAC5F,QAAM,EAAE,UAAU,GAAG,MAAM,IAAI,aAAa,CAAC;AAC7C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,eAAe,KAAK;AAAA,IACvB,UAAU,EAAE,GAAG,gBAAgB,UAAU,GAAG,eAAe,YAAY,CAAC,CAAC,EAAE;AAAA,EAC7E;AACF;AAIA,SAAS,eAAiC,SAA+D;AACvG,SAAO,OAAO,YAAY,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAG9F;;;ACnFO,IAAM,oBAAoB;AAG1B,IAAM,mBAAmB;AAGzB,IAAM,0BAA0B;AAmBhC,SAAS,iBAAiB,OAAoC;AACnE,QAAM,EAAE,gBAAgB,cAAc,WAAW,YAAY,IAAI;AACjE,MAAI,kBAAkB,MAAM,OAAQ,QAAO;AAC3C,QAAM,eAAe,iBAAiB,gBAAgB;AACtD,QAAM,gBAAgB,iBAAiB,gBAAgB;AACvD,MAAI,cAAc,YAAY,kBAAmB,QAAO;AACxD,MAAI,gBAAgB,UAAa,eAAe,cAAc,kBAAmB,QAAO;AACxF,SAAO;AACT;AAGO,SAAS,iBAAiB,iBAAkC;AACjE,SAAO,kBAAkB,MAAM;AACjC;AAiBO,SAAS,aAAa,OAAqC;AAChE,QAAM,EAAE,QAAQ,QAAQ,SAAS,UAAU,IAAI;AAC/C,QAAM,cAAc,OAAO,IAAI,OAAO,SAAS,IAAI,UAAU,SAAS;AACtE,QAAM,IAAI,cAAc,OAAO,IAAI,OAAO,SAAS,MAAM,MAAM,OAAO,IAAI,MAAM,MAAM,QAAQ;AAC9F,QAAM,UAAU,OAAO,IAAI,OAAO,QAAQ,IAAI,QAAQ,QAAQ;AAC9D,QAAM,YAAY,UAAU,QAAQ,MAAM,OAAO,QAAQ;AAEzD,QAAM,IAAI,KAAK,IAAI,MAAM,MAAM,KAAK,IAAI,SAAS,SAAS,CAAC;AAC3D,SAAO,EAAE,GAAG,EAAE;AAChB;;;ACjEO,SAAS,cACd,eACA,KACA,aAA2D,CAAC,MACzD,UACuB;AAC1B,QAAM,UAAU,cAAc,cAAc,GAAG;AAC/C,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACtD,QAAI,UAAU,OAAW,SAAQ,aAAa,MAAM,KAAK;AAAA,EAC3D;AACA,aAAW,SAAS,UAAU;AAC5B,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,MAAO;AAC9D,YAAQ,OAAO,KAAK;AAAA,EACtB;AACA,SAAO;AACT;AAGO,SAAS,gBAAgB,SAAkB,MAAc,OAAoC;AAClG,MAAI,UAAU,QAAQ,UAAU,MAAO,SAAQ,gBAAgB,IAAI;AAAA,MAC9D,SAAQ,aAAa,MAAM,KAAK;AACvC;AAGO,SAAS,cAAc,SAAkB,MAAmB;AACjE,QAAM,MAAM,QAAQ,sBAAsB;AAC1C,QAAM,SAAS,KAAK,sBAAsB;AAC1C,SAAO;AAAA,IACL,GAAG,IAAI,OAAO,OAAO,OAAO,KAAK;AAAA,IACjC,GAAG,IAAI,MAAM,OAAO,MAAM,KAAK;AAAA,IAC/B,OAAO,IAAI;AAAA,IACX,QAAQ,IAAI;AAAA,EACd;AACF;AAGO,SAAS,eAAe,SAA0B;AACvD,UAAQ,QAAQ,aAAa,YAAY,KAAK,QAAQ,eAAe,IAAI,KAAK;AAChF;AAGO,SAAS,gBAAgB,SAA2B;AACzD,MAAI;AACF,WAAO,QAAQ,QAAQ,gBAAgB;AAAA,EACzC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACrCO,SAAS,gBACd,eACA,UACA,SACW;AACX,QAAM,EAAE,gBAAgB,IAAI;AAC5B,QAAM,SAAS,kBACX;AAAA,IACE;AAAA,IACA;AAAA,IACA,EAAE,MAAM,UAAU,OAAO,uBAAuB;AAAA,IAChD,SAAS;AAAA,EACX,IACA;AACJ,UAAQ,iBAAiB,SAAS,MAAM,kBAAkB,CAAC;AAC3D,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,EAAE,OAAO,gBAAgB;AAAA,IACzB,cAAc,eAAe,KAAK,EAAE,OAAO,qBAAqB,GAAG,SAAS,SAAS;AAAA,IACrF;AAAA,EACF;AACA,UAAQ,SAAS;AAEjB,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAM,CAAC,QAAQ;AAAA,IACxB,SAAS,OAAO;AACd,cAAQ,SAAS,CAAC;AAAA,IACpB;AAAA,IACA,MAAM,EAAE,KAAK,OAAO,QAAQ,KAAK,GAAG;AAClC,cAAQ,MAAM,QAAQ,GAAG,GAAG,MAAM,KAAK,MAAM,MAAM,MAAM,IAAI;AAAA,IAC/D;AAAA,IACA,UAAU;AACR,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;AC3CO,SAAS,gBACd,eACA,SACA,UACqB;AACrB,QAAM,UAAU,cAAc,eAAe,SAAS;AAAA,IACpD,OAAO;AAAA,IACP,eAAe;AAAA,IACf,cAAc,QAAQ;AAAA,EACxB,CAAC;AACD,UAAQ,SAAS;AAEjB,WAAS,QAAQ,MAAqB;AACpC,QAAI,SAAS,CAAC,QAAQ,OAAQ;AAC9B,YAAQ,SAAS,CAAC;AAClB,aAAS,IAAI;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,MAAM,CAAC,QAAQ;AAAA,IACvB,MAAM,MAAM,QAAQ,IAAI;AAAA,IACxB,OAAO,MAAM,QAAQ,KAAK;AAAA,IAC1B,UAAU;AACR,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;ACtBA,SAAS,YAAY,QAAqC;AACxD,MAAI,CAAC,UAAU,OAAQ,OAAmB,YAAY,WAAY,QAAO;AACzE,QAAM,UAAU;AAChB,SAAO,QAAQ,sBAAsB,QAAQ,QAAQ,QAAQ,mBAAmB,MAAM;AACxF;AAGA,SAAS,QAAQ,SAA2B;AAC1C,MAAI,QAAQ,cAAc,YAAY,CAAC,QAAQ,aAAa,MAAM,EAAG,QAAO;AAC5E,MAAI,QAAQ,QAAQ,UAAU,EAAG,QAAO;AACxC,SACE,OAAO,QAAQ,oBAAoB,cAAc,QAAQ,gBAAgB,EAAE,oBAAoB,KAAK,CAAC;AAEzG;AAEA,SAAS,QAAQ,SAA2B;AAC1C,MAAI,QAAQ,aAAa,YAAY,MAAM,OAAQ,QAAO;AAC1D,MAAI;AACF,WAAO,QAAQ,QAAQ,QAAQ;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAY,OAA8B;AACjD,SAAO,CAAC,GAAG,MAAM,iBAAiB,+CAA+C,CAAC,EAAE,OAAO,OAAO;AACpG;AAGO,SAAS,kBAAkB,SAA6D;AAC7F,SAAO,CAAC,UAAU;AAChB,QAAI,MAAM,QAAQ,SAAU,SAAQ,YAAY;AAChD,UAAM,UAAU,YAAY,QAAQ,WAAW;AAC/C,UAAM,WAAW,UAAU,OAAO;AAAA,MAChC,MAAM,QAAQ;AAAA,MACd,aAAa,YAAY,MAAM,MAAM;AAAA,MACrC,UAAU,QAAQ,SAAS;AAAA,MAC3B,YAAY,QAAQ,SAAS;AAAA,MAC7B,WAAW,QAAQ,KAAK,OAAO;AAAA,MAC/B,kBAAkB,MAAM;AAAA,IAC1B,CAAC;AACD,QAAI,SAAS,eAAgB,OAAM,eAAe;AAClD,QAAI,SAAS,gBAAiB,OAAM,gBAAgB;AACpD,QAAI,SAAS,WAAW,YAAa,SAAQ,UAAU;AAAA,aAC9C,SAAS,OAAQ,SAAQ,IAAI,SAAS,MAAM;AAAA,EACvD;AACF;;;ACrDO,IAAM,SAAN,MAAa;AAAA,EACD,OAAuB,CAAC;AAAA,EACxB,qBAAqB,oBAAI,IAAyC;AAAA,EAC3E,SAAS;AAAA,EAEjB,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,MAAwB;AAC5B,SAAK,KAAK,KAAK,IAAI;AAAA,EACrB;AAAA;AAAA,EAGA,SAAS,SAAkB,WAAyB;AAClD,QAAI,QAAQ,UAAU,SAAS,SAAS,EAAG;AAC3C,UAAM,oBAAoB,QAAQ,aAAa,OAAO;AACtD,YAAQ,UAAU,IAAI,SAAS;AAC/B,SAAK,MAAM,MAAM;AACf,cAAQ,UAAU,OAAO,SAAS;AAClC,UAAI,CAAC,qBAAqB,QAAQ,UAAU,WAAW,EAAG,SAAQ,gBAAgB,OAAO;AAAA,IAC3F,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAAU,SAAkB,MAAc,OAA4B;AACpE,QAAI,YAAY,KAAK,mBAAmB,IAAI,OAAO;AACnD,QAAI,CAAC,WAAW;AACd,kBAAY,oBAAI,IAAI;AACpB,WAAK,mBAAmB,IAAI,SAAS,SAAS;AAAA,IAChD;AACA,QAAI,CAAC,UAAU,IAAI,IAAI,GAAG;AACxB,gBAAU,IAAI,MAAM,QAAQ,aAAa,IAAI,CAAC;AAC9C,WAAK,MAAM,MAAM;AACf,cAAM,WAAW,UAAU,IAAI,IAAI,KAAK;AACxC,YAAI,aAAa,KAAM,SAAQ,gBAAgB,IAAI;AAAA,YAC9C,SAAQ,aAAa,MAAM,QAAQ;AAAA,MAC1C,CAAC;AAAA,IACH;AACA,QAAI,UAAU,KAAM,SAAQ,gBAAgB,IAAI;AAAA,QAC3C,SAAQ,aAAa,MAAM,KAAK;AAAA,EACvC;AAAA,EAcA,OACE,QACA,MACA,UACA,SACM;AACN,UAAM,UAAU;AAChB,WAAO,iBAAiB,MAAM,SAAS,OAAO;AAC9C,SAAK,MAAM,MAAM,OAAO,oBAAoB,MAAM,SAAS,OAAO,CAAC;AAAA,EACrE;AAAA;AAAA,EAGA,QAAc;AACZ,QAAI,KAAK,OAAQ;AACjB,SAAK,SAAS;AACd,eAAW,QAAQ,KAAK,KAAK,QAAQ,GAAG;AACtC,UAAI;AACF,aAAK;AAAA,MACP,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,KAAK,SAAS;AACnB,SAAK,mBAAmB,MAAM;AAAA,EAChC;AACF;;;AC7CO,IAAM,QAAmD;AAAA,EAC9D,MAAM;AAAA,IACJ,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,EAC5B;AAAA,EACA,OAAO,CAAC,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC,CAAC;AAAA,EACnC,MAAM;AAAA,IACJ,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,EAC5B;AAAA,EACA,UAAU;AAAA,IACR,CAAC,QAAQ,EAAE,GAAG,yBAAyB,CAAC;AAAA,IACxC,CAAC,QAAQ,EAAE,GAAG,2BAA2B,CAAC;AAAA,IAC1C,CAAC,QAAQ,EAAE,GAAG,0BAA0B,CAAC;AAAA,IACzC,CAAC,QAAQ,EAAE,GAAG,4BAA4B,CAAC;AAAA,EAC7C;AAAA,EACA,OAAO,CAAC,CAAC,QAAQ,EAAE,GAAG,kBAAkB,CAAC,CAAC;AAAA,EAC1C,GAAG;AAAA,IACD,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC;AAAA,IAC5B,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC;AAAA,EAC9B;AAAA,EACA,aAAa;AAAA,IACX;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,EAAE,GAAG,0BAA0B,CAAC;AAAA,IACzC,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC;AAAA,EAC7B;AAAA,EACA,eAAe;AAAA,IACb;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,gBAAgB,CAAC;AAAA,IAC/B,CAAC,QAAQ,EAAE,GAAG,4EAA4E,CAAC;AAAA,EAC7F;AAAA,EACA,cAAc;AAAA,IACZ;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,EAAE,GAAG,0BAA0B,CAAC;AAAA,IACzC,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC;AAAA,IACzC,CAAC,QAAQ,EAAE,GAAG,kDAAkD,CAAC;AAAA,EACnE;AAAA,EACA,oBAAoB;AAAA,IAClB;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,EAAE,GAAG,0BAA0B,CAAC;AAAA,IACzC,CAAC,QAAQ,EAAE,GAAG,gBAAgB,CAAC;AAAA,IAC/B,CAAC,QAAQ,EAAE,GAAG,gBAAgB,CAAC;AAAA,EACjC;AAAA,EACA,UAAU;AAAA,IACR,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC;AAAA,IAC3B,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC;AAAA,IAC5B,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC;AAAA,IAC3B,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC;AAAA,IAC5B,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC;AAAA,IAC3B,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC;AAAA,IAC3B,CAAC,QAAQ,EAAE,OAAO,MAAM,QAAQ,MAAM,GAAG,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC;AAAA,EACjE;AAAA,EACA,WAAW;AAAA,IACT,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,KAAK,GAAG,IAAI,CAAC;AAAA,IACxC,CAAC,UAAU,EAAE,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAAC;AAAA,IACxC,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC;AAAA,IACzC,CAAC,QAAQ,EAAE,IAAI,QAAQ,IAAI,SAAS,IAAI,SAAS,IAAI,QAAQ,CAAC;AAAA,IAC9D,CAAC,QAAQ,EAAE,IAAI,SAAS,IAAI,QAAQ,IAAI,QAAQ,IAAI,QAAQ,CAAC;AAAA,EAC/D;AAAA,EACA,YAAY;AAAA,IACV,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,MAAM,GAAG,KAAK,CAAC;AAAA,IAC1C,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC;AAAA,IAC3B,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,EAC5B;AAAA,EACA,kBAAkB;AAAA,IAChB,CAAC,QAAQ,EAAE,GAAG,2EAA2E,CAAC;AAAA,IAC1F,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,aAAa,CAAC;AAAA,EAC9B;AAAA,EACA,+BAA+B;AAAA,IAC7B;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,EAAE,GAAG,qBAAqB,CAAC;AAAA,IACpC,CAAC,QAAQ,EAAE,GAAG,sBAAsB,CAAC;AAAA,IACrC,CAAC,QAAQ,EAAE,GAAG,sBAAsB,CAAC;AAAA,IACrC,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC;AAAA,IACxB,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC;AAAA,IACxB,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,EAC3B;AAAA,EACA,MAAM;AAAA,IACJ,CAAC,QAAQ,EAAE,GAAG,uCAAuC,CAAC;AAAA,IACtD,CAAC,QAAQ,EAAE,GAAG,yCAAyC,CAAC;AAAA,IACxD,CAAC,QAAQ,EAAE,GAAG,2CAA2C,CAAC;AAAA,IAC1D;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EACA,gBAAgB;AAAA,IACd,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,KAAK,GAAG,IAAI,CAAC;AAAA,IACxC,CAAC,UAAU,EAAE,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAAC;AAAA,IACxC,CAAC,QAAQ,EAAE,GAAG,qBAAqB,CAAC;AAAA,EACtC;AAAA,EACA,qBAAqB;AAAA,IACnB,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC;AAAA,IACzB,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AAAA,IAC1B,CAAC,QAAQ,EAAE,GAAG,iBAAiB,CAAC;AAAA,IAChC,CAAC,QAAQ,EAAE,GAAG,eAAe,CAAC;AAAA,EAChC;AAAA,EACA,UAAU;AAAA,IACR,CAAC,QAAQ,EAAE,OAAO,KAAK,QAAQ,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC;AAAA,IAC7D,CAAC,QAAQ,EAAE,GAAG,0BAA0B,CAAC;AAAA,IACzC,CAAC,QAAQ,EAAE,OAAO,KAAK,QAAQ,KAAK,GAAG,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC;AAAA,EACjE;AACF;AAWO,IAAM,oBAA2C,EAAE,MAAM,IAAI,aAAa,EAAE;AAEnF,IAAM,eAAe;AACrB,IAAM,uBAAuB;AAC7B,IAAM,gBAAgB;AAItB,IAAM,gBAAqC,oBAAI,IAAI;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,sBAA2C,oBAAI,IAAI;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOD,SAAS,WAAW,OAA2B,UAA0B;AACvE,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AACpF;AAEA,SAAS,WAAW,MAA0C;AAC5D,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,SAAO,OAAO,UAAU,eAAe,KAAK,OAAO,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC;AAC5E;AAEA,SAAS,SAAS,MAAgC,UAAuB,CAAC,GAAkB;AAC1F,QAAM,OAAO,OAAO,WAAW,QAAQ,MAAM,YAAY,CAAC;AAC1D,QAAM,OAA8B,CAAC;AACrC,MAAI,QAAQ,UAAW,MAAK,KAAK,CAAC,SAAS,QAAQ,SAAS,CAAC;AAC7D,OAAK;AAAA,IACH,CAAC,SAAS,IAAI;AAAA,IACd,CAAC,UAAU,IAAI;AAAA,IACf,CAAC,WAAW,WAAW;AAAA,IACvB,CAAC,QAAQ,MAAM;AAAA,IACf,CAAC,UAAU,cAAc;AAAA,IACzB,CAAC,gBAAgB,OAAO,WAAW,QAAQ,aAAa,oBAAoB,CAAC,CAAC;AAAA,IAC9E,CAAC,kBAAkB,OAAO;AAAA,IAC1B,CAAC,mBAAmB,OAAO;AAAA,IAC3B,CAAC,eAAe,MAAM;AAAA,IACtB,CAAC,aAAa,OAAO;AAAA,EACvB;AACA,QAAM,WAAsC,CAAC;AAC7C,aAAW,QAAQ,WAAW,IAAI,GAAG;AACnC,UAAM,CAAC,KAAK,UAAU,IAAI;AAC1B,QAAI,CAAC,cAAc,IAAI,GAAG,EAAG;AAC7B,UAAM,OAAO,OAAO,QAAQ,UAAU,EACnC,OAAO,CAAC,CAAC,IAAI,MAAM,oBAAoB,IAAI,IAAI,CAAC,EAChD,IAAI,CAAC,CAAC,MAAM,KAAK,MAAwB,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AACjE,aAAS,KAAK,CAAC,KAAK,IAAI,CAAC;AAAA,EAC3B;AACA,SAAO,EAAE,MAAM,SAAS;AAC1B;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,MACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM;AACzB;AAEA,SAAS,cAAc,YAAiD;AACtE,SAAO,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,gBAAgB,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE;AAC1F;AAOO,SAAS,WAAW,MAAgC,SAA+B;AACxF,QAAM,EAAE,MAAM,SAAS,IAAI,SAAS,MAAM,OAAO;AACjD,QAAM,UAAU,SAAS,IAAI,CAAC,CAAC,KAAK,UAAU,MAAM,IAAI,GAAG,GAAG,cAAc,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE;AACpG,SAAO,eAAe,aAAa,IAAI,cAAc,IAAI,CAAC,IAAI,OAAO;AACvE;AAGO,SAAS,YAAY,MAAgC,SAAsC;AAChG,QAAM,EAAE,MAAM,SAAS,IAAI,SAAS,MAAM,OAAO;AACjD,QAAM,MAAM,SAAS,gBAAgB,eAAe,KAAK;AACzD,aAAW,CAAC,MAAM,KAAK,KAAK,KAAM,KAAI,aAAa,MAAM,KAAK;AAC9D,aAAW,CAAC,KAAK,UAAU,KAAK,UAAU;AACxC,UAAM,QAAQ,SAAS,gBAAgB,eAAe,GAAG;AACzD,eAAW,CAAC,MAAM,KAAK,KAAK,WAAY,OAAM,aAAa,MAAM,KAAK;AACtE,QAAI,OAAO,KAAK;AAAA,EAClB;AACA,SAAO;AACT;;;AC5RO,SAAS,aAAa,SAA0C;AACrE,QAAM,EAAE,eAAe,UAAU,SAAS,SAAS,QAAQ,IAAI;AAC/D,QAAM,QAAQ,cAAc,eAAe,UAAU;AAAA,IACnD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,cAAc,SAAS;AAAA,EACzB,CAAC;AACD,QAAM,OAAO,YAAY,GAAG,CAAC;AAC7B,QAAM,OAAO,cAAc,eAAe,OAAO,EAAE,OAAO,uBAAuB,CAAC;AAClF,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,EAAE,OAAO,mCAAmC,eAAe,UAAU,mBAAmB,QAAQ;AAAA,IAChG;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,OAAO,yBAAyB;AAAA,MAClC,cAAc,eAAe,OAAO,EAAE,OAAO,yBAAyB,IAAI,QAAQ,GAAG,SAAS,MAAM;AAAA,MACpG;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACA,UAAQ,SAAS;AACjB,UAAQ,OAAO,IAAI;AAEnB,MAAI,OAAO;AACX,MAAI,UAAU;AACd,QAAM,gBAAgB,QAAQ,OAAO,OAAO,EAAE,OAAO,SAAS,YAAY,CAAC;AAE3E,WAAS,MAAM,MAAwB;AACrC,cAAU;AACV,QAAI,SAAS,KAAM,QAAO;AAC1B,WAAO;AACP,YAAQ,SAAS,CAAC;AAClB,QAAI,CAAC,QAAQ,QAAQ,SAAS,cAAc,aAAa,EAAG,SAAQ,gBAAgB;AACpF,YAAQ,SAAS,IAAI;AACrB,WAAO;AAAA,EACT;AAEA,WAAS,QAAQ,MAAqB;AACpC,QAAI,MAAM,IAAI,EAAG,SAAQ,WAAW,IAAI;AAAA,EAC1C;AAEA,QAAM,iBAAiB,SAAS,MAAM,QAAQ,KAAK,CAAC;AAEpD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ,MAAM;AAAA,IACd;AAAA,IACA,QAAQ,MAAM,QAAQ,CAAC,IAAI;AAAA,IAC3B,MAAM,SAAS;AACb,UAAI,CAAC,QAAS,OAAM,OAAO;AAAA,IAC7B;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,UAAU;AACR,oBAAc;AACd,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;AC7EA,IAAM,cAAoC,CAAC,SAAS,UAAU,MAAM;AA2BpE,SAAS,YAAY,OAA+B;AAClD,SAAO,MAAM,IAAI,WAAW,KAAK,KAAK,KAAK,MAAM,GAAG,KAAK,CAAC,MAAM,WAAW,CAAC,MAAM,WAAW,CAAC,MAAM;AACtG;AAEO,SAAS,WAAW,SAAsC;AAC/D,QAAM,EAAE,MAAM,OAAO,IAAI,UAAU,QAAQ,IAAI;AAC/C,QAAM,gBAAgB,KAAK;AAC3B,MAAI,SAAS,QAAQ;AACrB,MAAI,QAAgB,CAAC;AACrB,MAAI,YAAY;AAEhB,QAAM,UAAU,cAAc,eAAe,UAAU;AAAA,IACrD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,eAAe;AAAA,IACf,cAAc,SAAS;AAAA,IACvB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB,CAAC;AACD,UAAQ,OAAO,YAAY,MAAM,CAAC;AAElC,QAAM,WAAW,cAAc,eAAe,OAAO;AAAA,IACnD,OAAO;AAAA,IACP;AAAA,IACA,MAAM;AAAA,IACN,cAAc,SAAS;AAAA,EACzB,CAAC;AACD,WAAS,SAAS;AAClB,QAAM,QAAQ,QAAQ;AAEtB,QAAM,SAAS,MAAe,CAAC,SAAS;AAExC,WAAS,UAAU,MAAuC;AACxD,UAAM,MAAM,OAAO,IAAI,KAAK,CAAC;AAC7B,WAAO,SAAS,UAAU,CAAC,GAAG,KAAK,GAAG,QAAQ,kBAAkB,CAAC,IAAI;AAAA,EACvE;AAEA,WAAS,aAAsB;AAC7B,WAAO,YAAY,KAAK,CAAC,SAAS,UAAU,IAAI,EAAE,SAAS,CAAC;AAAA,EAC9D;AAEA,WAAS,0BAAgC;AACvC,YAAQ,SAAS,CAAC,WAAW;AAC7B,QAAI,QAAQ,OAAQ,OAAM;AAAA,EAC5B;AAIA,WAAS,WAAW,OAAkB,OAA2B;AAC/D,QAAI,UAAU,WAAW,QAAQ,WAAW,KAAK,MAAM,4BAA4B,KAAM,QAAO;AAChG,WAAO,MAAM,WAAW,KAAK;AAAA,EAC/B;AAEA,WAAS,YACP,MACA,OACA,SAMmB;AACnB,UAAM,WAAW,cAAc,eAAe,QAAQ,EAAE,OAAO,0BAA0B,CAAC;AAC1F,QAAI,QAAQ,KAAM,UAAS,OAAO,YAAY,QAAQ,IAAI,CAAC;AAC3D,UAAM,UAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA,EAAE,MAAM,UAAU,OAAO,sBAAsB,MAAM,UAAU,KAAK;AAAA,MACpE;AAAA,MACA,cAAc,eAAe,QAAQ,EAAE,OAAO,2BAA2B,GAAG,KAAK;AAAA,MACjF,QAAQ,OAAO,cAAc,eAAe,QAAQ,EAAE,OAAO,yBAAyB,GAAG,QAAQ,GAAG;AAAA,IACtG;AACA,oBAAgB,SAAS,iBAAiB,QAAQ,YAAY,MAAM;AACpE,QAAI,QAAQ,YAAY,OAAW,SAAQ,aAAa,gBAAgB,OAAO,QAAQ,OAAO,CAAC;AAC/F,WAAO;AAAA,EACT;AAEA,WAAS,YAA2B;AAClC,WAAO,YAAY,SAAS,EAAE,WAAW,sBAAsB,CAAC;AAAA,EAClE;AAEA,WAAS,YAAY,OAA2C,OAAwB;AACtF,UAAM,WAAW,WAAW,OAAO,KAAK;AACxC,QAAI,MAAM,SAAS,YAAY;AAC7B,YAAM,UAAU,MAAM,QAAQ;AAC9B,YAAMA,WAAU,YAAY,oBAAoB,MAAM,OAAO;AAAA,QAC3D,MAAM,MAAM;AAAA,QACZ,KAAK,UAAU;AAAA,QACf;AAAA,QACA;AAAA,MACF,CAAC;AACD,MAAAA,SAAQ,QAAQ,SAAS,MAAM;AAC/B,MAAAA,SAAQ,QAAQ,YAAY;AAC5B,aAAO;AAAA,QACL,KAAK,MAAM;AAAA,QACX,SAAAA;AAAA,QACA,OAAO,MAAM;AAAA,QACb;AAAA,QACA,WAAW;AACT,gBAAM,SAAS,CAAC,MAAM,QAAQ,CAAC;AAC/B,kBAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AACA,UAAM,WACJ,MAAM,SAAS,YAAY,MAAM,WAC7B,cAAc,eAAe,QAAQ,EAAE,OAAO,yBAAyB,GAAG,MAAM,QAAQ,IACxF;AACN,UAAM,UAAU,YAAY,YAAY,MAAM,OAAO,EAAE,MAAM,MAAM,MAAM,KAAK,UAAU,SAAS,CAAC;AAClG,YAAQ,QAAQ,SAAS,MAAM;AAC/B,YAAQ,QAAQ,YAAY;AAC5B,QAAI,MAAM,SAAS,UAAU;AAC3B,YAAM,eACJ,MAAM,qBAAqB,MAAM,WAAW,0BAA0B,MAAM,QAAQ,IAAI;AAC1F,sBAAgB,SAAS,qBAAqB,gBAAgB,IAAI;AAAA,IACpE;AACA,QAAI,MAAM,SAAS,SAAU,SAAQ,aAAa,iBAAiB,QAAQ;AAC3E,QAAI,MAAM,SAAS,YAAY,MAAM,OAAQ,SAAQ,QAAQ,SAAS;AACtE,WAAO;AAAA,MACL,KAAK,MAAM;AAAA,MACX;AAAA,MACA,OAAO,MAAM;AAAA,MACb;AAAA,MACA,WAAW;AACT,cAAM,EAAE,cAAc,KAAK,CAAC;AAC5B,cAAM,SAAS;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,WAAS,iBACP,OACA,OACyC;AACzC,UAAM,WAAW,WAAW,OAAO,KAAK;AACxC,UAAM,QAAQ,MAAM,MAAM;AAC1B,UAAM,YAAY;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,MAAM;AAAA,QACN,cAAc,MAAM;AAAA,QACpB,gBAAgB,MAAM;AAAA,QACtB,mBAAmB;AAAA,MACrB;AAAA;AAAA,MAEA;AAAA,QACE;AAAA,QACA;AAAA,QACA,EAAE,OAAO,yBAAyB,eAAe,OAAO;AAAA,QACxD,MAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,aAAa,MAAM,QAAQ,IAAI,CAAC,WAAiB;AACrD,YAAM,UAAU,YAAY,iBAAiB,OAAO,OAAO;AAAA,QACzD,KAAK,UAAU;AAAA,QACf;AAAA,QACA,SAAS,OAAO,UAAU;AAAA,MAC5B,CAAC;AACD,cAAQ,QAAQ,YAAY,OAAO;AACnC,gBAAU,OAAO,OAAO;AACxB,aAAO;AAAA,QACL,KAAK,GAAG,MAAM,EAAE,KAAS,OAAO,KAAK;AAAA,QACrC;AAAA,QACA,OAAO,OAAO;AAAA,QACd;AAAA,QACA,WAAW;AACT,cAAI,MAAM,MAAM,MAAM,OAAO,MAAO,OAAM,SAAS,OAAO,KAAK;AAC/D,kBAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO,EAAE,SAAS,WAAW,OAAO,WAAW;AAAA,EACjD;AAEA,WAAS,SAAe;AACtB,UAAM,aAAa,MAAM,KAAK,CAAC,SAAS,KAAK,YAAY,cAAc,aAAa,GAAG;AACvF,UAAM,QAAuB,CAAC;AAC9B,UAAM,WAAmB,CAAC;AAC1B,eAAW,QAAQ,aAAa;AAC9B,YAAM,UAAU,UAAU,IAAI;AAC9B,UAAI,QAAQ,WAAW,EAAG;AAC1B,UAAI,MAAM,SAAS,GAAG;AACpB,cAAM;AAAA,UACJ,cAAc,eAAe,OAAO,EAAE,OAAO,2BAA2B,MAAM,YAAY,CAAC;AAAA,QAC7F;AAAA,MACF;AACA,iBAAW,SAAS,SAAS;AAC3B,YAAI,MAAM,SAAS,SAAS;AAC1B,gBAAM,QAAQ,iBAAiB,OAAO,IAAI;AAC1C,gBAAM,KAAK,MAAM,OAAO;AACxB,mBAAS,KAAK,GAAG,MAAM,KAAK;AAAA,QAC9B,OAAO;AACL,gBAAM,OAAO,YAAY,OAAO,IAAI;AACpC,gBAAM,KAAK,KAAK,OAAO;AACvB,mBAAS,KAAK,IAAI;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AACA,eAAW,QAAQ,UAAU;AAC3B,WAAK,QAAQ,iBAAiB,SAAS,MAAM;AAC3C,YAAI,CAAC,KAAK,SAAU,MAAK,SAAS;AAAA,MACpC,CAAC;AAAA,IACH;AACA,aAAS,gBAAgB,GAAG,KAAK;AACjC,YAAQ;AACR,QAAI,eAAe,UAAa,OAAO,GAAG;AACxC,OAAC,MAAM,KAAK,CAAC,SAAS,KAAK,QAAQ,UAAU,KAAK,MAAM,CAAC,IAAI,QAAQ,MAAM;AAAA,IAC7E;AAAA,EACF;AAEA,WAAS,QAAQ,OAAqB;AACpC,QAAI,MAAM,WAAW,EAAG;AACxB,WAAO,QAAQ,MAAM,UAAU,MAAM,MAAM,GAAG,QAAQ,MAAM;AAAA,EAC9D;AAEA,WAAS,eAAuB;AAC9B,WAAO,MAAM,UAAU,CAAC,SAAS,KAAK,YAAY,cAAc,aAAa;AAAA,EAC/E;AAEA,WAAS,UAAU,WAAyB;AAC1C,UAAM,QAAQ,aAAa;AAC3B,UAAM,QAAQ,UAAU,YAAY;AACpC,aAAS,OAAO,GAAG,QAAQ,MAAM,QAAQ,QAAQ;AAC/C,YAAM,SAAS,KAAK,IAAI,OAAO,EAAE,IAAI,QAAQ,MAAM;AACnD,UAAI,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,WAAW,KAAK,GAAG;AACvD,gBAAQ,KAAK;AACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,uBAAuB,CAAC,UAA8B;AAC1D,UAAM,SAAS,MAAM;AACrB,QAAI,WAAW,SAAS,SAAS,MAAM,KAAK,QAAQ,SAAS,MAAM,GAAI;AACvE,UAAM;AAAA,EACR;AAIA,QAAM,eAAe,MAAY,MAAM;AAEvC,WAAS,KAAK,QAA0B,SAAe;AACrD,QAAI,aAAa,CAAC,WAAW,EAAG;AAChC,YAAQ,KAAK;AACb,UAAM,UAAU,OAAO;AACvB,WAAO;AACP,QAAI,CAAC,SAAS;AACZ,eAAS,SAAS;AAClB,cAAQ,aAAa,iBAAiB,MAAM;AAE5C,oBAAc,iBAAiB,eAAe,sBAAsB,IAAI;AACxE,oBAAc,aAAa,iBAAiB,QAAQ,YAAY;AAAA,IAClE;AACA,YAAQ,UAAU,SAAS,MAAM,SAAS,IAAI,CAAC;AAAA,EACjD;AAEA,WAAS,MAAM,UAAsC,CAAC,GAAS;AAC7D,QAAI,CAAC,OAAO,EAAG;AACf,aAAS,SAAS;AAClB,YAAQ,aAAa,iBAAiB,OAAO;AAC7C,kBAAc,oBAAoB,eAAe,sBAAsB,IAAI;AAC3E,kBAAc,aAAa,oBAAoB,QAAQ,YAAY;AACnE,QAAI,QAAQ,gBAAgB,CAAC,QAAQ,OAAQ,SAAQ,MAAM;AAAA,EAC7D;AAEA,WAAS,UAAgB;AACvB,QAAI,OAAO,EAAG,QAAO;AAAA,EACvB;AAEA,UAAQ,iBAAiB,SAAS,MAAM;AACtC,QAAI,OAAO,EAAG,OAAM;AAAA,QACf,MAAK,OAAO;AAAA,EACnB,CAAC;AAKD,WAAS,QAAQ,OAA4B;AAC3C,UAAM,eAAe;AACrB,UAAM,gBAAgB;AAAA,EACxB;AAEA,UAAQ,iBAAiB,WAAW,CAAC,UAAU;AAC7C,QAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,OAAO,MAAM,QAAQ,aAAa;AAC3E,cAAQ,KAAK;AACb,WAAK,OAAO;AAAA,IACd,WAAW,MAAM,QAAQ,WAAW;AAClC,cAAQ,KAAK;AACb,WAAK,MAAM;AAAA,IACb;AAAA,EACF,CAAC;AAED,WAAS,iBAAiB,WAAW,CAAC,UAAU;AAE9C,QAAI,eAAe,KAAK,EAAG;AAC3B,YAAQ,MAAM,KAAK;AAAA,MACjB,KAAK;AACH,gBAAQ,aAAa,IAAI,CAAC;AAC1B;AAAA,MACF,KAAK,WAAW;AACd,cAAM,QAAQ,aAAa;AAC3B,gBAAQ,QAAQ,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAChD;AAAA,MACF;AAAA,MACA,KAAK;AACH,gBAAQ,CAAC;AACT;AAAA,MACF,KAAK;AACH,gBAAQ,MAAM,SAAS,CAAC;AACxB;AAAA,MACF,KAAK;AAGH,cAAM,EAAE,cAAc,KAAK,CAAC;AAC5B;AAAA,MACF,KAAK;AAEH;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAEH,cAAM,gBAAgB;AACtB;AAAA,MACF;AACE,YAAI,CAAC,YAAY,KAAK,EAAG;AACzB,kBAAU,MAAM,GAAG;AAAA,IACvB;AACA,YAAQ,KAAK;AAAA,EACf,CAAC;AAED,0BAAwB;AAExB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,MAAM;AACd,eAAS;AACT,8BAAwB;AACxB,cAAQ;AAAA,IACV;AAAA,IACA,UAAU;AACR,UAAI,UAAW;AACf,YAAM;AACN,kBAAY;AACZ,cAAQ,OAAO;AACf,eAAS,OAAO;AAAA,IAClB;AAAA,EACF;AACF;;;ACjXO,SAAS,mBAAmB,SAAwC;AACzE,QAAM,EAAE,eAAe,UAAU,MAAM,SAAS,QAAQ,IAAI;AAC5D,QAAM,OAAO,cAAc,eAAe,QAAQ,EAAE,OAAO,yBAAyB,CAAC;AACrF,QAAM,OAAO,cAAc,eAAe,QAAQ,EAAE,OAAO,yBAAyB,CAAC;AACrF,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,EAAE,MAAM,UAAU,OAAO,qCAAqC,eAAe,WAAW;AAAA,IACxF;AAAA,IACA;AAAA,EACF;AACA,UAAQ,SAAS;AACjB,UAAQ,iBAAiB,SAAS,MAAM,QAAQ,WAAW,CAAC;AAC5D,QAAM,gBAAgB,QAAQ,cAC1B,QAAQ,OAAO,SAAS,EAAE,OAAO,SAAS,aAAa,CAAC,IACxD;AAEJ,MAAI;AAEJ,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAM,CAAC,QAAQ;AAAA,IACxB,IAAI,EAAE,OAAO,OAAO,GAAG;AACrB,YAAM,QAAQ,QAAQ;AACtB,cAAQ,SAAS,CAAC;AAClB,UAAI,CAAC,OAAO;AACV,gBAAQ,KAAK;AACb;AAAA,MACF;AACA,YAAM,iBAAiB,aAAa,OAAO,IAAI;AAC/C,WAAK,cAAc,SAAS,SAAS,OAAO,cAAc;AAC1D,cAAQ;AAAA,QACN;AAAA,QACA,SAAS,cAAc,OAAO,QAAQ,gBAAgB,aAAa,QAAQ,IAAI,CAAC;AAAA,MAClF;AAEA,YAAM,OAAO,SAAS,IAAI,WAAW;AACrC,UAAI,SAAS,UAAU;AACrB,mBAAW;AACX,gBAAQ,QAAQ,WAAW;AAC3B,aAAK,gBAAgB,YAAY,SAAS,WAAW,aAAa,gBAAgB,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,IACA,UAAU;AACR,sBAAgB;AAChB,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;AC7DO,SAAS,gBAAgB,eAAoC;AAClE,QAAM,OAAO,cAAc,eAAe,QAAQ,EAAE,OAAO,uBAAuB,CAAC;AACnF,QAAM,OAAO,cAAc,eAAe,KAAK,EAAE,OAAO,uBAAuB,CAAC;AAChF,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,EAAE,OAAO,mBAAmB,eAAe,SAAS;AAAA,IACpD;AAAA,IACA;AAAA,EACF;AACA,UAAQ,SAAS;AAEjB,MAAI;AAEJ,WAAS,gBAAsB;AAC7B,QAAI,QAAS,cAAa,QAAQ,KAAK;AACvC,cAAU;AAAA,EACZ;AAEA,WAAS,KAAK,QAA6B;AACzC,cAAU;AACV,QAAI,QAAQ,QAAQ,aAAa,OAAO,UAAU;AAChD,cAAQ,QAAQ,WAAW,OAAO;AAClC,cAAQ,aAAa,QAAQ,OAAO,aAAa,WAAW,UAAU,QAAQ;AAC9E,WAAK,gBAAgB,YAAY,OAAO,aAAa,WAAW,aAAa,gBAAgB,CAAC;AAAA,IAChG;AAEA,QAAI,KAAK,gBAAgB,OAAO,KAAM,MAAK,cAAc,OAAO;AAChE,YAAQ,SAAS;AAAA,EACnB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,IAAI,QAAQ,SAAS;AACnB,UAAI,WAAW,MAAM;AACnB,sBAAc;AACd,gBAAQ,SAAS;AACjB;AAAA,MACF;AACA,UAAI,CAAC,QAAQ,QAAQ;AACnB,aAAK,MAAM;AACX;AAAA,MACF;AAGA,UAAI,SAAS;AACX,gBAAQ,SAAS;AACjB;AAAA,MACF;AACA,UAAI,UAAU,GAAG;AACf,cAAM,QAAQ,EAAE,QAAQ,OAAO,WAAW,MAAM,KAAK,MAAM,MAAM,GAAG,OAAO,EAAE;AAC7E,kBAAU;AAAA,MACZ,OAAO;AACL,aAAK,MAAM;AAAA,MACb;AAAA,IACF;AAAA,IACA,UAAU;AACR,oBAAc;AACd,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;AC3CO,SAAS,cAAc,EAAE,MAAM,OAAO,GAAG,GAAsC;AACpF,QAAM,gBAAgB,KAAK;AAC3B,QAAM,QAAQ,cAAc,eAAe,QAAQ,EAAE,OAAO,yBAAyB,CAAC;AACtF,QAAM,WAAW,cAAc,eAAe,OAAO,EAAE,OAAO,eAAe,CAAC;AAC9E,QAAM,UAAU,cAAc,eAAe,OAAO,EAAE,OAAO,oBAAoB,MAAM,WAAW,GAAG,CAAC;AACtG,UAAQ,SAAS;AACjB,UAAQ,OAAO,OAAO,QAAQ;AAC9B,QAAM,OAAO,OAAO;AAEpB,MAAI;AACJ,MAAI;AAGJ,MAAI,YAAY;AAEhB,MAAI;AACJ,QAAM,YAAY,oBAAI,IAAgB;AAEtC,WAAS,gBAAsB;AAC7B,QAAI,QAAS,cAAa,QAAQ,KAAK;AACvC,cAAU;AAAA,EACZ;AAEA,WAAS,QAAQ,QAA8C;AAC7D,WAAO,OAAO,WAAW,aAAa,OAAO,IAAI;AAAA,EACnD;AAEA,WAAS,MAAM,SAA4B;AACzC,UAAM,SAAS,QAAQ,QAAqB,eAAe,KAAK;AAChE,UAAM,QAAQ,aAAa;AAAA,MACzB,QAAQ,cAAc,SAAS,IAAI;AAAA,MACnC,QAAQ,cAAc,QAAQ,IAAI;AAAA,MAClC,SAAS,EAAE,OAAO,QAAQ,aAAa,QAAQ,QAAQ,aAAa;AAAA,MACpE,WAAW,EAAE,OAAO,KAAK,aAAa,QAAQ,KAAK,aAAa;AAAA,IAClE,CAAC;AACD,YAAQ,MAAM,OAAO,GAAG,MAAM,CAAC;AAC/B,YAAQ,MAAM,MAAM,GAAG,MAAM,CAAC;AAAA,EAChC;AAEA,WAAS,OAAa;AACpB,kBAAc;AACd,QAAI,CAAC,MAAO;AACZ,UAAM,EAAE,SAAS,YAAY,IAAI;AACjC,YAAQ;AACR,YAAQ,SAAS;AACjB,QAAI,gBAAgB,KAAM,SAAQ,gBAAgB,kBAAkB;AAAA,QAC/D,SAAQ,aAAa,oBAAoB,WAAW;AAAA,EAC3D;AAEA,WAAS,KAAK,SAAsB,QAA6B;AAC/D,kBAAc;AACd,UAAM,UAAU,QAAQ,MAAM;AAC9B,QAAI,CAAC,WAAW,CAAC,QAAQ,aAAa;AACpC,UAAI,OAAO,YAAY,QAAS,MAAK;AACrC;AAAA,IACF;AACA,QAAI,SAAS,MAAM,YAAY,QAAS,MAAK;AAC7C,UAAM,cAAc,QAAQ;AAC5B,aAAS,cAAc,QAAQ,YAAY;AAC3C,aAAS,SAAS,CAAC,QAAQ;AAC3B,YAAQ,SAAS;AACjB,QAAI,CAAC,OAAO;AACV,YAAM,cAAc,QAAQ,aAAa,kBAAkB;AAC3D,cAAQ,EAAE,SAAS,YAAY;AAG/B,YAAM,WACJ,CAAC,eAAe,OAAO,EAAE,SAAS,QAAQ,KAAK,KAC9C,QAAQ,QAAQ,QAAQ,KAAK,CAAC,QAAQ,aAAa,mBAAmB;AACzE,UAAI,UAAU;AACZ,gBAAQ,aAAa,oBAAoB,CAAC,aAAa,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC;AAAA,MACtF;AAAA,IACF;AACA,UAAM,OAAO;AAAA,EACf;AAEA,WAAS,QAAQ,SAAsB,QAAuB,OAA2B;AACvF,QAAI,MAAM,gBAAgB,WAAW,YAAY,QAAS;AAC1D,QAAI,SAAS,KAAK,IAAI,IAAI,WAAW;AACnC,WAAK,SAAS,MAAM;AACpB;AAAA,IACF;AACA,kBAAc;AACd,cAAU,EAAE,SAAS,OAAO,WAAW,MAAM,KAAK,SAAS,MAAM,GAAG,gBAAgB,EAAE;AAAA,EACxF;AAEA,WAAS,QAAQ,SAA4B;AAC3C,QAAI,YAAY,QAAS,WAAU;AACnC,QAAI,SAAS,YAAY,QAAS,eAAc;AAChD,QAAI,OAAO,YAAY,SAAS;AAC9B,WAAK;AACL,kBAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,WAAS,QAAQ,SAAsB,QAA6B;AAClE,QAAI,gBAAgB,OAAO,EAAG,MAAK,SAAS,MAAM;AAAA,EACpD;AAEA,WAAS,OAAO,SAA4B;AAC1C,QAAI,SAAS,YAAY,QAAS,eAAc;AAChD,QAAI,OAAO,YAAY,QAAS,MAAK;AAAA,EACvC;AAEA,WAAS,QAAQ,SAAsB,OAAoB;AACzD,QAAI,MAAM,SAAS,cAAe,WAAU;AAC5C,QAAI,SAAS,YAAY,QAAS,eAAc;AAChD,QAAI,OAAO,YAAY,QAAS,MAAK;AAAA,EACvC;AAEA,WAAS,OAAO,SAAsB,QAAmC;AACvE,UAAM,QAAQ,CAAC,UAAwB,QAAQ,SAAS,QAAQ,KAAK;AACrE,UAAM,QAAQ,MAAM,QAAQ,OAAO;AACnC,UAAM,QAAQ,MAAM,QAAQ,SAAS,MAAM;AAC3C,UAAM,OAAO,MAAM,OAAO,OAAO;AACjC,UAAM,QAAQ,CAAC,UAAiB,QAAQ,SAAS,KAAK;AACtD,YAAQ,iBAAiB,gBAAgB,KAAK;AAC9C,YAAQ,iBAAiB,gBAAgB,KAAK;AAC9C,YAAQ,iBAAiB,SAAS,KAAK;AACvC,YAAQ,iBAAiB,QAAQ,IAAI;AACrC,YAAQ,iBAAiB,eAAe,KAAK;AAC7C,YAAQ,iBAAiB,SAAS,KAAK;AACvC,UAAM,SAAS,MAAM;AACnB,UAAI,CAAC,UAAU,OAAO,MAAM,EAAG;AAC/B,cAAQ,oBAAoB,gBAAgB,KAAK;AACjD,cAAQ,oBAAoB,gBAAgB,KAAK;AACjD,cAAQ,oBAAoB,SAAS,KAAK;AAC1C,cAAQ,oBAAoB,QAAQ,IAAI;AACxC,cAAQ,oBAAoB,eAAe,KAAK;AAChD,cAAQ,oBAAoB,SAAS,KAAK;AAC1C,UAAI,OAAO,YAAY,WAAW,SAAS,YAAY,QAAS,MAAK;AACrE,UAAI,YAAY,QAAS,WAAU;AAAA,IACrC;AACA,cAAU,IAAI,MAAM;AACpB,WAAO;AAAA,EACT;AAEA,WAAS,SACP,WACA,UACA,SACY;AACZ,QAAI;AACJ,UAAM,YAAY,CAAC,WAAwD;AACzE,UAAI,CAAC,UAAU,OAAQ,OAAmB,YAAY,WAAY,QAAO;AACzE,YAAM,QAAS,OAAmB,QAAqB,QAAQ;AAC/D,aAAO,SAAS,UAAU,SAAS,KAAK,IAAI,QAAQ;AAAA,IACtD;AACA,UAAM,WAAW,CAAC,YAAyB,MAAM,QAAQ,OAAO;AAChE,UAAM,OAAO,CAAC,UAAwB;AACpC,YAAM,UAAU,UAAU,MAAM,MAAM;AACtC,UAAI,YAAY,QAAS;AACzB,UAAI,QAAS,SAAQ,OAAO;AAC5B,gBAAU;AACV,UAAI,QAAS,SAAQ,SAAS,SAAS,OAAO,GAAG,KAAK;AAAA,IACxD;AACA,UAAM,MAAM,CAAC,UAAwB;AACnC,UAAI,CAAC,QAAS;AACd,UAAI,UAAU,MAAM,aAAa,MAAM,QAAS;AAChD,cAAQ,OAAO;AACf,gBAAU;AAAA,IACZ;AACA,UAAM,UAAU,CAAC,UAAsB;AACrC,YAAM,UAAU,UAAU,MAAM,MAAM;AACtC,UAAI,QAAS,SAAQ,SAAS,SAAS,OAAO,CAAC;AAAA,IACjD;AACA,UAAM,WAAW,CAAC,UAAsB;AACtC,YAAM,UAAU,UAAU,MAAM,MAAM;AACtC,UAAI,QAAS,QAAO,OAAO;AAAA,IAC7B;AACA,UAAM,QAAQ,CAAC,UAAiB;AAC9B,YAAM,UAAU,UAAU,MAAM,MAAM;AACtC,UAAI,QAAS,SAAQ,SAAS,KAAK;AAAA,IACrC;AACA,cAAU,iBAAiB,eAAe,IAAI;AAC9C,cAAU,iBAAiB,cAAc,GAAG;AAC5C,cAAU,iBAAiB,WAAW,OAAO;AAC7C,cAAU,iBAAiB,YAAY,QAAQ;AAC/C,cAAU,iBAAiB,eAAe,KAAK;AAC/C,cAAU,iBAAiB,SAAS,KAAK;AACzC,UAAM,SAAS,MAAM;AACnB,UAAI,CAAC,UAAU,OAAO,MAAM,EAAG;AAC/B,gBAAU,oBAAoB,eAAe,IAAI;AACjD,gBAAU,oBAAoB,cAAc,GAAG;AAC/C,gBAAU,oBAAoB,WAAW,OAAO;AAChD,gBAAU,oBAAoB,YAAY,QAAQ;AAClD,gBAAU,oBAAoB,eAAe,KAAK;AAClD,gBAAU,oBAAoB,SAAS,KAAK;AAC5C,UAAK,SAAS,UAAU,SAAS,MAAM,OAAO,KAAO,WAAW,UAAU,SAAS,QAAQ,OAAO,GAAI;AACpG,aAAK;AAAA,MACP;AACA,gBAAU;AAAA,IACZ;AACA,cAAU,IAAI,MAAM;AACpB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AACR,WAAK;AACL,iBAAW,UAAU,CAAC,GAAG,SAAS,EAAG,QAAO;AAC5C,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;AC5MO,SAAS,gBAAgB,SAAsC;AACpE,QAAM,EAAE,eAAe,UAAU,MAAM,UAAU,QAAQ,IAAI;AAC7D,MAAI,SAA4B;AAChC,MAAI;AACJ,MAAI;AACJ,QAAM,YAA4B,CAAC;AAEnC,WAAS,OACP,MACA,KACA,cACA,SACmB;AACnB,UAAMC,WAAU,cAAc,eAAe,UAAU;AAAA,MACrD,MAAM;AAAA,MACN,OAAO,QAAQ,aAAa;AAAA,MAC5B,aAAa;AAAA,MACb,cAAc,QAAQ;AAAA,MACtB,qBAAqB,iBAAiB,KAAK,QAAQ;AAAA,IACrD,CAAC;AACD,QAAI,QAAQ,KAAM,CAAAA,SAAQ,OAAO,YAAY,QAAQ,IAAI,CAAC;AAC1D,IAAAA,SAAQ,iBAAiB,SAAS,MAAM,IAAI,GAAG,CAAC;AAChD,cAAU;AAAA,MACR,QAAQ,OAAOA,UAAS;AAAA,QACtB,OAAO;AAAA,QACP,UAAU,cAAc,KAAK,UAAU,SAAS,QAAQ;AAAA,MAC1D,CAAC;AAAA,IACH;AACA,WAAOA;AAAA,EACT;AAEA,QAAM,UAAU,OAAO,OAAO,WAAW,SAAS,SAAS,EAAE,OAAO,SAAS,SAAS,MAAM,QAAQ,CAAC;AACrG,QAAM,UAAU,OAAO,UAAU,gBAAgB,SAAS,aAAa,cAAc,GAAG,IAAI,CAAC,GAAG;AAAA,IAC9F,WAAW;AAAA,EACb,CAAC;AACD,QAAM,SAAS,OAAO,MAAM,UAAU,SAAS,QAAQ,EAAE,OAAO,SAAS,QAAQ,MAAM,OAAO,CAAC;AAC/F,QAAM,MAAM,OAAO,OAAO,OAAO,SAAS,KAAK,EAAE,OAAO,SAAS,KAAK,MAAM,WAAW,CAAC;AACxF,QAAM,YAAY,cAAc,eAAe,QAAQ;AAAA,IACrD,OAAO;AAAA,IACP,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,eAAe;AAAA,MACf,MAAM;AAAA,MACN,cAAc,SAAS;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,WAAS,SAAe;AACtB,YAAQ;AACR,UAAM,OAAO,QAAQ,KAAK,KAAK;AAC/B,UAAM,QAAQ,YAAY,MAAM,MAAM,QAAQ;AAC9C,QAAI,QAAQ,gBAAgB,MAAM,KAAM,SAAQ,cAAc,MAAM;AACpE,YAAQ,aAAa,cAAc,MAAM,SAAS;AAElD,oBAAgB,SAAS,kBAAkB,CAAC,UAAU,CAAC,MAAM,eAAe,MAAM;AAClF,oBAAgB,QAAQ,kBAAkB,CAAC,UAAU,CAAC,MAAM,cAAc,MAAM;AAChF,oBAAgB,KAAK,kBAAkB,CAAC,UAAU,CAAC,OAAO,OAAO,MAAM,MAAM;AAAA,EAE/E;AAEA,WAAS,WAAiB;AACxB,QAAI,UAAU,OAAW,SAAQ,sBAAsB,MAAM;AAAA,EAC/D;AAEA,WAAS,cAAoB;AAC3B,QAAI,UAAU,OAAW,sBAAqB,KAAK;AACnD,YAAQ;AAAA,EACV;AAEA,WAAS,IAAI,KAAsB;AACjC,QAAI,CAAC,OAAQ;AACb,UAAM,OAAO,OAAO,KAAK;AACzB,YAAQ,KAAK;AAAA,MACX,KAAK;AACH,YAAI,UAAU,IAAI,EAAG,QAAO,SAAS,CAAC;AACtC;AAAA,MACF,KAAK;AACH,YAAI,WAAW,IAAI,EAAG,QAAO,SAAS,EAAE;AACxC;AAAA,MACF,KAAK;AACH,YAAI,SAAS,EAAG,QAAO,aAAa;AACpC;AAAA,MACF,KAAK;AACH,YAAI,OAAO,OAAO,EAAG,QAAO,IAAI;AAChC;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AAEP,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU,MAAM;AACd,oBAAc;AACd,oBAAc;AACd,kBAAY;AACZ,eAAS;AACT,UAAI,KAAM,eAAc,KAAK,SAAS,QAAQ;AAC9C,aAAO;AAAA,IACT;AAAA,IACA,UAAU;AACR,oBAAc;AACd,oBAAc;AACd,kBAAY;AACZ,eAAS;AACT,iBAAW,UAAU,UAAW,QAAO;AACvC,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;AClHA,IAAM,gBAAgB,uBAAO,IAAI,+BAA+B;AAEhE,SAAS,iBAAyB;AAChC,QAAM,QAAQ;AACd,QAAM,SAAS,MAAM,aAAa,KAAK,KAAK;AAC5C,QAAM,aAAa,IAAI;AACvB,SAAO;AACT;AAEA,IAAM,iBAAmC,CAAC,OAAO;AAGjD,SAAS,WAAW,MAAmB,MAA4B,WAAuC;AACxG,MAAI,UAAW,QAAO;AACtB,QAAM,WACJ,SAAS,aAAa,KAAK,aAAa,MAAM,IAAI,KAAK,QAAQ,QAAQ,GAAG,aAAa,MAAM;AAC/F,SAAO,YAAY;AACrB;AAGA,SAAS,aAAa,MAAkC;AACtD,QAAM,UAAU,KAAK,eAAe,QAAQ,qCAAqC;AACjF,SAAO,SAAS,aAAa,kBAAkB,MAAM,SAAS,SAAS;AACzE;AAYO,SAAS,WAAW,MAAmB,SAAoC;AAChF,QAAM,SAAS,QAAQ,UAAU;AACjC,MAAI,OAAO,WAAW,EAAG,OAAM,IAAI,MAAM,6DAA6D;AACtG,QAAM,SAAS,IAAI,OAAO;AAC1B,MAAI;AACF,WAAO,YAAY,MAAM,SAAS,QAAQ,MAAM;AAAA,EAClD,SAAS,OAAO;AACd,WAAO,MAAM;AACb,UAAM;AAAA,EACR;AACF;AAEA,SAAS,YACP,MACA,SACA,QACA,QACa;AACb,QAAM,gBAAgB,KAAK;AAC3B,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,QAAQ,eAAe;AAC7B,QAAM,WAAW,gBAAgB,QAAQ,QAAQ;AACjD,QAAM,WAAW,QAAQ,YAAY,eAAe,WAAW,SAAS;AACxE,QAAM,OAAO,WAAW,MAAM,MAAM,QAAQ,IAAI;AAChD,QAAM,WAAW,QAAQ,aAAa,SAAS,aAAa,SAAS;AAErE,SAAO,SAAS,MAAM,UAAU;AAChC,SAAO,UAAU,MAAM,sBAAsB,IAAI;AACjD,SAAO,UAAU,MAAM,gBAAgB,KAAK;AAC5C,MAAI,SAAS,YAAY;AACvB,WAAO,UAAU,MAAM,QAAQ,IAAI;AACnC,iBAAa,MAAM,OAAO,CAAC,KAAK,SAAS,MAAM;AAAA,EACjD,OAAO;AACL,WAAO,SAAS,cAAc,iBAAiB,mBAAmB;AAAA,EACpE;AAEA,QAAM,WAAW,CAAC,MAAc,UAA+B;AAC7D,QAAI,CAAC,OAAO,SAAU,QAAO,UAAU,MAAM,MAAM,KAAK;AAAA,EAC1D;AAEA,QAAM,QAAQ,cAAc,eAAe,OAAO,EAAE,OAAO,iBAAiB,CAAC;AAC7E,SAAO,MAAM,MAAM,MAAM,OAAO,CAAC;AACjC,QAAM,UAAU,cAAc,EAAE,MAAM,OAAO,IAAI,oBAAoB,KAAK,GAAG,CAAC;AAC9E,SAAO,MAAM,MAAM,QAAQ,QAAQ,CAAC;AAGpC,MAAI,WAAW;AACf,MAAI,gBAAgB;AACpB,MAAI;AACJ,SAAO,MAAM,MAAM,aAAa,aAAa,CAAC;AAE9C,QAAM,SAAS,QAAQ,SACnB,aAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,yBAAyB,KAAK;AAAA,IACvC,SAAS,QAAQ;AAAA,IACjB,SAAS,MAAM;AACb,eAAS,eAAe,OAAO,SAAS,IAAI;AAC5C,gBAAU;AACV,WAAK,QAAQ;AAAA,IACf;AAAA,IACA,iBAAiB,MAAM,KAAK,QAAQ,MAAM;AAAA,EAC5C,CAAC,IACD;AACJ,MAAI,OAAQ,QAAO,MAAM,MAAM,OAAO,QAAQ,CAAC;AAE/C,QAAM,cACJ,UAAU,QAAQ,QAAQ,cAAc,QACpC;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO,SAAS;AAAA,IAChB,SAAS,MAAM,OAAO,OAAO;AAAA,IAC7B,UAAU,CAAC,YAAY,OAAO,QAAQ,OAAO;AAAA,IAC7C,yBAAyB;AAAA,EAC3B,IACA;AACN,QAAM,oBAAkD,cAAc,CAAC,WAAW,IAAI,CAAC;AAEvF,QAAM,OAAO,WAAW;AAAA,IACtB;AAAA,IACA;AAAA,IACA,IAAI,iBAAiB,KAAK;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ,QAAQ,CAAC;AAAA,IACzB,mBAAmB,MAAM;AAAA,IACzB,YAAY,MAAM;AAAA,EACpB,CAAC;AACD,SAAO,MAAM,MAAM,KAAK,QAAQ,CAAC;AACjC,SAAO,MAAM,QAAQ,OAAO,KAAK,SAAS,MAAO,KAAK,OAAO,IAAI,OAAO,EAAE,OAAO,SAAS,KAAK,CAAE,CAAC;AAElG,QAAM,SAAS,QAAQ,UAAU,cAAc,eAAe,KAAK;AACnE,SAAO,SAAS,QAAQ,iBAAiB;AACzC,MAAI,CAAC,QAAQ,OAAQ,QAAO,MAAM,MAAM,OAAO,OAAO,CAAC;AAGvD,WAAS,eAAe,QAA2B;AACjD,QAAI,CAAC,OAAO,SAAS,cAAc,aAAa,EAAG;AACnD,UAAM,eAAe,OAAO,cAAwC,eAAe;AACnF,kBAAc,MAAM,EAAE,eAAe,KAAK,CAAC;AAC3C,QAAI,gBAAgB,cAAc,kBAAkB,aAAc;AAClE,QAAI,CAAC,KAAK,QAAQ,OAAQ,MAAK,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EACtE;AAEA,QAAM,SAAS,gBAAgB,aAAa;AAC5C,SAAO,MAAM,MAAM,OAAO,QAAQ,CAAC;AACnC,QAAM,OAAO,QAAQ,YAAY,gBAAgB,eAAe,UAAU,QAAQ,SAAS,IAAI;AAC/F,MAAI,KAAM,QAAO,MAAM,MAAM,KAAK,QAAQ,CAAC;AAC3C,QAAM,YAAY,QAAQ,YACtB,gBAAgB,eAAe,QAAQ,WAAW,CAAC,SAAS;AAC1D,aAAS,kBAAkB,OAAO,SAAS,IAAI;AAC/C,cAAU;AAAA,EACZ,CAAC,IACD;AACJ,MAAI,UAAW,QAAO,MAAM,MAAM,UAAU,QAAQ,CAAC;AACrD,QAAM,OAAO,QAAQ,WACjB,mBAAmB;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,SAAS;AAAA,IACtB,SAAS,QAAQ;AAAA,EACnB,CAAC,IACD;AACJ,MAAI,KAAM,QAAO,MAAM,MAAM,KAAK,QAAQ,CAAC;AAC3C,QAAM,YAAY,gBAAgB,EAAE,eAAe,UAAU,MAAM,UAAU,QAAQ,CAAC;AACtF,SAAO,MAAM,MAAM,UAAU,QAAQ,CAAC;AAEtC,OAAK,QAAQ,KAAK,SAAS,MAAM;AACjC,OAAK;AAAA,IACH,GAAG;AAAA,MACD,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ,EAAE,OAAO,CAAC,YAAoC,YAAY,MAAS;AAAA,IACnE;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,aAAyB;AAE7B,WAAS,gBAAsB;AAC7B,WAAO,EAAE,OAAO,KAAK,aAAa,QAAQ,KAAK,aAAa;AAAA,EAC9D;AAEA,WAAS,YAAoB;AAC3B,UAAM,MAAM,cAAc,KAAK,SAAS,IAAI;AAC5C,WAAO,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,QAAQ,MAAM,OAAO,MAAM;AAAA,EAChE;AAGA,WAAS,eAAuB;AAC9B,UAAM,UAAU,SAAS,aAAa;AACtC,WAAO,UAAU,QAAQ,cAAc,QAAQ,cAAc,QAAQ,cAAc;AAAA,EACrF;AAEA,WAAS,mBAA2B;AAClC,UAAM,YAAY,cAAc;AAChC,UAAM,SAAoB;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,MAAM,QAAQ,KAAK;AAAA,IACtC;AACA,QAAI,QAAQ,OAAO,EAAG,QAAO,cAAc,OAAO,QAAQ,sBAAsB,EAAE;AAClF,QAAI,WAAW,OAAO,GAAG;AACvB,aAAO,YACL,UAAU,QAAQ,MAAM,SAAS,CAAC,IAAI,EAAE,UAAU,cAAc,UAAU,SAAS,IAAI,EAAE,EAAE;AAAA,IAC/F;AACA,WAAO,UAAU,MAAM;AAAA,EACzB;AAEA,WAAS,YAAkB;AACzB,QAAI,MAAM,QAAQ,EAAG,MAAK,MAAM,iBAAiB,CAAC;AAAA,EACpD;AAEA,WAAS,eAAqB;AAC5B,QAAI,OAAO,SAAU;AACrB,UAAM,OAAO,cAAc;AAE3B,QAAI,KAAK,UAAU,KAAK,KAAK,WAAW,EAAG;AAC3C,iBAAa,iBAAiB;AAAA,MAC5B,gBAAgB,KAAK;AAAA,MACrB,cAAc,aAAa;AAAA,MAC3B,WAAW,UAAU;AAAA,IACvB,CAAC;AACD,aAAS,gBAAgB,UAAU;AACnC,QAAI,UAAU,CAAC,OAAO,UAAU,EAAG,QAAO,MAAM,QAAQ,QAAQ,QAAQ,iBAAiB,KAAK,MAAM,CAAC;AACrG,cAAU;AAAA,EACZ;AAEA,QAAM,sBAAsB,WAAW;AACvC,QAAM,iBAAiB,sBAAsB,IAAI,oBAAoB,MAAM,aAAa,CAAC,IAAI;AAC7F,kBAAgB,QAAQ,IAAI;AAC5B,SAAO,MAAM,MAAM,gBAAgB,WAAW,CAAC;AAE/C,MAAI,UAAU,QAAQ,QAAQ,SAAS,OAAW,QAAO,MAAM,QAAQ,OAAO,IAAI;AAClF,eAAa;AAEb,QAAM,YAAoC,aAAa,SAAS,OAAO;AACvE,QAAM,YAAY,kBAAkB;AAAA,IAClC;AAAA,IACA,aAAa;AAAA,IACb,UAAU,MAAM,KAAK,OAAO;AAAA,IAC5B,YAAY;AACV,YAAM,SAAS,cAAc;AAC7B,WAAK,MAAM,EAAE,cAAc,WAAW,KAAK,WAAW,KAAK,SAAS,SAAS,MAAM,EAAE,CAAC;AAAA,IACxF;AAAA,IACA,aAAa,MAAM,QAAQ,KAAK;AAAA,IAChC,KAAK,CAAC,QAAQ,UAAU,IAAI,GAAG;AAAA,EACjC,CAAC;AACD,YAAU,iBAAiB,WAAW,SAA0B;AAChE,SAAO,MAAM,MAAM,UAAU,oBAAoB,WAAW,SAA0B,CAAC;AAEvF,WAAS,gBAAsC;AAC7C,WAAO,EAAE,QAAQ,UAAU,OAAO,cAAc;AAAA,EAClD;AAEA,WAAS,gBAAsB;AAC7B,aAAS,iBAAiB,gBAAgB,KAAK,IAAI;AACnD,aAAS,aAAa,YAAY,cAAc,CAAC;AACjD,SAAK,QAAQ;AAAA,EACf;AAEA,WAAS,eAAqB;AAC5B,oBAAgB;AAChB,QAAI,OAAO,YAAY,CAAC,SAAU;AAClC,oBAAgB;AAChB,kBAAc;AAAA,EAChB;AAEA,WAAS,oBAA0B;AACjC,QAAI,CAAC,QAAS;AACd,YAAQ,cAAc;AACtB,oBAAgB,UAAU,QAAQ,aAAa,OAAO;AACtD,cAAU;AAAA,EACZ;AACA,SAAO,MAAM,iBAAiB;AAE9B,QAAM,aAAyB;AAAA,IAC7B,SAAS,KAAK;AAAA,IACd,UAAU,KAAK;AAAA,IACf,QAAQ,MAAM,KAAK,OAAO;AAAA,IAC1B,MAAM,CAAC,UAAU,KAAK,KAAK,KAAK;AAAA,IAChC,OAAO,CAAC,iBAAiB,KAAK,MAAM,YAAY;AAAA,IAChD,SAAS,MAAM,KAAK,QAAQ;AAAA,IAC5B,WAAW,CAAC,WAAW;AACrB,UAAI,CAAC,OAAO,SAAU,MAAK,UAAU,MAAM;AAAA,IAC7C;AAAA,EACF;AAEA,QAAM,gBAA+B;AAAA,IACnC,QAAQ,CAAC,SAAS,YAAa,OAAO,WAAW,MAAM;AAAA,IAAC,IAAI,QAAQ,OAAO,SAAS,OAAO;AAAA,IAC3F,MAAM,MAAM,QAAQ,KAAK;AAAA,EAC3B;AAEA,QAAM,eAAyC,UAAU;AAAA,IACvD,SAAS,OAAO;AAAA,IAChB,MAAM,OAAO;AAAA,IACb,QAAQ,MAAM,OAAO,OAAO;AAAA,IAC5B,SAAS,CAAC,SAAS;AACjB,UAAI,CAAC,OAAO,SAAU,QAAO,QAAQ,IAAI;AAAA,IAC3C;AAAA,IACA,QAAQ,MAAM;AACZ,UAAI,CAAC,OAAO,SAAU,QAAO,OAAO;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,kBAA+C,aAAa;AAAA,IAChE,SAAS,UAAU;AAAA,IACnB,QAAQ,MAAM,UAAU,OAAO;AAAA,IAC/B,MAAM,MAAM;AACV,UAAI,CAAC,OAAO,SAAU,WAAU,KAAK;AAAA,IACvC;AAAA,IACA,OAAO,MAAM;AACX,UAAI,OAAO,SAAU;AACrB,UAAI,UAAU,OAAO,EAAG,gBAAe,UAAU,OAAO;AACxD,gBAAU,MAAM;AAAA,IAClB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,cAAc,QAA2B;AACvC,UAAI,CAAC,OAAO,SAAU,WAAU,UAAU,MAAM;AAAA,IAClD;AAAA,IACA,WAAW;AAAA,IACX,gBAAgB,cAAc;AAC5B,UAAI,OAAO,SAAU,QAAO,MAAM;AAAA,MAAC;AACnC,wBAAkB;AAClB,gBAAU;AAAA,QACR;AAAA,QACA,eAAe,QAAQ;AAAA,UAAS,aAAa;AAAA,UAAS;AAAA,UAAU,CAAC,UAC/D,aAAa,aAAa,KAAK;AAAA,QACjC;AAAA,MACF;AACA,sBAAgB,QAAQ,aAAa,OAAO;AAC5C,mBAAa,YAAY,cAAc,CAAC;AACxC,mBAAa;AACb,YAAM,aAAa;AACnB,aAAO,MAAM;AACX,YAAI,YAAY,WAAY;AAC5B,0BAAkB;AAClB,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,YAAY,SAAS;AACnB,UAAI,OAAO,YAAY,CAAC,KAAM;AAC9B,WAAK,IAAI,OAAO;AAChB,eAAS,iBAAiB,KAAK,QAAQ,IAAI,UAAU,IAAI;AACzD,gBAAU;AAAA,IACZ;AAAA,IACA,UAAU,MAAM,eAAe;AAC7B,UAAI,CAAC,OAAO,SAAU,QAAO,IAAI,MAAM,eAAe,WAAW,CAAC;AAAA,IACpE;AAAA,IACA,aAAa,SAAS;AACpB,UAAI,OAAO,YAAY,CAAC,KAAM;AAC9B,UAAI,CAAC,WAAW,KAAK,QAAQ,EAAG,gBAAe,KAAK,OAAO;AAC3D,WAAK,SAAS,OAAO;AACrB,gBAAU;AAAA,IACZ;AAAA,IACA,YAAY,MAAM,iBAAiB;AACjC,UAAI,OAAO,SAAU;AACrB,UAAI,CAAC,MAAM;AACT,qBAAa,aAAa;AAC1B,wBAAgB;AAChB,mBAAW;AACX,wBAAgB;AAAA,MAClB,OAAO;AACL,mBAAW;AACX,cAAM,UAAU,iBAAiB,WAAW;AAE5C,YAAI,CAAC,iBAAiB,kBAAkB,QAAW;AACjD,cAAI,UAAU,EAAG,iBAAgB,WAAW,cAAc,OAAO;AAAA,cAC5D,iBAAgB;AAAA,QACvB;AAAA,MACF;AACA,oBAAc;AAAA,IAChB;AAAA,IACA,YAAY,MAAM;AAAA,IAClB,UAAU;AACR,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;AAQA,SAAS,aAAa,MAAmB,OAAc,QAAsB;AAC3E,SAAO,UAAU,MAAM,iBAAiB,KAAK;AAC7C,QAAM,SAAS,MAAY;AACzB,QAAI,OAAO,SAAU;AACrB,UAAM,WAAW,aAAa,IAAI;AAClC,QAAI,KAAK,aAAa,kBAAkB,MAAM;AAC5C,aAAO,UAAU,MAAM,oBAAoB,QAAQ;AAAA,EACvD;AACA,SAAO;AACP,QAAM,wBAAwB,WAAW;AACzC,MAAI,CAAC,sBAAuB;AAC5B,QAAM,WAAW,IAAI,sBAAsB,MAAM;AACjD,WAAS,QAAQ,KAAK,cAAc,iBAAiB;AAAA,IACnD,YAAY;AAAA,IACZ,iBAAiB,CAAC,iBAAiB,kBAAkB;AAAA,IACrD,SAAS;AAAA,EACX,CAAC;AACD,SAAO,MAAM,MAAM,SAAS,WAAW,CAAC;AAC1C;","names":["element","element"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/types.ts","../src/core/sizes.ts","../src/core/web-chrome/bottom-row.ts","../src/core/fit.ts","../src/core/zoom.ts","../src/core/keymap.ts","../src/core/appearance.ts","../src/core/messages.ts","../src/core/layout.ts","../src/core/web-chrome/top-row.ts","../src/core/web-chrome/drop.ts","../src/core/feedback/toasts.ts","../src/core/feedback/appearance.ts","../src/core/feedback/problems.ts","../src/dom/element.ts","../src/dom/feedback/appearance.ts","../src/dom/icons.ts","../src/dom/feedback/problems-popover.ts","../src/dom/feedback/toasts.ts","../src/dom/hint.ts","../src/dom/inspector.ts","../src/dom/keys.ts","../src/dom/ledger.ts","../src/dom/legend.ts","../src/dom/menu.ts","../src/dom/problems.ts","../src/dom/status.ts","../src/dom/tooltip.ts","../src/dom/web/drop-zone.ts","../src/dom/web/empty-state.ts","../src/dom/web/legal.ts","../src/dom/web/menu-groups.ts","../src/dom/web/primary.ts","../src/dom/zoom-panel.ts","../src/dom/mount.ts"],"sourcesContent":["// \"@miragon/modeler-shell\": the DOM chrome plus everything DOM-free from \"./core\".\nexport * from \"./core/index.js\";\nexport * from \"./dom/index.js\";\n","/** A point in pixels or diagram coordinates, as the context says. */\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** A rectangle; content bounds and viewboxes are in diagram coordinates. */\nexport interface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A viewbox together with the scale diagram-js shows it at (`canvas.viewbox().scale`). */\nexport interface ScaledViewbox extends Bounds {\n scale: number;\n}\n\n/** Distances in pixels from the edges of the modeler's container. */\nexport interface Insets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/**\n * The host column of guide §5.2: `ide` is a VS Code webview (later IntelliJ), `web` a Miragon web\n * app that owns its page, `embedded` a modeler inside a foreign page (designIQ, modeler-api hosts).\n */\nexport type ShellHost = \"ide\" | \"web\" | \"embedded\";\n\n/**\n * The `data-chrome` names of the chrome (guide §5.2, §13.4). The web column adds `primary`, `legal`,\n * `toasts`, `empty-state`, `drop-zone` and `problems-popover` (0.2); IDE and embedded hosts never\n * show `primary`, `legal`, `empty-state` and `drop-zone`, the IDE host never `toasts` and\n * `problems-popover`.\n */\nexport type ChromeIsland =\n | \"menu\"\n | \"palette\"\n | \"primary\"\n | \"zoom\"\n | \"problems\"\n | \"legend\"\n | \"inspector\"\n | \"status\"\n | \"legal\"\n | \"toasts\"\n | \"empty-state\"\n | \"drop-zone\"\n | \"problems-popover\";\n\nexport const CHROME_ISLANDS: readonly ChromeIsland[] = [\n \"menu\",\n \"palette\",\n \"primary\",\n \"zoom\",\n \"problems\",\n \"legend\",\n \"inspector\",\n \"status\",\n \"legal\",\n \"toasts\",\n \"empty-state\",\n \"drop-zone\",\n \"problems-popover\",\n];\n\n/** Where the palette sits: in the top row, or in the second row below it (guide §5.15). */\nexport type PaletteRow = \"top\" | \"second-row\";\n\n/**\n * What the zoom panel and the chrome keys act on. The diagram-js viewport implements it; the DOM\n * shell only talks to this interface.\n */\nexport interface ZoomTarget {\n /** The current zoom, 1 = 100 % (diagram-js `canvas.zoom()`, rounded to three decimals). */\n zoom(): number;\n /** One step on the zoom raster around the container centre (diagram-js `zoomScroll.stepZoom`). */\n stepZoom(direction: 1 | -1): void;\n /** 100 % around the container centre. Counts as a user move. */\n zoomToActual(): void;\n /** Explicit fit (button, Shift+1, command): animated unless reduced motion, makes the view automatic. */\n fit(): void;\n /** False while there is nothing to fit (the content bounds are empty). */\n canFit(): boolean;\n /**\n * Calls `listener` after every viewbox change and whenever `canFit()` may have changed, possibly\n * several times per frame. Returns the unsubscribe function.\n */\n onChange(listener: () => void): () => void;\n}\n\n/** The persisted view (VS Code `setState`): JSON-serializable. */\nexport interface ViewportState {\n viewbox: Bounds;\n /** The user zoomed or panned since the last fit; a resize no longer refits. */\n userMoved: boolean;\n}\n","/**\n * The shell dimensions of the design system (guide §5.1, `shell` group of\n * `cd-tokens.generated.json`), keyed by a readable name. Scripts use `SHELL`; CSS uses the\n * `var(--cd-shell-*)` variables the consumer vendors. A drift test pins `SHELL` to the token JSON.\n */\nexport const SHELL_TOKENS = {\n edge: \"--cd-shell-rand\",\n gap: \"--cd-shell-luecke\",\n row: \"--cd-shell-zeile\",\n target: \"--cd-shell-ziel\",\n entry: \"--cd-shell-eintrag\",\n free: \"--cd-shell-frei\",\n menuMinWidth: \"--cd-shell-menue-breite\",\n inspectorWidth: \"--cd-shell-inspector-breite\",\n fitInsetTop: \"--cd-shell-einpassen-oben\",\n fitInsetTopSecondRow: \"--cd-shell-einpassen-oben-schmal\",\n fitInsetSide: \"--cd-shell-einpassen-seite\",\n fitInsetBottom: \"--cd-shell-einpassen-unten\",\n fitInsetBottomWeb: \"--cd-shell-einpassen-unten-web\",\n narrow: \"--cd-shell-schmal\",\n veryNarrow: \"--cd-shell-sehr-schmal\",\n low: \"--cd-shell-niedrig\",\n layerIslands: \"--cd-shell-ebene-inseln\",\n layerInspector: \"--cd-shell-ebene-inspector\",\n layerTopRow: \"--cd-shell-ebene-reihe\",\n layerPopups: \"--cd-shell-ebene-aufklapper\",\n layerDialog: \"--cd-shell-ebene-dialog\",\n layerToast: \"--cd-shell-ebene-toast\",\n} as const;\n\nexport type ShellSizeName = keyof typeof SHELL_TOKENS;\n\nexport type ShellSizes = Readonly<Record<ShellSizeName, number>>;\n\n/** Pixels (layers: plain z-index numbers), equal to `parseFloat` of the token JSON values. */\nexport const SHELL: ShellSizes = {\n edge: 12,\n gap: 8,\n row: 40,\n target: 32,\n entry: 36,\n free: 64,\n menuMinWidth: 248,\n inspectorWidth: 288,\n fitInsetTop: 88,\n fitInsetTopSecondRow: 140,\n fitInsetSide: 24,\n fitInsetBottom: 64,\n fitInsetBottomWeb: 92,\n narrow: 760,\n veryNarrow: 440,\n low: 820,\n layerIslands: 20,\n layerInspector: 25,\n layerTopRow: 30,\n layerPopups: 40,\n layerDialog: 50,\n layerToast: 60,\n};\n\n// Shell sizes are pixels (\"12px\") or plain z-index numbers (\"20\"); any other unit would make\n// parseFloat silently return a number with the wrong meaning.\nconst PIXEL_OR_PLAIN_NUMBER = /^\\s*-?(?:\\d+\\.?\\d*|\\.\\d+)(?:px)?\\s*$/;\n\n/**\n * Reads the `shell` group of `cd-tokens.generated.json` (`{ \"--cd-shell-rand\": \"12px\", … }`) into\n * numbers. Throws when a size of `SHELL_TOKENS` is missing or not a number.\n */\nexport function shellSizesFromTokens(shellGroup: Readonly<Record<string, string>>): ShellSizes {\n const sizes = {} as Record<ShellSizeName, number>;\n for (const name of Object.keys(SHELL_TOKENS) as ShellSizeName[]) {\n const token = SHELL_TOKENS[name];\n const raw: unknown = Object.hasOwn(shellGroup, token) ? shellGroup[token] : undefined;\n if (raw === undefined) {\n throw new Error(`@miragon/modeler-shell: the shell token ${token} is missing`);\n }\n if (typeof raw !== \"string\" || !PIXEL_OR_PLAIN_NUMBER.test(raw)) {\n throw new Error(\n `@miragon/modeler-shell: the shell token ${token} is not a number: ${JSON.stringify(raw)}`,\n );\n }\n sizes[name] = Number.parseFloat(raw);\n }\n return sizes;\n}\n","import { SHELL } from \"../sizes.js\";\n\n/**\n * Height of one line of the web app's legal line: 13px text on a 20px line (guide §5.10). Where a\n * narrow container cannot hold it in one line, it wraps (40 for two lines) and everything stacked\n * above it rises by as much: the pill, the legend, the raised zoom panel and the fit's bottom.\n */\nexport const LEGAL_LINE_HEIGHT = 20;\n\n/** A measured legal line's height in whole lines, at least one: what the stack above it stands on. */\nexport function legalLineHeight(measured: number | undefined): number {\n if (measured === undefined || !Number.isFinite(measured) || measured <= 0) return LEGAL_LINE_HEIGHT;\n return Math.max(1, Math.round(measured / LEGAL_LINE_HEIGHT)) * LEGAL_LINE_HEIGHT;\n}\n\nexport interface BottomRowInput {\n containerWidth: number;\n /** Measured right edge of the legal line relative to the shell root; absent while it is not shown. */\n legalRight?: number | undefined;\n /** Measured width of the zoom panel (173 with a 56px readout); absent while it is not shown. */\n zoomWidth?: number | undefined;\n}\n\n/**\n * Web app, bottom row: true when the zoom panel at `right: 12px` would keep less than\n * `SHELL.gap` (8px) to the legal line at `left: 12px`. The zoom panel then stands above the legal\n * line at `bottom: 40px` (12 + 20 + 8; a wrapped line lifts it further), like the pill\n * (`data-zoom-row=\"raised\"` on the root), and the fit keeps 92px at the bottom (`FitLayout.zoomRaised`). Guide §5.10 and §5.15 do not settle\n * this collision of a narrow container; it is the shell's rule until they do.\n * False when either of the two is not shown.\n */\nexport function zoomRowRaised(input: BottomRowInput): boolean {\n const { containerWidth, legalRight, zoomWidth } = input;\n if (legalRight === undefined || zoomWidth === undefined) return false;\n const zoomLeft = containerWidth - SHELL.edge - zoomWidth;\n return legalRight + SHELL.gap > zoomLeft;\n}\n","import { SHELL } from \"./sizes.js\";\nimport { LEGAL_LINE_HEIGHT, legalLineHeight } from \"./web-chrome/bottom-row.js\";\nimport type { Bounds, Insets, PaletteRow, Point, ScaledViewbox, ShellHost, Size } from \"./types.js\";\n\n/** Fit never zooms above 100 % (guide §5.9). */\nexport const MAX_FIT_ZOOM = 1;\n\n/** Duration of the explicit, animated fit (`--cd-motion-base`). */\nexport const FIT_ANIMATION_MS = 250;\n\n/**\n * The viewbox that shows `bounds` centred in the free rectangle (`container` minus `insets`) at the\n * largest scale that fits, capped at `maxZoom`. The box has the container's aspect ratio, so\n * diagram-js's `canvas.viewbox(box)` sets exactly this view. Returns `undefined` when the container\n * is 0 × 0 or `bounds` has neither width nor height; a zero width or height scales by the other\n * dimension. Where the insets leave no free room on an axis (a container lower or narrower than\n * its chrome), that axis centres in the whole container instead.\n */\nexport function fitViewbox(\n bounds: Bounds,\n container: Size,\n insets: Insets,\n maxZoom: number = MAX_FIT_ZOOM,\n): ScaledViewbox | undefined {\n if (!(container.width > 0 && container.height > 0)) return undefined;\n const hasWidth = bounds.width > 0;\n const hasHeight = bounds.height > 0;\n if (!hasWidth && !hasHeight) return undefined;\n\n const horizontal = freeExtent(container.width, insets.left, insets.right);\n const vertical = freeExtent(container.height, insets.top, insets.bottom);\n const contentWidth = hasWidth ? bounds.width : 0;\n const contentHeight = hasHeight ? bounds.height : 0;\n const scale = Math.min(\n maxZoom,\n hasWidth ? horizontal.extent / contentWidth : Infinity,\n hasHeight ? vertical.extent / contentHeight : Infinity,\n );\n const box: ScaledViewbox = {\n x: bounds.x + contentWidth / 2 - (horizontal.start + horizontal.extent / 2) / scale,\n y: bounds.y + contentHeight / 2 - (vertical.start + vertical.extent / 2) / scale,\n width: container.width / scale,\n height: container.height / scale,\n scale,\n };\n return Object.values(box).every(Number.isFinite) && scale > 0 ? box : undefined;\n}\n\nfunction freeExtent(total: number, before: number, after: number): { start: number; extent: number } {\n const extent = total - before - after;\n return extent > 0 ? { start: before, extent } : { start: 0, extent: total };\n}\n\n/**\n * The centre of the free rectangle (`container` minus `insets`) in pixels from the container's top\n * left, where `fitViewbox` centres the content and keyboard creation places an element (guide\n * §5.5). An axis the insets leave no room on centres in the whole container, as in `fitViewbox`.\n * Returns `undefined` when the container is 0 × 0.\n */\nexport function freeRectCenter(container: Size, insets: Insets): Point | undefined {\n if (!(container.width > 0 && container.height > 0)) return undefined;\n const horizontal = freeExtent(container.width, insets.left, insets.right);\n const vertical = freeExtent(container.height, insets.top, insets.bottom);\n return {\n x: horizontal.start + horizontal.extent / 2,\n y: vertical.start + vertical.extent / 2,\n };\n}\n\n/** What is open or shown when a fit runs (guide §5.9: every fit counts what is open right now). */\nexport interface FitLayout {\n container: Size;\n host: ShellHost;\n paletteRow: PaletteRow;\n /** The problems pill is shown (only the web app reserves room for it). */\n problemsVisible: boolean;\n /**\n * Web app: the zoom panel stands above the legal line (`bottom: 40px`) because the two would\n * meet in the bottom row of a narrow container (`zoomRowRaised`); the bottom then keeps 92px as\n * with the pill.\n */\n zoomRaised?: boolean | undefined;\n /**\n * Web app: the measured height of the legal line (`LEGAL_LINE_HEIGHT`, more where a narrow\n * container wraps it); the raised bottom row stands on it. Default one line.\n */\n legalHeight?: number | undefined;\n /** Rendered width of the open legend; `undefined` when it is closed or the modeler has none. */\n legendWidth?: number | undefined;\n /**\n * The open inspector; `undefined` when closed. Above `SHELL.narrow` it is the side panel; up to it\n * a bottom sheet whose top edge (`sheetTop`, px from the container top) must be measured.\n */\n inspector?: { sheetTop?: number | undefined } | undefined;\n}\n\n/**\n * The fit insets of guide §5.9: top 88 (second row 140), sides 24, bottom 64 (web app with pill or\n * with the zoom panel raised above the legal line 92, plus 20 per extra line of a wrapped legal line),\n * right 324 with an open side inspector, left 12 + legend width + 24 with an open legend above\n * `SHELL.veryNarrow`, bottom = distance to the sheet's top edge + 12 with an open bottom sheet.\n */\nexport function fitInsets(layout: FitLayout): Insets {\n const { container, host, paletteRow, problemsVisible, zoomRaised, legendWidth, inspector } = layout;\n const raisedBottomRow = host === \"web\" && (problemsVisible || zoomRaised === true);\n const wrappedLegalLines = legalLineHeight(layout.legalHeight) - LEGAL_LINE_HEIGHT;\n const insets: Insets = {\n top: paletteRow === \"second-row\" ? SHELL.fitInsetTopSecondRow : SHELL.fitInsetTop,\n right: SHELL.fitInsetSide,\n bottom: raisedBottomRow ? SHELL.fitInsetBottomWeb + wrappedLegalLines : SHELL.fitInsetBottom,\n left: SHELL.fitInsetSide,\n };\n\n const bottomSheetOpen = inspector !== undefined && container.width <= SHELL.narrow;\n if (inspector !== undefined && !bottomSheetOpen) {\n insets.right = SHELL.edge + SHELL.inspectorWidth + SHELL.fitInsetSide;\n }\n if (bottomSheetOpen) {\n // Guide §5.11: the sheet hides zoom panel, pill and legend, so only the sheet itself counts.\n insets.bottom =\n inspector.sheetTop === undefined\n ? SHELL.fitInsetBottom\n : container.height - inspector.sheetTop + SHELL.edge;\n } else if (legendWidth !== undefined && legendWidth > 0 && container.width > SHELL.veryNarrow) {\n insets.left = SHELL.edge + legendWidth + SHELL.fitInsetSide;\n }\n return insets;\n}\n\n/** Relative tolerance of `sameView` (diagram-js rounds the transform to three decimals). */\nexport const VIEW_TOLERANCE = 1e-3;\n\n/**\n * True when two views are the same within `tolerance`: the scale and the translation in screen\n * pixels (`x · scale`, `y · scale`) agree relative to `max(1, |value|)`. Width and height are\n * ignored, so a container resize is never a difference.\n */\nexport function sameView(\n a: Pick<ScaledViewbox, \"x\" | \"y\" | \"scale\">,\n b: Pick<ScaledViewbox, \"x\" | \"y\" | \"scale\">,\n tolerance: number = VIEW_TOLERANCE,\n): boolean {\n const close = (first: number, second: number): boolean =>\n Math.abs(first - second) <= tolerance * Math.max(1, Math.abs(first), Math.abs(second));\n return (\n close(a.scale, b.scale) && close(a.x * a.scale, b.x * b.scale) && close(a.y * a.scale, b.y * b.scale)\n );\n}\n\n/**\n * The view at `progress` (0…1) between two viewboxes of the same container: the scale is\n * interpolated in log space, the centre linearly. Used per animation frame by the animated fit.\n */\nexport function interpolateViewbox(from: ScaledViewbox, to: ScaledViewbox, progress: number): ScaledViewbox {\n if (!(progress > 0)) return { ...from };\n if (progress >= 1) return { ...to };\n const linear = (start: number, end: number): number => start + (end - start) * progress;\n const scale =\n from.scale > 0 && to.scale > 0\n ? Math.exp(linear(Math.log(from.scale), Math.log(to.scale)))\n : linear(from.scale, to.scale);\n const centreX = linear(from.x + from.width / 2, to.x + to.width / 2);\n const centreY = linear(from.y + from.height / 2, to.y + to.height / 2);\n const width = linear(from.width * from.scale, to.width * to.scale) / scale;\n const height = linear(from.height * from.scale, to.height * to.scale) / scale;\n return { x: centreX - width / 2, y: centreY - height / 2, width, height, scale };\n}\n\n/** `--cd-ease`, `cubic-bezier(0.4, 0, 0.2, 1)`, as a function of time 0…1. */\nexport function easeStandard(progress: number): number {\n return STANDARD_EASING(progress);\n}\n\nconst STANDARD_EASING = cubicBezier(0.4, 0, 0.2, 1);\n\n/** A CSS `cubic-bezier(x1, y1, x2, y2)` timing function (`x1`, `x2` within 0…1, so x(t) is monotone). */\nfunction cubicBezier(x1: number, y1: number, x2: number, y2: number): (progress: number) => number {\n const polynomial = (first: number, second: number) => {\n const c = 3 * first;\n const b = 3 * (second - first) - c;\n const a = 1 - c - b;\n return {\n at: (t: number): number => ((a * t + b) * t + c) * t,\n slope: (t: number): number => (3 * a * t + 2 * b) * t + c,\n };\n };\n const curveX = polynomial(x1, x2);\n const curveY = polynomial(y1, y2);\n const precision = 1e-7;\n\n const parameterFor = (x: number): number => {\n let t = x;\n for (let iteration = 0; iteration < 8; iteration++) {\n const error = curveX.at(t) - x;\n if (Math.abs(error) < precision) return t;\n const slope = curveX.slope(t);\n if (Math.abs(slope) < 1e-6) break;\n t -= error / slope;\n if (t < 0 || t > 1) break;\n }\n // Newton left the curve or stalled on a flat stretch: bisection always converges.\n let low = 0;\n let high = 1;\n t = x;\n for (let iteration = 0; iteration < 60; iteration++) {\n const value = curveX.at(t);\n if (Math.abs(value - x) < precision) break;\n if (value < x) low = t;\n else high = t;\n t = (low + high) / 2;\n }\n return t;\n };\n\n return (progress) => {\n if (!(progress > 0)) return 0;\n if (progress >= 1) return 1;\n return curveY.at(parameterFor(progress));\n };\n}\n","import type { ShellMessages } from \"./messages.js\";\n\n/** diagram-js `ZoomScroll` RANGE (not configurable): 20 % … 400 %. */\nexport const ZOOM_MIN = 0.2;\nexport const ZOOM_MAX = 4;\n\n/** Zoom out is disabled at 20 % and below (`zoom <= 0.2 · 1.001`), so it never zooms in. */\nexport function canZoomOut(zoom: number): boolean {\n return zoom > ZOOM_MIN * 1.001;\n}\n\n/** Zoom in is disabled at 400 % (`zoom >= 4 · 0.999`). */\nexport function canZoomIn(zoom: number): boolean {\n return zoom < ZOOM_MAX * 0.999;\n}\n\n/**\n * A zoom as a whole percentage in the UI language: `Intl.NumberFormat(lang, { style: \"percent\",\n * maximumFractionDigits: 0 })`, so English \"86%\", German \"86 %\" (with U+00A0).\n */\nexport function formatPercent(zoom: number, lang: string): string {\n return numberFormat(lang, \"percent\").format(zoom);\n}\n\n/** Any other number in the chrome (\"2 problems\"), via `Intl.NumberFormat(lang)`. */\nexport function formatNumber(value: number, lang: string): string {\n return numberFormat(lang, \"decimal\").format(value);\n}\n\nconst FALLBACK_LANG = \"en\";\nconst formats = new Map<string, Intl.NumberFormat>();\n\n// The readout formats on every animation frame of a zoom, so each formatter is built once. A\n// language tag Intl rejects (an empty `lang=\"\"`, a typo) falls back to English, the shell's default\n// language, instead of breaking the chrome.\nfunction numberFormat(lang: string, style: \"percent\" | \"decimal\"): Intl.NumberFormat {\n const key = `${style}|${lang}`;\n let format = formats.get(key);\n if (!format) {\n const options: Intl.NumberFormatOptions =\n style === \"percent\" ? { style, maximumFractionDigits: 0 } : { style };\n try {\n format = new Intl.NumberFormat(lang, options);\n } catch {\n format = new Intl.NumberFormat(FALLBACK_LANG, options);\n }\n formats.set(key, format);\n }\n return format;\n}\n\nexport interface ZoomReadout {\n /** \"86%\" */\n text: string;\n /** \"Zoom to 100% (now 86%)\" */\n ariaLabel: string;\n canZoomOut: boolean;\n canZoomIn: boolean;\n}\n\n/** Everything the zoom panel shows for a zoom: readout text, its accessible name and the limits. */\nexport function zoomReadout(\n zoom: number,\n lang: string,\n messages: Pick<ShellMessages, \"zoomToActualNow\">,\n): ZoomReadout {\n const text = formatPercent(zoom, lang);\n return {\n text,\n ariaLabel: messages.zoomToActualNow(formatPercent(1, lang), text),\n canZoomOut: canZoomOut(zoom),\n canZoomIn: canZoomIn(zoom),\n };\n}\n","import type { ShellMessages } from \"./messages.js\";\nimport type { ShellHost } from \"./types.js\";\n\n/** The only keys the chrome handles (guide §5.8). */\nexport type ChromeKey = \"zoomIn\" | \"zoomOut\" | \"zoomToActual\" | \"fit\";\n\n/** The `KeyboardEvent` fields the keymap reads. */\nexport interface KeyLike {\n key: string;\n code: string;\n metaKey: boolean;\n ctrlKey: boolean;\n shiftKey: boolean;\n altKey: boolean;\n isComposing?: boolean | undefined;\n}\n\n/**\n * Which chrome key `event` is, ignoring where it was pressed:\n * - `zoomIn`: Cmd/Ctrl + `+` or `=` (by `key`, with or without Shift), or `NumpadAdd` (by `code`);\n * - `zoomOut`: Cmd/Ctrl + `-` or `_`, or `NumpadSubtract`;\n * - `zoomToActual`: Cmd/Ctrl + `0`, or `Numpad0` (also with NumLock off);\n * - `fit`: Shift + `Digit1` (by `code`, every layout) without Cmd, Ctrl or Alt.\n * Cmd/Ctrl is `metaKey || ctrlKey` on every platform; nothing matches with `altKey` (AltGr).\n */\nexport function matchChromeKey(event: KeyLike): ChromeKey | undefined {\n if (event.altKey) return undefined;\n if (isCommand(event)) {\n if (event.key === \"+\" || event.key === \"=\" || event.code === \"NumpadAdd\") return \"zoomIn\";\n if (event.key === \"-\" || event.key === \"_\" || event.code === \"NumpadSubtract\") return \"zoomOut\";\n if (event.key === \"0\" || event.code === \"Numpad0\") return \"zoomToActual\";\n return undefined;\n }\n return event.shiftKey && event.code === \"Digit1\" ? \"fit\" : undefined;\n}\n\nfunction isCommand(event: KeyLike): boolean {\n return event.metaKey || event.ctrlKey;\n}\n\n/**\n * Cmd/Ctrl + Z, Cmd/Ctrl + Shift + Z or Cmd/Ctrl + Y, without Alt (by `key`, `code` as fallback).\n * Cmd/Ctrl + Shift + Y is not redo (VS Code toggles its Debug Console with it).\n */\nexport function isUndoRedoKey(event: KeyLike): boolean {\n if (event.altKey || !isCommand(event)) return false;\n const letter = undoRedoLetter(event);\n return letter === \"z\" || (letter === \"y\" && !event.shiftKey);\n}\n\n// The produced character decides on Latin layouts (QWERTZ swaps the Y and Z keys); only where the\n// layout produces no ASCII character (Cyrillic, Greek, …) the physical key stands in.\nfunction undoRedoLetter(event: KeyLike): string | undefined {\n if (event.key.length === 1 && event.key.charCodeAt(0) < 0x80) return event.key.toLowerCase();\n if (event.code === \"KeyZ\") return \"z\";\n if (event.code === \"KeyY\") return \"y\";\n return undefined;\n}\n\n/** A text field: every input, select list and editable text (label editor, inspector, dialogs). */\nexport const TEXT_FIELD_SELECTOR =\n \"input, textarea, select, [contenteditable]:not([contenteditable='false'])\";\n\n/** Where a key was pressed, as the shell's one `keydown` listener sees it. */\nexport interface KeyContext {\n host: ShellHost;\n /** The event target matches `TEXT_FIELD_SELECTOR` or is `isContentEditable`. */\n inTextField: boolean;\n /** The shell's menu dropdown is open. */\n menuOpen: boolean;\n /** A popover or dialog (`[role=\"dialog\"]`, modal or not) is open. */\n dialogOpen: boolean;\n /** A modal dialog (`[role=\"dialog\"][aria-modal=\"true\"]`) is open: chrome keys do not act. */\n modalOpen: boolean;\n /** `event.defaultPrevented` when the listener ran: the canvas (or the modeler) handled the key. */\n defaultPrevented: boolean;\n /**\n * The web app's start screen shows (`setEmptyState(true)`): there is no diagram to zoom, so the\n * zoom keys and Shift+1 are left to the browser, which zooms the page.\n */\n startScreen?: boolean | undefined;\n}\n\nexport type KeyAction = ChromeKey | \"closeMenu\";\n\nexport interface KeyDecision {\n /** What the shell executes; `undefined` = nothing. */\n action?: KeyAction;\n preventDefault: boolean;\n stopPropagation: boolean;\n}\n\n/**\n * The key rules of guide §5.8 and §13.5 in one place:\n * 1. Escape with the menu open: `closeMenu`, prevented; in the IDE host stopped whenever the menu\n * or a dialog/popover is open. During IME composition Escape belongs to the IME: no `closeMenu`.\n * 2. Zoom keys: executed and prevented unless composing, in a text field or with a modal dialog;\n * in the IDE host always stopped, also when not executed (VS Code must never zoom the window).\n * Behind the web app's start screen untouched: the browser zooms the page (WCAG 1.4.4).\n * 3. Shift+1: `fit` under the same conditions; otherwise untouched (it types \"!\").\n * 4. IDE host, text field, undo/redo key: stopped only (the field keeps its native undo).\n * 5. IDE host, `defaultPrevented`: stopped (the canvas handled it; VS Code must not run it again).\n * Everything else passes untouched. `stopPropagation` is only ever true in the IDE host.\n */\nexport function decideKey(event: KeyLike, context: KeyContext): KeyDecision {\n const stop = context.host === \"ide\";\n const composing = event.isComposing === true;\n\n if (event.key === \"Escape\" && !event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey) {\n if (context.menuOpen && !composing) {\n return { action: \"closeMenu\", preventDefault: true, stopPropagation: stop };\n }\n if (context.menuOpen || context.dialogOpen) return { preventDefault: false, stopPropagation: stop };\n }\n\n const chromeKey = matchChromeKey(event);\n if (chromeKey !== undefined) {\n if (context.startScreen === true && !stop) return { preventDefault: false, stopPropagation: false };\n const blocked = composing || context.inTextField || context.modalOpen;\n if (!blocked) return { action: chromeKey, preventDefault: true, stopPropagation: stop };\n // Blocked zoom keys are still kept from VS Code (it would zoom the window); a blocked Shift+1\n // is a character and travels on like any other.\n return { preventDefault: false, stopPropagation: chromeKey === \"fit\" ? false : stop };\n }\n\n if (context.inTextField && isUndoRedoKey(event)) return { preventDefault: false, stopPropagation: stop };\n if (context.defaultPrevented) return { preventDefault: false, stopPropagation: stop };\n return { preventDefault: false, stopPropagation: false };\n}\n\n/** The keyboard the user sits at; decides the shortcut labels (guide §5.8). */\nexport type Platform = \"mac\" | \"other\";\n\n/** The `navigator` fields `detectPlatform` reads. */\nexport interface NavigatorLike {\n platform?: string | undefined;\n userAgentData?: { platform?: string | undefined } | undefined;\n}\n\n/**\n * `mac` when `userAgentData.platform ?? platform` matches `/mac/i`, else `other`; `other` without a\n * navigator. Read it in the webview or page itself, never from the extension host (VS Code Remote).\n */\nexport function detectPlatform(navigator?: NavigatorLike | undefined): Platform {\n // An empty userAgentData.platform means \"unknown\", not \"not a Mac\": fall back to navigator.platform.\n const platform = navigator?.userAgentData?.platform || navigator?.platform || \"\";\n return /mac/i.test(platform) ? \"mac\" : \"other\";\n}\n\n/**\n * The tooltip chip text: macOS `⌘+`, `⌘−` (U+2212), `⌘0`, `⇧1`; elsewhere `Ctrl+Plus`,\n * `Ctrl+Minus`, `Ctrl+0`, `Shift+1` with the key names of the messages table.\n */\nexport function shortcutLabel(\n key: ChromeKey,\n platform: Platform,\n keyNames: ShellMessages[\"keyNames\"],\n): string {\n if (platform === \"mac\") return MAC_SHORTCUT_LABELS[key];\n switch (key) {\n case \"zoomIn\":\n return `${keyNames.ctrl}+${keyNames.plus}`;\n case \"zoomOut\":\n return `${keyNames.ctrl}+${keyNames.minus}`;\n case \"zoomToActual\":\n return `${keyNames.ctrl}+0`;\n case \"fit\":\n return `${keyNames.shift}+1`;\n }\n}\n\n/**\n * The chip of a Cmd/Ctrl key a modeler binds itself (the web app's File entries, guide §5.4): macOS\n * `⌘O`, elsewhere `Ctrl+O` with the key name of the messages table (`Strg+O`). `key` as printed on\n * the key cap; pass the result to `FileMenuAction.shortcut` or `MenuActionEntry.shortcut`.\n */\nexport function commandKeyLabel(\n key: string,\n platform: Platform,\n keyNames: Pick<ShellMessages[\"keyNames\"], \"ctrl\">,\n): string {\n return platform === \"mac\" ? `⌘${key}` : `${keyNames.ctrl}+${key}`;\n}\n\nconst MAC_SHORTCUT_LABELS: Readonly<Record<ChromeKey, string>> = {\n zoomIn: \"⌘+\",\n zoomOut: \"⌘\\u2212\",\n zoomToActual: \"⌘0\",\n fit: \"⇧1\",\n};\n\n/**\n * The `aria-keyshortcuts` value (WAI-ARIA names): zoom in `Meta+= Meta+Plus`, zoom out `Meta+-`,\n * 100 % `Meta+0`, fit `Shift+1`; outside macOS `Control` instead of `Meta`.\n */\nexport function ariaKeyShortcuts(key: ChromeKey, platform: Platform): string {\n const command = platform === \"mac\" ? \"Meta\" : \"Control\";\n switch (key) {\n case \"zoomIn\":\n return `${command}+= ${command}+Plus`;\n case \"zoomOut\":\n return `${command}+-`;\n case \"zoomToActual\":\n return `${command}+0`;\n case \"fit\":\n return \"Shift+1\";\n }\n}\n\nconst MAC_MODIFIER_SYMBOLS: Readonly<Record<string, string>> = {\n \"⌘\": \"Meta\",\n \"⇧\": \"Shift\",\n \"⌥\": \"Alt\",\n \"⌃\": \"Control\",\n};\n\nconst MODIFIER_NAMES: Readonly<Record<string, string>> = {\n cmd: \"Meta\",\n command: \"Meta\",\n meta: \"Meta\",\n ctrl: \"Control\",\n control: \"Control\",\n strg: \"Control\",\n shift: \"Shift\",\n umschalt: \"Shift\",\n alt: \"Alt\",\n option: \"Alt\",\n opt: \"Alt\",\n};\n\nconst NAMED_KEYS: Readonly<Record<string, string>> = {\n esc: \"Escape\",\n escape: \"Escape\",\n del: \"Delete\",\n delete: \"Delete\",\n entf: \"Delete\",\n backspace: \"Backspace\",\n enter: \"Enter\",\n return: \"Enter\",\n tab: \"Tab\",\n space: \"Space\",\n home: \"Home\",\n end: \"End\",\n pageup: \"PageUp\",\n pagedown: \"PageDown\",\n arrowup: \"ArrowUp\",\n arrowdown: \"ArrowDown\",\n arrowleft: \"ArrowLeft\",\n arrowright: \"ArrowRight\",\n \"↑\": \"ArrowUp\",\n \"↓\": \"ArrowDown\",\n \"←\": \"ArrowLeft\",\n \"→\": \"ArrowRight\",\n plus: \"Plus\",\n};\n\nfunction ariaKeyName(key: string): string | undefined {\n const named = NAMED_KEYS[key.toLowerCase()];\n if (named) return named;\n if (/^f\\d{1,2}$/i.test(key)) return key.toUpperCase();\n if (key.length !== 1 || MAC_MODIFIER_SYMBOLS[key]) return undefined;\n if (key === \"+\") return \"Plus\";\n if (key === \" \") return \"Space\";\n return key.toUpperCase();\n}\n\n/**\n * The `aria-keyshortcuts` value (WAI-ARIA names, guide §5.6) for a shortcut chip label: `\"L\"` →\n * `\"L\"`, `\"⇧L\"` → `\"Shift+L\"`, `\"⌘⇧Z\"` → `\"Meta+Shift+Z\"`, `\"Ctrl+Shift+E\"` → `\"Control+Shift+E\"`,\n * `\"Del\"` → `\"Delete\"`, `\"Ctrl++\"` → `\"Control+Plus\"`. `undefined` for a label that is not one key\n * combination (`\"G then D\"`, `\"1–9\"`, empty).\n */\nexport function ariaKeyShortcutsFromLabel(label: string): string | undefined {\n let rest = label.trim();\n const modifiers: string[] = [];\n for (let symbol = MAC_MODIFIER_SYMBOLS[rest.charAt(0)]; symbol && rest.length > 1;) {\n modifiers.push(symbol);\n rest = rest.slice(1).trim();\n symbol = MAC_MODIFIER_SYMBOLS[rest.charAt(0)];\n }\n if (!rest || /\\s/.test(rest.replace(/\\s*\\+\\s*/g, \"+\"))) return undefined;\n const parts = rest.split(\"+\").map((part) => part.trim());\n let key = parts.pop() ?? \"\";\n if (key === \"\" && parts.at(-1) === \"\") {\n parts.pop();\n key = \"+\";\n }\n for (const part of parts) {\n const modifier = MODIFIER_NAMES[part.toLowerCase()];\n if (!modifier) return undefined;\n modifiers.push(modifier);\n }\n const name = ariaKeyName(key);\n return name ? [...new Set(modifiers), name].join(\"+\") : undefined;\n}\n","/** The modes a Miragon modeler can show (guide §13.3). */\nexport type Theme = \"light\" | \"dark\";\n\n/** High contrast; written as `data-cd-kontrast=\"hoch\"` on the same element as `data-cd-theme`. */\nexport type Kontrast = \"hoch\";\n\nexport interface Appearance {\n theme: Theme;\n kontrast?: Kontrast | undefined;\n}\n\n/**\n * The one appearance decision of guide §13.5: a theme the modeler cannot show is never shown\n * (`themes[0]` wins, so `[\"light\"]` stays light whatever the host requests); `kontrast` always\n * passes through. Throws when `themes` is empty.\n */\nexport function resolveAppearance(requested: Appearance, themes: readonly Theme[]): Appearance {\n const [fallback] = themes;\n if (fallback === undefined) {\n throw new Error(\n \"@miragon/modeler-shell: resolveAppearance needs at least one theme the modeler can show\",\n );\n }\n const theme = themes.includes(requested.theme) ? requested.theme : fallback;\n return withKontrast(theme, requested.kontrast);\n}\n\n// Appearances arrive through postMessage and settings, so only the one known value passes.\nfunction withKontrast(theme: Theme, kontrast: unknown): Appearance {\n return kontrast === \"hoch\" ? { theme, kontrast } : { theme };\n}\n\n/**\n * The appearance VS Code requests for `vscode.window.activeColorTheme.kind`:\n * 1 Light → light, 2 Dark → dark, 3 HighContrast → dark + hoch, 4 HighContrastLight → light + hoch;\n * any other value → light.\n */\nexport function appearanceFromColorThemeKind(kind: number): Appearance {\n switch (kind) {\n case 2:\n return { theme: \"dark\" };\n case 3:\n return { theme: \"dark\", kontrast: \"hoch\" };\n case 4:\n return { theme: \"light\", kontrast: \"hoch\" };\n default:\n return { theme: \"light\" };\n }\n}\n\n/** The values of the setting `miragon.<modeler>.colorTheme` (it ships once a modeler can show dark). */\nexport type ColorThemeSetting = \"automatic\" | \"light\" | \"dark\";\n\n/**\n * The requested appearance in an IDE host: the setting's theme unless it is `automatic` (or\n * missing), the contrast always from the color theme kind.\n */\nexport function requestedAppearance(kind: number, setting?: ColorThemeSetting | undefined): Appearance {\n const fromKind = appearanceFromColorThemeKind(kind);\n const theme = setting === \"light\" || setting === \"dark\" ? setting : fromKind.theme;\n return withKontrast(theme, fromKind.kontrast);\n}\n\n/**\n * The fallback signal inside a VS Code webview: the body classes `vscode-high-contrast-light`\n * (checked first, VS Code adds `vscode-high-contrast` to it as well), `vscode-high-contrast`,\n * `vscode-dark`, `vscode-light`. `undefined` when none is set. Never use them for styling.\n */\nexport function appearanceFromBodyClasses(classes: Iterable<string>): Appearance | undefined {\n const present = new Set(classes);\n if (present.has(\"vscode-high-contrast-light\")) return { theme: \"light\", kontrast: \"hoch\" };\n if (present.has(\"vscode-high-contrast\")) return { theme: \"dark\", kontrast: \"hoch\" };\n if (present.has(\"vscode-dark\")) return { theme: \"dark\" };\n if (present.has(\"vscode-light\")) return { theme: \"light\" };\n return undefined;\n}\n\n/**\n * VS Code's `workbench.reduceMotion` as the webview sees it: the body class `vscode-reduce-motion`\n * (the webview host page sets it). Never use it for styling; the shell mirrors it as\n * `REDUCED_MOTION_CLASS` on `<html>`.\n */\nexport function reducedMotionFromBodyClasses(classes: Iterable<string>): boolean {\n return new Set(classes).has(\"vscode-reduce-motion\");\n}\n\n/**\n * On `<html>` while the host asks for reduced motion although the OS does not (VS Code's\n * `workbench.reduceMotion`): the shell's animations stop as under `prefers-reduced-motion`, and an\n * explicit fit jumps.\n */\nexport const REDUCED_MOTION_CLASS = \"cd-shell-reduce-motion\";\n\nexport interface AppearanceAttributes {\n \"data-cd-theme\": Theme;\n \"data-cd-kontrast\"?: Kontrast;\n}\n\n/** The attributes for `<html>` (own document) or the modeler container (foreign page). */\nexport function appearanceAttributes(appearance: Appearance): AppearanceAttributes {\n return appearance.kontrast === \"hoch\"\n ? { \"data-cd-theme\": appearance.theme, \"data-cd-kontrast\": \"hoch\" }\n : { \"data-cd-theme\": appearance.theme };\n}\n","import type { ProblemSeverity } from \"./feedback/problems.js\";\nimport type { DropForbiddenReason } from \"./web-chrome/drop.js\";\n\n/**\n * Every text the shell shows or announces, in one table (guide §2, shared terms). English by\n * default; a localized modeler overrides the whole table in its language, numbers arrive already\n * formatted through `Intl` in that language.\n */\nexport interface ShellMessages {\n /** Menu trigger `aria-label` and tooltip, dropdown `aria-label`. */\n menu: string;\n /** Palette `aria-label`. */\n tools: string;\n /** `aria-label` of the focusable canvas `<svg>` (`role=\"application\"`); a modeler names its notation. */\n canvas: string;\n /** Zoom panel `aria-label`. */\n zoom: string;\n zoomOut: string;\n zoomIn: string;\n /** Tooltip of the readout, e.g. `(percent) => \"Zoom to \" + percent` with percent \"100%\". */\n zoomToActual(percent: string): string;\n /** `aria-label` of the readout: \"Zoom to 100% (now 86%)\". */\n zoomToActualNow(percent: string, now: string): string;\n fit: string;\n /** Legend title and the Model-group checkbox. */\n legend: string;\n closeLegend: string;\n /** Pill text: \"1 problem\", \"2 problems\". */\n problems(count: number, formattedCount: string): string;\n /** Pill `aria-label`: \"2 problems, 1 error\", \"2 problems, no errors\". */\n problemsLabel(count: number, errors: number, formattedCount: string, formattedErrors: string): string;\n /** Pill tooltip in the IDE host. */\n showProblems: string;\n /** Empty-file hint (guide §13.5). */\n emptyHint: string;\n insertExample: string;\n /** Status box for an invalid file; `diagram` names the notation (\"Event Storming board\"). */\n invalidFile(diagram: string): string;\n /** Key names in shortcut chips outside macOS (German: Strg, Umschalt, Plus, Minus). */\n keyNames: { ctrl: string; shift: string; plus: string; minus: string };\n\n // ---- Web host (0.2): guide §2 shared terms, §5.4, §5.7, §5.10, §8, §9 ----\n\n /** Default label and `aria-label` of the primary action (web app, top right). */\n share: string;\n /** `aria-label` of the legal line's `<nav>`. \"Impressum\" and \"Datenschutz\" are never translated (guide §2). */\n legal: string;\n /** First entry of the legal line, linking the Miragon home page: \"© 2026 Miragon GmbH\". */\n copyright(year: number): string;\n /** The description of every legal link for screen readers: they open in a new tab. */\n opensInNewTab: string;\n /** File group (web app) and the empty state's primary button. */\n newDiagram: string;\n /** File group: \"Open…\" (U+2026, it opens the browser's file dialog). */\n openFile: string;\n /** File group and the empty state's ghost button. */\n showExample: string;\n /** File group: \"Import…\". */\n importFile: string;\n /** Heading and `aria-label` of the Appearance radio group (web app with dark only, guide §13.3). */\n appearance: string;\n appearanceSystem: string;\n appearanceLight: string;\n appearanceDark: string;\n /** Title of the problems popover (web app). */\n problemsTitle: string;\n /** A row's severity for screen readers, the `aria-label` of its icon: \"Error\", \"Warning\". */\n problemSeverity(severity: ProblemSeverity): string;\n /** `aria-label` of a Close button (toasts). */\n close: string;\n /** Chip of the drop zone while a drag can be dropped (guide §9 Drag-over). */\n dropFile: string;\n /** Chip of the drop zone while the drag cannot be dropped (guide §9 Drop forbidden). */\n dropForbidden(reason: DropForbiddenReason): string;\n /** The empty state's drag-and-drop hint when the modeler has a drop zone. */\n dropHint: string;\n /** The text link after the empty state's hint that runs the File group's \"Open…\". */\n openFileLink: string;\n /**\n * Danger toast for a dropped file outside `DropZoneOptions.accept`; `accepted` is the accept list\n * joined by `Intl.ListFormat` (disjunction) in `lang`: \".storm, .json, or .txt\".\n */\n cannotOpenFile(name: string, accepted: string): string;\n}\n\n/** Every key optional; an `undefined` value keeps the default (a conditional override). */\nexport type ShellMessageOverrides = {\n [Key in Exclude<keyof ShellMessages, \"keyNames\">]?: ShellMessages[Key] | undefined;\n} & {\n keyNames?: { [Key in keyof ShellMessages[\"keyNames\"]]?: string | undefined } | undefined;\n};\n\nexport const defaultMessages: ShellMessages = {\n menu: \"Menu\",\n tools: \"Tools\",\n canvas: \"Diagram\",\n zoom: \"Zoom\",\n zoomOut: \"Zoom out\",\n zoomIn: \"Zoom in\",\n zoomToActual: (percent) => `Zoom to ${percent}`,\n zoomToActualNow: (percent, now) => `Zoom to ${percent} (now ${now})`,\n fit: \"Fit to view\",\n legend: \"Legend\",\n closeLegend: \"Close legend\",\n problems: (count, formattedCount) => `${formattedCount} ${count === 1 ? \"problem\" : \"problems\"}`,\n problemsLabel: (count, errors, formattedCount, formattedErrors) =>\n `${formattedCount} ${count === 1 ? \"problem\" : \"problems\"}, ${\n errors === 0 ? \"no errors\" : `${formattedErrors} ${errors === 1 ? \"error\" : \"errors\"}`\n }`,\n showProblems: \"Show in Problems view\",\n emptyHint: \"Pick a tool from the palette to start.\",\n insertExample: \"Insert example\",\n invalidFile: (diagram) =>\n `This file isn't a valid ${diagram} right now. The diagram shows the last valid version and is read-only until you fix the text.`,\n keyNames: { ctrl: \"Ctrl\", shift: \"Shift\", plus: \"Plus\", minus: \"Minus\" },\n share: \"Share\",\n legal: \"Legal\",\n copyright: (year) => `© ${year} Miragon GmbH`,\n opensInNewTab: \"Opens in a new tab\",\n newDiagram: \"New diagram\",\n openFile: \"Open…\",\n showExample: \"Show example\",\n importFile: \"Import…\",\n appearance: \"Appearance\",\n appearanceSystem: \"System\",\n appearanceLight: \"Light\",\n appearanceDark: \"Dark\",\n problemsTitle: \"Problems\",\n problemSeverity: (severity) => (severity === \"error\" ? \"Error\" : \"Warning\"),\n close: \"Close\",\n dropFile: \"Drop file here\",\n dropForbidden: (reason) =>\n reason === \"multiple\"\n ? \"Drop one file at a time\"\n : reason === \"dialog\"\n ? \"Close the dialog to drop a file\"\n : \"This modeler can't open this file type\",\n dropHint: \"Or drop a file here\",\n openFileLink: \"Open a file…\",\n cannotOpenFile: (name, accepted) => `Couldn't open “${name}”. Drop a ${accepted} file.`,\n};\n\n/** `defaultMessages` with `overrides` applied (`keyNames` merged key by key). */\nexport function resolveMessages(overrides?: ShellMessageOverrides | undefined): ShellMessages {\n const { keyNames, ...texts } = overrides ?? {};\n return {\n ...defaultMessages,\n ...definedEntries(texts),\n keyNames: { ...defaultMessages.keyNames, ...definedEntries(keyNames ?? {}) },\n };\n}\n\n// `{ menu: undefined }` (a spread of optional fields, a conditional override) keeps the default\n// instead of blanking the text.\nfunction definedEntries<T extends object>(partial: T): { [Key in keyof T]?: Exclude<T[Key], undefined> } {\n return Object.fromEntries(Object.entries(partial).filter(([, value]) => value !== undefined)) as {\n [Key in keyof T]?: Exclude<T[Key], undefined>;\n };\n}\n","import { SHELL } from \"./sizes.js\";\nimport type { Bounds, PaletteRow, Point, Size } from \"./types.js\";\n\n/** Free space the top row needs between the palette and a neighbouring island (guide §5.15). */\nexport const PALETTE_CLEARANCE = 16;\n\n/** Hover delay of the chrome tooltip, equal to diagram-js `HoverTooltip` `SHOW_DELAY`. */\nexport const TOOLTIP_DELAY_MS = 300;\n\n/** The status box for an invalid file shows after this long without a valid import (guide §5.12). */\nexport const INVALID_STATUS_DELAY_MS = 800;\n\nexport interface PaletteRowInput {\n containerWidth: number;\n /**\n * The palette's intrinsic border-box width (`scrollWidth` plus its borders), so the decision does\n * not flip once the second row clips it.\n */\n paletteWidth: number;\n /** Right edge of the menu trigger, relative to the shell root. */\n menuRight: number;\n /** Left edge of the primary action (web app), relative to the shell root; absent in IDE hosts. */\n primaryLeft?: number | undefined;\n}\n\n/**\n * `second-row` when the container is at most `SHELL.narrow` wide or a centred palette would keep\n * less than `PALETTE_CLEARANCE` to the menu trigger (or the primary action); `top` otherwise.\n */\nexport function decidePaletteRow(input: PaletteRowInput): PaletteRow {\n const { containerWidth, paletteWidth, menuRight, primaryLeft } = input;\n if (containerWidth <= SHELL.narrow) return \"second-row\";\n const paletteLeft = (containerWidth - paletteWidth) / 2;\n const paletteRight = (containerWidth + paletteWidth) / 2;\n if (paletteLeft < menuRight + PALETTE_CLEARANCE) return \"second-row\";\n if (primaryLeft !== undefined && paletteRight > primaryLeft - PALETTE_CLEARANCE) return \"second-row\";\n return \"top\";\n}\n\n/** The legend starts open unless the container is at most `SHELL.low` high (guide §5.10). */\nexport function legendStartsOpen(containerHeight: number): boolean {\n return containerHeight > SHELL.low;\n}\n\nexport interface TooltipPlacementInput {\n /** The hovered or focused control, relative to the shell root (horizontal centre). */\n anchor: Bounds;\n /** The island the control sits in, relative to the shell root (vertical placement). */\n island: Bounds;\n tooltip: Size;\n container: Size;\n}\n\n/**\n * The tooltip's top-left corner relative to the shell root (guide §5.6): below an island in the\n * upper half (`island.bottom + 8`: top row 60, second row 112), above one in the lower half\n * (`island.top − 8 − height`: bottom row ends at `bottom: 60px`); centred on the anchor, shifted to\n * keep `SHELL.edge` to the container's sides.\n */\nexport function placeTooltip(input: TooltipPlacementInput): Point {\n const { anchor, island, tooltip, container } = input;\n const inUpperHalf = island.y + island.height / 2 < container.height / 2;\n const y = inUpperHalf ? island.y + island.height + SHELL.gap : island.y - SHELL.gap - tooltip.height;\n const centred = anchor.x + anchor.width / 2 - tooltip.width / 2;\n const rightmost = container.width - SHELL.edge - tooltip.width;\n // In a container narrower than the tooltip plus both edges, the left edge wins.\n const x = Math.max(SHELL.edge, Math.min(centred, rightmost));\n return { x, y };\n}\n","import { PALETTE_CLEARANCE, decidePaletteRow } from \"../layout.js\";\nimport { SHELL } from \"../sizes.js\";\nimport type { PaletteRow } from \"../types.js\";\n\n/** Border-box widths of the web app's primary action, measured with and without its label. */\nexport interface PrimaryWidths {\n /** Icon and label: padding `0 16px`, icon 16px, gap 8px, label 13px/600 (guide §5.7). */\n withLabel: number;\n /** The icon alone: `SHELL.row` (40) square. */\n iconOnly: number;\n}\n\nexport interface TopRowInput {\n containerWidth: number;\n /** The palette's intrinsic border-box width, as for `decidePaletteRow`. */\n paletteWidth: number;\n /** Right edge of the menu trigger, relative to the shell root. */\n menuRight: number;\n /** The primary action at `right: 12px`; absent in IDE and embedded hosts and without one. */\n primary?: PrimaryWidths | undefined;\n}\n\nexport interface TopRow {\n paletteRow: PaletteRow;\n /** `collapsed`: the primary action shows its icon only; its `aria-label` keeps the name. */\n primaryLabel: \"shown\" | \"collapsed\";\n}\n\n/**\n * The top row of guide §5.15 with a primary action: when it gets tight, the primary action loses\n * its label first, and only then the palette moves to the second row.\n *\n * 1. Without `primary`: `decidePaletteRow` alone, label `shown`.\n * 2. With the label (`primaryLeft = containerWidth − SHELL.edge − withLabel`): palette `top` →\n * `{ top, shown }`.\n * 3. Icon only (`primaryLeft = containerWidth − SHELL.edge − iconOnly`): palette `top` →\n * `{ top, collapsed }`.\n * 4. Otherwise the palette is in the second row and the top row holds only menu trigger and\n * primary action: the label shows again when `menuRight + PALETTE_CLEARANCE` stays left of the\n * labelled button, else it stays collapsed.\n *\n * Up to `SHELL.narrow` the palette is always in the second row (step 4).\n */\nexport function decideTopRow(input: TopRowInput): TopRow {\n const { containerWidth, paletteWidth, menuRight, primary } = input;\n if (!primary) {\n return {\n paletteRow: decidePaletteRow({ containerWidth, paletteWidth, menuRight }),\n primaryLabel: \"shown\",\n };\n }\n const paletteRowBeside = (primaryWidth: number): PaletteRow =>\n decidePaletteRow({\n containerWidth,\n paletteWidth,\n menuRight,\n primaryLeft: containerWidth - SHELL.edge - primaryWidth,\n });\n if (paletteRowBeside(primary.withLabel) === \"top\") return { paletteRow: \"top\", primaryLabel: \"shown\" };\n if (paletteRowBeside(primary.iconOnly) === \"top\") return { paletteRow: \"top\", primaryLabel: \"collapsed\" };\n const labelledLeft = containerWidth - SHELL.edge - primary.withLabel;\n return {\n paletteRow: \"second-row\",\n primaryLabel: menuRight + PALETTE_CLEARANCE <= labelledLeft ? \"shown\" : \"collapsed\",\n };\n}\n","/** Why a drag cannot be dropped (guide §9 Drop forbidden); `messages.dropForbidden` words each one. */\nexport type DropForbiddenReason = \"multiple\" | \"type\" | \"dialog\";\n\n/** One entry of `DataTransfer.items` as a drag shows it (names are not readable before the drop). */\nexport interface DragItemLike {\n kind: string;\n type: string;\n}\n\nexport interface DragContext {\n /** `DropZoneOptions.accept`: extensions (\".storm\") and MIME types (\"application/json\", \"text/*\"). */\n accept: readonly string[];\n /** `DropZoneOptions.multiple`. */\n multiple: boolean;\n /** A modal dialog is open (the shell's dialog test, as for the keys). */\n dialogOpen: boolean;\n}\n\n/** What the drop zone shows for the drag over the page right now (guide §9). */\nexport type DragVerdict =\n { state: \"none\" } | { state: \"over\" } | { state: \"forbidden\"; reason: DropForbiddenReason };\n\ninterface AcceptEntries {\n extensions: readonly string[];\n mimeTypes: readonly string[];\n}\n\n/** `<input accept>` tokens: trimmed, lower case, blanks dropped; \".\" starts an extension, \"/\" marks a MIME type. */\nfunction acceptEntries(accept: readonly string[]): AcceptEntries {\n const entries = accept.map((entry) => entry.trim().toLowerCase()).filter((entry) => entry !== \"\");\n return {\n extensions: entries.filter((entry) => entry.startsWith(\".\")),\n mimeTypes: entries.filter((entry) => !entry.startsWith(\".\") && entry.includes(\"/\")),\n };\n}\n\nfunction matchesMimeType(type: string, mimeTypes: readonly string[]): boolean {\n const normalized = type.trim().toLowerCase();\n if (normalized === \"\") return false;\n return mimeTypes.some((entry) =>\n entry.endsWith(\"/*\") ? normalized.startsWith(entry.slice(0, -1)) : normalized === entry,\n );\n}\n\n/**\n * The drop zone's state for a drag (guide §9, Drag-over and Drop forbidden):\n *\n * - `none`: no item of kind `file` (a palette drag, selected text): the drop zone stays out of it.\n * - `forbidden` / `dialog`: a modal dialog is open.\n * - `forbidden` / `multiple`: more than one file and `multiple` is false.\n * - `forbidden` / `type`: `accept` lists at least one MIME type and every file item carries a\n * non-empty type that none of them matches (`type/*` wildcards included). Extensions cannot be\n * checked before the drop, and an empty type (\".storm\" has none) never forbids.\n * - `over` otherwise.\n */\nexport function dragVerdict(items: readonly DragItemLike[], context: DragContext): DragVerdict {\n const files = items.filter((item) => item.kind === \"file\");\n if (files.length === 0) return { state: \"none\" };\n if (context.dialogOpen) return { state: \"forbidden\", reason: \"dialog\" };\n if (files.length > 1 && !context.multiple) return { state: \"forbidden\", reason: \"multiple\" };\n const { mimeTypes } = acceptEntries(context.accept);\n const foreignType = (item: DragItemLike) =>\n item.type.trim() !== \"\" && !matchesMimeType(item.type, mimeTypes);\n if (mimeTypes.length > 0 && files.every(foreignType)) return { state: \"forbidden\", reason: \"type\" };\n return { state: \"over\" };\n}\n\n/**\n * A dropped file matches `accept` like `<input accept>`: an entry starting with \".\" matches the\n * end of the name (case-insensitive), an entry with \"/\" the MIME type exactly or as `type/*`; an\n * empty `accept` matches every file.\n */\nexport function acceptsFile(file: { name: string; type: string }, accept: readonly string[]): boolean {\n const { extensions, mimeTypes } = acceptEntries(accept);\n if (extensions.length === 0 && mimeTypes.length === 0) return true;\n const name = file.name.toLowerCase();\n return extensions.some((extension) => name.endsWith(extension)) || matchesMimeType(file.type, mimeTypes);\n}\n","import { SHELL } from \"../sizes.js\";\n\n/** The statuses of guide §3.3 and §9; each colours bar and dot through `--cd-ui-<status>`. */\nexport type ToastStatus = \"success\" | \"info\" | \"warning\" | \"danger\";\n\n/** A ghost button before Close (guide §8); the toast then never closes by itself. */\nexport interface ToastAction {\n label: string;\n /** Runs after the toast closed. */\n onSelect(): void;\n}\n\nexport interface ToastRequest {\n status: ToastStatus;\n /** What happened and what you can do (guide §2): \"Link copied\", \"Couldn't read this file. …\". */\n text: string;\n action?: ToastAction | undefined;\n /** Only to give a long text more time than `TOAST_DURATION_MS`; ignored with an `action`. */\n durationMs?: number | undefined;\n}\n\n/** At most three toasts at once, the newest at the bottom (guide §8). */\nexport const MAX_TOASTS = 3;\n\n/**\n * How long a toast stays without hover or focus (guide §8: about 2.8 s, errors about 5 s). A\n * warning asks you to read a sentence and act on it like an error, so it gets the error's 5 s.\n */\nexport const TOAST_DURATION_MS: Readonly<Record<ToastStatus, number>> = {\n success: 2800,\n info: 2800,\n warning: 5000,\n danger: 5000,\n};\n\n/** The stack's widest toast: `min(480px, 100cqw − 24px)` (guide §8). */\nexport const TOAST_MAX_WIDTH = 480;\n\n/**\n * Milliseconds until the toast closes by itself: `undefined` with an `action` (it never closes by\n * itself, guide §8), else `max(TOAST_DURATION_MS[status], durationMs ?? 0)`.\n */\nexport function toastLifetime(request: ToastRequest): number | undefined {\n if (request.action) return undefined;\n const requested = request.durationMs;\n // A NaN or an infinite duration would reach setTimeout, which fires at once for both.\n const longer = requested !== undefined && Number.isFinite(requested) ? requested : 0;\n return Math.max(TOAST_DURATION_MS[request.status], longer);\n}\n\n/** A toast in the stack as the eviction sees it, oldest first. */\nexport interface ToastSlot {\n id: number;\n hasAction: boolean;\n /** Hovered or holding the focus. */\n engaged: boolean;\n}\n\n/**\n * Which toast leaves when a fourth arrives (`MAX_TOASTS`): the oldest that is neither engaged nor\n * has an action, else the oldest that is not engaged, else the oldest. `undefined` while the\n * stack has room.\n */\nexport function toastToEvict(stack: readonly ToastSlot[]): number | undefined {\n if (stack.length < MAX_TOASTS) return undefined;\n const evicted =\n stack.find((slot) => !slot.engaged && !slot.hasAction) ?? stack.find((slot) => !slot.engaged) ?? stack[0];\n return evicted?.id;\n}\n\n/** Something in the bottom row the toast stack must clear, relative to the shell root. */\nexport interface BottomObstacle {\n left: number;\n right: number;\n /** Distance of its top edge from the container's bottom edge. */\n top: number;\n}\n\nexport interface ToastStackInput {\n containerWidth: number;\n /** The visible zoom panel, legal line and problems pill (not the legend card). */\n obstacles: readonly BottomObstacle[];\n /**\n * Measured width of the widest toast in the stack. The cards are sized to their text and centred\n * in the stack, so only this column can touch an obstacle; absent = the whole `toastStackWidth`.\n */\n cardWidth?: number | undefined;\n}\n\n/** `min(TOAST_MAX_WIDTH, containerWidth − 2 · SHELL.edge)`. */\nexport function toastStackWidth(containerWidth: number): number {\n return Math.max(0, Math.min(TOAST_MAX_WIDTH, containerWidth - 2 * SHELL.edge));\n}\n\n/**\n * The stack's `bottom` in px. Guide §8 anchors it at `bottom: 12px`, centred; where the column of\n * its widest card (`cardWidth`, at most `toastStackWidth`, centred) comes closer than `SHELL.gap`\n * horizontally to an obstacle, the stack stands `SHELL.gap` above the highest such obstacle instead\n * (above the legal line 40, above the zoom panel 60, above a raised zoom panel or the web pill 88).\n * Guide §8 does not settle this collision of a narrow container; it is the shell's rule until it does.\n */\nexport function toastStackBottom(input: ToastStackInput): number {\n const stackWidth = toastStackWidth(input.containerWidth);\n const { cardWidth } = input;\n const width =\n cardWidth !== undefined && Number.isFinite(cardWidth)\n ? Math.min(stackWidth, Math.max(0, cardWidth))\n : stackWidth;\n const left = (input.containerWidth - width) / 2;\n const right = left + width;\n let highest: number | undefined;\n for (const obstacle of input.obstacles) {\n const distance = Math.max(obstacle.left - right, left - obstacle.right);\n if (distance >= SHELL.gap) continue;\n highest = highest === undefined ? obstacle.top : Math.max(highest, obstacle.top);\n }\n return highest === undefined ? SHELL.edge : Math.max(SHELL.edge, highest + SHELL.gap);\n}\n","import type { Theme } from \"../appearance.js\";\n\n/** The web app's mode choice (guide §13.3): Appearance, System · Light · Dark. */\nexport type AppearanceChoice = \"system\" | \"light\" | \"dark\";\n\n/** Where the web app keeps the choice: `light` or `dark`; \"System\" removes the entry (guide §13.3). */\nexport const APPEARANCE_STORAGE_KEY = \"miragon.darstellung\";\n\n/**\n * The two `theme-color` values (guide §11, §13.3): light is the app's own value (`#335DE5`, `fest`\n * `--cd-blau` of the vendored `cd-tokens.generated.json`), dark `#1D1D1D` (`dunkel`\n * `--cd-ui-grund`). The modeler reads both from its vendored JSON; the shell keeps no colour.\n */\nexport interface ThemeColors {\n light: string;\n dark: string;\n}\n\n/** `\"light\"` and `\"dark\"` pass, everything else (a missing entry, a foreign value) is `\"system\"`. */\nexport function parseAppearanceChoice(stored: unknown): AppearanceChoice {\n return stored === \"light\" || stored === \"dark\" ? stored : \"system\";\n}\n\n/** What `<html>` and the meta tags carry for a choice. */\nexport interface DocumentMode {\n /** `data-cd-theme` on `<html>`. */\n theme: \"system\" | Theme;\n /** `<meta name=\"color-scheme\" content>`. */\n colorScheme: \"light dark\" | Theme;\n /** The `content` of the `theme-color` metas with `media=\"(prefers-color-scheme: light|dark)\"`. */\n themeColor: ThemeColors;\n}\n\n/**\n * The document mode for `choice` (guide §13.3). A modeler that cannot show dark (`themes` without\n * `\"dark\"`) is `light` whatever the choice: theme `light`, color-scheme `light`, both theme\n * colours `colors.light`. Dark-capable: `system` → theme `system`, color-scheme `light dark`,\n * `colors` as they are; `light`/`dark` → that theme and color-scheme, both theme colours the\n * chosen mode's, so the browser bar matches a fixed choice under the other system mode.\n */\nexport function documentMode(\n choice: AppearanceChoice,\n themes: readonly Theme[],\n colors: ThemeColors,\n): DocumentMode {\n if (!themes.includes(\"dark\")) return fixedMode(\"light\", colors.light);\n const parsed = parseAppearanceChoice(choice);\n if (parsed === \"system\") {\n return {\n theme: \"system\",\n colorScheme: \"light dark\",\n themeColor: { light: colors.light, dark: colors.dark },\n };\n }\n return fixedMode(parsed, colors[parsed]);\n}\n\nfunction fixedMode(theme: Theme, color: string): DocumentMode {\n return { theme, colorScheme: theme, themeColor: { light: color, dark: color } };\n}\n\nexport interface WebModeScriptOptions {\n /** The modes the modeler can show, as passed to `mountShell`. */\n themes: readonly Theme[];\n themeColors: ThemeColors;\n}\n\n/**\n * The body of the inline `<script>` in `<head>`, before the first stylesheet (guide §13.3). With\n * `themes` including `\"dark\"`: the guide's script, which reads `APPEARANCE_STORAGE_KEY` inside\n * `try`/`catch`, writes `data-cd-theme`, `color-scheme` and both `theme-color` metas for a fixed\n * choice and sets `data-cd-kontrast=\"hoch\"` under `(prefers-contrast: more)`. Light-only: the\n * contrast line alone. Plain ES5 without the modeler's bundle, so it runs before the first paint.\n */\nexport function webModeScript(options: WebModeScriptOptions): string {\n const contrast = [\n `if (window.matchMedia && window.matchMedia(${scriptString(\"(prefers-contrast: more)\")}).matches)`,\n ` document.documentElement.setAttribute(\"data-cd-kontrast\", \"hoch\");`,\n ];\n if (!options.themes.includes(\"dark\")) return contrast.join(\"\\n\");\n const { light, dark } = options.themeColors;\n return [\n \"(function () {\",\n \" var html = document.documentElement;\",\n \" var choice = null;\",\n \" try {\",\n ` choice = window.localStorage.getItem(${scriptString(APPEARANCE_STORAGE_KEY)});`,\n \" } catch (error) {}\",\n ` if (choice === \"light\" || choice === \"dark\") {`,\n ` var color = choice === \"dark\" ? ${scriptString(dark)} : ${scriptString(light)};`,\n ` html.setAttribute(\"data-cd-theme\", choice);`,\n ` var scheme = document.querySelector(\"meta[name=color-scheme]\");`,\n ` if (scheme) scheme.setAttribute(\"content\", choice);`,\n ` var metas = document.querySelectorAll(\"meta[name=theme-color]\");`,\n ` for (var index = 0; index < metas.length; index++) metas[index].setAttribute(\"content\", color);`,\n \" }\",\n ...contrast.map((line) => ` ${line}`),\n \"})();\",\n ].join(\"\\n\");\n}\n\n// The script sits inline in <head>: \"<\" never appears in a literal, so a value cannot end the\n// element (\"</script>\"), and U+2028/U+2029 are escaped because ES5 forbids them in string literals.\nfunction scriptString(value: string): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\n/**\n * The `<head>` markup the web app's `index.html` carries for its mode, as one string (for a Vite\n * `transformIndexHtml` hook or to paste): dark-capable `<meta name=\"color-scheme\" content=\"light\n * dark\">`, two `theme-color` metas with `media` and the script; light-only one `theme-color`\n * without `media` and the contrast script. `<html>` itself carries `lang` and\n * `data-cd-theme=\"<documentMode(\"system\", themes, colors).theme>\"` statically.\n */\nexport function webHeadMarkup(options: WebModeScriptOptions): string {\n const mode = documentMode(\"system\", options.themes, options.themeColors);\n const script = `<script>\\n${webModeScript(options)}\\n</script>`;\n if (mode.theme !== \"system\") {\n return [`<meta name=\"theme-color\" content=\"${escapeAttribute(mode.themeColor.light)}\">`, script].join(\n \"\\n\",\n );\n }\n return [\n `<meta name=\"color-scheme\" content=\"${escapeAttribute(mode.colorScheme)}\">`,\n `<meta name=\"theme-color\" content=\"${escapeAttribute(mode.themeColor.light)}\" media=\"(prefers-color-scheme: light)\">`,\n `<meta name=\"theme-color\" content=\"${escapeAttribute(mode.themeColor.dark)}\" media=\"(prefers-color-scheme: dark)\">`,\n script,\n ].join(\"\\n\");\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n","/** The severity of one problem; the pill and the list show `circle-x` or `triangle-alert` (guide §5.10). */\nexport type ProblemSeverity = \"error\" | \"warning\";\n\n/** One row of the web app's problems list (guide §5.10). */\nexport interface ProblemItem {\n severity: ProblemSeverity;\n /** 13px `--cd-ui-text`: \"Unknown sticky type “evnt”.\" */\n message: string;\n /** The place in 13px `--cd-ui-text-leise` below the message: \"Line 12\", \"“Order Placed”\". */\n location?: string | undefined;\n /** The diagram element a click on the row selects (`ProblemsOptions.onSelectItem`). */\n elementId?: string | undefined;\n}\n\n/** `ShellHandle.setProblems` input built from the items: count, errors and the items themselves. */\nexport function problemSummary(items: readonly ProblemItem[]): {\n count: number;\n errors: number;\n items: readonly ProblemItem[];\n} {\n const errors = items.filter((item) => item.severity === \"error\").length;\n return { count: items.length, errors, items };\n}\n","type Child = Node | string | undefined | null | false;\n\n/** `document.createElement` with attributes and children; `undefined` attribute values are skipped. */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n ownerDocument: Document,\n tag: K,\n attributes: Readonly<Record<string, string | undefined>> = {},\n ...children: Child[]\n): HTMLElementTagNameMap[K] {\n const element = ownerDocument.createElement(tag);\n for (const [name, value] of Object.entries(attributes)) {\n if (value !== undefined) element.setAttribute(name, value);\n }\n for (const child of children) {\n if (child === undefined || child === null || child === false) continue;\n element.append(child);\n }\n return element;\n}\n\n/** Sets an attribute, or removes it for `null`/`false`. */\nexport function toggleAttribute(element: Element, name: string, value: string | null | false): void {\n if (value === null || value === false) element.removeAttribute(name);\n else element.setAttribute(name, value);\n}\n\n/** The element's box relative to the padding box of `root` (the containing block of the islands). */\nexport function boxRelativeTo(element: Element, root: HTMLElement) {\n const box = element.getBoundingClientRect();\n const origin = root.getBoundingClientRect();\n return {\n x: box.left - origin.left - root.clientLeft,\n y: box.top - origin.top - root.clientTop,\n width: box.width,\n height: box.height,\n };\n}\n\n/** The accessible name a control shows without its tooltip: `aria-label`, else its text. */\nexport function accessibleName(control: Element): string {\n return (control.getAttribute(\"aria-label\") ?? control.textContent ?? \"\").trim();\n}\n\n/** True for keyboard focus (`:focus-visible`); engines without the selector count every focus. */\nexport function hasVisibleFocus(element: Element): boolean {\n try {\n return element.matches(\":focus-visible\");\n } catch {\n return true;\n }\n}\n","import {\n APPEARANCE_STORAGE_KEY,\n documentMode,\n parseAppearanceChoice,\n type AppearanceChoice,\n type Theme,\n} from \"../../core/index.js\";\nimport { createElement, toggleAttribute } from \"../element.js\";\nimport type { AppearanceHandle, StorageLike, WebAppearanceOptions } from \"../types.js\";\n\nexport interface WebAppearanceContext {\n ownerDocument: Document;\n themes: readonly Theme[];\n /** Required when `themes` includes `\"dark\"`; read only then. */\n options: WebAppearanceOptions | undefined;\n}\n\nexport interface WebAppearanceController extends AppearanceHandle {\n /** Stops following `prefers-contrast` and other tabs' `storage` events; leaves `<html>` as it is. */\n destroy(): void;\n}\n\n/** On `<html>` for one frame of a mode switch (guide §7); shell-dom.css turns every transition off. */\nexport const NO_TRANSITION_CLASS = \"cd-shell-no-transition\";\n\nconst CONTRAST_QUERY = \"(prefers-contrast: more)\";\nconst SCHEME_MEDIA: Readonly<Record<Theme, string>> = {\n light: \"(prefers-color-scheme: light)\",\n dark: \"(prefers-color-scheme: dark)\",\n};\n\n/** `change` on a media query list; Safari before 14 only has `addListener`. */\nfunction onMediaChange(query: MediaQueryList, listener: () => void): () => void {\n if (typeof query.addEventListener === \"function\") {\n query.addEventListener(\"change\", listener);\n return () => query.removeEventListener(\"change\", listener);\n }\n query.addListener(listener);\n return () => query.removeListener(listener);\n}\n\n/**\n * The web host's mode at runtime (guide §13.3), after the head script (`webModeScript`) set it\n * before the first paint. Always: mirrors `(prefers-contrast: more)` as `data-cd-kontrast=\"hoch\"`\n * on `<html>`, at once and on every change. With `\"dark\"` in `themes` (throws without `options`):\n * `choice()` is the stored choice, read once through `parseAppearanceChoice` (a blocked storage\n * reads `\"system\"`) and then kept by `setChoice` and other tabs' `storage` events, so a choice the\n * storage refused still holds for the page. `setChoice` writes it (`\"system\"` removes the key; a\n * throwing storage is ignored) and applies `documentMode` on `<html data-cd-theme>`,\n * `<meta name=\"color-scheme\">` and both `theme-color` metas (created where missing) in one task,\n * with `cd-shell-no-transition` on `<html>` until a nested `requestAnimationFrame`; a `storage`\n * event for the key applies the same way. Light-only: `choice()` is `\"system\"`, `setChoice` does\n * nothing.\n */\nexport function connectWebAppearance(context: WebAppearanceContext): WebAppearanceController {\n const { ownerDocument, themes, options } = context;\n const darkCapable = themes.includes(\"dark\");\n if (darkCapable && !options) {\n throw new Error(\n '@miragon/modeler-shell: a web modeler whose themes include \"dark\" needs the appearance option ' +\n \"({ themeColors } from its vendored cd-tokens.generated.json)\",\n );\n }\n const html = ownerDocument.documentElement;\n const view = ownerDocument.defaultView;\n const cleanups: (() => void)[] = [];\n\n const contrast = typeof view?.matchMedia === \"function\" ? view.matchMedia(CONTRAST_QUERY) : undefined;\n if (contrast) {\n const mirrorContrast = (): void => toggleAttribute(html, \"data-cd-kontrast\", contrast.matches && \"hoch\");\n mirrorContrast();\n cleanups.push(onMediaChange(contrast, mirrorContrast));\n }\n\n function destroy(): void {\n for (const cleanup of cleanups.splice(0)) cleanup();\n }\n\n if (!darkCapable || !options) {\n return { choice: () => \"system\", setChoice() {}, destroy };\n }\n const { themeColors } = options;\n\n function storage(): StorageLike | undefined {\n if (options?.storage) return options.storage;\n try {\n return globalThis.localStorage;\n } catch {\n return undefined;\n }\n }\n\n function readStored(): AppearanceChoice {\n try {\n return parseAppearanceChoice(storage()?.getItem(APPEARANCE_STORAGE_KEY));\n } catch {\n return \"system\";\n }\n }\n\n function store(choice: AppearanceChoice): void {\n try {\n const target = storage();\n if (choice === \"system\") target?.removeItem(APPEARANCE_STORAGE_KEY);\n else target?.setItem(APPEARANCE_STORAGE_KEY, choice);\n } catch {\n // Blocked or full: the choice still applies for this page.\n }\n }\n\n function nextFrame(callback: () => void): () => void {\n if (view && typeof view.requestAnimationFrame === \"function\") {\n const frame = view.requestAnimationFrame(() => callback());\n return () => view.cancelAnimationFrame(frame);\n }\n const timer = setTimeout(callback, 16);\n return () => clearTimeout(timer);\n }\n\n let cancelTransitionFrame: (() => void) | undefined;\n function allowTransitions(): void {\n cancelTransitionFrame?.();\n cancelTransitionFrame = undefined;\n html.classList.remove(NO_TRANSITION_CLASS);\n }\n cleanups.push(() => {\n if (cancelTransitionFrame) allowTransitions();\n });\n\n // The first frame still computes styles with the new colours; only after it may they fade again.\n function suspendTransitions(): void {\n cancelTransitionFrame?.();\n html.classList.add(NO_TRANSITION_CLASS);\n cancelTransitionFrame = nextFrame(() => {\n cancelTransitionFrame = nextFrame(allowTransitions);\n });\n }\n\n function metaFor(name: string, media?: string): HTMLMetaElement {\n const normalize = (value: string | null): string => (value ?? \"\").replace(/\\s+/g, \"\").toLowerCase();\n const existing = [...ownerDocument.querySelectorAll<HTMLMetaElement>(`meta[name=\"${name}\"]`)].find(\n (meta) => (media === undefined ? true : normalize(meta.getAttribute(\"media\")) === normalize(media)),\n );\n if (existing) return existing;\n const created = createElement(ownerDocument, \"meta\", { name, media });\n (ownerDocument.head ?? html).append(created);\n return created;\n }\n\n function apply(choice: AppearanceChoice): void {\n const mode = documentMode(choice, themes, themeColors);\n suspendTransitions();\n html.setAttribute(\"data-cd-theme\", mode.theme);\n metaFor(\"color-scheme\").setAttribute(\"content\", mode.colorScheme);\n metaFor(\"theme-color\", SCHEME_MEDIA.light).setAttribute(\"content\", mode.themeColor.light);\n metaFor(\"theme-color\", SCHEME_MEDIA.dark).setAttribute(\"content\", mode.themeColor.dark);\n }\n\n let current = readStored();\n\n const onStorage = (event: StorageEvent): void => {\n // A null key is a clear() of the whole storage: the choice is gone, so \"system\".\n if (event.key !== null && event.key !== APPEARANCE_STORAGE_KEY) return;\n const next = event.key === null ? \"system\" : parseAppearanceChoice(event.newValue);\n if (next === current) return;\n current = next;\n apply(next);\n };\n if (view) {\n view.addEventListener(\"storage\", onStorage);\n cleanups.push(() => view.removeEventListener(\"storage\", onStorage));\n }\n\n return {\n choice: () => current,\n setChoice(choice) {\n const next = parseAppearanceChoice(choice);\n current = next;\n store(next);\n apply(next);\n },\n destroy,\n };\n}\n","/*! @miragon/modeler-shell icon geometry\n * Lucide (lucide-static 1.59.0) @license ISC\n * Copyright (c) 2026 Lucide Icons and Contributors\n * Derived from Feather, as Lucide's LICENSE lists them: check, circle-x (x-circle), maximize,\n * minus, plus, triangle-alert (alert-triangle) and x. Feather @license MIT\n * Copyright (c) 2013-present Cole Bemis\n * Full notices: THIRD_PARTY_NOTICES.md of @miragon/modeler-shell */\n\n/*\n * The common Lucide set of the chrome (guide §5.14), inlined so the package has no icon runtime\n * dependency, copied unchanged from `icon-nodes.json`. One exception: `line-segment` (Draw) is\n * Lucide's `spline` with a straight segment between its end points, because the curve read as a\n * telephone receiver at 20px. The comment above is a legal comment, so\n * esbuild keeps it in the bundle chunk that carries this geometry.\n */\n\n/** One Lucide icon: its SVG child elements on the 24 × 24 grid. */\nexport type IconNode = ReadonlyArray<readonly [tag: string, attributes: Readonly<Record<string, string>>]>;\n\nexport type ShellIconName =\n | \"menu\"\n | \"minus\"\n | \"plus\"\n | \"maximize\"\n | \"check\"\n | \"x\"\n | \"file-plus\"\n | \"folder-open\"\n | \"import\"\n | \"file-image\"\n | \"file-code-corner\"\n | \"keyboard\"\n | \"share-2\"\n | \"circle-x\"\n | \"triangle-alert\"\n | \"square-dashed-mouse-pointer\"\n | \"hand\"\n | \"line-segment\"\n | \"unfold-horizontal\"\n | \"workflow\";\n\nexport const ICONS: Readonly<Record<ShellIconName, IconNode>> = {\n menu: [\n [\"path\", { d: \"M4 5h16\" }],\n [\"path\", { d: \"M4 12h16\" }],\n [\"path\", { d: \"M4 19h16\" }],\n ],\n minus: [[\"path\", { d: \"M5 12h14\" }]],\n plus: [\n [\"path\", { d: \"M5 12h14\" }],\n [\"path\", { d: \"M12 5v14\" }],\n ],\n maximize: [\n [\"path\", { d: \"M8 3H5a2 2 0 0 0-2 2v3\" }],\n [\"path\", { d: \"M21 8V5a2 2 0 0 0-2-2h-3\" }],\n [\"path\", { d: \"M3 16v3a2 2 0 0 0 2 2h3\" }],\n [\"path\", { d: \"M16 21h3a2 2 0 0 0 2-2v-3\" }],\n ],\n check: [[\"path\", { d: \"M20 6 9 17l-5-5\" }]],\n x: [\n [\"path\", { d: \"M18 6 6 18\" }],\n [\"path\", { d: \"m6 6 12 12\" }],\n ],\n \"file-plus\": [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n },\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\" }],\n [\"path\", { d: \"M9 15h6\" }],\n [\"path\", { d: \"M12 18v-6\" }],\n ],\n \"folder-open\": [\n [\n \"path\",\n {\n d: \"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\",\n },\n ],\n ],\n import: [\n [\"path\", { d: \"M12 3v12\" }],\n [\"path\", { d: \"m8 11 4 4 4-4\" }],\n [\"path\", { d: \"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4\" }],\n ],\n \"file-image\": [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n },\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\" }],\n [\"circle\", { cx: \"10\", cy: \"12\", r: \"2\" }],\n [\"path\", { d: \"m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22\" }],\n ],\n \"file-code-corner\": [\n [\n \"path\",\n {\n d: \"M4 12.15V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-3.35\",\n },\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\" }],\n [\"path\", { d: \"m5 16-3 3 3 3\" }],\n [\"path\", { d: \"m9 22 3-3-3-3\" }],\n ],\n keyboard: [\n [\"path\", { d: \"M10 8h.01\" }],\n [\"path\", { d: \"M12 12h.01\" }],\n [\"path\", { d: \"M14 8h.01\" }],\n [\"path\", { d: \"M16 12h.01\" }],\n [\"path\", { d: \"M18 8h.01\" }],\n [\"path\", { d: \"M6 8h.01\" }],\n [\"path\", { d: \"M7 16h10\" }],\n [\"path\", { d: \"M8 12h.01\" }],\n [\"rect\", { width: \"20\", height: \"16\", x: \"2\", y: \"4\", rx: \"2\" }],\n ],\n \"share-2\": [\n [\"circle\", { cx: \"18\", cy: \"5\", r: \"3\" }],\n [\"circle\", { cx: \"6\", cy: \"12\", r: \"3\" }],\n [\"circle\", { cx: \"18\", cy: \"19\", r: \"3\" }],\n [\"line\", { x1: \"8.59\", x2: \"15.42\", y1: \"13.51\", y2: \"17.49\" }],\n [\"line\", { x1: \"15.41\", x2: \"8.59\", y1: \"6.51\", y2: \"10.49\" }],\n ],\n \"circle-x\": [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\" }],\n [\"path\", { d: \"m15 9-6 6\" }],\n [\"path\", { d: \"m9 9 6 6\" }],\n ],\n \"triangle-alert\": [\n [\"path\", { d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\" }],\n [\"path\", { d: \"M12 9v4\" }],\n [\"path\", { d: \"M12 17h.01\" }],\n ],\n \"square-dashed-mouse-pointer\": [\n [\n \"path\",\n {\n d: \"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z\",\n },\n ],\n [\"path\", { d: \"M5 3a2 2 0 0 0-2 2\" }],\n [\"path\", { d: \"M19 3a2 2 0 0 1 2 2\" }],\n [\"path\", { d: \"M5 21a2 2 0 0 1-2-2\" }],\n [\"path\", { d: \"M9 3h1\" }],\n [\"path\", { d: \"M9 21h2\" }],\n [\"path\", { d: \"M14 3h1\" }],\n [\"path\", { d: \"M3 9v1\" }],\n [\"path\", { d: \"M21 9v2\" }],\n [\"path\", { d: \"M3 14v1\" }],\n ],\n hand: [\n [\"path\", { d: \"M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2\" }],\n [\"path\", { d: \"M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2\" }],\n [\"path\", { d: \"M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8\" }],\n [\n \"path\",\n {\n d: \"M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15\",\n },\n ],\n ],\n \"line-segment\": [\n [\"circle\", { cx: \"19\", cy: \"5\", r: \"2\" }],\n [\"circle\", { cx: \"5\", cy: \"19\", r: \"2\" }],\n [\"path\", { d: \"M6.5 17.5 17.5 6.5\" }],\n ],\n \"unfold-horizontal\": [\n [\"path\", { d: \"M16 12h6\" }],\n [\"path\", { d: \"M8 12H2\" }],\n [\"path\", { d: \"M12 2v2\" }],\n [\"path\", { d: \"M12 8v2\" }],\n [\"path\", { d: \"M12 14v2\" }],\n [\"path\", { d: \"M12 20v2\" }],\n [\"path\", { d: \"m19 15 3-3-3-3\" }],\n [\"path\", { d: \"m5 9-3 3 3 3\" }],\n ],\n workflow: [\n [\"rect\", { width: \"8\", height: \"8\", x: \"3\", y: \"3\", rx: \"2\" }],\n [\"path\", { d: \"M7 11v4a2 2 0 0 0 2 2h4\" }],\n [\"rect\", { width: \"8\", height: \"8\", x: \"13\", y: \"13\", rx: \"2\" }],\n ],\n};\n\nexport interface IconOptions {\n /** Rendered width and height in px; default 16 (chrome). */\n size?: number;\n /** Stroke width on the 24 grid; default 2.5. */\n strokeWidth?: number;\n className?: string;\n}\n\n/** Palette tool icons: 20px with stroke 2 (guide §5.5), as heavy as the 16px chrome icons. */\nexport const PALETTE_TOOL_ICON: Readonly<IconOptions> = { size: 20, strokeWidth: 2 };\n\nconst DEFAULT_SIZE = 16;\nconst DEFAULT_STROKE_WIDTH = 2.5;\nconst SVG_NAMESPACE = \"http://www.w3.org/2000/svg\";\n\n// Everything Lucide icon nodes are made of. Markup goes into innerHTML (palette entry `html`), so\n// any other element or attribute (a <script>, an onload, an href) is dropped.\nconst ICON_ELEMENTS: ReadonlySet<string> = new Set([\n \"path\",\n \"circle\",\n \"ellipse\",\n \"line\",\n \"polyline\",\n \"polygon\",\n \"rect\",\n]);\nconst GEOMETRY_ATTRIBUTES: ReadonlySet<string> = new Set([\n \"d\",\n \"cx\",\n \"cy\",\n \"r\",\n \"rx\",\n \"ry\",\n \"x\",\n \"y\",\n \"x1\",\n \"y1\",\n \"x2\",\n \"y2\",\n \"width\",\n \"height\",\n \"points\",\n]);\n\ninterface SanitizedIcon {\n root: [name: string, value: string][];\n children: [tag: string, attributes: [name: string, value: string][]][];\n}\n\nfunction positiveOr(value: number | undefined, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nfunction iconNodeOf(icon: ShellIconName | IconNode): IconNode {\n if (typeof icon !== \"string\") return icon;\n return Object.prototype.hasOwnProperty.call(ICONS, icon) ? ICONS[icon] : [];\n}\n\nfunction sanitize(icon: ShellIconName | IconNode, options: IconOptions = {}): SanitizedIcon {\n const size = String(positiveOr(options.size, DEFAULT_SIZE));\n const root: SanitizedIcon[\"root\"] = [];\n if (options.className) root.push([\"class\", options.className]);\n root.push(\n [\"width\", size],\n [\"height\", size],\n [\"viewBox\", \"0 0 24 24\"],\n [\"fill\", \"none\"],\n [\"stroke\", \"currentColor\"],\n [\"stroke-width\", String(positiveOr(options.strokeWidth, DEFAULT_STROKE_WIDTH))],\n [\"stroke-linecap\", \"round\"],\n [\"stroke-linejoin\", \"round\"],\n [\"aria-hidden\", \"true\"],\n [\"focusable\", \"false\"],\n );\n const children: SanitizedIcon[\"children\"] = [];\n for (const node of iconNodeOf(icon)) {\n const [tag, attributes] = node;\n if (!ICON_ELEMENTS.has(tag)) continue;\n const kept = Object.entries(attributes)\n .filter(([name]) => GEOMETRY_ATTRIBUTES.has(name))\n .map(([name, value]): [string, string] => [name, String(value)]);\n children.push([tag, kept]);\n }\n return { root, children };\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction attributeList(attributes: readonly [string, string][]): string {\n return attributes.map(([name, value]) => ` ${name}=\"${escapeAttribute(value)}\"`).join(\"\");\n}\n\n/**\n * Decorative inline SVG markup (`aria-hidden=\"true\"`, `focusable=\"false\"`, `fill=\"none\"`,\n * `stroke=\"currentColor\"`, round caps and joins). Only Lucide's elements and geometry attributes\n * pass, so the result is safe for `innerHTML` (palette entry `html`).\n */\nexport function iconMarkup(icon: ShellIconName | IconNode, options?: IconOptions): string {\n const { root, children } = sanitize(icon, options);\n const content = children.map(([tag, attributes]) => `<${tag}${attributeList(attributes)}/>`).join(\"\");\n return `<svg xmlns=\"${SVG_NAMESPACE}\"${attributeList(root)}>${content}</svg>`;\n}\n\n/** The same icon as an `SVGSVGElement`. */\nexport function iconElement(icon: ShellIconName | IconNode, options?: IconOptions): SVGSVGElement {\n const { root, children } = sanitize(icon, options);\n const svg = document.createElementNS(SVG_NAMESPACE, \"svg\");\n for (const [name, value] of root) svg.setAttribute(name, value);\n for (const [tag, attributes] of children) {\n const child = document.createElementNS(SVG_NAMESPACE, tag);\n for (const [name, value] of attributes) child.setAttribute(name, value);\n svg.append(child);\n }\n return svg;\n}\n","import { matchChromeKey, type ProblemItem, type ShellMessages } from \"../../core/index.js\";\nimport { createElement } from \"../element.js\";\nimport { iconElement } from \"../icons.js\";\n\nexport interface ProblemsPopoverContext {\n ownerDocument: Document;\n /** The shell root: outside clicks and the window's blur close the popover, as the menu does. */\n root: HTMLElement;\n /** The shell's layer (40): the popover lives there, like the dropdown. */\n layer: HTMLElement;\n /** The pill, its trigger: gets `aria-haspopup=\"dialog\"`, `aria-expanded` and `aria-controls`. */\n pill: HTMLButtonElement;\n /** `cd-shell-problems-N` on the popover. */\n id: string;\n /** `cd-shell-problems-title-N` on its title. */\n titleId: string;\n messages: ShellMessages;\n onSelectItem?: ((item: ProblemItem) => void) | undefined;\n}\n\nexport interface ProblemsPopover {\n /** The `<div data-chrome=\"problems-popover\" role=\"dialog\">`. */\n readonly element: HTMLElement;\n isOpen(): boolean;\n /** Open (focus on the first row, else the popover) or close (focus back to the pill). */\n toggle(): void;\n open(): void;\n close(options?: { restoreFocus?: boolean | undefined }): void;\n /** The rows; while open the list re-renders and keeps the focused row. */\n setItems(items: readonly ProblemItem[]): void;\n destroy(): void;\n}\n\ninterface Row {\n /** The same problem across `setItems`, so a re-render keeps the focus on it. */\n key: string;\n /** A `<button>` for a row with an element, else a `<div tabindex=\"-1\">`. */\n element: HTMLElement;\n}\n\nconst PILL_ATTRIBUTES = [\"aria-haspopup\", \"aria-expanded\", \"aria-controls\"] as const;\n\nfunction isPrintable(event: KeyboardEvent): boolean {\n return event.key.length === 1 && /\\S/.test(event.key) && !event.ctrlKey && !event.metaKey && !event.altKey;\n}\n\n/**\n * The web app's problems list (guide §5.10): a popover above the pill, left-aligned with it\n * (`left: 12px`, its bottom 8px above the pill's top), `role=\"dialog\"` without `aria-modal`,\n * `aria-labelledby` its title `messages.problemsTitle` (13px/600); opaque `--cd-ui-flaeche-hoch`,\n * 1px `--cd-ui-linie`, radius `md`, `shadow-3`, `min(320px, 100cqw − 24px)` wide, at most 320px\n * high with a scrolling list; pop-in 150ms from `translateY(4px)`. A row is at least 36px: the 16px\n * icon of the pill (`circle-x` in `--cd-ui-danger`, `triangle-alert` in `--cd-ui-warning`), the\n * message 13px `--cd-ui-text`, below it the location 13px `--cd-ui-text-leise`. Rows with an\n * `elementId` are buttons: a click closes the popover, returns the focus to the canvas and then\n * calls `onSelectItem(item)`; rows without one are text that still takes the focus (`tabindex=\"-1\"`),\n * so the keyboard reads every row. ↑/↓/Home/End move between all rows and scroll the focused one\n * into the list; Enter and Space act only on a row button. Escape (the popover's own handler) and\n * Tab out close it with the focus back on the pill (Tab then moves on from the pill, Shift+Tab stays\n * on it); an outside `pointerdown` (capture) and the window's blur close it without moving the\n * focus. The zoom keys keep working (not modal).\n */\nexport function createProblemsPopover(context: ProblemsPopoverContext): ProblemsPopover {\n const { ownerDocument, root, layer, pill, id, titleId, messages } = context;\n const view = ownerDocument.defaultView;\n\n const list = createElement(ownerDocument, \"ul\", { class: \"cd-shell-problems-list\", role: \"list\" });\n const element = createElement(\n ownerDocument,\n \"div\",\n {\n class: \"cd-shell-problems-popover\",\n \"data-chrome\": \"problems-popover\",\n role: \"dialog\",\n id,\n \"aria-labelledby\": titleId,\n tabindex: \"-1\",\n },\n createElement(\n ownerDocument,\n \"h2\",\n { class: \"cd-shell-problems-popover-title\", id: titleId },\n messages.problemsTitle,\n ),\n list,\n );\n element.hidden = true;\n layer.append(element);\n\n pill.setAttribute(\"aria-haspopup\", \"dialog\");\n pill.setAttribute(\"aria-expanded\", \"false\");\n pill.setAttribute(\"aria-controls\", id);\n\n let items: readonly ProblemItem[] = [];\n let rows: Row[] = [];\n let destroyed = false;\n\n const isOpen = (): boolean => !element.hidden;\n\n function keyOf(item: ProblemItem): string {\n return `${item.elementId ?? \"\"}\\u0000${item.severity}\\u0000${item.message}`;\n }\n\n function rowElement(item: ProblemItem): HTMLElement {\n const severity = item.severity === \"error\" ? \"error\" : \"warning\";\n const parts = [\n // The shape and colour of the icon carry the severity on screen, its name for screen readers.\n createElement(\n ownerDocument,\n \"span\",\n { class: \"cd-shell-problem-icon\", role: \"img\", \"aria-label\": messages.problemSeverity(severity) },\n iconElement(severity === \"error\" ? \"circle-x\" : \"triangle-alert\"),\n ),\n createElement(ownerDocument, \"span\", { class: \"cd-shell-problem-message\" }, item.message),\n item.location\n ? createElement(ownerDocument, \"span\", { class: \"cd-shell-problem-location\" }, item.location)\n : undefined,\n ];\n const attributes = { class: \"cd-shell-problem\", \"data-severity\": severity };\n if (!item.elementId) {\n const text = createElement(ownerDocument, \"div\", { ...attributes, tabindex: \"-1\" }, ...parts);\n rows.push({ key: keyOf(item), element: text });\n return text;\n }\n const button = createElement(ownerDocument, \"button\", { type: \"button\", ...attributes }, ...parts);\n button.addEventListener(\"click\", () => select(item));\n rows.push({ key: keyOf(item), element: button });\n return button;\n }\n\n function focusedRowIndex(): number {\n return rows.findIndex((row) => row.element === ownerDocument.activeElement);\n }\n\n function render(): void {\n const focusedIndex = focusedRowIndex();\n const focusedKey = rows[focusedIndex]?.key;\n rows = [];\n list.replaceChildren(...items.map((item) => createElement(ownerDocument, \"li\", {}, rowElement(item))));\n if (focusedKey === undefined || !isOpen()) return;\n const kept = rows.find((row) => row.key === focusedKey) ?? rows[Math.min(focusedIndex, rows.length - 1)];\n if (kept) focusRowElement(kept.element);\n else element.focus({ preventScroll: true });\n }\n\n // Scrolls only the list: `focus()` and `scrollIntoView()` would also scroll the shell root.\n function revealInList(row: HTMLElement): void {\n const rowBox = row.getBoundingClientRect();\n const listBox = list.getBoundingClientRect();\n if (rowBox.top < listBox.top) list.scrollTop -= listBox.top - rowBox.top;\n else if (rowBox.bottom > listBox.bottom) list.scrollTop += rowBox.bottom - listBox.bottom;\n }\n\n function focusRowElement(row: HTMLElement): void {\n row.focus({ preventScroll: true });\n revealInList(row);\n }\n\n function focusCanvas(): void {\n const canvas = root.querySelector<HTMLElement | SVGElement>(\".cd-shell-canvas svg[tabindex]\");\n canvas?.focus({ preventScroll: true });\n if ((!canvas || ownerDocument.activeElement !== canvas) && !pill.hidden)\n pill.focus({ preventScroll: true });\n }\n\n function select(item: ProblemItem): void {\n close();\n focusCanvas();\n context.onSelectItem?.(item);\n }\n\n function focusRow(index: number): void {\n if (rows.length === 0) return;\n const row = rows[(index + rows.length) % rows.length];\n if (row) focusRowElement(row.element);\n }\n\n const onOutsidePointerDown = (event: PointerEvent): void => {\n const target = event.target as Node | null;\n if (target && (element.contains(target) || pill.contains(target))) return;\n close();\n };\n\n // The focus left the document (another window, an iframe of the host page): from the user's\n // view a click outside, so the popover closes without moving the focus.\n const onWindowBlur = (): void => close();\n\n function open(): void {\n if (destroyed || isOpen()) return;\n element.hidden = false;\n pill.setAttribute(\"aria-expanded\", \"true\");\n // Capture phase: diagram-js stops pointer events on palette, context pad and canvas.\n ownerDocument.addEventListener(\"pointerdown\", onOutsidePointerDown, true);\n view?.addEventListener(\"blur\", onWindowBlur);\n list.scrollTop = 0;\n const first = rows[0];\n if (first) focusRowElement(first.element);\n else element.focus({ preventScroll: true });\n }\n\n function close(options: { restoreFocus?: boolean | undefined } = {}): void {\n if (!isOpen()) return;\n element.hidden = true;\n pill.setAttribute(\"aria-expanded\", \"false\");\n ownerDocument.removeEventListener(\"pointerdown\", onOutsidePointerDown, true);\n view?.removeEventListener(\"blur\", onWindowBlur);\n if (options.restoreFocus && !pill.hidden) pill.focus({ preventScroll: true });\n }\n\n // Keys typed in the list stop here, like the menu's: a modeler's keyboard on document (Event\n // Storming deletes the selection on Delete) must never act on them.\n function consume(event: KeyboardEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n\n element.addEventListener(\"keydown\", (event) => {\n // Zoom and fit keys still act with the popover open; the shell's key listener runs them.\n if (matchChromeKey(event)) return;\n const index = focusedRowIndex();\n switch (event.key) {\n case \"Escape\":\n consume(event);\n close({ restoreFocus: true });\n return;\n case \"Tab\": {\n // Without a row the popover itself holds the focus and is first and last at once.\n const first = index <= 0;\n const last = rows.length === 0 || index === rows.length - 1;\n if (event.shiftKey && first) {\n consume(event);\n close({ restoreFocus: true });\n } else if (!event.shiftKey && last) {\n // The browser's Tab runs after this handler from the pill, so it moves on to what follows it.\n event.stopPropagation();\n close({ restoreFocus: true });\n }\n return;\n }\n case \"ArrowDown\":\n focusRow(index + 1);\n break;\n case \"ArrowUp\":\n focusRow(index < 0 ? rows.length - 1 : index - 1);\n break;\n case \"Home\":\n focusRow(0);\n break;\n case \"End\":\n focusRow(rows.length - 1);\n break;\n case \"Enter\":\n case \" \":\n case \"Delete\":\n case \"Backspace\":\n // A row button's native click handles Enter and Space; nothing else may act on these keys.\n event.stopPropagation();\n return;\n default:\n if (isPrintable(event)) event.stopPropagation();\n return;\n }\n consume(event);\n });\n\n return {\n element,\n isOpen,\n toggle() {\n if (isOpen()) close({ restoreFocus: true });\n else open();\n },\n open,\n close,\n setItems(next) {\n items = next;\n if (!destroyed) render();\n },\n destroy() {\n if (destroyed) return;\n close();\n destroyed = true;\n for (const name of PILL_ATTRIBUTES) pill.removeAttribute(name);\n element.remove();\n },\n };\n}\n","import {\n MAX_TOASTS,\n REDUCED_MOTION_CLASS,\n toastLifetime,\n toastToEvict,\n type ShellHost,\n type ShellMessages,\n type ToastAction,\n type ToastRequest,\n type ToastSlot,\n} from \"../../core/index.js\";\nimport { createElement } from \"../element.js\";\nimport { iconElement } from \"../icons.js\";\nimport type { ToastHandle } from \"../types.js\";\n\nexport interface ToasterContext {\n ownerDocument: Document;\n /** `web`: the stack is a `popover=\"manual\"` raised on every toast; `embedded`: absolute in the root. */\n host: Exclude<ShellHost, \"ide\">;\n messages: ShellMessages;\n /** `cd-shell-toast-N`: the prefix of the ids the Close buttons' `aria-describedby` names. */\n idPrefix: string;\n /** Where the focus goes when a closing toast held it and no other toast can take it. */\n focusFallback(): void;\n /** A toast came or went: the widest card, and with it the stack's bottom, may have changed. */\n onChange?: (() => void) | undefined;\n}\n\nexport interface Toaster {\n /** The stack `<div class=\"cd-shell-toasts\" data-chrome=\"toasts\">`, always in the DOM, empty = no box. */\n readonly element: HTMLElement;\n /**\n * `<div class=\"cd-shell-live\">` with the two live regions, always rendered and visually hidden,\n * outside the stack: `role=\"status\"` (polite) and `role=\"alert\"` (danger). The shell puts it in the\n * root, where it stays in the accessibility tree while the stack is empty or closed.\n */\n readonly announcer: HTMLElement;\n show(request: ToastRequest): ToastHandle;\n /** The stack's `bottom` in px from `toastStackBottom`, set by the shell's layout pass. */\n setBottom(bottom: number): void;\n /** Rendered width of the widest card in the stack; `undefined` while it is empty. */\n widestCard(): number | undefined;\n destroy(): void;\n}\n\n/** A paused toast resumes with at least this long, so it does not vanish the moment the pointer leaves. */\nexport const TOAST_RESUME_MIN_MS = 1500;\n\n/** The leave animation runs `--cd-motion-base` (250ms); the toast goes after this even without `animationend`. */\nexport const TOAST_LEAVE_FALLBACK_MS = 400;\n\n/** The keyframes of feedback.css the leaving toast runs. */\nconst LEAVE_ANIMATION = \"cd-shell-toast-out\";\n\n/**\n * A live region announces a change of its content, not content it was created with; the text\n * arrives this long after the region was emptied, so a repeated toast is announced again too.\n */\nexport const TOAST_ANNOUNCE_DELAY_MS = 100;\n\nconst INERT_HANDLE: ToastHandle = Object.freeze({ dismiss() {} });\n\ninterface LiveToast {\n readonly id: number;\n readonly element: HTMLElement;\n readonly closeButton: HTMLButtonElement;\n readonly handle: ToastHandle;\n request: ToastRequest;\n actionButton: HTMLButtonElement | undefined;\n hovered: boolean;\n focused: boolean;\n /** Milliseconds left while paused, the whole lifetime while running; `undefined` never closes. */\n remaining: number | undefined;\n startedAt: number;\n timer: ReturnType<typeof setTimeout> | undefined;\n}\n\n/**\n * The toast stack (guide §8, §9): centred at `bottom` (`toastStackBottom`), `toastStackWidth`\n * wide, column with 8px gap, newest at the bottom, layer 60 (`--cd-shell-ebene-toast`). In the\n * web host the stack is a manual popover, re-shown on every toast, so it stays above a\n * `showModal()` dialog in the top layer; in the embedded host it is absolute inside the root.\n *\n * A toast: `<div class=\"cd-shell-toast\" data-status>`, opaque `--cd-ui-flaeche-hoch`, 1px\n * `--cd-ui-linie`, a straight 4px bar and an 8px dot in `--cd-ui-<status>`, radius `md`,\n * `shadow-3`, at least 40px high, padding `4px 4px 4px 16px`, gap 8px, text 13px/1.5\n * `--cd-ui-text`; then the action as a 32px ghost button and Close as a 32 × 32 ghost icon button\n * (Lucide `x`, `aria-label` `messages.close`, `aria-describedby` the toast's text). Slide and fade\n * in from `translateY(8px)` (250ms), out the same way; none under reduced motion.\n *\n * Screen readers hear a toast through the two persistent live regions of `announcer` (guide §8,\n * §12): its text goes to `role=\"alert\"` for danger, else to `role=\"status\"` (`aria-live=\"polite\"`),\n * `TOAST_ANNOUNCE_DELAY_MS` after the region was emptied; a repeat is announced again. The cards\n * themselves carry no live role, so nothing is read twice and re-showing the stack re-announces\n * nothing. The region empties again when its toast closes.\n *\n * Lifetime `toastLifetime(request)`, paused while hovered or focused (and resumed with at least\n * 1.5 s left); a toast with an action never closes by itself. A fourth toast evicts per\n * `toastToEvict`. A request equal to a shown toast (status and text) restarts that toast's timer\n * instead of stacking a second; its action and lifetime become the new request's, so an \"Undo\"\n * always undoes the latest change. An action click closes the toast, then runs `onSelect`. A\n * closing toast that held the focus hands it to the next toast's Close button, else\n * `focusFallback()`.\n */\nexport function createToaster(context: ToasterContext): Toaster {\n const { ownerDocument, messages } = context;\n const web = context.host === \"web\";\n const element = createElement(ownerDocument, \"div\", {\n class: \"cd-shell-toasts\",\n \"data-chrome\": \"toasts\",\n popover: web ? \"manual\" : undefined,\n });\n const liveRegion = (politeness: \"polite\" | \"assertive\"): HTMLElement =>\n createElement(ownerDocument, \"div\", {\n class: \"cd-shell-live-region\",\n \"data-live\": politeness,\n role: politeness === \"polite\" ? \"status\" : \"alert\",\n \"aria-live\": politeness,\n \"aria-atomic\": \"true\",\n });\n const politeRegion = liveRegion(\"polite\");\n const assertiveRegion = liveRegion(\"assertive\");\n const announcer = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-live\" },\n politeRegion,\n assertiveRegion,\n );\n\n /** Shown toasts, oldest first; a leaving toast is no longer one of them. */\n const live: LiveToast[] = [];\n const leaveTimers = new Set<ReturnType<typeof setTimeout>>();\n const announceTimers = new Map<HTMLElement, ReturnType<typeof setTimeout>>();\n let lastId = 0;\n let destroyed = false;\n\n function regionFor(request: ToastRequest): HTMLElement {\n return request.status === \"danger\" ? assertiveRegion : politeRegion;\n }\n\n function announce(request: ToastRequest): void {\n const region = regionFor(request);\n clearTimeout(announceTimers.get(region));\n region.textContent = \"\";\n announceTimers.set(\n region,\n setTimeout(() => {\n announceTimers.delete(region);\n if (!destroyed) region.textContent = request.text;\n }, TOAST_ANNOUNCE_DELAY_MS),\n );\n }\n\n // A closed toast's text stays out of the regions, where a screen reader's reading cursor finds it.\n function silence(request: ToastRequest): void {\n const region = regionFor(request);\n if (region.textContent === request.text) region.textContent = \"\";\n }\n\n function changed(): void {\n if (!destroyed) context.onChange?.();\n }\n\n function supportsPopover(): boolean {\n return web && typeof element.showPopover === \"function\" && typeof element.hidePopover === \"function\";\n }\n\n function popoverOpen(): boolean {\n try {\n return element.matches(\":popover-open\");\n } catch {\n return false;\n }\n }\n\n function modalOpen(): boolean {\n try {\n return ownerDocument.querySelector(\":modal\") !== null;\n } catch {\n return true;\n }\n }\n\n // Showing a popover again puts it on top of the top layer, above a modal dialog opened since. An\n // open stack without a modal dialog stays as it is: hiding it would rebuild it for screen readers.\n function raise(): void {\n if (!supportsPopover() || !element.isConnected) return;\n if (popoverOpen() && !modalOpen()) return;\n const focused = ownerDocument.activeElement as HTMLElement | null;\n const keepFocus = focused && element.contains(focused) ? focused : undefined;\n try {\n element.hidePopover();\n element.showPopover();\n } catch {\n return;\n }\n if (keepFocus && ownerDocument.activeElement !== keepFocus) keepFocus.focus({ preventScroll: true });\n }\n\n function lowerWhenEmpty(): void {\n if (element.childElementCount > 0 || !supportsPopover()) return;\n try {\n element.hidePopover();\n } catch {\n // Not shown (or never connected): nothing to hide.\n }\n }\n\n function engaged(toast: LiveToast): boolean {\n return toast.hovered || toast.focused;\n }\n\n function stopTimer(toast: LiveToast): void {\n clearTimeout(toast.timer);\n toast.timer = undefined;\n }\n\n function runTimer(toast: LiveToast): void {\n stopTimer(toast);\n if (toast.remaining === undefined || engaged(toast)) return;\n toast.startedAt = Date.now();\n toast.timer = setTimeout(() => close(toast), toast.remaining);\n }\n\n function pause(toast: LiveToast): void {\n if (toast.timer === undefined) return;\n stopTimer(toast);\n if (toast.remaining !== undefined) {\n toast.remaining = Math.max(0, toast.remaining - (Date.now() - toast.startedAt));\n }\n }\n\n function setEngagement(toast: LiveToast, hovered: boolean, focused: boolean): void {\n if (!live.includes(toast)) return;\n const wasEngaged = engaged(toast);\n toast.hovered = hovered;\n toast.focused = focused;\n if (engaged(toast) === wasEngaged) return;\n if (wasEngaged) {\n if (toast.remaining !== undefined) toast.remaining = Math.max(toast.remaining, TOAST_RESUME_MIN_MS);\n runTimer(toast);\n } else {\n pause(toast);\n }\n }\n\n function reducedMotion(): boolean {\n if (ownerDocument.documentElement.classList.contains(REDUCED_MOTION_CLASS)) return true;\n const view = ownerDocument.defaultView;\n return (\n typeof view?.matchMedia === \"function\" && view.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n );\n }\n\n function removeElement(toastElement: HTMLElement): void {\n toastElement.remove();\n lowerWhenEmpty();\n changed();\n }\n\n function leave(toastElement: HTMLElement): void {\n toastElement.setAttribute(\"data-leaving\", \"\");\n // Nothing on its way out takes a click or the focus.\n toastElement.inert = true;\n if (reducedMotion()) {\n removeElement(toastElement);\n return;\n }\n let done = false;\n const finish = (): void => {\n if (done) return;\n done = true;\n clearTimeout(fallback);\n leaveTimers.delete(fallback);\n removeElement(toastElement);\n };\n toastElement.addEventListener(\"animationend\", (event) => {\n if (event.target === toastElement && event.animationName === LEAVE_ANIMATION) finish();\n });\n const fallback = setTimeout(finish, TOAST_LEAVE_FALLBACK_MS);\n leaveTimers.add(fallback);\n }\n\n function close(toast: LiveToast): void {\n const index = live.indexOf(toast);\n if (index < 0) return;\n live.splice(index, 1);\n stopTimer(toast);\n silence(toast.request);\n const heldFocus = toast.element.contains(ownerDocument.activeElement);\n if (heldFocus) {\n const next = live[index] ?? live[index - 1];\n if (next) next.closeButton.focus({ preventScroll: true });\n else context.focusFallback();\n }\n leave(toast.element);\n }\n\n function setAction(toast: LiveToast, action: ToastAction | undefined): void {\n const previous = toast.actionButton;\n const hadFocus = previous !== undefined && ownerDocument.activeElement === previous;\n previous?.remove();\n toast.actionButton = undefined;\n if (action) {\n const button = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-toast-action cd-shell-button\", \"data-variant\": \"ghost\" },\n action.label,\n );\n button.addEventListener(\"click\", () => {\n close(toast);\n action.onSelect();\n });\n toast.closeButton.before(button);\n toast.actionButton = button;\n }\n if (hadFocus) (toast.actionButton ?? toast.closeButton).focus({ preventScroll: true });\n }\n\n function slotOf(toast: LiveToast): ToastSlot {\n return { id: toast.id, hasAction: toast.request.action !== undefined, engaged: engaged(toast) };\n }\n\n function render(request: ToastRequest): LiveToast {\n const id = ++lastId;\n const textId = `${context.idPrefix}-${id}`;\n // Three Close buttons in a stack are told apart by the text of their toast.\n const closeButton = createElement(\n ownerDocument,\n \"button\",\n {\n type: \"button\",\n class: \"cd-shell-toast-close\",\n \"aria-label\": messages.close,\n \"aria-describedby\": textId,\n },\n iconElement(\"x\"),\n );\n const toastElement = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-toast\", \"data-status\": request.status },\n createElement(ownerDocument, \"span\", { class: \"cd-shell-toast-dot\", \"aria-hidden\": \"true\" }),\n createElement(ownerDocument, \"span\", { class: \"cd-shell-toast-text\", id: textId }, request.text),\n closeButton,\n );\n const toast: LiveToast = {\n id,\n element: toastElement,\n closeButton,\n handle: Object.freeze({ dismiss: () => close(toast) }),\n request,\n actionButton: undefined,\n hovered: false,\n focused: false,\n remaining: toastLifetime(request),\n startedAt: Date.now(),\n timer: undefined,\n };\n setAction(toast, request.action);\n closeButton.addEventListener(\"click\", () => close(toast));\n toastElement.addEventListener(\"mouseenter\", () => setEngagement(toast, true, toast.focused));\n toastElement.addEventListener(\"mouseleave\", () => setEngagement(toast, false, toast.focused));\n toastElement.addEventListener(\"focusin\", () => setEngagement(toast, toast.hovered, true));\n toastElement.addEventListener(\"focusout\", (event) =>\n setEngagement(toast, toast.hovered, toastElement.contains(event.relatedTarget as Node | null)),\n );\n return toast;\n }\n\n function show(request: ToastRequest): ToastHandle {\n if (destroyed) return INERT_HANDLE;\n const same = live.find(\n (toast) => toast.request.status === request.status && toast.request.text === request.text,\n );\n if (same) {\n same.request = request;\n setAction(same, request.action);\n same.remaining = toastLifetime(request);\n runTimer(same);\n raise();\n announce(request);\n changed();\n return same.handle;\n }\n while (live.length >= MAX_TOASTS) {\n const evictedId = toastToEvict(live.map(slotOf));\n const evicted = live.find((toast) => toast.id === evictedId) ?? live[0];\n if (!evicted) break;\n close(evicted);\n }\n const toast = render(request);\n live.push(toast);\n element.append(toast.element);\n raise();\n runTimer(toast);\n announce(request);\n changed();\n return toast.handle;\n }\n\n return {\n element,\n announcer,\n show,\n setBottom(bottom) {\n element.style.bottom = `${bottom}px`;\n },\n widestCard() {\n let widest: number | undefined;\n for (const card of element.children) {\n const width = card.getBoundingClientRect().width;\n if (width > 0) widest = Math.max(widest ?? 0, width);\n }\n return widest;\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n for (const toast of live.splice(0)) stopTimer(toast);\n for (const timer of leaveTimers) clearTimeout(timer);\n leaveTimers.clear();\n for (const timer of announceTimers.values()) clearTimeout(timer);\n announceTimers.clear();\n element.remove();\n announcer.remove();\n },\n };\n}\n","import type { Insets, ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport type { EmptyHintOptions } from \"./types.js\";\n\nexport interface EmptyHint {\n readonly element: HTMLElement;\n isShown(): boolean;\n setShown(shown: boolean): void;\n /** Centres the hint in the free rectangle of the fit (guide §13.5). */\n place(insets: Insets): void;\n destroy(): void;\n}\n\nexport function createEmptyHint(\n ownerDocument: Document,\n messages: ShellMessages,\n options: EmptyHintOptions,\n): EmptyHint {\n const { onInsertExample } = options;\n const action = onInsertExample\n ? createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-hint-action\" },\n messages.insertExample,\n )\n : undefined;\n action?.addEventListener(\"click\", () => onInsertExample?.());\n const element = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-hint\" },\n createElement(ownerDocument, \"p\", { class: \"cd-shell-hint-text\" }, messages.emptyHint),\n action,\n );\n element.hidden = true;\n\n return {\n element,\n isShown: () => !element.hidden,\n setShown(shown) {\n element.hidden = !shown;\n },\n place({ top, right, bottom, left }) {\n element.style.inset = `${top}px ${right}px ${bottom}px ${left}px`;\n },\n destroy() {\n element.remove();\n },\n };\n}\n","import { createElement } from \"./element.js\";\nimport type { InspectorHandle, InspectorOptions } from \"./types.js\";\n\nexport interface InspectorController extends InspectorHandle {\n destroy(): void;\n}\n\nexport function createInspector(\n ownerDocument: Document,\n options: InspectorOptions,\n onChange: (open: boolean) => void,\n): InspectorController {\n const element = createElement(ownerDocument, \"aside\", {\n class: \"cd-shell-inspector\",\n \"data-chrome\": \"inspector\",\n \"aria-label\": options.label,\n });\n element.hidden = true;\n\n function setOpen(open: boolean): void {\n if (open === !element.hidden) return;\n element.hidden = !open;\n onChange(open);\n }\n\n return {\n element,\n isOpen: () => !element.hidden,\n open: () => setOpen(true),\n close: () => setOpen(false),\n destroy() {\n element.remove();\n },\n };\n}\n","import { TEXT_FIELD_SELECTOR, decideKey, type ChromeKey, type ShellHost } from \"../core/index.js\";\n\nexport interface KeyListenerContext {\n host: ShellHost;\n /** Where dialogs and popovers count: the document in an own document, else the shell root. */\n dialogScope: ParentNode;\n menuOpen(): boolean;\n /** The web app's start screen shows: the zoom keys belong to the browser (`KeyContext.startScreen`). */\n startScreen?: (() => boolean) | undefined;\n closeMenu(): void;\n hideTooltip(): void;\n run(key: ChromeKey): void;\n}\n\nfunction isTextField(target: EventTarget | null): boolean {\n if (!target || typeof (target as Element).closest !== \"function\") return false;\n const element = target as HTMLElement;\n return element.isContentEditable === true || element.closest(TEXT_FIELD_SELECTOR) !== null;\n}\n\n// A dialog a modeler hides through CSS (a class with display: none) is closed as well.\nfunction isShown(element: Element): boolean {\n if (element.localName === \"dialog\" && !element.hasAttribute(\"open\")) return false;\n if (element.closest(\"[hidden]\")) return false;\n return (\n typeof element.checkVisibility !== \"function\" || element.checkVisibility({ visibilityProperty: true })\n );\n}\n\nfunction isModal(element: Element): boolean {\n if (element.getAttribute(\"aria-modal\") === \"true\") return true;\n try {\n return element.matches(\":modal\");\n } catch {\n return false;\n }\n}\n\nfunction openDialogs(scope: ParentNode): Element[] {\n return [...scope.querySelectorAll('[role=\"dialog\"], [role=\"alertdialog\"], dialog')].filter(isShown);\n}\n\n/** A shown modal dialog in `scope`, by the keys' own test (the drop zone forbids drops meanwhile). */\nexport function isModalOpen(scope: ParentNode): boolean {\n return openDialogs(scope).some(isModal);\n}\n\n/** The shell's one `keydown` listener (bubble phase): applies `decideKey` (guide §5.8, §13.5). */\nexport function createKeyListener(context: KeyListenerContext): (event: KeyboardEvent) => void {\n return (event) => {\n if (event.key === \"Escape\") context.hideTooltip();\n const dialogs = openDialogs(context.dialogScope);\n const decision = decideKey(event, {\n host: context.host,\n inTextField: isTextField(event.target),\n menuOpen: context.menuOpen(),\n dialogOpen: dialogs.length > 0,\n modalOpen: dialogs.some(isModal),\n defaultPrevented: event.defaultPrevented,\n startScreen: context.startScreen?.() ?? false,\n });\n if (decision.preventDefault) event.preventDefault();\n if (decision.stopPropagation) event.stopPropagation();\n if (decision.action === \"closeMenu\") context.closeMenu();\n else if (decision.action) context.run(decision.action);\n };\n}\n","/**\n * Everything the shell changes outside the elements it creates (classes and attributes on the root,\n * `<html>` and a passed canvas, listeners, observers, timers), recorded so `destroy()` puts it back\n * exactly as it was before `mountShell`.\n */\nexport class Ledger {\n private readonly undo: (() => void)[] = [];\n private readonly originalAttributes = new Map<Element, Map<string, string | null>>();\n private closed = false;\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n /** Runs `task` on `close()`, in reverse order of registration. */\n defer(task: () => void): void {\n this.undo.push(task);\n }\n\n /** Adds `className` unless present; `close()` removes it only if this ledger added it. */\n addClass(element: Element, className: string): void {\n if (element.classList.contains(className)) return;\n const hadClassAttribute = element.hasAttribute(\"class\");\n element.classList.add(className);\n this.defer(() => {\n element.classList.remove(className);\n if (!hadClassAttribute && element.classList.length === 0) element.removeAttribute(\"class\");\n });\n }\n\n /** Sets (string) or removes (`null`) an attribute; `close()` restores the value before the first change. */\n attribute(element: Element, name: string, value: string | null): void {\n let originals = this.originalAttributes.get(element);\n if (!originals) {\n originals = new Map();\n this.originalAttributes.set(element, originals);\n }\n if (!originals.has(name)) {\n originals.set(name, element.getAttribute(name));\n this.defer(() => {\n const original = originals.get(name) ?? null;\n if (original === null) element.removeAttribute(name);\n else element.setAttribute(name, original);\n });\n }\n if (value === null) element.removeAttribute(name);\n else element.setAttribute(name, value);\n }\n\n listen<K extends keyof DocumentEventMap>(\n target: Document,\n type: K,\n listener: (event: DocumentEventMap[K]) => void,\n options?: AddEventListenerOptions,\n ): void;\n listen<K extends keyof HTMLElementEventMap>(\n target: HTMLElement,\n type: K,\n listener: (event: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n ): void;\n listen(\n target: EventTarget,\n type: string,\n listener: (event: never) => void,\n options?: AddEventListenerOptions,\n ): void {\n const handler = listener as EventListener;\n target.addEventListener(type, handler, options);\n this.defer(() => target.removeEventListener(type, handler, options));\n }\n\n /** Runs every undo task once; later calls are no-ops. */\n close(): void {\n if (this.closed) return;\n this.closed = true;\n for (const task of this.undo.reverse()) {\n try {\n task();\n } catch {\n // one failing undo (an element the modeler already removed) must not keep the rest\n }\n }\n this.undo.length = 0;\n this.originalAttributes.clear();\n }\n}\n","import type { ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { LegendHandle, LegendOptions } from \"./types.js\";\n\nexport interface LegendController extends LegendHandle {\n /** The start state once the container height is known; never reported through `onToggle`. */\n start(open: boolean): void;\n isStarted(): boolean;\n destroy(): void;\n}\n\nexport interface LegendContext {\n ownerDocument: Document;\n messages: ShellMessages;\n tooltip: TooltipController;\n titleId: string;\n options: LegendOptions;\n onChange(open: boolean): void;\n /** Where the focus goes when the close button hides the legend under it. */\n focusAfterClose(): void;\n}\n\nexport function createLegend(context: LegendContext): LegendController {\n const { ownerDocument, messages, tooltip, titleId, options } = context;\n const close = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: \"cd-shell-legend-close\",\n \"aria-label\": messages.closeLegend,\n });\n close.append(iconElement(\"x\"));\n const body = createElement(ownerDocument, \"div\", { class: \"cd-shell-legend-body\" });\n const element = createElement(\n ownerDocument,\n \"section\",\n { class: \"cd-shell-legend cd-shell-island\", \"data-chrome\": \"legend\", \"aria-labelledby\": titleId },\n createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-legend-header\" },\n createElement(ownerDocument, \"div\", { class: \"cd-shell-legend-title\", id: titleId }, messages.legend),\n close,\n ),\n body,\n );\n element.hidden = true;\n options.render(body);\n\n let open = false;\n let started = false;\n const detachTooltip = tooltip.attach(close, { label: messages.closeLegend });\n\n function apply(next: boolean): boolean {\n started = true;\n if (next === open) return false;\n open = next;\n element.hidden = !open;\n if (!open && element.contains(ownerDocument.activeElement)) context.focusAfterClose();\n context.onChange(open);\n return true;\n }\n\n function setOpen(next: boolean): void {\n if (apply(next)) options.onToggle?.(next);\n }\n\n close.addEventListener(\"click\", () => setOpen(false));\n\n return {\n element,\n body,\n isOpen: () => open,\n setOpen,\n toggle: () => setOpen(!open),\n start(initial) {\n if (!started) apply(initial);\n },\n isStarted: () => started,\n destroy() {\n detachTooltip();\n element.remove();\n },\n };\n}\n","import { ariaKeyShortcutsFromLabel, matchChromeKey, type ShellMessages } from \"../core/index.js\";\nimport { createElement, toggleAttribute } from \"./element.js\";\nimport { iconElement, type ShellIconName } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { MenuEntry, MenuGroups, MenuHandle, MenuRadioGroup } from \"./types.js\";\n\n/**\n * The fixed groups of guide §5.4 in their order, written as `data-menu-group`. File and Appearance\n * exist in the web host only and come from the shell (`ShellOptions.file`, the Appearance group of\n * a dark-capable modeler); Model, Export and Help from `MenuGroups`.\n */\nexport type MenuGroupName = \"file\" | \"model\" | \"export\" | \"appearance\" | \"help\";\nconst GROUP_ORDER: readonly MenuGroupName[] = [\"file\", \"model\", \"export\", \"appearance\", \"help\"];\ntype GroupName = MenuGroupName;\n\nfunction isModelerGroup(name: MenuGroupName): name is keyof MenuGroups {\n return name === \"model\" || name === \"export\" || name === \"help\";\n}\n\ninterface Item {\n /** Stable across renders, so a re-render keeps the focus on the same entry. */\n key: string;\n element: HTMLButtonElement;\n label: string;\n disabled: boolean;\n activate(): void;\n}\n\nexport interface MenuContext {\n root: HTMLElement;\n layer: HTMLElement;\n id: string;\n messages: ShellMessages;\n tooltip: TooltipController;\n groups: MenuGroups;\n /**\n * Entries the shell adds to a group, after the modeler's: the File group and the Appearance group\n * (web host), the Legend checkbox at the end of Model.\n */\n shellEntries(group: MenuGroupName): readonly MenuEntry[];\n isReadOnly(): boolean;\n}\n\nexport interface MenuController extends MenuHandle {\n destroy(): void;\n}\n\nfunction isPrintable(event: KeyboardEvent): boolean {\n return event.key.length === 1 && /\\S/.test(event.key) && !event.ctrlKey && !event.metaKey && !event.altKey;\n}\n\nexport function createMenu(context: MenuContext): MenuController {\n const { root, layer, id, messages, tooltip } = context;\n const ownerDocument = root.ownerDocument;\n let groups = context.groups;\n let items: Item[] = [];\n let destroyed = false;\n\n const trigger = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: \"cd-shell-menu-trigger cd-shell-island\",\n \"data-chrome\": \"menu\",\n \"aria-label\": messages.menu,\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": \"false\",\n \"aria-controls\": id,\n });\n trigger.append(iconElement(\"menu\"));\n\n const dropdown = createElement(ownerDocument, \"div\", {\n class: \"cd-shell-menu\",\n id,\n role: \"menu\",\n \"aria-label\": messages.menu,\n });\n dropdown.hidden = true;\n layer.prepend(dropdown);\n\n const isOpen = (): boolean => !dropdown.hidden;\n\n function entriesOf(name: GroupName): readonly MenuEntry[] {\n const own = isModelerGroup(name) ? (groups[name] ?? []) : [];\n const added = context.shellEntries(name);\n return added.length > 0 ? [...own, ...added] : own;\n }\n\n function hasEntries(): boolean {\n return GROUP_ORDER.some((name) => entriesOf(name).length > 0);\n }\n\n function updateTriggerVisibility(): void {\n trigger.hidden = !hasEntries();\n if (trigger.hidden) close();\n }\n\n // Guide §13.5: on a read-only canvas the Model entries that change the document are aria-disabled.\n // View-only toggles (the shell's Legend, a modeler's Type captions) opt out and stay usable.\n function isDisabled(entry: MenuEntry, group: GroupName): boolean {\n if (group === \"model\" && context.isReadOnly() && entry.keepEnabledWhenReadOnly !== true) return true;\n return entry.disabled?.() ?? false;\n }\n\n function itemElement(\n role: \"menuitem\" | \"menuitemcheckbox\" | \"menuitemradio\",\n label: string,\n options: {\n icon?: ShellIconName | undefined;\n end?: Node | undefined;\n disabled: boolean;\n checked?: boolean;\n },\n ): HTMLButtonElement {\n const iconSlot = createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-icon\" });\n if (options.icon) iconSlot.append(iconElement(options.icon));\n const element = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-menu-item\", role, tabindex: \"-1\" },\n iconSlot,\n createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-label\" }, label),\n options.end && createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-end\" }, options.end),\n );\n toggleAttribute(element, \"aria-disabled\", options.disabled && \"true\");\n if (options.checked !== undefined) element.setAttribute(\"aria-checked\", String(options.checked));\n return element;\n }\n\n function checkMark(): SVGSVGElement {\n return iconElement(\"check\", { className: \"cd-shell-menu-check\" });\n }\n\n function renderEntry(entry: Exclude<MenuEntry, MenuRadioGroup>, group: GroupName): Item {\n const disabled = isDisabled(entry, group);\n if (entry.kind === \"checkbox\") {\n const checked = entry.checked();\n const element = itemElement(\"menuitemcheckbox\", entry.label, {\n icon: entry.icon,\n end: checkMark(),\n disabled,\n checked,\n });\n element.dataset.menuId = entry.id;\n element.dataset.menuGroup = group;\n return {\n key: entry.id,\n element,\n label: entry.label,\n disabled,\n activate() {\n entry.onToggle(!entry.checked());\n refresh();\n },\n };\n }\n const shortcut = entry.shortcut\n ? createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-shortcut\" }, entry.shortcut)\n : undefined;\n const element = itemElement(\"menuitem\", entry.label, { icon: entry.icon, end: shortcut, disabled });\n element.dataset.menuId = entry.id;\n element.dataset.menuGroup = group;\n const keyShortcuts =\n entry.ariaKeyShortcuts ?? (entry.shortcut ? ariaKeyShortcutsFromLabel(entry.shortcut) : undefined);\n toggleAttribute(element, \"aria-keyshortcuts\", keyShortcuts || null);\n if (entry.kind === \"dialog\") element.setAttribute(\"aria-haspopup\", \"dialog\");\n if (entry.kind === \"action\" && entry.danger) element.dataset.danger = \"\";\n return {\n key: entry.id,\n element,\n label: entry.label,\n disabled,\n activate() {\n close({ restoreFocus: true });\n entry.onSelect();\n },\n };\n }\n\n function renderRadioGroup(\n entry: MenuRadioGroup,\n group: GroupName,\n ): { element: HTMLElement; items: Item[] } {\n const disabled = isDisabled(entry, group);\n const value = entry.value();\n const container = createElement(\n ownerDocument,\n \"div\",\n {\n class: \"cd-shell-menu-group\",\n role: \"group\",\n \"aria-label\": entry.label,\n \"data-menu-id\": entry.id,\n \"data-menu-group\": group,\n },\n // The group's aria-label carries the heading; a menu holds no loose text.\n createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-menu-heading\", \"aria-hidden\": \"true\" },\n entry.label,\n ),\n );\n const radioItems = entry.options.map((option): Item => {\n const element = itemElement(\"menuitemradio\", option.label, {\n end: checkMark(),\n disabled,\n checked: option.value === value,\n });\n element.dataset.menuValue = option.value;\n container.append(element);\n return {\n key: `${entry.id}\\u0000${option.value}`,\n element,\n label: option.label,\n disabled,\n activate() {\n if (entry.value() !== option.value) entry.onSelect(option.value);\n refresh();\n },\n };\n });\n return { element: container, items: radioItems };\n }\n\n function render(): void {\n const focusedKey = items.find((item) => item.element === ownerDocument.activeElement)?.key;\n const nodes: HTMLElement[] = [];\n const rendered: Item[] = [];\n for (const name of GROUP_ORDER) {\n const entries = entriesOf(name);\n if (entries.length === 0) continue;\n if (nodes.length > 0) {\n nodes.push(\n createElement(ownerDocument, \"div\", { class: \"cd-shell-menu-separator\", role: \"separator\" }),\n );\n }\n for (const entry of entries) {\n if (entry.kind === \"radio\") {\n const radio = renderRadioGroup(entry, name);\n nodes.push(radio.element);\n rendered.push(...radio.items);\n } else {\n const item = renderEntry(entry, name);\n nodes.push(item.element);\n rendered.push(item);\n }\n }\n }\n for (const item of rendered) {\n item.element.addEventListener(\"click\", () => {\n if (!item.disabled) item.activate();\n });\n }\n dropdown.replaceChildren(...nodes);\n items = rendered;\n if (focusedKey !== undefined && isOpen()) {\n (items.find((item) => item.key === focusedKey) ?? items[0])?.element.focus();\n }\n }\n\n function focusAt(index: number): void {\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.element.focus();\n }\n\n function currentIndex(): number {\n return items.findIndex((item) => item.element === ownerDocument.activeElement);\n }\n\n function typeAhead(character: string): void {\n const start = currentIndex();\n const lower = character.toLowerCase();\n for (let step = 1; step <= items.length; step++) {\n const index = (Math.max(start, -1) + step) % items.length;\n if (items[index]?.label.toLowerCase().startsWith(lower)) {\n focusAt(index);\n return;\n }\n }\n }\n\n const onOutsidePointerDown = (event: PointerEvent): void => {\n const target = event.target as Node | null;\n if (target && (dropdown.contains(target) || trigger.contains(target))) return;\n close();\n };\n\n // The focus left the document (a click into the VS Code workbench, another iframe): from the\n // user's view a click outside, so the menu closes without moving the focus (guide §5.4).\n const onWindowBlur = (): void => close();\n\n function open(focus: \"first\" | \"last\" = \"first\"): void {\n if (destroyed || !hasEntries()) return;\n tooltip.hide();\n const wasOpen = isOpen();\n render();\n if (!wasOpen) {\n dropdown.hidden = false;\n trigger.setAttribute(\"aria-expanded\", \"true\");\n // Capture phase: diagram-js stops pointer events on palette, context pad and canvas.\n ownerDocument.addEventListener(\"pointerdown\", onOutsidePointerDown, true);\n ownerDocument.defaultView?.addEventListener(\"blur\", onWindowBlur);\n }\n focusAt(focus === \"last\" ? items.length - 1 : 0);\n }\n\n function close(options: { restoreFocus?: boolean } = {}): void {\n if (!isOpen()) return;\n dropdown.hidden = true;\n trigger.setAttribute(\"aria-expanded\", \"false\");\n ownerDocument.removeEventListener(\"pointerdown\", onOutsidePointerDown, true);\n ownerDocument.defaultView?.removeEventListener(\"blur\", onWindowBlur);\n if (options.restoreFocus && !trigger.hidden) trigger.focus();\n }\n\n function refresh(): void {\n if (isOpen()) render();\n }\n\n trigger.addEventListener(\"click\", () => {\n if (isOpen()) close();\n else open(\"first\");\n });\n\n // Keys the menu consumes stop here, in every host like the palette's: a modeler's keyboard on\n // document (Event Storming moves the selection on ↑/↓, deletes it on Delete, creates a sticky on\n // E) must never act on them, and VS Code never sees them.\n function consume(event: KeyboardEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n\n trigger.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\" || event.key === \" \" || event.key === \"ArrowDown\") {\n consume(event);\n open(\"first\");\n } else if (event.key === \"ArrowUp\") {\n consume(event);\n open(\"last\");\n }\n });\n\n dropdown.addEventListener(\"keydown\", (event) => {\n // Zoom and fit keys still act with the menu open; the shell's key listener runs them.\n if (matchChromeKey(event)) return;\n switch (event.key) {\n case \"ArrowDown\":\n focusAt(currentIndex() + 1);\n break;\n case \"ArrowUp\": {\n const index = currentIndex();\n focusAt(index < 0 ? items.length - 1 : index - 1);\n break;\n }\n case \"Home\":\n focusAt(0);\n break;\n case \"End\":\n focusAt(items.length - 1);\n break;\n case \"Tab\":\n // The browser's Tab runs after this handler from wherever the focus is then: from the\n // trigger it moves on to the palette instead of leaving the shell from the layer.\n close({ restoreFocus: true });\n return;\n case \"Escape\":\n // The shell's key listener closes the menu (and keeps Escape from VS Code in the IDE host).\n return;\n case \"Enter\":\n case \" \":\n case \"Delete\":\n case \"Backspace\":\n // The entry's native click handles Enter and Space; nothing else may act on these keys.\n event.stopPropagation();\n return;\n default:\n if (!isPrintable(event)) return;\n typeAhead(event.key);\n }\n consume(event);\n });\n\n updateTriggerVisibility();\n\n return {\n trigger,\n dropdown,\n isOpen,\n open,\n close,\n refresh,\n setGroups(next) {\n groups = next;\n updateTriggerVisibility();\n refresh();\n },\n destroy() {\n if (destroyed) return;\n close();\n destroyed = true;\n trigger.remove();\n dropdown.remove();\n },\n };\n}\n","import { formatNumber, type ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { ProblemSummary } from \"./types.js\";\n\nexport interface ProblemsPill {\n readonly element: HTMLButtonElement;\n isShown(): boolean;\n set(summary: ProblemSummary): void;\n destroy(): void;\n}\n\nexport interface ProblemsContext {\n ownerDocument: Document;\n messages: ShellMessages;\n lang: string;\n tooltip: TooltipController;\n /** The IDE host opens its Problems view, so only there the pill explains itself. */\n showTooltip: boolean;\n /** A click: `ProblemsOptions.onActivate` (IDE host) or the problems popover's toggle (web host). */\n onActivate(): void;\n}\n\nexport function createProblemsPill(context: ProblemsContext): ProblemsPill {\n const { ownerDocument, messages, lang, tooltip } = context;\n const icon = createElement(ownerDocument, \"span\", { class: \"cd-shell-problems-icon\" });\n const text = createElement(ownerDocument, \"span\", { class: \"cd-shell-problems-text\" });\n const element = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-problems cd-shell-island\", \"data-chrome\": \"problems\" },\n icon,\n text,\n );\n element.hidden = true;\n element.addEventListener(\"click\", () => context.onActivate());\n const detachTooltip = context.showTooltip\n ? tooltip.attach(element, { label: messages.showProblems })\n : undefined;\n\n let severity: \"danger\" | \"warning\" | undefined;\n\n return {\n element,\n isShown: () => !element.hidden,\n set({ count, errors }) {\n const shown = count > 0;\n element.hidden = !shown;\n if (!shown) {\n tooltip.hide();\n return;\n }\n const formattedCount = formatNumber(count, lang);\n text.textContent = messages.problems(count, formattedCount);\n element.setAttribute(\n \"aria-label\",\n messages.problemsLabel(count, errors, formattedCount, formatNumber(errors, lang)),\n );\n // The shape carries the severity as well, colour is never the only signal (guide §5.10).\n const next = errors > 0 ? \"danger\" : \"warning\";\n if (next !== severity) {\n severity = next;\n element.dataset.severity = next;\n icon.replaceChildren(iconElement(next === \"danger\" ? \"circle-x\" : \"triangle-alert\"));\n }\n },\n destroy() {\n detachTooltip?.();\n element.remove();\n },\n };\n}\n","import { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { StatusMessage } from \"./types.js\";\n\nexport interface StatusBox {\n readonly element: HTMLElement;\n set(status: StatusMessage | null, delayMs: number): void;\n destroy(): void;\n}\n\nexport function createStatusBox(ownerDocument: Document): StatusBox {\n const icon = createElement(ownerDocument, \"span\", { class: \"cd-shell-status-icon\" });\n const text = createElement(ownerDocument, \"p\", { class: \"cd-shell-status-text\" });\n const element = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-status\", \"data-chrome\": \"status\" },\n icon,\n text,\n );\n element.hidden = true;\n\n let pending: { status: StatusMessage; timer: ReturnType<typeof setTimeout> } | undefined;\n\n function cancelPending(): void {\n if (pending) clearTimeout(pending.timer);\n pending = undefined;\n }\n\n function show(status: StatusMessage): void {\n pending = undefined;\n if (element.dataset.severity !== status.severity) {\n element.dataset.severity = status.severity;\n element.setAttribute(\"role\", status.severity === \"danger\" ? \"alert\" : \"status\");\n icon.replaceChildren(iconElement(status.severity === \"danger\" ? \"circle-x\" : \"triangle-alert\"));\n }\n // An unchanged text is not written again, so role=\"alert\" does not announce it again.\n if (text.textContent !== status.text) text.textContent = status.text;\n element.hidden = false;\n }\n\n return {\n element,\n set(status, delayMs) {\n if (status === null) {\n cancelPending();\n element.hidden = true;\n return;\n }\n if (!element.hidden) {\n show(status);\n return;\n }\n // Repeated invalid imports while typing keep the first timer: the box shows once the text\n // stayed invalid for the delay, not the delay after the last keystroke (guide §5.12).\n if (pending) {\n pending.status = status;\n return;\n }\n if (delayMs > 0) {\n const entry = { status, timer: setTimeout(() => show(entry.status), delayMs) };\n pending = entry;\n } else {\n show(status);\n }\n },\n destroy() {\n cancelPending();\n element.remove();\n },\n };\n}\n","import { TOOLTIP_DELAY_MS, placeTooltip } from \"../core/index.js\";\nimport { accessibleName, boxRelativeTo, createElement, hasVisibleFocus } from \"./element.js\";\nimport type { TooltipContent, TooltipHandle } from \"./types.js\";\n\ntype ContentSource = TooltipContent | (() => TooltipContent | null);\n\ninterface Shown {\n control: HTMLElement;\n describedBy: string | null;\n}\n\nexport interface TooltipController extends TooltipHandle {\n readonly element: HTMLElement;\n /** One tooltip for every `selector` match inside `container` (palette entries are rebuilt often). */\n delegate(\n container: HTMLElement,\n selector: string,\n content: (control: HTMLElement) => TooltipContent | null,\n ): () => void;\n destroy(): void;\n}\n\nexport interface TooltipContext {\n root: HTMLElement;\n layer: HTMLElement;\n id: string;\n}\n\nexport function createTooltip({ root, layer, id }: TooltipContext): TooltipController {\n const ownerDocument = root.ownerDocument;\n const label = createElement(ownerDocument, \"span\", { class: \"cd-shell-tooltip-label\" });\n const shortcut = createElement(ownerDocument, \"kbd\", { class: \"cd-shell-kbd\" });\n const element = createElement(ownerDocument, \"div\", { class: \"cd-shell-tooltip\", role: \"tooltip\", id });\n element.hidden = true;\n element.append(label, shortcut);\n layer.append(element);\n\n let shown: Shown | undefined;\n let pending: { control: HTMLElement; timer: ReturnType<typeof setTimeout> } | undefined;\n // After a pointer leaves a control the next one shows at once, so moving along a row of\n // buttons does not wait 300ms for every neighbour (guide §5.6).\n let warmUntil = 0;\n // A clicked control keeps its tooltip hidden until the pointer leaves it.\n let pressed: HTMLElement | undefined;\n const detachers = new Set<() => void>();\n // The tooltip grows when a web font arrives after it was placed; place it again so it keeps\n // its edge distance instead of running past the container.\n const resizeObserver =\n typeof ResizeObserver === \"function\"\n ? new ResizeObserver(() => {\n if (shown) place(shown.control);\n })\n : undefined;\n resizeObserver?.observe(element);\n\n function cancelPending(): void {\n if (pending) clearTimeout(pending.timer);\n pending = undefined;\n }\n\n function resolve(source: ContentSource): TooltipContent | null {\n return typeof source === \"function\" ? source() : source;\n }\n\n function place(control: HTMLElement): void {\n const island = control.closest<HTMLElement>(\"[data-chrome]\") ?? control;\n const point = placeTooltip({\n anchor: boxRelativeTo(control, root),\n island: boxRelativeTo(island, root),\n tooltip: { width: element.offsetWidth, height: element.offsetHeight },\n container: { width: root.clientWidth, height: root.clientHeight },\n });\n element.style.left = `${point.x}px`;\n element.style.top = `${point.y}px`;\n }\n\n function hide(): void {\n cancelPending();\n if (!shown) return;\n const { control, describedBy } = shown;\n shown = undefined;\n element.hidden = true;\n if (describedBy === null) control.removeAttribute(\"aria-describedby\");\n else control.setAttribute(\"aria-describedby\", describedBy);\n }\n\n function show(control: HTMLElement, source: ContentSource): void {\n cancelPending();\n const content = resolve(source);\n if (!content || !control.isConnected) {\n if (shown?.control === control) hide();\n return;\n }\n if (shown && shown.control !== control) hide();\n label.textContent = content.label;\n shortcut.textContent = content.shortcut ?? \"\";\n shortcut.hidden = !content.shortcut;\n element.hidden = false;\n if (!shown) {\n const describedBy = control.getAttribute(\"aria-describedby\");\n shown = { control, describedBy };\n // Only a tooltip that says more than the control's name describes it (guide §5.6); a shortcut\n // chip does, unless the control names its keys in aria-keyshortcuts.\n const saysMore =\n !accessibleName(control).includes(content.label) ||\n (Boolean(content.shortcut) && !control.hasAttribute(\"aria-keyshortcuts\"));\n if (saysMore) {\n control.setAttribute(\"aria-describedby\", [describedBy, id].filter(Boolean).join(\" \"));\n }\n }\n place(control);\n }\n\n function onEnter(control: HTMLElement, source: ContentSource, event: PointerEvent): void {\n if (event.pointerType === \"touch\" || pressed === control) return;\n if (shown || Date.now() < warmUntil) {\n show(control, source);\n return;\n }\n cancelPending();\n pending = { control, timer: setTimeout(() => show(control, source), TOOLTIP_DELAY_MS) };\n }\n\n function onLeave(control: HTMLElement): void {\n if (pressed === control) pressed = undefined;\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) {\n hide();\n warmUntil = Date.now() + TOOLTIP_DELAY_MS;\n }\n }\n\n function onFocus(control: HTMLElement, source: ContentSource): void {\n if (hasVisibleFocus(control)) show(control, source);\n }\n\n function onBlur(control: HTMLElement): void {\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) hide();\n }\n\n function onPress(control: HTMLElement, event: Event): void {\n if (event.type === \"pointerdown\") pressed = control;\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) hide();\n }\n\n function attach(control: HTMLElement, source: ContentSource): () => void {\n const enter = (event: PointerEvent) => onEnter(control, source, event);\n const leave = () => onLeave(control);\n const focus = () => onFocus(control, source);\n const blur = () => onBlur(control);\n const press = (event: Event) => onPress(control, event);\n control.addEventListener(\"pointerenter\", enter);\n control.addEventListener(\"pointerleave\", leave);\n control.addEventListener(\"focus\", focus);\n control.addEventListener(\"blur\", blur);\n control.addEventListener(\"pointerdown\", press);\n control.addEventListener(\"click\", press);\n const detach = () => {\n if (!detachers.delete(detach)) return;\n control.removeEventListener(\"pointerenter\", enter);\n control.removeEventListener(\"pointerleave\", leave);\n control.removeEventListener(\"focus\", focus);\n control.removeEventListener(\"blur\", blur);\n control.removeEventListener(\"pointerdown\", press);\n control.removeEventListener(\"click\", press);\n if (shown?.control === control || pending?.control === control) hide();\n if (pressed === control) pressed = undefined;\n };\n detachers.add(detach);\n return detach;\n }\n\n function delegate(\n container: HTMLElement,\n selector: string,\n content: (control: HTMLElement) => TooltipContent | null,\n ): () => void {\n let hovered: HTMLElement | undefined;\n const controlOf = (target: EventTarget | null): HTMLElement | undefined => {\n if (!target || typeof (target as Element).closest !== \"function\") return undefined;\n const match = (target as Element).closest<HTMLElement>(selector);\n return match && container.contains(match) ? match : undefined;\n };\n const sourceOf = (control: HTMLElement) => () => content(control);\n const over = (event: PointerEvent) => {\n const control = controlOf(event.target);\n if (control === hovered) return;\n if (hovered) onLeave(hovered);\n hovered = control;\n if (control) onEnter(control, sourceOf(control), event);\n };\n const out = (event: PointerEvent) => {\n if (!hovered) return;\n if (controlOf(event.relatedTarget) === hovered) return;\n onLeave(hovered);\n hovered = undefined;\n };\n const focusIn = (event: FocusEvent) => {\n const control = controlOf(event.target);\n if (control) onFocus(control, sourceOf(control));\n };\n const focusOut = (event: FocusEvent) => {\n const control = controlOf(event.target);\n if (control) onBlur(control);\n };\n const press = (event: Event) => {\n const control = controlOf(event.target);\n if (control) onPress(control, event);\n };\n container.addEventListener(\"pointerover\", over);\n container.addEventListener(\"pointerout\", out);\n container.addEventListener(\"focusin\", focusIn);\n container.addEventListener(\"focusout\", focusOut);\n container.addEventListener(\"pointerdown\", press);\n container.addEventListener(\"click\", press);\n const detach = () => {\n if (!detachers.delete(detach)) return;\n container.removeEventListener(\"pointerover\", over);\n container.removeEventListener(\"pointerout\", out);\n container.removeEventListener(\"focusin\", focusIn);\n container.removeEventListener(\"focusout\", focusOut);\n container.removeEventListener(\"pointerdown\", press);\n container.removeEventListener(\"click\", press);\n if ((shown && container.contains(shown.control)) || (pending && container.contains(pending.control))) {\n hide();\n }\n hovered = undefined;\n };\n detachers.add(detach);\n return detach;\n }\n\n return {\n element,\n attach,\n delegate,\n hide,\n destroy() {\n hide();\n for (const detach of [...detachers]) detach();\n resizeObserver?.disconnect();\n element.remove();\n },\n };\n}\n","import {\n acceptsFile,\n dragVerdict,\n type DragItemLike,\n type DragVerdict,\n type ShellMessages,\n type ToastRequest,\n} from \"../../core/index.js\";\nimport { createElement } from \"../element.js\";\nimport type { DropZoneOptions, ToastHandle } from \"../types.js\";\n\n/** The drop zone as the root shows it: `data-drop=\"over\"` or `\"forbidden\"` while a file drag is on the page. */\nexport type DropZoneState = \"over\" | \"forbidden\" | null;\n\nexport interface DropZoneContext {\n ownerDocument: Document;\n /** Where the overlay goes: the shell's layer (40, guide §5.13). */\n layer: HTMLElement;\n messages: ShellMessages;\n lang: string;\n options: DropZoneOptions;\n /** A modal dialog is open in the document (the shell's dialog test). */\n modalOpen(): boolean;\n /** For the default `onReject`. */\n toast(request: ToastRequest): ToastHandle;\n /** Writes the root's `data-drop`. */\n setState(state: DropZoneState): void;\n}\n\nexport interface DropZoneController {\n /** The overlay `<div data-chrome=\"drop-zone\" aria-hidden=\"true\">`. */\n readonly element: HTMLElement;\n state(): DropZoneState;\n destroy(): void;\n}\n\nconst DRAG_EVENTS = [\"dragenter\", \"dragover\", \"dragleave\", \"drop\"] as const;\n\nfunction carriesFiles(transfer: DataTransfer | null): transfer is DataTransfer {\n if (!transfer) return false;\n if (Array.from(transfer.types ?? []).includes(\"Files\")) return true;\n return Array.from(transfer.items ?? []).some((item) => item.kind === \"file\");\n}\n\n/** What the drag shows of its items; a browser without `items` still names \"Files\" in `types`. */\nfunction dragItems(transfer: DataTransfer): DragItemLike[] {\n const items = Array.from(transfer.items ?? [], (item) => ({ kind: item.kind, type: item.type }));\n return items.length > 0 ? items : [{ kind: \"file\", type: \"\" }];\n}\n\n/** The extensions of `accept` for the reject toast (\"a .storm, .json, or .txt file\"), else every entry. */\nfunction acceptList(accept: readonly string[], lang: string): string {\n const entries = accept.map((entry) => entry.trim()).filter((entry) => entry !== \"\");\n const extensions = entries.filter((entry) => entry.startsWith(\".\"));\n const listed = extensions.length > 0 ? extensions : entries;\n let format: Intl.ListFormat;\n try {\n format = new Intl.ListFormat(lang, { type: \"disjunction\" });\n } catch {\n format = new Intl.ListFormat(\"en\", { type: \"disjunction\" });\n }\n return format.format(listed);\n}\n\n/**\n * The page-wide drop zone of the web app (guide §9). Listens on the window (`dragenter`,\n * `dragover`, `dragleave`, `drop`; outermost pair counted) for drags carrying files only, so\n * palette drags and text drags into the label editor stay alone; `dragVerdict` decides the state.\n * Drag-over: overlay `inset: 12px`, fill `--cd-ui-hover`, 2px dashed `--cd-ui-interaktion`, radius\n * `lg`, chip `messages.dropFile` centred on `--cd-ui-flaeche-hoch` (13px/600, radius `md`,\n * `shadow-2`), `dropEffect = \"copy\"`. Forbidden: fill `--cd-ui-danger-flaeche`, dashed\n * `--cd-ui-danger`, chip `messages.dropForbidden(reason)`, `dropEffect = \"none\"` (cursor\n * `not-allowed`). Every file drag is `preventDefault`-ed, so the browser never navigates to the\n * file. A drop: files through `acceptsFile` → `onDrop(accepted)`, the rest → `onReject` (default\n * a danger toast `cannotOpenFile(name, accept joined by Intl.ListFormat disjunction)`); a forbidden\n * drop opens nothing. Hidden while no file drag is on the page.\n */\nexport function createDropZone(context: DropZoneContext): DropZoneController {\n const { ownerDocument, layer, messages, lang, options, modalOpen, toast, setState } = context;\n const chip = createElement(ownerDocument, \"span\", { class: \"cd-shell-drop-zone-chip\" });\n const element = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-drop-zone\", \"data-chrome\": \"drop-zone\", \"aria-hidden\": \"true\" },\n chip,\n );\n element.hidden = true;\n layer.append(element);\n\n const view = ownerDocument.defaultView;\n // dragenter and dragleave fire for every element the pointer crosses: only the outermost pair counts.\n let depth = 0;\n let current: DropZoneState = null;\n\n function verdictFor(items: readonly DragItemLike[]): DragVerdict {\n return dragVerdict(items, {\n accept: options.accept,\n multiple: options.multiple ?? false,\n dialogOpen: modalOpen(),\n });\n }\n\n function show(verdict: DragVerdict): void {\n const next: DropZoneState = verdict.state === \"none\" ? null : verdict.state;\n if (verdict.state === \"over\") chip.textContent = messages.dropFile;\n if (verdict.state === \"forbidden\") chip.textContent = messages.dropForbidden(verdict.reason);\n if (next === current) return;\n current = next;\n element.hidden = next === null;\n if (next === null) element.removeAttribute(\"data-state\");\n else element.setAttribute(\"data-state\", next);\n setState(next);\n }\n\n function track(transfer: DataTransfer): void {\n const verdict = verdictFor(dragItems(transfer));\n show(verdict);\n transfer.dropEffect = verdict.state === \"forbidden\" ? \"none\" : \"copy\";\n }\n\n function rejectByDefault(files: readonly File[]): void {\n const accepted = acceptList(options.accept, lang);\n for (const file of files) toast({ status: \"danger\", text: messages.cannotOpenFile(file.name, accepted) });\n }\n\n function receive(files: readonly File[], verdict: DragVerdict): void {\n // The type verdict only guesses while names are unreadable; at the drop acceptsFile knows.\n if (verdict.state === \"forbidden\" && verdict.reason !== \"type\") return;\n const accepted = files.filter((file) => acceptsFile(file, options.accept));\n const rejected = files.filter((file) => !accepted.includes(file));\n if (accepted.length > 0) options.onDrop(accepted);\n if (rejected.length > 0) (options.onReject ?? rejectByDefault)(rejected);\n }\n\n const onDragEvent = (event: Event): void => {\n const transfer = (event as DragEvent).dataTransfer;\n if (!carriesFiles(transfer)) return;\n // Unprevented, the browser opens the file in place of the app.\n event.preventDefault();\n switch (event.type) {\n case \"dragenter\":\n depth += 1;\n track(transfer);\n break;\n case \"dragover\":\n // A drag that entered before the listener existed is on the page all the same.\n depth = Math.max(depth, 1);\n track(transfer);\n break;\n case \"dragleave\":\n depth = Math.max(0, depth - 1);\n if (depth === 0) show({ state: \"none\" });\n break;\n case \"drop\": {\n depth = 0;\n show({ state: \"none\" });\n const files = Array.from(transfer.files ?? []);\n const items =\n files.length > 0 ? files.map((file) => ({ kind: \"file\", type: file.type })) : dragItems(transfer);\n receive(files, verdictFor(items));\n break;\n }\n }\n };\n\n for (const type of DRAG_EVENTS) view?.addEventListener(type, onDragEvent);\n\n return {\n element,\n state: () => current,\n destroy() {\n for (const type of DRAG_EVENTS) view?.removeEventListener(type, onDragEvent);\n depth = 0;\n if (current !== null) {\n current = null;\n setState(null);\n }\n element.remove();\n },\n };\n}\n","import { ariaKeyShortcutsFromLabel, type ShellMessages } from \"../../core/index.js\";\nimport { createElement } from \"../element.js\";\nimport type { EmptyStateOptions, FileMenuAction } from \"../types.js\";\n\nexport interface EmptyStateContext {\n ownerDocument: Document;\n messages: ShellMessages;\n options: EmptyStateOptions;\n /** The drop hint under the buttons; `undefined` without a drop zone. */\n dropHint: string | undefined;\n /**\n * The File group's \"Open…\": the hint offers it as a text link, the keyboard's way to a file\n * while the start screen hides the menu and a drop needs a pointer. `undefined` without one.\n */\n open?: FileMenuAction | undefined;\n /** `id` of the title, the section's `aria-labelledby`. */\n titleId: string;\n /** Runs before `onNewDiagram` / `onShowExample`: the shell hides the card and moves the focus. */\n onLeave(): void;\n}\n\nexport interface EmptyStateController {\n /** The `<section data-chrome=\"empty-state\">`. */\n readonly element: HTMLElement;\n isShown(): boolean;\n setShown(shown: boolean): void;\n /** Focuses \"New diagram\", the card's first button. */\n focus(): void;\n destroy(): void;\n}\n\n/** The Komet's size on the card (guide §8). */\nconst KOMET_SIZE = \"64\";\n\n/**\n * `<section class=\"cd-shell-empty-state\" data-chrome=\"empty-state\" aria-labelledby>` (guide §8):\n * centred in the container, `min(400px, 100cqw − 24px)` wide, glass, `shadow-2`, radius `lg`,\n * padding `32px 40px`, content centred with 16px gaps: `<img src=komet width=64 height=64\n * alt=\"\">`, `<h1>` title 21px/600, help 16px/1.6 `--cd-ui-text-leise`, then the buttons side by\n * side with 8px gap, 36px high (`cd-shell-button`): primary \"New diagram\" first, ghost \"Show\n * example\", then the drop hint 13px `--cd-ui-text-leise`. With the File group's \"Open…\" the hint\n * ends in a text link `messages.openFileLink` in `--cd-ui-link` (and its shortcut chip in Geist\n * Mono): not a third action, the keyboard's way to open a file. Opening keeps the card until the\n * modeler leaves it (`setEmptyState(false)` after the file loaded). Layer 20, `hidden` until\n * `setShown(true)`.\n */\nexport function createEmptyState(context: EmptyStateContext): EmptyStateController {\n const { ownerDocument, messages, options, dropHint, open, titleId, onLeave } = context;\n\n const button = (variant: \"primary\" | \"ghost\", label: string, run: () => void): HTMLButtonElement => {\n const element = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-button\", \"data-variant\": variant },\n label,\n );\n element.addEventListener(\"click\", () => {\n onLeave();\n run();\n });\n return element;\n };\n\n const onShowExample = options.onShowExample;\n const newDiagram = button(\"primary\", messages.newDiagram, () => options.onNewDiagram());\n const element = createElement(\n ownerDocument,\n \"section\",\n { class: \"cd-shell-empty-state\", \"data-chrome\": \"empty-state\", \"aria-labelledby\": titleId },\n // Dragging the mark would start an image drag that some browsers carry as a file.\n createElement(ownerDocument, \"img\", {\n class: \"cd-shell-empty-state-mark\",\n src: options.komet,\n width: KOMET_SIZE,\n height: KOMET_SIZE,\n alt: \"\",\n draggable: \"false\",\n }),\n createElement(ownerDocument, \"h1\", { class: \"cd-shell-empty-state-title\", id: titleId }, options.title),\n createElement(ownerDocument, \"p\", { class: \"cd-shell-empty-state-text\" }, options.text),\n createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-empty-state-actions\" },\n newDiagram,\n onShowExample && button(\"ghost\", messages.showExample, () => onShowExample()),\n ),\n hintParagraph(),\n );\n\n function hintParagraph(): HTMLElement | undefined {\n const hasDropHint = dropHint !== undefined && dropHint !== \"\";\n if (!hasDropHint && !open) return undefined;\n const paragraph = createElement(ownerDocument, \"p\", { class: \"cd-shell-empty-state-hint\" });\n if (hasDropHint) paragraph.append(dropHint);\n if (!open) return paragraph;\n const shortcut = open.shortcut?.trim();\n const link = createElement(\n ownerDocument,\n \"button\",\n {\n type: \"button\",\n class: \"cd-shell-empty-state-open\",\n \"aria-keyshortcuts\": shortcut ? ariaKeyShortcutsFromLabel(shortcut) : undefined,\n \"aria-haspopup\": open.dialog ? \"dialog\" : undefined,\n },\n messages.openFileLink,\n );\n link.addEventListener(\"click\", () => open.onSelect());\n if (hasDropHint) {\n paragraph.append(\" \", createElement(ownerDocument, \"span\", { \"aria-hidden\": \"true\" }, \"·\"), \" \");\n }\n // The link and its chip wrap as one: a chip alone on a line names no action.\n const openItem = createElement(ownerDocument, \"span\", { class: \"cd-shell-empty-state-open-item\" }, link);\n if (shortcut) {\n openItem.append(\n \" \",\n createElement(\n ownerDocument,\n \"kbd\",\n { class: \"cd-shell-empty-state-key\", \"aria-hidden\": \"true\" },\n shortcut,\n ),\n );\n }\n paragraph.append(openItem);\n return paragraph;\n }\n element.hidden = true;\n\n return {\n element,\n isShown: () => !element.hidden,\n setShown(shown) {\n element.hidden = !shown;\n },\n focus() {\n newDiagram.focus({ preventScroll: true });\n },\n destroy() {\n element.remove();\n },\n };\n}\n","import type { ShellMessages } from \"../../core/index.js\";\nimport { createElement } from \"../element.js\";\nimport type { LegalLineOptions } from \"../types.js\";\n\n/** The Miragon legal pages (corporate-identity, skill docs-site, `miragon/legal.ts`). */\nexport const MIRAGON_HOME = \"https://www.miragon.io/\";\nexport const MIRAGON_IMPRESSUM = \"https://www.miragon.io/impressum/\";\nexport const MIRAGON_DATENSCHUTZ = \"https://www.miragon.io/datenschutz/\";\n\nexport interface LegalLineContext {\n ownerDocument: Document;\n messages: ShellMessages;\n options: LegalLineOptions;\n /** `cd-shell-legal-N`: the prefix of the id the links' `aria-describedby` names. */\n idPrefix: string;\n}\n\nexport interface LegalLineController {\n /** The `<nav data-chrome=\"legal\">`. */\n readonly element: HTMLElement;\n destroy(): void;\n}\n\n/**\n * `<nav class=\"cd-shell-legal\" data-chrome=\"legal\" aria-label=\"Legal\">` (guide §5.10, §2): one\n * line, 13px, line height 20px, at `left: 12px; bottom: 12px`, glass without border and shadow,\n * padding `0 8px`, radius `sm`, layer 20; in a container too narrow for it, it wraps between its\n * entries and grows upwards. Links in `--cd-ui-link`, `target=\"_blank\" rel=\"noopener noreferrer\"`\n * and `aria-describedby` a hidden `messages.opensInNewTab`, each after the first in a\n * `<span class=\"cd-shell-legal-item\">` with its separator `<span aria-hidden=\"true\">·</span>`:\n * `messages.copyright(year)` → `MIRAGON_HOME`, \"Impressum\" → `MIRAGON_IMPRESSUM` and \"Datenschutz\"\n * → `MIRAGON_DATENSCHUTZ` (both `lang=\"de\"`, never translated), then `options.links`.\n */\nexport function createLegalLine(context: LegalLineContext): LegalLineController {\n const { ownerDocument, messages, options } = context;\n const year = options.year ?? new Date().getFullYear();\n\n // Every link opens a new tab; screen readers hear that from one shared description.\n const newTabId = `${context.idPrefix}-new-tab`;\n const link = (label: string, href: string, lang?: string): HTMLAnchorElement =>\n createElement(\n ownerDocument,\n \"a\",\n { href, lang, target: \"_blank\", rel: \"noopener noreferrer\", \"aria-describedby\": newTabId },\n label,\n );\n const separator = (): HTMLElement => createElement(ownerDocument, \"span\", { \"aria-hidden\": \"true\" }, \"·\");\n const item = (anchor: HTMLAnchorElement): HTMLElement =>\n createElement(ownerDocument, \"span\", { class: \"cd-shell-legal-item\" }, separator(), anchor);\n\n // The legal pages are German whatever the tool's language (guide §2), so their names are too.\n const links = [\n link(messages.copyright(year), MIRAGON_HOME),\n link(\"Impressum\", MIRAGON_IMPRESSUM, \"de\"),\n link(\"Datenschutz\", MIRAGON_DATENSCHUTZ, \"de\"),\n ...(options.links ?? []).map((extra) => link(extra.label, extra.href, extra.lang)),\n ];\n\n const element = createElement(ownerDocument, \"nav\", {\n class: \"cd-shell-legal\",\n \"data-chrome\": \"legal\",\n \"aria-label\": messages.legal,\n });\n element.append(\n ...links.map((anchor, index) => (index === 0 ? anchor : item(anchor))),\n createElement(ownerDocument, \"span\", { id: newTabId, hidden: \"\" }, messages.opensInNewTab),\n );\n\n return {\n element,\n destroy() {\n element.remove();\n },\n };\n}\n","import { parseAppearanceChoice, type ShellMessages } from \"../../core/index.js\";\nimport type { ShellIconName } from \"../icons.js\";\nimport type { AppearanceHandle, FileMenuAction, FileMenuOptions, MenuEntry } from \"../types.js\";\n\ninterface FileEntrySpec {\n option: keyof FileMenuOptions;\n id: string;\n label: string;\n icon: ShellIconName | undefined;\n}\n\nfunction fileEntry(spec: FileEntrySpec, action: FileMenuAction): MenuEntry {\n const common = {\n id: spec.id,\n label: spec.label,\n ...(spec.icon ? { icon: spec.icon } : {}),\n ...(action.disabled ? { disabled: action.disabled } : {}),\n ...(action.shortcut ? { shortcut: action.shortcut } : {}),\n onSelect: () => action.onSelect(),\n };\n return action.dialog ? { kind: \"dialog\", ...common } : { kind: \"action\", ...common };\n}\n\n/**\n * The File group (guide §5.4, §2), first in the menu: \"New diagram\" (`file-plus`, id\n * `new-diagram`), \"Open…\" (`folder-open`, `open`), \"Show example\" (no icon, `show-example`),\n * \"Import…\" (`import`, `import`), in this order and only those `options` gives. `action` entries\n * (`dialog` with `FileMenuAction.dialog`) with the action's `shortcut` and `disabled`. Never\n * locked on a read-only canvas.\n */\nexport function fileMenuEntries(options: FileMenuOptions, messages: ShellMessages): readonly MenuEntry[] {\n const specs: readonly FileEntrySpec[] = [\n { option: \"newDiagram\", id: \"new-diagram\", label: messages.newDiagram, icon: \"file-plus\" },\n { option: \"open\", id: \"open\", label: messages.openFile, icon: \"folder-open\" },\n // §5.14 gives \"Show example\" no icon.\n { option: \"showExample\", id: \"show-example\", label: messages.showExample, icon: undefined },\n { option: \"import\", id: \"import\", label: messages.importFile, icon: \"import\" },\n ];\n return specs.flatMap((spec) => {\n const action = options[spec.option];\n return action ? [fileEntry(spec, action)] : [];\n });\n}\n\n/**\n * The Appearance group (guide §5.4, §13.3) between Export and Help: one radio group, id\n * `appearance`, label `messages.appearance`, options `system`, `light`, `dark` labelled\n * `messages.appearanceSystem` / `Light` / `Dark`, value `appearance.choice()`, selecting calls\n * `appearance.setChoice`. Never locked. The shell asks for it only when `themes` includes `\"dark\"`.\n */\nexport function appearanceMenuEntries(\n appearance: AppearanceHandle,\n messages: ShellMessages,\n): readonly MenuEntry[] {\n return [\n {\n kind: \"radio\",\n id: \"appearance\",\n label: messages.appearance,\n options: [\n { value: \"system\", label: messages.appearanceSystem },\n { value: \"light\", label: messages.appearanceLight },\n { value: \"dark\", label: messages.appearanceDark },\n ],\n value: () => appearance.choice(),\n onSelect: (value) => appearance.setChoice(parseAppearanceChoice(value)),\n },\n ];\n}\n","import { SHELL, type PrimaryWidths, type ShellMessages } from \"../../core/index.js\";\nimport { createElement, toggleAttribute } from \"../element.js\";\nimport { iconElement } from \"../icons.js\";\nimport type { TooltipController } from \"../tooltip.js\";\nimport type { PrimaryActionHandle, PrimaryActionOptions } from \"../types.js\";\n\nexport interface PrimaryActionContext {\n ownerDocument: Document;\n messages: ShellMessages;\n tooltip: TooltipController;\n options: PrimaryActionOptions;\n}\n\nexport interface PrimaryActionController extends PrimaryActionHandle {\n /**\n * Border-box widths with and without the label for `decideTopRow`, measured also while the label\n * is collapsed (the label's width does not change with the state), cached until `refresh()`.\n */\n widths(): PrimaryWidths;\n /** Icon only (`true`) or icon and label; the `aria-label` stays, the tooltip shows only while collapsed. */\n setCollapsed(collapsed: boolean): void;\n destroy(): void;\n}\n\n/** On the button while it shows its icon only: the stylesheet's 40 × 40 (the root mirrors it as `data-primary`). */\nconst COLLAPSED_ATTRIBUTE = \"data-collapsed\";\n\n/**\n * `<button type=\"button\" class=\"cd-shell-primary cd-shell-button\" data-variant=\"primary\"\n * data-chrome=\"primary\" aria-label=\"Share\">` with the 16px icon and `<span\n * class=\"cd-shell-primary-label\">` (guide §5.7): 40px high at `top: 12px; right: 12px`, layer 30,\n * blue (`dom/buttons.css`), hover lift. Collapsed: 40 × 40, label hidden, chrome tooltip with the\n * label (no `aria-describedby`, it repeats the name). `disabled()` → `aria-disabled`, no action.\n */\nexport function createPrimaryAction(context: PrimaryActionContext): PrimaryActionController {\n const { ownerDocument, messages, tooltip, options } = context;\n const label = options.label ?? messages.share;\n const labelElement = createElement(ownerDocument, \"span\", { class: \"cd-shell-primary-label\" }, label);\n const element = createElement(\n ownerDocument,\n \"button\",\n {\n type: \"button\",\n class: \"cd-shell-primary cd-shell-button\",\n \"data-variant\": \"primary\",\n \"data-chrome\": \"primary\",\n \"aria-label\": label,\n },\n iconElement(options.icon ?? \"share-2\"),\n labelElement,\n );\n\n let collapsed = false;\n let disabled = false;\n let labelledWidth: number | undefined;\n\n function readDisabled(): void {\n disabled = options.disabled?.() ?? false;\n toggleAttribute(element, \"aria-disabled\", disabled ? \"true\" : null);\n }\n\n function showCollapsed(state: boolean): void {\n labelElement.hidden = state;\n toggleAttribute(element, COLLAPSED_ATTRIBUTE, state ? \"\" : null);\n }\n\n /** The labelled width; while collapsed the label shows for one synchronous layout, never painted. */\n function measureLabelledWidth(): number {\n if (!collapsed) return element.offsetWidth;\n showCollapsed(false);\n const width = element.offsetWidth;\n showCollapsed(true);\n return width;\n }\n\n function isEngaged(): boolean {\n if (ownerDocument.activeElement === element) return true;\n try {\n return element.matches(\":hover\");\n } catch {\n return false;\n }\n }\n\n const onClick = (event: MouseEvent): void => {\n if (disabled) {\n event.preventDefault();\n return;\n }\n options.onSelect();\n };\n element.addEventListener(\"click\", onClick);\n const detachTooltip = tooltip.attach(element, () => (collapsed ? { label } : null));\n readDisabled();\n\n return {\n element,\n isCollapsed: () => collapsed,\n refresh() {\n readDisabled();\n labelledWidth = undefined;\n },\n widths() {\n // Measured fresh while the label shows (a late web font widens it), from the cache while collapsed.\n if (!collapsed || labelledWidth === undefined) {\n const measured = measureLabelledWidth();\n if (measured > 0) labelledWidth = measured;\n }\n return { withLabel: labelledWidth ?? 0, iconOnly: SHELL.row };\n },\n setCollapsed(next) {\n if (next === collapsed) return;\n collapsed = next;\n showCollapsed(next);\n // An expanded button names itself; a tooltip still showing for it would only repeat the label.\n if (!next && isEngaged()) tooltip.hide();\n },\n destroy() {\n detachTooltip();\n element.removeEventListener(\"click\", onClick);\n element.remove();\n },\n };\n}\n","import {\n ariaKeyShortcuts,\n canZoomIn,\n canZoomOut,\n formatPercent,\n shortcutLabel,\n zoomReadout,\n type ChromeKey,\n type Platform,\n type ShellMessages,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport { createElement, toggleAttribute } from \"./element.js\";\nimport { iconElement, type ShellIconName } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\n\nexport interface ZoomPanelContext {\n ownerDocument: Document;\n messages: ShellMessages;\n lang: string;\n platform: Platform;\n tooltip: TooltipController;\n}\n\nexport interface ZoomPanel {\n readonly element: HTMLElement;\n setTarget(target: ZoomTarget | null): void;\n /** Runs a chrome key on the bound target; zoom out never zooms in (guide §5.8). */\n run(key: ChromeKey): void;\n destroy(): void;\n}\n\nexport function createZoomPanel(context: ZoomPanelContext): ZoomPanel {\n const { ownerDocument, messages, lang, platform, tooltip } = context;\n let target: ZoomTarget | null = null;\n let unsubscribe: (() => void) | undefined;\n let frame: number | undefined;\n const detachers: (() => void)[] = [];\n\n function button(\n zoom: \"out\" | \"actual\" | \"in\" | \"fit\",\n key: ChromeKey,\n tooltipLabel: string,\n options: { label?: string; icon?: ShellIconName; className?: string },\n ): HTMLButtonElement {\n const element = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: options.className ?? \"cd-shell-target\",\n \"data-zoom\": zoom,\n \"aria-label\": options.label,\n \"aria-keyshortcuts\": ariaKeyShortcuts(key, platform),\n });\n if (options.icon) element.append(iconElement(options.icon));\n element.addEventListener(\"click\", () => run(key));\n detachers.push(\n tooltip.attach(element, {\n label: tooltipLabel,\n shortcut: shortcutLabel(key, platform, messages.keyNames),\n }),\n );\n return element;\n }\n\n const zoomOut = button(\"out\", \"zoomOut\", messages.zoomOut, { label: messages.zoomOut, icon: \"minus\" });\n const readout = button(\"actual\", \"zoomToActual\", messages.zoomToActual(formatPercent(1, lang)), {\n className: \"cd-shell-target cd-shell-zoom-readout\",\n });\n const zoomIn = button(\"in\", \"zoomIn\", messages.zoomIn, { label: messages.zoomIn, icon: \"plus\" });\n const fit = button(\"fit\", \"fit\", messages.fit, { label: messages.fit, icon: \"maximize\" });\n const separator = createElement(ownerDocument, \"span\", {\n class: \"cd-shell-zoom-separator\",\n \"aria-hidden\": \"true\",\n });\n\n const element = createElement(\n ownerDocument,\n \"div\",\n {\n class: \"cd-shell-zoom cd-shell-island\",\n \"data-chrome\": \"zoom\",\n role: \"group\",\n \"aria-label\": messages.zoom,\n },\n zoomOut,\n readout,\n zoomIn,\n separator,\n fit,\n );\n\n function render(): void {\n frame = undefined;\n const zoom = target?.zoom() ?? 1;\n const state = zoomReadout(zoom, lang, messages);\n if (readout.textContent !== state.text) readout.textContent = state.text;\n readout.setAttribute(\"aria-label\", state.ariaLabel);\n // aria-disabled, not disabled: a button pressed up to the limit keeps the focus (guide §5.8).\n toggleAttribute(zoomOut, \"aria-disabled\", (!target || !state.canZoomOut) && \"true\");\n toggleAttribute(zoomIn, \"aria-disabled\", (!target || !state.canZoomIn) && \"true\");\n toggleAttribute(fit, \"aria-disabled\", (!target || !target.canFit()) && \"true\");\n // The readout is never disabled (guide §5.8); without a target its click does nothing.\n }\n\n function schedule(): void {\n if (frame === undefined) frame = requestAnimationFrame(render);\n }\n\n function cancelFrame(): void {\n if (frame !== undefined) cancelAnimationFrame(frame);\n frame = undefined;\n }\n\n function run(key: ChromeKey): void {\n if (!target) return;\n const zoom = target.zoom();\n switch (key) {\n case \"zoomIn\":\n if (canZoomIn(zoom)) target.stepZoom(1);\n break;\n case \"zoomOut\":\n if (canZoomOut(zoom)) target.stepZoom(-1);\n break;\n case \"zoomToActual\":\n if (zoom !== 1) target.zoomToActual();\n break;\n case \"fit\":\n if (target.canFit()) target.fit();\n break;\n }\n }\n\n render();\n\n return {\n element,\n run,\n setTarget(next) {\n unsubscribe?.();\n unsubscribe = undefined;\n cancelFrame();\n target = next;\n if (next) unsubscribe = next.onChange(schedule);\n render();\n },\n destroy() {\n unsubscribe?.();\n unsubscribe = undefined;\n cancelFrame();\n target = null;\n for (const detach of detachers) detach();\n element.remove();\n },\n };\n}\n","import {\n LEGAL_LINE_HEIGHT,\n SHELL,\n decideTopRow,\n detectPlatform,\n fitInsets,\n legalLineHeight,\n legendStartsOpen,\n resolveMessages,\n toastStackBottom,\n zoomRowRaised,\n type BottomObstacle,\n type FitLayout,\n type Insets,\n type PaletteRow,\n type Size,\n type Theme,\n type ToastRequest,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport { boxRelativeTo, createElement } from \"./element.js\";\nimport { connectWebAppearance } from \"./feedback/appearance.js\";\nimport { createProblemsPopover, type ProblemsPopover } from \"./feedback/problems-popover.js\";\nimport { createToaster } from \"./feedback/toasts.js\";\nimport { createEmptyHint } from \"./hint.js\";\nimport { createInspector } from \"./inspector.js\";\nimport { createKeyListener, isModalOpen } from \"./keys.js\";\nimport { Ledger } from \"./ledger.js\";\nimport { createLegend } from \"./legend.js\";\nimport { createMenu, type MenuGroupName } from \"./menu.js\";\nimport { createProblemsPill } from \"./problems.js\";\nimport { createStatusBox } from \"./status.js\";\nimport { createTooltip } from \"./tooltip.js\";\nimport type {\n AppearanceHandle,\n InspectorHandle,\n LegendHandle,\n MenuCheckboxEntry,\n MenuEntry,\n MenuHandle,\n PaletteReadOnlyState,\n PaletteRegistration,\n PrimaryActionHandle,\n ShellHandle,\n ShellOptions,\n ToastHandle,\n TooltipHandle,\n} from \"./types.js\";\nimport { createDropZone } from \"./web/drop-zone.js\";\nimport { createEmptyState } from \"./web/empty-state.js\";\nimport { createLegalLine } from \"./web/legal.js\";\nimport { appearanceMenuEntries, fileMenuEntries } from \"./web/menu-groups.js\";\nimport { createPrimaryAction } from \"./web/primary.js\";\nimport { createZoomPanel } from \"./zoom-panel.js\";\n\n// Page-global: every modeler bundles its own copy of the shell (and the CJS entries inline one each),\n// and two shells on one foreign page must not share element ids.\nconst MOUNT_COUNTER = Symbol.for(\"@miragon/modeler-shell.mounts\");\n\nfunction nextMountIndex(): number {\n const scope = globalThis as unknown as Record<symbol, number | undefined>;\n const index = (scope[MOUNT_COUNTER] ?? 0) + 1;\n scope[MOUNT_COUNTER] = index;\n return index;\n}\n\nconst DEFAULT_THEMES: readonly Theme[] = [\"light\"];\n\n/** The legal line's height on the root, which the stack above it (pill, legend, zoom row) adds. */\nconst LEGAL_HEIGHT_PROPERTY = \"--modeler-shell-legal-height\";\n\n/** What `toast()` returns where no toast shows (the IDE host, after `destroy`). */\nconst INERT_TOAST: ToastHandle = Object.freeze({ dismiss() {} });\n\n/** The element's box relative to the root while it is rendered and visible, else `undefined`. */\nfunction visibleBoxIn(element: HTMLElement | undefined, root: HTMLElement) {\n if (!element || element.hidden || !element.isConnected) return undefined;\n if (typeof element.checkVisibility === \"function\" && !element.checkVisibility({ visibilityProperty: true }))\n return undefined;\n const box = boxRelativeTo(element, root);\n return box.width > 0 && box.height > 0 ? box : undefined;\n}\n\n// In a foreign page the closest [lang] is the page's language, not the tool's (guide §2).\nfunction languageOf(root: HTMLElement, host: ShellOptions[\"host\"], requested: string | undefined): string {\n if (requested) return requested;\n const declared =\n host === \"embedded\" ? root.getAttribute(\"lang\") : root.closest(\"[lang]\")?.getAttribute(\"lang\");\n return declared || \"en\";\n}\n\n/** The contrast of the host page around an embedded root: the nearest mode carrier above it. */\nfunction hostKontrast(root: HTMLElement): \"hoch\" | null {\n const carrier = root.parentElement?.closest(\"[data-cd-theme], [data-cd-kontrast]\");\n return carrier?.getAttribute(\"data-cd-kontrast\") === \"hoch\" ? \"hoch\" : null;\n}\n\n/**\n * Turns `root` into the shell (`.cd-shell`, container `cd-shell`) and renders the chrome in the\n * DOM order of guide §5.14: menu trigger, primary action (web), canvas slot, status box,\n * empty-file hint, empty state (web), inspector, problems pill, legend, legal line (web), zoom\n * panel, then the layer for dropdown, tooltip, problems popover and drop zone, and last the toast\n * stack (web, embedded). Installs the one `keydown` listener (see `ShellOptions.keyScope`) and the\n * root `ResizeObserver`.\n *\n * `root` must get its size from outside (`container-type: size`): `height: 100%` in an own\n * document, an explicitly sized element in a foreign page. When rendering throws (a modeler's\n * `legend.render`), everything added so far is removed again before the error propagates.\n */\nexport function mountShell(root: HTMLElement, options: ShellOptions): ShellHandle {\n const themes = options.themes ?? DEFAULT_THEMES;\n if (themes.length === 0) throw new Error(\"@miragon/modeler-shell: mountShell needs at least one theme\");\n const ledger = new Ledger();\n try {\n return renderShell(root, options, themes, ledger);\n } catch (error) {\n ledger.close();\n throw error;\n }\n}\n\nfunction renderShell(\n root: HTMLElement,\n options: ShellOptions,\n themes: readonly Theme[],\n ledger: Ledger,\n): ShellHandle {\n const ownerDocument = root.ownerDocument;\n const { host } = options;\n const index = nextMountIndex();\n const messages = resolveMessages(options.messages);\n const platform = options.platform ?? detectPlatform(globalThis.navigator);\n const lang = languageOf(root, host, options.lang);\n const keyScope = options.keyScope ?? (host === \"embedded\" ? \"root\" : \"document\");\n const web = host === \"web\";\n\n ledger.addClass(root, \"cd-shell\");\n ledger.attribute(root, \"data-cd-shell-host\", host);\n ledger.attribute(root, \"data-palette\", \"top\");\n if (host === \"embedded\") {\n ledger.attribute(root, \"lang\", lang);\n carryOwnMode(root, themes[0] ?? \"light\", ledger);\n } else {\n ledger.addClass(ownerDocument.documentElement, \"cd-shell-document\");\n }\n\n const setState = (name: string, value: string | null): void => {\n if (!ledger.isClosed) ledger.attribute(root, name, value);\n };\n\n // The head script set the mode before the first paint; this follows contrast and the menu choice.\n const appearance = web\n ? connectWebAppearance({ ownerDocument, themes, options: options.appearance })\n : undefined;\n if (appearance) ledger.defer(() => appearance.destroy());\n const darkCapable = themes.includes(\"dark\");\n\n const layer = createElement(ownerDocument, \"div\", { class: \"cd-shell-layer\" });\n ledger.defer(() => layer.remove());\n const tooltip = createTooltip({ root, layer, id: `cd-shell-tooltip-${index}` });\n ledger.defer(() => tooltip.destroy());\n\n /** The lock of `setReadOnly(true)`; `readOnlyShown` its marks, which may follow after a delay. */\n let readOnly = false;\n let readOnlyShown = false;\n let readOnlyTimer: ReturnType<typeof setTimeout> | undefined;\n ledger.defer(() => clearTimeout(readOnlyTimer));\n\n const legend = options.legend\n ? createLegend({\n ownerDocument,\n messages,\n tooltip,\n titleId: `cd-shell-legend-title-${index}`,\n options: options.legend,\n onChange(open) {\n setState(\"data-legend\", open ? \"open\" : null);\n placeHint();\n menu.refresh();\n },\n focusAfterClose: () => menu.trigger.focus(),\n })\n : undefined;\n if (legend) ledger.defer(() => legend.destroy());\n\n const legendEntry: MenuCheckboxEntry | undefined =\n legend && options.legend?.menuEntry !== false\n ? {\n kind: \"checkbox\",\n id: \"legend\",\n label: messages.legend,\n checked: () => legend.isOpen(),\n onToggle: (checked) => legend.setOpen(checked),\n keepEnabledWhenReadOnly: true,\n }\n : undefined;\n const shellModelEntries: readonly MenuCheckboxEntry[] = legendEntry ? [legendEntry] : [];\n const fileEntries: readonly MenuEntry[] =\n web && options.file ? fileMenuEntries(options.file, messages) : [];\n const appearanceEntries: readonly MenuEntry[] =\n appearance && darkCapable ? appearanceMenuEntries(appearance, messages) : [];\n const shellEntries = (group: MenuGroupName): readonly MenuEntry[] => {\n if (group === \"file\") return fileEntries;\n if (group === \"model\") return shellModelEntries;\n if (group === \"appearance\") return appearanceEntries;\n return [];\n };\n\n const menu = createMenu({\n root,\n layer,\n id: `cd-shell-menu-${index}`,\n messages,\n tooltip,\n groups: options.menu ?? {},\n shellEntries,\n isReadOnly: () => readOnly,\n });\n ledger.defer(() => menu.destroy());\n ledger.defer(tooltip.attach(menu.trigger, () => (menu.isOpen() ? null : { label: messages.menu })));\n\n const primary =\n web && options.primary\n ? createPrimaryAction({ ownerDocument, messages, tooltip, options: options.primary })\n : undefined;\n if (primary) ledger.defer(() => primary.destroy());\n\n const canvas = options.canvas ?? createElement(ownerDocument, \"div\");\n ledger.addClass(canvas, \"cd-shell-canvas\");\n // An own page needs a main landmark; the diagram is its content. A foreign page has its own.\n if (web && !canvas.hasAttribute(\"role\")) ledger.attribute(canvas, \"role\", \"main\");\n if (!options.canvas) ledger.defer(() => canvas.remove());\n\n /**\n * The focus target when the element holding it goes away: on the start screen its \"New\n * diagram\", else the canvas, else the menu trigger. A target that cannot take the focus (inert,\n * hidden behind the start screen) is passed over, so the focus never falls to `<body>` unseen.\n */\n function focusCanvasOrTrigger(): void {\n const took = (target: HTMLElement | SVGElement | null | undefined): boolean => {\n target?.focus({ preventScroll: true });\n return target !== null && target !== undefined && ownerDocument.activeElement === target;\n };\n if (emptyState?.isShown()) {\n emptyState.focus();\n if (emptyState.element.contains(ownerDocument.activeElement)) return;\n }\n if (took(canvas.querySelector<HTMLElement | SVGElement>(\"svg[tabindex]\"))) return;\n if (!menu.trigger.hidden) took(menu.trigger);\n }\n\n /** Where the focus goes when the island holding it hides. */\n function moveFocusOutOf(island: HTMLElement): void {\n if (island.contains(ownerDocument.activeElement)) focusCanvasOrTrigger();\n }\n\n const status = createStatusBox(ownerDocument);\n ledger.defer(() => status.destroy());\n const hint = options.emptyHint ? createEmptyHint(ownerDocument, messages, options.emptyHint) : undefined;\n if (hint) ledger.defer(() => hint.destroy());\n const emptyState =\n web && options.emptyState\n ? createEmptyState({\n ownerDocument,\n messages,\n options: options.emptyState,\n dropHint: options.dropZone ? (options.emptyState.dropHint ?? messages.dropHint) : undefined,\n open: options.file?.open,\n titleId: `cd-shell-empty-state-title-${index}`,\n onLeave: () => setEmptyStateShown(false),\n })\n : undefined;\n if (emptyState) ledger.defer(() => emptyState.destroy());\n const inspector = options.inspector\n ? createInspector(ownerDocument, options.inspector, (open) => {\n setState(\"data-inspector\", open ? \"open\" : null);\n // Up to 760px the sheet hides zoom panel and pill, so the toasts' bottom row changes.\n updateBottomRow();\n placeHint();\n })\n : undefined;\n if (inspector) ledger.defer(() => inspector.destroy());\n const problemsOptions = options.problems;\n let popover: ProblemsPopover | undefined;\n const pill = problemsOptions\n ? createProblemsPill({\n ownerDocument,\n messages,\n lang,\n tooltip,\n showTooltip: host === \"ide\",\n onActivate() {\n if (popover) popover.toggle();\n else problemsOptions.onActivate?.();\n },\n })\n : undefined;\n if (pill) ledger.defer(() => pill.destroy());\n // The web app lists its problems itself; an embedding host only when it has no list of its own.\n if (pill && (web || (host === \"embedded\" && !problemsOptions?.onActivate))) {\n const created = createProblemsPopover({\n ownerDocument,\n root,\n layer,\n pill: pill.element,\n id: `cd-shell-problems-${index}`,\n titleId: `cd-shell-problems-title-${index}`,\n messages,\n onSelectItem: problemsOptions?.onSelectItem,\n });\n popover = created;\n ledger.defer(() => created.destroy());\n }\n const legal = web\n ? createLegalLine({\n ownerDocument,\n messages,\n options: options.legal ?? {},\n idPrefix: `cd-shell-legal-${index}`,\n })\n : undefined;\n if (legal) ledger.defer(() => legal.destroy());\n const zoomPanel = createZoomPanel({ ownerDocument, messages, lang, platform, tooltip });\n ledger.defer(() => zoomPanel.destroy());\n const toaster =\n host === \"ide\"\n ? undefined\n : createToaster({\n ownerDocument,\n host,\n messages,\n idPrefix: `cd-shell-toast-${index}`,\n focusFallback: focusCanvasOrTrigger,\n onChange: () => updateBottomRow(),\n });\n if (toaster) ledger.defer(() => toaster.destroy());\n\n const defined = (element: HTMLElement | undefined): element is HTMLElement => element !== undefined;\n root.prepend(...[menu.trigger, primary?.element, canvas].filter(defined));\n root.append(\n ...[\n status.element,\n hint?.element,\n emptyState?.element,\n inspector?.element,\n pill?.element,\n legend?.element,\n legal?.element,\n zoomPanel.element,\n ].filter(defined),\n layer,\n ...[toaster?.announcer, toaster?.element].filter(defined),\n );\n\n function showToast(request: ToastRequest): ToastHandle {\n return ledger.isClosed || !toaster ? INERT_TOAST : toaster.show(request);\n }\n\n const dropZone =\n web && options.dropZone\n ? createDropZone({\n ownerDocument,\n layer,\n messages,\n lang,\n options: options.dropZone,\n modalOpen: () => isModalOpen(ownerDocument),\n toast: showToast,\n setState: (state) => setState(\"data-drop\", state),\n })\n : undefined;\n if (dropZone) ledger.defer(() => dropZone.destroy());\n\n let palette: { registration: PaletteRegistration; detachTooltip: () => void } | undefined;\n let paletteRow: PaletteRow = \"top\";\n /** Web: the zoom panel stands above the legal line (`data-zoom-row=\"raised\"`). */\n let zoomRaised = false;\n /** Web: the legal line's measured height, more than one line where a narrow container wraps it. */\n let legalHeight = LEGAL_LINE_HEIGHT;\n if (legal) ledger.defer(() => root.style.removeProperty(LEGAL_HEIGHT_PROPERTY));\n\n function containerSize(): Size {\n return { width: root.clientWidth, height: root.clientHeight };\n }\n\n function menuRight(): number {\n const box = boxRelativeTo(menu.trigger, root);\n return box.width > 0 ? box.x + box.width : SHELL.edge + SHELL.row;\n }\n\n /** The palette's intrinsic border-box width: it does not shrink once the second row clips it. */\n function paletteWidth(): number {\n const element = palette?.registration.element;\n return element ? element.offsetWidth - element.clientWidth + element.scrollWidth : 0;\n }\n\n function currentFitInsets(): Insets {\n const container = containerSize();\n const layout: FitLayout = {\n container,\n host,\n paletteRow,\n problemsVisible: pill?.isShown() ?? false,\n };\n if (web) {\n layout.zoomRaised = zoomRaised;\n layout.legalHeight = legalHeight;\n }\n if (legend?.isOpen()) layout.legendWidth = legend.element.getBoundingClientRect().width;\n if (inspector?.isOpen()) {\n layout.inspector =\n container.width > SHELL.narrow ? {} : { sheetTop: boxRelativeTo(inspector.element, root).y };\n }\n return fitInsets(layout);\n }\n\n function placeHint(): void {\n if (hint?.isShown()) hint.place(currentFitInsets());\n }\n\n function updateLayout(): void {\n if (ledger.isClosed) return;\n const size = containerSize();\n // A hidden tab reports 0 × 0; it neither measures nor decides anything (guide §5.9).\n if (size.width === 0 || size.height === 0) return;\n const topRow = decideTopRow({\n containerWidth: size.width,\n paletteWidth: paletteWidth(),\n menuRight: menuRight(),\n primary: primary?.widths(),\n });\n paletteRow = topRow.paletteRow;\n setState(\"data-palette\", paletteRow);\n if (primary) {\n const collapsed = topRow.primaryLabel === \"collapsed\";\n primary.setCollapsed(collapsed);\n setState(\"data-primary\", collapsed ? \"collapsed\" : null);\n }\n if (legend && !legend.isStarted()) legend.start(options.legend?.open ?? legendStartsOpen(size.height));\n updateBottomRow();\n placeHint();\n }\n\n /** Web and embedded: the raised zoom row (legal line) and the toast stack's bottom, from what is visible. */\n function updateBottomRow(): void {\n if (ledger.isClosed) return;\n const size = containerSize();\n if (size.width === 0 || size.height === 0) return;\n if (legal) {\n const legalBox = visibleBoxIn(legal.element, root);\n const height = legalLineHeight(legalBox?.height);\n if (height !== legalHeight || !root.style.getPropertyValue(LEGAL_HEIGHT_PROPERTY)) {\n legalHeight = height;\n root.style.setProperty(LEGAL_HEIGHT_PROPERTY, `${height}px`);\n }\n zoomRaised = zoomRowRaised({\n containerWidth: size.width,\n legalRight: legalBox && legalBox.x + legalBox.width,\n zoomWidth: visibleBoxIn(zoomPanel.element, root)?.width,\n });\n setState(\"data-zoom-row\", zoomRaised ? \"raised\" : null);\n }\n if (toaster) {\n const obstacles = [zoomPanel.element, legal?.element, pill?.element].flatMap(\n (element): BottomObstacle[] => {\n const box = visibleBoxIn(element, root);\n return box ? [{ left: box.x, right: box.x + box.width, top: size.height - box.y }] : [];\n },\n );\n toaster.setBottom(\n toastStackBottom({ containerWidth: size.width, obstacles, cardWidth: toaster.widestCard() }),\n );\n }\n }\n\n function setEmptyStateShown(shown: boolean): void {\n if (ledger.isClosed || !emptyState || emptyState.isShown() === shown) return;\n const active = ownerDocument.activeElement;\n const hadFocus = emptyState.element.contains(active);\n // The work chrome and the canvas are about to hide: a focus there would fall to <body>. The\n // legal line and the toasts stay.\n const workHadFocus =\n shown &&\n active !== null &&\n root.contains(active) &&\n ![emptyState.element, legal?.element, toaster?.element].some((kept) => kept?.contains(active));\n emptyState.setShown(shown);\n setState(\"data-empty-state\", shown ? \"shown\" : null);\n // Nothing behind the card takes a click or the Tab (guide §8: nothing else competes).\n ledger.attribute(canvas, \"inert\", shown ? \"\" : null);\n if (shown) {\n menu.close();\n popover?.close();\n tooltip.hide();\n if (workHadFocus) emptyState.focus();\n } else if (hadFocus) {\n focusCanvasOrTrigger();\n }\n updateLayout();\n }\n\n const ResizeObserverClass = globalThis.ResizeObserver;\n const resizeObserver = ResizeObserverClass ? new ResizeObserverClass(() => updateLayout()) : undefined;\n resizeObserver?.observe(root);\n // The label widens once the web font has loaded; the top row decides again then. The legal line\n // may wrap onto a second line then, which lifts everything stacked above it.\n if (primary) resizeObserver?.observe(primary.element);\n if (legal) resizeObserver?.observe(legal.element);\n ledger.defer(() => resizeObserver?.disconnect());\n\n if (legend && options.legend?.open !== undefined) legend.start(options.legend.open);\n updateLayout();\n\n const keyTarget: HTMLElement | Document = keyScope === \"root\" ? root : ownerDocument;\n const onKeydown = createKeyListener({\n host,\n dialogScope: keyTarget,\n menuOpen: () => menu.isOpen(),\n startScreen: () => emptyState?.isShown() ?? false,\n closeMenu() {\n const active = ownerDocument.activeElement;\n menu.close({ restoreFocus: active === menu.trigger || menu.dropdown.contains(active) });\n },\n hideTooltip: () => tooltip.hide(),\n // Behind the start screen the keys reach the browser instead: there is no diagram to zoom.\n run: (key) => {\n if (!emptyState?.isShown()) zoomPanel.run(key);\n },\n });\n keyTarget.addEventListener(\"keydown\", onKeydown as EventListener);\n ledger.defer(() => keyTarget.removeEventListener(\"keydown\", onKeydown as EventListener));\n\n function readOnlyState(): PaletteReadOnlyState {\n return { locked: readOnly, shown: readOnlyShown };\n }\n\n function applyReadOnly(): void {\n setState(\"data-readonly\", readOnlyShown ? \"\" : null);\n palette?.registration.setReadOnly(readOnlyState());\n menu.refresh();\n }\n\n function showReadOnly(): void {\n readOnlyTimer = undefined;\n if (ledger.isClosed || !readOnly) return;\n readOnlyShown = true;\n applyReadOnly();\n }\n\n function unregisterPalette(): void {\n if (!palette) return;\n palette.detachTooltip();\n resizeObserver?.unobserve(palette.registration.element);\n palette = undefined;\n }\n ledger.defer(unregisterPalette);\n\n const menuHandle: MenuHandle = {\n trigger: menu.trigger,\n dropdown: menu.dropdown,\n isOpen: () => menu.isOpen(),\n open: (focus) => menu.open(focus),\n close: (closeOptions) => menu.close(closeOptions),\n refresh: () => menu.refresh(),\n setGroups: (groups) => {\n if (!ledger.isClosed) menu.setGroups(groups);\n },\n };\n\n const tooltipHandle: TooltipHandle = {\n attach: (control, content) => (ledger.isClosed ? () => {} : tooltip.attach(control, content)),\n hide: () => tooltip.hide(),\n };\n\n const legendHandle: LegendHandle | undefined = legend && {\n element: legend.element,\n body: legend.body,\n isOpen: () => legend.isOpen(),\n setOpen: (open) => {\n if (!ledger.isClosed) legend.setOpen(open);\n },\n toggle: () => {\n if (!ledger.isClosed) legend.toggle();\n },\n };\n\n const primaryHandle: PrimaryActionHandle | undefined = primary && {\n element: primary.element,\n isCollapsed: () => primary.isCollapsed(),\n refresh: () => {\n if (!ledger.isClosed) primary.refresh();\n },\n };\n\n const appearanceHandle: AppearanceHandle | undefined =\n appearance && darkCapable\n ? {\n choice: () => appearance.choice(),\n setChoice: (choice) => {\n if (ledger.isClosed) return;\n appearance.setChoice(choice);\n menu.refresh();\n },\n }\n : undefined;\n\n const inspectorHandle: InspectorHandle | undefined = inspector && {\n element: inspector.element,\n isOpen: () => inspector.isOpen(),\n open: () => {\n if (!ledger.isClosed) inspector.open();\n },\n close: () => {\n if (ledger.isClosed) return;\n if (inspector.isOpen()) moveFocusOutOf(inspector.element);\n inspector.close();\n },\n };\n\n return {\n root,\n canvas,\n host,\n lang,\n platform,\n messages,\n menu: menuHandle,\n tooltip: tooltipHandle,\n legend: legendHandle,\n inspector: inspectorHandle,\n primary: primaryHandle,\n appearance: appearanceHandle,\n setZoomTarget(target: ZoomTarget | null) {\n if (!ledger.isClosed) zoomPanel.setTarget(target);\n },\n fitInsets: currentFitInsets,\n registerPalette(registration) {\n if (ledger.isClosed) return () => {};\n unregisterPalette();\n palette = {\n registration,\n detachTooltip: tooltip.delegate(registration.element, \".entry\", (entry) =>\n registration.entryTooltip(entry),\n ),\n };\n resizeObserver?.observe(registration.element);\n registration.setReadOnly(readOnlyState());\n updateLayout();\n const registered = palette;\n return () => {\n if (palette !== registered) return;\n unregisterPalette();\n updateLayout();\n };\n },\n setProblems(summary) {\n if (ledger.isClosed || !pill) return;\n const listHadFocus = popover?.element.contains(ownerDocument.activeElement) ?? false;\n pill.set(summary);\n setState(\"data-problems\", pill.isShown() ? \"shown\" : null);\n popover?.setItems(summary.items ?? []);\n if (!pill.isShown() && popover?.isOpen()) {\n popover.close();\n // The pill went with the list, so the focus cannot return to it.\n if (listHadFocus) focusCanvasOrTrigger();\n }\n updateBottomRow();\n placeHint();\n },\n setStatus(next, statusOptions) {\n if (!ledger.isClosed) status.set(next, statusOptions?.delayMs ?? 0);\n },\n setEmptyHint(visible) {\n if (ledger.isClosed || !hint) return;\n if (!visible && hint.isShown()) moveFocusOutOf(hint.element);\n hint.setShown(visible);\n placeHint();\n },\n setReadOnly(next, readOnlyOptions) {\n if (ledger.isClosed) return;\n if (!next) {\n clearTimeout(readOnlyTimer);\n readOnlyTimer = undefined;\n readOnly = false;\n readOnlyShown = false;\n } else {\n readOnly = true;\n const delayMs = readOnlyOptions?.delayMs ?? 0;\n // Repeated invalid imports while typing keep the first timer, like the status box.\n if (!readOnlyShown && readOnlyTimer === undefined) {\n if (delayMs > 0) readOnlyTimer = setTimeout(showReadOnly, delayMs);\n else readOnlyShown = true;\n }\n }\n applyReadOnly();\n },\n isReadOnly: () => readOnly,\n setEmptyState: setEmptyStateShown,\n isEmptyStateShown: () => emptyState?.isShown() ?? false,\n toast: showToast,\n destroy() {\n ledger.close();\n },\n };\n}\n\n/**\n * An embedded root carries its own mode (guide §13.3): the token CSS resolves the roles on the\n * nearest `[data-cd-theme]`, so without it a light-only modeler would inherit a dark host page and\n * be half-dark against its light-drawn diagram. The root's own `data-cd-theme` would also drop the\n * host's high contrast, so `data-cd-kontrast` is mirrored from the host for as long as it lives.\n */\nfunction carryOwnMode(root: HTMLElement, theme: Theme, ledger: Ledger): void {\n ledger.attribute(root, \"data-cd-theme\", theme);\n const mirror = (): void => {\n if (ledger.isClosed) return;\n const kontrast = hostKontrast(root);\n if (root.getAttribute(\"data-cd-kontrast\") !== kontrast)\n ledger.attribute(root, \"data-cd-kontrast\", kontrast);\n };\n mirror();\n const MutationObserverClass = globalThis.MutationObserver;\n if (!MutationObserverClass) return;\n const observer = new MutationObserverClass(mirror);\n observer.observe(root.ownerDocument.documentElement, {\n attributes: true,\n attributeFilter: [\"data-cd-theme\", \"data-cd-kontrast\"],\n subtree: true,\n });\n ledger.defer(() => observer.disconnect());\n}\n"],"mappings":"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","names":["escapeAttribute","toast","isPrintable","element","element","element"]}
|