@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/dom/icons.ts","../src/dom/element.ts","../src/dom/hint.ts","../src/dom/inspector.ts","../src/dom/keys.ts","../src/dom/ledger.ts","../src/dom/legend.ts","../src/dom/menu.ts","../src/dom/problems.ts","../src/dom/status.ts","../src/dom/tooltip.ts","../src/dom/zoom-panel.ts","../src/dom/mount.ts"],"sourcesContent":["/*! @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","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","import type { ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { LegendHandle, LegendOptions } from \"./types.js\";\n\nexport interface LegendController extends LegendHandle {\n /** The start state once the container height is known; never reported through `onToggle`. */\n start(open: boolean): void;\n isStarted(): boolean;\n destroy(): void;\n}\n\nexport interface LegendContext {\n ownerDocument: Document;\n messages: ShellMessages;\n tooltip: TooltipController;\n titleId: string;\n options: LegendOptions;\n onChange(open: boolean): void;\n /** Where the focus goes when the close button hides the legend under it. */\n focusAfterClose(): void;\n}\n\nexport function createLegend(context: LegendContext): LegendController {\n const { ownerDocument, messages, tooltip, titleId, options } = context;\n const close = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: \"cd-shell-legend-close\",\n \"aria-label\": messages.closeLegend,\n });\n close.append(iconElement(\"x\"));\n const body = createElement(ownerDocument, \"div\", { class: \"cd-shell-legend-body\" });\n const element = createElement(\n ownerDocument,\n \"section\",\n { class: \"cd-shell-legend cd-shell-island\", \"data-chrome\": \"legend\", \"aria-labelledby\": titleId },\n createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-legend-header\" },\n createElement(ownerDocument, \"div\", { class: \"cd-shell-legend-title\", id: titleId }, messages.legend),\n close,\n ),\n body,\n );\n element.hidden = true;\n options.render(body);\n\n let open = false;\n let started = false;\n const detachTooltip = tooltip.attach(close, { label: messages.closeLegend });\n\n function apply(next: boolean): boolean {\n started = true;\n if (next === open) return false;\n open = next;\n element.hidden = !open;\n if (!open && element.contains(ownerDocument.activeElement)) context.focusAfterClose();\n context.onChange(open);\n return true;\n }\n\n function setOpen(next: boolean): void {\n if (apply(next)) options.onToggle?.(next);\n }\n\n close.addEventListener(\"click\", () => setOpen(false));\n\n return {\n element,\n body,\n isOpen: () => open,\n setOpen,\n toggle: () => setOpen(!open),\n start(initial) {\n if (!started) apply(initial);\n },\n isStarted: () => started,\n destroy() {\n detachTooltip();\n element.remove();\n },\n };\n}\n","import { ariaKeyShortcutsFromLabel, matchChromeKey, type ShellMessages } from \"../core/index.js\";\nimport { createElement, toggleAttribute } from \"./element.js\";\nimport { iconElement, type ShellIconName } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { MenuCheckboxEntry, MenuEntry, MenuGroups, MenuHandle, MenuRadioGroup } from \"./types.js\";\n\ntype GroupName = keyof MenuGroups;\nconst GROUP_ORDER: readonly GroupName[] = [\"model\", \"export\", \"help\"];\n\ninterface Item {\n /** Stable across renders, so a re-render keeps the focus on the same entry. */\n key: string;\n element: HTMLButtonElement;\n label: string;\n disabled: boolean;\n activate(): void;\n}\n\nexport interface MenuContext {\n root: HTMLElement;\n layer: HTMLElement;\n id: string;\n messages: ShellMessages;\n tooltip: TooltipController;\n groups: MenuGroups;\n /** Entries the shell appends to the Model group (the Legend checkbox). */\n shellModelEntries(): readonly MenuCheckboxEntry[];\n isReadOnly(): boolean;\n}\n\nexport interface MenuController extends MenuHandle {\n destroy(): void;\n}\n\nfunction isPrintable(event: KeyboardEvent): boolean {\n return event.key.length === 1 && /\\S/.test(event.key) && !event.ctrlKey && !event.metaKey && !event.altKey;\n}\n\nexport function createMenu(context: MenuContext): MenuController {\n const { root, layer, id, messages, tooltip } = context;\n const ownerDocument = root.ownerDocument;\n let groups = context.groups;\n let items: Item[] = [];\n let destroyed = false;\n\n const trigger = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: \"cd-shell-menu-trigger cd-shell-island\",\n \"data-chrome\": \"menu\",\n \"aria-label\": messages.menu,\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": \"false\",\n \"aria-controls\": id,\n });\n trigger.append(iconElement(\"menu\"));\n\n const dropdown = createElement(ownerDocument, \"div\", {\n class: \"cd-shell-menu\",\n id,\n role: \"menu\",\n \"aria-label\": messages.menu,\n });\n dropdown.hidden = true;\n layer.prepend(dropdown);\n\n const isOpen = (): boolean => !dropdown.hidden;\n\n function entriesOf(name: GroupName): readonly MenuEntry[] {\n const own = groups[name] ?? [];\n return name === \"model\" ? [...own, ...context.shellModelEntries()] : own;\n }\n\n function hasEntries(): boolean {\n return GROUP_ORDER.some((name) => entriesOf(name).length > 0);\n }\n\n function updateTriggerVisibility(): void {\n trigger.hidden = !hasEntries();\n if (trigger.hidden) close();\n }\n\n // Guide §13.5: on a read-only canvas the Model entries that change the document are aria-disabled.\n // View-only toggles (the shell's Legend, a modeler's Type captions) opt out and stay usable.\n function isDisabled(entry: MenuEntry, group: GroupName): boolean {\n if (group === \"model\" && context.isReadOnly() && entry.keepEnabledWhenReadOnly !== true) return true;\n return entry.disabled?.() ?? false;\n }\n\n function itemElement(\n role: \"menuitem\" | \"menuitemcheckbox\" | \"menuitemradio\",\n label: string,\n options: {\n icon?: ShellIconName | undefined;\n end?: Node | undefined;\n disabled: boolean;\n checked?: boolean;\n },\n ): HTMLButtonElement {\n const iconSlot = createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-icon\" });\n if (options.icon) iconSlot.append(iconElement(options.icon));\n const element = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-menu-item\", role, tabindex: \"-1\" },\n iconSlot,\n createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-label\" }, label),\n options.end && createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-item-end\" }, options.end),\n );\n toggleAttribute(element, \"aria-disabled\", options.disabled && \"true\");\n if (options.checked !== undefined) element.setAttribute(\"aria-checked\", String(options.checked));\n return element;\n }\n\n function checkMark(): SVGSVGElement {\n return iconElement(\"check\", { className: \"cd-shell-menu-check\" });\n }\n\n function renderEntry(entry: Exclude<MenuEntry, MenuRadioGroup>, group: GroupName): Item {\n const disabled = isDisabled(entry, group);\n if (entry.kind === \"checkbox\") {\n const checked = entry.checked();\n const element = itemElement(\"menuitemcheckbox\", entry.label, {\n icon: entry.icon,\n end: checkMark(),\n disabled,\n checked,\n });\n element.dataset.menuId = entry.id;\n element.dataset.menuGroup = group;\n return {\n key: entry.id,\n element,\n label: entry.label,\n disabled,\n activate() {\n entry.onToggle(!entry.checked());\n refresh();\n },\n };\n }\n const shortcut =\n entry.kind === \"action\" && entry.shortcut\n ? createElement(ownerDocument, \"span\", { class: \"cd-shell-menu-shortcut\" }, entry.shortcut)\n : undefined;\n const element = itemElement(\"menuitem\", entry.label, { icon: entry.icon, end: shortcut, disabled });\n element.dataset.menuId = entry.id;\n element.dataset.menuGroup = group;\n if (entry.kind === \"action\") {\n const keyShortcuts =\n entry.ariaKeyShortcuts ?? (entry.shortcut ? ariaKeyShortcutsFromLabel(entry.shortcut) : undefined);\n toggleAttribute(element, \"aria-keyshortcuts\", keyShortcuts || null);\n }\n if (entry.kind === \"dialog\") element.setAttribute(\"aria-haspopup\", \"dialog\");\n if (entry.kind === \"action\" && entry.danger) element.dataset.danger = \"\";\n return {\n key: entry.id,\n element,\n label: entry.label,\n disabled,\n activate() {\n close({ restoreFocus: true });\n entry.onSelect();\n },\n };\n }\n\n function renderRadioGroup(\n entry: MenuRadioGroup,\n group: GroupName,\n ): { element: HTMLElement; items: Item[] } {\n const disabled = isDisabled(entry, group);\n const value = entry.value();\n const container = createElement(\n ownerDocument,\n \"div\",\n {\n class: \"cd-shell-menu-group\",\n role: \"group\",\n \"aria-label\": entry.label,\n \"data-menu-id\": entry.id,\n \"data-menu-group\": group,\n },\n // The group's aria-label carries the heading; a menu holds no loose text.\n createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-menu-heading\", \"aria-hidden\": \"true\" },\n entry.label,\n ),\n );\n const radioItems = entry.options.map((option): Item => {\n const element = itemElement(\"menuitemradio\", option.label, {\n end: checkMark(),\n disabled,\n checked: option.value === value,\n });\n element.dataset.menuValue = option.value;\n container.append(element);\n return {\n key: `${entry.id}\\u0000${option.value}`,\n element,\n label: option.label,\n disabled,\n activate() {\n if (entry.value() !== option.value) entry.onSelect(option.value);\n refresh();\n },\n };\n });\n return { element: container, items: radioItems };\n }\n\n function render(): void {\n const focusedKey = items.find((item) => item.element === ownerDocument.activeElement)?.key;\n const nodes: HTMLElement[] = [];\n const rendered: Item[] = [];\n for (const name of GROUP_ORDER) {\n const entries = entriesOf(name);\n if (entries.length === 0) continue;\n if (nodes.length > 0) {\n nodes.push(\n createElement(ownerDocument, \"div\", { class: \"cd-shell-menu-separator\", role: \"separator\" }),\n );\n }\n for (const entry of entries) {\n if (entry.kind === \"radio\") {\n const radio = renderRadioGroup(entry, name);\n nodes.push(radio.element);\n rendered.push(...radio.items);\n } else {\n const item = renderEntry(entry, name);\n nodes.push(item.element);\n rendered.push(item);\n }\n }\n }\n for (const item of rendered) {\n item.element.addEventListener(\"click\", () => {\n if (!item.disabled) item.activate();\n });\n }\n dropdown.replaceChildren(...nodes);\n items = rendered;\n if (focusedKey !== undefined && isOpen()) {\n (items.find((item) => item.key === focusedKey) ?? items[0])?.element.focus();\n }\n }\n\n function focusAt(index: number): void {\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.element.focus();\n }\n\n function currentIndex(): number {\n return items.findIndex((item) => item.element === ownerDocument.activeElement);\n }\n\n function typeAhead(character: string): void {\n const start = currentIndex();\n const lower = character.toLowerCase();\n for (let step = 1; step <= items.length; step++) {\n const index = (Math.max(start, -1) + step) % items.length;\n if (items[index]?.label.toLowerCase().startsWith(lower)) {\n focusAt(index);\n return;\n }\n }\n }\n\n const onOutsidePointerDown = (event: PointerEvent): void => {\n const target = event.target as Node | null;\n if (target && (dropdown.contains(target) || trigger.contains(target))) return;\n close();\n };\n\n // The focus left the document (a click into the VS Code workbench, another iframe): from the\n // user's view a click outside, so the menu closes without moving the focus (guide §5.4).\n const onWindowBlur = (): void => close();\n\n function open(focus: \"first\" | \"last\" = \"first\"): void {\n if (destroyed || !hasEntries()) return;\n tooltip.hide();\n const wasOpen = isOpen();\n render();\n if (!wasOpen) {\n dropdown.hidden = false;\n trigger.setAttribute(\"aria-expanded\", \"true\");\n // Capture phase: diagram-js stops pointer events on palette, context pad and canvas.\n ownerDocument.addEventListener(\"pointerdown\", onOutsidePointerDown, true);\n ownerDocument.defaultView?.addEventListener(\"blur\", onWindowBlur);\n }\n focusAt(focus === \"last\" ? items.length - 1 : 0);\n }\n\n function close(options: { restoreFocus?: boolean } = {}): void {\n if (!isOpen()) return;\n dropdown.hidden = true;\n trigger.setAttribute(\"aria-expanded\", \"false\");\n ownerDocument.removeEventListener(\"pointerdown\", onOutsidePointerDown, true);\n ownerDocument.defaultView?.removeEventListener(\"blur\", onWindowBlur);\n if (options.restoreFocus && !trigger.hidden) trigger.focus();\n }\n\n function refresh(): void {\n if (isOpen()) render();\n }\n\n trigger.addEventListener(\"click\", () => {\n if (isOpen()) close();\n else open(\"first\");\n });\n\n // Keys the menu consumes stop here, in every host like the palette's: a modeler's keyboard on\n // document (Event Storming moves the selection on ↑/↓, deletes it on Delete, creates a sticky on\n // E) must never act on them, and VS Code never sees them.\n function consume(event: KeyboardEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n\n trigger.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\" || event.key === \" \" || event.key === \"ArrowDown\") {\n consume(event);\n open(\"first\");\n } else if (event.key === \"ArrowUp\") {\n consume(event);\n open(\"last\");\n }\n });\n\n dropdown.addEventListener(\"keydown\", (event) => {\n // Zoom and fit keys still act with the menu open; the shell's key listener runs them.\n if (matchChromeKey(event)) return;\n switch (event.key) {\n case \"ArrowDown\":\n focusAt(currentIndex() + 1);\n break;\n case \"ArrowUp\": {\n const index = currentIndex();\n focusAt(index < 0 ? items.length - 1 : index - 1);\n break;\n }\n case \"Home\":\n focusAt(0);\n break;\n case \"End\":\n focusAt(items.length - 1);\n break;\n case \"Tab\":\n // The browser's Tab runs after this handler from wherever the focus is then: from the\n // trigger it moves on to the palette instead of leaving the shell from the layer.\n close({ restoreFocus: true });\n return;\n case \"Escape\":\n // The shell's key listener closes the menu (and keeps Escape from VS Code in the IDE host).\n return;\n case \"Enter\":\n case \" \":\n case \"Delete\":\n case \"Backspace\":\n // The entry's native click handles Enter and Space; nothing else may act on these keys.\n event.stopPropagation();\n return;\n default:\n if (!isPrintable(event)) return;\n typeAhead(event.key);\n }\n consume(event);\n });\n\n updateTriggerVisibility();\n\n return {\n trigger,\n dropdown,\n isOpen,\n open,\n close,\n refresh,\n setGroups(next) {\n groups = next;\n updateTriggerVisibility();\n refresh();\n },\n destroy() {\n if (destroyed) return;\n close();\n destroyed = true;\n trigger.remove();\n dropdown.remove();\n },\n };\n}\n","import { formatNumber, type ShellMessages } from \"../core/index.js\";\nimport { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\nimport type { ProblemSummary, ProblemsOptions } from \"./types.js\";\n\nexport interface ProblemsPill {\n readonly element: HTMLButtonElement;\n isShown(): boolean;\n set(summary: ProblemSummary): void;\n destroy(): void;\n}\n\nexport interface ProblemsContext {\n ownerDocument: Document;\n messages: ShellMessages;\n lang: string;\n tooltip: TooltipController;\n /** The IDE host opens its Problems view, so only there the pill explains itself. */\n showTooltip: boolean;\n options: ProblemsOptions;\n}\n\nexport function createProblemsPill(context: ProblemsContext): ProblemsPill {\n const { ownerDocument, messages, lang, tooltip, options } = context;\n const icon = createElement(ownerDocument, \"span\", { class: \"cd-shell-problems-icon\" });\n const text = createElement(ownerDocument, \"span\", { class: \"cd-shell-problems-text\" });\n const element = createElement(\n ownerDocument,\n \"button\",\n { type: \"button\", class: \"cd-shell-problems cd-shell-island\", \"data-chrome\": \"problems\" },\n icon,\n text,\n );\n element.hidden = true;\n element.addEventListener(\"click\", () => options.onActivate());\n const detachTooltip = context.showTooltip\n ? tooltip.attach(element, { label: messages.showProblems })\n : undefined;\n\n let severity: \"danger\" | \"warning\" | undefined;\n\n return {\n element,\n isShown: () => !element.hidden,\n set({ count, errors }) {\n const shown = count > 0;\n element.hidden = !shown;\n if (!shown) {\n tooltip.hide();\n return;\n }\n const formattedCount = formatNumber(count, lang);\n text.textContent = messages.problems(count, formattedCount);\n element.setAttribute(\n \"aria-label\",\n messages.problemsLabel(count, errors, formattedCount, formatNumber(errors, lang)),\n );\n // The shape carries the severity as well, colour is never the only signal (guide §5.10).\n const next = errors > 0 ? \"danger\" : \"warning\";\n if (next !== severity) {\n severity = next;\n element.dataset.severity = next;\n icon.replaceChildren(iconElement(next === \"danger\" ? \"circle-x\" : \"triangle-alert\"));\n }\n },\n destroy() {\n detachTooltip?.();\n element.remove();\n },\n };\n}\n","import { createElement } from \"./element.js\";\nimport { iconElement } from \"./icons.js\";\nimport type { StatusMessage } from \"./types.js\";\n\nexport interface StatusBox {\n readonly element: HTMLElement;\n set(status: StatusMessage | null, delayMs: number): void;\n destroy(): void;\n}\n\nexport function createStatusBox(ownerDocument: Document): StatusBox {\n const icon = createElement(ownerDocument, \"span\", { class: \"cd-shell-status-icon\" });\n const text = createElement(ownerDocument, \"p\", { class: \"cd-shell-status-text\" });\n const element = createElement(\n ownerDocument,\n \"div\",\n { class: \"cd-shell-status\", \"data-chrome\": \"status\" },\n icon,\n text,\n );\n element.hidden = true;\n\n let pending: { status: StatusMessage; timer: ReturnType<typeof setTimeout> } | undefined;\n\n function cancelPending(): void {\n if (pending) clearTimeout(pending.timer);\n pending = undefined;\n }\n\n function show(status: StatusMessage): void {\n pending = undefined;\n if (element.dataset.severity !== status.severity) {\n element.dataset.severity = status.severity;\n element.setAttribute(\"role\", status.severity === \"danger\" ? \"alert\" : \"status\");\n icon.replaceChildren(iconElement(status.severity === \"danger\" ? \"circle-x\" : \"triangle-alert\"));\n }\n // An unchanged text is not written again, so role=\"alert\" does not announce it again.\n if (text.textContent !== status.text) text.textContent = status.text;\n element.hidden = false;\n }\n\n return {\n element,\n set(status, delayMs) {\n if (status === null) {\n cancelPending();\n element.hidden = true;\n return;\n }\n if (!element.hidden) {\n show(status);\n return;\n }\n // Repeated invalid imports while typing keep the first timer: the box shows once the text\n // stayed invalid for the delay, not the delay after the last keystroke (guide §5.12).\n if (pending) {\n pending.status = status;\n return;\n }\n if (delayMs > 0) {\n const entry = { status, timer: setTimeout(() => show(entry.status), delayMs) };\n pending = entry;\n } else {\n show(status);\n }\n },\n destroy() {\n cancelPending();\n element.remove();\n },\n };\n}\n","import { TOOLTIP_DELAY_MS, placeTooltip } from \"../core/index.js\";\nimport { accessibleName, boxRelativeTo, createElement, hasVisibleFocus } from \"./element.js\";\nimport type { TooltipContent, TooltipHandle } from \"./types.js\";\n\ntype ContentSource = TooltipContent | (() => TooltipContent | null);\n\ninterface Shown {\n control: HTMLElement;\n describedBy: string | null;\n}\n\nexport interface TooltipController extends TooltipHandle {\n readonly element: HTMLElement;\n /** One tooltip for every `selector` match inside `container` (palette entries are rebuilt often). */\n delegate(\n container: HTMLElement,\n selector: string,\n content: (control: HTMLElement) => TooltipContent | null,\n ): () => void;\n destroy(): void;\n}\n\nexport interface TooltipContext {\n root: HTMLElement;\n layer: HTMLElement;\n id: string;\n}\n\nexport function createTooltip({ root, layer, id }: TooltipContext): TooltipController {\n const ownerDocument = root.ownerDocument;\n const label = createElement(ownerDocument, \"span\", { class: \"cd-shell-tooltip-label\" });\n const shortcut = createElement(ownerDocument, \"kbd\", { class: \"cd-shell-kbd\" });\n const element = createElement(ownerDocument, \"div\", { class: \"cd-shell-tooltip\", role: \"tooltip\", id });\n element.hidden = true;\n element.append(label, shortcut);\n layer.append(element);\n\n let shown: Shown | undefined;\n let pending: { control: HTMLElement; timer: ReturnType<typeof setTimeout> } | undefined;\n // After a pointer leaves a control the next one shows at once, so moving along a row of\n // buttons does not wait 300ms for every neighbour (guide §5.6).\n let warmUntil = 0;\n // A clicked control keeps its tooltip hidden until the pointer leaves it.\n let pressed: HTMLElement | undefined;\n const detachers = new Set<() => void>();\n\n function cancelPending(): void {\n if (pending) clearTimeout(pending.timer);\n pending = undefined;\n }\n\n function resolve(source: ContentSource): TooltipContent | null {\n return typeof source === \"function\" ? source() : source;\n }\n\n function place(control: HTMLElement): void {\n const island = control.closest<HTMLElement>(\"[data-chrome]\") ?? control;\n const point = placeTooltip({\n anchor: boxRelativeTo(control, root),\n island: boxRelativeTo(island, root),\n tooltip: { width: element.offsetWidth, height: element.offsetHeight },\n container: { width: root.clientWidth, height: root.clientHeight },\n });\n element.style.left = `${point.x}px`;\n element.style.top = `${point.y}px`;\n }\n\n function hide(): void {\n cancelPending();\n if (!shown) return;\n const { control, describedBy } = shown;\n shown = undefined;\n element.hidden = true;\n if (describedBy === null) control.removeAttribute(\"aria-describedby\");\n else control.setAttribute(\"aria-describedby\", describedBy);\n }\n\n function show(control: HTMLElement, source: ContentSource): void {\n cancelPending();\n const content = resolve(source);\n if (!content || !control.isConnected) {\n if (shown?.control === control) hide();\n return;\n }\n if (shown && shown.control !== control) hide();\n label.textContent = content.label;\n shortcut.textContent = content.shortcut ?? \"\";\n shortcut.hidden = !content.shortcut;\n element.hidden = false;\n if (!shown) {\n const describedBy = control.getAttribute(\"aria-describedby\");\n shown = { control, describedBy };\n // Only a tooltip that says more than the control's name describes it (guide §5.6); a shortcut\n // chip does, unless the control names its keys in aria-keyshortcuts.\n const saysMore =\n !accessibleName(control).includes(content.label) ||\n (Boolean(content.shortcut) && !control.hasAttribute(\"aria-keyshortcuts\"));\n if (saysMore) {\n control.setAttribute(\"aria-describedby\", [describedBy, id].filter(Boolean).join(\" \"));\n }\n }\n place(control);\n }\n\n function onEnter(control: HTMLElement, source: ContentSource, event: PointerEvent): void {\n if (event.pointerType === \"touch\" || pressed === control) return;\n if (shown || Date.now() < warmUntil) {\n show(control, source);\n return;\n }\n cancelPending();\n pending = { control, timer: setTimeout(() => show(control, source), TOOLTIP_DELAY_MS) };\n }\n\n function onLeave(control: HTMLElement): void {\n if (pressed === control) pressed = undefined;\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) {\n hide();\n warmUntil = Date.now() + TOOLTIP_DELAY_MS;\n }\n }\n\n function onFocus(control: HTMLElement, source: ContentSource): void {\n if (hasVisibleFocus(control)) show(control, source);\n }\n\n function onBlur(control: HTMLElement): void {\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) hide();\n }\n\n function onPress(control: HTMLElement, event: Event): void {\n if (event.type === \"pointerdown\") pressed = control;\n if (pending?.control === control) cancelPending();\n if (shown?.control === control) hide();\n }\n\n function attach(control: HTMLElement, source: ContentSource): () => void {\n const enter = (event: PointerEvent) => onEnter(control, source, event);\n const leave = () => onLeave(control);\n const focus = () => onFocus(control, source);\n const blur = () => onBlur(control);\n const press = (event: Event) => onPress(control, event);\n control.addEventListener(\"pointerenter\", enter);\n control.addEventListener(\"pointerleave\", leave);\n control.addEventListener(\"focus\", focus);\n control.addEventListener(\"blur\", blur);\n control.addEventListener(\"pointerdown\", press);\n control.addEventListener(\"click\", press);\n const detach = () => {\n if (!detachers.delete(detach)) return;\n control.removeEventListener(\"pointerenter\", enter);\n control.removeEventListener(\"pointerleave\", leave);\n control.removeEventListener(\"focus\", focus);\n control.removeEventListener(\"blur\", blur);\n control.removeEventListener(\"pointerdown\", press);\n control.removeEventListener(\"click\", press);\n if (shown?.control === control || pending?.control === control) hide();\n if (pressed === control) pressed = undefined;\n };\n detachers.add(detach);\n return detach;\n }\n\n function delegate(\n container: HTMLElement,\n selector: string,\n content: (control: HTMLElement) => TooltipContent | null,\n ): () => void {\n let hovered: HTMLElement | undefined;\n const controlOf = (target: EventTarget | null): HTMLElement | undefined => {\n if (!target || typeof (target as Element).closest !== \"function\") return undefined;\n const match = (target as Element).closest<HTMLElement>(selector);\n return match && container.contains(match) ? match : undefined;\n };\n const sourceOf = (control: HTMLElement) => () => content(control);\n const over = (event: PointerEvent) => {\n const control = controlOf(event.target);\n if (control === hovered) return;\n if (hovered) onLeave(hovered);\n hovered = control;\n if (control) onEnter(control, sourceOf(control), event);\n };\n const out = (event: PointerEvent) => {\n if (!hovered) return;\n if (controlOf(event.relatedTarget) === hovered) return;\n onLeave(hovered);\n hovered = undefined;\n };\n const focusIn = (event: FocusEvent) => {\n const control = controlOf(event.target);\n if (control) onFocus(control, sourceOf(control));\n };\n const focusOut = (event: FocusEvent) => {\n const control = controlOf(event.target);\n if (control) onBlur(control);\n };\n const press = (event: Event) => {\n const control = controlOf(event.target);\n if (control) onPress(control, event);\n };\n container.addEventListener(\"pointerover\", over);\n container.addEventListener(\"pointerout\", out);\n container.addEventListener(\"focusin\", focusIn);\n container.addEventListener(\"focusout\", focusOut);\n container.addEventListener(\"pointerdown\", press);\n container.addEventListener(\"click\", press);\n const detach = () => {\n if (!detachers.delete(detach)) return;\n container.removeEventListener(\"pointerover\", over);\n container.removeEventListener(\"pointerout\", out);\n container.removeEventListener(\"focusin\", focusIn);\n container.removeEventListener(\"focusout\", focusOut);\n container.removeEventListener(\"pointerdown\", press);\n container.removeEventListener(\"click\", press);\n if ((shown && container.contains(shown.control)) || (pending && container.contains(pending.control))) {\n hide();\n }\n hovered = undefined;\n };\n detachers.add(detach);\n return detach;\n }\n\n return {\n element,\n attach,\n delegate,\n hide,\n destroy() {\n hide();\n for (const detach of [...detachers]) detach();\n element.remove();\n },\n };\n}\n","import {\n ariaKeyShortcuts,\n canZoomIn,\n canZoomOut,\n formatPercent,\n shortcutLabel,\n zoomReadout,\n type ChromeKey,\n type Platform,\n type ShellMessages,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport { createElement, toggleAttribute } from \"./element.js\";\nimport { iconElement, type ShellIconName } from \"./icons.js\";\nimport type { TooltipController } from \"./tooltip.js\";\n\nexport interface ZoomPanelContext {\n ownerDocument: Document;\n messages: ShellMessages;\n lang: string;\n platform: Platform;\n tooltip: TooltipController;\n}\n\nexport interface ZoomPanel {\n readonly element: HTMLElement;\n setTarget(target: ZoomTarget | null): void;\n /** Runs a chrome key on the bound target; zoom out never zooms in (guide §5.8). */\n run(key: ChromeKey): void;\n destroy(): void;\n}\n\nexport function createZoomPanel(context: ZoomPanelContext): ZoomPanel {\n const { ownerDocument, messages, lang, platform, tooltip } = context;\n let target: ZoomTarget | null = null;\n let unsubscribe: (() => void) | undefined;\n let frame: number | undefined;\n const detachers: (() => void)[] = [];\n\n function button(\n zoom: \"out\" | \"actual\" | \"in\" | \"fit\",\n key: ChromeKey,\n tooltipLabel: string,\n options: { label?: string; icon?: ShellIconName; className?: string },\n ): HTMLButtonElement {\n const element = createElement(ownerDocument, \"button\", {\n type: \"button\",\n class: options.className ?? \"cd-shell-target\",\n \"data-zoom\": zoom,\n \"aria-label\": options.label,\n \"aria-keyshortcuts\": ariaKeyShortcuts(key, platform),\n });\n if (options.icon) element.append(iconElement(options.icon));\n element.addEventListener(\"click\", () => run(key));\n detachers.push(\n tooltip.attach(element, {\n label: tooltipLabel,\n shortcut: shortcutLabel(key, platform, messages.keyNames),\n }),\n );\n return element;\n }\n\n const zoomOut = button(\"out\", \"zoomOut\", messages.zoomOut, { label: messages.zoomOut, icon: \"minus\" });\n const readout = button(\"actual\", \"zoomToActual\", messages.zoomToActual(formatPercent(1, lang)), {\n className: \"cd-shell-target cd-shell-zoom-readout\",\n });\n const zoomIn = button(\"in\", \"zoomIn\", messages.zoomIn, { label: messages.zoomIn, icon: \"plus\" });\n const fit = button(\"fit\", \"fit\", messages.fit, { label: messages.fit, icon: \"maximize\" });\n const separator = createElement(ownerDocument, \"span\", {\n class: \"cd-shell-zoom-separator\",\n \"aria-hidden\": \"true\",\n });\n\n const element = createElement(\n ownerDocument,\n \"div\",\n {\n class: \"cd-shell-zoom cd-shell-island\",\n \"data-chrome\": \"zoom\",\n role: \"group\",\n \"aria-label\": messages.zoom,\n },\n zoomOut,\n readout,\n zoomIn,\n separator,\n fit,\n );\n\n function render(): void {\n frame = undefined;\n const zoom = target?.zoom() ?? 1;\n const state = zoomReadout(zoom, lang, messages);\n if (readout.textContent !== state.text) readout.textContent = state.text;\n readout.setAttribute(\"aria-label\", state.ariaLabel);\n // aria-disabled, not disabled: a button pressed up to the limit keeps the focus (guide §5.8).\n toggleAttribute(zoomOut, \"aria-disabled\", (!target || !state.canZoomOut) && \"true\");\n toggleAttribute(zoomIn, \"aria-disabled\", (!target || !state.canZoomIn) && \"true\");\n toggleAttribute(fit, \"aria-disabled\", (!target || !target.canFit()) && \"true\");\n // The readout is never disabled (guide §5.8); without a target its click does nothing.\n }\n\n function schedule(): void {\n if (frame === undefined) frame = requestAnimationFrame(render);\n }\n\n function cancelFrame(): void {\n if (frame !== undefined) cancelAnimationFrame(frame);\n frame = undefined;\n }\n\n function run(key: ChromeKey): void {\n if (!target) return;\n const zoom = target.zoom();\n switch (key) {\n case \"zoomIn\":\n if (canZoomIn(zoom)) target.stepZoom(1);\n break;\n case \"zoomOut\":\n if (canZoomOut(zoom)) target.stepZoom(-1);\n break;\n case \"zoomToActual\":\n if (zoom !== 1) target.zoomToActual();\n break;\n case \"fit\":\n if (target.canFit()) target.fit();\n break;\n }\n }\n\n render();\n\n return {\n element,\n run,\n setTarget(next) {\n unsubscribe?.();\n unsubscribe = undefined;\n cancelFrame();\n target = next;\n if (next) unsubscribe = next.onChange(schedule);\n render();\n },\n destroy() {\n unsubscribe?.();\n unsubscribe = undefined;\n cancelFrame();\n target = null;\n for (const detach of detachers) detach();\n element.remove();\n },\n };\n}\n","import {\n SHELL,\n decidePaletteRow,\n detectPlatform,\n fitInsets,\n legendStartsOpen,\n resolveMessages,\n type FitLayout,\n type Insets,\n type PaletteRow,\n type Size,\n type Theme,\n type ZoomTarget,\n} from \"../core/index.js\";\nimport { boxRelativeTo, createElement } from \"./element.js\";\nimport { createEmptyHint } from \"./hint.js\";\nimport { createInspector } from \"./inspector.js\";\nimport { createKeyListener } from \"./keys.js\";\nimport { Ledger } from \"./ledger.js\";\nimport { createLegend } from \"./legend.js\";\nimport { createMenu } from \"./menu.js\";\nimport { createProblemsPill } from \"./problems.js\";\nimport { createStatusBox } from \"./status.js\";\nimport { createTooltip } from \"./tooltip.js\";\nimport type {\n InspectorHandle,\n LegendHandle,\n MenuCheckboxEntry,\n MenuHandle,\n PaletteReadOnlyState,\n PaletteRegistration,\n ShellHandle,\n ShellOptions,\n TooltipHandle,\n} from \"./types.js\";\nimport { createZoomPanel } from \"./zoom-panel.js\";\n\n// Page-global: every modeler bundles its own copy of the shell (and the CJS entries inline one each),\n// and two shells on one foreign page must not share element ids.\nconst MOUNT_COUNTER = Symbol.for(\"@miragon/modeler-shell.mounts\");\n\nfunction nextMountIndex(): number {\n const scope = globalThis as unknown as Record<symbol, number | undefined>;\n const index = (scope[MOUNT_COUNTER] ?? 0) + 1;\n scope[MOUNT_COUNTER] = index;\n return index;\n}\n\nconst DEFAULT_THEMES: readonly Theme[] = [\"light\"];\n\n// In a foreign page the closest [lang] is the page's language, not the tool's (guide §2).\nfunction languageOf(root: HTMLElement, host: ShellOptions[\"host\"], requested: string | undefined): string {\n if (requested) return requested;\n const declared =\n host === \"embedded\" ? root.getAttribute(\"lang\") : root.closest(\"[lang]\")?.getAttribute(\"lang\");\n return declared || \"en\";\n}\n\n/** The contrast of the host page around an embedded root: the nearest mode carrier above it. */\nfunction hostKontrast(root: HTMLElement): \"hoch\" | null {\n const carrier = root.parentElement?.closest(\"[data-cd-theme], [data-cd-kontrast]\");\n return carrier?.getAttribute(\"data-cd-kontrast\") === \"hoch\" ? \"hoch\" : null;\n}\n\n/**\n * Turns `root` into the shell (`.cd-shell`, container `cd-shell`) and renders the chrome in the\n * DOM order of guide §5.14: menu trigger, canvas slot, status box, empty-file hint, inspector,\n * problems pill, legend, zoom panel, then the layer for dropdown and tooltip. Installs the one\n * `keydown` listener (see `ShellOptions.keyScope`) and the root `ResizeObserver`.\n *\n * `root` must get its size from outside (`container-type: size`): `height: 100%` in an own\n * document, an explicitly sized element in a foreign page. When rendering throws (a modeler's\n * `legend.render`), everything added so far is removed again before the error propagates.\n */\nexport function mountShell(root: HTMLElement, options: ShellOptions): ShellHandle {\n const themes = options.themes ?? DEFAULT_THEMES;\n if (themes.length === 0) throw new Error(\"@miragon/modeler-shell: mountShell needs at least one theme\");\n const ledger = new Ledger();\n try {\n return renderShell(root, options, themes, ledger);\n } catch (error) {\n ledger.close();\n throw error;\n }\n}\n\nfunction renderShell(\n root: HTMLElement,\n options: ShellOptions,\n themes: readonly Theme[],\n ledger: Ledger,\n): ShellHandle {\n const ownerDocument = root.ownerDocument;\n const { host } = options;\n const index = nextMountIndex();\n const messages = resolveMessages(options.messages);\n const platform = options.platform ?? detectPlatform(globalThis.navigator);\n const lang = languageOf(root, host, options.lang);\n const keyScope = options.keyScope ?? (host === \"embedded\" ? \"root\" : \"document\");\n\n ledger.addClass(root, \"cd-shell\");\n ledger.attribute(root, \"data-cd-shell-host\", host);\n ledger.attribute(root, \"data-palette\", \"top\");\n if (host === \"embedded\") {\n ledger.attribute(root, \"lang\", lang);\n carryOwnMode(root, themes[0] ?? \"light\", ledger);\n } else {\n ledger.addClass(ownerDocument.documentElement, \"cd-shell-document\");\n }\n\n const setState = (name: string, value: string | null): void => {\n if (!ledger.isClosed) ledger.attribute(root, name, value);\n };\n\n const layer = createElement(ownerDocument, \"div\", { class: \"cd-shell-layer\" });\n ledger.defer(() => layer.remove());\n const tooltip = createTooltip({ root, layer, id: `cd-shell-tooltip-${index}` });\n ledger.defer(() => tooltip.destroy());\n\n /** The lock of `setReadOnly(true)`; `readOnlyShown` its marks, which may follow after a delay. */\n let readOnly = false;\n let readOnlyShown = false;\n let readOnlyTimer: ReturnType<typeof setTimeout> | undefined;\n ledger.defer(() => clearTimeout(readOnlyTimer));\n\n const legend = options.legend\n ? createLegend({\n ownerDocument,\n messages,\n tooltip,\n titleId: `cd-shell-legend-title-${index}`,\n options: options.legend,\n onChange(open) {\n setState(\"data-legend\", open ? \"open\" : null);\n placeHint();\n menu.refresh();\n },\n focusAfterClose: () => menu.trigger.focus(),\n })\n : undefined;\n if (legend) ledger.defer(() => legend.destroy());\n\n const legendEntry: MenuCheckboxEntry | undefined =\n legend && options.legend?.menuEntry !== false\n ? {\n kind: \"checkbox\",\n id: \"legend\",\n label: messages.legend,\n checked: () => legend.isOpen(),\n onToggle: (checked) => legend.setOpen(checked),\n keepEnabledWhenReadOnly: true,\n }\n : undefined;\n const shellModelEntries: readonly MenuCheckboxEntry[] = legendEntry ? [legendEntry] : [];\n\n const menu = createMenu({\n root,\n layer,\n id: `cd-shell-menu-${index}`,\n messages,\n tooltip,\n groups: options.menu ?? {},\n shellModelEntries: () => shellModelEntries,\n isReadOnly: () => readOnly,\n });\n ledger.defer(() => menu.destroy());\n ledger.defer(tooltip.attach(menu.trigger, () => (menu.isOpen() ? null : { label: messages.menu })));\n\n const canvas = options.canvas ?? createElement(ownerDocument, \"div\");\n ledger.addClass(canvas, \"cd-shell-canvas\");\n if (!options.canvas) ledger.defer(() => canvas.remove());\n\n /** Where the focus goes when the island holding it hides: the canvas, else the menu trigger. */\n function moveFocusOutOf(island: HTMLElement): void {\n if (!island.contains(ownerDocument.activeElement)) return;\n const canvasTarget = canvas.querySelector<HTMLElement | SVGElement>(\"svg[tabindex]\");\n canvasTarget?.focus({ preventScroll: true });\n if (canvasTarget && ownerDocument.activeElement === canvasTarget) return;\n if (!menu.trigger.hidden) menu.trigger.focus({ preventScroll: true });\n }\n\n const status = createStatusBox(ownerDocument);\n ledger.defer(() => status.destroy());\n const hint = options.emptyHint ? createEmptyHint(ownerDocument, messages, options.emptyHint) : undefined;\n if (hint) ledger.defer(() => hint.destroy());\n const inspector = options.inspector\n ? createInspector(ownerDocument, options.inspector, (open) => {\n setState(\"data-inspector\", open ? \"open\" : null);\n placeHint();\n })\n : undefined;\n if (inspector) ledger.defer(() => inspector.destroy());\n const pill = options.problems\n ? createProblemsPill({\n ownerDocument,\n messages,\n lang,\n tooltip,\n showTooltip: host === \"ide\",\n options: options.problems,\n })\n : undefined;\n if (pill) ledger.defer(() => pill.destroy());\n const zoomPanel = createZoomPanel({ ownerDocument, messages, lang, platform, tooltip });\n ledger.defer(() => zoomPanel.destroy());\n\n root.prepend(menu.trigger, canvas);\n root.append(\n ...[\n status.element,\n hint?.element,\n inspector?.element,\n pill?.element,\n legend?.element,\n zoomPanel.element,\n ].filter((element): element is HTMLElement => element !== undefined),\n layer,\n );\n\n let palette: { registration: PaletteRegistration; detachTooltip: () => void } | undefined;\n let paletteRow: PaletteRow = \"top\";\n\n function containerSize(): Size {\n return { width: root.clientWidth, height: root.clientHeight };\n }\n\n function menuRight(): number {\n const box = boxRelativeTo(menu.trigger, root);\n return box.width > 0 ? box.x + box.width : SHELL.edge + SHELL.row;\n }\n\n /** The palette's intrinsic border-box width: it does not shrink once the second row clips it. */\n function paletteWidth(): number {\n const element = palette?.registration.element;\n return element ? element.offsetWidth - element.clientWidth + element.scrollWidth : 0;\n }\n\n function currentFitInsets(): Insets {\n const container = containerSize();\n const layout: FitLayout = {\n container,\n host,\n paletteRow,\n problemsVisible: pill?.isShown() ?? false,\n };\n if (legend?.isOpen()) layout.legendWidth = legend.element.getBoundingClientRect().width;\n if (inspector?.isOpen()) {\n layout.inspector =\n container.width > SHELL.narrow ? {} : { sheetTop: boxRelativeTo(inspector.element, root).y };\n }\n return fitInsets(layout);\n }\n\n function placeHint(): void {\n if (hint?.isShown()) hint.place(currentFitInsets());\n }\n\n function updateLayout(): void {\n if (ledger.isClosed) return;\n const size = containerSize();\n // A hidden tab reports 0 × 0; it neither measures nor decides anything (guide §5.9).\n if (size.width === 0 || size.height === 0) return;\n paletteRow = decidePaletteRow({\n containerWidth: size.width,\n paletteWidth: paletteWidth(),\n menuRight: menuRight(),\n });\n setState(\"data-palette\", paletteRow);\n if (legend && !legend.isStarted()) legend.start(options.legend?.open ?? legendStartsOpen(size.height));\n placeHint();\n }\n\n const ResizeObserverClass = globalThis.ResizeObserver;\n const resizeObserver = ResizeObserverClass ? new ResizeObserverClass(() => updateLayout()) : undefined;\n resizeObserver?.observe(root);\n ledger.defer(() => resizeObserver?.disconnect());\n\n if (legend && options.legend?.open !== undefined) legend.start(options.legend.open);\n updateLayout();\n\n const keyTarget: HTMLElement | Document = keyScope === \"root\" ? root : ownerDocument;\n const onKeydown = createKeyListener({\n host,\n dialogScope: keyTarget,\n menuOpen: () => menu.isOpen(),\n closeMenu() {\n const active = ownerDocument.activeElement;\n menu.close({ restoreFocus: active === menu.trigger || menu.dropdown.contains(active) });\n },\n hideTooltip: () => tooltip.hide(),\n run: (key) => zoomPanel.run(key),\n });\n keyTarget.addEventListener(\"keydown\", onKeydown as EventListener);\n ledger.defer(() => keyTarget.removeEventListener(\"keydown\", onKeydown as EventListener));\n\n function readOnlyState(): PaletteReadOnlyState {\n return { locked: readOnly, shown: readOnlyShown };\n }\n\n function applyReadOnly(): void {\n setState(\"data-readonly\", readOnlyShown ? \"\" : null);\n palette?.registration.setReadOnly(readOnlyState());\n menu.refresh();\n }\n\n function showReadOnly(): void {\n readOnlyTimer = undefined;\n if (ledger.isClosed || !readOnly) return;\n readOnlyShown = true;\n applyReadOnly();\n }\n\n function unregisterPalette(): void {\n if (!palette) return;\n palette.detachTooltip();\n resizeObserver?.unobserve(palette.registration.element);\n palette = undefined;\n }\n ledger.defer(unregisterPalette);\n\n const menuHandle: MenuHandle = {\n trigger: menu.trigger,\n dropdown: menu.dropdown,\n isOpen: () => menu.isOpen(),\n open: (focus) => menu.open(focus),\n close: (closeOptions) => menu.close(closeOptions),\n refresh: () => menu.refresh(),\n setGroups: (groups) => {\n if (!ledger.isClosed) menu.setGroups(groups);\n },\n };\n\n const tooltipHandle: TooltipHandle = {\n attach: (control, content) => (ledger.isClosed ? () => {} : tooltip.attach(control, content)),\n hide: () => tooltip.hide(),\n };\n\n const legendHandle: LegendHandle | undefined = legend && {\n element: legend.element,\n body: legend.body,\n isOpen: () => legend.isOpen(),\n setOpen: (open) => {\n if (!ledger.isClosed) legend.setOpen(open);\n },\n toggle: () => {\n if (!ledger.isClosed) legend.toggle();\n },\n };\n\n const inspectorHandle: InspectorHandle | undefined = inspector && {\n element: inspector.element,\n isOpen: () => inspector.isOpen(),\n open: () => {\n if (!ledger.isClosed) inspector.open();\n },\n close: () => {\n if (ledger.isClosed) return;\n if (inspector.isOpen()) moveFocusOutOf(inspector.element);\n inspector.close();\n },\n };\n\n return {\n root,\n canvas,\n host,\n lang,\n platform,\n messages,\n menu: menuHandle,\n tooltip: tooltipHandle,\n legend: legendHandle,\n inspector: inspectorHandle,\n setZoomTarget(target: ZoomTarget | null) {\n if (!ledger.isClosed) zoomPanel.setTarget(target);\n },\n fitInsets: currentFitInsets,\n registerPalette(registration) {\n if (ledger.isClosed) return () => {};\n unregisterPalette();\n palette = {\n registration,\n detachTooltip: tooltip.delegate(registration.element, \".entry\", (entry) =>\n registration.entryTooltip(entry),\n ),\n };\n resizeObserver?.observe(registration.element);\n registration.setReadOnly(readOnlyState());\n updateLayout();\n const registered = palette;\n return () => {\n if (palette !== registered) return;\n unregisterPalette();\n updateLayout();\n };\n },\n setProblems(summary) {\n if (ledger.isClosed || !pill) return;\n pill.set(summary);\n setState(\"data-problems\", pill.isShown() ? \"shown\" : null);\n placeHint();\n },\n setStatus(next, statusOptions) {\n if (!ledger.isClosed) status.set(next, statusOptions?.delayMs ?? 0);\n },\n setEmptyHint(visible) {\n if (ledger.isClosed || !hint) return;\n if (!visible && hint.isShown()) moveFocusOutOf(hint.element);\n hint.setShown(visible);\n placeHint();\n },\n setReadOnly(next, readOnlyOptions) {\n if (ledger.isClosed) return;\n if (!next) {\n clearTimeout(readOnlyTimer);\n readOnlyTimer = undefined;\n readOnly = false;\n readOnlyShown = false;\n } else {\n readOnly = true;\n const delayMs = readOnlyOptions?.delayMs ?? 0;\n // Repeated invalid imports while typing keep the first timer, like the status box.\n if (!readOnlyShown && readOnlyTimer === undefined) {\n if (delayMs > 0) readOnlyTimer = setTimeout(showReadOnly, delayMs);\n else readOnlyShown = true;\n }\n }\n applyReadOnly();\n },\n isReadOnly: () => readOnly,\n destroy() {\n ledger.close();\n },\n };\n}\n\n/**\n * An embedded root carries its own mode (guide §13.3): the token CSS resolves the roles on the\n * nearest `[data-cd-theme]`, so without it a light-only modeler would inherit a dark host page and\n * be half-dark against its light-drawn diagram. The root's own `data-cd-theme` would also drop the\n * host's high contrast, so `data-cd-kontrast` is mirrored from the host for as long as it lives.\n */\nfunction carryOwnMode(root: HTMLElement, theme: Theme, ledger: Ledger): void {\n ledger.attribute(root, \"data-cd-theme\", theme);\n const mirror = (): void => {\n if (ledger.isClosed) return;\n const kontrast = hostKontrast(root);\n if (root.getAttribute(\"data-cd-kontrast\") !== kontrast)\n ledger.attribute(root, \"data-cd-kontrast\", kontrast);\n };\n mirror();\n const MutationObserverClass = globalThis.MutationObserver;\n if (!MutationObserverClass) return;\n const observer = new MutationObserverClass(mirror);\n observer.observe(root.ownerDocument.documentElement, {\n attributes: true,\n attributeFilter: [\"data-cd-theme\", \"data-cd-kontrast\"],\n subtree: true,\n });\n ledger.defer(() => observer.disconnect());\n}\n"],"mappings":"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","names":["element","element"]}
@@ -0,0 +1,23 @@
1
+ // src/vscode/protocol.ts
2
+ var APPEARANCE_MESSAGE_TYPE = "modelerShell.appearance";
3
+ function appearanceMessage(appearance) {
4
+ return {
5
+ type: APPEARANCE_MESSAGE_TYPE,
6
+ appearance: appearance.kontrast ? { theme: appearance.theme, kontrast: appearance.kontrast } : { theme: appearance.theme }
7
+ };
8
+ }
9
+ function isRecord(value) {
10
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11
+ }
12
+ function isAppearanceMessage(value) {
13
+ if (!isRecord(value) || value.type !== APPEARANCE_MESSAGE_TYPE || !isRecord(value.appearance)) return false;
14
+ const { theme, kontrast } = value.appearance;
15
+ return (theme === "light" || theme === "dark") && (kontrast === void 0 || kontrast === "hoch");
16
+ }
17
+
18
+ export {
19
+ APPEARANCE_MESSAGE_TYPE,
20
+ appearanceMessage,
21
+ isAppearanceMessage
22
+ };
23
+ //# sourceMappingURL=chunk-N4QXFF3A.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vscode/protocol.ts"],"sourcesContent":["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"],"mappings":";AAGO,IAAM,0BAA0B;AAShC,SAAS,kBAAkB,YAA2C;AAC3E,SAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY,WAAW,WACnB,EAAE,OAAO,WAAW,OAAO,UAAU,WAAW,SAAS,IACzD,EAAE,OAAO,WAAW,MAAM;AAAA,EAChC;AACF;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAGO,SAAS,oBAAoB,OAA4C;AAC9E,MAAI,CAAC,SAAS,KAAK,KAAK,MAAM,SAAS,2BAA2B,CAAC,SAAS,MAAM,UAAU,EAAG,QAAO;AACtG,QAAM,EAAE,OAAO,SAAS,IAAI,MAAM;AAClC,UAAQ,UAAU,WAAW,UAAU,YAAY,aAAa,UAAa,aAAa;AAC5F;","names":[]}
@@ -0,0 +1,136 @@
1
+ import {
2
+ appearanceMessage
3
+ } from "./chunk-N4QXFF3A.js";
4
+ import {
5
+ appearanceAttributes,
6
+ requestedAppearance,
7
+ resolveAppearance
8
+ } from "./chunk-5JSZ4VGA.js";
9
+
10
+ // src/vscode/extension/html.ts
11
+ var NONCE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
12
+ var NONCE_LENGTH = 32;
13
+ var UNBIASED_BYTE_LIMIT = 256 - 256 % NONCE_ALPHABET.length;
14
+ var CSP_NONCE = /^[A-Za-z0-9+/_-]+={0,2}$/;
15
+ var DEFAULT_BODY = '<div id="app"></div>';
16
+ function createNonce() {
17
+ let nonce = "";
18
+ while (nonce.length < NONCE_LENGTH) {
19
+ for (const byte of crypto.getRandomValues(new Uint8Array(NONCE_LENGTH))) {
20
+ if (byte < UNBIASED_BYTE_LIMIT && nonce.length < NONCE_LENGTH) {
21
+ nonce += NONCE_ALPHABET.charAt(byte % NONCE_ALPHABET.length);
22
+ }
23
+ }
24
+ }
25
+ return nonce;
26
+ }
27
+ function escapeHtml(value) {
28
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
29
+ }
30
+ function attribute(name, value) {
31
+ return `${name}="${escapeHtml(value)}"`;
32
+ }
33
+ function contentSecurityPolicy(cspSource, nonce, inlineStyles) {
34
+ return [
35
+ "default-src 'none'",
36
+ `img-src ${cspSource} data: blob:`,
37
+ inlineStyles ? `style-src ${cspSource} 'unsafe-inline'` : `style-src ${cspSource}`,
38
+ `font-src ${cspSource} data:`,
39
+ `script-src 'nonce-${nonce}'`
40
+ ].join("; ");
41
+ }
42
+ function renderWebviewHtml(options) {
43
+ const nonce = options.nonce ?? createNonce();
44
+ if (!CSP_NONCE.test(nonce)) {
45
+ throw new Error(`@miragon/modeler-shell: renderWebviewHtml got an invalid nonce "${nonce}"`);
46
+ }
47
+ const appearance = appearanceAttributes(options.appearance);
48
+ const kontrast = appearance["data-cd-kontrast"];
49
+ const htmlAttributes = [
50
+ attribute("lang", options.lang),
51
+ attribute("class", "cd-shell-document"),
52
+ attribute("data-cd-theme", appearance["data-cd-theme"]),
53
+ ...kontrast ? [attribute("data-cd-kontrast", kontrast)] : []
54
+ ].join(" ");
55
+ const stylesheets = (options.styleUris ?? []).map(
56
+ (uri) => `
57
+ <link ${attribute("rel", "stylesheet")} ${attribute("href", uri)} />`
58
+ );
59
+ return `<!doctype html>
60
+ <html ${htmlAttributes}>
61
+ <head>
62
+ <meta charset="UTF-8" />
63
+ <meta http-equiv="Content-Security-Policy" ${attribute("content", contentSecurityPolicy(options.cspSource, nonce, options.inlineStyles !== false))} />
64
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />${stylesheets.join("")}
65
+ <title>${escapeHtml(options.title)}</title>
66
+ </head>
67
+ <body>
68
+ ${options.body ?? DEFAULT_BODY}
69
+ <script ${attribute("nonce", nonce)} ${attribute("src", options.scriptUri)}></script>
70
+ </body>
71
+ </html>
72
+ `;
73
+ }
74
+
75
+ // src/vscode/extension/theme-bridge.ts
76
+ function isColorThemeSetting(value) {
77
+ return value === "automatic" || value === "light" || value === "dark";
78
+ }
79
+ function readColorThemeSetting(vscode, settingKey) {
80
+ const separator = settingKey.lastIndexOf(".");
81
+ const value = separator < 0 ? vscode.workspace.getConfiguration().get(settingKey) : vscode.workspace.getConfiguration(settingKey.slice(0, separator)).get(settingKey.slice(separator + 1));
82
+ return isColorThemeSetting(value) ? value : void 0;
83
+ }
84
+ function currentAppearance(vscode, options) {
85
+ const setting = options.settingKey ? readColorThemeSetting(vscode, options.settingKey) : void 0;
86
+ return resolveAppearance(requestedAppearance(vscode.window.activeColorTheme.kind, setting), options.themes);
87
+ }
88
+ function connectThemeBridge(vscode, panel, options) {
89
+ if (options.themes.length === 0) {
90
+ throw new Error("@miragon/modeler-shell: connectThemeBridge needs at least one theme");
91
+ }
92
+ const { settingKey } = options;
93
+ const post = () => {
94
+ void panel.webview.postMessage(appearanceMessage(currentAppearance(vscode, options)));
95
+ };
96
+ let wasVisible = panel.visible;
97
+ const subscriptions = [
98
+ vscode.window.onDidChangeActiveColorTheme(post),
99
+ panel.onDidChangeViewState(({ webviewPanel }) => {
100
+ const becameVisible = webviewPanel.visible && !wasVisible;
101
+ wasVisible = webviewPanel.visible;
102
+ if (becameVisible) post();
103
+ })
104
+ ];
105
+ if (settingKey) {
106
+ subscriptions.push(
107
+ vscode.workspace.onDidChangeConfiguration((event) => {
108
+ if (event.affectsConfiguration(settingKey)) post();
109
+ })
110
+ );
111
+ }
112
+ let disposed = false;
113
+ const dispose = () => {
114
+ if (disposed) return;
115
+ disposed = true;
116
+ for (const subscription of subscriptions.splice(0)) subscription.dispose();
117
+ };
118
+ subscriptions.push(panel.onDidDispose(dispose));
119
+ return { dispose };
120
+ }
121
+
122
+ // src/vscode/extension/reveal.ts
123
+ function revealFileLabel(platform) {
124
+ if (platform === "darwin") return "Reveal in Finder";
125
+ if (platform === "win32") return "Reveal in File Explorer";
126
+ return "Open Containing Folder";
127
+ }
128
+
129
+ export {
130
+ createNonce,
131
+ renderWebviewHtml,
132
+ currentAppearance,
133
+ connectThemeBridge,
134
+ revealFileLabel
135
+ };
136
+ //# sourceMappingURL=chunk-RJRFR6N3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vscode/extension/html.ts","../src/vscode/extension/theme-bridge.ts","../src/vscode/extension/reveal.ts"],"sourcesContent":["import { appearanceAttributes, type Appearance } from \"../../core/index.js\";\n\nexport interface WebviewHtmlOptions {\n /** `webview.cspSource` */\n cspSource: string;\n /** The bundle, `webview.asWebviewUri(…).toString()`. */\n scriptUri: string;\n /** Stylesheets in load order (token CSS first, see API.md). */\n styleUris?: readonly string[] | undefined;\n /** `<title>` */\n title: string;\n /** The tool's UI language for `<html lang>`; English modelers pass `\"en\"`. */\n lang: string;\n /** Resolved appearance (`currentAppearance`), written before the first paint. */\n appearance: Appearance;\n /** Markup inside `<body>` before the script; default `<div id=\"app\"></div>`. */\n body?: string | undefined;\n /** Script nonce; default `createNonce()`. */\n nonce?: string | undefined;\n /**\n * Allow inline styles (`style-src … 'unsafe-inline'`), default `true`: renderers write `style`\n * attributes into markup (palette entries, SVG strings). The shell and diagram-js themselves\n * only style through the CSSOM and run without it; pass `false` once the renderer does too.\n */\n inlineStyles?: boolean | undefined;\n}\n\nconst NONCE_ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst NONCE_LENGTH = 32;\n/** Bytes at or above this limit are rejected, so every character is equally likely. */\nconst UNBIASED_BYTE_LIMIT = 256 - (256 % NONCE_ALPHABET.length);\n/** The `base64-value` of a CSP `nonce-source`. */\nconst CSP_NONCE = /^[A-Za-z0-9+/_-]+={0,2}$/;\n\nconst DEFAULT_BODY = '<div id=\"app\"></div>';\n\n/** 32 characters `[A-Za-z0-9]` from `crypto.getRandomValues`. */\nexport function createNonce(): string {\n let nonce = \"\";\n while (nonce.length < NONCE_LENGTH) {\n for (const byte of crypto.getRandomValues(new Uint8Array(NONCE_LENGTH))) {\n if (byte < UNBIASED_BYTE_LIMIT && nonce.length < NONCE_LENGTH) {\n nonce += NONCE_ALPHABET.charAt(byte % NONCE_ALPHABET.length);\n }\n }\n }\n return nonce;\n}\n\nfunction escapeHtml(value: string): string {\n return value.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\n}\n\nfunction attribute(name: string, value: string): string {\n return `${name}=\"${escapeHtml(value)}\"`;\n}\n\nfunction contentSecurityPolicy(cspSource: string, nonce: string, inlineStyles: boolean): string {\n return [\n \"default-src 'none'\",\n `img-src ${cspSource} data: blob:`,\n inlineStyles ? `style-src ${cspSource} 'unsafe-inline'` : `style-src ${cspSource}`,\n `font-src ${cspSource} data:`,\n `script-src 'nonce-${nonce}'`,\n ].join(\"; \");\n}\n\n/**\n * The webview document: `<html lang class=\"cd-shell-document\" data-cd-theme [data-cd-kontrast]>`,\n * the CSP (`default-src 'none'`, `img-src <cspSource> data: blob:`, `style-src <cspSource>` plus\n * `'unsafe-inline'` unless `inlineStyles: false`, `font-src <cspSource> data:`,\n * `script-src 'nonce-…'`), the stylesheets, `body` and the nonce'd script. Attribute values and the\n * title are escaped; `body` is markup and is not. Throws for a `nonce` that is not a CSP base64\n * value.\n */\nexport function renderWebviewHtml(options: WebviewHtmlOptions): string {\n const nonce = options.nonce ?? createNonce();\n if (!CSP_NONCE.test(nonce)) {\n throw new Error(`@miragon/modeler-shell: renderWebviewHtml got an invalid nonce \"${nonce}\"`);\n }\n const appearance = appearanceAttributes(options.appearance);\n const kontrast = appearance[\"data-cd-kontrast\"];\n const htmlAttributes = [\n attribute(\"lang\", options.lang),\n attribute(\"class\", \"cd-shell-document\"),\n attribute(\"data-cd-theme\", appearance[\"data-cd-theme\"]),\n ...(kontrast ? [attribute(\"data-cd-kontrast\", kontrast)] : []),\n ].join(\" \");\n const stylesheets = (options.styleUris ?? []).map(\n (uri) => `\\n <link ${attribute(\"rel\", \"stylesheet\")} ${attribute(\"href\", uri)} />`,\n );\n\n return `<!doctype html>\n<html ${htmlAttributes}>\n <head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"Content-Security-Policy\" ${attribute(\"content\", contentSecurityPolicy(options.cspSource, nonce, options.inlineStyles !== false))} />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />${stylesheets.join(\"\")}\n <title>${escapeHtml(options.title)}</title>\n </head>\n <body>\n ${options.body ?? DEFAULT_BODY}\n <script ${attribute(\"nonce\", nonce)} ${attribute(\"src\", options.scriptUri)}></script>\n </body>\n</html>\n`;\n}\n","import {\n requestedAppearance,\n resolveAppearance,\n type Appearance,\n type ColorThemeSetting,\n type Theme,\n} from \"../../core/index.js\";\nimport { appearanceMessage } from \"../protocol.js\";\nimport type { DisposableLike, VsCodeLike, WebviewPanelLike } from \"./types.js\";\n\nexport interface ThemeBridgeOptions {\n /** The modes the modeler can show, a static value of the modeler package (`[\"light\"]` today). */\n themes: readonly Theme[];\n /** Full key of `miragon.<modeler>.colorTheme`; omit until the modeler can show dark. */\n settingKey?: string | undefined;\n}\n\nfunction isColorThemeSetting(value: unknown): value is ColorThemeSetting {\n return value === \"automatic\" || value === \"light\" || value === \"dark\";\n}\n\nfunction readColorThemeSetting(vscode: VsCodeLike, settingKey: string): ColorThemeSetting | undefined {\n const separator = settingKey.lastIndexOf(\".\");\n const value =\n separator < 0\n ? vscode.workspace.getConfiguration().get<unknown>(settingKey)\n : vscode.workspace\n .getConfiguration(settingKey.slice(0, separator))\n .get<unknown>(settingKey.slice(separator + 1));\n return isColorThemeSetting(value) ? value : undefined;\n}\n\n/**\n * The resolved appearance right now: color theme kind (and setting) through `resolveAppearance`.\n * A setting value outside `automatic | light | dark` counts as `automatic`.\n */\nexport function currentAppearance(vscode: VsCodeLike, options: ThemeBridgeOptions): Appearance {\n const setting = options.settingKey ? readColorThemeSetting(vscode, options.settingKey) : undefined;\n return resolveAppearance(requestedAppearance(vscode.window.activeColorTheme.kind, setting), options.themes);\n}\n\n/**\n * Posts an `AppearanceMessage` to the panel's webview on `onDidChangeActiveColorTheme`, on a change\n * of `settingKey` and whenever the panel becomes visible again (hidden retained webviews may miss\n * messages). Disposes itself with the panel. Throws when `themes` is empty.\n */\nexport function connectThemeBridge(\n vscode: VsCodeLike,\n panel: WebviewPanelLike,\n options: ThemeBridgeOptions,\n): DisposableLike {\n if (options.themes.length === 0) {\n throw new Error(\"@miragon/modeler-shell: connectThemeBridge needs at least one theme\");\n }\n const { settingKey } = options;\n const post = (): void => {\n void panel.webview.postMessage(appearanceMessage(currentAppearance(vscode, options)));\n };\n\n let wasVisible = panel.visible;\n const subscriptions: DisposableLike[] = [\n vscode.window.onDidChangeActiveColorTheme(post),\n panel.onDidChangeViewState(({ webviewPanel }) => {\n const becameVisible = webviewPanel.visible && !wasVisible;\n wasVisible = webviewPanel.visible;\n if (becameVisible) post();\n }),\n ];\n if (settingKey) {\n subscriptions.push(\n vscode.workspace.onDidChangeConfiguration((event) => {\n if (event.affectsConfiguration(settingKey)) post();\n }),\n );\n }\n\n let disposed = false;\n const dispose = (): void => {\n if (disposed) return;\n disposed = true;\n for (const subscription of subscriptions.splice(0)) subscription.dispose();\n };\n subscriptions.push(panel.onDidDispose(dispose));\n return { dispose };\n}\n","/**\n * The label VS Code itself uses for revealing a file, for the action on the export notification:\n * `darwin` \"Reveal in Finder\", `win32` \"Reveal in File Explorer\", otherwise \"Open Containing Folder\".\n */\nexport function revealFileLabel(platform: string): string {\n if (platform === \"darwin\") return \"Reveal in Finder\";\n if (platform === \"win32\") return \"Reveal in File Explorer\";\n return \"Open Containing Folder\";\n}\n"],"mappings":"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","names":[]}