@miragon/modeler-shell 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/API.md +1902 -0
  2. package/LICENSE +21 -0
  3. package/README.md +435 -2
  4. package/THIRD_PARTY_NOTICES.md +52 -0
  5. package/dist/appearance-D3FUcbu6.d.cts +53 -0
  6. package/dist/appearance-D3FUcbu6.d.ts +53 -0
  7. package/dist/chunk-5JSZ4VGA.js +551 -0
  8. package/dist/chunk-5JSZ4VGA.js.map +1 -0
  9. package/dist/chunk-6LQOFACK.js +1576 -0
  10. package/dist/chunk-6LQOFACK.js.map +1 -0
  11. package/dist/chunk-N4QXFF3A.js +23 -0
  12. package/dist/chunk-N4QXFF3A.js.map +1 -0
  13. package/dist/chunk-RJRFR6N3.js +136 -0
  14. package/dist/chunk-RJRFR6N3.js.map +1 -0
  15. package/dist/core.cjs +619 -0
  16. package/dist/core.cjs.map +1 -0
  17. package/dist/core.d.cts +171 -0
  18. package/dist/core.d.ts +171 -0
  19. package/dist/core.js +91 -0
  20. package/dist/core.js.map +1 -0
  21. package/dist/diagram-js.cjs +1115 -0
  22. package/dist/diagram-js.cjs.map +1 -0
  23. package/dist/diagram-js.d.cts +163 -0
  24. package/dist/diagram-js.d.ts +163 -0
  25. package/dist/diagram-js.js +867 -0
  26. package/dist/diagram-js.js.map +1 -0
  27. package/dist/index.cjs +2175 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +20 -0
  30. package/dist/index.d.ts +20 -0
  31. package/dist/index.js +103 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/keymap-CObQE6q6.d.cts +151 -0
  34. package/dist/keymap-DORzHnK-.d.ts +151 -0
  35. package/dist/protocol-DhYBakWL.d.cts +15 -0
  36. package/dist/protocol-IeW8bf4f.d.ts +15 -0
  37. package/dist/shell.css +914 -0
  38. package/dist/testing-vscode-stub.cjs +332 -0
  39. package/dist/testing-vscode-stub.cjs.map +1 -0
  40. package/dist/testing-vscode-stub.d.cts +65 -0
  41. package/dist/testing-vscode-stub.d.ts +65 -0
  42. package/dist/testing-vscode-stub.js +154 -0
  43. package/dist/testing-vscode-stub.js.map +1 -0
  44. package/dist/testing.cjs +2364 -0
  45. package/dist/testing.cjs.map +1 -0
  46. package/dist/testing.d.cts +165 -0
  47. package/dist/testing.d.ts +165 -0
  48. package/dist/testing.js +2297 -0
  49. package/dist/testing.js.map +1 -0
  50. package/dist/types-B6NfkiUG.d.cts +66 -0
  51. package/dist/types-B6NfkiUG.d.ts +66 -0
  52. package/dist/types-DnZn9CPw.d.ts +284 -0
  53. package/dist/types-OuFlqZp0.d.cts +284 -0
  54. package/dist/vscode-extension.cjs +215 -0
  55. package/dist/vscode-extension.cjs.map +1 -0
  56. package/dist/vscode-extension.d.cts +103 -0
  57. package/dist/vscode-extension.d.ts +103 -0
  58. package/dist/vscode-extension.js +24 -0
  59. package/dist/vscode-extension.js.map +1 -0
  60. package/dist/vscode-webview.cjs +2198 -0
  61. package/dist/vscode-webview.cjs.map +1 -0
  62. package/dist/vscode-webview.d.cts +82 -0
  63. package/dist/vscode-webview.d.ts +82 -0
  64. package/dist/vscode-webview.js +250 -0
  65. package/dist/vscode-webview.js.map +1 -0
  66. package/package.json +145 -4
  67. package/src/core/appearance.ts +104 -0
  68. package/src/core/fit.ts +205 -0
  69. package/src/core/index.ts +84 -0
  70. package/src/core/keymap.ts +275 -0
  71. package/src/core/layout.ts +69 -0
  72. package/src/core/messages.ts +88 -0
  73. package/src/core/sizes.ts +85 -0
  74. package/src/core/types.ts +84 -0
  75. package/src/core/zoom.ts +74 -0
  76. package/src/core.ts +2 -0
  77. package/src/diagram-js/connect.ts +75 -0
  78. package/src/diagram-js/index.ts +16 -0
  79. package/src/diagram-js/module.ts +20 -0
  80. package/src/diagram-js/palette-skin.ts +267 -0
  81. package/src/diagram-js/palette.css +269 -0
  82. package/src/diagram-js/service.ts +240 -0
  83. package/src/diagram-js/types.ts +67 -0
  84. package/src/diagram-js/viewport.ts +564 -0
  85. package/src/diagram-js.ts +2 -0
  86. package/src/dom/element.ts +51 -0
  87. package/src/dom/hint.ts +51 -0
  88. package/src/dom/icons.ts +309 -0
  89. package/src/dom/index.ts +29 -0
  90. package/src/dom/inspector.ts +35 -0
  91. package/src/dom/keys.ts +59 -0
  92. package/src/dom/ledger.ts +87 -0
  93. package/src/dom/legend.ts +85 -0
  94. package/src/dom/menu.ts +393 -0
  95. package/src/dom/mount.ts +461 -0
  96. package/src/dom/problems.ts +72 -0
  97. package/src/dom/shell-dom.css +966 -0
  98. package/src/dom/status.ts +72 -0
  99. package/src/dom/tooltip.ts +237 -0
  100. package/src/dom/types.ts +277 -0
  101. package/src/dom/zoom-panel.ts +154 -0
  102. package/src/index.ts +3 -0
  103. package/src/shell.css +6 -0
  104. package/src/testing/cases.ts +1012 -0
  105. package/src/testing/checks.ts +832 -0
  106. package/src/testing/facts.ts +587 -0
  107. package/src/testing/geometry.ts +472 -0
  108. package/src/testing/harness.ts +138 -0
  109. package/src/testing/index.ts +15 -0
  110. package/src/testing/page-tools.ts +434 -0
  111. package/src/testing/page.ts +17 -0
  112. package/src/testing/vscode-stub.ts +237 -0
  113. package/src/testing-vscode-stub.ts +2 -0
  114. package/src/testing.ts +2 -0
  115. package/src/vscode/extension/html.ts +107 -0
  116. package/src/vscode/extension/index.ts +8 -0
  117. package/src/vscode/extension/reveal.ts +9 -0
  118. package/src/vscode/extension/theme-bridge.ts +85 -0
  119. package/src/vscode/extension/types.ts +36 -0
  120. package/src/vscode/protocol.ts +31 -0
  121. package/src/vscode/webview/appearance.ts +141 -0
  122. package/src/vscode/webview/index.ts +8 -0
  123. package/src/vscode/webview/mount.ts +76 -0
  124. package/src/vscode/webview/state.ts +116 -0
  125. package/src/vscode-extension.ts +2 -0
  126. package/src/vscode-webview.ts +2 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vscode-webview.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/vscode/protocol.ts","../src/vscode/webview/appearance.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","../src/vscode/webview/mount.ts","../src/vscode/webview/state.ts"],"sourcesContent":["// \"@miragon/modeler-shell/vscode/webview\": the webview side.\nexport * from \"./vscode/webview/index.js\";\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","import type { Appearance } from \"../core/index.js\";\n\n/** The one message the theme bridge posts to the webview. */\nexport const APPEARANCE_MESSAGE_TYPE = \"modelerShell.appearance\";\n\nexport interface AppearanceMessage {\n type: typeof APPEARANCE_MESSAGE_TYPE;\n /** Already resolved against the modeler's themes. */\n appearance: Appearance;\n}\n\n/** A plain, JSON-safe message (no `kontrast: undefined` key). */\nexport function appearanceMessage(appearance: Appearance): AppearanceMessage {\n return {\n type: APPEARANCE_MESSAGE_TYPE,\n appearance: appearance.kontrast\n ? { theme: appearance.theme, kontrast: appearance.kontrast }\n : { theme: appearance.theme },\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Type guard for `MessageEvent.data` in the webview. */\nexport function isAppearanceMessage(value: unknown): value is AppearanceMessage {\n if (!isRecord(value) || value.type !== APPEARANCE_MESSAGE_TYPE || !isRecord(value.appearance)) return false;\n const { theme, kontrast } = value.appearance;\n return (theme === \"light\" || theme === \"dark\") && (kontrast === undefined || kontrast === \"hoch\");\n}\n","import {\n REDUCED_MOTION_CLASS,\n appearanceAttributes,\n appearanceFromBodyClasses,\n reducedMotionFromBodyClasses,\n resolveAppearance,\n type Appearance,\n type Theme,\n} from \"../../core/index.js\";\nimport { isAppearanceMessage } from \"../protocol.js\";\n\nconst NO_TRANSITION_CLASS = \"cd-shell-no-transition\";\n\n/** The latest mode switch per `<html>`: only its second frame may lift the transition stop. */\nconst latestSwitch = new WeakMap<Element, number>();\n\nfunction showsAppearance(element: Element, appearance: Appearance): boolean {\n const attributes = appearanceAttributes(appearance);\n return (\n element.getAttribute(\"data-cd-theme\") === attributes[\"data-cd-theme\"] &&\n element.getAttribute(\"data-cd-kontrast\") === (attributes[\"data-cd-kontrast\"] ?? null)\n );\n}\n\n/**\n * Writes `data-cd-theme` and `data-cd-kontrast` on `element` (default `<html>`) in one task, with\n * transitions suppressed for one frame: adds `cd-shell-no-transition` to `<html>`, sets both\n * attributes and removes the class in a nested `requestAnimationFrame` (after the last of several\n * quick switches).\n */\nexport function applyAppearance(appearance: Appearance, element?: HTMLElement): void {\n const target = element ?? document.documentElement;\n const html = target.ownerDocument.documentElement;\n const attributes = appearanceAttributes(appearance);\n const kontrast = attributes[\"data-cd-kontrast\"];\n\n const switchId = (latestSwitch.get(html) ?? 0) + 1;\n latestSwitch.set(html, switchId);\n html.classList.add(NO_TRANSITION_CLASS);\n target.setAttribute(\"data-cd-theme\", attributes[\"data-cd-theme\"]);\n if (kontrast) target.setAttribute(\"data-cd-kontrast\", kontrast);\n else target.removeAttribute(\"data-cd-kontrast\");\n\n requestAnimationFrame(() =>\n requestAnimationFrame(() => {\n if (latestSwitch.get(html) !== switchId) return;\n latestSwitch.delete(html);\n html.classList.remove(NO_TRANSITION_CLASS);\n }),\n );\n}\n\nexport interface AppearanceListenerOptions {\n /** The modes the modeler can show; the body-class fallback resolves against them. */\n themes: readonly Theme[];\n}\n\n/**\n * Listens for `AppearanceMessage`s on `window` and applies them to `<html>`, resolved against\n * `themes` once more so a webview never shows a mode its bundle cannot. A page whose `<html>` has\n * no `data-cd-theme` at connect (no `renderWebviewHtml`) falls back to the VS Code body classes,\n * through a `MutationObserver` on `<body>` until the first message (resolved against `themes`).\n * With the attributes of `renderWebviewHtml` there is no fallback: the extension's bridge knows the\n * `colorTheme` setting, the body classes do not, and VS Code changes them before the bridge's\n * message arrives, which would flash the mode without the setting. Returns the disconnect\n * function. Throws when `themes` is empty.\n */\nexport function connectAppearance(options: AppearanceListenerOptions): () => void {\n const { themes } = options;\n if (themes.length === 0) {\n throw new Error(\"@miragon/modeler-shell: connectAppearance needs at least one theme\");\n }\n const html = document.documentElement;\n const show = (requested: Appearance): void => {\n const resolved = resolveAppearance(requested, themes);\n if (!showsAppearance(html, resolved)) applyAppearance(resolved, html);\n };\n\n let fallbackActive = !html.hasAttribute(\"data-cd-theme\");\n const applyBodyClasses = (): void => {\n if (!fallbackActive || !document.body) return;\n const requested = appearanceFromBodyClasses(document.body.classList);\n if (requested) show(requested);\n };\n const observer = new MutationObserver(applyBodyClasses);\n const startFallback = (): void => {\n if (!fallbackActive || !document.body) return;\n observer.observe(document.body, { attributes: true, attributeFilter: [\"class\"] });\n applyBodyClasses();\n };\n const stopFallback = (): void => {\n if (!fallbackActive) return;\n fallbackActive = false;\n observer.disconnect();\n document.removeEventListener(\"DOMContentLoaded\", startFallback);\n };\n\n const onMessage = (event: MessageEvent): void => {\n if (!isAppearanceMessage(event.data)) return;\n stopFallback();\n show(event.data.appearance);\n };\n\n window.addEventListener(\"message\", onMessage);\n if (document.body) startFallback();\n else if (fallbackActive) document.addEventListener(\"DOMContentLoaded\", startFallback, { once: true });\n\n return () => {\n window.removeEventListener(\"message\", onMessage);\n fallbackActive = false;\n observer.disconnect();\n document.removeEventListener(\"DOMContentLoaded\", startFallback);\n };\n}\n\n/**\n * Mirrors VS Code's `workbench.reduceMotion` (the body class `vscode-reduce-motion`, which VS Code\n * keeps up to date) as `REDUCED_MOTION_CLASS` on `<html>` for the whole session: the shell's\n * animations stop and an explicit fit jumps, as under `prefers-reduced-motion` (guide §5.14, §7).\n * Returns the disconnect function, which removes the class again.\n */\nexport function connectReducedMotion(): () => void {\n const html = document.documentElement;\n const apply = (): void => {\n if (document.body)\n html.classList.toggle(REDUCED_MOTION_CLASS, reducedMotionFromBodyClasses(document.body.classList));\n };\n const observer = new MutationObserver(apply);\n const start = (): void => {\n if (!document.body) return;\n observer.observe(document.body, { attributes: true, attributeFilter: [\"class\"] });\n apply();\n };\n if (document.body) start();\n else document.addEventListener(\"DOMContentLoaded\", start, { once: true });\n return () => {\n observer.disconnect();\n document.removeEventListener(\"DOMContentLoaded\", start);\n html.classList.remove(REDUCED_MOTION_CLASS);\n };\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, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\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","import { mountShell, type ShellHandle, type ShellOptions } from \"../../dom/index.js\";\nimport { connectAppearance, connectReducedMotion, type AppearanceListenerOptions } from \"./appearance.js\";\n\nexport interface VsCodeShellOptions\n extends Omit<ShellOptions, \"host\" | \"keyScope\" | \"themes\">, AppearanceListenerOptions {}\n\n/** The shell's handle with a `destroy` that runs `beforeDestroy` first; every other member delegates. */\nfunction withDestroyHook(shell: ShellHandle, beforeDestroy: () => void): ShellHandle {\n return {\n get root() {\n return shell.root;\n },\n get canvas() {\n return shell.canvas;\n },\n get host() {\n return shell.host;\n },\n get lang() {\n return shell.lang;\n },\n get platform() {\n return shell.platform;\n },\n get messages() {\n return shell.messages;\n },\n get menu() {\n return shell.menu;\n },\n get tooltip() {\n return shell.tooltip;\n },\n get legend() {\n return shell.legend;\n },\n get inspector() {\n return shell.inspector;\n },\n setZoomTarget: (target) => shell.setZoomTarget(target),\n fitInsets: () => shell.fitInsets(),\n registerPalette: (palette) => shell.registerPalette(palette),\n setProblems: (summary) => shell.setProblems(summary),\n setStatus: (status, options) => shell.setStatus(status, options),\n setEmptyHint: (visible) => shell.setEmptyHint(visible),\n setReadOnly: (readOnly, options) => shell.setReadOnly(readOnly, options),\n isReadOnly: () => shell.isReadOnly(),\n destroy() {\n beforeDestroy();\n shell.destroy();\n },\n };\n}\n\n/**\n * `mountShell` for a VS Code webview: `host: \"ide\"`, the key listener on `document` (VS Code's own\n * listener sits on `window`, so handled keys are stopped before it), `cd-shell-document` on\n * `<html>`, plus `connectAppearance` and `connectReducedMotion`. `destroy()` also disconnects both.\n */\nexport function mountVsCodeShell(root: HTMLElement, options: VsCodeShellOptions): ShellHandle {\n const { themes } = options;\n const disconnectAppearance = connectAppearance({ themes });\n const disconnectReducedMotion = connectReducedMotion();\n const disconnect = (): void => {\n disconnectAppearance();\n disconnectReducedMotion();\n };\n let shell: ShellHandle;\n try {\n shell = mountShell(root, { ...options, host: \"ide\", keyScope: \"document\" });\n } catch (error) {\n disconnect();\n throw error;\n }\n return withDestroyHook(shell, disconnect);\n}\n","import type { Bounds, ViewportState } from \"../../core/index.js\";\n\n/** `acquireVsCodeApi()` as far as the state helpers need it. */\nexport interface WebviewStateApi {\n getState(): unknown;\n setState(state: unknown): void;\n}\n\n/** What the shell keeps across a webview rebuild (guide §13.5: legend state and view). */\nexport interface ShellWebviewState {\n legendOpen?: boolean | undefined;\n view?: ViewportState | undefined;\n}\n\n/** The key under which the shell's part lives in the webview state; other keys stay untouched. */\nexport const SHELL_STATE_KEY = \"modelerShell\";\n\ntype StateRecord = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is StateRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction storedState(api: WebviewStateApi): StateRecord {\n const state = api.getState();\n return isRecord(state) ? state : {};\n}\n\nfunction viewboxFrom(value: unknown): Bounds | undefined {\n if (!isRecord(value)) return undefined;\n const { x, y, width, height } = value;\n if (typeof x !== \"number\" || typeof y !== \"number\") return undefined;\n if (typeof width !== \"number\" || typeof height !== \"number\") return undefined;\n if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(width) || !Number.isFinite(height)) {\n return undefined;\n }\n return width > 0 && height > 0 ? { x, y, width, height } : undefined;\n}\n\nfunction viewFrom(value: unknown): ViewportState | undefined {\n if (!isRecord(value) || typeof value.userMoved !== \"boolean\") return undefined;\n const viewbox = viewboxFrom(value.viewbox);\n return viewbox ? { viewbox, userMoved: value.userMoved } : undefined;\n}\n\n/** The shell's part of `api.getState()`; `{}` when there is none or it is malformed. */\nexport function readShellState(api: WebviewStateApi): ShellWebviewState {\n const part = storedState(api)[SHELL_STATE_KEY];\n if (!isRecord(part)) return {};\n const state: ShellWebviewState = {};\n if (typeof part.legendOpen === \"boolean\") state.legendOpen = part.legendOpen;\n const view = viewFrom(part.view);\n if (view) state.view = view;\n return state;\n}\n\n/**\n * Merges `patch` into the shell's part and writes the whole state back, keeping every other key.\n * A value that is `undefined` (for example `viewport.getState()` before the first import) or\n * malformed leaves the stored value alone; nothing is written when nothing changed.\n */\nexport function writeShellState(api: WebviewStateApi, patch: ShellWebviewState): void {\n const state = storedState(api);\n const part = isRecord(state[SHELL_STATE_KEY]) ? (state[SHELL_STATE_KEY] as StateRecord) : {};\n const next: StateRecord = { ...part };\n if (typeof patch.legendOpen === \"boolean\") next.legendOpen = patch.legendOpen;\n const view = viewFrom(patch.view);\n if (view) next.view = view;\n if (JSON.stringify(next) === JSON.stringify(state[SHELL_STATE_KEY])) return;\n api.setState({ ...state, [SHELL_STATE_KEY]: next });\n}\n\n/** What `persistView` reads of a viewport (`connectDiagramJs(…).viewport`). */\nexport interface PersistableView {\n onChange(listener: () => void): () => void;\n getState(): ViewportState | undefined;\n}\n\nexport interface PersistViewOptions {\n /** Quiet time before the write, default 250ms. */\n delayMs?: number | undefined;\n}\n\n/** A pan, a wheel zoom or a fit animation changes the view on every frame. */\nconst PERSIST_VIEW_DELAY_MS = 250;\n\n/**\n * Keeps the stored view (`writeShellState(api, { view })`) up to date once the view has rested for\n * `delayMs`, instead of one `vscode.setState` IPC message per animation frame. Returns the stop\n * function; it writes a pending change at once.\n */\nexport function persistView(\n api: WebviewStateApi,\n viewport: PersistableView,\n options: PersistViewOptions = {},\n): () => void {\n const delayMs = options.delayMs ?? PERSIST_VIEW_DELAY_MS;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const write = (): void => {\n timer = undefined;\n writeShellState(api, { view: viewport.getState() });\n };\n const unsubscribe = viewport.onChange(() => {\n clearTimeout(timer);\n timer = setTimeout(write, delayMs);\n });\n let stopped = false;\n return () => {\n if (stopped) return;\n stopped = true;\n unsubscribe();\n if (timer === undefined) return;\n clearTimeout(timer);\n write();\n };\n}\n"],"mappings":"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","names":["element","element","isRecord"]}
@@ -0,0 +1,82 @@
1
+ import { T as Theme, A as Appearance } from './appearance-D3FUcbu6.cjs';
2
+ import { S as ShellOptions, a as ShellHandle } from './types-OuFlqZp0.cjs';
3
+ import { V as ViewportState } from './types-B6NfkiUG.cjs';
4
+ export { A as APPEARANCE_MESSAGE_TYPE, a as AppearanceMessage, b as appearanceMessage, i as isAppearanceMessage } from './protocol-DhYBakWL.cjs';
5
+ import './keymap-CObQE6q6.cjs';
6
+
7
+ /**
8
+ * Writes `data-cd-theme` and `data-cd-kontrast` on `element` (default `<html>`) in one task, with
9
+ * transitions suppressed for one frame: adds `cd-shell-no-transition` to `<html>`, sets both
10
+ * attributes and removes the class in a nested `requestAnimationFrame` (after the last of several
11
+ * quick switches).
12
+ */
13
+ declare function applyAppearance(appearance: Appearance, element?: HTMLElement): void;
14
+ interface AppearanceListenerOptions {
15
+ /** The modes the modeler can show; the body-class fallback resolves against them. */
16
+ themes: readonly Theme[];
17
+ }
18
+ /**
19
+ * Listens for `AppearanceMessage`s on `window` and applies them to `<html>`, resolved against
20
+ * `themes` once more so a webview never shows a mode its bundle cannot. A page whose `<html>` has
21
+ * no `data-cd-theme` at connect (no `renderWebviewHtml`) falls back to the VS Code body classes,
22
+ * through a `MutationObserver` on `<body>` until the first message (resolved against `themes`).
23
+ * With the attributes of `renderWebviewHtml` there is no fallback: the extension's bridge knows the
24
+ * `colorTheme` setting, the body classes do not, and VS Code changes them before the bridge's
25
+ * message arrives, which would flash the mode without the setting. Returns the disconnect
26
+ * function. Throws when `themes` is empty.
27
+ */
28
+ declare function connectAppearance(options: AppearanceListenerOptions): () => void;
29
+ /**
30
+ * Mirrors VS Code's `workbench.reduceMotion` (the body class `vscode-reduce-motion`, which VS Code
31
+ * keeps up to date) as `REDUCED_MOTION_CLASS` on `<html>` for the whole session: the shell's
32
+ * animations stop and an explicit fit jumps, as under `prefers-reduced-motion` (guide §5.14, §7).
33
+ * Returns the disconnect function, which removes the class again.
34
+ */
35
+ declare function connectReducedMotion(): () => void;
36
+
37
+ interface VsCodeShellOptions extends Omit<ShellOptions, "host" | "keyScope" | "themes">, AppearanceListenerOptions {
38
+ }
39
+ /**
40
+ * `mountShell` for a VS Code webview: `host: "ide"`, the key listener on `document` (VS Code's own
41
+ * listener sits on `window`, so handled keys are stopped before it), `cd-shell-document` on
42
+ * `<html>`, plus `connectAppearance` and `connectReducedMotion`. `destroy()` also disconnects both.
43
+ */
44
+ declare function mountVsCodeShell(root: HTMLElement, options: VsCodeShellOptions): ShellHandle;
45
+
46
+ /** `acquireVsCodeApi()` as far as the state helpers need it. */
47
+ interface WebviewStateApi {
48
+ getState(): unknown;
49
+ setState(state: unknown): void;
50
+ }
51
+ /** What the shell keeps across a webview rebuild (guide §13.5: legend state and view). */
52
+ interface ShellWebviewState {
53
+ legendOpen?: boolean | undefined;
54
+ view?: ViewportState | undefined;
55
+ }
56
+ /** The key under which the shell's part lives in the webview state; other keys stay untouched. */
57
+ declare const SHELL_STATE_KEY = "modelerShell";
58
+ /** The shell's part of `api.getState()`; `{}` when there is none or it is malformed. */
59
+ declare function readShellState(api: WebviewStateApi): ShellWebviewState;
60
+ /**
61
+ * Merges `patch` into the shell's part and writes the whole state back, keeping every other key.
62
+ * A value that is `undefined` (for example `viewport.getState()` before the first import) or
63
+ * malformed leaves the stored value alone; nothing is written when nothing changed.
64
+ */
65
+ declare function writeShellState(api: WebviewStateApi, patch: ShellWebviewState): void;
66
+ /** What `persistView` reads of a viewport (`connectDiagramJs(…).viewport`). */
67
+ interface PersistableView {
68
+ onChange(listener: () => void): () => void;
69
+ getState(): ViewportState | undefined;
70
+ }
71
+ interface PersistViewOptions {
72
+ /** Quiet time before the write, default 250ms. */
73
+ delayMs?: number | undefined;
74
+ }
75
+ /**
76
+ * Keeps the stored view (`writeShellState(api, { view })`) up to date once the view has rested for
77
+ * `delayMs`, instead of one `vscode.setState` IPC message per animation frame. Returns the stop
78
+ * function; it writes a pending change at once.
79
+ */
80
+ declare function persistView(api: WebviewStateApi, viewport: PersistableView, options?: PersistViewOptions): () => void;
81
+
82
+ export { type AppearanceListenerOptions, type PersistViewOptions, type PersistableView, SHELL_STATE_KEY, type ShellWebviewState, type VsCodeShellOptions, type WebviewStateApi, applyAppearance, connectAppearance, connectReducedMotion, mountVsCodeShell, persistView, readShellState, writeShellState };
@@ -0,0 +1,82 @@
1
+ import { T as Theme, A as Appearance } from './appearance-D3FUcbu6.js';
2
+ import { S as ShellOptions, a as ShellHandle } from './types-DnZn9CPw.js';
3
+ import { V as ViewportState } from './types-B6NfkiUG.js';
4
+ export { A as APPEARANCE_MESSAGE_TYPE, a as AppearanceMessage, b as appearanceMessage, i as isAppearanceMessage } from './protocol-IeW8bf4f.js';
5
+ import './keymap-DORzHnK-.js';
6
+
7
+ /**
8
+ * Writes `data-cd-theme` and `data-cd-kontrast` on `element` (default `<html>`) in one task, with
9
+ * transitions suppressed for one frame: adds `cd-shell-no-transition` to `<html>`, sets both
10
+ * attributes and removes the class in a nested `requestAnimationFrame` (after the last of several
11
+ * quick switches).
12
+ */
13
+ declare function applyAppearance(appearance: Appearance, element?: HTMLElement): void;
14
+ interface AppearanceListenerOptions {
15
+ /** The modes the modeler can show; the body-class fallback resolves against them. */
16
+ themes: readonly Theme[];
17
+ }
18
+ /**
19
+ * Listens for `AppearanceMessage`s on `window` and applies them to `<html>`, resolved against
20
+ * `themes` once more so a webview never shows a mode its bundle cannot. A page whose `<html>` has
21
+ * no `data-cd-theme` at connect (no `renderWebviewHtml`) falls back to the VS Code body classes,
22
+ * through a `MutationObserver` on `<body>` until the first message (resolved against `themes`).
23
+ * With the attributes of `renderWebviewHtml` there is no fallback: the extension's bridge knows the
24
+ * `colorTheme` setting, the body classes do not, and VS Code changes them before the bridge's
25
+ * message arrives, which would flash the mode without the setting. Returns the disconnect
26
+ * function. Throws when `themes` is empty.
27
+ */
28
+ declare function connectAppearance(options: AppearanceListenerOptions): () => void;
29
+ /**
30
+ * Mirrors VS Code's `workbench.reduceMotion` (the body class `vscode-reduce-motion`, which VS Code
31
+ * keeps up to date) as `REDUCED_MOTION_CLASS` on `<html>` for the whole session: the shell's
32
+ * animations stop and an explicit fit jumps, as under `prefers-reduced-motion` (guide §5.14, §7).
33
+ * Returns the disconnect function, which removes the class again.
34
+ */
35
+ declare function connectReducedMotion(): () => void;
36
+
37
+ interface VsCodeShellOptions extends Omit<ShellOptions, "host" | "keyScope" | "themes">, AppearanceListenerOptions {
38
+ }
39
+ /**
40
+ * `mountShell` for a VS Code webview: `host: "ide"`, the key listener on `document` (VS Code's own
41
+ * listener sits on `window`, so handled keys are stopped before it), `cd-shell-document` on
42
+ * `<html>`, plus `connectAppearance` and `connectReducedMotion`. `destroy()` also disconnects both.
43
+ */
44
+ declare function mountVsCodeShell(root: HTMLElement, options: VsCodeShellOptions): ShellHandle;
45
+
46
+ /** `acquireVsCodeApi()` as far as the state helpers need it. */
47
+ interface WebviewStateApi {
48
+ getState(): unknown;
49
+ setState(state: unknown): void;
50
+ }
51
+ /** What the shell keeps across a webview rebuild (guide §13.5: legend state and view). */
52
+ interface ShellWebviewState {
53
+ legendOpen?: boolean | undefined;
54
+ view?: ViewportState | undefined;
55
+ }
56
+ /** The key under which the shell's part lives in the webview state; other keys stay untouched. */
57
+ declare const SHELL_STATE_KEY = "modelerShell";
58
+ /** The shell's part of `api.getState()`; `{}` when there is none or it is malformed. */
59
+ declare function readShellState(api: WebviewStateApi): ShellWebviewState;
60
+ /**
61
+ * Merges `patch` into the shell's part and writes the whole state back, keeping every other key.
62
+ * A value that is `undefined` (for example `viewport.getState()` before the first import) or
63
+ * malformed leaves the stored value alone; nothing is written when nothing changed.
64
+ */
65
+ declare function writeShellState(api: WebviewStateApi, patch: ShellWebviewState): void;
66
+ /** What `persistView` reads of a viewport (`connectDiagramJs(…).viewport`). */
67
+ interface PersistableView {
68
+ onChange(listener: () => void): () => void;
69
+ getState(): ViewportState | undefined;
70
+ }
71
+ interface PersistViewOptions {
72
+ /** Quiet time before the write, default 250ms. */
73
+ delayMs?: number | undefined;
74
+ }
75
+ /**
76
+ * Keeps the stored view (`writeShellState(api, { view })`) up to date once the view has rested for
77
+ * `delayMs`, instead of one `vscode.setState` IPC message per animation frame. Returns the stop
78
+ * function; it writes a pending change at once.
79
+ */
80
+ declare function persistView(api: WebviewStateApi, viewport: PersistableView, options?: PersistViewOptions): () => void;
81
+
82
+ export { type AppearanceListenerOptions, type PersistViewOptions, type PersistableView, SHELL_STATE_KEY, type ShellWebviewState, type VsCodeShellOptions, type WebviewStateApi, applyAppearance, connectAppearance, connectReducedMotion, mountVsCodeShell, persistView, readShellState, writeShellState };