@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/testing.ts","../src/core/types.ts","../src/core/sizes.ts","../src/core/layout.ts","../src/testing/page-tools.ts","../src/testing/geometry.ts","../src/testing/facts.ts","../src/testing/checks.ts","../src/testing/cases.ts","../src/testing/harness.ts"],"sourcesContent":["// \"@miragon/modeler-shell/testing\": the Playwright-driven shell conformance kit (Playwright injected).\nexport * from \"./testing/index.js\";\n","/** A point in pixels or diagram coordinates, as the context says. */\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** A rectangle; content bounds and viewboxes are in diagram coordinates. */\nexport interface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A viewbox together with the scale diagram-js shows it at (`canvas.viewbox().scale`). */\nexport interface ScaledViewbox extends Bounds {\n scale: number;\n}\n\n/** Distances in pixels from the edges of the modeler's container. */\nexport interface Insets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/**\n * The host column of guide §5.2: `ide` is a VS Code webview (later IntelliJ), `web` a Miragon web\n * app that owns its page, `embedded` a modeler inside a foreign page (designIQ, modeler-api hosts).\n */\nexport type ShellHost = \"ide\" | \"web\" | \"embedded\";\n\n/** The `data-chrome` names of the islands (guide §5.2, §13.4). `primary` is reserved for the web app. */\nexport type ChromeIsland =\n \"menu\" | \"palette\" | \"primary\" | \"zoom\" | \"problems\" | \"legend\" | \"inspector\" | \"status\";\n\nexport const CHROME_ISLANDS: readonly ChromeIsland[] = [\n \"menu\",\n \"palette\",\n \"primary\",\n \"zoom\",\n \"problems\",\n \"legend\",\n \"inspector\",\n \"status\",\n];\n\n/** Where the palette sits: in the top row, or in the second row below it (guide §5.15). */\nexport type PaletteRow = \"top\" | \"second-row\";\n\n/**\n * What the zoom panel and the chrome keys act on. The diagram-js viewport implements it; the DOM\n * shell only talks to this interface.\n */\nexport interface ZoomTarget {\n /** The current zoom, 1 = 100 % (diagram-js `canvas.zoom()`, rounded to three decimals). */\n zoom(): number;\n /** One step on the zoom raster around the container centre (diagram-js `zoomScroll.stepZoom`). */\n stepZoom(direction: 1 | -1): void;\n /** 100 % around the container centre. Counts as a user move. */\n zoomToActual(): void;\n /** Explicit fit (button, Shift+1, command): animated unless reduced motion, makes the view automatic. */\n fit(): void;\n /** False while there is nothing to fit (the content bounds are empty). */\n canFit(): boolean;\n /**\n * Calls `listener` after every viewbox change and whenever `canFit()` may have changed, possibly\n * several times per frame. Returns the unsubscribe function.\n */\n onChange(listener: () => void): () => void;\n}\n\n/** The persisted view (VS Code `setState`): JSON-serializable. */\nexport interface ViewportState {\n viewbox: Bounds;\n /** The user zoomed or panned since the last fit; a resize no longer refits. */\n userMoved: boolean;\n}\n","/**\n * The shell dimensions of the design system (guide §5.1, `shell` group of\n * `cd-tokens.generated.json`), keyed by a readable name. Scripts use `SHELL`; CSS uses the\n * `var(--cd-shell-*)` variables the consumer vendors. A drift test pins `SHELL` to the token JSON.\n */\nexport const SHELL_TOKENS = {\n edge: \"--cd-shell-rand\",\n gap: \"--cd-shell-luecke\",\n row: \"--cd-shell-zeile\",\n target: \"--cd-shell-ziel\",\n entry: \"--cd-shell-eintrag\",\n free: \"--cd-shell-frei\",\n menuMinWidth: \"--cd-shell-menue-breite\",\n inspectorWidth: \"--cd-shell-inspector-breite\",\n fitInsetTop: \"--cd-shell-einpassen-oben\",\n fitInsetTopSecondRow: \"--cd-shell-einpassen-oben-schmal\",\n fitInsetSide: \"--cd-shell-einpassen-seite\",\n fitInsetBottom: \"--cd-shell-einpassen-unten\",\n fitInsetBottomWeb: \"--cd-shell-einpassen-unten-web\",\n narrow: \"--cd-shell-schmal\",\n veryNarrow: \"--cd-shell-sehr-schmal\",\n low: \"--cd-shell-niedrig\",\n layerIslands: \"--cd-shell-ebene-inseln\",\n layerInspector: \"--cd-shell-ebene-inspector\",\n layerTopRow: \"--cd-shell-ebene-reihe\",\n layerPopups: \"--cd-shell-ebene-aufklapper\",\n layerDialog: \"--cd-shell-ebene-dialog\",\n layerToast: \"--cd-shell-ebene-toast\",\n} as const;\n\nexport type ShellSizeName = keyof typeof SHELL_TOKENS;\n\nexport type ShellSizes = Readonly<Record<ShellSizeName, number>>;\n\n/** Pixels (layers: plain z-index numbers), equal to `parseFloat` of the token JSON values. */\nexport const SHELL: ShellSizes = {\n edge: 12,\n gap: 8,\n row: 40,\n target: 32,\n entry: 36,\n free: 64,\n menuMinWidth: 248,\n inspectorWidth: 288,\n fitInsetTop: 88,\n fitInsetTopSecondRow: 140,\n fitInsetSide: 24,\n fitInsetBottom: 64,\n fitInsetBottomWeb: 92,\n narrow: 760,\n veryNarrow: 440,\n low: 820,\n layerIslands: 20,\n layerInspector: 25,\n layerTopRow: 30,\n layerPopups: 40,\n layerDialog: 50,\n layerToast: 60,\n};\n\n// Shell sizes are pixels (\"12px\") or plain z-index numbers (\"20\"); any other unit would make\n// parseFloat silently return a number with the wrong meaning.\nconst PIXEL_OR_PLAIN_NUMBER = /^\\s*-?(?:\\d+\\.?\\d*|\\.\\d+)(?:px)?\\s*$/;\n\n/**\n * Reads the `shell` group of `cd-tokens.generated.json` (`{ \"--cd-shell-rand\": \"12px\", … }`) into\n * numbers. Throws when a size of `SHELL_TOKENS` is missing or not a number.\n */\nexport function shellSizesFromTokens(shellGroup: Readonly<Record<string, string>>): ShellSizes {\n const sizes = {} as Record<ShellSizeName, number>;\n for (const name of Object.keys(SHELL_TOKENS) as ShellSizeName[]) {\n const token = SHELL_TOKENS[name];\n const raw: unknown = Object.hasOwn(shellGroup, token) ? shellGroup[token] : undefined;\n if (raw === undefined) {\n throw new Error(`@miragon/modeler-shell: the shell token ${token} is missing`);\n }\n if (typeof raw !== \"string\" || !PIXEL_OR_PLAIN_NUMBER.test(raw)) {\n throw new Error(\n `@miragon/modeler-shell: the shell token ${token} is not a number: ${JSON.stringify(raw)}`,\n );\n }\n sizes[name] = Number.parseFloat(raw);\n }\n return sizes;\n}\n","import { SHELL } from \"./sizes.js\";\nimport type { Bounds, 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 { Size } from \"../core/index.js\";\nimport type { PageLike } from \"./page.js\";\n\n/*\n * Everything here that is handed to `page.evaluate` runs in the browser: Playwright serializes the\n * function source, so these functions must not reference anything outside their own body. They\n * only collect facts; every judgement happens in Node (`checks.ts`, `geometry.ts`), where it is\n * unit-tested. `installPageTools` puts the shared helpers and the recorders under one page global.\n */\n\n/** A box relative to the shell root's padding box (where `position: absolute` islands anchor). */\nexport interface RelativeBox {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/** A `keydown` that reached the kit's listener on `window` (bubble phase), where VS Code's host page listens. */\nexport interface RecordedKey {\n key: string;\n code: string;\n ctrlKey: boolean;\n metaKey: boolean;\n shiftKey: boolean;\n altKey: boolean;\n defaultPrevented: boolean;\n}\n\n/** The facts the kit reads about one element. */\nexport interface ElementFacts {\n tag: string;\n description: string;\n attributes: Record<string, string>;\n text: string;\n visible: boolean;\n /** The native `disabled` property (a disabled `<button>` loses focus, `aria-disabled` keeps it). */\n disabled: boolean;\n}\n\n/** The helpers and recorders `installPageTools` keeps under the page global. */\nexport interface PageTools {\n /** `keydown`s that reached `window`, where VS Code's host page listens. */\n keys: RecordedKey[];\n /**\n * `keydown`s seen on `document` after every listener registered before the kit's (the shell's,\n * the modeler's), so `defaultPrevented` is final even where the shell stops the key.\n */\n documentKeys: RecordedKey[];\n errors: string[];\n injected: Element[];\n cleanups: Array<() => void>;\n armedRoot?: HTMLElement;\n frame(): Promise<void>;\n settle(): Promise<void>;\n visible(element: Element): boolean;\n container(root: HTMLElement): Size;\n box(element: Element, root: HTMLElement): RelativeBox;\n describe(element: Element): string;\n facts(element: Element): ElementFacts;\n}\n\nexport type ToolWindow = Window & { __modelerShellConformance?: PageTools };\n\n/** Installs the in-page helpers once per document (idempotent; a navigation drops them). */\nexport const installPageTools = (_: null): void => {\n const scope = window as ToolWindow;\n if (scope.__modelerShellConformance) return;\n const modifierKeys = [\"Control\", \"Meta\", \"Shift\", \"Alt\", \"AltGraph\", \"CapsLock\", \"Fn\"];\n const frame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));\n const borders = (element: Element) => {\n const style = getComputedStyle(element);\n return {\n left: parseFloat(style.borderLeftWidth) || 0,\n top: parseFloat(style.borderTopWidth) || 0,\n right: parseFloat(style.borderRightWidth) || 0,\n bottom: parseFloat(style.borderBottomWidth) || 0,\n };\n };\n const visible = (element: Element): boolean => {\n if (!element.isConnected) return false;\n if (typeof element.checkVisibility === \"function\") {\n if (!element.checkVisibility({ visibilityProperty: true })) return false;\n } else {\n if (element.closest(\"[hidden]\")) return false;\n for (let node: Element | null = element; node; node = node.parentElement) {\n if (getComputedStyle(node).display === \"none\") return false;\n }\n if (getComputedStyle(element).visibility === \"hidden\") return false;\n }\n const rect = element.getBoundingClientRect();\n return rect.width > 0 && rect.height > 0;\n };\n const describe = (element: Element): string => {\n const id = element.id ? `#${element.id}` : \"\";\n const classes = [...element.classList]\n .slice(0, 3)\n .map((name) => `.${name}`)\n .join(\"\");\n const chrome = element.getAttribute(\"data-chrome\");\n return `${element.tagName.toLowerCase()}${id}${classes}${chrome ? `[data-chrome=\"${chrome}\"]` : \"\"}`;\n };\n const tools: PageTools = {\n keys: [],\n documentKeys: [],\n errors: [],\n injected: [],\n cleanups: [],\n frame,\n async settle() {\n await frame();\n await frame();\n const running =\n typeof document.getAnimations === \"function\"\n ? document.getAnimations().filter((animation) => {\n const end = animation.effect?.getComputedTiming().endTime;\n return animation.playState === \"running\" && typeof end === \"number\" && Number.isFinite(end);\n })\n : [];\n if (running.length > 0) {\n await Promise.race([\n Promise.allSettled(running.map((animation) => animation.finished)),\n new Promise((resolve) => setTimeout(resolve, 2000)),\n ]);\n }\n await frame();\n },\n visible,\n container(root) {\n const rect = root.getBoundingClientRect();\n const border = borders(root);\n return {\n width: rect.width - border.left - border.right,\n height: rect.height - border.top - border.bottom,\n };\n },\n box(element, root) {\n const rect = element.getBoundingClientRect();\n const origin = root.getBoundingClientRect();\n const border = borders(root);\n return {\n left: rect.left - origin.left - border.left,\n top: rect.top - origin.top - border.top,\n width: rect.width,\n height: rect.height,\n };\n },\n describe,\n facts(element) {\n const attributes: Record<string, string> = {};\n for (const name of element.getAttributeNames()) attributes[name] = element.getAttribute(name) ?? \"\";\n return {\n tag: element.tagName.toLowerCase(),\n description: describe(element),\n attributes,\n text: (element.textContent ?? \"\").replace(/\\s+/g, \" \").trim(),\n visible: visible(element),\n disabled: Boolean((element as HTMLButtonElement).disabled),\n };\n },\n };\n const recorder = (into: RecordedKey[]) => (event: KeyboardEvent) => {\n if (modifierKeys.includes(event.key)) return;\n into.push({\n key: event.key,\n code: event.code,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n defaultPrevented: event.defaultPrevented,\n });\n };\n document.addEventListener(\"keydown\", recorder(tools.documentKeys));\n window.addEventListener(\"keydown\", recorder(tools.keys));\n window.addEventListener(\"error\", (event) => {\n tools.errors.push(event.message || String(event.error));\n });\n window.addEventListener(\"unhandledrejection\", (event) => {\n tools.errors.push(`unhandled rejection: ${String(event.reason)}`);\n });\n scope.__modelerShellConformance = tools;\n};\n\n/** Runs `pageFunction` in the page after making sure the helpers are installed. */\nexport async function inPage<Arg, Result>(\n page: PageLike,\n pageFunction: (arg: Arg) => Result | Promise<Result>,\n arg: Arg,\n): Promise<Result> {\n await page.evaluate(installPageTools, null);\n return page.evaluate(pageFunction, arg);\n}\n\n/** Two frames plus every finite running animation (pop-ins, slide-ins), capped at 2s. */\nexport const settleInPage = (_: null): Promise<void> =>\n (window as ToolWindow).__modelerShellConformance!.settle();\n\nexport function settle(page: PageLike): Promise<void> {\n return inPage(page, settleInPage, null);\n}\n\n/** The controls the kit hovers, clicks or focuses, found inside the shell root. */\nexport type ChromeTarget =\n | \"menu\"\n | \"palette-entry\"\n | \"palette-tab-stop\"\n | \"zoom-out\"\n | \"zoom-actual\"\n | \"zoom-in\"\n | \"zoom-fit\"\n | \"canvas\";\n\nexport const CHROME_TARGET_SELECTORS: Readonly<Record<ChromeTarget, string>> = {\n menu: '[data-chrome=\"menu\"]',\n \"palette-entry\": '[data-chrome=\"palette\"] [data-action]',\n \"palette-tab-stop\": '[data-chrome=\"palette\"] [data-action][tabindex=\"0\"]',\n \"zoom-out\": '[data-chrome=\"zoom\"] [data-zoom=\"out\"]',\n \"zoom-actual\": '[data-chrome=\"zoom\"] [data-zoom=\"actual\"]',\n \"zoom-in\": '[data-chrome=\"zoom\"] [data-zoom=\"in\"]',\n \"zoom-fit\": '[data-chrome=\"zoom\"] [data-zoom=\"fit\"]',\n canvas: \".djs-container > svg\",\n};\n\nexport interface TargetFacts {\n /** Viewport coordinates of the centre, for `page.mouse`. */\n client: { x: number; y: number };\n box: RelativeBox;\n /** `aria-label`, else the text. */\n label: string;\n}\n\n/** The first visible match of `selector` inside the root; `null` when there is none. */\nexport const targetProbe = ({ root, selector }: { root: string; selector: string }): TargetFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return null;\n const element = [...rootElement.querySelectorAll(selector)].find((candidate) => tools.visible(candidate));\n if (!element) return null;\n const rect = element.getBoundingClientRect();\n return {\n client: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },\n box: tools.box(element, rootElement),\n label: (element.getAttribute(\"aria-label\") ?? element.textContent ?? \"\").replace(/\\s+/g, \" \").trim(),\n };\n};\n\nexport async function findTarget(\n page: PageLike,\n root: string,\n target: ChromeTarget,\n): Promise<TargetFacts | null> {\n return inPage(page, targetProbe, { root, selector: CHROME_TARGET_SELECTORS[target] });\n}\n\n/** Focuses the first match of `selector` inside the root; the description of the focused element. */\nexport const focusProbe = ({ root, selector }: { root: string; selector: string }): string | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const element = document.querySelector(root)?.querySelector<HTMLElement | SVGElement>(selector);\n if (!element) return null;\n element.focus();\n return document.activeElement === element ? tools.describe(element) : null;\n};\n\nexport async function focusTarget(\n page: PageLike,\n root: string,\n target: ChromeTarget,\n): Promise<string | null> {\n return inPage(page, focusProbe, { root, selector: CHROME_TARGET_SELECTORS[target] });\n}\n\n/** A visible popup with `role` inside the root (the dropdown, the chrome tooltip). */\nexport interface OverlayFacts {\n box: RelativeBox;\n text: string;\n /** How many visible elements carry the role. */\n count: number;\n id: string;\n}\n\nexport const overlayProbe = ({ root, role }: { root: string; role: string }): OverlayFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return null;\n const shown = [...rootElement.querySelectorAll(`[role=\"${role}\"]`)].filter((element) =>\n tools.visible(element),\n );\n const first = shown[0];\n if (!first) return null;\n return {\n box: tools.box(first, rootElement),\n text: (first.textContent ?? \"\").replace(/\\s+/g, \" \").trim(),\n count: shown.length,\n id: first.id,\n };\n};\n\nexport async function findOverlay(\n page: PageLike,\n root: string,\n role: \"menu\" | \"tooltip\",\n): Promise<OverlayFacts | null> {\n return inPage(page, overlayProbe, { root, role });\n}\n\nexport interface PressFacts {\n /** The readout as a whole percentage; `null` without a readout. */\n zoom: number | null;\n keys: RecordedKey[];\n documentKeys: RecordedKey[];\n}\n\n/** After a key press: settles, then reads the readout and takes the keys `window` and `document` saw. */\nexport const afterPressProbe = async ({ root }: { root: string }): Promise<PressFacts> => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n await tools.settle();\n const readout = document\n .querySelector(root)\n ?.querySelector('[data-chrome=\"zoom\"] [data-zoom=\"actual\"]')?.textContent;\n const digits = (readout ?? \"\").replace(/[^0-9]/g, \"\");\n return {\n zoom: digits ? Number(digits) : null,\n keys: tools.keys.splice(0),\n documentKeys: tools.documentKeys.splice(0),\n };\n};\n\n/** Drops what `window` saw so far. */\nexport const clearKeysProbe = (_: null): void => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n tools.keys.splice(0);\n tools.documentKeys.splice(0);\n};\n\nexport type InjectedKind = \"input\" | \"textarea\" | \"contenteditable\" | \"modal\" | \"popover\" | \"focus-target\";\n\n/**\n * Adds a stand-in for what modelers render inside the shell (text fields: an input, a textarea, an\n * editable label; a modal dialog, a popover, a plain focus target), inside the root or, once it is\n * gone, the body; focuses it.\n */\nexport const injectProbe = ({ root, kind }: { root: string; kind: InjectedKind }): boolean => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const parent = document.querySelector(root) ?? tools.armedRoot ?? document.body;\n const host = parent.isConnected ? parent : document.body;\n const element =\n kind === \"input\" || kind === \"textarea\"\n ? document.createElement(kind)\n : (document.createElement(\"div\") as HTMLElement);\n element.setAttribute(\"data-modeler-shell-conformance\", kind);\n element.style.cssText = \"position:absolute;left:0;top:0;width:40px;height:20px;\";\n if (kind === \"modal\" || kind === \"popover\") {\n element.setAttribute(\"role\", \"dialog\");\n element.setAttribute(\"aria-label\", \"Conformance stand-in\");\n if (kind === \"modal\") element.setAttribute(\"aria-modal\", \"true\");\n }\n if (kind === \"contenteditable\") element.setAttribute(\"contenteditable\", \"true\");\n else if (kind !== \"input\" && kind !== \"textarea\") element.tabIndex = -1;\n host.append(element);\n tools.injected.push(element);\n element.focus();\n return document.activeElement === element;\n};\n\nexport const removeInjectedProbe = (_: null): void => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n for (const element of tools.injected.splice(0)) element.remove();\n for (const cleanup of tools.cleanups.splice(0)) cleanup();\n};\n\n/** Makes the canvas `<svg>` handle `key` (`preventDefault`), as a modeler's own canvas binding would. */\nexport const canvasHandlesProbe = ({ root, key }: { root: string; key: string }): boolean => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const svg = document.querySelector(root)?.querySelector(\".djs-container > svg\");\n if (!svg) return false;\n const listener = (event: Event) => {\n if ((event as KeyboardEvent).key === key) event.preventDefault();\n };\n svg.addEventListener(\"keydown\", listener);\n tools.cleanups.push(() => svg.removeEventListener(\"keydown\", listener));\n return true;\n};\n\n/** Remembers the root right before `destroy` (its class is gone afterwards) and clears the recorders. */\nexport const armCleanupProbe = ({ root }: { root: string }): boolean => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (rootElement) tools.armedRoot = rootElement;\n tools.errors.splice(0);\n tools.keys.splice(0);\n tools.documentKeys.splice(0);\n return Boolean(rootElement);\n};\n\n/** What the shell left behind after `destroy`. */\nexport interface LeftoverFacts {\n /** Elements (other than `<html>`) with a `cd-shell*` class. */\n classedElements: string[];\n /** `cd-shell*` classes on `<html>`. */\n documentClasses: string[];\n /** Elements still carrying `data-chrome`. */\n chromeElements: string[];\n /** The remembered root's `class` and attributes. */\n rootClasses: string[];\n rootAttributes: string[];\n errors: string[];\n}\n\nexport const leftoverProbe = (_: null): LeftoverFacts => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const ours = (element: Element) => element.hasAttribute(\"data-modeler-shell-conformance\");\n const shellClass = (name: string) => name.startsWith(\"cd-shell\");\n const root = tools.armedRoot;\n return {\n classedElements: [...document.querySelectorAll(\"[class]\")]\n .filter((element) => element !== document.documentElement && !ours(element))\n .filter((element) => [...element.classList].some(shellClass))\n .map((element) => tools.describe(element)),\n documentClasses: [...document.documentElement.classList].filter(shellClass),\n chromeElements: [...document.querySelectorAll(\"[data-chrome]\")].map((element) => tools.describe(element)),\n rootClasses: root ? [...root.classList].filter(shellClass) : [],\n rootAttributes: root ? root.getAttributeNames() : [],\n errors: [...tools.errors],\n };\n};\n\n/** Puts a foreign page's `<html>` in a mode, as a themed host page around an embedded modeler. */\nexport const hostPageModeProbe = ({ theme, kontrast }: { theme: string; kontrast: string | null }): void => {\n const html = document.documentElement;\n html.setAttribute(\"data-cd-theme\", theme);\n if (kontrast) html.setAttribute(\"data-cd-kontrast\", kontrast);\n else html.removeAttribute(\"data-cd-kontrast\");\n};\n","import {\n CHROME_ISLANDS,\n PALETTE_CLEARANCE,\n SHELL,\n type ChromeIsland,\n type Insets,\n type PaletteRow,\n type ShellHost,\n type Size,\n} from \"../core/index.js\";\nimport type { PageLike } from \"./page.js\";\nimport { inPage, type RelativeBox, type ToolWindow } from \"./page-tools.js\";\n\n/** Every island box must match within this many pixels (guide §13.4). */\nexport const GEOMETRY_TOLERANCE_PX = 1;\n\n/**\n * `getBoundingClientRect()` relative to the shell root's padding box, where its absolutely\n * positioned islands anchor (a border on the root, as in a framed foreign page, does not count).\n */\nexport interface IslandBox {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\nexport interface ChromeMeasurement {\n container: Size;\n /** From the root's `data-palette` attribute. */\n paletteRow: PaletteRow;\n /** The visible islands, found by `[data-chrome]`. */\n islands: Partial<Record<ChromeIsland, IslandBox>>;\n /** `[data-legend=\"open\"]`, `[data-inspector=\"open\"]`, `[data-problems=\"shown\"]` on the root. */\n open: { legend: boolean; inspector: boolean; problems: boolean };\n}\n\n/** Constraints of one island; every given field must hold within `GEOMETRY_TOLERANCE_PX`. */\nexport interface ExpectedBox {\n left?: number;\n top?: number;\n right?: number;\n bottom?: number;\n width?: number;\n height?: number;\n /** Horizontal centre relative to the root. */\n centerX?: number;\n}\n\nexport const DEFAULT_ROOT = \".cd-shell\";\n\n/** `[−] [NN%] [+] | [Fit]` with a 56px readout (guide §5.1, §5.8): 1+3+32+2+56+2+32+2+5+2+32+3+1. */\nexport const ZOOM_PANEL_WIDTH = 173;\n\n/** Height of the web app's legal line under the bottom-left stack (guide §5.10). */\nconst LEGAL_LINE = 20;\n\n/** Minimum width of the legend card (guide §5.10). */\nconst LEGEND_MIN_WIDTH = 184;\n\nconst STATUS_MAX_WIDTH = 560;\nconst DROPDOWN_MAX_WIDTH = 320;\nconst TOOLTIP_MAX_WIDTH = 280;\nconst SHEET_MAX_HEIGHT_SHARE = 0.45;\n\ntype MeasureResult = { error: string } | (ChromeMeasurement & { duplicates: string[] });\n\nconst measureProbe = ({ root, islands }: { root: string; islands: readonly string[] }): MeasureResult => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return { error: `no element matches the shell root selector \"${root}\"` };\n const boxes: Partial<Record<string, RelativeBox>> = {};\n const duplicates: string[] = [];\n for (const element of rootElement.querySelectorAll(\"[data-chrome]\")) {\n const name = element.getAttribute(\"data-chrome\") ?? \"\";\n if (!islands.includes(name) || !tools.visible(element)) continue;\n if (boxes[name]) {\n duplicates.push(name);\n continue;\n }\n boxes[name] = tools.box(element, rootElement);\n }\n return {\n container: tools.container(rootElement),\n paletteRow: rootElement.getAttribute(\"data-palette\") === \"second-row\" ? \"second-row\" : \"top\",\n islands: boxes,\n open: {\n legend: rootElement.getAttribute(\"data-legend\") === \"open\",\n inspector: rootElement.getAttribute(\"data-inspector\") === \"open\",\n problems: rootElement.getAttribute(\"data-problems\") === \"shown\",\n },\n duplicates,\n };\n};\n\n/** Measures the islands of the shell under `root` (default `.cd-shell`) in the page. */\nexport async function measureChrome(page: PageLike, root: string = DEFAULT_ROOT): Promise<ChromeMeasurement> {\n const result = await inPage(page, measureProbe, { root, islands: CHROME_ISLANDS });\n if (\"error\" in result) throw new Error(`@miragon/modeler-shell conformance: ${result.error}`);\n if (result.duplicates.length > 0) {\n const names = [...new Set(result.duplicates)].map((name) => `[data-chrome=\"${name}\"]`).join(\", \");\n throw new Error(`@miragon/modeler-shell conformance: more than one visible ${names}`);\n }\n return {\n container: result.container,\n paletteRow: result.paletteRow,\n islands: result.islands,\n open: result.open,\n };\n}\n\n/** Upper and lower limits the guide gives as \"at least\" and \"at most\" (guide §5.4 to §5.15). */\nexport interface BoxLimits {\n minWidth?: number;\n maxWidth?: number;\n maxHeight?: number;\n minLeft?: number;\n minRight?: number;\n minBottom?: number;\n}\n\n/** What the guide expects of the chrome in a measured state. */\nexport interface ChromeExpectations {\n boxes: Partial<Record<ChromeIsland, ExpectedBox>>;\n limits: Partial<Record<ChromeIsland, BoxLimits>>;\n /** Islands that must be visible. */\n required: ChromeIsland[];\n /** Islands that must not be visible, with the rule that hides them. */\n hidden: Partial<Record<ChromeIsland, string>>;\n}\n\nfunction isNarrow(container: Size): boolean {\n return container.width <= SHELL.narrow;\n}\n\nfunction isVeryNarrow(container: Size): boolean {\n return container.width <= SHELL.veryNarrow;\n}\n\n/** The open inspector is a bottom sheet up to `SHELL.narrow` (guide §5.11). */\nfunction sheetOpen(measurement: ChromeMeasurement): boolean {\n return measurement.open.inspector && isNarrow(measurement.container);\n}\n\n/** The anchors and limits of guide §5.2 to §5.15 for `measurement` in `host`. */\nexport function chromeExpectations(measurement: ChromeMeasurement, host: ShellHost): ChromeExpectations {\n const { container, islands, open, paletteRow } = measurement;\n const { edge, gap, row, free, inspectorWidth } = SHELL;\n const web = host === \"web\";\n const secondRow = paletteRow === \"second-row\";\n const sheet = sheetOpen(measurement);\n const sideInspector = open.inspector && !isNarrow(container);\n const boxes: Partial<Record<ChromeIsland, ExpectedBox>> = {};\n const limits: Partial<Record<ChromeIsland, BoxLimits>> = {};\n const hidden: Partial<Record<ChromeIsland, string>> = {};\n const required: ChromeIsland[] = [\"menu\", \"palette\"];\n\n boxes.menu = { left: edge, top: edge, width: row, height: row };\n\n boxes.palette = { top: secondRow ? free : edge, height: row, centerX: container.width / 2 };\n const menu = islands.menu;\n limits.palette = secondRow\n ? { maxWidth: container.width - 2 * edge }\n : menu\n ? { minLeft: menu.left + menu.width + PALETTE_CLEARANCE }\n : {};\n\n if (sheet) {\n const reason = \"hidden while the inspector is a bottom sheet (guide §5.11)\";\n hidden.zoom = reason;\n hidden.problems = reason;\n hidden.legend = reason;\n } else {\n required.push(\"zoom\");\n boxes.zoom = { right: edge, bottom: edge, width: ZOOM_PANEL_WIDTH, height: row };\n const stackBase = web ? edge + LEGAL_LINE + gap : edge;\n if (islands.problems) boxes.problems = { left: edge, bottom: stackBase, height: row };\n if (islands.legend) {\n const besidePill = open.problems ? stackBase + row + gap : stackBase;\n const bottom = isVeryNarrow(container) ? Math.max(besidePill, edge + row + gap) : besidePill;\n boxes.legend = { left: edge, bottom };\n limits.legend = { minWidth: LEGEND_MIN_WIDTH };\n }\n }\n\n if (islands.inspector) {\n if (sheet) {\n boxes.inspector = { left: edge, right: edge, bottom: edge };\n limits.inspector = { maxHeight: container.height * SHEET_MAX_HEIGHT_SHARE };\n } else {\n boxes.inspector = { top: free, right: edge, width: inspectorWidth };\n limits.inspector = { minBottom: free };\n }\n }\n\n if (islands.status) {\n const strip = sideInspector ? container.width - edge - inspectorWidth : container.width;\n boxes.status = { top: secondRow ? free + row + edge : free, centerX: strip / 2 };\n limits.status = {\n minLeft: edge,\n maxWidth: Math.min(STATUS_MAX_WIDTH, container.width - 2 * edge),\n };\n }\n\n if (web) {\n if (islands.primary) boxes.primary = { top: edge, right: edge, height: row };\n } else {\n hidden.primary = \"the top right stays empty in IDE and embedded hosts (guide §5.7)\";\n }\n\n return { boxes, limits, required, hidden };\n}\n\n/** The boxes guide §5.2–§5.12 expects for what was measured (anchors per host and breakpoint). */\nexport function expectedChromeBoxes(\n measurement: ChromeMeasurement,\n host: ShellHost,\n): Partial<Record<ChromeIsland, ExpectedBox>> {\n return chromeExpectations(measurement, host).boxes;\n}\n\nconst round = (value: number): number => Math.round(value * 10) / 10;\n\nfunction sides(box: IslandBox, container: Size): Required<ExpectedBox> {\n return {\n left: box.left,\n top: box.top,\n right: container.width - box.left - box.width,\n bottom: container.height - box.top - box.height,\n width: box.width,\n height: box.height,\n centerX: box.left + box.width / 2,\n };\n}\n\n/** Every field of `expected` that `box` misses by more than `tolerance`, as readable problems. */\nexport function boxMismatches(\n name: string,\n box: IslandBox,\n expected: ExpectedBox,\n container: Size,\n tolerance: number = GEOMETRY_TOLERANCE_PX,\n): string[] {\n const actual = sides(box, container);\n return (Object.keys(expected) as Array<keyof ExpectedBox>).flatMap((field) => {\n const want = expected[field];\n if (want === undefined) return [];\n const have = actual[field];\n return Math.abs(have - want) > tolerance + 1e-6\n ? [`${name}: ${field} is ${round(have)}px, expected ${round(want)}px (±${tolerance}px)`]\n : [];\n });\n}\n\n/** Every limit `box` breaks by more than `tolerance`. */\nexport function limitViolations(\n name: string,\n box: IslandBox,\n limits: BoxLimits,\n container: Size,\n tolerance: number = GEOMETRY_TOLERANCE_PX,\n): string[] {\n const actual = sides(box, container);\n const problems: string[] = [];\n const atLeast = (field: string, have: number, limit: number | undefined) => {\n if (limit !== undefined && have < limit - tolerance - 1e-6) {\n problems.push(`${name}: ${field} is ${round(have)}px, at least ${round(limit)}px expected`);\n }\n };\n const atMost = (field: string, have: number, limit: number | undefined) => {\n if (limit !== undefined && have > limit + tolerance + 1e-6) {\n problems.push(`${name}: ${field} is ${round(have)}px, at most ${round(limit)}px expected`);\n }\n };\n atLeast(\"width\", actual.width, limits.minWidth);\n atMost(\"width\", actual.width, limits.maxWidth);\n atMost(\"height\", actual.height, limits.maxHeight);\n atLeast(\"left\", actual.left, limits.minLeft);\n atLeast(\"right\", actual.right, limits.minRight);\n atLeast(\"bottom\", actual.bottom, limits.minBottom);\n return problems;\n}\n\n/**\n * Every deviation of a measured state from guide §5.2 to §5.15: missing and unexpected islands,\n * boxes and limits, the palette row decision and the root's state attributes.\n */\nexport function geometryProblems(\n measurement: ChromeMeasurement,\n host: ShellHost,\n tolerance: number = GEOMETRY_TOLERANCE_PX,\n): string[] {\n const { container, islands, open, paletteRow } = measurement;\n const expectations = chromeExpectations(measurement, host);\n const problems: string[] = [];\n const sheet = sheetOpen(measurement);\n\n for (const name of expectations.required) {\n if (!islands[name]) problems.push(`${name}: [data-chrome=\"${name}\"] is missing or not visible`);\n }\n for (const name of CHROME_ISLANDS) {\n const box = islands[name];\n if (!box) continue;\n const expected = expectations.boxes[name];\n if (!expected) {\n const reason = expectations.hidden[name] ?? \"no anchor of the guide applies\";\n problems.push(`${name}: visible, but ${reason}`);\n continue;\n }\n problems.push(...boxMismatches(name, box, expected, container, tolerance));\n const limits = expectations.limits[name];\n if (limits) problems.push(...limitViolations(name, box, limits, container, tolerance));\n }\n\n if (isNarrow(container) && paletteRow !== \"second-row\") {\n problems.push(\n `palette: data-palette=\"${paletteRow}\" in a ${round(container.width)}px wide container; up to ${SHELL.narrow}px it is \"second-row\" (guide §5.15)`,\n );\n }\n const palette = islands.palette;\n const menu = islands.menu;\n if (paletteRow === \"second-row\" && !isNarrow(container) && palette && menu) {\n const clipped = palette.width >= container.width - 2 * SHELL.edge - tolerance;\n const topRowLeft = (container.width - palette.width) / 2;\n if (!clipped && topRowLeft >= menu.left + menu.width + PALETTE_CLEARANCE + tolerance) {\n problems.push(\n `palette: in the second row although the top row keeps ${round(topRowLeft - menu.left - menu.width)}px to the menu trigger (at least ${PALETTE_CLEARANCE}px suffice, guide §5.15)`,\n );\n }\n }\n\n const state = (island: ChromeIsland, flag: boolean, attribute: string, hiddenBySheet: boolean) => {\n const shown = Boolean(islands[island]);\n if (flag && !shown && !hiddenBySheet) {\n problems.push(`${island}: the root carries ${attribute}, but the island is not visible`);\n }\n if (!flag && shown) problems.push(`${island}: visible, but the root lacks ${attribute}`);\n };\n state(\"problems\", open.problems, 'data-problems=\"shown\"', sheet);\n state(\"legend\", open.legend, 'data-legend=\"open\"', sheet);\n state(\"inspector\", open.inspector, 'data-inspector=\"open\"', false);\n\n return problems;\n}\n\n/**\n * The fit insets of guide §5.9 for what was measured, recomputed from the guide's table: top 88\n * (second row 140), sides 24, bottom 64 (web app with the pill 92); right 12 + 288 + 24 with a side\n * inspector; left 12 + legend width + 24 with an open legend in a container wider than 440px; with\n * a bottom sheet the bottom is the distance to its top edge plus 12, and the legend does not count.\n */\nexport function expectedFitInsets(measurement: ChromeMeasurement, host: ShellHost): Insets {\n const { container, islands, open, paletteRow } = measurement;\n const insets: Insets = {\n top: paletteRow === \"second-row\" ? SHELL.fitInsetTopSecondRow : SHELL.fitInsetTop,\n right: SHELL.fitInsetSide,\n bottom: host === \"web\" && open.problems ? SHELL.fitInsetBottomWeb : SHELL.fitInsetBottom,\n left: SHELL.fitInsetSide,\n };\n if (sheetOpen(measurement)) {\n const sheet = islands.inspector;\n insets.bottom = sheet ? container.height - sheet.top + SHELL.edge : SHELL.fitInsetBottom;\n return insets;\n }\n if (open.inspector) insets.right = SHELL.edge + SHELL.inspectorWidth + SHELL.fitInsetSide;\n const legend = islands.legend;\n if (open.legend && legend && legend.width > 0 && container.width > SHELL.veryNarrow) {\n insets.left = SHELL.edge + legend.width + SHELL.fitInsetSide;\n }\n return insets;\n}\n\n/** A rectangle relative to the shell root's padding box, by its edges. */\nexport interface Rectangle {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\n/**\n * The free rectangle of guide §5.9: the container minus `expectedFitInsets`. Where the insets\n * leave no room on an axis, that axis spans the whole container (as the fit centres there).\n */\nexport function freeRectangle(measurement: ChromeMeasurement, host: ShellHost): Rectangle {\n const { container } = measurement;\n const insets = expectedFitInsets(measurement, host);\n const horizontal = container.width - insets.left - insets.right > 0;\n const vertical = container.height - insets.top - insets.bottom > 0;\n return {\n left: horizontal ? insets.left : 0,\n top: vertical ? insets.top : 0,\n right: horizontal ? container.width - insets.right : container.width,\n bottom: vertical ? container.height - insets.bottom : container.height,\n };\n}\n\n/** Where the dropdown opens (guide §5.4): under the trigger, at least 248px, inside the container. */\nexport function dropdownProblems(\n box: IslandBox,\n container: Size,\n tolerance = GEOMETRY_TOLERANCE_PX,\n): string[] {\n const { edge, gap, row, menuMinWidth } = SHELL;\n return [\n ...boxMismatches(\"dropdown\", box, { top: edge + row + gap, left: edge }, container, tolerance),\n ...limitViolations(\n \"dropdown\",\n box,\n {\n minWidth: menuMinWidth,\n maxWidth: Math.min(DROPDOWN_MAX_WIDTH, container.width - 2 * edge),\n minBottom: edge,\n },\n container,\n tolerance,\n ),\n ];\n}\n\n/** Which island a tooltip belongs to decides its row (guide §5.6). */\nexport type TooltipRow = \"top\" | \"second-row\" | \"bottom\";\n\n/**\n * Where the chrome tooltip of a control stands (guide §5.6): 8px below the top row (`top: 60px`)\n * or the second row (`top: 112px`), 8px above the bottom row (`bottom: 60px`); centred on its\n * control and shifted to keep 12px to the sides.\n */\nexport function tooltipProblems(\n tooltip: IslandBox,\n anchor: IslandBox,\n row: TooltipRow,\n container: Size,\n tolerance = GEOMETRY_TOLERANCE_PX,\n): string[] {\n const { edge, gap, row: rowHeight, free } = SHELL;\n const clamp = (centred: number) =>\n Math.max(edge, Math.min(centred, container.width - edge - tooltip.width));\n const expectedAt = (left: number): ExpectedBox =>\n row === \"bottom\"\n ? { left, bottom: edge + rowHeight + gap }\n : { left, top: (row === \"top\" ? edge : free) + rowHeight + gap };\n let mismatches = boxMismatches(\n \"tooltip\",\n tooltip,\n expectedAt(clamp(anchor.left + anchor.width / 2 - tooltip.width / 2)),\n container,\n tolerance,\n );\n // Guide §5.15 reads \"mittig im Container\" for the second row; until the guide settles whether\n // that means the container or the entry, either centre conforms.\n if (row === \"second-row\" && mismatches.length > 0) {\n const inContainer = boxMismatches(\n \"tooltip\",\n tooltip,\n expectedAt(clamp(container.width / 2 - tooltip.width / 2)),\n container,\n tolerance,\n );\n if (inContainer.length === 0) mismatches = inContainer;\n }\n return [\n ...mismatches,\n ...limitViolations(\n \"tooltip\",\n tooltip,\n { minLeft: edge, minRight: edge, maxWidth: Math.min(TOOLTIP_MAX_WIDTH, container.width - 2 * edge) },\n container,\n tolerance,\n ),\n ];\n}\n","import type { ElementFacts, RelativeBox, ToolWindow } from \"./page-tools.js\";\n\n/*\n * Snapshots the cases judge in Node (`checks.ts`). Each probe runs in the page and must stay\n * self-contained (see page-tools.ts).\n */\n\nexport type ZoomButton = \"out\" | \"actual\" | \"in\" | \"fit\";\n\n/** The chrome parts in the DOM (and tab) order of guide §5.14. */\nexport const DOM_ORDER = [\n \"menu\",\n \"primary\",\n \"palette\",\n \"canvas\",\n \"status\",\n \"hint\",\n \"inspector\",\n \"problems\",\n \"legend\",\n \"zoom\",\n] as const;\n\nexport type OrderedPart = (typeof DOM_ORDER)[number];\n\nexport interface PaletteEntryFacts extends ElementFacts {\n group: string | null;\n}\n\nexport interface AriaFacts {\n platform: \"mac\" | \"other\";\n documentLang: string;\n rootLang: string | null;\n trigger: ElementFacts | null;\n /** The element the trigger's `aria-controls` names. */\n controlled: ElementFacts | null;\n palette: ElementFacts | null;\n toolbar: ElementFacts | null;\n /** The focusable canvas `<svg>` (`.djs-container > svg`). */\n canvas: ElementFacts | null;\n entries: PaletteEntryFacts[];\n zoom: ElementFacts | null;\n zoomButtons: Partial<Record<ZoomButton, ElementFacts>>;\n /** The parts that exist, in DOM order. */\n order: OrderedPart[];\n /** Elements inside the root with a positive `tabindex`. */\n positiveTabindex: string[];\n /** Chrome controls with a native `title` tooltip. */\n titled: string[];\n problems: ElementFacts | null;\n status: ElementFacts | null;\n legend: ElementFacts | null;\n /** Text of the legend's `aria-labelledby` targets. */\n legendTitle: string | null;\n legendClose: ElementFacts | null;\n inspector: ElementFacts | null;\n}\n\nexport const ariaProbe = ({ root }: { root: string }): AriaFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return null;\n const find = (selector: string) => rootElement.querySelector(selector);\n const factsOf = (element: Element | null | undefined) => (element ? tools.facts(element) : null);\n const navigatorLike = navigator as Navigator & { userAgentData?: { platform?: string } };\n const trigger = find('[data-chrome=\"menu\"]');\n const controlsId = trigger?.getAttribute(\"aria-controls\");\n const palette = find('[data-chrome=\"palette\"]');\n const toolbar =\n palette?.querySelector('[role=\"toolbar\"]') ?? palette?.querySelector(\".djs-palette-entries\");\n const zoom = find('[data-chrome=\"zoom\"]');\n const zoomButtons: Partial<Record<ZoomButton, ElementFacts>> = {};\n for (const name of [\"out\", \"actual\", \"in\", \"fit\"] as const) {\n const button = zoom?.querySelector(`[data-zoom=\"${name}\"]`);\n if (button) zoomButtons[name] = tools.facts(button);\n }\n const legend = find('[data-chrome=\"legend\"]');\n const labelledBy = legend?.getAttribute(\"aria-labelledby\");\n const parts: Array<[string, Element | null]> = [\n [\"menu\", trigger],\n [\"primary\", find('[data-chrome=\"primary\"]')],\n [\"palette\", palette],\n [\"canvas\", find(\".djs-container > svg\")],\n [\"status\", find('[data-chrome=\"status\"]')],\n [\"hint\", find(\".cd-shell-hint\")],\n [\"inspector\", find('[data-chrome=\"inspector\"]')],\n [\"problems\", find('[data-chrome=\"problems\"]')],\n [\"legend\", legend],\n [\"zoom\", zoom],\n ];\n const present = parts.filter((part): part is [string, Element] => part[1] !== null);\n present.sort(([, a], [, b]) => (a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1));\n const titledSelector = [\n '[data-chrome=\"menu\"][title]',\n '[data-chrome=\"palette\"] [data-action][title]',\n '[data-chrome=\"zoom\"] [title]',\n '[data-chrome=\"problems\"][title]',\n ].join(\", \");\n return {\n platform: /mac/i.test(navigatorLike.userAgentData?.platform ?? navigatorLike.platform ?? \"\")\n ? \"mac\"\n : \"other\",\n documentLang: document.documentElement.lang,\n rootLang: rootElement.getAttribute(\"lang\"),\n trigger: factsOf(trigger),\n controlled: factsOf(controlsId ? document.getElementById(controlsId) : null),\n palette: factsOf(palette),\n toolbar: factsOf(toolbar),\n canvas: factsOf(find(\".djs-container > svg\")),\n entries: [...(palette?.querySelectorAll(\"[data-action]\") ?? [])].map((entry) => ({\n ...tools.facts(entry),\n group: entry.closest(\"[data-group]\")?.getAttribute(\"data-group\") ?? null,\n })),\n zoom: factsOf(zoom),\n zoomButtons,\n order: present.map(([name]) => name) as OrderedPart[],\n positiveTabindex: [...rootElement.querySelectorAll(\"[tabindex]\")]\n .filter((element) => Number(element.getAttribute(\"tabindex\")) > 0)\n .map((element) => `${tools.describe(element)} (tabindex=\"${element.getAttribute(\"tabindex\")}\")`),\n titled: [...rootElement.querySelectorAll(titledSelector)].map((element) => tools.describe(element)),\n problems: factsOf(find('[data-chrome=\"problems\"]')),\n status: factsOf(find('[data-chrome=\"status\"]')),\n legend: factsOf(legend),\n legendTitle: labelledBy\n ? labelledBy\n .split(/\\s+/)\n .map((id) => document.getElementById(id)?.textContent?.trim() ?? \"\")\n .join(\" \")\n .trim()\n : null,\n legendClose: factsOf(legend?.querySelector(\"button\")),\n inspector: factsOf(find('[data-chrome=\"inspector\"]')),\n };\n};\n\nexport interface MenuItemFacts {\n role: string;\n name: string;\n checked: string | null;\n disabled: string | null;\n haspopup: string | null;\n /** `aria-label` of the enclosing `role=\"group\"`; `null` outside a group. */\n group: string | null;\n}\n\nexport interface MenuFacts {\n /** The trigger's `aria-expanded` and `aria-controls`. */\n expanded: string | null;\n controls: string | null;\n /** The visible `role=\"menu\"` inside the root. */\n menu: ElementFacts | null;\n items: MenuItemFacts[];\n /** Index of the focused item; -1 when the focus is elsewhere. */\n active: number;\n activeIsTrigger: boolean;\n}\n\nexport const menuProbe = ({ root }: { root: string }): MenuFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return null;\n const trigger = rootElement.querySelector('[data-chrome=\"menu\"]');\n const menu =\n [...rootElement.querySelectorAll('[role=\"menu\"]')].find((element) => tools.visible(element)) ?? null;\n const items = menu\n ? [\n ...menu.querySelectorAll('[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]'),\n ].filter((item) => tools.visible(item))\n : [];\n return {\n expanded: trigger?.getAttribute(\"aria-expanded\") ?? null,\n controls: trigger?.getAttribute(\"aria-controls\") ?? null,\n menu: menu ? tools.facts(menu) : null,\n items: items.map((item) => {\n const group = item.closest('[role=\"group\"]');\n return {\n role: item.getAttribute(\"role\") ?? \"\",\n name: (item.getAttribute(\"aria-label\") ?? item.textContent ?? \"\").replace(/\\s+/g, \" \").trim(),\n checked: item.getAttribute(\"aria-checked\"),\n disabled: item.getAttribute(\"aria-disabled\"),\n haspopup: item.getAttribute(\"aria-haspopup\"),\n group: group && menu?.contains(group) ? (group.getAttribute(\"aria-label\") ?? \"\") : null,\n };\n }),\n active: items.findIndex((item) => item === document.activeElement),\n activeIsTrigger: Boolean(trigger) && document.activeElement === trigger,\n };\n};\n\nexport interface PaletteFocusFacts {\n /** `data-action` of every entry, in order. */\n entries: string[];\n /** Entries with `tabindex=\"0\"`. */\n tabStops: string[];\n /** `data-action` of the focused entry; `null` when the focus is elsewhere. */\n active: string | null;\n}\n\nexport const paletteFocusProbe = ({ root }: { root: string }): PaletteFocusFacts | null => {\n const palette = document.querySelector(root)?.querySelector('[data-chrome=\"palette\"]');\n if (!palette) return null;\n const entries = [...palette.querySelectorAll(\"[data-action]\")];\n const active = document.activeElement;\n return {\n entries: entries.map((entry) => entry.getAttribute(\"data-action\") ?? \"\"),\n tabStops: entries\n .filter((entry) => entry.getAttribute(\"tabindex\") === \"0\")\n .map((entry) => entry.getAttribute(\"data-action\") ?? \"\"),\n active: active && entries.includes(active) ? active.getAttribute(\"data-action\") : null,\n };\n};\n\nexport const zoomButtonsProbe = ({ root }: { root: string }): Partial<Record<ZoomButton, ElementFacts>> => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const zoom = document.querySelector(root)?.querySelector('[data-chrome=\"zoom\"]');\n const buttons: Partial<Record<ZoomButton, ElementFacts>> = {};\n for (const name of [\"out\", \"actual\", \"in\", \"fit\"] as const) {\n const button = zoom?.querySelector(`[data-zoom=\"${name}\"]`);\n if (button) buttons[name] = tools.facts(button);\n }\n return buttons;\n};\n\n/** The design-system roles whose resolved values must agree on every part (no half-dark). */\nexport const MODE_ROLES = [\"--cd-ui-grund\", \"--cd-ui-text\", \"--cd-ui-flaeche-hoch\", \"--cd-ui-linie\"] as const;\n\nexport interface ModeFacts {\n name: string;\n description: string;\n colorScheme: string;\n roles: Record<string, string>;\n}\n\nexport interface ThemedElementFacts {\n description: string;\n isDocument: boolean;\n /** Where it sits relative to the shell root. */\n relation: \"self\" | \"ancestor\" | \"descendant\" | \"elsewhere\";\n theme: string | null;\n kontrast: string | null;\n}\n\nexport interface AppearanceFacts {\n documentClasses: string[];\n /** Every element with `data-cd-theme` or `data-cd-kontrast`. */\n themed: ThemedElementFacts[];\n /** Root, canvas, every visible island, the open dropdown and the visible tooltip. */\n parts: ModeFacts[];\n}\n\nexport const appearanceProbe = ({\n root,\n roles,\n}: {\n root: string;\n roles: readonly string[];\n}): AppearanceFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return null;\n const mode = (name: string, element: Element) => {\n const style = getComputedStyle(element);\n const resolved: Record<string, string> = {};\n for (const role of roles) resolved[role] = style.getPropertyValue(role).trim();\n return { name, description: tools.describe(element), colorScheme: style.colorScheme, roles: resolved };\n };\n const parts = [mode(\"root\", rootElement)];\n const canvas = rootElement.querySelector(\".djs-container\");\n if (canvas) parts.push(mode(\"canvas\", canvas));\n for (const island of rootElement.querySelectorAll(\"[data-chrome]\")) {\n if (tools.visible(island)) parts.push(mode(island.getAttribute(\"data-chrome\") ?? \"island\", island));\n }\n for (const [name, role] of [\n [\"dropdown\", \"menu\"],\n [\"tooltip\", \"tooltip\"],\n ] as const) {\n const popup = [...rootElement.querySelectorAll(`[role=\"${role}\"]`)].find((element) =>\n tools.visible(element),\n );\n if (popup) parts.push(mode(name, popup));\n }\n return {\n documentClasses: [...document.documentElement.classList],\n themed: [...document.querySelectorAll(\"[data-cd-theme], [data-cd-kontrast]\")].map((element) => ({\n description: tools.describe(element),\n isDocument: element === document.documentElement,\n relation:\n element === rootElement\n ? \"self\"\n : element.contains(rootElement)\n ? \"ancestor\"\n : rootElement.contains(element)\n ? \"descendant\"\n : \"elsewhere\",\n theme: element.getAttribute(\"data-cd-theme\"),\n kontrast: element.getAttribute(\"data-cd-kontrast\"),\n })),\n parts,\n };\n};\n\n/** The element with the focus, classified for the tab-sequence check. */\nexport const activeStopProbe = ({ root }: { root: string }): { description: string; kind: string } => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const active = document.activeElement;\n const rootElement = document.querySelector(root);\n if (!active || active === document.body || !rootElement) return { description: \"<body>\", kind: \"other\" };\n const description = tools.describe(active);\n if (!rootElement.contains(active))\n return { description: `${description} outside the shell root`, kind: \"other\" };\n if (active.matches('[data-chrome=\"palette\"] [data-action]')) return { description, kind: \"palette\" };\n if (active.matches(\".djs-container > svg\")) return { description, kind: \"canvas\" };\n if (active.closest('[data-chrome=\"primary\"]')) return { description, kind: \"primary\" };\n const tabindex = active.getAttribute(\"tabindex\");\n return {\n description: tabindex === null ? description : `${description}[tabindex=\"${tabindex}\"]`,\n kind: \"other\",\n };\n};\n\n/** The focused palette entry, its `aria-keyshortcuts` and the chip of the visible tooltip. */\nexport const paletteShortcutProbe = ({\n root,\n}: {\n root: string;\n}): { action: string; chip: string; keyShortcuts: string | null } | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector(root);\n const active = document.activeElement;\n if (!rootElement || !active?.matches('[data-chrome=\"palette\"] [data-action]')) return null;\n const tooltip = [...rootElement.querySelectorAll('[role=\"tooltip\"]')].find((element) =>\n tools.visible(element),\n );\n const chip = tooltip\n ? [...tooltip.querySelectorAll(\"kbd\")].find((element) => tools.visible(element))\n : undefined;\n return {\n action: active.getAttribute(\"data-action\") ?? \"\",\n chip: (chip?.textContent ?? \"\").trim(),\n keyShortcuts: active.getAttribute(\"aria-keyshortcuts\"),\n };\n};\n\n/** The canvas surround (guide §10.1) and the role it must show. */\nexport interface SurroundFacts {\n /** Whether the root holds a `.djs-container`. */\n container: boolean;\n /** The first element from `.djs-container` out to the root that paints a background colour. */\n painted: { description: string; color: string } | null;\n /** `--cd-ui-grund` resolved to a computed colour inside the root. */\n grund: string;\n}\n\nexport const surroundProbe = ({ root }: { root: string }): SurroundFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return null;\n const transparent = (color: string): boolean => {\n if (color === \"\" || color === \"transparent\") return true;\n const legacy = /^rgba\\([^)]*,\\s*([\\d.]+)\\)$/.exec(color);\n if (legacy) return Number(legacy[1]) === 0;\n const modern = /\\/\\s*([\\d.]+)%?\\s*\\)$/.exec(color);\n return modern ? Number(modern[1]) === 0 : false;\n };\n const start = rootElement.querySelector(\".djs-container\");\n let painted: SurroundFacts[\"painted\"] = null;\n for (let node: Element | null = start; node && !painted; node = node.parentElement) {\n const color = getComputedStyle(node).backgroundColor;\n if (!transparent(color)) painted = { description: tools.describe(node), color };\n if (node === rootElement) break;\n }\n const probe = document.createElement(\"span\");\n probe.setAttribute(\"data-modeler-shell-conformance\", \"role-probe\");\n probe.style.cssText = \"position:absolute;visibility:hidden;background-color:var(--cd-ui-grund);\";\n rootElement.append(probe);\n const grund = getComputedStyle(probe).backgroundColor;\n probe.remove();\n return { container: start !== null, painted, grund };\n};\n\n/** One visible palette entry, as the keyboard walk and the read-only lock read it. */\nexport interface PaletteEntryState {\n action: string;\n /** `data-group` of the enclosing `.group`; `null` outside one. */\n group: string | null;\n pressed: boolean;\n disabled: boolean;\n /** Viewport coordinates of the centre, for `page.mouse`. */\n client: { x: number; y: number };\n}\n\nexport const paletteEntriesProbe = ({ root }: { root: string }): PaletteEntryState[] => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const palette = document.querySelector(root)?.querySelector('[data-chrome=\"palette\"]');\n if (!palette) return [];\n return [...palette.querySelectorAll(\"[data-action]\")]\n .filter((entry) => tools.visible(entry))\n .map((entry) => {\n const rect = entry.getBoundingClientRect();\n return {\n action: entry.getAttribute(\"data-action\") ?? \"\",\n group: entry.closest(\"[data-group]\")?.getAttribute(\"data-group\") ?? null,\n pressed: entry.getAttribute(\"aria-pressed\") === \"true\",\n disabled: entry.getAttribute(\"aria-disabled\") === \"true\",\n client: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },\n };\n });\n};\n\n/** The computed colours of one visible palette entry and of its icon. */\nexport interface PaletteColorEntry extends Omit<PaletteEntryState, \"client\"> {\n hovered: boolean;\n color: string;\n /** The entry's `<svg>`, else its `::before` when that has content; `null` for an image or a text entry. */\n icon: { kind: \"svg\" | \"::before\"; color: string } | null;\n}\n\nexport interface PaletteColorFacts {\n /** The roles of guide §5.5 and §13.5, resolved to computed colours inside the palette. */\n roles: { text: string; interaktion: string; textLeise: string };\n entries: PaletteColorEntry[];\n}\n\nexport const paletteColorProbe = ({ root }: { root: string }): PaletteColorFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const palette = document.querySelector(root)?.querySelector('[data-chrome=\"palette\"]');\n if (!palette) return null;\n const resolve = (role: string): string => {\n const probe = document.createElement(\"span\");\n probe.setAttribute(\"data-modeler-shell-conformance\", \"role-probe\");\n probe.style.cssText = `position:absolute;visibility:hidden;color:var(${role});`;\n palette.append(probe);\n const color = getComputedStyle(probe).color;\n probe.remove();\n return color;\n };\n const iconOf = (entry: Element): PaletteColorEntry[\"icon\"] => {\n const svg = entry.querySelector(\"svg\");\n if (svg) return { kind: \"svg\", color: getComputedStyle(svg).color };\n const before = getComputedStyle(entry, \"::before\");\n if (before.content && before.content !== \"none\" && before.content !== \"normal\") {\n return { kind: \"::before\", color: before.color };\n }\n return null;\n };\n return {\n roles: {\n text: resolve(\"--cd-ui-text\"),\n interaktion: resolve(\"--cd-ui-interaktion\"),\n textLeise: resolve(\"--cd-ui-text-leise\"),\n },\n entries: [...palette.querySelectorAll(\"[data-action]\")]\n .filter((entry) => tools.visible(entry))\n .map((entry) => ({\n action: entry.getAttribute(\"data-action\") ?? \"\",\n group: entry.closest(\"[data-group]\")?.getAttribute(\"data-group\") ?? null,\n pressed: entry.getAttribute(\"aria-pressed\") === \"true\",\n disabled: entry.getAttribute(\"aria-disabled\") === \"true\",\n hovered: entry.matches(\":hover\"),\n color: getComputedStyle(entry).color,\n icon: iconOf(entry),\n })),\n };\n};\n\n/** One diagram-js shape on the canvas (`.djs-shape[data-element-id]`). */\nexport interface ShapeFacts {\n id: string;\n /** diagram-js's selection marker on the shape's `<g>`. */\n selected: boolean;\n /** The `<g>`'s `transform` (its position in the diagram, unaffected by panning). */\n transform: string;\n /** Size of its `.djs-visual` in diagram units. */\n size: { width: number; height: number };\n /** Its `.djs-visual` relative to the root's padding box. */\n box: RelativeBox;\n /** Viewport coordinates of the centre, for `page.mouse`. */\n client: { x: number; y: number };\n /** Whether a pointer at the centre reaches the shape and not chrome above it. */\n hit: boolean;\n}\n\nexport const shapesProbe = ({ root }: { root: string }): ShapeFacts[] => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector<HTMLElement>(root);\n if (!rootElement) return [];\n return [...rootElement.querySelectorAll<SVGGraphicsElement>(\".djs-container .djs-shape[data-element-id]\")]\n .filter((shape) => tools.visible(shape))\n .map((shape) => {\n const visual = shape.querySelector<SVGGraphicsElement>(\".djs-visual\") ?? shape;\n const rect = visual.getBoundingClientRect();\n const client = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };\n const local = typeof visual.getBBox === \"function\" ? visual.getBBox() : rect;\n const hitElement = document.elementFromPoint(client.x, client.y);\n return {\n id: shape.getAttribute(\"data-element-id\") ?? \"\",\n selected: shape.classList.contains(\"selected\"),\n transform: shape.getAttribute(\"transform\") ?? \"\",\n size: { width: local.width, height: local.height },\n box: tools.box(visual, rootElement),\n client,\n hit: hitElement !== null && shape.contains(hitElement),\n };\n });\n};\n\n/** What the canvas offers at the moment: focus, context pad, open text fields. */\nexport interface CanvasStateFacts {\n /** The focus is inside `.djs-container` (the `<svg>` or a label editor). */\n focusInCanvas: boolean;\n focused: string;\n /** Visible entries of a diagram-js context pad. */\n contextPadEntries: string[];\n /** Visible text fields inside `.djs-container` (a label editor), the kit's stand-ins aside. */\n textFields: string[];\n}\n\nexport const canvasStateProbe = ({ root }: { root: string }): CanvasStateFacts => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const container = document.querySelector(root)?.querySelector(\".djs-container\");\n const active = document.activeElement;\n const ours = (element: Element) => element.closest(\"[data-modeler-shell-conformance]\") !== null;\n const visibleIn = (selector: string) =>\n container\n ? [...container.querySelectorAll(selector)].filter(\n (element) => !ours(element) && tools.visible(element),\n )\n : [];\n return {\n focusInCanvas: Boolean(container && active && container.contains(active)),\n focused: !active || active === document.body ? \"<body>\" : tools.describe(active),\n contextPadEntries: visibleIn(\".djs-context-pad .entry\").map(\n (entry) => entry.getAttribute(\"data-action\") ?? tools.describe(entry),\n ),\n textFields: visibleIn('input, textarea, [contenteditable]:not([contenteditable=\"false\"])').map((field) =>\n tools.describe(field),\n ),\n };\n};\n\n/** The read-only marks of the root and the status box (guide §5.12, §13.5). */\nexport interface ReadOnlyStateFacts {\n readOnly: boolean;\n status: ElementFacts | null;\n}\n\nexport const readOnlyStateProbe = ({ root }: { root: string }): ReadOnlyStateFacts | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector(root);\n if (!rootElement) return null;\n const status = rootElement.querySelector('[data-chrome=\"status\"]');\n return { readOnly: rootElement.hasAttribute(\"data-readonly\"), status: status ? tools.facts(status) : null };\n};\n\n/** One item of the open menu with the group it stands in, counted by the separators. */\nexport interface MenuEntryFacts {\n name: string;\n role: string;\n /** `data-menu-id` of the item or its radio group. */\n menuId: string | null;\n disabled: boolean;\n /** `data-menu-group` of the item or its radio group: the shell's `model`, `export` or `help`. */\n group: string | null;\n}\n\nexport const menuEntriesProbe = ({ root }: { root: string }): MenuEntryFacts[] | null => {\n const tools = (window as ToolWindow).__modelerShellConformance!;\n const rootElement = document.querySelector(root);\n const menu = rootElement\n ? [...rootElement.querySelectorAll('[role=\"menu\"]')].find((element) => tools.visible(element))\n : undefined;\n if (!menu) return null;\n const entries: MenuEntryFacts[] = [];\n const selector = '[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]';\n for (const element of menu.querySelectorAll(selector)) {\n const role = element.getAttribute(\"role\") ?? \"\";\n if (!tools.visible(element)) continue;\n entries.push({\n name: (element.getAttribute(\"aria-label\") ?? element.textContent ?? \"\").replace(/\\s+/g, \" \").trim(),\n role,\n menuId: element.closest(\"[data-menu-id]\")?.getAttribute(\"data-menu-id\") ?? null,\n disabled: element.getAttribute(\"aria-disabled\") === \"true\",\n group: element.closest(\"[data-menu-group]\")?.getAttribute(\"data-menu-group\") ?? null,\n });\n }\n return entries;\n};\n","import { INVALID_STATUS_DELAY_MS, type Appearance, type ShellHost, type Theme } from \"../core/index.js\";\nimport {\n DOM_ORDER,\n type AppearanceFacts,\n type AriaFacts,\n type CanvasStateFacts,\n type MenuEntryFacts,\n type MenuFacts,\n type PaletteColorEntry,\n type PaletteColorFacts,\n type PaletteEntryState,\n type ReadOnlyStateFacts,\n type ShapeFacts,\n type SurroundFacts,\n type ZoomButton,\n} from \"./facts.js\";\nimport { GEOMETRY_TOLERANCE_PX, type Rectangle } from \"./geometry.js\";\nimport type { ShellConformanceHarness, ShowHook } from \"./harness.js\";\nimport type { ElementFacts, LeftoverFacts, RecordedKey } from \"./page-tools.js\";\nimport type { PageLike } from \"./page.js\";\n\n/*\n * The judgements of the cases, as pure functions of what the probes saw. Each returns readable\n * problems (empty = conforming), so a case can report all of them at once.\n */\n\nconst normalize = (text: string): string => text.replace(/\\s+/g, \" \").trim();\n\nconst name = (element: ElementFacts): string => normalize(element.attributes[\"aria-label\"] ?? element.text);\n\nconst attribute = (element: ElementFacts, key: string): string | undefined => element.attributes[key];\n\n/** `aria-keyshortcuts` of the zoom panel (guide §5.6, WAI-ARIA key names). */\nexport function expectedKeyShortcuts(platform: \"mac\" | \"other\"): Record<ZoomButton, string> {\n const modifier = platform === \"mac\" ? \"Meta\" : \"Control\";\n return {\n in: `${modifier}+= ${modifier}+Plus`,\n out: `${modifier}+-`,\n actual: `${modifier}+0`,\n fit: \"Shift+1\",\n };\n}\n\n/** Roles, names, states, DOM order and tab stops of guide §5.4 to §5.14 and §12. */\nexport function ariaProblems(facts: AriaFacts, host: ShellHost): string[] {\n const problems: string[] = [];\n\n if (host === \"embedded\") {\n if (!facts.rootLang)\n problems.push(\"root: an embedded shell root carries the tool's lang itself (guide §2, §12)\");\n } else if (!facts.documentLang) {\n problems.push(\"<html> has no lang (guide §2)\");\n }\n\n const trigger = facts.trigger;\n if (!trigger) {\n problems.push('menu: no [data-chrome=\"menu\"] trigger');\n } else {\n if (trigger.tag !== \"button\")\n problems.push(`menu: the trigger is a <${trigger.tag}>, expected a <button>`);\n if (!attribute(trigger, \"aria-label\")) problems.push(\"menu: the icon-only trigger has no aria-label\");\n if (attribute(trigger, \"aria-haspopup\") !== \"menu\") {\n problems.push(`menu: aria-haspopup is \"${attribute(trigger, \"aria-haspopup\") ?? \"\"}\", expected \"menu\"`);\n }\n if (attribute(trigger, \"aria-expanded\") !== \"false\") {\n problems.push(\n `menu: aria-expanded is \"${attribute(trigger, \"aria-expanded\") ?? \"\"}\" while closed, expected \"false\"`,\n );\n }\n if (!attribute(trigger, \"aria-controls\")) {\n problems.push(\"menu: the trigger has no aria-controls\");\n } else if (!facts.controlled) {\n problems.push(`menu: aria-controls=\"${attribute(trigger, \"aria-controls\")}\" names no element`);\n } else if (attribute(facts.controlled, \"role\") !== \"menu\") {\n problems.push(\n `menu: aria-controls names a ${facts.controlled.description} with role \"${attribute(facts.controlled, \"role\") ?? \"\"}\", expected \"menu\"`,\n );\n }\n }\n\n if (!facts.palette) {\n problems.push('palette: no [data-chrome=\"palette\"]');\n } else {\n const toolbar = facts.toolbar;\n if (!toolbar || attribute(toolbar, \"role\") !== \"toolbar\") {\n problems.push('palette: .djs-palette-entries has no role=\"toolbar\"');\n } else if (!attribute(toolbar, \"aria-label\")) {\n problems.push(\"palette: the toolbar has no aria-label\");\n }\n for (const entry of facts.entries) {\n const action = attribute(entry, \"data-action\") ?? entry.description;\n if (attribute(entry, \"role\") !== \"button\")\n problems.push(`palette: entry \"${action}\" has no role=\"button\"`);\n if (!attribute(entry, \"aria-label\"))\n problems.push(`palette: entry \"${action}\" has no aria-label (title)`);\n const tabindex = attribute(entry, \"tabindex\");\n if (tabindex !== \"0\" && tabindex !== \"-1\") {\n problems.push(`palette: entry \"${action}\" has tabindex \"${tabindex ?? \"\"}\", expected roving 0/-1`);\n }\n }\n const stops = facts.entries.filter((entry) => attribute(entry, \"tabindex\") === \"0\");\n if (facts.entries.length > 0 && stops.length !== 1) {\n problems.push(\n `palette: ${stops.length} entries with tabindex=\"0\", expected exactly one (roving tabindex)`,\n );\n }\n const tools = facts.entries.filter(\n (entry) => entry.group === \"tools\" && (attribute(entry, \"data-action\") ?? \"\").endsWith(\"-tool\"),\n );\n for (const tool of tools) {\n const pressed = attribute(tool, \"aria-pressed\");\n if (pressed !== \"true\" && pressed !== \"false\") {\n problems.push(`palette: tool \"${attribute(tool, \"data-action\")}\" has no aria-pressed`);\n }\n }\n const pressed = tools.filter((tool) => attribute(tool, \"aria-pressed\") === \"true\");\n if (pressed.length > 1) problems.push(`palette: ${pressed.length} tools are aria-pressed at once`);\n }\n\n const zoom = facts.zoom;\n if (!zoom) {\n problems.push('zoom: no [data-chrome=\"zoom\"]');\n } else {\n if (attribute(zoom, \"role\") !== \"group\") problems.push('zoom: the panel has no role=\"group\"');\n if (!attribute(zoom, \"aria-label\")) problems.push(\"zoom: the panel has no aria-label\");\n const shortcuts = expectedKeyShortcuts(facts.platform);\n for (const button of [\"out\", \"actual\", \"in\", \"fit\"] as const) {\n const control = facts.zoomButtons[button];\n if (!control) {\n problems.push(`zoom: no [data-zoom=\"${button}\"] button`);\n continue;\n }\n if (control.tag !== \"button\") problems.push(`zoom: [data-zoom=\"${button}\"] is a <${control.tag}>`);\n if (!name(control)) problems.push(`zoom: [data-zoom=\"${button}\"] has no accessible name`);\n if (attribute(control, \"aria-keyshortcuts\") !== shortcuts[button]) {\n problems.push(\n `zoom: [data-zoom=\"${button}\"] aria-keyshortcuts is \"${attribute(control, \"aria-keyshortcuts\") ?? \"\"}\", expected \"${shortcuts[button]}\" (${facts.platform})`,\n );\n }\n if (control.disabled) {\n problems.push(\n `zoom: [data-zoom=\"${button}\"] is natively disabled; aria-disabled keeps the focus (guide §5.8)`,\n );\n }\n }\n const readout = facts.zoomButtons.actual;\n if (readout) {\n if (!/\\d/.test(readout.text))\n problems.push(`zoom: the readout shows \"${readout.text}\", expected a percentage`);\n const label = normalize(attribute(readout, \"aria-label\") ?? \"\");\n if (!label.includes(readout.text)) {\n problems.push(\n `zoom: the readout's aria-label \"${label}\" does not name the current zoom \"${readout.text}\"`,\n );\n }\n if (attribute(readout, \"aria-disabled\") === \"true\")\n problems.push(\"zoom: the readout is never disabled\");\n }\n }\n\n const present = new Set(facts.order);\n const expectedOrder = DOM_ORDER.filter((part) => present.has(part));\n if (facts.order.join() !== expectedOrder.join()) {\n problems.push(\n `DOM order is ${facts.order.join(\", \")}; expected ${expectedOrder.join(\", \")} (guide §5.14)`,\n );\n }\n if (!present.has(\"canvas\")) problems.push(\"canvas: no diagram-js <svg> (.djs-container > svg) in the root\");\n const canvas = facts.canvas;\n if (canvas && !normalize(attribute(canvas, \"aria-label\") ?? \"\") && !attribute(canvas, \"aria-labelledby\")) {\n problems.push(\n 'canvas: the focusable <svg> has no accessible name (WCAG 4.1.2); shellModule names it role=\"application\" with messages.canvas',\n );\n }\n for (const element of facts.positiveTabindex)\n problems.push(`positive tabindex on ${element} (guide §5.14)`);\n for (const element of facts.titled) {\n problems.push(`${element} has a native title; the chrome tooltip replaces it (guide §5.6)`);\n }\n return problems;\n}\n\n/** The optional islands once the harness showed them. */\nexport function optionalIslandProblems(facts: AriaFacts, shown: ReadonlySet<string>): string[] {\n const problems: string[] = [];\n if (shown.has(\"problems\")) {\n const pill = facts.problems;\n if (!pill?.visible) {\n problems.push(\"problems: the pill is not visible after show.problems\");\n } else {\n if (pill.tag !== \"button\") problems.push(`problems: the pill is a <${pill.tag}>, expected a <button>`);\n const label = normalize(attribute(pill, \"aria-label\") ?? \"\");\n if (!label) problems.push(\"problems: the pill has no aria-label (count and errors)\");\n else if (!label.includes(pill.text)) {\n problems.push(`problems: the aria-label \"${label}\" does not contain the visible text \"${pill.text}\"`);\n }\n }\n }\n if (shown.has(\"status\")) {\n const status = facts.status;\n if (!status?.visible) {\n problems.push(\"status: the status box is not visible after show.status\");\n } else {\n const role = attribute(status, \"role\");\n const severity = attribute(status, \"data-severity\");\n const expected = severity === \"danger\" ? \"alert\" : \"status\";\n if (role !== expected) {\n problems.push(\n `status: role is \"${role ?? \"\"}\" for data-severity=\"${severity ?? \"\"}\", expected \"${expected}\"`,\n );\n }\n }\n }\n if (shown.has(\"legend\")) {\n const legend = facts.legend;\n if (!legend?.visible) {\n problems.push(\"legend: the legend is not visible after show.legend\");\n } else {\n if (!facts.legendTitle)\n problems.push(\"legend: the card is not labelled by its title (aria-labelledby)\");\n if (!facts.legendClose || !attribute(facts.legendClose, \"aria-label\")) {\n problems.push(\"legend: the close button has no aria-label\");\n }\n }\n }\n if (shown.has(\"inspector\")) {\n const inspector = facts.inspector;\n if (!inspector?.visible) {\n problems.push(\"inspector: the inspector is not visible after show.inspector\");\n } else {\n if (inspector.tag !== \"aside\") problems.push(`inspector: a <${inspector.tag}>, expected an <aside>`);\n if (!attribute(inspector, \"aria-label\")) problems.push(\"inspector: the <aside> has no aria-label\");\n }\n }\n return problems;\n}\n\n/** One Tab stop as the kit's tab-sequence probe saw it. */\nexport interface TabStop {\n description: string;\n /** What the stop is: the palette's roving entry, the canvas `<svg>`, the web app's primary action. */\n kind: \"palette\" | \"canvas\" | \"primary\" | \"other\";\n}\n\n/**\n * Tab from the menu trigger (guide §5.14): the primary action (web app), the palette's one tab\n * stop, then the canvas `<svg>`; nothing else in between (a renderer's own `tabindex` on\n * `.djs-container` would be an extra, unnamed stop).\n */\nexport function tabSequenceProblems(stops: readonly TabStop[]): string[] {\n const [first, second, third] = stops;\n const sequence = first?.kind === \"primary\" ? [second, third] : [first, second];\n const [palette, canvas] = sequence;\n const problems: string[] = [];\n if (palette?.kind !== \"palette\") {\n problems.push(\n `tab order: Tab from the menu trigger lands on ${palette?.description ?? \"nothing\"}, expected the palette's roving entry (guide §5.14)`,\n );\n } else if (canvas?.kind !== \"canvas\") {\n problems.push(\n `tab order: Tab from the palette lands on ${canvas?.description ?? \"nothing\"}, expected the canvas <svg> (an unexpected tab stop, guide §5.14)`,\n );\n }\n return problems;\n}\n\n/** A palette entry with the keyboard focus: its tooltip's chip and what it names for assistive technology. */\nexport interface PaletteShortcutFacts {\n action: string;\n /** Text of the visible tooltip's `kbd` chip; empty without a chip. */\n chip: string;\n keyShortcuts: string | null;\n}\n\n/** Guide §5.6: an entry whose tooltip shows a shortcut carries `aria-keyshortcuts`. */\nexport function paletteShortcutProblems(entries: readonly PaletteShortcutFacts[]): string[] {\n return entries\n .filter((entry) => entry.chip && !entry.keyShortcuts)\n .map(\n (entry) =>\n `palette: entry \"${entry.action}\" shows the shortcut \"${entry.chip}\" in its tooltip but has no aria-keyshortcuts (guide §5.6)`,\n );\n}\n\n/**\n * The keys an open menu consumes (↑ ↓ Home End, a letter) never reach a `keydown` listener on\n * `document`: a modeler's document keyboard would act on them (Event Storming moves the selection\n * on ↑/↓).\n */\nexport function menuKeysAtDocumentProblems(\n pressed: readonly string[],\n documentKeys: readonly RecordedKey[],\n): string[] {\n const reached = new Set(documentKeys.map((key) => key.key));\n return pressed\n .filter((key) => reached.has(key))\n .map(\n (key) =>\n `menu: ${key} in the open menu reached a keydown listener on document; a modeler's document keyboard acts on it (stop it at the menu, guide §5.4)`,\n );\n}\n\n/** An open menu (guide §5.4): expanded trigger, labelled `role=\"menu\"`, named items, focus. */\nexport function menuOpenProblems(facts: MenuFacts, focus?: \"first\" | \"last\"): string[] {\n const problems: string[] = [];\n if (facts.expanded !== \"true\") {\n problems.push(`menu: aria-expanded is \"${facts.expanded ?? \"\"}\" while open, expected \"true\"`);\n }\n const menu = facts.menu;\n if (!menu) return [...problems, 'menu: no visible role=\"menu\" after opening'];\n if (!attribute(menu, \"aria-label\")) problems.push(\"menu: the dropdown has no aria-label\");\n if (facts.controls && attribute(menu, \"id\") !== facts.controls) {\n problems.push(\n `menu: the visible dropdown is #${attribute(menu, \"id\") ?? \"\"}, the trigger controls #${facts.controls}`,\n );\n }\n if (facts.items.length === 0) problems.push(\"menu: the dropdown has no menuitem\");\n facts.items.forEach((item, index) => {\n const label = item.name || `item ${index + 1}`;\n if (!item.name) problems.push(`menu: ${label} has no accessible name`);\n if (item.role !== \"menuitem\" && item.checked !== \"true\" && item.checked !== \"false\") {\n problems.push(`menu: \"${label}\" (${item.role}) has aria-checked \"${item.checked ?? \"\"}\"`);\n }\n if (item.role === \"menuitemradio\" && !item.group) {\n problems.push(`menu: radio \"${label}\" is not in a labelled role=\"group\"`);\n }\n if (item.haspopup === \"dialog\" && !item.name.endsWith(\"…\")) {\n problems.push(`menu: \"${label}\" opens a dialog, so its label ends with \"…\" (U+2026)`);\n }\n });\n if (focus && facts.items.length > 0) {\n const expected = focus === \"first\" ? 0 : facts.items.length - 1;\n if (facts.active !== expected) {\n problems.push(\n `menu: focus is on ${facts.active < 0 ? \"no entry\" : `entry ${facts.active + 1}`}, expected the ${focus} entry`,\n );\n }\n }\n return problems;\n}\n\nexport function menuClosedProblems(facts: MenuFacts, focusOnTrigger: boolean): string[] {\n const problems: string[] = [];\n if (facts.expanded !== \"false\")\n problems.push(`menu: aria-expanded is \"${facts.expanded ?? \"\"}\" after closing`);\n if (facts.menu) problems.push(\"menu: the dropdown is still visible after Escape\");\n if (focusOnTrigger && !facts.activeIsTrigger)\n problems.push(\"menu: Escape did not return the focus to the trigger\");\n return problems;\n}\n\n/**\n * How a key press must arrive at a `keydown` listener on `window` (guide §5.8, §13.5):\n * - `handled`: the shell executes it; IDE: stopped, else it arrives prevented;\n * - `blocked`: recognized but not executed (text field, modal, Escape with a dialog); IDE: stopped,\n * else it arrives unprevented (the browser, the field or the dialog acts);\n * - `canvas`: the canvas handled it (`defaultPrevented`); IDE: stopped, else it arrives prevented;\n * - `free`: nobody may handle it; it arrives unprevented in every host.\n * In the IDE host a stopped key never reaches `window`, so `prevented` is read on `document`.\n */\nexport type KeyReach = \"handled\" | \"blocked\" | \"canvas\" | \"free\";\n\nexport interface SeenKeys {\n /** What a listener on `window` saw. */\n keys: readonly RecordedKey[];\n /** What a listener on `document`, registered after the shell's, saw. */\n documentKeys?: readonly RecordedKey[];\n}\n\nexport function keyReachProblem(\n press: string,\n reach: KeyReach,\n host: ShellHost,\n seen: SeenKeys,\n): string | undefined {\n const shouldPrevent = reach === \"handled\" || reach === \"canvas\";\n if (host === \"ide\" && reach !== \"free\") {\n if (seen.keys.length > 0) {\n return `${press} reached a keydown listener on window; in the IDE host the shell stops it on document, or VS Code runs it again (guide §13.5)`;\n }\n const atDocument = seen.documentKeys ?? [];\n const prevented = atDocument.length === 1 ? atDocument[0]?.defaultPrevented : undefined;\n if (prevented === true && !shouldPrevent) {\n return `${press} was prevented; the shell only stops it, so the field, dialog or browser still acts (guide §13.5)`;\n }\n if (prevented === false && shouldPrevent) {\n return `${press} was stopped but not prevented; a handled key also calls preventDefault`;\n }\n return undefined;\n }\n if (seen.keys.length === 0) {\n return host === \"ide\"\n ? `${press} never reached window; keys the webview does not handle must go on to VS Code (guide §13.5)`\n : `${press} never reached window; outside the IDE host the shell never stops propagation`;\n }\n if (seen.keys.length > 1) return `${press} reached window ${seen.keys.length} times`;\n const prevented = seen.keys[0]?.defaultPrevented ?? false;\n if (prevented && !shouldPrevent) {\n return `${press} arrived prevented; ${reach === \"free\" ? \"nothing may handle it\" : \"the browser, the field or the dialog must act\"}`;\n }\n if (!prevented && shouldPrevent) {\n return `${press} arrived unprevented; a handled key calls preventDefault (the browser would zoom the page)`;\n }\n return undefined;\n}\n\n/** The decision of guide §13.5, computed independently of the shell under test. */\nexport function expectedAppearance(requested: Appearance, themes: readonly Theme[]): Appearance {\n const fallback = themes[0];\n if (fallback === undefined) throw new Error(\"@miragon/modeler-shell conformance: harness.themes is empty\");\n const theme = themes.includes(requested.theme) ? requested.theme : fallback;\n return requested.kontrast ? { theme, kontrast: requested.kontrast } : { theme };\n}\n\nconst describeAppearance = (appearance: Appearance): string =>\n appearance.kontrast ? `${appearance.theme} + ${appearance.kontrast}` : appearance.theme;\n\nexport interface AppearanceVerdict {\n problems: string[];\n}\n\n/**\n * What an embedded root must show (guide §13.3): until the contract's `appearance` surface there\n * is no channel to ask it for a mode, so it stays in its first one whatever the page shows, and\n * takes the page's high contrast over from the nearest mode carrier above it.\n */\nexport function expectedEmbeddedAppearance(facts: AppearanceFacts, themes: readonly Theme[]): Appearance {\n const fallback = themes[0];\n if (fallback === undefined) throw new Error(\"@miragon/modeler-shell conformance: harness.themes is empty\");\n const host = facts.themed.filter((element) => element.relation === \"ancestor\").at(-1);\n return host?.kontrast === \"hoch\" ? { theme: fallback, kontrast: \"hoch\" } : { theme: fallback };\n}\n\n/** No half-dark (guide §13.3, §13.5): one mode on `<html>` (own document) or the root (embedded). */\nexport function appearanceProblems(\n facts: AppearanceFacts,\n host: ShellHost,\n requested: Appearance,\n themes: readonly Theme[],\n): AppearanceVerdict {\n const ownDocument = host !== \"embedded\";\n const expected = ownDocument\n ? expectedAppearance(requested, themes)\n : expectedEmbeddedAppearance(facts, themes);\n const problems: string[] = [];\n const label = ownDocument\n ? `requested ${describeAppearance(requested)}, expected ${describeAppearance(expected)}`\n : `host page ${describeAppearance(requested)}, expected ${describeAppearance(expected)}`;\n\n const carrier = ownDocument\n ? facts.themed.find((element) => element.isDocument && element.theme !== null)\n : facts.themed.find((element) => element.relation === \"self\" && element.theme !== null);\n if (!carrier) {\n problems.push(\n ownDocument\n ? `<html> has no data-cd-theme (${label}); the host always writes it, also \"light\" (guide §13.3)`\n : `the embedded root has no data-cd-theme (${label}): it takes the host page's mode instead of its own (guide §13.3)`,\n );\n } else {\n if (carrier.theme !== expected.theme) {\n problems.push(`${carrier.description} has data-cd-theme=\"${carrier.theme}\" (${label})`);\n }\n if ((carrier.kontrast ?? undefined) !== expected.kontrast) {\n problems.push(\n `${carrier.description} has ${carrier.kontrast ? `data-cd-kontrast=\"${carrier.kontrast}\"` : \"no data-cd-kontrast\"} (${label})`,\n );\n }\n }\n for (const element of facts.themed) {\n if (element === carrier) continue;\n const stray = ownDocument\n ? !element.isDocument || element.theme === null\n : element.relation === \"descendant\" || element.relation === \"self\";\n if (!stray) continue;\n const values = [\n element.theme !== null ? `data-cd-theme=\"${element.theme}\"` : \"\",\n element.kontrast !== null ? `data-cd-kontrast=\"${element.kontrast}\"` : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n const sameMode =\n carrier !== undefined && element.theme === carrier.theme && element.kontrast === carrier.kontrast;\n problems.push(\n element.theme === null\n ? `${element.description} carries ${values} without data-cd-theme on the same element (guide §13.3)`\n : sameMode\n ? `${element.description} repeats ${values}: in an own document the attributes stand only on <html> (guide §13.5)`\n : `${element.description} carries ${values}: a second mode inside the modeler is half-dark (guide §13.5)`,\n );\n }\n\n if (ownDocument && !facts.documentClasses.includes(\"cd-shell-document\")) {\n problems.push(\n \"<html> lacks cd-shell-document in an own document (the reset of the webview's host styles)\",\n );\n }\n if (!ownDocument && facts.documentClasses.includes(\"cd-shell-document\")) {\n problems.push(\n \"<html> of a foreign page carries cd-shell-document: the own-document reset restyles the host page\",\n );\n }\n\n const reference = facts.parts[0];\n if (reference && !reference.roles[\"--cd-ui-text\"]) {\n problems.push(\n \"--cd-ui-text is empty at the shell root: the vendored cd-tokens.generated.css is not loaded\",\n );\n }\n for (const part of facts.parts) {\n const schemes = part.colorScheme.split(/\\s+/);\n const dark = schemes.includes(\"dark\");\n const light = schemes.includes(\"light\");\n if (expected.theme === \"light\" && (dark || (carrier && !light))) {\n problems.push(`${part.name}: color-scheme is \"${part.colorScheme}\" (${label})`);\n }\n if (expected.theme === \"dark\" && (!dark || light)) {\n problems.push(`${part.name}: color-scheme is \"${part.colorScheme}\" (${label})`);\n }\n if (reference && part !== reference) {\n for (const [role, value] of Object.entries(part.roles)) {\n if (value !== reference.roles[role]) {\n problems.push(\n `${part.name}: ${role} resolves to \"${value}\", the root to \"${reference.roles[role] ?? \"\"}\" (half-dark)`,\n );\n }\n }\n }\n }\n for (const required of [\"dropdown\", \"tooltip\"]) {\n if (!facts.parts.some((part) => part.name === required)) {\n problems.push(`${required}: not visible when the kit opened it, so its mode was not checked`);\n }\n }\n return { problems };\n}\n\n/** The root attributes the shell writes (API.md, DOM). */\nconst SHELL_ROOT_ATTRIBUTES = [\n \"data-cd-shell-host\",\n \"data-palette\",\n \"data-legend\",\n \"data-inspector\",\n \"data-problems\",\n \"data-readonly\",\n];\n\n/** What an embedded root carries on top (its own mode). */\nconst EMBEDDED_ROOT_ATTRIBUTES = [\"data-cd-theme\", \"data-cd-kontrast\"];\n\n/** Messages of benign browser reports that are no shell error. */\nconst BENIGN_ERRORS = /ResizeObserver loop/;\n\n/** Nothing of the shell remains after `destroy` (API.md, `destroy()`). */\nexport function leftoverProblems(facts: LeftoverFacts, host: ShellHost): string[] {\n const problems: string[] = [];\n for (const element of facts.classedElements) problems.push(`${element} is left after destroy`);\n const ownDocument = host !== \"embedded\";\n for (const name of facts.documentClasses) {\n if (ownDocument && name === \"cd-shell-document\") continue;\n problems.push(`<html> keeps the class ${name} after destroy`);\n }\n for (const element of facts.chromeElements) problems.push(`${element} is left after destroy`);\n for (const name of facts.rootClasses) problems.push(`the root keeps the class ${name} after destroy`);\n const written = ownDocument\n ? SHELL_ROOT_ATTRIBUTES\n : [...SHELL_ROOT_ATTRIBUTES, ...EMBEDDED_ROOT_ATTRIBUTES];\n for (const name of facts.rootAttributes) {\n if (written.includes(name)) problems.push(`the root keeps ${name} after destroy`);\n }\n for (const error of facts.errors) {\n if (!BENIGN_ERRORS.test(error)) problems.push(`the page reported an error after destroy: ${error}`);\n }\n return problems;\n}\n\n/** After `destroy` no listener of the shell may act on a chrome key any more. */\nexport function afterDestroyKeyProblem(press: string, recorded: readonly RecordedKey[]): string | undefined {\n if (recorded.length === 0)\n return `${press} after destroy never reached window: a shell listener still stops it`;\n if (recorded.some((key) => key.defaultPrevented)) {\n return `${press} after destroy arrived prevented: a shell listener is still installed`;\n }\n return undefined;\n}\n\n/** The islands a harness may list as `absent`, as far as `geometry` and `aria` see them. */\nexport type AbsentIsland = Extract<ShowHook, \"legend\" | \"inspector\" | \"problems\" | \"status\">;\n\nconst ABSENT_ISLANDS: readonly AbsentIsland[] = [\"legend\", \"inspector\", \"problems\", \"status\"];\n\n/** The islands of `absent` (its state `invalid` has no island). */\nexport function absentIslands(absent: readonly ShowHook[] | undefined): AbsentIsland[] {\n return ABSENT_ISLANDS.filter((island) => absent?.includes(island));\n}\n\n/** An island the harness declares absent must never show. */\nexport function absentIslandProblems(\n visible: ReadonlySet<string>,\n absent: readonly ShowHook[] | undefined,\n): string[] {\n return absentIslands(absent)\n .filter((island) => visible.has(island))\n .map((island) => `${island}: visible, but harness.absent says the modeler has no ${island}`);\n}\n\n/** A hook the harness both gives and lists as absent is a contradiction in the harness itself. */\nexport function harnessHookProblems<P extends PageLike>(\n harness: ShellConformanceHarness<P>,\n hooks: readonly ShowHook[],\n): string[] {\n return hooks\n .filter((hook) => harness.absent?.includes(hook) && harness.show?.[hook])\n .map((hook) => `harness: absent lists \"${hook}\", but show.${hook} is given`);\n}\n\n/** Guide §10.1: the surround of the canvas is a container painted in `--cd-ui-grund`, in both modes. */\nexport function surroundProblems(facts: SurroundFacts): string[] {\n if (!facts.container) return [\"canvas surround: no .djs-container in the root to check\"];\n if (!facts.painted) {\n return [\n \"canvas surround: nothing from .djs-container out to the root paints a background colour; the surround is var(--cd-ui-grund) (guide §10.1)\",\n ];\n }\n if (facts.painted.color === facts.grund) return [];\n return [\n `canvas surround: ${facts.painted.description} paints ${facts.painted.color}, but --cd-ui-grund resolves to ${facts.grund}; the surround follows the mode (guide §10.1)`,\n ];\n}\n\n/** Lasso, Hand and the other tools of the `tools` group; every other entry is a notation preview. */\nexport function isToolEntry(entry: Pick<PaletteEntryState, \"action\" | \"group\">): boolean {\n return entry.group === \"tools\" || entry.action.endsWith(\"-tool\");\n}\n\nfunction paletteEntryState(entry: PaletteColorEntry): string {\n if (entry.disabled) return \"aria-disabled\";\n if (entry.hovered) return entry.pressed ? \"pressed and hovered\" : \"hovered\";\n return entry.pressed ? \"pressed\" : \"at rest\";\n}\n\n/**\n * Guide §5.5 and §13.5: a tool entry and its icon (`currentColor`) show `--cd-ui-text` at rest and\n * while pressed, `--cd-ui-interaktion` while hovered and `--cd-ui-text-leise` while aria-disabled.\n * Notation previews keep their own colours and are exempt.\n */\nexport function paletteColorProblems(facts: PaletteColorFacts): string[] {\n const problems: string[] = [];\n for (const entry of facts.entries) {\n if (!isToolEntry(entry)) continue;\n const [role, value] = entry.disabled\n ? ([\"--cd-ui-text-leise\", facts.roles.textLeise] as const)\n : entry.hovered\n ? ([\"--cd-ui-interaktion\", facts.roles.interaktion] as const)\n : ([\"--cd-ui-text\", facts.roles.text] as const);\n const state = paletteEntryState(entry);\n if (entry.color !== value) {\n problems.push(\n `palette: tool \"${entry.action}\" ${state} has color ${entry.color}, expected ${role} (${value}) (guide §5.5)`,\n );\n }\n if (entry.icon && entry.icon.color !== value) {\n const icon = entry.icon.kind === \"svg\" ? \"<svg> icon\" : \"::before icon\";\n problems.push(\n `palette: the ${icon} of tool \"${entry.action}\" ${state} has color ${entry.icon.color}, expected ${role} (${value}); a renderer rule overrides the skin (guide §5.5)`,\n );\n }\n }\n return problems;\n}\n\nexport interface CreateFacts {\n /** `data-action` of the entry the kit pressed Enter on. */\n entry: string;\n before: readonly ShapeFacts[];\n after: readonly ShapeFacts[];\n canvas: CanvasStateFacts;\n /** The free rectangle when Enter was pressed (guide §5.9). */\n free: Rectangle;\n}\n\nconst round = (value: number): number => Math.round(value * 10) / 10;\n\n/**\n * Guide §5.5: Enter on a creating entry places exactly one element in the centre of the free\n * rectangle, selects it and puts the focus on the canvas (its `<svg>` or the label editor).\n */\nexport function createProblems(facts: CreateFacts): string[] {\n const known = new Set(facts.before.map((shape) => shape.id));\n const added = facts.after.filter((shape) => !known.has(shape.id));\n const pressed = `Enter on palette entry \"${facts.entry}\"`;\n if (added.length === 0) {\n return [\n `create: ${pressed} added no element; Enter on a creating entry places it in the centre of the free rectangle (guide §5.5)`,\n ];\n }\n if (added.length > 1) {\n return [\n `create: ${pressed} added ${added.length} elements (${added.map((shape) => shape.id).join(\", \")}), expected exactly one`,\n ];\n }\n const [shape] = added as [ShapeFacts];\n const problems: string[] = [];\n if (!shape.selected) problems.push(`create: the new element \"${shape.id}\" is not selected (guide §5.5)`);\n if (!facts.canvas.focusInCanvas) {\n problems.push(\n `create: after ${pressed} the focus is on ${facts.canvas.focused}, expected the canvas (its <svg> or the label editor, guide §5.5)`,\n );\n }\n const centre = { x: shape.box.left + shape.box.width / 2, y: shape.box.top + shape.box.height / 2 };\n const { free } = facts;\n const tolerance = GEOMETRY_TOLERANCE_PX + 1e-6;\n const inside =\n centre.x >= free.left - tolerance &&\n centre.x <= free.right + tolerance &&\n centre.y >= free.top - tolerance &&\n centre.y <= free.bottom + tolerance;\n if (!inside) {\n problems.push(\n `create: the new element \"${shape.id}\" is centred at (${round(centre.x)}, ${round(centre.y)})px, outside the free rectangle ${round(free.left)}–${round(free.right)} × ${round(free.top)}–${round(free.bottom)}px (guide §5.5, §5.9)`,\n );\n }\n return problems;\n}\n\n/** The read-only marks once the invalid-file state shows (guide §5.12, §13.5). */\nexport function readOnlyStateProblems(facts: ReadOnlyStateFacts): string[] {\n const problems: string[] = [];\n const after = `${INVALID_STATUS_DELAY_MS}ms after show.invalid`;\n if (!facts.readOnly) problems.push(`read-only: the root has no data-readonly ${after}`);\n const status = facts.status;\n if (!status?.visible) {\n problems.push(`read-only: the status box is not visible ${after} (guide §5.12)`);\n } else if (status.attributes.role !== \"alert\") {\n problems.push(\n `read-only: the status box of an invalid file has role \"${status.attributes.role ?? \"\"}\", expected \"alert\" (guide §13.5)`,\n );\n }\n return problems;\n}\n\n/** The palette entries that stay active on a read-only canvas (guide §13.5), named independently of the shell. */\nexport const READ_ONLY_PALETTE_ACTIONS: readonly string[] = [\"lasso-tool\", \"hand-tool\"];\n\n/** Guide §13.5: every palette entry that changes something is aria-disabled, Lasso and Hand stay active. */\nexport function readOnlyPaletteProblems(entries: readonly PaletteEntryState[]): string[] {\n return entries.flatMap((entry) => {\n const staysActive = READ_ONLY_PALETTE_ACTIONS.includes(entry.action);\n if (staysActive && entry.disabled) {\n return [\n `palette: \"${entry.action}\" is aria-disabled on the read-only canvas; Lasso and Hand stay active (guide §13.5)`,\n ];\n }\n if (!staysActive && !entry.disabled) {\n return [`palette: \"${entry.action}\" is not aria-disabled on the read-only canvas (guide §13.5)`];\n }\n return [];\n });\n}\n\n/** The shell's own Legend toggle in the Model group. */\nconst LEGEND_MENU_ID = \"legend\";\n\n/**\n * Guide §13.5 and the product decision on view toggles: on a read-only canvas the Legend toggle,\n * export and help stay usable. The shell renders its `MenuGroups` as Model, Export, Help, empty\n * groups left out, so only the first group can be Model: an entry in a later one that read-only\n * newly disabled is a problem.\n */\nexport function readOnlyMenuProblems(\n before: readonly MenuEntryFacts[],\n after: readonly MenuEntryFacts[],\n): string[] {\n const problems: string[] = [];\n const key = (entry: MenuEntryFacts) => `${entry.menuId ?? \"\"}\\u0000${entry.name}`;\n const enabledBefore = new Set(before.filter((entry) => !entry.disabled).map(key));\n for (const entry of after) {\n if (!entry.disabled) continue;\n if (entry.menuId === LEGEND_MENU_ID && entry.role === \"menuitemcheckbox\") {\n problems.push(\n \"menu: the Legend toggle is aria-disabled on the read-only canvas; a view-only toggle stays usable (guide §13.5)\",\n );\n } else if (entry.group !== \"model\" && enabledBefore.has(key(entry))) {\n problems.push(\n `menu: \"${entry.name}\" is aria-disabled on the read-only canvas; export and help stay usable (guide §13.5)`,\n );\n }\n }\n return problems;\n}\n\n/** What the read-only lock must keep from a shape (guide §13.5): no context pad, move, resize, delete or label editor. */\nexport interface LockedShapeFacts {\n /** Context-pad entries visible after clicking the shape. */\n contextPadEntries: readonly string[];\n /** The shape before and after a 40px drag (`undefined`: gone). */\n dragged: { before: ShapeFacts; after: ShapeFacts | undefined };\n /** Text fields inside `.djs-container` after a double-click on the shape. */\n textFields: readonly string[];\n /** Whether the shape is still there after Delete, then after Backspace. */\n kept: { Delete: boolean; Backspace: boolean };\n}\n\nexport function lockedShapeProblems(facts: LockedShapeFacts): string[] {\n const problems: string[] = [];\n const { before, after } = facts.dragged;\n if (facts.contextPadEntries.length > 0) {\n problems.push(\n `read-only: selecting \"${before.id}\" shows the context pad (${facts.contextPadEntries.join(\", \")}) (guide §13.5)`,\n );\n }\n if (!after) {\n problems.push(`read-only: a 40px drag removed \"${before.id}\" from the canvas (guide §13.5)`);\n } else if (\n after.transform !== before.transform ||\n Math.abs(after.size.width - before.size.width) > 0.5 ||\n Math.abs(after.size.height - before.size.height) > 0.5\n ) {\n problems.push(\n `read-only: a 40px drag changed \"${before.id}\" (transform \"${before.transform}\" → \"${after.transform}\", ${round(before.size.width)} × ${round(before.size.height)} → ${round(after.size.width)} × ${round(after.size.height)}) (guide §13.5)`,\n );\n }\n if (facts.textFields.length > 0) {\n problems.push(\n `read-only: a double-click on \"${before.id}\" opens a text field (${facts.textFields.join(\", \")}) (guide §13.5)`,\n );\n }\n for (const key of [\"Delete\", \"Backspace\"] as const) {\n if (!facts.kept[key])\n problems.push(`read-only: ${key} on the canvas deleted \"${before.id}\" (guide §13.5)`);\n }\n return problems;\n}\n","import {\n INVALID_STATUS_DELAY_MS,\n TOOLTIP_DELAY_MS,\n type Appearance,\n type ShellHost,\n type Size,\n} from \"../core/index.js\";\nimport {\n absentIslandProblems,\n afterDestroyKeyProblem,\n appearanceProblems,\n ariaProblems,\n createProblems,\n harnessHookProblems,\n isToolEntry,\n keyReachProblem,\n leftoverProblems,\n lockedShapeProblems,\n menuClosedProblems,\n menuKeysAtDocumentProblems,\n menuOpenProblems,\n optionalIslandProblems,\n paletteColorProblems,\n paletteShortcutProblems,\n readOnlyMenuProblems,\n readOnlyPaletteProblems,\n readOnlyStateProblems,\n surroundProblems,\n tabSequenceProblems,\n type KeyReach,\n type PaletteShortcutFacts,\n type TabStop,\n} from \"./checks.js\";\nimport {\n MODE_ROLES,\n activeStopProbe,\n appearanceProbe,\n ariaProbe,\n canvasStateProbe,\n menuEntriesProbe,\n menuProbe,\n paletteColorProbe,\n paletteEntriesProbe,\n paletteFocusProbe,\n paletteShortcutProbe,\n readOnlyStateProbe,\n shapesProbe,\n surroundProbe,\n zoomButtonsProbe,\n type AppearanceFacts,\n type AriaFacts,\n type MenuEntryFacts,\n type MenuFacts,\n type PaletteEntryState,\n type ShapeFacts,\n} from \"./facts.js\";\nimport {\n DEFAULT_ROOT,\n dropdownProblems,\n freeRectangle,\n geometryProblems,\n measureChrome,\n tooltipProblems,\n type ChromeMeasurement,\n type TooltipRow,\n} from \"./geometry.js\";\nimport type {\n ShellCaseOutcome,\n ShellConformanceCase,\n ShellConformanceHarness,\n ShellSkip,\n ShowHook,\n ShowHooks,\n} from \"./harness.js\";\nimport type { PageLike } from \"./page.js\";\nimport {\n afterPressProbe,\n armCleanupProbe,\n canvasHandlesProbe,\n clearKeysProbe,\n findOverlay,\n findTarget,\n focusTarget,\n hostPageModeProbe,\n inPage,\n injectProbe,\n leftoverProbe,\n removeInjectedProbe,\n settle,\n type ChromeTarget,\n type InjectedKind,\n type TargetFacts,\n} from \"./page-tools.js\";\n\n/** Wide, narrow and very narrow (guide §5.15); 900 is above, 700 below the low breakpoint. */\nexport const DEFAULT_SIZES: readonly Size[] = [\n { width: 1280, height: 900 },\n { width: 720, height: 700 },\n { width: 420, height: 700 },\n];\n\nconst LIGHT: Appearance = { theme: \"light\" };\n\n/** Shown in this order, so the legend is measured without and then with the pill. */\nconst SHOWN_ISLANDS = [\"legend\", \"problems\", \"status\", \"inspector\"] as const satisfies ReadonlyArray<\n keyof ShowHooks\n>;\n\n/** How far the read-only case drags a shape (guide §13.5: no move). */\nconst LOCKED_DRAG_PX = 40;\n\n/** Room for a modeler that places, selects or re-renders a frame or two after Enter. */\nconst CREATE_WAIT_MS = 1000;\n\n/** Room after `INVALID_STATUS_DELAY_MS` for the read-only marks and the status box to show. */\nconst READ_ONLY_WAIT_MS = 1000;\n\n/** Room for the palette's 150ms colour transition (`--cd-motion-fast`) and a frame on either side. */\nconst COLOR_WAIT_MS = 600;\n\nconst POLL_MS = 50;\n\n/** Requested from the modeler by the appearance case (VS Code Dark, High Contrast, High Contrast Light). */\nconst REQUESTED_APPEARANCES: readonly Appearance[] = [\n { theme: \"dark\" },\n { theme: \"dark\", kontrast: \"hoch\" },\n { theme: \"light\", kontrast: \"hoch\" },\n];\n\n/** Room for the chrome tooltip's own fade after its 300ms hover delay. */\nconst HOVER_MARGIN_MS = 200;\n\n/** A spot without chrome: the root's top-left corner lies outside every island (12px edge). */\nconst PARK = { x: 1, y: 1 } as const;\n\n/** Every kind of text field a modeler renders: inspector and dialog fields, the label editor. */\nconst TEXT_FIELDS: ReadonlyArray<readonly [InjectedKind, string]> = [\n [\"input\", \"a text field\"],\n [\"textarea\", \"a textarea\"],\n [\"contenteditable\", \"an editable label\"],\n];\n\nconst UNDO_REDO_PRESSES = [\n \"Control+KeyZ\",\n \"Meta+KeyZ\",\n \"Control+Shift+KeyZ\",\n \"Meta+Shift+KeyZ\",\n \"Control+KeyY\",\n] as const;\n\nconst ONE_STEP_UP = 135;\nconst TWO_STEPS_UP = 182;\nconst ZOOM_LIMIT_MAX = 400;\nconst ZOOM_LIMIT_MIN = 20;\n\nfunction sizeLabel(size: Size): string {\n return `${size.width} × ${size.height}`;\n}\n\nfunction appearanceLabel(appearance: Appearance): string {\n return appearance.kontrast ? `${appearance.theme} + ${appearance.kontrast}` : appearance.theme;\n}\n\nfunction fail(caseName: string, host: ShellHost, problems: readonly string[]): never {\n const unique = [...new Set(problems)];\n throw new Error(\n `@miragon/modeler-shell conformance: ${caseName} (${host} host)\\n${unique.map((problem) => `- ${problem}`).join(\"\\n\")}`,\n );\n}\n\nfunction finish(\n caseName: string,\n host: ShellHost,\n problems: readonly string[],\n skipped: Iterable<ShellSkip>,\n): ShellCaseOutcome | void {\n if (problems.length > 0) fail(caseName, host, problems);\n const seen = new Set<string>();\n const unique = [...skipped].filter((skip) => !seen.has(skip.reason) && seen.add(skip.reason));\n return unique.length > 0 ? { skipped: unique } : undefined;\n}\n\n/** A harness that gives a hook it also declares absent contradicts itself: fail before opening anything. */\nfunction assertHooksConsistent<P extends PageLike>(\n caseName: string,\n harness: ShellConformanceHarness<P>,\n hooks: readonly ShowHook[],\n): void {\n const problems = harnessHookProblems(harness, hooks);\n if (problems.length > 0) fail(caseName, harness.host, problems);\n}\n\n/** A hook that is neither given nor declared absent. */\nfunction unfed<P extends PageLike>(harness: ShellConformanceHarness<P>, hook: ShowHook): boolean {\n return !harness.show?.[hook] && !harness.absent?.includes(hook);\n}\n\nfunction missingHooks<P extends PageLike>(harness: ShellConformanceHarness<P>, what: string): ShellSkip[] {\n return SHOWN_ISLANDS.filter((island) => unfed(harness, island)).map((island) => ({\n hook: island,\n reason: `show.${island} is undefined: ${what} of the ${island} island not verified`,\n }));\n}\n\n/** Reads until `done` holds or `timeoutMs` passed; the last value either way. */\nasync function pollUntil<T>(\n page: PageLike,\n read: () => Promise<T>,\n done: (value: T) => boolean,\n timeoutMs: number,\n): Promise<T> {\n let value = await read();\n for (let waited = 0; !done(value) && waited < timeoutMs; waited += POLL_MS) {\n await page.waitForTimeout(POLL_MS);\n value = await read();\n }\n return value;\n}\n\n/** The visible islands of an ARIA snapshot that a harness may declare absent. */\nfunction visibleIslands(facts: AriaFacts): Set<string> {\n const islands = new Set<string>();\n for (const island of SHOWN_ISLANDS) if (facts[island]?.visible) islands.add(island);\n return islands;\n}\n\n/** Hovers `target` long enough for its chrome tooltip; the hovered control, `null` when there is none. */\nasync function hover(page: PageLike, root: string, target: ChromeTarget): Promise<TargetFacts | null> {\n const anchor = await findTarget(page, root, target);\n if (!anchor) return null;\n await page.mouse.move(PARK.x, PARK.y);\n await page.mouse.move(anchor.client.x, anchor.client.y);\n await page.waitForTimeout(TOOLTIP_DELAY_MS + HOVER_MARGIN_MS);\n await settle(page);\n return anchor;\n}\n\nasync function openMenuByClick(page: PageLike, root: string): Promise<boolean> {\n const trigger = await findTarget(page, root, \"menu\");\n if (!trigger) return false;\n await page.mouse.click(trigger.client.x, trigger.client.y);\n await settle(page);\n return true;\n}\n\nasync function closeByEscape(page: PageLike): Promise<void> {\n await page.keyboard.press(\"Escape\");\n await settle(page);\n}\n\n/** Dropdown and tooltips of one measured state (guide §5.4, §5.6). */\nasync function popupGeometry(\n page: PageLike,\n root: string,\n measurement: ChromeMeasurement,\n): Promise<string[]> {\n const problems: string[] = [];\n if (!(await openMenuByClick(page, root))) return [\"dropdown: no visible menu trigger to open it\"];\n const dropdown = await findOverlay(page, root, \"menu\");\n if (!dropdown) problems.push('dropdown: no visible role=\"menu\" after clicking the trigger');\n else problems.push(...dropdownProblems(dropdown.box, measurement.container));\n await closeByEscape(page);\n\n const rows: Array<[ChromeTarget, TooltipRow]> = [\n [\"menu\", \"top\"],\n [\"palette-entry\", measurement.paletteRow === \"second-row\" ? \"second-row\" : \"top\"],\n [\"zoom-in\", \"bottom\"],\n ];\n for (const [target, row] of rows) {\n const anchor = await hover(page, root, target);\n if (!anchor) {\n problems.push(`tooltip: no visible ${target} to hover`);\n continue;\n }\n const tooltip = await findOverlay(page, root, \"tooltip\");\n if (!tooltip) {\n problems.push(`tooltip: none visible ${TOOLTIP_DELAY_MS + HOVER_MARGIN_MS}ms after hovering ${target}`);\n continue;\n }\n if (tooltip.count > 1) problems.push(`tooltip: ${tooltip.count} tooltips visible at once`);\n if (anchor.label && !tooltip.text.startsWith(anchor.label)) {\n problems.push(`tooltip: hovering ${target} (\"${anchor.label}\") shows \"${tooltip.text}\"`);\n }\n problems.push(\n ...tooltipProblems(tooltip.box, anchor.box, row, measurement.container).map(\n (problem) => `${problem} (on ${target})`,\n ),\n );\n }\n await page.mouse.move(PARK.x, PARK.y);\n return problems;\n}\n\nconst geometryCase: ShellConformanceCase = {\n name: \"geometry\",\n async run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>) {\n assertHooksConsistent(\"geometry\", harness, SHOWN_ISLANDS);\n const root = harness.root ?? DEFAULT_ROOT;\n const problems: string[] = [];\n for (const size of harness.sizes ?? DEFAULT_SIZES) {\n const at = sizeLabel(size);\n await harness.open(page, { size, requested: LIGHT });\n await settle(page);\n const check = async (state: string): Promise<ChromeMeasurement> => {\n const measurement = await measureChrome(page, root);\n problems.push(\n ...[\n ...geometryProblems(measurement, harness.host),\n ...absentIslandProblems(new Set(Object.keys(measurement.islands)), harness.absent),\n ].map((problem) => `[${at}, ${state}] ${problem}`),\n );\n return measurement;\n };\n const opened = await check(\"as opened\");\n problems.push(...(await popupGeometry(page, root, opened)).map((problem) => `[${at}] ${problem}`));\n for (const island of SHOWN_ISLANDS) {\n const show = harness.show?.[island];\n if (!show) continue;\n await show(page);\n await settle(page);\n await check(`after show.${island}`);\n }\n }\n return finish(\"geometry\", harness.host, problems, missingHooks(harness, \"the geometry\"));\n },\n};\n\nasync function menuState(page: PageLike, root: string): Promise<MenuFacts> {\n const facts = await inPage(page, menuProbe, { root });\n if (!facts) throw new Error(`@miragon/modeler-shell conformance: no element matches \"${root}\"`);\n return facts;\n}\n\n/** Keyboard model of the menu (guide §5.4): Enter/↓ open on the first entry, ↑ on the last, wrap, Escape. */\nasync function menuKeyboardProblems(page: PageLike, root: string): Promise<string[]> {\n const problems: string[] = [];\n const openWith = async (key: string, focus: \"first\" | \"last\"): Promise<MenuFacts | undefined> => {\n if (!(await focusTarget(page, root, \"menu\"))) {\n problems.push(\"menu: the trigger cannot take focus\");\n return undefined;\n }\n await page.keyboard.press(key);\n await settle(page);\n const opened = await menuState(page, root);\n problems.push(...menuOpenProblems(opened, focus).map((problem) => `${key} on the trigger: ${problem}`));\n return opened;\n };\n const close = async (key: string) => {\n await closeByEscape(page);\n problems.push(\n ...menuClosedProblems(await menuState(page, root), true).map(\n (problem) => `${key}, then Escape: ${problem}`,\n ),\n );\n };\n\n const opened = await openWith(\"Enter\", \"first\");\n if (opened && opened.items.length > 1) {\n const moves: Array<[string, (count: number) => number]> = [\n [\"ArrowUp\", (count) => count - 1],\n [\"ArrowDown\", () => 0],\n [\"End\", (count) => count - 1],\n [\"Home\", () => 0],\n ];\n await inPage(page, clearKeysProbe, null);\n for (const [key, target] of moves) {\n await page.keyboard.press(key);\n const moved = await menuState(page, root);\n const expected = target(moved.items.length);\n if (moved.active !== expected) {\n problems.push(\n `menu: ${key} moves the focus to entry ${moved.active + 1}, expected entry ${expected + 1} of ${moved.items.length}`,\n );\n }\n }\n const { documentKeys } = await inPage(page, afterPressProbe, { root });\n problems.push(\n ...menuKeysAtDocumentProblems(\n moves.map(([key]) => key),\n documentKeys,\n ),\n );\n }\n if (opened) await close(\"Enter\");\n if (await openWith(\"ArrowDown\", \"first\")) await close(\"ArrowDown\");\n if (await openWith(\"ArrowUp\", \"last\")) await close(\"ArrowUp\");\n return problems;\n}\n\n/** Roving tabindex of the palette toolbar (guide §5.5): ← → Home End. */\nasync function paletteKeyboardProblems(page: PageLike, root: string): Promise<string[]> {\n const before = await inPage(page, paletteFocusProbe, { root });\n if (!before || before.entries.length < 2) return [];\n if (!(await focusTarget(page, root, \"palette-tab-stop\"))) {\n return ['palette: no entry with tabindex=\"0\" takes the focus'];\n }\n const problems: string[] = [];\n const start = before.entries.indexOf(before.tabStops[0] ?? \"\");\n const step = start < before.entries.length - 1 ? 1 : -1;\n const moves: Array<[string, number]> = [\n [step === 1 ? \"ArrowRight\" : \"ArrowLeft\", start + step],\n [\"End\", before.entries.length - 1],\n [\"Home\", 0],\n ];\n for (const [key, index] of moves) {\n await page.keyboard.press(key);\n const after = await inPage(page, paletteFocusProbe, { root });\n const expected = before.entries[index];\n if (!after || after.active !== expected) {\n problems.push(`palette: ${key} focuses \"${after?.active ?? \"nothing\"}\", expected \"${expected}\"`);\n } else if (after.tabStops.length !== 1 || after.tabStops[0] !== expected) {\n problems.push(\n `palette: after ${key} tabindex=\"0\" is on ${after.tabStops.join(\", \") || \"no entry\"}, expected \"${expected}\"`,\n );\n }\n }\n return problems;\n}\n\n/** Every palette entry by keyboard: a shortcut its tooltip shows is named in `aria-keyshortcuts`. */\nasync function paletteShortcutWalk(page: PageLike, root: string): Promise<string[]> {\n const before = await inPage(page, paletteFocusProbe, { root });\n if (!before || before.entries.length === 0) return [];\n if (!(await focusTarget(page, root, \"palette-tab-stop\"))) return [];\n if (before.entries.length > 1) await page.keyboard.press(\"End\");\n await page.keyboard.press(\"Home\");\n const seen: PaletteShortcutFacts[] = [];\n for (let index = 0; index < before.entries.length; index++) {\n const facts = await inPage(page, paletteShortcutProbe, { root });\n if (facts) seen.push(facts);\n await page.keyboard.press(\"ArrowRight\");\n }\n return paletteShortcutProblems(seen);\n}\n\n/** Tab from the menu trigger: the palette's one stop, then the canvas (guide §5.14). */\nasync function tabSequenceFromMenu(page: PageLike, root: string): Promise<string[]> {\n if (!(await focusTarget(page, root, \"menu\"))) return [];\n const stops: TabStop[] = [];\n for (let step = 0; step < 3; step++) {\n await page.keyboard.press(\"Tab\");\n const stop = await inPage(page, activeStopProbe, { root });\n stops.push({ description: stop.description, kind: stop.kind as TabStop[\"kind\"] });\n }\n return tabSequenceProblems(stops);\n}\n\n/** `aria-disabled` at 400 % and 20 % (guide §5.8), reached by clicking the buttons. */\nasync function zoomLimitProblems(page: PageLike, root: string): Promise<string[]> {\n const problems: string[] = [];\n const limits: Array<[\"in\" | \"out\", ChromeTarget, number, number, \"in\" | \"out\"]> = [\n [\"in\", \"zoom-in\", ZOOM_LIMIT_MAX, 12, \"out\"],\n [\"out\", \"zoom-out\", ZOOM_LIMIT_MIN, 16, \"in\"],\n ];\n for (const [button, target, limit, maxClicks, other] of limits) {\n const control = await findTarget(page, root, target);\n if (!control) continue;\n let buttons = await inPage(page, zoomButtonsProbe, { root });\n for (\n let click = 0;\n click < maxClicks && buttons[button]?.attributes[\"aria-disabled\"] !== \"true\";\n click++\n ) {\n await page.mouse.click(control.client.x, control.client.y);\n await settle(page);\n buttons = await inPage(page, zoomButtonsProbe, { root });\n }\n const { zoom } = await inPage(page, afterPressProbe, { root });\n const reached = buttons[button];\n if (reached?.attributes[\"aria-disabled\"] !== \"true\") {\n problems.push(\n `zoom: [data-zoom=\"${button}\"] is not aria-disabled after ${maxClicks} clicks (readout ${zoom ?? \"?\"}%)`,\n );\n } else {\n if (zoom !== limit) {\n problems.push(`zoom: [data-zoom=\"${button}\"] is disabled at ${zoom ?? \"?\"}%, expected at ${limit}%`);\n }\n if (reached.disabled) problems.push(`zoom: [data-zoom=\"${button}\"] is natively disabled at the limit`);\n }\n if (buttons[other]?.attributes[\"aria-disabled\"] === \"true\") {\n problems.push(`zoom: [data-zoom=\"${other}\"] is aria-disabled at ${zoom ?? \"?\"}%`);\n }\n if (buttons.actual?.attributes[\"aria-disabled\"] === \"true\") {\n problems.push(\"zoom: the readout is disabled at a limit\");\n }\n }\n await page.mouse.move(PARK.x, PARK.y);\n return problems;\n}\n\nconst ariaCase: ShellConformanceCase = {\n name: \"aria\",\n async run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>) {\n assertHooksConsistent(\"aria\", harness, SHOWN_ISLANDS);\n const root = harness.root ?? DEFAULT_ROOT;\n const size = (harness.sizes ?? DEFAULT_SIZES)[0] ?? DEFAULT_SIZES[0]!;\n await harness.open(page, { size, requested: LIGHT });\n await settle(page);\n const facts = await inPage(page, ariaProbe, { root });\n if (!facts) fail(\"aria\", harness.host, [`no element matches the shell root selector \"${root}\"`]);\n const problems = ariaProblems(facts, harness.host);\n problems.push(...(await menuKeyboardProblems(page, root)));\n problems.push(...(await paletteKeyboardProblems(page, root)));\n problems.push(...(await paletteShortcutWalk(page, root)));\n problems.push(...(await tabSequenceFromMenu(page, root)));\n problems.push(...(await zoomLimitProblems(page, root)));\n\n const shown = new Set<string>();\n for (const island of SHOWN_ISLANDS) {\n const show = harness.show?.[island];\n if (!show) continue;\n await show(page);\n shown.add(island);\n }\n let final: AriaFacts = facts;\n if (shown.size > 0) {\n await settle(page);\n const withIslands = await inPage(page, ariaProbe, { root });\n if (withIslands) {\n final = withIslands;\n problems.push(...optionalIslandProblems(withIslands, shown));\n const known = new Set(problems);\n problems.push(\n ...ariaProblems(withIslands, harness.host)\n .filter((problem) => !known.has(problem))\n .map((problem) => `with every island shown: ${problem}`),\n );\n }\n }\n problems.push(...absentIslandProblems(visibleIslands(final), harness.absent));\n return finish(\"aria\", harness.host, problems, missingHooks(harness, \"the roles and names\"));\n },\n};\n\nconst keysCase: ShellConformanceCase = {\n name: \"keys\",\n async run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>) {\n const root = harness.root ?? DEFAULT_ROOT;\n const host = harness.host;\n const size = (harness.sizes ?? DEFAULT_SIZES)[0] ?? DEFAULT_SIZES[0]!;\n await harness.open(page, { size, requested: LIGHT });\n await settle(page);\n const problems: string[] = [];\n\n if (!(await focusTarget(page, root, \"canvas\"))) {\n fail(\"keys\", host, [\"canvas: the diagram-js <svg> (.djs-container > svg) cannot take focus\"]);\n }\n await inPage(page, clearKeysProbe, null);\n let current = (await inPage(page, afterPressProbe, { root })).zoom;\n if (current === null) fail(\"keys\", host, ['zoom: no readout [data-zoom=\"actual\"] showing a percentage']);\n\n const press = async (\n key: string,\n reach: KeyReach | undefined,\n zoom: number | \"unchanged\" | undefined,\n context = \"on the canvas\",\n ) => {\n const before = current;\n await page.keyboard.press(key);\n let after = await inPage(page, afterPressProbe, { root });\n const where = `${key} ${context}`;\n if (reach) {\n const problem = keyReachProblem(where, reach, host, after);\n if (problem) problems.push(problem);\n }\n if (zoom === undefined) return;\n const expected = zoom === \"unchanged\" ? before : zoom;\n // a readout that has not moved yet may still be waiting for its frame; a wrong one stays wrong\n for (let poll = 0; after.zoom === before && expected !== before && poll < 10; poll++) {\n await page.waitForTimeout(50);\n after = await inPage(page, afterPressProbe, { root });\n }\n if (after.zoom !== expected) {\n problems.push(\n zoom === \"unchanged\"\n ? `${where} changed the zoom from ${before}% to ${after.zoom ?? \"?\"}%; it must not act`\n : `${where} zoomed to ${after.zoom ?? \"?\"}% from ${before}%, expected ${expected}% (exactly one step)`,\n );\n }\n current = after.zoom ?? current;\n };\n const inside = async (kind: InjectedKind, context: string, steps: () => Promise<void>) => {\n if (await inPage(page, injectProbe, { root, kind })) await steps();\n else problems.push(`cannot focus ${context} stand-in inside the root`);\n await inPage(page, removeInjectedProbe, null);\n };\n\n await press(\"Control+Digit0\", \"handled\", 100);\n const pairs: Array<[string, string]> = [\n [\"Control+Equal\", \"Control+Minus\"],\n [\"Control+Shift+Equal\", \"Control+Shift+Minus\"],\n [\"Meta+Equal\", \"Meta+Minus\"],\n [\"Meta+Shift+Equal\", \"Meta+Shift+Minus\"],\n [\"Control+NumpadAdd\", \"Control+NumpadSubtract\"],\n [\"Meta+NumpadAdd\", \"Meta+NumpadSubtract\"],\n ];\n for (const [zoomIn, zoomOut] of pairs) {\n await press(zoomIn, \"handled\", ONE_STEP_UP);\n await press(zoomOut, \"handled\", 100);\n }\n for (const zoomToActual of [\"Meta+Digit0\", \"Control+Numpad0\"]) {\n await press(\"Control+Equal\", \"handled\", ONE_STEP_UP);\n await press(zoomToActual, \"handled\", 100);\n }\n for (const key of [\"Equal\", \"Minus\", \"Shift+Equal\", \"Shift+Minus\", \"NumpadAdd\", \"NumpadSubtract\"]) {\n await press(key, \"free\", \"unchanged\", \"on the canvas without Cmd/Ctrl\");\n }\n for (const key of [\"Digit0\", \"Control+Alt+Equal\", \"Control+Alt+Minus\", \"Control+Shift+Digit1\"]) {\n await press(key, undefined, \"unchanged\");\n }\n await press(\"F1\", \"free\", undefined);\n await press(\"Escape\", \"free\", undefined, \"on the canvas without a menu or dialog\");\n if (await inPage(page, canvasHandlesProbe, { root, key: \"F9\" })) {\n await press(\"F9\", \"canvas\", undefined, \"handled by the canvas\");\n }\n await inPage(page, removeInjectedProbe, null);\n if (host === \"ide\") {\n // Guide §13.5: on the canvas, undo and redo use the document's history, never the canvas's.\n for (const key of UNDO_REDO_PRESSES) {\n await press(key, \"free\", undefined, \"on the canvas (undo and redo belong to the VS Code document)\");\n }\n }\n // Guide §13.5: keys the canvas uses act on the canvas only, select all included; in VS Code an\n // unhandled Cmd/Ctrl+A would select the webview's text instead.\n for (const key of [\"Control+KeyA\", \"Meta+KeyA\"]) {\n await press(key, \"canvas\", undefined, \"on the canvas (select all acts on the canvas only)\");\n }\n\n await press(\"Control+Equal\", \"handled\", ONE_STEP_UP);\n for (const [kind, field] of TEXT_FIELDS) {\n await inside(kind, field, async () => {\n await press(\"Control+Equal\", \"blocked\", \"unchanged\", `in ${field}`);\n await press(\"Control+Minus\", \"blocked\", \"unchanged\", `in ${field}`);\n await press(\"Shift+Digit1\", \"free\", \"unchanged\", `in ${field}`);\n await press(\"Control+KeyZ\", \"blocked\", undefined, `in ${field}`);\n await press(\"Meta+Shift+KeyZ\", \"blocked\", undefined, `in ${field}`);\n await press(\"Control+KeyY\", \"blocked\", undefined, `in ${field}`);\n });\n }\n await inside(\"modal\", \"a modal dialog\", async () => {\n await press(\"Control+Equal\", \"blocked\", \"unchanged\", \"with a modal dialog open\");\n await press(\"Shift+Digit1\", \"free\", \"unchanged\", \"with a modal dialog open\");\n await press(\"Escape\", \"blocked\", undefined, \"with a modal dialog open\");\n });\n await inside(\"popover\", \"a popover\", async () => {\n await press(\"Control+Minus\", \"handled\", 100, \"in a popover\");\n await press(\"Control+Equal\", \"handled\", ONE_STEP_UP, \"in a popover\");\n await press(\"Escape\", \"blocked\", undefined, \"with a popover open\");\n });\n\n if (await openMenuByClick(page, root)) {\n await inPage(page, clearKeysProbe, null);\n await press(\"Escape\", \"handled\", undefined, \"with the menu open\");\n if (await findOverlay(page, root, \"menu\")) problems.push(\"Escape with the menu open did not close it\");\n }\n\n await focusTarget(page, root, \"canvas\");\n await press(\"Control+Equal\", \"handled\", TWO_STEPS_UP);\n await page.keyboard.press(\"Shift+Digit1\");\n let fitted = await inPage(page, afterPressProbe, { root });\n const reachProblem = keyReachProblem(\"Shift+Digit1 on the canvas\", \"handled\", host, fitted);\n if (reachProblem) problems.push(reachProblem);\n for (let poll = 0; (fitted.zoom === null || fitted.zoom > 100) && poll < 20; poll++) {\n await page.waitForTimeout(50);\n fitted = await inPage(page, afterPressProbe, { root });\n }\n if (fitted.zoom === null || fitted.zoom > 100) {\n problems.push(\n `Shift+Digit1 on the canvas left the zoom at ${fitted.zoom ?? \"?\"}%, expected a fit (at most 100%)`,\n );\n }\n return finish(\"keys\", host, problems, []);\n },\n};\n\nasync function appearanceFacts(page: PageLike, root: string): Promise<AppearanceFacts | null> {\n const probe = () => inPage(page, appearanceProbe, { root, roles: MODE_ROLES });\n await hover(page, root, \"zoom-in\");\n const withTooltip = await probe();\n const opened = await openMenuByClick(page, root);\n const withMenu = await probe();\n if (opened) await closeByEscape(page);\n await page.mouse.move(PARK.x, PARK.y);\n if (!withTooltip || !withMenu) return withTooltip ?? withMenu;\n const names = new Set(withTooltip.parts.map((part) => part.name));\n return {\n ...withMenu,\n parts: [...withTooltip.parts, ...withMenu.parts.filter((part) => !names.has(part.name))],\n };\n}\n\n/** The palette's tool colours in the current state, read until a running colour transition is done. */\nasync function paletteColors(page: PageLike, root: string): Promise<string[]> {\n const read = async () => {\n const facts = await inPage(page, paletteColorProbe, { root });\n return facts ? paletteColorProblems(facts) : [];\n };\n return pollUntil(page, read, (problems) => problems.length === 0, COLOR_WAIT_MS);\n}\n\n/**\n * Guide §5.5: every tool entry at rest, hovered in turn, and the first tool armed by a click\n * (pressed and hovered, then pressed with the pointer away), Escape afterwards.\n */\nasync function paletteColorWalk(page: PageLike, root: string): Promise<string[]> {\n const problems: string[] = [];\n await page.mouse.move(PARK.x, PARK.y);\n problems.push(...(await paletteColors(page, root)));\n const tools = (await inPage(page, paletteEntriesProbe, { root })).filter(\n (entry) => isToolEntry(entry) && !entry.disabled,\n );\n for (const tool of tools) {\n await page.mouse.move(tool.client.x, tool.client.y);\n problems.push(...(await paletteColors(page, root)));\n await page.mouse.move(PARK.x, PARK.y);\n }\n const armed =\n tools.find((tool) => tool.action === \"lasso-tool\") ?? tools.find((tool) => tool.action.endsWith(\"-tool\"));\n if (armed) {\n await page.mouse.click(armed.client.x, armed.client.y);\n await settle(page);\n const pressed = (await inPage(page, paletteEntriesProbe, { root })).find(\n (entry) => entry.action === armed.action,\n );\n if (!pressed?.pressed) {\n problems.push(`palette: clicking tool \"${armed.action}\" does not set aria-pressed=\"true\" (guide §5.5)`);\n }\n problems.push(...(await paletteColors(page, root)));\n await page.mouse.move(PARK.x, PARK.y);\n problems.push(...(await paletteColors(page, root)));\n await closeByEscape(page);\n }\n return [...new Set(problems)];\n}\n\nconst appearanceCase: ShellConformanceCase = {\n name: \"appearance\",\n async run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>) {\n const root = harness.root ?? DEFAULT_ROOT;\n const size = (harness.sizes ?? DEFAULT_SIZES)[0] ?? DEFAULT_SIZES[0]!;\n const problems: string[] = [];\n for (const requested of REQUESTED_APPEARANCES) {\n const at = `[requested ${appearanceLabel(requested)}]`;\n await harness.open(page, { size, requested });\n if (harness.host === \"embedded\") {\n // The foreign page itself in that mode: a themed page around the modeler (guide §13.3).\n await inPage(page, hostPageModeProbe, {\n theme: requested.theme,\n kontrast: requested.kontrast ?? null,\n });\n }\n await settle(page);\n const facts = await appearanceFacts(page, root);\n if (!facts) {\n problems.push(`${at} no element matches the shell root selector \"${root}\"`);\n continue;\n }\n const verdict = appearanceProblems(facts, harness.host, requested, harness.themes);\n problems.push(...verdict.problems.map((problem) => `${at} ${problem}`));\n const surround = await inPage(page, surroundProbe, { root });\n if (surround) problems.push(...surroundProblems(surround).map((problem) => `${at} ${problem}`));\n problems.push(...(await paletteColorWalk(page, root)).map((problem) => `${at} ${problem}`));\n }\n return finish(\"appearance\", harness.host, problems, []);\n },\n};\n\n/** The visible shapes on the canvas. */\nfunction shapes(page: PageLike, root: string): Promise<ShapeFacts[]> {\n return inPage(page, shapesProbe, { root });\n}\n\n/** Moves the palette's roving focus by keyboard to `action`; `false` when it cannot get there. */\nasync function focusPaletteEntry(page: PageLike, root: string, action: string): Promise<boolean> {\n const before = await inPage(page, paletteFocusProbe, { root });\n if (!before || !before.entries.includes(action)) return false;\n if (!(await focusTarget(page, root, \"palette-tab-stop\"))) return false;\n await page.keyboard.press(\"Home\");\n for (let step = 0; step <= before.entries.length; step++) {\n if ((await inPage(page, paletteFocusProbe, { root }))?.active === action) return true;\n await page.keyboard.press(\"ArrowRight\");\n }\n return false;\n}\n\n/** The first entry that creates something: outside the tools group and not a tool. */\nfunction firstCreatingEntry(entries: readonly PaletteEntryState[]): PaletteEntryState | undefined {\n return entries.find((entry) => !isToolEntry(entry));\n}\n\n/** Enter on `entry`; the shapes once a new one appeared or `CREATE_WAIT_MS` passed. */\nasync function enterOnEntry(\n page: PageLike,\n root: string,\n entry: string,\n before: readonly ShapeFacts[],\n): Promise<ShapeFacts[] | undefined> {\n if (!(await focusPaletteEntry(page, root, entry))) return undefined;\n await page.keyboard.press(\"Enter\");\n await settle(page);\n const known = new Set(before.map((shape) => shape.id));\n return pollUntil(\n page,\n () => shapes(page, root),\n (after) => after.some((shape) => !known.has(shape.id)),\n CREATE_WAIT_MS,\n );\n}\n\nconst createCase: ShellConformanceCase = {\n name: \"create\",\n async run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>) {\n const root = harness.root ?? DEFAULT_ROOT;\n const size = (harness.sizes ?? DEFAULT_SIZES)[0] ?? DEFAULT_SIZES[0]!;\n await harness.open(page, { size, requested: LIGHT });\n await settle(page);\n const entry = firstCreatingEntry(await inPage(page, paletteEntriesProbe, { root }));\n // A notation whose palette only switches tools has nothing to place.\n if (!entry) return undefined;\n await page.mouse.move(PARK.x, PARK.y);\n const free = freeRectangle(await measureChrome(page, root), harness.host);\n const before = await shapes(page, root);\n const after = await enterOnEntry(page, root, entry.action, before);\n if (!after) {\n fail(\"create\", harness.host, [`create: the palette's roving focus does not reach \"${entry.action}\"`]);\n }\n const canvas = await inPage(page, canvasStateProbe, { root });\n const problems = createProblems({ entry: entry.action, before, after, canvas, free });\n await closeByEscape(page);\n return finish(\"create\", harness.host, problems, []);\n },\n};\n\n/** The open menu's entries, opened by a click and closed again by Escape. */\nasync function menuEntries(page: PageLike, root: string): Promise<MenuEntryFacts[]> {\n if (!(await openMenuByClick(page, root))) return [];\n const entries = (await inPage(page, menuEntriesProbe, { root })) ?? [];\n await closeByEscape(page);\n return entries;\n}\n\n/** A shape whose centre a pointer reaches (no chrome above it), found again by its id. */\nasync function reachableShape(page: PageLike, root: string, id?: string): Promise<ShapeFacts | undefined> {\n const all = await shapes(page, root);\n return id === undefined ? all.find((shape) => shape.hit) : all.find((shape) => shape.id === id);\n}\n\n/** Guide §13.5, \"Was der Schreibschutz sperrt\", on one shape: select, drag, double-click, delete. */\nasync function lockedShapeChecks(page: PageLike, root: string, shape: ShapeFacts): Promise<string[]> {\n await page.mouse.click(shape.client.x, shape.client.y);\n await settle(page);\n const selected = await inPage(page, canvasStateProbe, { root });\n\n const before = (await reachableShape(page, root, shape.id)) ?? shape;\n await page.mouse.move(before.client.x, before.client.y);\n await page.mouse.down();\n for (let step = 1; step <= 4; step++) {\n await page.mouse.move(before.client.x + (LOCKED_DRAG_PX * step) / 4, before.client.y);\n }\n await page.mouse.up();\n await settle(page);\n const dragged = await reachableShape(page, root, shape.id);\n\n const target = dragged ?? before;\n await page.mouse.dblclick(target.client.x, target.client.y);\n await settle(page);\n const { textFields } = await inPage(page, canvasStateProbe, { root });\n await closeByEscape(page);\n\n const kept = { Delete: true, Backspace: true };\n for (const key of [\"Delete\", \"Backspace\"] as const) {\n const current = await reachableShape(page, root, shape.id);\n if (!current) break;\n // a key that deletes the selection must not miss it; a click on a selected shape deselects it\n if (!current.selected) await page.mouse.click(current.client.x, current.client.y);\n await focusTarget(page, root, \"canvas\");\n await page.keyboard.press(key);\n await settle(page);\n kept[key] = (await reachableShape(page, root, shape.id)) !== undefined;\n }\n await page.mouse.move(PARK.x, PARK.y);\n return lockedShapeProblems({\n contextPadEntries: selected.contextPadEntries,\n dragged: { before, after: dragged },\n textFields,\n kept,\n });\n}\n\nconst readOnlyCase: ShellConformanceCase = {\n name: \"readOnly\",\n async run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>) {\n assertHooksConsistent(\"readOnly\", harness, [\"invalid\"]);\n const invalid = harness.show?.invalid;\n if (!invalid) {\n if (harness.absent?.includes(\"invalid\")) return undefined;\n return {\n skipped: [\n {\n hook: \"invalid\",\n reason: \"show.invalid is undefined: the read-only canvas of an invalid file was not verified\",\n },\n ],\n };\n }\n const root = harness.root ?? DEFAULT_ROOT;\n const size = (harness.sizes ?? DEFAULT_SIZES)[0] ?? DEFAULT_SIZES[0]!;\n const problems: string[] = [];\n const skipped: ShellSkip[] = [];\n await harness.open(page, { size, requested: LIGHT });\n await settle(page);\n const menuBefore = await menuEntries(page, root);\n\n await invalid(page);\n await page.waitForTimeout(INVALID_STATUS_DELAY_MS);\n const state = await pollUntil(\n page,\n () => inPage(page, readOnlyStateProbe, { root }),\n (facts) => facts === null || readOnlyStateProblems(facts).length === 0,\n READ_ONLY_WAIT_MS,\n );\n if (!state) fail(\"readOnly\", harness.host, [`no element matches the shell root selector \"${root}\"`]);\n await settle(page);\n problems.push(...readOnlyStateProblems(state));\n\n const entries = await inPage(page, paletteEntriesProbe, { root });\n problems.push(...readOnlyPaletteProblems(entries));\n problems.push(...(await paletteColors(page, root)));\n const creating = firstCreatingEntry(entries);\n if (creating) {\n const before = await shapes(page, root);\n const after = await enterOnEntry(page, root, creating.action, before);\n const known = new Set(before.map((shape) => shape.id));\n const added = (after ?? []).filter((shape) => !known.has(shape.id));\n if (added.length > 0) {\n problems.push(\n `read-only: Enter on palette entry \"${creating.action}\" added ${added.map((shape) => `\"${shape.id}\"`).join(\", \")} (guide §13.5)`,\n );\n }\n await closeByEscape(page);\n }\n\n problems.push(...readOnlyMenuProblems(menuBefore, await menuEntries(page, root)));\n\n const shape = await reachableShape(page, root);\n if (shape) {\n problems.push(...(await lockedShapeChecks(page, root, shape)));\n } else {\n skipped.push({\n hook: \"open\",\n reason:\n \"the opened document shows no shape a pointer reaches: context pad, move, delete and label editor of the read-only canvas not verified\",\n });\n }\n return finish(\"readOnly\", harness.host, problems, skipped);\n },\n};\n\nconst cleanupCase: ShellConformanceCase = {\n name: \"cleanup\",\n async run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>) {\n if (!harness.destroy) {\n return {\n skipped: [\n {\n hook: \"destroy\",\n reason: \"harness.destroy is undefined: the cleanup after destroy was not verified\",\n },\n ],\n };\n }\n const root = harness.root ?? DEFAULT_ROOT;\n const size = (harness.sizes ?? DEFAULT_SIZES)[0] ?? DEFAULT_SIZES[0]!;\n await harness.open(page, { size, requested: LIGHT });\n await settle(page);\n const armed = await inPage(page, armCleanupProbe, { root });\n if (!armed) fail(\"cleanup\", harness.host, [`no element matches the shell root selector \"${root}\"`]);\n const problems: string[] = [];\n\n // A hover leaves the tooltip timer pending, so a timer that outlives destroy shows up below.\n const zoomIn = await findTarget(page, root, \"zoom-in\");\n if (zoomIn) {\n await page.mouse.move(PARK.x, PARK.y);\n await page.mouse.move(zoomIn.client.x, zoomIn.client.y);\n }\n try {\n await harness.destroy(page);\n } catch (error) {\n problems.push(`destroy threw: ${error instanceof Error ? error.message : String(error)}`);\n }\n await page.waitForTimeout(Math.max(INVALID_STATUS_DELAY_MS, TOOLTIP_DELAY_MS) + HOVER_MARGIN_MS);\n await page.mouse.move(PARK.x, PARK.y);\n await page.setViewportSize({ width: size.width - 40, height: size.height - 40 });\n await settle(page);\n\n await inPage(page, injectProbe, { root, kind: \"focus-target\" });\n await inPage(page, clearKeysProbe, null);\n for (const key of [\"Control+Equal\", \"Control+Minus\", \"Control+Digit0\", \"Shift+Digit1\"]) {\n await page.keyboard.press(key);\n const { keys } = await inPage(page, afterPressProbe, { root });\n const problem = afterDestroyKeyProblem(key, keys);\n if (problem) problems.push(problem);\n }\n await inPage(page, removeInjectedProbe, null);\n problems.push(...leftoverProblems(await inPage(page, leftoverProbe, null), harness.host));\n return finish(\"cleanup\", harness.host, problems, []);\n },\n};\n\nexport function createCases(): ShellConformanceCase[] {\n return [geometryCase, ariaCase, keysCase, createCase, readOnlyCase, appearanceCase, cleanupCase];\n}\n","import type { Appearance, ColorThemeSetting, ShellHost, Size, Theme } from \"../core/index.js\";\nimport { createCases } from \"./cases.js\";\nimport type { PageLike } from \"./page.js\";\n\nexport interface OpenContext {\n /** The page's viewport, which is the modeler's container in an own document. */\n size: Size;\n /**\n * What the host requests before the modeler resolves it: in an IDE host the VS Code color theme\n * (`vsCodeStubSearch` hands it to a page with the VS Code stub). For an embedded host the kit\n * itself puts the foreign page's `<html>` in this mode once `open` resolved.\n */\n requested: Appearance;\n}\n\n/**\n * How the kit makes the optional islands visible (`geometry`, `aria`) and puts the modeler into its\n * invalid-file state (`readOnly`).\n */\nexport interface ShowHooks<P extends PageLike = PageLike> {\n problems?: ((page: P) => Promise<void>) | undefined;\n status?: ((page: P) => Promise<void>) | undefined;\n legend?: ((page: P) => Promise<void>) | undefined;\n inspector?: ((page: P) => Promise<void>) | undefined;\n /**\n * Puts the modeler into its invalid-file state the way its host does (an invalid import): a\n * read-only canvas and the status box. The kit waits `INVALID_STATUS_DELAY_MS` afterwards.\n */\n invalid?: ((page: P) => Promise<void>) | undefined;\n}\n\n/** A show hook by name: the islands `legend`, `inspector`, `problems`, `status` and the state `invalid`. */\nexport type ShowHook = keyof ShowHooks;\n\nexport interface ShellConformanceHarness<P extends PageLike = PageLike> {\n host: ShellHost;\n /** The modes the modeler declares (static); the appearance case requests dark from `[\"light\"]`. */\n themes: readonly Theme[];\n /** Load the modeler with the shell at `size`, as the host would with `requested`; resolve once the first import is done. */\n open(page: P, context: OpenContext): Promise<void>;\n /** Tear modeler and shell down through the page's own path; `undefined` skips the cleanup case. */\n destroy?: ((page: P) => Promise<void>) | undefined;\n /** CSS selector of the shell root; default `.cd-shell`. */\n root?: string | undefined;\n /** Hooks for the islands and states the modeler has; one that is neither given nor `absent` is reported as skipped. */\n show?: ShowHooks<P> | undefined;\n /**\n * The islands and states the modeler does not have. An absent hook is not reported as skipped,\n * and `geometry` and `aria` assert that its island is never visible. Listing a hook that `show`\n * also gives fails every case that uses it.\n */\n absent?: readonly ShowHook[] | undefined;\n /** Container sizes of the geometry case; default wide 1280 × 900, narrow 720 × 700, very narrow 420 × 700. */\n sizes?: readonly Size[] | undefined;\n}\n\n/** One part of a case the harness could not feed. */\nexport interface ShellSkip {\n /**\n * The harness field that would feed it: a show hook, `destroy`, or `open` when the document it\n * opens lacks what the case needs (a shape on the canvas).\n */\n hook: ShowHook | \"destroy\" | \"open\";\n reason: string;\n}\n\nexport interface ShellCaseOutcome {\n /** What the case could not (fully) run, one entry per missing harness field. */\n skipped?: readonly ShellSkip[];\n}\n\nexport interface ShellConformanceCase {\n name: string;\n run<P extends PageLike>(page: P, harness: ShellConformanceHarness<P>): Promise<ShellCaseOutcome | void>;\n}\n\n/**\n * The cases: `geometry` (every `data-chrome` island ±1px, per host and breakpoint), `aria`\n * (roles, names, `aria-expanded`/`-controls`/`-keyshortcuts`/`-disabled`, DOM order, no positive\n * tabindex), `keys` (each chrome key acts exactly once; in the IDE host a `keydown` listener on\n * `window` never fires for a handled key; unmodified `+`/`-` never zoom; select all acts on the\n * canvas only), `create` (Enter on the first creating palette entry places one selected element in\n * the free rectangle and focuses the canvas), `readOnly` (the invalid-file lock of guide §13.5),\n * `appearance` (dark requested from a light-only modeler: nothing turns dark, `color-scheme` light\n * everywhere, the canvas surround and the palette's tool colours from the roles) and `cleanup` (after\n * `destroy` no shell element, class, attribute or key handling remains).\n */\nexport function shellConformanceCases(): ShellConformanceCase[] {\n return createCases();\n}\n\n/** Playwright's `test` (or any runner whose body receives `{ page }`). */\nexport type ShellConformanceTest<P extends PageLike = PageLike> = (\n name: string,\n body: (fixtures: { page: P }) => Promise<void>,\n) => unknown;\n\nexport interface RegisterShellConformanceOptions {\n /** Default: `console.warn`, one line per case with its skips joined by \"; \". */\n onSkip?: ((caseName: string, skips: readonly ShellSkip[]) => void) | undefined;\n}\n\n/**\n * The query string for a test page that installs the VS Code stub of\n * `@miragon/modeler-shell/testing/vscode-stub` with `stubOptionsFromSearch(location.search)`:\n * `theme=dark&kontrast=hoch`, plus the `colorTheme` setting and VS Code's reduce motion.\n */\nexport function vsCodeStubSearch(\n requested: Appearance,\n extra: { colorTheme?: ColorThemeSetting | undefined; reduceMotion?: boolean | undefined } = {},\n): string {\n const query = new URLSearchParams({ theme: requested.theme });\n if (requested.kontrast) query.set(\"kontrast\", requested.kontrast);\n if (extra.colorTheme) query.set(\"colorTheme\", extra.colorTheme);\n if (extra.reduceMotion) query.set(\"reduceMotion\", \"\");\n return query.toString();\n}\n\n/** Registers every case as `shell conformance: <name>`. */\nexport function registerShellConformance<P extends PageLike>(\n harness: ShellConformanceHarness<P>,\n test: ShellConformanceTest<P>,\n options: RegisterShellConformanceOptions = {},\n): void {\n const onSkip =\n options.onSkip ??\n ((caseName: string, skips: readonly ShellSkip[]) => {\n console.warn(\n `@miragon/modeler-shell conformance: SKIPPED \"${caseName}\" (${harness.host} host): ${skips.map((skip) => skip.reason).join(\"; \")}`,\n );\n });\n for (const conformanceCase of shellConformanceCases()) {\n test(`shell conformance: ${conformanceCase.name}`, async ({ page }) => {\n const outcome = await conformanceCase.run(page, harness);\n if (outcome?.skipped && outcome.skipped.length > 0) onSkip(conformanceCase.name, outcome.skipped);\n });\n }\n}\n"],"mappings":"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","names":["name","name","attribute","name","pressed","prevented","name","round","shape","opened","shape"]}