@base44/vite-plugin 1.0.15 → 1.0.17

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/injections/utils.ts","../../src/injections/layer-dropdown/consts.ts","../../src/injections/layer-dropdown/utils.ts","../../src/injections/layer-dropdown/dropdown-ui.ts","../../src/injections/layer-dropdown/controller.ts","../../src/capabilities/inline-edit/dom-utils.ts","../../src/capabilities/inline-edit/controller.ts","../../src/consts.ts","../../src/injections/canvas-wheel-zoom-bridge.ts","../../src/injections/page-height-bridge.ts","../../src/injections/visual-edit-agent.ts"],"sourcesContent":["const LABEL_HEIGHT = 27;\n\n/**\n * Positions an element-tag label relative to its highlighted overlay.\n *\n * Strategy (in priority order):\n * 1. If the element is near the viewport top AND tall enough (>= 2x label height),\n * place the label **inside** the element at the top-left.\n * 2. If the element is near the viewport top but too short, place the label\n * **below** the element.\n * 3. Otherwise, place the label **above** the element (default).\n *\n * For full-width elements (spanning nearly the entire viewport), the left offset\n * is nudged inward (6px) to prevent clipping against the viewport edge.\n *\n * @param label - The label div to position (style.top and style.left are set).\n * @param rect - The bounding client rect of the highlighted element.\n */\nexport function positionLabel(label: HTMLDivElement, rect: DOMRect): void {\n const nearTop = rect.top < LABEL_HEIGHT;\n const tallEnough = rect.height >= LABEL_HEIGHT * 2;\n const isFullWidth = rect.width >= window.innerWidth - 4;\n const edgeLeft = isFullWidth ? \"8px\" : \"-2px\";\n const insideLeft = isFullWidth ? \"8px\" : \"4px\";\n\n if (nearTop && tallEnough) {\n label.style.top = \"2px\";\n label.style.left = insideLeft;\n } else if (nearTop) {\n label.style.top = `${rect.height + 2}px`;\n label.style.left = edgeLeft;\n } else {\n label.style.top = `-${LABEL_HEIGHT}px`;\n label.style.left = edgeLeft;\n }\n}\n\n/** Check if an element has instrumentation attributes */\nexport function isInstrumentedElement(element: Element): boolean {\n const htmlEl = element as HTMLElement;\n return !!(\n htmlEl.dataset?.sourceLocation || htmlEl.dataset?.visualSelectorId\n );\n}\n\n/** Get the selector ID from an element's data attributes (prefers source-location) */\nexport function getElementSelectorId(element: Element): string | null {\n const htmlEl = element as HTMLElement;\n return (\n htmlEl.dataset?.sourceLocation ||\n htmlEl.dataset?.visualSelectorId ||\n null\n );\n}\n\nexport const ALLOWED_ATTRIBUTES: string[] = [\"src\"];\n\nexport const PLUGIN_ELEMENT_ATTR = \"data-vite-plugin-element\";\n\n/** Find elements by ID - first try data-source-location, fallback to data-visual-selector-id */\nexport function findElementsById(id: string | null): Element[] {\n if (!id) return [];\n const sourceElements = Array.from(\n document.querySelectorAll(`[data-source-location=\"${id}\"]`)\n );\n if (sourceElements.length > 0) {\n return sourceElements;\n }\n return Array.from(\n document.querySelectorAll(`[data-visual-selector-id=\"${id}\"]`)\n );\n}\n\n/**\n * Update element classes by visual selector ID.\n * Uses setAttribute instead of className to support both HTML and SVG elements.\n */\nexport function updateElementClasses(elements: Element[], classes: string): void {\n elements.forEach((element) => {\n element.setAttribute(\"class\", classes);\n });\n}\n\n/** Set a single attribute on all provided elements. */\nexport function updateElementAttribute(elements: Element[], attribute: string, value: string): void {\n if (!ALLOWED_ATTRIBUTES.includes(attribute)) {\n return;\n }\n\n elements.forEach((element) => {\n element.setAttribute(attribute, value);\n });\n}\n\n/** Collect attribute values from an element for a given allowlist. */\nexport function collectAllowedAttributes(element: Element, allowedAttributes: string[]): Record<string, string> {\n const attributes: Record<string, string> = {};\n for (const attr of allowedAttributes) {\n const val = element.getAttribute(attr);\n if (val !== null) {\n attributes[attr] = val;\n }\n }\n return attributes;\n}\n\n/**\n * Freeze all CSS animations and transitions on the page by injecting\n * scoped styles under `[data-visual-edit-active]` and programmatically\n * finishing (or pausing) every running animation.\n *\n * Plugin-owned elements (`[data-vite-plugin-element]`) are excluded so\n * the plugin UI stays animated.\n */\nexport function stopAnimations(): void {\n if (document.getElementById('freeze-animations')) return;\n\n document.documentElement.setAttribute('data-visual-edit-active', '');\n\n const animStyle = document.createElement('style');\n animStyle.id = 'freeze-animations';\n animStyle.textContent = `\n [data-visual-edit-active] *:not([${PLUGIN_ELEMENT_ATTR}]):not([${PLUGIN_ELEMENT_ATTR}] *),\n [data-visual-edit-active] *:not([${PLUGIN_ELEMENT_ATTR}]):not([${PLUGIN_ELEMENT_ATTR}] *)::before,\n [data-visual-edit-active] *:not([${PLUGIN_ELEMENT_ATTR}]):not([${PLUGIN_ELEMENT_ATTR}] *)::after {\n animation-play-state: paused !important;\n transition: none !important;\n }\n `;\n\n const pointerStyle = document.createElement('style');\n pointerStyle.id = 'freeze-pointer-events';\n pointerStyle.textContent = `\n [data-visual-edit-active] * { pointer-events: none !important; }\n [${PLUGIN_ELEMENT_ATTR}], [${PLUGIN_ELEMENT_ATTR}] * { pointer-events: auto !important; }\n `;\n\n const target = document.head || document.documentElement;\n target.appendChild(animStyle);\n target.appendChild(pointerStyle);\n\n document.getAnimations().forEach((a) => {\n // Skip animations on plugin UI elements\n const animTarget = (a.effect as KeyframeEffect)?.target;\n if (animTarget instanceof Element && animTarget.closest(`[${PLUGIN_ELEMENT_ATTR}]`)) return;\n\n try {\n a.finish(); // fast-forward to end state\n } catch {\n a.pause(); // finish() throws on infinite animations — pause instead\n }\n });\n}\n\n/**\n * Resume all previously frozen animations and remove the injected\n * freeze styles. Cleans up the `data-visual-edit-active` attribute\n * from `<html>` so scoped selectors no longer match.\n */\nexport function resumeAnimations(): void {\n const animStyle = document.getElementById('freeze-animations');\n if (!animStyle) return;\n\n animStyle.remove();\n document.getElementById('freeze-pointer-events')?.remove();\n document.documentElement.removeAttribute('data-visual-edit-active');\n\n document.getAnimations().forEach((a) => {\n if (a.playState === 'paused') {\n try { a.play(); } catch { /* animation target may have been removed */ }\n }\n });\n}\n\n/**\n * Hit-test the page at (`x`, `y`) and walk up the DOM to find the\n * nearest ancestor that carries instrumentation attributes\n * (`data-source-location` or `data-visual-selector-id`).\n *\n * Temporarily disables the pointer-events freeze sheet so the\n * browser's native `elementFromPoint` can reach the real target.\n */\nexport function findInstrumentedElement(x: number, y: number): Element | null {\n const pointerStyle = document.getElementById('freeze-pointer-events') as HTMLStyleElement | null;\n if (pointerStyle) pointerStyle.disabled = true;\n\n const el = document.elementFromPoint(x, y);\n\n if (pointerStyle) pointerStyle.disabled = false;\n\n return el?.closest('[data-source-location], [data-visual-selector-id]') ?? null;\n}\n\n/**\n * Resolve which element should be hovered at (`x`, `y`), skipping the\n * currently selected element. Returns the selector ID of the hovered\n * element, or `null` if the point is empty or hits the selected element.\n */\nexport function resolveHoverTarget(x: number, y: number, selectedElementId: string | null): string | null {\n const element = findInstrumentedElement(x, y);\n if (!element) return null;\n\n const selectorId = getElementSelectorId(element);\n\n if (selectorId === selectedElementId) return null;\n\n return selectorId;\n}\n","/** Style constants for the layer dropdown UI */\n\nexport const DROPDOWN_CONTAINER_STYLES: Record<string, string> = {\n position: \"absolute\",\n backgroundColor: \"#ffffff\",\n border: \"1px solid #e2e8f0\",\n borderRadius: \"6px\",\n boxShadow: \"0 4px 12px rgba(0, 0, 0, 0.15)\",\n fontSize: \"12px\",\n minWidth: \"120px\",\n maxHeight: \"200px\",\n overflowY: \"auto\",\n zIndex: \"10001\",\n padding: \"4px 0\",\n pointerEvents: \"auto\",\n};\n\nexport const DROPDOWN_ITEM_BASE_STYLES: Record<string, string> = {\n padding: \"4px 12px\",\n cursor: \"pointer\",\n color: \"#334155\",\n backgroundColor: \"transparent\",\n whiteSpace: \"nowrap\",\n lineHeight: \"1.5\",\n fontWeight: \"400\",\n};\n\nexport const DROPDOWN_ITEM_ACTIVE_COLOR = \"#526cff\";\nexport const DROPDOWN_ITEM_ACTIVE_BG = \"#DBEAFE\";\nexport const DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT = \"600\";\n\nexport const DROPDOWN_ITEM_HOVER_BG = \"#f1f5f9\";\n\nexport const DEPTH_INDENT_PX = 10;\n\n/** SVG chevron shown when dropdown is collapsed (click to expand) */\nexport const CHEVRON_COLLAPSED = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" style=\"vertical-align:middle;margin-left:4px\"><path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"/></svg>`;\n/** SVG chevron shown when dropdown is expanded (click to collapse) */\nexport const CHEVRON_EXPANDED = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" style=\"vertical-align:middle;margin-left:4px\"><path d=\"M18 15l-6-6-6 6\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"/></svg>`;\n\nexport const CHEVRON_ATTR = \"data-chevron\";\n\nexport const BASE_PADDING_PX = 12;\n\nexport const LAYER_DROPDOWN_ATTR = \"data-layer-dropdown\";\n\n/** Max instrumented ancestors to show above the selected element */\nexport const MAX_PARENT_DEPTH = 2;\n\n/** Max instrumented depth levels to show below the selected element */\nexport const MAX_CHILD_DEPTH = 2;\n","/** DOM utilities for the layer-dropdown module */\n\nimport { isInstrumentedElement, getElementSelectorId } from \"../utils.js\";\nimport { MAX_PARENT_DEPTH, MAX_CHILD_DEPTH } from \"./consts.js\";\n\nimport type { LayerInfo } from \"./types.js\";\n\n/** Apply a style map to an element */\nexport function applyStyles(element: HTMLElement, styles: Record<string, string>): void {\n for (const key of Object.keys(styles)) {\n element.style.setProperty(\n key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),\n styles[key]!\n );\n }\n}\n\n/** Display name for a layer — just the real tag name */\nexport function getLayerDisplayName(layer: LayerInfo): string {\n return layer.tagName;\n}\n\nfunction toLayerInfo(element: Element, depth?: number): LayerInfo {\n const info: LayerInfo = {\n element,\n tagName: element.tagName.toLowerCase(),\n selectorId: getElementSelectorId(element),\n };\n if (depth !== undefined) info.depth = depth;\n return info;\n}\n\n/**\n * Collect instrumented descendants up to `maxDepth` instrumented nesting levels.\n * Non-instrumented wrappers are walked through without counting toward depth.\n * Results are in DOM order.\n * When `startDepth` is provided, assigns `depth` to each item during collection.\n */\nexport function getInstrumentedDescendants(\n parent: Element,\n maxDepth: number,\n startDepth?: number\n): LayerInfo[] {\n const result: LayerInfo[] = [];\n\n function walk(el: Element, instrDepth: number): void {\n if (instrDepth > maxDepth) return;\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children[i]!;\n if (isInstrumentedElement(child)) {\n const info: LayerInfo = {\n element: child,\n tagName: child.tagName.toLowerCase(),\n selectorId: getElementSelectorId(child),\n };\n if (startDepth !== undefined) {\n info.depth = startDepth + instrDepth - 1;\n }\n result.push(info);\n walk(child, instrDepth + 1);\n } else {\n walk(child, instrDepth);\n }\n }\n }\n\n walk(parent, 1);\n return result;\n}\n\n/** Collect instrumented ancestors from selected element up to MAX_PARENT_DEPTH (outermost first). */\nfunction collectInstrumentedParents(selectedElement: Element): LayerInfo[] {\n const parents: LayerInfo[] = [];\n let current = selectedElement.parentElement;\n while (\n current &&\n current !== document.documentElement &&\n current !== document.body &&\n parents.length < MAX_PARENT_DEPTH\n ) {\n if (isInstrumentedElement(current)) {\n parents.push(toLayerInfo(current));\n }\n current = current.parentElement;\n }\n parents.reverse();\n return parents;\n}\n\n/** Add parents to chain with depth 0, 1, …; returns depth of selected (parents.length). */\nfunction addParentsToChain(chain: LayerInfo[], parents: LayerInfo[]): number {\n parents.forEach((p, i) => {\n chain.push({ ...p, depth: i });\n });\n return parents.length;\n}\n\n/** Add selected element and its descendants at the given depth. */\nfunction addSelfAndDescendantsToChain(\n chain: LayerInfo[],\n selectedElement: Element,\n selfDepth: number\n): void {\n chain.push(toLayerInfo(selectedElement, selfDepth));\n const descendants = getInstrumentedDescendants(\n selectedElement,\n MAX_CHILD_DEPTH,\n selfDepth + 1\n );\n chain.push(...descendants);\n}\n\n/** Get the innermost instrumented parent's DOM element, or null if none. */\nfunction getImmediateInstrParent(parents: LayerInfo[]): Element | null {\n return parents.at(-1)?.element ?? null;\n}\n\n/** Collect instrumented siblings of the selected element from its parent (DOM order). */\nfunction collectSiblings(parent: Element, selectedElement: Element): LayerInfo[] {\n const siblings = getInstrumentedDescendants(parent, 1);\n if (!siblings.some((s) => s.element === selectedElement)) {\n siblings.push(toLayerInfo(selectedElement));\n }\n return siblings;\n}\n\n/** Add siblings at selfDepth, expanding children only for the selected element. */\nfunction appendSiblingsWithSelected(\n chain: LayerInfo[],\n siblings: LayerInfo[],\n selectedElement: Element,\n selfDepth: number\n): void {\n const selectedSelectorId = getElementSelectorId(selectedElement);\n const seen = new Set<string>();\n for (const sibling of siblings) {\n if (sibling.element === selectedElement) {\n addSelfAndDescendantsToChain(chain, selectedElement, selfDepth);\n if (selectedSelectorId) seen.add(selectedSelectorId);\n } else {\n const id = sibling.selectorId;\n if (id != null) {\n if (id === selectedSelectorId || seen.has(id)) continue;\n seen.add(id);\n }\n chain.push({ ...sibling, depth: selfDepth });\n }\n }\n}\n\n/**\n * Build the layer chain for the dropdown:\n *\n * Parents – up to MAX_PARENT_DEPTH instrumented ancestors, outer → inner.\n * Siblings – instrumented children of the immediate parent, at the same depth.\n * Current – the selected element (highlighted), with children expanded.\n * Children – instrumented descendants within MAX_CHILD_DEPTH levels, DOM order.\n *\n * Each item carries a `depth` for visual indentation.\n */\nexport function buildLayerChain(selectedElement: Element): LayerInfo[] {\n const parents = collectInstrumentedParents(selectedElement);\n const chain: LayerInfo[] = [];\n const selfDepth = addParentsToChain(chain, parents);\n\n const instrParent = getImmediateInstrParent(parents);\n if (instrParent) {\n const siblings = collectSiblings(instrParent, selectedElement);\n appendSiblingsWithSelected(chain, siblings, selectedElement, selfDepth);\n } else {\n addSelfAndDescendantsToChain(chain, selectedElement, selfDepth);\n }\n\n return chain;\n}\n","/** Dropdown UI component for layer navigation */\n\nimport {\n DROPDOWN_CONTAINER_STYLES,\n DROPDOWN_ITEM_BASE_STYLES,\n DROPDOWN_ITEM_ACTIVE_COLOR,\n DROPDOWN_ITEM_ACTIVE_BG,\n DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT,\n DROPDOWN_ITEM_HOVER_BG,\n DEPTH_INDENT_PX,\n BASE_PADDING_PX,\n CHEVRON_COLLAPSED,\n CHEVRON_EXPANDED,\n CHEVRON_ATTR,\n LAYER_DROPDOWN_ATTR,\n} from \"./consts.js\";\nimport { applyStyles, getLayerDisplayName } from \"./utils.js\";\nimport type { LayerInfo, DropdownCallbacks } from \"./types.js\";\nimport { PLUGIN_ELEMENT_ATTR } from \"../utils.js\";\n\nlet activeDropdown: HTMLDivElement | null = null;\nlet activeLabel: HTMLDivElement | null = null;\nlet outsideMousedownHandler: ((e: MouseEvent) => void) | null = null;\nlet activeOnHoverEnd: (() => void) | null = null;\nlet activeKeydownHandler: ((e: KeyboardEvent) => void) | null = null;\n\nfunction createDropdownItem(\n layer: LayerInfo,\n isActive: boolean,\n { onSelect, onHover, onHoverEnd }: DropdownCallbacks\n): HTMLDivElement {\n const item = document.createElement(\"div\");\n item.textContent = getLayerDisplayName(layer);\n applyStyles(item, DROPDOWN_ITEM_BASE_STYLES);\n\n const depth = layer.depth ?? 0;\n if (depth > 0) {\n item.style.paddingLeft = `${BASE_PADDING_PX + depth * DEPTH_INDENT_PX}px`;\n }\n\n if (isActive) {\n item.style.color = DROPDOWN_ITEM_ACTIVE_COLOR;\n item.style.backgroundColor = DROPDOWN_ITEM_ACTIVE_BG;\n item.style.fontWeight = DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT;\n }\n\n item.addEventListener(\"mouseenter\", () => {\n if (!isActive) item.style.backgroundColor = DROPDOWN_ITEM_HOVER_BG;\n if (onHover) onHover(layer);\n });\n\n item.addEventListener(\"mouseleave\", () => {\n if (!isActive) item.style.backgroundColor = \"transparent\";\n if (onHoverEnd) onHoverEnd();\n });\n\n item.addEventListener(\"click\", (e: MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n onSelect(layer);\n });\n\n return item;\n}\n\n/** Create the dropdown DOM element with layer items */\nexport function createDropdownElement(\n layers: LayerInfo[],\n currentElement: Element | null,\n callbacks: DropdownCallbacks\n): HTMLDivElement {\n const container = document.createElement(\"div\");\n container.setAttribute(LAYER_DROPDOWN_ATTR, \"true\");\n container.setAttribute(PLUGIN_ELEMENT_ATTR, \"true\");\n applyStyles(container, DROPDOWN_CONTAINER_STYLES);\n\n layers.forEach((layer) => {\n const isActive = layer.element === currentElement;\n container.appendChild(createDropdownItem(layer, isActive, callbacks));\n });\n\n return container;\n}\n\n/** Add chevron indicator and pointer-events to the label */\nexport function enhanceLabelWithChevron(label: HTMLDivElement): void {\n if (label.querySelector(`[${CHEVRON_ATTR}]`)) return;\n\n const chevron = document.createElement(\"span\");\n chevron.setAttribute(CHEVRON_ATTR, \"true\");\n chevron.style.display = \"inline-flex\";\n chevron.innerHTML = CHEVRON_COLLAPSED;\n label.appendChild(chevron);\n\n label.style.display = \"inline-flex\";\n label.style.alignItems = \"center\";\n label.style.cursor = \"pointer\";\n label.style.userSelect = \"none\";\n label.style.whiteSpace = \"nowrap\";\n label.style.pointerEvents = \"auto\";\n label.setAttribute(LAYER_DROPDOWN_ATTR, \"true\");\n label.setAttribute(PLUGIN_ELEMENT_ATTR, \"true\");\n}\n\nfunction setupKeyboardNavigation(\n dropdown: HTMLDivElement,\n layers: LayerInfo[],\n currentElement: Element | null,\n { onSelect, onHover, onHoverEnd }: DropdownCallbacks\n): void {\n const items = Array.from(dropdown.children) as HTMLDivElement[];\n let focusedIndex = layers.findIndex((l) => l.element === currentElement);\n\n const setFocusedItem = (index: number) => {\n if (focusedIndex >= 0 && focusedIndex < items.length) {\n const prev = items[focusedIndex]!;\n if (prev.style.color !== DROPDOWN_ITEM_ACTIVE_COLOR) {\n prev.style.backgroundColor = \"transparent\";\n }\n }\n focusedIndex = index;\n if (focusedIndex >= 0 && focusedIndex < items.length) {\n const cur = items[focusedIndex]!;\n if (cur.style.color !== DROPDOWN_ITEM_ACTIVE_COLOR) {\n cur.style.backgroundColor = DROPDOWN_ITEM_HOVER_BG;\n }\n cur.scrollIntoView({ block: \"nearest\" });\n if (onHover && focusedIndex >= 0 && focusedIndex < layers.length) {\n onHover(layers[focusedIndex]!);\n }\n }\n };\n\n activeKeydownHandler = (e: KeyboardEvent) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n setFocusedItem(focusedIndex < items.length - 1 ? focusedIndex + 1 : 0);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n e.stopPropagation();\n setFocusedItem(focusedIndex > 0 ? focusedIndex - 1 : items.length - 1);\n } else if (e.key === \"Enter\" && focusedIndex >= 0 && focusedIndex < layers.length) {\n e.preventDefault();\n e.stopPropagation();\n if (onHoverEnd) onHoverEnd();\n onSelect(layers[focusedIndex]!);\n closeDropdown();\n }\n };\n document.addEventListener(\"keydown\", activeKeydownHandler, true);\n}\n\nfunction setupOutsideClickHandler(\n dropdown: HTMLDivElement,\n label: HTMLDivElement\n): void {\n let skipFirst = true;\n outsideMousedownHandler = (e: MouseEvent) => {\n if (skipFirst) { skipFirst = false; return; }\n const target = e.target as Node;\n if (!dropdown.contains(target) && target !== label) {\n closeDropdown();\n }\n };\n document.addEventListener(\"mousedown\", outsideMousedownHandler, true);\n}\n\n/** Show the dropdown below the label element */\nexport function showDropdown(\n label: HTMLDivElement,\n layers: LayerInfo[],\n currentElement: Element | null,\n callbacks: DropdownCallbacks\n): void {\n closeDropdown();\n\n const dropdown = createDropdownElement(\n layers,\n currentElement,\n {\n ...callbacks,\n onSelect: (layer) => {\n if (callbacks.onHoverEnd) callbacks.onHoverEnd();\n callbacks.onSelect(layer);\n closeDropdown();\n },\n }\n );\n\n const overlay = label.parentElement;\n if (!overlay) return;\n\n dropdown.style.top = `${label.offsetTop + label.offsetHeight + 2}px`;\n dropdown.style.left = `${label.offsetLeft}px`;\n\n overlay.appendChild(dropdown);\n activeDropdown = dropdown;\n activeLabel = label;\n const chevronEl = label.querySelector(`[${CHEVRON_ATTR}]`);\n if (chevronEl) {\n chevronEl.innerHTML = CHEVRON_EXPANDED;\n }\n activeOnHoverEnd = callbacks.onHoverEnd ?? null;\n\n setupKeyboardNavigation(dropdown, layers, currentElement, callbacks);\n setupOutsideClickHandler(dropdown, label);\n}\n\n/** Close the active dropdown and clean up listeners */\nexport function closeDropdown(): void {\n const chevronEl = activeLabel?.querySelector(`[${CHEVRON_ATTR}]`);\n if (chevronEl) {\n chevronEl.innerHTML = CHEVRON_COLLAPSED;\n }\n activeLabel = null;\n\n if (activeOnHoverEnd) {\n activeOnHoverEnd();\n activeOnHoverEnd = null;\n }\n\n if (activeDropdown && activeDropdown.parentNode) {\n activeDropdown.remove();\n }\n activeDropdown = null;\n\n if (outsideMousedownHandler) {\n document.removeEventListener(\"mousedown\", outsideMousedownHandler, true);\n outsideMousedownHandler = null;\n }\n\n if (activeKeydownHandler) {\n document.removeEventListener(\"keydown\", activeKeydownHandler, true);\n activeKeydownHandler = null;\n }\n}\n\n/** Check if a dropdown is currently visible */\nexport function isDropdownOpen(): boolean {\n return activeDropdown !== null;\n}\n","/** Controller that encapsulates layer-dropdown integration logic */\n\nimport { getElementSelectorId } from \"../utils.js\";\nimport { buildLayerChain } from \"./utils.js\";\nimport {\n enhanceLabelWithChevron,\n showDropdown,\n closeDropdown,\n isDropdownOpen,\n} from \"./dropdown-ui.js\";\nimport type { LayerInfo, LayerControllerConfig, LayerController } from \"./types.js\";\n\nexport function createLayerController(config: LayerControllerConfig): LayerController {\n let layerPreviewOverlay: HTMLDivElement | null = null;\n let escapeHandler: ((e: KeyboardEvent) => void) | null = null;\n let dropdownSourceLayer: LayerInfo | null = null;\n\n const clearLayerPreview = () => {\n if (layerPreviewOverlay && layerPreviewOverlay.parentNode) {\n layerPreviewOverlay.remove();\n }\n layerPreviewOverlay = null;\n };\n\n const showLayerPreview = (layer: LayerInfo) => {\n clearLayerPreview();\n if (getElementSelectorId(layer.element) === config.getSelectedElementId()) return;\n\n layerPreviewOverlay = config.createPreviewOverlay(layer.element);\n };\n\n const selectLayer = (layer: LayerInfo) => {\n clearLayerPreview();\n closeDropdown();\n if (escapeHandler) {\n document.removeEventListener(\"keydown\", escapeHandler, true);\n escapeHandler = null;\n }\n dropdownSourceLayer = null;\n\n const firstOverlay = config.selectElement(layer.element);\n attachToOverlay(firstOverlay, layer.element);\n };\n\n const restoreSelection = () => {\n if (escapeHandler) {\n document.removeEventListener(\"keydown\", escapeHandler, true);\n escapeHandler = null;\n }\n if (dropdownSourceLayer) {\n selectLayer(dropdownSourceLayer);\n dropdownSourceLayer = null;\n }\n };\n\n const handleLabelClick = (e: MouseEvent, label: HTMLDivElement, element: Element, layers: LayerInfo[], currentId: string | null) => {\n e.stopPropagation();\n e.preventDefault();\n if (isDropdownOpen()) {\n closeDropdown();\n restoreSelection();\n } else {\n dropdownSourceLayer = {\n element,\n tagName: element.tagName.toLowerCase(),\n selectorId: currentId,\n };\n config.onDeselect();\n\n escapeHandler = (ev: KeyboardEvent) => {\n if (ev.key === \"Escape\") {\n ev.stopPropagation();\n closeDropdown();\n restoreSelection();\n }\n };\n document.addEventListener(\"keydown\", escapeHandler, true);\n\n showDropdown(label, layers, element, { onSelect: selectLayer, onHover: showLayerPreview, onHoverEnd: clearLayerPreview });\n }\n };\n\n const attachToOverlay = (\n overlay: HTMLDivElement | undefined,\n element: Element\n ) => {\n if (!overlay) return;\n\n const label = overlay.querySelector(\"div\") as HTMLDivElement | null;\n if (!label) return;\n\n const layers = buildLayerChain(element);\n if (layers.length <= 1) return;\n\n const currentId = getElementSelectorId(element);\n enhanceLabelWithChevron(label);\n\n label.addEventListener(\"click\", (e: MouseEvent) => {\n handleLabelClick(e, label, element, layers, currentId);\n });\n };\n\n const cleanup = () => {\n clearLayerPreview();\n closeDropdown();\n };\n\n return { attachToOverlay, cleanup };\n}\n","const FOCUS_STYLE_ID = \"visual-edit-focus-styles\";\n\nconst EDITABLE_TAGS = [\n \"div\", \"p\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\",\n \"span\", \"li\", \"td\", \"a\", \"button\", \"label\",\n];\n\nexport const isStaticArrayTextElement = (element: HTMLElement): boolean => {\n return !!element.dataset.arrField;\n};\n\nconst passesStructuralChecks = (element: HTMLElement): boolean => {\n if (!EDITABLE_TAGS.includes(element.tagName.toLowerCase())) return false;\n if (!element.textContent?.trim()) return false;\n if (element.querySelector(\"img, video, canvas, svg\")) return false;\n if (element.children?.length > 0) return false;\n return true;\n};\n\nexport const injectFocusOutlineCSS = () => {\n if (document.getElementById(FOCUS_STYLE_ID)) return;\n\n const style = document.createElement(\"style\");\n style.id = FOCUS_STYLE_ID;\n style.textContent = `\n [data-selected=\"true\"][contenteditable=\"true\"]:focus {\n outline: none !important;\n }\n `;\n document.head.appendChild(style);\n};\n\nexport const removeFocusOutlineCSS = () => {\n document.getElementById(FOCUS_STYLE_ID)?.remove();\n};\n\nexport const selectText = (element: HTMLElement) => {\n const range = document.createRange();\n range.selectNodeContents(element);\n const selection = window.getSelection();\n selection?.removeAllRanges();\n selection?.addRange(range);\n};\n\nexport const isEditableTextElement = (element: Element): boolean => {\n if (!(element instanceof HTMLElement)) return false;\n if (!passesStructuralChecks(element)) return false;\n if (isStaticArrayTextElement(element)) return true;\n if (element.dataset.dynamicContent === \"true\") return false;\n return true;\n};\n\nexport const shouldEnterInlineEditingMode = (element: Element): boolean => {\n if (!(element instanceof HTMLElement) || element.dataset.selected !== \"true\") {\n return false;\n }\n return isEditableTextElement(element);\n};\n","import type { InlineEditHost, InlineEditController } from \"./types.js\";\nimport {\n injectFocusOutlineCSS,\n removeFocusOutlineCSS,\n selectText,\n shouldEnterInlineEditingMode,\n isStaticArrayTextElement,\n} from \"./dom-utils.js\";\nimport { PLUGIN_ELEMENT_ATTR } from \"../../injections/utils.js\";\n\nconst DEBOUNCE_MS = 500;\n\nexport function createInlineEditController(\n host: InlineEditHost\n): InlineEditController {\n let currentEditingElement: HTMLElement | null = null;\n let debouncedSendTimeout: ReturnType<typeof setTimeout> | null = null;\n let enabled = false;\n const listenerAbortControllers = new WeakMap<HTMLElement, AbortController>();\n\n // --- Private helpers ---\n\n const repositionOverlays = () => {\n const selectedId = host.getSelectedElementId();\n if (!selectedId) return;\n const elements = host.findElementsById(selectedId);\n const overlays = host.getSelectedOverlays();\n overlays.forEach((overlay, i) => {\n if (i < elements.length && elements[i]) {\n host.positionOverlay(overlay, elements[i]);\n }\n });\n };\n\n const reportEdit = (element: HTMLElement) => {\n const originalContent = element.dataset.originalTextContent;\n const newContent = element.textContent;\n\n const svgElement = element as unknown as SVGElement;\n const rect = element.getBoundingClientRect();\n\n const message: Record<string, unknown> = {\n type: \"inline-edit\",\n elementInfo: {\n tagName: element.tagName,\n classes:\n (svgElement.className as unknown as SVGAnimatedString)?.baseVal ||\n element.className ||\n \"\",\n visualSelectorId: host.getSelectedElementId(),\n content: newContent,\n dataSourceLocation: element.dataset.sourceLocation,\n isDynamicContent: element.dataset.dynamicContent === \"true\",\n linenumber: element.dataset.linenumber,\n filename: element.dataset.filename,\n position: {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n },\n },\n originalContent,\n newContent,\n };\n\n if (isStaticArrayTextElement(element)) {\n message.arrIndex = element.dataset.arrIndex;\n message.arrVariableName = element.dataset.arrVariableName;\n message.arrField = element.dataset.arrField;\n }\n\n window.parent.postMessage(message, \"*\");\n\n element.dataset.originalTextContent = newContent || \"\";\n };\n\n const debouncedReport = (element: HTMLElement) => {\n if (debouncedSendTimeout) clearTimeout(debouncedSendTimeout);\n debouncedSendTimeout = setTimeout(() => reportEdit(element), DEBOUNCE_MS);\n };\n\n const onTextInput = (element: HTMLElement) => {\n repositionOverlays();\n debouncedReport(element);\n };\n\n const handleInputEvent = function (this: HTMLElement) {\n onTextInput(this);\n };\n\n const makeEditable = (element: HTMLElement) => {\n injectFocusOutlineCSS();\n\n element.dataset.originalTextContent = element.textContent || \"\";\n element.dataset.originalCursor = element.style.cursor;\n element.contentEditable = \"true\";\n element.setAttribute(PLUGIN_ELEMENT_ATTR, \"true\");\n\n const abortController = new AbortController();\n listenerAbortControllers.set(element, abortController);\n element.addEventListener(\"input\", handleInputEvent, {\n signal: abortController.signal,\n });\n\n element.style.cursor = \"text\";\n selectText(element);\n setTimeout(() => {\n if (element.isConnected) {\n element.focus();\n }\n }, 0);\n };\n\n const makeNonEditable = (element: HTMLElement) => {\n const abortController = listenerAbortControllers.get(element);\n if (abortController) {\n abortController.abort();\n listenerAbortControllers.delete(element);\n }\n\n if (!element.isConnected) return;\n\n removeFocusOutlineCSS();\n element.contentEditable = \"false\";\n element.removeAttribute(PLUGIN_ELEMENT_ATTR);\n delete element.dataset.originalTextContent;\n\n if (element.dataset.originalCursor !== undefined) {\n element.style.cursor = element.dataset.originalCursor;\n delete element.dataset.originalCursor;\n }\n };\n\n // --- Public API ---\n\n return {\n get enabled() {\n return enabled;\n },\n set enabled(value: boolean) {\n enabled = value;\n },\n\n isEditing() {\n return currentEditingElement !== null;\n },\n\n getCurrentElement() {\n return currentEditingElement;\n },\n\n canEdit(element: Element) {\n return shouldEnterInlineEditingMode(element);\n },\n\n startEditing(element: HTMLElement) {\n currentEditingElement = element;\n\n host.getSelectedOverlays().forEach((o) => {\n o.style.display = \"none\";\n });\n\n makeEditable(element);\n\n window.parent.postMessage(\n {\n type: \"content-editing-started\",\n visualSelectorId: host.getSelectedElementId(),\n },\n \"*\"\n );\n },\n\n stopEditing() {\n if (!currentEditingElement) return;\n\n if (debouncedSendTimeout) {\n clearTimeout(debouncedSendTimeout);\n debouncedSendTimeout = null;\n }\n\n const element = currentEditingElement;\n makeNonEditable(element);\n\n host.getSelectedOverlays().forEach((o) => {\n o.style.display = \"\";\n });\n\n repositionOverlays();\n\n window.parent.postMessage(\n {\n type: \"content-editing-ended\",\n visualSelectorId: host.getSelectedElementId(),\n },\n \"*\"\n );\n\n currentEditingElement = null;\n },\n\n markElementsSelected(elements: Element[]) {\n elements.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.dataset.selected = \"true\";\n }\n });\n },\n\n clearSelectedMarks(elementId: string | null) {\n if (!elementId) return;\n host.findElementsById(elementId).forEach((el) => {\n if (el instanceof HTMLElement) {\n delete el.dataset.selected;\n }\n });\n },\n\n handleToggleMessage(data: { dataSourceLocation: string; inlineEditingMode: boolean }) {\n if (!enabled) return;\n\n const elements = host.findElementsById(data.dataSourceLocation);\n if (elements.length === 0 || !(elements[0] instanceof HTMLElement)) return;\n\n const element = elements[0];\n\n if (data.inlineEditingMode) {\n if (!shouldEnterInlineEditingMode(element)) return;\n\n // Select the element first if not already selected\n if (host.getSelectedElementId() !== data.dataSourceLocation) {\n this.stopEditing();\n host.clearSelection();\n this.markElementsSelected(elements);\n host.createSelectionOverlays(elements, data.dataSourceLocation);\n }\n this.startEditing(element);\n } else {\n if (currentEditingElement === element) {\n this.stopEditing();\n }\n }\n },\n\n cleanup() {\n this.stopEditing();\n },\n };\n}\n","export const DATA_COLLECTION_ID = \"data-collection-id\";\nexport const DATA_COLLECTION_ITEM_ID = \"data-collection-item-id\";\nexport const DATA_COLLECTION_ITEM_FIELD = \"data-collection-item-field\";\nexport const DATA_COLLECTION_REFERENCE = \"data-collection-reference\";\nexport const DATA_ARR_INDEX = \"data-arr-index\";\nexport const DATA_ARR_VARIABLE_NAME = \"data-arr-variable-name\";\nexport const DATA_ARR_FIELD = \"data-arr-field\";\n\nexport const ALLOWED_CUSTOM_COMPONENTS = [\"Image\", \"Link\"];\nexport const MAX_JSX_DEPTH = 10;\nexport const EXCLUDED_FIELDS = [\"children\", \"length\"];\nexport const THEME_FONT_PREVIEW_ID = \"__theme-font-preview\";\n","export function createCanvasWheelZoomBridgeController() {\n const onWheel = (event: WheelEvent): void => {\n if (!event.ctrlKey && !event.metaKey) return;\n\n event.preventDefault();\n window.parent.postMessage({\n type: \"canvas-wheel-zoom\",\n data: {\n deltaY: event.deltaY,\n deltaMode: event.deltaMode,\n clientX: event.clientX,\n clientY: event.clientY,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n },\n }, \"*\");\n };\n\n return {\n enable: (): void => {\n window.addEventListener(\"wheel\", onWheel, { capture: true, passive: false });\n },\n teardown: (): void => {\n window.removeEventListener(\"wheel\", onWheel, true);\n },\n };\n}\n","// page-height-bridge — postMessage protocol the iframe exposes to its parent.\n// Inert until the parent posts a message; no observers, rewrites, or timers\n// fire on their own.\n//\n// parent → child { type: \"freeze-vh-units\", referenceVhBase?: number }\n// Rewrites every `vh` in <style> + CSSOM to a CSS variable-backed\n// expression (kills the vh ↔ auto-resize feedback loop). Repeated calls\n// update the variable, so callers can rebase without recovering raw CSS.\n// Idempotent; covers HMR-added styles too. Fire-and-forget.\n//\n// parent → child { type: \"measure-page-height\", settleMs?: number }\n// After `settleMs` (default 2000) posts the page's measured content height\n// as `{ type: \"page-height-measured\", height }` to the requester.\n\ntype IncomingMessage = {\n type?: string;\n settleMs?: number;\n referenceVhBase?: number;\n};\n\ntype IndexableCssRule = CSSRule & {\n cssRules?: CSSRuleList;\n style?: CSSStyleDeclaration;\n};\n\ntype Debouncer = { trigger: () => void; cancel: () => void };\n\nexport type PageHeightBridgeController = {\n freezeVhUnits: (override?: number) => void;\n measurePageHeight: (origin: string, settleMs?: number) => void;\n teardown: () => void;\n};\n\nconst FALLBACK_VHBASE: number = 900;\nconst MIN_VHBASE: number = 400;\nconst DEFAULT_SETTLE_MS: number = 2000;\nconst NEUTRALIZE_DEBOUNCE_MS: number = 16;\nconst REFERENCE_VH_BASE_VAR: string = \"--base44-reference-vh-base\";\n\nconst noop: () => void = (): void => {};\n\nlet started: boolean = false;\n\n/**\n * Installs the parent-driven message listener. Returns a teardown that\n * removes the listener, disconnects any observers attached as a result of\n * `freeze-vh-units`, and clears any pending response timer. Returns a\n * no-op when bailed (already started, SSR, top window).\n */\nexport function setupPageHeightBridge(): () => void {\n if (started) return noop;\n if (typeof window === \"undefined\") return noop;\n if (window.self === window.top) return noop;\n started = true;\n\n const controller: PageHeightBridgeController = createPageHeightBridgeController();\n\n const onMessage = (event: MessageEvent): void => {\n const data: IncomingMessage | null = (event.data ?? null) as IncomingMessage | null;\n if (!data || typeof data !== \"object\") return;\n switch (data.type) {\n case \"freeze-vh-units\": {\n const override: number | undefined =\n typeof data.referenceVhBase === \"number\" ? data.referenceVhBase : undefined;\n controller.freezeVhUnits(override);\n return;\n }\n case \"measure-page-height\": {\n const settleMs: number =\n typeof data.settleMs === \"number\" ? data.settleMs : DEFAULT_SETTLE_MS;\n const origin: string =\n event.origin && event.origin !== \"null\" ? event.origin : \"*\";\n controller.measurePageHeight(origin, settleMs);\n return;\n }\n }\n };\n\n window.addEventListener(\"message\", onMessage);\n\n let torn: boolean = false;\n return (): void => {\n if (torn) return;\n torn = true;\n started = false;\n window.removeEventListener(\"message\", onMessage);\n controller.teardown();\n };\n}\n\nexport function createPageHeightBridgeController(): PageHeightBridgeController {\n let vhCleanups: Array<() => void> | null = null;\n let vhForceRun: (() => void) | null = null;\n let pendingResponse: number | undefined;\n let pendingOrigin: string = \"*\";\n\n return {\n freezeVhUnits: (override: number | undefined): void => {\n const referenceVhBase: number = resolveReferenceVhBase(override);\n setReferenceVhBase(referenceVhBase);\n if (vhCleanups) {\n vhForceRun?.();\n return;\n }\n vhCleanups = [];\n vhForceRun = startVhNeutralizer(vhCleanups);\n },\n\n // Target the requester's origin so the height isn't broadcast to anyone\n // who happens to embed us. Falls back to \"*\" when origin is unavailable\n // (jsdom default, sandboxed iframes with `null` origin).\n measurePageHeight: (origin: string, settleMs: number = DEFAULT_SETTLE_MS): void => {\n pendingOrigin = origin;\n if (pendingResponse !== undefined) window.clearTimeout(pendingResponse);\n pendingResponse = window.setTimeout((): void => {\n requestAnimationFrame((): void => {\n const height: number = measureContentHeight();\n window.parent.postMessage({ type: \"page-height-measured\", height }, pendingOrigin);\n });\n }, settleMs);\n },\n\n teardown: (): void => {\n if (vhCleanups) {\n for (const c of vhCleanups) c();\n vhCleanups = null;\n vhForceRun = null;\n }\n if (pendingResponse !== undefined) window.clearTimeout(pendingResponse);\n },\n };\n}\n\nfunction resolveReferenceVhBase(override: number | undefined): number {\n if (override !== undefined) return override;\n const detected: number = window.innerHeight || 0;\n return detected >= MIN_VHBASE ? detected : FALLBACK_VHBASE;\n}\n\nfunction setReferenceVhBase(referenceVhBase: number): void {\n document.documentElement.style.setProperty(REFERENCE_VH_BASE_VAR, `${referenceVhBase}px`);\n}\n\n// Caches keep work proportional to *new* CSS, not total CSS. <head> observer\n// catches `<style>`/`<link>` adds; per-element observers catch HMR text edits.\n// Returns a `forceRun` so the caller can re-trigger neutralization on later\n// parent requests (idempotent — already-rewritten text is skipped via the\n// processed sets).\nfunction startVhNeutralizer(cleanups: Array<() => void>): () => void {\n const VH_RE: RegExp = /(\\d+(?:\\.\\d+)?)vh\\b/g;\n const processedStyles: WeakSet<HTMLStyleElement> = new WeakSet();\n const processedSheets: WeakMap<CSSStyleSheet, number> = new WeakMap();\n const watchedStyles: WeakSet<HTMLStyleElement> = new WeakSet();\n const styleObservers: Set<MutationObserver> = new Set();\n\n const neutralize = (): void => {\n const rewrite = (input: string): string =>\n input.replace(VH_RE, (_match: string, n: string): string =>\n `calc(var(${REFERENCE_VH_BASE_VAR}) * ${formatVhFactor(n)})`,\n );\n\n document.querySelectorAll<HTMLStyleElement>(\"style\").forEach((el: HTMLStyleElement): void => {\n watchStyleEl(el);\n if (processedStyles.has(el)) return;\n processedStyles.add(el);\n const text: string | null = el.textContent;\n if (!text || text.indexOf(\"vh\") === -1) return;\n const next: string = rewrite(text);\n if (next !== text) el.textContent = next;\n });\n\n for (let i: number = 0; i < document.styleSheets.length; i++) {\n const sheet: CSSStyleSheet | undefined = document.styleSheets[i];\n if (!sheet) continue;\n let rules: CSSRuleList;\n try {\n rules = sheet.cssRules;\n } catch {\n continue; // CORS-protected\n }\n if (processedSheets.get(sheet) === rules.length) continue;\n rewriteVhInRules(rules, rewrite);\n processedSheets.set(sheet, rules.length);\n }\n };\n\n const debouncer: Debouncer = createDebouncer(neutralize, NEUTRALIZE_DEBOUNCE_MS);\n const debouncedNeutralize: () => void = debouncer.trigger;\n cleanups.push(debouncer.cancel);\n\n const watchStyleEl = (el: HTMLStyleElement): void => {\n if (watchedStyles.has(el)) return;\n watchedStyles.add(el);\n const obs: MutationObserver = new MutationObserver((): void => {\n processedStyles.delete(el);\n debouncedNeutralize();\n });\n obs.observe(el, { characterData: true, childList: true, subtree: true });\n styleObservers.add(obs);\n };\n cleanups.push((): void => {\n for (const obs of styleObservers) obs.disconnect();\n styleObservers.clear();\n });\n\n debouncedNeutralize();\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", debouncedNeutralize);\n cleanups.push((): void => document.removeEventListener(\"DOMContentLoaded\", debouncedNeutralize));\n }\n window.addEventListener(\"load\", debouncedNeutralize);\n cleanups.push((): void => window.removeEventListener(\"load\", debouncedNeutralize));\n\n const headObserver: MutationObserver = new MutationObserver((mutations: MutationRecord[]): void => {\n for (const m of mutations) {\n if (containsStylesheetNode(m.addedNodes) || containsStylesheetNode(m.removedNodes)) {\n debouncedNeutralize();\n return;\n }\n }\n });\n cleanups.push((): void => headObserver.disconnect());\n\n const attachHeadObserver = (): void => {\n if (document.head) headObserver.observe(document.head, { childList: true, subtree: false });\n };\n if (document.head) {\n attachHeadObserver();\n } else {\n document.addEventListener(\"DOMContentLoaded\", attachHeadObserver);\n cleanups.push((): void => document.removeEventListener(\"DOMContentLoaded\", attachHeadObserver));\n }\n\n return debouncedNeutralize;\n}\n\nfunction formatVhFactor(value: string): string {\n return String(Number((parseFloat(value) / 100).toFixed(6)));\n}\n\nfunction rewriteVhInRules(rules: CSSRuleList, rewrite: (value: string) => string): void {\n for (let i: number = 0; i < rules.length; i++) {\n const rule: IndexableCssRule | undefined = rules[i] as IndexableCssRule | undefined;\n if (!rule) continue;\n if (rule.cssRules) rewriteVhInRules(rule.cssRules, rewrite);\n const style: CSSStyleDeclaration | undefined = rule.style;\n if (!style) continue;\n for (let j: number = 0; j < style.length; j++) {\n const prop: string | undefined = style[j];\n if (!prop) continue;\n const value: string = style.getPropertyValue(prop);\n if (!value || value.indexOf(\"vh\") === -1) continue;\n const next: string = rewrite(value);\n if (next !== value) style.setProperty(prop, next, style.getPropertyPriority(prop));\n }\n }\n}\n\nfunction containsStylesheetNode(nodes: NodeList): boolean {\n for (let i: number = 0; i < nodes.length; i++) {\n const node: Node | undefined = nodes[i];\n if (node instanceof HTMLStyleElement || node instanceof HTMLLinkElement) return true;\n }\n return false;\n}\n\nfunction measureContentHeight(): number {\n const scrollHeight: number = Math.max(\n document.documentElement.scrollHeight,\n document.body?.scrollHeight ?? 0,\n );\n const viewportHeight: number = Math.max(\n window.innerHeight || 0,\n document.documentElement.clientHeight,\n document.body?.clientHeight ?? 0,\n );\n const contentBottom: number = measureElementContentBottom(viewportHeight);\n const referenceVhBase: number = readReferenceVhBase();\n if (contentBottom > 0) return Math.ceil(Math.max(contentBottom, referenceVhBase));\n return Math.ceil(Math.max(scrollHeight, referenceVhBase));\n}\n\nfunction readReferenceVhBase(): number {\n const value: string = document.documentElement.style.getPropertyValue(REFERENCE_VH_BASE_VAR);\n const parsed: number = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction measureElementContentBottom(viewportHeight: number): number {\n if (!document.body) return 0;\n const elements: Element[] = [document.body, ...Array.from(document.body.querySelectorAll(\"*\"))];\n const contentBottoms: WeakMap<Element, number> = new WeakMap();\n const viewportBottom: number = window.scrollY + viewportHeight;\n\n for (let i: number = elements.length - 1; i >= 0; i--) {\n const el: Element | undefined = elements[i];\n if (!el) continue;\n const childContentBottom: number = readChildrenContentBottom(el, contentBottoms);\n const rawBottom: number = readElementBottom(el);\n const selfBottom: number = isViewportStretchedContainer(rawBottom, childContentBottom, viewportBottom)\n ? 0\n : rawBottom;\n contentBottoms.set(el, Math.max(childContentBottom, selfBottom));\n }\n\n return contentBottoms.get(document.body) ?? 0;\n}\n\nfunction readChildrenContentBottom(\n el: Element,\n contentBottoms: WeakMap<Element, number>,\n): number {\n let childContentBottom: number = 0;\n for (let i: number = 0; i < el.children.length; i++) {\n const child: Element | undefined = el.children[i];\n if (!child) continue;\n childContentBottom = Math.max(childContentBottom, contentBottoms.get(child) ?? 0);\n }\n return childContentBottom;\n}\n\nfunction readElementBottom(el: Element): number {\n const computedStyle: CSSStyleDeclaration = window.getComputedStyle(el);\n if (isOutOfFlowDecoration(computedStyle)) return 0;\n const rect: DOMRect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return 0;\n return rect.bottom + window.scrollY + readMarginBottom(computedStyle);\n}\n\nfunction readMarginBottom(computedStyle: CSSStyleDeclaration): number {\n const marginBottom: number = parseFloat(computedStyle.marginBottom);\n return Number.isFinite(marginBottom) ? marginBottom : 0;\n}\n\nfunction isOutOfFlowDecoration(computedStyle: CSSStyleDeclaration): boolean {\n if (computedStyle.position === \"fixed\") return true;\n return computedStyle.position === \"absolute\" && computedStyle.pointerEvents === \"none\";\n}\n\nfunction isViewportStretchedContainer(\n elementBottom: number,\n childBottom: number,\n viewportBottom: number,\n): boolean {\n return (\n childBottom > 0 &&\n Math.abs(elementBottom - viewportBottom) <= 1 &&\n elementBottom - childBottom > 8\n );\n}\n\nfunction createDebouncer(fn: () => void, delayMs: number): Debouncer {\n let timer: number | undefined;\n return {\n trigger: (): void => {\n if (timer !== undefined) window.clearTimeout(timer);\n timer = window.setTimeout(fn, delayMs);\n },\n cancel: (): void => {\n if (timer !== undefined) {\n window.clearTimeout(timer);\n timer = undefined;\n }\n },\n };\n}\n","import { findElementsById, updateElementClasses, updateElementAttribute, collectAllowedAttributes, ALLOWED_ATTRIBUTES, getElementSelectorId, stopAnimations, resumeAnimations, findInstrumentedElement, resolveHoverTarget, positionLabel } from \"./utils.js\";\nimport { createLayerController } from \"./layer-dropdown/controller.js\";\nimport { LAYER_DROPDOWN_ATTR } from \"./layer-dropdown/consts.js\";\nimport { createInlineEditController } from \"../capabilities/inline-edit/index.js\";\nimport { THEME_FONT_PREVIEW_ID } from \"../consts.js\";\nimport { createCanvasWheelZoomBridgeController } from \"./canvas-wheel-zoom-bridge.js\";\nimport { createPageHeightBridgeController } from \"./page-height-bridge.js\";\n\nconst REPOSITION_DELAY_MS = 50;\n\nexport function setupVisualEditAgent() {\n const canvasWheelZoomBridge = createCanvasWheelZoomBridgeController();\n const pageHeightBridge = createPageHeightBridgeController();\n\n // State variables (replacing React useState/useRef)\n let isVisualEditMode = false;\n let isPopoverDragging = false;\n let isDropdownOpen = false;\n let hoverOverlays: HTMLDivElement[] = [];\n let selectedOverlays: HTMLDivElement[] = [];\n let currentHighlightedElements: Element[] = [];\n let selectedElementId: string | null = null;\n let selectedElement: Element | null = null;\n\n // Create overlay element\n const createOverlay = (isSelected = false): HTMLDivElement => {\n const overlay = document.createElement(\"div\");\n overlay.style.position = \"absolute\";\n overlay.style.pointerEvents = \"none\";\n overlay.style.transition = \"all 0.1s ease-in-out\";\n overlay.style.zIndex = \"9999\";\n\n if (isSelected) {\n overlay.style.border = \"2px solid #2563EB\";\n } else {\n overlay.style.border = \"2px solid #95a5fc\";\n overlay.style.backgroundColor = \"rgba(99, 102, 241, 0.05)\";\n }\n\n return overlay;\n };\n\n // Position overlay relative to element\n const positionOverlay = (\n overlay: HTMLDivElement,\n element: Element,\n isSelected = false\n ) => {\n if (!element || !isVisualEditMode) return;\n\n const htmlElement = element as HTMLElement;\n // Force layout recalculation\n void htmlElement.offsetWidth;\n\n const rect = element.getBoundingClientRect();\n overlay.style.top = `${rect.top + window.scrollY}px`;\n overlay.style.left = `${rect.left + window.scrollX}px`;\n overlay.style.width = `${rect.width}px`;\n overlay.style.height = `${rect.height}px`;\n\n // Check if label already exists in overlay\n let label = overlay.querySelector(\"div\") as HTMLDivElement | null;\n\n if (!label) {\n label = document.createElement(\"div\");\n label.textContent = element.tagName.toLowerCase();\n label.style.position = \"absolute\";\n label.style.left = \"-2px\";\n label.style.padding = \"2px 8px\";\n label.style.fontSize = \"11px\";\n label.style.fontWeight = isSelected ? \"500\" : \"400\";\n label.style.color = isSelected ? \"#ffffff\" : \"#526cff\";\n label.style.backgroundColor = isSelected ? \"#2563EB\" : \"#DBEAFE\";\n label.style.borderRadius = \"3px\";\n label.style.minWidth = \"24px\";\n label.style.textAlign = \"center\";\n overlay.appendChild(label);\n }\n\n positionLabel(label, rect);\n };\n\n // --- Inline edit controller ---\n const inlineEdit = createInlineEditController({\n findElementsById,\n getSelectedElementId: () => selectedElementId,\n getSelectedOverlays: () => selectedOverlays,\n positionOverlay,\n clearSelection: () => {\n inlineEdit.clearSelectedMarks(selectedElementId);\n clearSelectedOverlays();\n selectedElementId = null;\n selectedElement = null;\n },\n createSelectionOverlays: (elements, elementId) => {\n elements.forEach((el) => {\n const overlay = createOverlay(true);\n document.body.appendChild(overlay);\n selectedOverlays.push(overlay);\n positionOverlay(overlay, el, true);\n });\n selectedElementId = elementId;\n },\n });\n\n const clearSelection = () => {\n inlineEdit.clearSelectedMarks(selectedElementId);\n clearSelectedOverlays();\n selectedElementId = null;\n selectedElement = null;\n };\n\n // Clear hover overlays\n const clearHoverOverlays = () => {\n hoverOverlays.forEach((overlay) => {\n if (overlay && overlay.parentNode) {\n overlay.remove();\n }\n });\n hoverOverlays = [];\n currentHighlightedElements = [];\n };\n\n const clearSelectedOverlays = () => {\n selectedOverlays.forEach((overlay) => {\n if (overlay && overlay.parentNode) {\n overlay.remove();\n }\n });\n selectedOverlays = [];\n };\n\n const TEXT_TAGS = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'a', 'label'];\n\n const notifyElementSelected = (element: Element) => {\n const htmlElement = element as HTMLElement;\n const rect = element.getBoundingClientRect();\n const svgElement = element as SVGElement;\n const isTextElement = TEXT_TAGS.includes(element.tagName?.toLowerCase());\n\n const arrEl = htmlElement.closest(\"[data-arr-variable-name]\") as HTMLElement | null;\n const staticArrayName = arrEl?.dataset?.arrVariableName || null;\n const rawIdx = arrEl?.dataset?.arrIndex;\n const staticArrayIndex = rawIdx != null ? parseInt(rawIdx, 10) : null;\n const staticArrayField = htmlElement.dataset?.arrField || null;\n\n const collectionEl = htmlElement.closest(\"[data-collection-id]\") as HTMLElement | null;\n const itemFieldEl = htmlElement.closest(\"[data-collection-item-field]\") as HTMLElement | null;\n const itemIdEl = htmlElement.closest(\"[data-collection-item-id]\") as HTMLElement | null;\n\n window.parent.postMessage({\n type: \"element-selected\",\n tagName: element.tagName,\n classes:\n (svgElement.className as unknown as SVGAnimatedString)?.baseVal ||\n element.className ||\n \"\",\n visualSelectorId: getElementSelectorId(element),\n content: isTextElement ? htmlElement.innerText : undefined,\n dataSourceLocation: htmlElement.dataset.sourceLocation,\n isDynamicContent: htmlElement.dataset.dynamicContent === \"true\",\n linenumber: htmlElement.dataset.linenumber,\n filename: htmlElement.dataset.filename,\n position: {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n },\n attributes: collectAllowedAttributes(element, ALLOWED_ATTRIBUTES),\n isTextElement,\n staticArrayName,\n staticArrayIndex,\n staticArrayField,\n collectionId: collectionEl?.dataset?.collectionId || null,\n collectionItemField: itemFieldEl?.dataset?.collectionItemField || null,\n collectionItemId: itemIdEl?.dataset?.collectionItemId || null,\n }, \"*\");\n };\n\n // Select an element: create overlays, update state, notify parent\n const selectElement = (element: Element): HTMLDivElement | undefined => {\n const visualSelectorId = getElementSelectorId(element);\n\n clearSelectedOverlays();\n\n const elements = findElementsById(visualSelectorId || null);\n elements.forEach((el) => {\n const overlay = createOverlay(true);\n document.body.appendChild(overlay);\n selectedOverlays.push(overlay);\n positionOverlay(overlay, el, true);\n });\n\n selectedElementId = visualSelectorId || null;\n selectedElement = element;\n clearHoverOverlays();\n notifyElementSelected(element);\n\n return selectedOverlays[0];\n };\n\n const notifyDeselection = (): void => {\n selectedElementId = null;\n window.parent.postMessage({ type: \"unselect-element\" }, \"*\");\n };\n\n // Hover detection via mousemove + elementFromPoint (since app elements have pointer-events: none)\n let lastHoveredSelectorId: string | null = null;\n let pendingMouseMoveRaf: number | null = null;\n\n const clearHoverState = () => {\n clearHoverOverlays();\n lastHoveredSelectorId = null;\n };\n\n const applyHoverOverlays = (selectorId: string) => {\n const elements = findElementsById(selectorId);\n clearHoverOverlays();\n\n elements.forEach((el) => {\n const overlay = createOverlay(false);\n document.body.appendChild(overlay);\n hoverOverlays.push(overlay);\n positionOverlay(overlay, el);\n });\n\n currentHighlightedElements = elements;\n lastHoveredSelectorId = selectorId;\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!isVisualEditMode || isPopoverDragging || inlineEdit.isEditing()) return;\n\n if (pendingMouseMoveRaf !== null) return;\n pendingMouseMoveRaf = requestAnimationFrame(() => {\n pendingMouseMoveRaf = null;\n\n if (isDropdownOpen) { clearHoverState(); return; }\n\n const selectorId = resolveHoverTarget(e.clientX, e.clientY, selectedElementId);\n if (!selectorId) { clearHoverState(); return; }\n if (lastHoveredSelectorId === selectorId) return;\n\n applyHoverOverlays(selectorId);\n });\n };\n\n // Clear hover overlays when mouse leaves the viewport\n const handleMouseLeave = () => {\n if (pendingMouseMoveRaf !== null) {\n cancelAnimationFrame(pendingMouseMoveRaf);\n pendingMouseMoveRaf = null;\n }\n clearHoverState();\n };\n\n // Handle element click\n const handleElementClick = (e: MouseEvent) => {\n if (!isVisualEditMode) return;\n\n const target = e.target as Element;\n\n // Let layer dropdown clicks pass through without interference\n if (target.closest(`[${LAYER_DROPDOWN_ATTR}]`)) return;\n\n // Let clicks inside the editable element pass through to the browser\n // so the user can reposition the cursor and select text naturally.\n if (inlineEdit.enabled && target instanceof HTMLElement && target.contentEditable === \"true\") {\n return;\n }\n\n // Clicking outside the editable element exits inline editing mode.\n if (inlineEdit.isEditing()) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n inlineEdit.stopEditing();\n return;\n }\n\n // Close dropdowns when clicking anywhere in iframe if a dropdown is open\n if (isDropdownOpen) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n window.parent.postMessage({ type: \"close-dropdowns\" }, \"*\");\n return;\n }\n\n // Prevent default behavior immediately when in visual edit mode\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n const element = findInstrumentedElement(e.clientX, e.clientY);\n if (!element) {\n return;\n }\n\n const htmlElement = element as HTMLElement;\n const visualSelectorId = getElementSelectorId(element);\n\n const isAlreadySelected =\n selectedElementId === visualSelectorId &&\n htmlElement.dataset.selected === \"true\";\n\n if (isAlreadySelected && inlineEdit.enabled && inlineEdit.canEdit(htmlElement)) {\n inlineEdit.startEditing(htmlElement);\n return;\n }\n\n inlineEdit.stopEditing();\n\n if (inlineEdit.enabled) {\n inlineEdit.markElementsSelected(findElementsById(visualSelectorId));\n }\n\n const selectedOverlay = selectElement(element);\n layerController.attachToOverlay(selectedOverlay, element);\n };\n\n const unselectElement = () => {\n inlineEdit.stopEditing();\n clearSelection();\n };\n\n const updateElementClassesAndReposition = (visualSelectorId: string, classes: string) => {\n const elements = findElementsById(visualSelectorId);\n if (elements.length === 0) return;\n\n updateElementClasses(elements, classes);\n\n // Use a small delay to allow the browser to recalculate layout before repositioning\n setTimeout(() => {\n // Reposition selected overlays\n if (selectedElementId === visualSelectorId) {\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n\n // Reposition hover overlays if needed\n if (currentHighlightedElements.length > 0) {\n const hoveredElement = currentHighlightedElements[0] as HTMLElement;\n const hoveredId = hoveredElement?.dataset?.visualSelectorId;\n if (hoveredId === visualSelectorId) {\n hoverOverlays.forEach((overlay, index) => {\n if (index < currentHighlightedElements.length) {\n positionOverlay(overlay, currentHighlightedElements[index]!);\n }\n });\n }\n }\n }, REPOSITION_DELAY_MS);\n };\n\n // Update element attribute by visual selector ID\n const updateElementAttributeAndReposition = (\n visualSelectorId: string,\n attribute: string,\n value: string\n ) => {\n const elements = findElementsById(visualSelectorId);\n if (elements.length === 0) return;\n\n updateElementAttribute(elements, attribute, value);\n\n // Reposition overlays after attribute change (e.g. image src swap can affect layout)\n setTimeout(() => {\n if (selectedElementId === visualSelectorId) {\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n }, REPOSITION_DELAY_MS);\n };\n\n const updateElementContent = (visualSelectorId: string, content: string, arrIndex?: number) => {\n let elements = findElementsById(visualSelectorId);\n\n if (elements.length === 0) {\n return;\n }\n\n if (arrIndex != null) {\n elements = elements.filter(\n (el) => (el as HTMLElement).dataset.arrIndex === String(arrIndex)\n );\n }\n\n elements.forEach((element) => {\n (element as HTMLElement).innerText = content;\n });\n\n setTimeout(() => {\n if (selectedElementId === visualSelectorId) {\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n }, REPOSITION_DELAY_MS);\n };\n\n // --- Layer dropdown controller ---\n const layerController = createLayerController({\n createPreviewOverlay: (element: Element) => {\n const overlay = createOverlay(false);\n overlay.style.zIndex = \"9998\";\n document.body.appendChild(overlay);\n positionOverlay(overlay, element);\n return overlay;\n },\n getSelectedElementId: () => selectedElementId,\n selectElement,\n onDeselect: notifyDeselection,\n });\n\n // Toggle visual edit mode\n const toggleVisualEditMode = (isEnabled: boolean) => {\n isVisualEditMode = isEnabled;\n\n if (!isEnabled) {\n resumeAnimations();\n inlineEdit.stopEditing();\n clearSelection();\n layerController.cleanup();\n handleMouseLeave();\n document.body.style.cursor = \"default\";\n\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseleave\", handleMouseLeave);\n document.removeEventListener(\"click\", handleElementClick, true);\n } else {\n document.body.style.cursor = \"crosshair\";\n stopAnimations();\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseleave\", handleMouseLeave);\n document.addEventListener(\"click\", handleElementClick, true);\n }\n };\n\n // Handle scroll events to update popover position\n const handleScroll = () => {\n if (selectedElementId) {\n const element = selectedElement;\n if (element && element.isConnected) {\n const rect = element.getBoundingClientRect();\n\n const viewportHeight = window.innerHeight;\n const viewportWidth = window.innerWidth;\n const isInViewport =\n rect.top < viewportHeight &&\n rect.bottom > 0 &&\n rect.left < viewportWidth &&\n rect.right > 0;\n\n const elementPosition = {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n };\n\n window.parent.postMessage(\n {\n type: \"element-position-update\",\n position: elementPosition,\n isInViewport: isInViewport,\n visualSelectorId: selectedElementId,\n },\n \"*\"\n );\n }\n }\n };\n\n // Handle messages from parent window\n const handleMessage = (event: MessageEvent) => {\n const message = event.data;\n\n switch (message.type) {\n case \"toggle-visual-edit-mode\":\n toggleVisualEditMode(message.data.enabled);\n if (message.data.specs?.newInlineEditEnabled !== undefined) {\n inlineEdit.enabled = message.data.specs.newInlineEditEnabled;\n }\n break;\n\n case \"update-classes\":\n if (message.data && message.data.classes !== undefined) {\n updateElementClassesAndReposition(\n message.data.visualSelectorId,\n message.data.classes\n );\n } else {\n console.warn(\n \"[VisualEditAgent] Invalid update-classes message:\",\n message\n );\n }\n break;\n\n case \"update-attribute\":\n if (\n message.data &&\n message.data.visualSelectorId &&\n message.data.attribute !== undefined &&\n message.data.value !== undefined\n ) {\n updateElementAttributeAndReposition(\n message.data.visualSelectorId,\n message.data.attribute,\n message.data.value\n );\n } else {\n console.warn(\n \"[VisualEditAgent] Invalid update-attribute message:\",\n message\n );\n }\n break;\n\n case \"unselect-element\":\n unselectElement();\n break;\n\n case \"refresh-page\":\n window.location.reload();\n break;\n\n case \"update-content\":\n if (message.data && message.data.content !== undefined) {\n updateElementContent(\n message.data.visualSelectorId,\n message.data.content,\n message.data.arrIndex\n );\n } else {\n console.warn(\n \"[VisualEditAgent] Invalid update-content message:\",\n message\n );\n }\n break;\n\n case \"request-element-position\":\n if (selectedElementId && selectedElement && selectedElement.isConnected) {\n const rect = selectedElement.getBoundingClientRect();\n\n const viewportHeight = window.innerHeight;\n const viewportWidth = window.innerWidth;\n const isInViewport =\n rect.top < viewportHeight &&\n rect.bottom > 0 &&\n rect.left < viewportWidth &&\n rect.right > 0;\n\n const elementPosition = {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n };\n\n window.parent.postMessage(\n {\n type: \"element-position-update\",\n position: elementPosition,\n isInViewport: isInViewport,\n visualSelectorId: selectedElementId,\n },\n \"*\"\n );\n }\n break;\n\n case \"popover-drag-state\":\n if (message.data && message.data.isDragging !== undefined) {\n isPopoverDragging = message.data.isDragging;\n if (message.data.isDragging) {\n clearHoverOverlays();\n }\n }\n break;\n\n case \"dropdown-state\":\n if (message.data && message.data.isOpen !== undefined) {\n isDropdownOpen = message.data.isOpen;\n if (message.data.isOpen) {\n clearHoverOverlays();\n }\n }\n break;\n\n case \"update-theme-variables\":\n if (message.data?.variables) {\n const target = message.data.mode === 'dark'\n ? document.querySelector('.dark') as HTMLElement\n : document.documentElement;\n if (target) {\n for (const [name, value] of Object.entries(message.data.variables)) {\n target.style.setProperty(name, value as string);\n }\n }\n }\n break;\n\n case \"inject-font-import\":\n if (message.data?.fontUrl) {\n let fontStyle = document.getElementById(THEME_FONT_PREVIEW_ID) as HTMLStyleElement | null;\n if (!fontStyle) {\n fontStyle = document.createElement('style');\n fontStyle.id = THEME_FONT_PREVIEW_ID;\n document.head.appendChild(fontStyle);\n }\n fontStyle.textContent = `@import url('${message.data.fontUrl}');`;\n }\n break;\n\n case \"toggle-inline-edit-mode\":\n if (message.data) {\n inlineEdit.handleToggleMessage(message.data);\n }\n break;\n\n case \"freeze-vh-units\":\n pageHeightBridge.freezeVhUnits(\n typeof message.referenceVhBase === \"number\"\n ? message.referenceVhBase\n : undefined\n );\n break;\n\n case \"measure-page-height\":\n pageHeightBridge.measurePageHeight(\n event.origin && event.origin !== \"null\" ? event.origin : \"*\",\n typeof message.settleMs === \"number\" ? message.settleMs : undefined\n );\n break;\n\n case \"toggle-canvas-wheel-zoom-bridge\":\n canvasWheelZoomBridge.enable();\n break;\n\n default:\n break;\n }\n };\n\n // Handle window resize to reposition overlays\n const handleResize = () => {\n if (selectedElementId) {\n const elements = findElementsById(selectedElementId);\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n\n if (currentHighlightedElements.length > 0) {\n hoverOverlays.forEach((overlay, index) => {\n if (index < currentHighlightedElements.length) {\n positionOverlay(overlay, currentHighlightedElements[index]!);\n }\n });\n }\n };\n\n // Initialize: Add IDs to elements that don't have them but have linenumbers\n const elementsWithLineNumber = document.querySelectorAll(\n \"[data-linenumber]:not([data-visual-selector-id])\"\n );\n elementsWithLineNumber.forEach((el, index) => {\n const htmlEl = el as HTMLElement;\n const id = `visual-id-${htmlEl.dataset.filename}-${htmlEl.dataset.linenumber}-${index}`;\n htmlEl.dataset.visualSelectorId = id;\n });\n\n // Create mutation observer to detect layout changes\n const mutationObserver = new MutationObserver((mutations) => {\n const needsUpdate = mutations.some((mutation) => {\n const hasVisualId = (node: Node): boolean => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n if (el.dataset && el.dataset.visualSelectorId) {\n return true;\n }\n for (let i = 0; i < el.children.length; i++) {\n if (hasVisualId(el.children[i]!)) {\n return true;\n }\n }\n }\n return false;\n };\n\n const isLayoutChange =\n mutation.type === \"attributes\" &&\n (mutation.attributeName === \"style\" ||\n mutation.attributeName === \"class\" ||\n mutation.attributeName === \"width\" ||\n mutation.attributeName === \"height\");\n\n return isLayoutChange && hasVisualId(mutation.target);\n });\n\n if (needsUpdate) {\n setTimeout(handleResize, REPOSITION_DELAY_MS);\n }\n });\n\n // Set up event listeners\n window.addEventListener(\"message\", handleMessage);\n window.addEventListener(\"scroll\", handleScroll, true);\n document.addEventListener(\"scroll\", handleScroll, true);\n window.addEventListener(\"resize\", handleResize);\n window.addEventListener(\"scroll\", handleResize);\n\n // Start observing DOM mutations\n mutationObserver.observe(document.body, {\n attributes: true,\n childList: true,\n subtree: true,\n attributeFilter: [\"style\", \"class\", \"width\", \"height\"],\n });\n\n // Send ready message to parent\n window.parent.postMessage({ type: \"visual-edit-agent-ready\" }, \"*\");\n}\n"],"mappings":"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","names":["positionLabel","label","rect","nearTop","tallEnough","isFullWidth","edgeLeft","insideLeft","isInstrumentedElement","element","htmlEl","getElementSelectorId","ALLOWED_ATTRIBUTES","PLUGIN_ELEMENT_ATTR","findElementsById","id","sourceElements","updateElementClasses","elements","classes","updateElementAttribute","attribute","value","collectAllowedAttributes","allowedAttributes","attributes","attr","val","stopAnimations","animStyle","pointerStyle","target","a","animTarget","resumeAnimations","findInstrumentedElement","x","y","el","resolveHoverTarget","selectedElementId","selectorId","DROPDOWN_CONTAINER_STYLES","DROPDOWN_ITEM_BASE_STYLES","DROPDOWN_ITEM_ACTIVE_COLOR","DROPDOWN_ITEM_ACTIVE_BG","DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT","DROPDOWN_ITEM_HOVER_BG","DEPTH_INDENT_PX","CHEVRON_COLLAPSED","CHEVRON_EXPANDED","CHEVRON_ATTR","BASE_PADDING_PX","LAYER_DROPDOWN_ATTR","MAX_PARENT_DEPTH","MAX_CHILD_DEPTH","applyStyles","element","styles","key","m","getLayerDisplayName","layer","toLayerInfo","depth","info","getElementSelectorId","getInstrumentedDescendants","parent","maxDepth","startDepth","result","walk","el","instrDepth","i","child","isInstrumentedElement","collectInstrumentedParents","selectedElement","parents","current","MAX_PARENT_DEPTH","addParentsToChain","chain","p","addSelfAndDescendantsToChain","selfDepth","descendants","MAX_CHILD_DEPTH","getImmediateInstrParent","collectSiblings","siblings","s","appendSiblingsWithSelected","selectedSelectorId","seen","sibling","id","buildLayerChain","instrParent","activeDropdown","activeLabel","outsideMousedownHandler","activeOnHoverEnd","activeKeydownHandler","createDropdownItem","layer","isActive","onSelect","onHover","onHoverEnd","item","getLayerDisplayName","applyStyles","DROPDOWN_ITEM_BASE_STYLES","depth","BASE_PADDING_PX","DEPTH_INDENT_PX","DROPDOWN_ITEM_ACTIVE_COLOR","DROPDOWN_ITEM_ACTIVE_BG","DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT","DROPDOWN_ITEM_HOVER_BG","e","createDropdownElement","layers","currentElement","callbacks","container","LAYER_DROPDOWN_ATTR","PLUGIN_ELEMENT_ATTR","DROPDOWN_CONTAINER_STYLES","enhanceLabelWithChevron","label","CHEVRON_ATTR","chevron","CHEVRON_COLLAPSED","setupKeyboardNavigation","dropdown","items","focusedIndex","l","setFocusedItem","index","prev","cur","closeDropdown","setupOutsideClickHandler","skipFirst","target","showDropdown","overlay","chevronEl","CHEVRON_EXPANDED","isDropdownOpen","createLayerController","config","layerPreviewOverlay","escapeHandler","dropdownSourceLayer","clearLayerPreview","showLayerPreview","layer","getElementSelectorId","selectLayer","closeDropdown","firstOverlay","attachToOverlay","restoreSelection","handleLabelClick","e","label","element","layers","currentId","isDropdownOpen","ev","showDropdown","overlay","buildLayerChain","enhanceLabelWithChevron","FOCUS_STYLE_ID","EDITABLE_TAGS","isStaticArrayTextElement","element","passesStructuralChecks","injectFocusOutlineCSS","style","removeFocusOutlineCSS","selectText","range","selection","isEditableTextElement","shouldEnterInlineEditingMode","DEBOUNCE_MS","createInlineEditController","host","currentEditingElement","debouncedSendTimeout","enabled","listenerAbortControllers","repositionOverlays","selectedId","elements","overlay","i","reportEdit","element","originalContent","newContent","svgElement","rect","message","isStaticArrayTextElement","debouncedReport","onTextInput","handleInputEvent","makeEditable","injectFocusOutlineCSS","PLUGIN_ELEMENT_ATTR","abortController","selectText","makeNonEditable","removeFocusOutlineCSS","value","shouldEnterInlineEditingMode","o","el","elementId","data","THEME_FONT_PREVIEW_ID","createCanvasWheelZoomBridgeController","onWheel","event","REFERENCE_VH_BASE_VAR","createPageHeightBridgeController","vhCleanups","vhForceRun","pendingResponse","pendingOrigin","override","referenceVhBase","resolveReferenceVhBase","setReferenceVhBase","startVhNeutralizer","origin","settleMs","height","measureContentHeight","c","detected","REFERENCE_VH_BASE_VAR","cleanups","VH_RE","processedStyles","processedSheets","watchedStyles","styleObservers","debouncer","createDebouncer","rewrite","input","_match","n","formatVhFactor","el","watchStyleEl","text","next","i","sheet","rules","rewriteVhInRules","debouncedNeutralize","obs","headObserver","mutations","m","containsStylesheetNode","attachHeadObserver","value","rule","style","j","prop","nodes","node","scrollHeight","viewportHeight","contentBottom","measureElementContentBottom","readReferenceVhBase","parsed","elements","contentBottoms","viewportBottom","childContentBottom","readChildrenContentBottom","rawBottom","readElementBottom","selfBottom","isViewportStretchedContainer","child","computedStyle","isOutOfFlowDecoration","rect","readMarginBottom","marginBottom","elementBottom","childBottom","fn","delayMs","timer","REPOSITION_DELAY_MS","setupVisualEditAgent","canvasWheelZoomBridge","createCanvasWheelZoomBridgeController","pageHeightBridge","createPageHeightBridgeController","isVisualEditMode","isPopoverDragging","isDropdownOpen","hoverOverlays","selectedOverlays","currentHighlightedElements","selectedElementId","selectedElement","createOverlay","isSelected","overlay","positionOverlay","element","rect","label","positionLabel","inlineEdit","createInlineEditController","findElementsById","clearSelectedOverlays","elements","elementId","el","clearSelection","clearHoverOverlays","TEXT_TAGS","notifyElementSelected","htmlElement","svgElement","isTextElement","arrEl","staticArrayName","rawIdx","staticArrayIndex","staticArrayField","collectionEl","itemFieldEl","itemIdEl","getElementSelectorId","collectAllowedAttributes","ALLOWED_ATTRIBUTES","selectElement","visualSelectorId","notifyDeselection","lastHoveredSelectorId","pendingMouseMoveRaf","clearHoverState","applyHoverOverlays","selectorId","handleMouseMove","e","resolveHoverTarget","handleMouseLeave","handleElementClick","target","LAYER_DROPDOWN_ATTR","findInstrumentedElement","selectedOverlay","layerController","unselectElement","updateElementClassesAndReposition","classes","updateElementClasses","index","updateElementAttributeAndReposition","attribute","value","updateElementAttribute","updateElementContent","content","arrIndex","createLayerController","toggleVisualEditMode","isEnabled","stopAnimations","resumeAnimations","handleScroll","viewportHeight","viewportWidth","isInViewport","elementPosition","handleMessage","event","message","name","fontStyle","THEME_FONT_PREVIEW_ID","handleResize","htmlEl","id","mutationObserver","mutations","mutation","hasVisualId","node","i"]}
1
+ {"version":3,"sources":["../../src/injections/utils.ts","../../src/injections/layer-dropdown/consts.ts","../../src/injections/layer-dropdown/utils.ts","../../src/injections/layer-dropdown/dropdown-ui.ts","../../src/injections/layer-dropdown/controller.ts","../../src/capabilities/inline-edit/dom-utils.ts","../../src/capabilities/inline-edit/controller.ts","../../src/consts.ts","../../src/injections/canvas-wheel-zoom-bridge.ts","../../src/injections/page-height-bridge.ts","../../src/injections/visual-edit-agent.ts"],"sourcesContent":["const LABEL_HEIGHT = 27;\n\n/**\n * Positions an element-tag label relative to its highlighted overlay.\n *\n * Strategy (in priority order):\n * 1. If the element is near the viewport top AND tall enough (>= 2x label height),\n * place the label **inside** the element at the top-left.\n * 2. If the element is near the viewport top but too short, place the label\n * **below** the element.\n * 3. Otherwise, place the label **above** the element (default).\n *\n * For full-width elements (spanning nearly the entire viewport), the left offset\n * is nudged inward (6px) to prevent clipping against the viewport edge.\n *\n * @param label - The label div to position (style.top and style.left are set).\n * @param rect - The bounding client rect of the highlighted element.\n */\nexport function positionLabel(label: HTMLDivElement, rect: DOMRect): void {\n const nearTop = rect.top < LABEL_HEIGHT;\n const tallEnough = rect.height >= LABEL_HEIGHT * 2;\n const isFullWidth = rect.width >= window.innerWidth - 4;\n const edgeLeft = isFullWidth ? \"8px\" : \"-2px\";\n const insideLeft = isFullWidth ? \"8px\" : \"4px\";\n\n if (nearTop && tallEnough) {\n label.style.top = \"2px\";\n label.style.left = insideLeft;\n } else if (nearTop) {\n label.style.top = `${rect.height + 2}px`;\n label.style.left = edgeLeft;\n } else {\n label.style.top = `-${LABEL_HEIGHT}px`;\n label.style.left = edgeLeft;\n }\n}\n\n/** Check if an element has instrumentation attributes */\nexport function isInstrumentedElement(element: Element): boolean {\n const htmlEl = element as HTMLElement;\n return !!(\n htmlEl.dataset?.sourceLocation || htmlEl.dataset?.visualSelectorId\n );\n}\n\n/** Get the selector ID from an element's data attributes (prefers source-location) */\nexport function getElementSelectorId(element: Element): string | null {\n const htmlEl = element as HTMLElement;\n return (\n htmlEl.dataset?.sourceLocation ||\n htmlEl.dataset?.visualSelectorId ||\n null\n );\n}\n\nexport const ALLOWED_ATTRIBUTES: string[] = [\"src\"];\n\nexport const PLUGIN_ELEMENT_ATTR = \"data-vite-plugin-element\";\n\n/** Find elements by ID - first try data-source-location, fallback to data-visual-selector-id */\nexport function findElementsById(id: string | null): Element[] {\n if (!id) return [];\n const sourceElements = Array.from(\n document.querySelectorAll(`[data-source-location=\"${id}\"]`)\n );\n if (sourceElements.length > 0) {\n return sourceElements;\n }\n return Array.from(\n document.querySelectorAll(`[data-visual-selector-id=\"${id}\"]`)\n );\n}\n\n/**\n * Update element classes by visual selector ID.\n * Uses setAttribute instead of className to support both HTML and SVG elements.\n */\nexport function updateElementClasses(elements: Element[], classes: string): void {\n elements.forEach((element) => {\n element.setAttribute(\"class\", classes);\n });\n}\n\n/** Set a single attribute on all provided elements. */\nexport function updateElementAttribute(elements: Element[], attribute: string, value: string): void {\n if (!ALLOWED_ATTRIBUTES.includes(attribute)) {\n return;\n }\n\n elements.forEach((element) => {\n element.setAttribute(attribute, value);\n });\n}\n\n/** Collect attribute values from an element for a given allowlist. */\nexport function collectAllowedAttributes(element: Element, allowedAttributes: string[]): Record<string, string> {\n const attributes: Record<string, string> = {};\n for (const attr of allowedAttributes) {\n const val = element.getAttribute(attr);\n if (val !== null) {\n attributes[attr] = val;\n }\n }\n return attributes;\n}\n\n/**\n * Freeze all CSS animations and transitions on the page by injecting\n * scoped styles under `[data-visual-edit-active]` and programmatically\n * finishing (or pausing) every running animation.\n *\n * Plugin-owned elements (`[data-vite-plugin-element]`) are excluded so\n * the plugin UI stays animated.\n */\nexport function stopAnimations(): void {\n if (document.getElementById('freeze-animations')) return;\n\n document.documentElement.setAttribute('data-visual-edit-active', '');\n\n const animStyle = document.createElement('style');\n animStyle.id = 'freeze-animations';\n animStyle.textContent = `\n [data-visual-edit-active] *:not([${PLUGIN_ELEMENT_ATTR}]):not([${PLUGIN_ELEMENT_ATTR}] *),\n [data-visual-edit-active] *:not([${PLUGIN_ELEMENT_ATTR}]):not([${PLUGIN_ELEMENT_ATTR}] *)::before,\n [data-visual-edit-active] *:not([${PLUGIN_ELEMENT_ATTR}]):not([${PLUGIN_ELEMENT_ATTR}] *)::after {\n animation-play-state: paused !important;\n transition: none !important;\n }\n `;\n\n const pointerStyle = document.createElement('style');\n pointerStyle.id = 'freeze-pointer-events';\n pointerStyle.textContent = `\n [data-visual-edit-active] * { pointer-events: none !important; }\n [${PLUGIN_ELEMENT_ATTR}], [${PLUGIN_ELEMENT_ATTR}] * { pointer-events: auto !important; }\n `;\n\n const target = document.head || document.documentElement;\n target.appendChild(animStyle);\n target.appendChild(pointerStyle);\n\n document.getAnimations().forEach((a) => {\n // Skip animations on plugin UI elements\n const animTarget = (a.effect as KeyframeEffect)?.target;\n if (animTarget instanceof Element && animTarget.closest(`[${PLUGIN_ELEMENT_ATTR}]`)) return;\n\n try {\n a.finish(); // fast-forward to end state\n } catch {\n a.pause(); // finish() throws on infinite animations — pause instead\n }\n });\n}\n\n/**\n * Resume all previously frozen animations and remove the injected\n * freeze styles. Cleans up the `data-visual-edit-active` attribute\n * from `<html>` so scoped selectors no longer match.\n */\nexport function resumeAnimations(): void {\n const animStyle = document.getElementById('freeze-animations');\n if (!animStyle) return;\n\n animStyle.remove();\n document.getElementById('freeze-pointer-events')?.remove();\n document.documentElement.removeAttribute('data-visual-edit-active');\n\n document.getAnimations().forEach((a) => {\n if (a.playState === 'paused') {\n try { a.play(); } catch { /* animation target may have been removed */ }\n }\n });\n}\n\n/**\n * Hit-test the page at (`x`, `y`) and walk up the DOM to find the\n * nearest ancestor that carries instrumentation attributes\n * (`data-source-location` or `data-visual-selector-id`).\n *\n * Temporarily disables the pointer-events freeze sheet so the\n * browser's native `elementFromPoint` can reach the real target.\n */\nexport function findInstrumentedElement(x: number, y: number): Element | null {\n const pointerStyle = document.getElementById('freeze-pointer-events') as HTMLStyleElement | null;\n if (pointerStyle) pointerStyle.disabled = true;\n\n const el = document.elementFromPoint(x, y);\n\n if (pointerStyle) pointerStyle.disabled = false;\n\n return el?.closest('[data-source-location], [data-visual-selector-id]') ?? null;\n}\n\n/**\n * Resolve which element should be hovered at (`x`, `y`), skipping the\n * currently selected element. Returns the selector ID of the hovered\n * element, or `null` if the point is empty or hits the selected element.\n */\nexport function resolveHoverTarget(x: number, y: number, selectedElementId: string | null): string | null {\n const element = findInstrumentedElement(x, y);\n if (!element) return null;\n\n const selectorId = getElementSelectorId(element);\n\n if (selectorId === selectedElementId) return null;\n\n return selectorId;\n}\n","/** Style constants for the layer dropdown UI */\n\nexport const DROPDOWN_CONTAINER_STYLES: Record<string, string> = {\n position: \"absolute\",\n backgroundColor: \"#ffffff\",\n border: \"1px solid #e2e8f0\",\n borderRadius: \"6px\",\n boxShadow: \"0 4px 12px rgba(0, 0, 0, 0.15)\",\n fontSize: \"12px\",\n minWidth: \"120px\",\n maxHeight: \"200px\",\n overflowY: \"auto\",\n zIndex: \"10001\",\n padding: \"4px 0\",\n pointerEvents: \"auto\",\n};\n\nexport const DROPDOWN_ITEM_BASE_STYLES: Record<string, string> = {\n padding: \"4px 12px\",\n cursor: \"pointer\",\n color: \"#334155\",\n backgroundColor: \"transparent\",\n whiteSpace: \"nowrap\",\n lineHeight: \"1.5\",\n fontWeight: \"400\",\n};\n\nexport const DROPDOWN_ITEM_ACTIVE_COLOR = \"#526cff\";\nexport const DROPDOWN_ITEM_ACTIVE_BG = \"#DBEAFE\";\nexport const DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT = \"600\";\n\nexport const DROPDOWN_ITEM_HOVER_BG = \"#f1f5f9\";\n\nexport const DEPTH_INDENT_PX = 10;\n\n/** SVG chevron shown when dropdown is collapsed (click to expand) */\nexport const CHEVRON_COLLAPSED = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" style=\"vertical-align:middle;margin-left:4px\"><path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"/></svg>`;\n/** SVG chevron shown when dropdown is expanded (click to collapse) */\nexport const CHEVRON_EXPANDED = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" style=\"vertical-align:middle;margin-left:4px\"><path d=\"M18 15l-6-6-6 6\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\"/></svg>`;\n\nexport const CHEVRON_ATTR = \"data-chevron\";\n\nexport const BASE_PADDING_PX = 12;\n\nexport const LAYER_DROPDOWN_ATTR = \"data-layer-dropdown\";\n\n/** Max instrumented ancestors to show above the selected element */\nexport const MAX_PARENT_DEPTH = 2;\n\n/** Max instrumented depth levels to show below the selected element */\nexport const MAX_CHILD_DEPTH = 2;\n","/** DOM utilities for the layer-dropdown module */\n\nimport { isInstrumentedElement, getElementSelectorId } from \"../utils.js\";\nimport { MAX_PARENT_DEPTH, MAX_CHILD_DEPTH } from \"./consts.js\";\n\nimport type { LayerInfo } from \"./types.js\";\n\n/** Apply a style map to an element */\nexport function applyStyles(element: HTMLElement, styles: Record<string, string>): void {\n for (const key of Object.keys(styles)) {\n element.style.setProperty(\n key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),\n styles[key]!\n );\n }\n}\n\n/** Display name for a layer — just the real tag name */\nexport function getLayerDisplayName(layer: LayerInfo): string {\n return layer.tagName;\n}\n\nfunction toLayerInfo(element: Element, depth?: number): LayerInfo {\n const info: LayerInfo = {\n element,\n tagName: element.tagName.toLowerCase(),\n selectorId: getElementSelectorId(element),\n };\n if (depth !== undefined) info.depth = depth;\n return info;\n}\n\n/**\n * Collect instrumented descendants up to `maxDepth` instrumented nesting levels.\n * Non-instrumented wrappers are walked through without counting toward depth.\n * Results are in DOM order.\n * When `startDepth` is provided, assigns `depth` to each item during collection.\n */\nexport function getInstrumentedDescendants(\n parent: Element,\n maxDepth: number,\n startDepth?: number\n): LayerInfo[] {\n const result: LayerInfo[] = [];\n\n function walk(el: Element, instrDepth: number): void {\n if (instrDepth > maxDepth) return;\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children[i]!;\n if (isInstrumentedElement(child)) {\n const info: LayerInfo = {\n element: child,\n tagName: child.tagName.toLowerCase(),\n selectorId: getElementSelectorId(child),\n };\n if (startDepth !== undefined) {\n info.depth = startDepth + instrDepth - 1;\n }\n result.push(info);\n walk(child, instrDepth + 1);\n } else {\n walk(child, instrDepth);\n }\n }\n }\n\n walk(parent, 1);\n return result;\n}\n\n/** Collect instrumented ancestors from selected element up to MAX_PARENT_DEPTH (outermost first). */\nfunction collectInstrumentedParents(selectedElement: Element): LayerInfo[] {\n const parents: LayerInfo[] = [];\n let current = selectedElement.parentElement;\n while (\n current &&\n current !== document.documentElement &&\n current !== document.body &&\n parents.length < MAX_PARENT_DEPTH\n ) {\n if (isInstrumentedElement(current)) {\n parents.push(toLayerInfo(current));\n }\n current = current.parentElement;\n }\n parents.reverse();\n return parents;\n}\n\n/** Add parents to chain with depth 0, 1, …; returns depth of selected (parents.length). */\nfunction addParentsToChain(chain: LayerInfo[], parents: LayerInfo[]): number {\n parents.forEach((p, i) => {\n chain.push({ ...p, depth: i });\n });\n return parents.length;\n}\n\n/** Add selected element and its descendants at the given depth. */\nfunction addSelfAndDescendantsToChain(\n chain: LayerInfo[],\n selectedElement: Element,\n selfDepth: number\n): void {\n chain.push(toLayerInfo(selectedElement, selfDepth));\n const descendants = getInstrumentedDescendants(\n selectedElement,\n MAX_CHILD_DEPTH,\n selfDepth + 1\n );\n chain.push(...descendants);\n}\n\n/** Get the innermost instrumented parent's DOM element, or null if none. */\nfunction getImmediateInstrParent(parents: LayerInfo[]): Element | null {\n return parents.at(-1)?.element ?? null;\n}\n\n/** Collect instrumented siblings of the selected element from its parent (DOM order). */\nfunction collectSiblings(parent: Element, selectedElement: Element): LayerInfo[] {\n const siblings = getInstrumentedDescendants(parent, 1);\n if (!siblings.some((s) => s.element === selectedElement)) {\n siblings.push(toLayerInfo(selectedElement));\n }\n return siblings;\n}\n\n/** Add siblings at selfDepth, expanding children only for the selected element. */\nfunction appendSiblingsWithSelected(\n chain: LayerInfo[],\n siblings: LayerInfo[],\n selectedElement: Element,\n selfDepth: number\n): void {\n const selectedSelectorId = getElementSelectorId(selectedElement);\n const seen = new Set<string>();\n for (const sibling of siblings) {\n if (sibling.element === selectedElement) {\n addSelfAndDescendantsToChain(chain, selectedElement, selfDepth);\n if (selectedSelectorId) seen.add(selectedSelectorId);\n } else {\n const id = sibling.selectorId;\n if (id != null) {\n if (id === selectedSelectorId || seen.has(id)) continue;\n seen.add(id);\n }\n chain.push({ ...sibling, depth: selfDepth });\n }\n }\n}\n\n/**\n * Build the layer chain for the dropdown:\n *\n * Parents – up to MAX_PARENT_DEPTH instrumented ancestors, outer → inner.\n * Siblings – instrumented children of the immediate parent, at the same depth.\n * Current – the selected element (highlighted), with children expanded.\n * Children – instrumented descendants within MAX_CHILD_DEPTH levels, DOM order.\n *\n * Each item carries a `depth` for visual indentation.\n */\nexport function buildLayerChain(selectedElement: Element): LayerInfo[] {\n const parents = collectInstrumentedParents(selectedElement);\n const chain: LayerInfo[] = [];\n const selfDepth = addParentsToChain(chain, parents);\n\n const instrParent = getImmediateInstrParent(parents);\n if (instrParent) {\n const siblings = collectSiblings(instrParent, selectedElement);\n appendSiblingsWithSelected(chain, siblings, selectedElement, selfDepth);\n } else {\n addSelfAndDescendantsToChain(chain, selectedElement, selfDepth);\n }\n\n return chain;\n}\n","/** Dropdown UI component for layer navigation */\n\nimport {\n DROPDOWN_CONTAINER_STYLES,\n DROPDOWN_ITEM_BASE_STYLES,\n DROPDOWN_ITEM_ACTIVE_COLOR,\n DROPDOWN_ITEM_ACTIVE_BG,\n DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT,\n DROPDOWN_ITEM_HOVER_BG,\n DEPTH_INDENT_PX,\n BASE_PADDING_PX,\n CHEVRON_COLLAPSED,\n CHEVRON_EXPANDED,\n CHEVRON_ATTR,\n LAYER_DROPDOWN_ATTR,\n} from \"./consts.js\";\nimport { applyStyles, getLayerDisplayName } from \"./utils.js\";\nimport type { LayerInfo, DropdownCallbacks } from \"./types.js\";\nimport { PLUGIN_ELEMENT_ATTR } from \"../utils.js\";\n\nlet activeDropdown: HTMLDivElement | null = null;\nlet activeLabel: HTMLDivElement | null = null;\nlet outsideMousedownHandler: ((e: MouseEvent) => void) | null = null;\nlet activeOnHoverEnd: (() => void) | null = null;\nlet activeKeydownHandler: ((e: KeyboardEvent) => void) | null = null;\n\nfunction createDropdownItem(\n layer: LayerInfo,\n isActive: boolean,\n { onSelect, onHover, onHoverEnd }: DropdownCallbacks\n): HTMLDivElement {\n const item = document.createElement(\"div\");\n item.textContent = getLayerDisplayName(layer);\n applyStyles(item, DROPDOWN_ITEM_BASE_STYLES);\n\n const depth = layer.depth ?? 0;\n if (depth > 0) {\n item.style.paddingLeft = `${BASE_PADDING_PX + depth * DEPTH_INDENT_PX}px`;\n }\n\n if (isActive) {\n item.style.color = DROPDOWN_ITEM_ACTIVE_COLOR;\n item.style.backgroundColor = DROPDOWN_ITEM_ACTIVE_BG;\n item.style.fontWeight = DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT;\n }\n\n item.addEventListener(\"mouseenter\", () => {\n if (!isActive) item.style.backgroundColor = DROPDOWN_ITEM_HOVER_BG;\n if (onHover) onHover(layer);\n });\n\n item.addEventListener(\"mouseleave\", () => {\n if (!isActive) item.style.backgroundColor = \"transparent\";\n if (onHoverEnd) onHoverEnd();\n });\n\n item.addEventListener(\"click\", (e: MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n onSelect(layer);\n });\n\n return item;\n}\n\n/** Create the dropdown DOM element with layer items */\nexport function createDropdownElement(\n layers: LayerInfo[],\n currentElement: Element | null,\n callbacks: DropdownCallbacks\n): HTMLDivElement {\n const container = document.createElement(\"div\");\n container.setAttribute(LAYER_DROPDOWN_ATTR, \"true\");\n container.setAttribute(PLUGIN_ELEMENT_ATTR, \"true\");\n applyStyles(container, DROPDOWN_CONTAINER_STYLES);\n\n layers.forEach((layer) => {\n const isActive = layer.element === currentElement;\n container.appendChild(createDropdownItem(layer, isActive, callbacks));\n });\n\n return container;\n}\n\n/** Add chevron indicator and pointer-events to the label */\nexport function enhanceLabelWithChevron(label: HTMLDivElement): void {\n if (label.querySelector(`[${CHEVRON_ATTR}]`)) return;\n\n const chevron = document.createElement(\"span\");\n chevron.setAttribute(CHEVRON_ATTR, \"true\");\n chevron.style.display = \"inline-flex\";\n chevron.innerHTML = CHEVRON_COLLAPSED;\n label.appendChild(chevron);\n\n label.style.display = \"inline-flex\";\n label.style.alignItems = \"center\";\n label.style.cursor = \"pointer\";\n label.style.userSelect = \"none\";\n label.style.whiteSpace = \"nowrap\";\n label.style.pointerEvents = \"auto\";\n label.setAttribute(LAYER_DROPDOWN_ATTR, \"true\");\n label.setAttribute(PLUGIN_ELEMENT_ATTR, \"true\");\n}\n\nfunction setupKeyboardNavigation(\n dropdown: HTMLDivElement,\n layers: LayerInfo[],\n currentElement: Element | null,\n { onSelect, onHover, onHoverEnd }: DropdownCallbacks\n): void {\n const items = Array.from(dropdown.children) as HTMLDivElement[];\n let focusedIndex = layers.findIndex((l) => l.element === currentElement);\n\n const setFocusedItem = (index: number) => {\n if (focusedIndex >= 0 && focusedIndex < items.length) {\n const prev = items[focusedIndex]!;\n if (prev.style.color !== DROPDOWN_ITEM_ACTIVE_COLOR) {\n prev.style.backgroundColor = \"transparent\";\n }\n }\n focusedIndex = index;\n if (focusedIndex >= 0 && focusedIndex < items.length) {\n const cur = items[focusedIndex]!;\n if (cur.style.color !== DROPDOWN_ITEM_ACTIVE_COLOR) {\n cur.style.backgroundColor = DROPDOWN_ITEM_HOVER_BG;\n }\n cur.scrollIntoView({ block: \"nearest\" });\n if (onHover && focusedIndex >= 0 && focusedIndex < layers.length) {\n onHover(layers[focusedIndex]!);\n }\n }\n };\n\n activeKeydownHandler = (e: KeyboardEvent) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n setFocusedItem(focusedIndex < items.length - 1 ? focusedIndex + 1 : 0);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n e.stopPropagation();\n setFocusedItem(focusedIndex > 0 ? focusedIndex - 1 : items.length - 1);\n } else if (e.key === \"Enter\" && focusedIndex >= 0 && focusedIndex < layers.length) {\n e.preventDefault();\n e.stopPropagation();\n if (onHoverEnd) onHoverEnd();\n onSelect(layers[focusedIndex]!);\n closeDropdown();\n }\n };\n document.addEventListener(\"keydown\", activeKeydownHandler, true);\n}\n\nfunction setupOutsideClickHandler(\n dropdown: HTMLDivElement,\n label: HTMLDivElement\n): void {\n let skipFirst = true;\n outsideMousedownHandler = (e: MouseEvent) => {\n if (skipFirst) { skipFirst = false; return; }\n const target = e.target as Node;\n if (!dropdown.contains(target) && target !== label) {\n closeDropdown();\n }\n };\n document.addEventListener(\"mousedown\", outsideMousedownHandler, true);\n}\n\n/** Show the dropdown below the label element */\nexport function showDropdown(\n label: HTMLDivElement,\n layers: LayerInfo[],\n currentElement: Element | null,\n callbacks: DropdownCallbacks\n): void {\n closeDropdown();\n\n const dropdown = createDropdownElement(\n layers,\n currentElement,\n {\n ...callbacks,\n onSelect: (layer) => {\n if (callbacks.onHoverEnd) callbacks.onHoverEnd();\n callbacks.onSelect(layer);\n closeDropdown();\n },\n }\n );\n\n const overlay = label.parentElement;\n if (!overlay) return;\n\n dropdown.style.top = `${label.offsetTop + label.offsetHeight + 2}px`;\n dropdown.style.left = `${label.offsetLeft}px`;\n\n overlay.appendChild(dropdown);\n activeDropdown = dropdown;\n activeLabel = label;\n const chevronEl = label.querySelector(`[${CHEVRON_ATTR}]`);\n if (chevronEl) {\n chevronEl.innerHTML = CHEVRON_EXPANDED;\n }\n activeOnHoverEnd = callbacks.onHoverEnd ?? null;\n\n setupKeyboardNavigation(dropdown, layers, currentElement, callbacks);\n setupOutsideClickHandler(dropdown, label);\n}\n\n/** Close the active dropdown and clean up listeners */\nexport function closeDropdown(): void {\n const chevronEl = activeLabel?.querySelector(`[${CHEVRON_ATTR}]`);\n if (chevronEl) {\n chevronEl.innerHTML = CHEVRON_COLLAPSED;\n }\n activeLabel = null;\n\n if (activeOnHoverEnd) {\n activeOnHoverEnd();\n activeOnHoverEnd = null;\n }\n\n if (activeDropdown && activeDropdown.parentNode) {\n activeDropdown.remove();\n }\n activeDropdown = null;\n\n if (outsideMousedownHandler) {\n document.removeEventListener(\"mousedown\", outsideMousedownHandler, true);\n outsideMousedownHandler = null;\n }\n\n if (activeKeydownHandler) {\n document.removeEventListener(\"keydown\", activeKeydownHandler, true);\n activeKeydownHandler = null;\n }\n}\n\n/** Check if a dropdown is currently visible */\nexport function isDropdownOpen(): boolean {\n return activeDropdown !== null;\n}\n","/** Controller that encapsulates layer-dropdown integration logic */\n\nimport { getElementSelectorId } from \"../utils.js\";\nimport { buildLayerChain } from \"./utils.js\";\nimport {\n enhanceLabelWithChevron,\n showDropdown,\n closeDropdown,\n isDropdownOpen,\n} from \"./dropdown-ui.js\";\nimport type { LayerInfo, LayerControllerConfig, LayerController } from \"./types.js\";\n\nexport function createLayerController(config: LayerControllerConfig): LayerController {\n let layerPreviewOverlay: HTMLDivElement | null = null;\n let escapeHandler: ((e: KeyboardEvent) => void) | null = null;\n let dropdownSourceLayer: LayerInfo | null = null;\n\n const clearLayerPreview = () => {\n if (layerPreviewOverlay && layerPreviewOverlay.parentNode) {\n layerPreviewOverlay.remove();\n }\n layerPreviewOverlay = null;\n };\n\n const showLayerPreview = (layer: LayerInfo) => {\n clearLayerPreview();\n if (getElementSelectorId(layer.element) === config.getSelectedElementId()) return;\n\n layerPreviewOverlay = config.createPreviewOverlay(layer.element);\n };\n\n const selectLayer = (layer: LayerInfo) => {\n clearLayerPreview();\n closeDropdown();\n if (escapeHandler) {\n document.removeEventListener(\"keydown\", escapeHandler, true);\n escapeHandler = null;\n }\n dropdownSourceLayer = null;\n\n const firstOverlay = config.selectElement(layer.element);\n attachToOverlay(firstOverlay, layer.element);\n };\n\n const restoreSelection = () => {\n if (escapeHandler) {\n document.removeEventListener(\"keydown\", escapeHandler, true);\n escapeHandler = null;\n }\n if (dropdownSourceLayer) {\n selectLayer(dropdownSourceLayer);\n dropdownSourceLayer = null;\n }\n };\n\n const handleLabelClick = (e: MouseEvent, label: HTMLDivElement, element: Element, layers: LayerInfo[], currentId: string | null) => {\n e.stopPropagation();\n e.preventDefault();\n if (isDropdownOpen()) {\n closeDropdown();\n restoreSelection();\n } else {\n dropdownSourceLayer = {\n element,\n tagName: element.tagName.toLowerCase(),\n selectorId: currentId,\n };\n config.onDeselect();\n\n escapeHandler = (ev: KeyboardEvent) => {\n if (ev.key === \"Escape\") {\n ev.stopPropagation();\n closeDropdown();\n restoreSelection();\n }\n };\n document.addEventListener(\"keydown\", escapeHandler, true);\n\n showDropdown(label, layers, element, { onSelect: selectLayer, onHover: showLayerPreview, onHoverEnd: clearLayerPreview });\n }\n };\n\n const attachToOverlay = (\n overlay: HTMLDivElement | undefined,\n element: Element\n ) => {\n if (!overlay) return;\n\n const label = overlay.querySelector(\"div\") as HTMLDivElement | null;\n if (!label) return;\n\n const layers = buildLayerChain(element);\n if (layers.length <= 1) return;\n\n const currentId = getElementSelectorId(element);\n enhanceLabelWithChevron(label);\n\n label.addEventListener(\"click\", (e: MouseEvent) => {\n handleLabelClick(e, label, element, layers, currentId);\n });\n };\n\n const cleanup = () => {\n clearLayerPreview();\n closeDropdown();\n };\n\n return { attachToOverlay, cleanup };\n}\n","const FOCUS_STYLE_ID = \"visual-edit-focus-styles\";\n\nconst EDITABLE_TAGS = [\n \"div\", \"p\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\",\n \"span\", \"li\", \"td\", \"a\", \"button\", \"label\",\n];\n\nexport const isStaticArrayTextElement = (element: HTMLElement): boolean => {\n return !!element.dataset.arrField;\n};\n\nconst passesStructuralChecks = (element: HTMLElement): boolean => {\n if (!EDITABLE_TAGS.includes(element.tagName.toLowerCase())) return false;\n if (!element.textContent?.trim()) return false;\n if (element.querySelector(\"img, video, canvas, svg\")) return false;\n if (element.children?.length > 0) return false;\n return true;\n};\n\nexport const injectFocusOutlineCSS = () => {\n if (document.getElementById(FOCUS_STYLE_ID)) return;\n\n const style = document.createElement(\"style\");\n style.id = FOCUS_STYLE_ID;\n style.textContent = `\n [data-selected=\"true\"][contenteditable=\"true\"]:focus {\n outline: none !important;\n }\n `;\n document.head.appendChild(style);\n};\n\nexport const removeFocusOutlineCSS = () => {\n document.getElementById(FOCUS_STYLE_ID)?.remove();\n};\n\nexport const selectText = (element: HTMLElement) => {\n const range = document.createRange();\n range.selectNodeContents(element);\n const selection = window.getSelection();\n selection?.removeAllRanges();\n selection?.addRange(range);\n};\n\nexport const isEditableTextElement = (element: Element): boolean => {\n if (!(element instanceof HTMLElement)) return false;\n if (!passesStructuralChecks(element)) return false;\n if (isStaticArrayTextElement(element)) return true;\n if (element.dataset.dynamicContent === \"true\") return false;\n return true;\n};\n\nexport const shouldEnterInlineEditingMode = (element: Element): boolean => {\n if (!(element instanceof HTMLElement) || element.dataset.selected !== \"true\") {\n return false;\n }\n return isEditableTextElement(element);\n};\n","import type { InlineEditHost, InlineEditController } from \"./types.js\";\nimport {\n injectFocusOutlineCSS,\n removeFocusOutlineCSS,\n selectText,\n shouldEnterInlineEditingMode,\n isStaticArrayTextElement,\n} from \"./dom-utils.js\";\nimport { PLUGIN_ELEMENT_ATTR } from \"../../injections/utils.js\";\n\nconst DEBOUNCE_MS = 500;\n\nexport function createInlineEditController(\n host: InlineEditHost\n): InlineEditController {\n let currentEditingElement: HTMLElement | null = null;\n let debouncedSendTimeout: ReturnType<typeof setTimeout> | null = null;\n let enabled = false;\n const listenerAbortControllers = new WeakMap<HTMLElement, AbortController>();\n\n // --- Private helpers ---\n\n const repositionOverlays = () => {\n const selectedId = host.getSelectedElementId();\n if (!selectedId) return;\n const elements = host.findElementsById(selectedId);\n const overlays = host.getSelectedOverlays();\n overlays.forEach((overlay, i) => {\n if (i < elements.length && elements[i]) {\n host.positionOverlay(overlay, elements[i]);\n }\n });\n };\n\n const reportEdit = (element: HTMLElement) => {\n const originalContent = element.dataset.originalTextContent;\n const newContent = element.textContent;\n\n const svgElement = element as unknown as SVGElement;\n const rect = element.getBoundingClientRect();\n\n const message: Record<string, unknown> = {\n type: \"inline-edit\",\n elementInfo: {\n tagName: element.tagName,\n classes:\n (svgElement.className as unknown as SVGAnimatedString)?.baseVal ||\n element.className ||\n \"\",\n visualSelectorId: host.getSelectedElementId(),\n content: newContent,\n dataSourceLocation: element.dataset.sourceLocation,\n isDynamicContent: element.dataset.dynamicContent === \"true\",\n linenumber: element.dataset.linenumber,\n filename: element.dataset.filename,\n position: {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n },\n },\n originalContent,\n newContent,\n };\n\n if (isStaticArrayTextElement(element)) {\n message.arrIndex = element.dataset.arrIndex;\n message.arrVariableName = element.dataset.arrVariableName;\n message.arrField = element.dataset.arrField;\n }\n\n window.parent.postMessage(message, \"*\");\n\n element.dataset.originalTextContent = newContent || \"\";\n };\n\n const debouncedReport = (element: HTMLElement) => {\n if (debouncedSendTimeout) clearTimeout(debouncedSendTimeout);\n debouncedSendTimeout = setTimeout(() => reportEdit(element), DEBOUNCE_MS);\n };\n\n const onTextInput = (element: HTMLElement) => {\n repositionOverlays();\n debouncedReport(element);\n };\n\n const handleInputEvent = function (this: HTMLElement) {\n onTextInput(this);\n };\n\n const makeEditable = (element: HTMLElement) => {\n injectFocusOutlineCSS();\n\n element.dataset.originalTextContent = element.textContent || \"\";\n element.dataset.originalCursor = element.style.cursor;\n element.contentEditable = \"true\";\n element.setAttribute(PLUGIN_ELEMENT_ATTR, \"true\");\n\n const abortController = new AbortController();\n listenerAbortControllers.set(element, abortController);\n element.addEventListener(\"input\", handleInputEvent, {\n signal: abortController.signal,\n });\n\n element.style.cursor = \"text\";\n selectText(element);\n setTimeout(() => {\n if (element.isConnected) {\n element.focus();\n }\n }, 0);\n };\n\n const makeNonEditable = (element: HTMLElement) => {\n const abortController = listenerAbortControllers.get(element);\n if (abortController) {\n abortController.abort();\n listenerAbortControllers.delete(element);\n }\n\n if (!element.isConnected) return;\n\n removeFocusOutlineCSS();\n element.contentEditable = \"false\";\n element.removeAttribute(PLUGIN_ELEMENT_ATTR);\n delete element.dataset.originalTextContent;\n\n if (element.dataset.originalCursor !== undefined) {\n element.style.cursor = element.dataset.originalCursor;\n delete element.dataset.originalCursor;\n }\n };\n\n // --- Public API ---\n\n return {\n get enabled() {\n return enabled;\n },\n set enabled(value: boolean) {\n enabled = value;\n },\n\n isEditing() {\n return currentEditingElement !== null;\n },\n\n getCurrentElement() {\n return currentEditingElement;\n },\n\n canEdit(element: Element) {\n return shouldEnterInlineEditingMode(element);\n },\n\n startEditing(element: HTMLElement) {\n currentEditingElement = element;\n\n host.getSelectedOverlays().forEach((o) => {\n o.style.display = \"none\";\n });\n\n makeEditable(element);\n\n window.parent.postMessage(\n {\n type: \"content-editing-started\",\n visualSelectorId: host.getSelectedElementId(),\n },\n \"*\"\n );\n },\n\n stopEditing() {\n if (!currentEditingElement) return;\n\n if (debouncedSendTimeout) {\n clearTimeout(debouncedSendTimeout);\n debouncedSendTimeout = null;\n }\n\n const element = currentEditingElement;\n makeNonEditable(element);\n\n host.getSelectedOverlays().forEach((o) => {\n o.style.display = \"\";\n });\n\n repositionOverlays();\n\n window.parent.postMessage(\n {\n type: \"content-editing-ended\",\n visualSelectorId: host.getSelectedElementId(),\n },\n \"*\"\n );\n\n currentEditingElement = null;\n },\n\n markElementsSelected(elements: Element[]) {\n elements.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.dataset.selected = \"true\";\n }\n });\n },\n\n clearSelectedMarks(elementId: string | null) {\n if (!elementId) return;\n host.findElementsById(elementId).forEach((el) => {\n if (el instanceof HTMLElement) {\n delete el.dataset.selected;\n }\n });\n },\n\n handleToggleMessage(data: { dataSourceLocation: string; inlineEditingMode: boolean }) {\n if (!enabled) return;\n\n const elements = host.findElementsById(data.dataSourceLocation);\n if (elements.length === 0 || !(elements[0] instanceof HTMLElement)) return;\n\n const element = elements[0];\n\n if (data.inlineEditingMode) {\n if (!shouldEnterInlineEditingMode(element)) return;\n\n // Select the element first if not already selected\n if (host.getSelectedElementId() !== data.dataSourceLocation) {\n this.stopEditing();\n host.clearSelection();\n this.markElementsSelected(elements);\n host.createSelectionOverlays(elements, data.dataSourceLocation);\n }\n this.startEditing(element);\n } else {\n if (currentEditingElement === element) {\n this.stopEditing();\n }\n }\n },\n\n cleanup() {\n this.stopEditing();\n },\n };\n}\n","export const DATA_COLLECTION_ID = \"data-collection-id\";\nexport const DATA_COLLECTION_ITEM_ID = \"data-collection-item-id\";\nexport const DATA_COLLECTION_ITEM_FIELD = \"data-collection-item-field\";\nexport const DATA_COLLECTION_REFERENCE = \"data-collection-reference\";\nexport const DATA_ARR_INDEX = \"data-arr-index\";\nexport const DATA_ARR_VARIABLE_NAME = \"data-arr-variable-name\";\nexport const DATA_ARR_FIELD = \"data-arr-field\";\n\nexport const ALLOWED_CUSTOM_COMPONENTS = [\"Image\", \"Link\"];\nexport const MAX_JSX_DEPTH = 10;\nexport const EXCLUDED_FIELDS = [\"children\", \"length\"];\nexport const THEME_FONT_PREVIEW_ID = \"__theme-font-preview\";\n","import { PLUGIN_ELEMENT_ATTR } from \"./utils.js\";\n\ntype CanvasWheelPanData = {\n deltaX: number;\n deltaY: number;\n deltaMode: number;\n clientX: number;\n clientY: number;\n shiftKey: boolean;\n ctrlKey: false;\n metaKey: false;\n};\n\nfunction elementFromEventTarget(target: EventTarget | null): Element | null {\n if (target instanceof Element) return target;\n if (target instanceof Node) return target.parentElement;\n return null;\n}\n\nfunction isPluginOwnedTarget(target: EventTarget | null): boolean {\n return elementFromEventTarget(target)?.closest(`[${PLUGIN_ELEMENT_ATTR}]`) != null;\n}\n\nexport function createCanvasWheelZoomBridgeController() {\n let isEnabled = false;\n\n const onWheel = (event: WheelEvent): void => {\n if (isPluginOwnedTarget(event.target)) return;\n\n event.preventDefault();\n if (event.ctrlKey || event.metaKey) {\n window.parent.postMessage({\n type: \"canvas-wheel-zoom\",\n data: {\n deltaY: event.deltaY,\n deltaMode: event.deltaMode,\n clientX: event.clientX,\n clientY: event.clientY,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n },\n }, \"*\");\n return;\n }\n\n const panData: CanvasWheelPanData = {\n deltaX: event.deltaX,\n deltaY: event.deltaY,\n deltaMode: event.deltaMode,\n clientX: event.clientX,\n clientY: event.clientY,\n shiftKey: event.shiftKey,\n ctrlKey: false,\n metaKey: false,\n };\n window.parent.postMessage({\n type: \"canvas-wheel-pan\",\n data: panData,\n }, \"*\");\n };\n\n const enable = (): void => {\n if (isEnabled) return;\n isEnabled = true;\n window.addEventListener(\"wheel\", onWheel, { capture: true, passive: false });\n };\n\n const disable = (): void => {\n if (!isEnabled) return;\n isEnabled = false;\n window.removeEventListener(\"wheel\", onWheel, true);\n };\n\n return {\n enable,\n disable,\n };\n}\n","// page-height-bridge — postMessage protocol the iframe exposes to its parent.\n// Inert until the parent posts a message; no observers, rewrites, or timers\n// fire on their own.\n//\n// parent → child { type: \"freeze-vh-units\", referenceVhBase?: number }\n// Rewrites every viewport-height unit (`vh`/`dvh`/`svh`/`lvh`) in\n// <style> + CSSOM to a CSS variable-backed expression (kills the\n// vh ↔ auto-resize feedback loop). Repeated calls update the variable,\n// so callers can rebase without recovering raw CSS. Idempotent; covers\n// HMR-added styles too. Fire-and-forget.\n//\n// parent → child { type: \"measure-page-height\", settleMs?: number }\n// After `settleMs` (default 2000) posts the page's measured content height\n// as `{ type: \"page-height-measured\", height }` to the requester.\n\ntype IncomingMessage = {\n type?: string;\n settleMs?: number;\n referenceVhBase?: number;\n};\n\ntype IndexableCssRule = CSSRule & {\n cssRules?: CSSRuleList;\n style?: CSSStyleDeclaration;\n};\n\ntype Debouncer = { trigger: () => void; cancel: () => void };\n\nexport type PageHeightBridgeController = {\n freezeVhUnits: (override?: number) => void;\n measurePageHeight: (origin: string, settleMs?: number) => void;\n teardown: () => void;\n};\n\nconst FALLBACK_VHBASE: number = 900;\nconst MIN_VHBASE: number = 400;\nconst DEFAULT_SETTLE_MS: number = 2000;\nconst NEUTRALIZE_DEBOUNCE_MS: number = 16;\n// Three consecutive same-height samples ≈ ~50ms of \"no change\". Three is\n// enough to filter single-frame jitter from layout passes but short enough\n// that responses arrive promptly when the DOM is already settled.\nconst STABILITY_SAMPLES: number = 3;\n// Interval between stability samples. ~1 frame at 60Hz; chosen as a plain\n// setTimeout (not rAF) because jsdom rAFs are unreliably timed for tests and\n// in real browsers a 16ms tick is post-layout for any layout work that fits\n// inside one frame.\nconst STABILITY_TICK_MS: number = 16;\n// Hard cap on the stability poll past settleMs. Pages that genuinely never\n// stabilize (looping height-animating content) reply with their last sample\n// rather than hanging the parent's resize logic.\nconst STABILITY_MAX_WAIT_MS: number = 1500;\nconst REFERENCE_VH_BASE_VAR: string = \"--base44-reference-vh-base\";\n\nconst noop: () => void = (): void => {};\n\nlet started: boolean = false;\n\n/**\n * Installs the parent-driven message listener. Returns a teardown that\n * removes the listener, disconnects any observers attached as a result of\n * `freeze-vh-units`, and clears any pending response timer. Returns a\n * no-op when bailed (already started, SSR, top window).\n */\nexport function setupPageHeightBridge(): () => void {\n if (started) return noop;\n if (typeof window === \"undefined\") return noop;\n if (window.self === window.top) return noop;\n started = true;\n\n const controller: PageHeightBridgeController = createPageHeightBridgeController();\n\n const onMessage = (event: MessageEvent): void => {\n const data: IncomingMessage | null = (event.data ?? null) as IncomingMessage | null;\n if (!data || typeof data !== \"object\") return;\n switch (data.type) {\n case \"freeze-vh-units\": {\n const override: number | undefined =\n typeof data.referenceVhBase === \"number\" ? data.referenceVhBase : undefined;\n controller.freezeVhUnits(override);\n return;\n }\n case \"measure-page-height\": {\n const settleMs: number =\n typeof data.settleMs === \"number\" ? data.settleMs : DEFAULT_SETTLE_MS;\n const origin: string =\n event.origin && event.origin !== \"null\" ? event.origin : \"*\";\n controller.measurePageHeight(origin, settleMs);\n return;\n }\n }\n };\n\n window.addEventListener(\"message\", onMessage);\n\n let torn: boolean = false;\n return (): void => {\n if (torn) return;\n torn = true;\n started = false;\n window.removeEventListener(\"message\", onMessage);\n controller.teardown();\n };\n}\n\nexport function createPageHeightBridgeController(): PageHeightBridgeController {\n let vhCleanups: Array<() => void> | null = null;\n let vhForceRun: (() => void) | null = null;\n let pendingSettle: number | undefined;\n let pendingTick: number | undefined;\n let pendingOrigin: string = \"*\";\n\n const cancelPending = (): void => {\n if (pendingSettle !== undefined) {\n window.clearTimeout(pendingSettle);\n pendingSettle = undefined;\n }\n if (pendingTick !== undefined) {\n window.clearTimeout(pendingTick);\n pendingTick = undefined;\n }\n };\n\n return {\n freezeVhUnits: (override: number | undefined): void => {\n const referenceVhBase: number = resolveReferenceVhBase(override);\n setReferenceVhBase(referenceVhBase);\n if (vhCleanups) {\n vhForceRun?.();\n return;\n }\n vhCleanups = [];\n vhForceRun = startVhNeutralizer(vhCleanups);\n },\n\n // Target the requester's origin so the height isn't broadcast to anyone\n // who happens to embed us. Falls back to \"*\" when origin is unavailable\n // (jsdom default, sandboxed iframes with `null` origin).\n //\n // Stability-wait response: after `settleMs`, poll measureContentHeight at\n // STABILITY_TICK_MS intervals until it's unchanged for STABILITY_SAMPLES\n // consecutive ticks, then send exactly one reply. Catches late React\n // mounts (sticky-positioned sections committing after settleMs), debounced\n // neutralizer mutations not yet flushed, image/font-driven layout shifts.\n // STABILITY_MAX_WAIT_MS caps the poll so a page that genuinely never\n // settles still replies eventually.\n measurePageHeight: (origin: string, settleMs: number = DEFAULT_SETTLE_MS): void => {\n pendingOrigin = origin;\n cancelPending();\n\n pendingSettle = window.setTimeout((): void => {\n pendingSettle = undefined;\n // Flush any debounced unscroll / inline-vh rewrites NOW so the first\n // sample sees a DOM that reflects every mutation triggered during the\n // settle window. Without this, an `overflow-y: scroll` container that\n // mounted mid-settle can still be hiding its children at sample time.\n vhForceRun?.();\n\n const deadline: number = nowMs() + STABILITY_MAX_WAIT_MS;\n let lastHeight: number = -1;\n let stableSamples: number = 0;\n\n const respond = (height: number): void => {\n pendingTick = undefined;\n window.parent.postMessage({ type: \"page-height-measured\", height }, pendingOrigin);\n };\n\n const tick = (): void => {\n pendingTick = undefined;\n const height: number = measureContentHeight();\n if (height === lastHeight) {\n stableSamples++;\n } else {\n stableSamples = 1;\n lastHeight = height;\n }\n if (stableSamples >= STABILITY_SAMPLES || nowMs() >= deadline) {\n respond(height);\n return;\n }\n pendingTick = window.setTimeout(tick, STABILITY_TICK_MS);\n };\n\n tick();\n }, settleMs);\n },\n\n teardown: (): void => {\n if (vhCleanups) {\n for (const c of vhCleanups) c();\n vhCleanups = null;\n vhForceRun = null;\n }\n cancelPending();\n },\n };\n}\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction resolveReferenceVhBase(override: number | undefined): number {\n if (override !== undefined) return override;\n const detected: number = window.innerHeight || 0;\n return detected >= MIN_VHBASE ? detected : FALLBACK_VHBASE;\n}\n\nfunction setReferenceVhBase(referenceVhBase: number): void {\n document.documentElement.style.setProperty(REFERENCE_VH_BASE_VAR, `${referenceVhBase}px`);\n}\n\n// Caches keep work proportional to *new* CSS, not total CSS. <head> observer\n// catches `<style>`/`<link>` adds; per-element observers catch HMR text edits.\n// Returns a `forceRun` so the caller can re-trigger neutralization on later\n// parent requests (idempotent — already-rewritten text is skipped via the\n// processed sets).\nfunction startVhNeutralizer(cleanups: Array<() => void>): () => void {\n // Match vh + the dynamic/small/large variants. Tailwind v4 emits `h-screen`\n // as `100dvh`; all four collapse to the same frozen `referenceVhBase`.\n const VH_RE: RegExp = /(\\d+(?:\\.\\d+)?)(?:d|s|l)?vh\\b/g;\n const processedStyles: WeakSet<HTMLStyleElement> = new WeakSet();\n const processedSheets: WeakMap<CSSStyleSheet, number> = new WeakMap();\n const watchedStyles: WeakSet<HTMLStyleElement> = new WeakSet();\n const styleObservers: Set<MutationObserver> = new Set();\n\n const unscrolled: WeakSet<Element> = new WeakSet();\n\n const rewrite = (input: string): string =>\n input.replace(VH_RE, (_match: string, n: string): string =>\n `calc(var(${REFERENCE_VH_BASE_VAR}) * ${formatVhFactor(n)})`,\n );\n\n // Defeats internal vertical scrollers. The canvas wants the whole page laid\n // out top-to-bottom, but `<div class=\"overflow-y-auto\" style={{height:\n // \"100vh\"}}>` hides its children behind an internal scrollbar — only the\n // first child appears in the preview. Forcing `overflow-y: visible` lets\n // children paint outside the parent's box; block flow positions them at\n // their natural offsets so document.body extends to include them. `auto`\n // and `scroll` only — `hidden` and `clip` express intentional clipping (UI\n // chrome, rounded-corner masks) we shouldn't undo.\n const unscrollY = (el: Element): void => {\n if (unscrolled.has(el)) return;\n const computedStyle: CSSStyleDeclaration = window.getComputedStyle(el);\n const ovY: string = computedStyle.overflowY;\n if (ovY !== \"auto\" && ovY !== \"scroll\") return;\n unscrolled.add(el);\n (el as HTMLElement).style.setProperty(\"overflow-y\", \"visible\", \"important\");\n };\n\n const unscrollSubtree = (root: Element): void => {\n unscrollY(root);\n root.querySelectorAll<HTMLElement>(\"*\").forEach(unscrollY);\n };\n\n // Rewrites vh-bearing properties on a single element's inline style. Covers\n // React's `style={{ height: \"100vh\" }}` and imperative `el.style.h = \".vh\"`\n // — both bypass <style> tags and CSSOM. Per-property setProperty preserves\n // `!important`. Snapshotting prop names first guards against iteration-time\n // mutation of `style.length`.\n const rewriteInlineStyle = (el: Element): void => {\n const style: CSSStyleDeclaration | undefined = (el as HTMLElement).style;\n if (!style || style.length === 0) return;\n const props: string[] = [];\n for (let i: number = 0; i < style.length; i++) {\n const prop: string | undefined = style[i];\n if (prop) props.push(prop);\n }\n for (const prop of props) {\n const value: string = style.getPropertyValue(prop);\n if (!value || value.indexOf(\"vh\") === -1) continue;\n const next: string = rewrite(value);\n if (next !== value) style.setProperty(prop, next, style.getPropertyPriority(prop));\n }\n };\n\n const neutralize = (): void => {\n document.querySelectorAll<HTMLStyleElement>(\"style\").forEach((el: HTMLStyleElement): void => {\n watchStyleEl(el);\n if (processedStyles.has(el)) return;\n processedStyles.add(el);\n const text: string | null = el.textContent;\n if (!text || text.indexOf(\"vh\") === -1) return;\n const next: string = rewrite(text);\n if (next !== text) el.textContent = next;\n });\n\n for (let i: number = 0; i < document.styleSheets.length; i++) {\n const sheet: CSSStyleSheet | undefined = document.styleSheets[i];\n if (!sheet) continue;\n let rules: CSSRuleList;\n try {\n rules = sheet.cssRules;\n } catch {\n continue; // CORS-protected\n }\n if (processedSheets.get(sheet) === rules.length) continue;\n rewriteVhInRules(rules, rewrite);\n processedSheets.set(sheet, rules.length);\n }\n\n // Initial sweep of inline `style=\"...vh...\"` attributes already in the DOM\n // at freeze time. Future inline-style mutations (React commits, motion\n // libraries, imperative assignments) are picked up by inlineStyleObserver.\n document.querySelectorAll<HTMLElement>('[style*=\"vh\"]').forEach(rewriteInlineStyle);\n\n // Defeat internal scrollers — same dual coverage (initial sweep here,\n // subtree additions in inlineStyleObserver).\n if (document.body) unscrollSubtree(document.body);\n };\n\n const debouncer: Debouncer = createDebouncer(neutralize, NEUTRALIZE_DEBOUNCE_MS);\n const debouncedNeutralize: () => void = debouncer.trigger;\n cleanups.push(debouncer.cancel);\n\n const watchStyleEl = (el: HTMLStyleElement): void => {\n if (watchedStyles.has(el)) return;\n watchedStyles.add(el);\n const obs: MutationObserver = new MutationObserver((): void => {\n processedStyles.delete(el);\n debouncedNeutralize();\n });\n obs.observe(el, { characterData: true, childList: true, subtree: true });\n styleObservers.add(obs);\n };\n cleanups.push((): void => {\n for (const obs of styleObservers) obs.disconnect();\n styleObservers.clear();\n });\n\n debouncedNeutralize();\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", debouncedNeutralize);\n cleanups.push((): void => document.removeEventListener(\"DOMContentLoaded\", debouncedNeutralize));\n }\n window.addEventListener(\"load\", debouncedNeutralize);\n cleanups.push((): void => window.removeEventListener(\"load\", debouncedNeutralize));\n\n const headObserver: MutationObserver = new MutationObserver((mutations: MutationRecord[]): void => {\n for (const m of mutations) {\n if (containsStylesheetNode(m.addedNodes) || containsStylesheetNode(m.removedNodes)) {\n debouncedNeutralize();\n return;\n }\n }\n });\n cleanups.push((): void => headObserver.disconnect());\n\n const attachHeadObserver = (): void => {\n if (document.head) headObserver.observe(document.head, { childList: true, subtree: false });\n };\n if (document.head) {\n attachHeadObserver();\n } else {\n document.addEventListener(\"DOMContentLoaded\", attachHeadObserver);\n cleanups.push((): void => document.removeEventListener(\"DOMContentLoaded\", attachHeadObserver));\n }\n\n // Pass 3: inline `style` attributes. One global observer covers every\n // element — past, present, and future — without per-node tracking. Two\n // mutation kinds matter:\n // • attributes: React/JS sets `style` on an element already in the tree\n // (`el.style.h = \"..vh\"`, re-render diff). After rewrite the value has\n // no \"vh\", so the next mutation gates out — single-tick convergence.\n // • childList: a node is mounted with its `style` attribute already set\n // off-tree (React's initial mount path uses createElement+setAttribute\n // BEFORE appendChild, so attribute mutations never fire for them). Scan\n // the added subtree for `[style*=\"vh\"]` and rewrite.\n // Microtask delivery means rewrites land before layout, so no flash.\n const scanSubtreeForInlineVh = (node: Node): void => {\n if (!(node instanceof Element)) return;\n const attr: string | null = node.getAttribute(\"style\");\n if (attr && attr.indexOf(\"vh\") !== -1) rewriteInlineStyle(node);\n node.querySelectorAll<HTMLElement>('[style*=\"vh\"]').forEach(rewriteInlineStyle);\n // New subtrees may introduce overflow-y: auto|scroll containers (route\n // changes, conditional UI). Catch them here too.\n unscrollSubtree(node);\n };\n const inlineStyleObserver: MutationObserver = new MutationObserver(\n (mutations: MutationRecord[]): void => {\n for (const m of mutations) {\n if (m.type === \"attributes\") {\n const target: Node = m.target;\n if (!(target instanceof Element)) continue;\n const attr: string | null = target.getAttribute(\"style\");\n if (!attr || attr.indexOf(\"vh\") === -1) continue;\n rewriteInlineStyle(target);\n } else if (m.type === \"childList\") {\n for (let i: number = 0; i < m.addedNodes.length; i++) {\n const node: Node | undefined = m.addedNodes[i];\n if (node) scanSubtreeForInlineVh(node);\n }\n }\n }\n },\n );\n cleanups.push((): void => inlineStyleObserver.disconnect());\n\n const attachInlineStyleObserver = (): void => {\n const root: Element | null = document.documentElement;\n if (!root) return;\n inlineStyleObserver.observe(root, {\n attributes: true,\n attributeFilter: [\"style\"],\n childList: true,\n subtree: true,\n });\n };\n attachInlineStyleObserver();\n\n return debouncedNeutralize;\n}\n\nfunction formatVhFactor(value: string): string {\n return String(Number((parseFloat(value) / 100).toFixed(6)));\n}\n\nfunction rewriteVhInRules(rules: CSSRuleList, rewrite: (value: string) => string): void {\n for (let i: number = 0; i < rules.length; i++) {\n const rule: IndexableCssRule | undefined = rules[i] as IndexableCssRule | undefined;\n if (!rule) continue;\n if (rule.cssRules) rewriteVhInRules(rule.cssRules, rewrite);\n const style: CSSStyleDeclaration | undefined = rule.style;\n if (!style) continue;\n for (let j: number = 0; j < style.length; j++) {\n const prop: string | undefined = style[j];\n if (!prop) continue;\n const value: string = style.getPropertyValue(prop);\n if (!value || value.indexOf(\"vh\") === -1) continue;\n const next: string = rewrite(value);\n if (next !== value) style.setProperty(prop, next, style.getPropertyPriority(prop));\n }\n }\n}\n\nfunction containsStylesheetNode(nodes: NodeList): boolean {\n for (let i: number = 0; i < nodes.length; i++) {\n const node: Node | undefined = nodes[i];\n if (node instanceof HTMLStyleElement || node instanceof HTMLLinkElement) return true;\n }\n return false;\n}\n\nfunction measureContentHeight(): number {\n const scrollHeight: number = Math.max(\n document.documentElement.scrollHeight,\n document.body?.scrollHeight ?? 0,\n );\n const referenceVhBase: number = readReferenceVhBase();\n // Excludes `body.clientHeight`: it grows with content, which makes\n // viewportBottom land at the document bottom and trips the stretched-\n // container heuristic on the last section. `referenceVhBase` keeps the\n // h-screen-wrapper case covered when the iframe is shorter than 100vh.\n const viewportHeight: number = Math.max(\n window.innerHeight || 0,\n document.documentElement.clientHeight,\n referenceVhBase,\n );\n const contentBottom: number = measureElementContentBottom(viewportHeight);\n if (contentBottom > 0) return Math.ceil(Math.max(contentBottom, referenceVhBase));\n return Math.ceil(Math.max(scrollHeight, referenceVhBase));\n}\n\nfunction readReferenceVhBase(): number {\n const value: string = document.documentElement.style.getPropertyValue(REFERENCE_VH_BASE_VAR);\n const parsed: number = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction measureElementContentBottom(viewportHeight: number): number {\n if (!document.body) return 0;\n const elements: Element[] = [document.body, ...Array.from(document.body.querySelectorAll(\"*\"))];\n const contentBottoms: WeakMap<Element, number> = new WeakMap();\n const viewportBottom: number = window.scrollY + viewportHeight;\n\n for (let i: number = elements.length - 1; i >= 0; i--) {\n const el: Element | undefined = elements[i];\n if (!el) continue;\n const childContentBottom: number = readChildrenContentBottom(el, contentBottoms);\n const metrics: ElementMetrics = readElementMetrics(el);\n const selfBottom: number = isViewportStretchedContainer(\n metrics,\n childContentBottom,\n viewportHeight,\n viewportBottom,\n )\n ? 0\n : metrics.bottom;\n contentBottoms.set(el, Math.max(childContentBottom, selfBottom));\n }\n\n return contentBottoms.get(document.body) ?? 0;\n}\n\nfunction readChildrenContentBottom(\n el: Element,\n contentBottoms: WeakMap<Element, number>,\n): number {\n let childContentBottom: number = 0;\n for (let i: number = 0; i < el.children.length; i++) {\n const child: Element | undefined = el.children[i];\n if (!child) continue;\n childContentBottom = Math.max(childContentBottom, contentBottoms.get(child) ?? 0);\n }\n return childContentBottom;\n}\n\ntype ElementMetrics = { bottom: number; height: number };\n\nfunction readElementMetrics(el: Element): ElementMetrics {\n const computedStyle: CSSStyleDeclaration = window.getComputedStyle(el);\n if (isOutOfFlowDecoration(computedStyle)) return { bottom: 0, height: 0 };\n const rect: DOMRect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return { bottom: 0, height: 0 };\n return {\n bottom: rect.bottom + window.scrollY + readMarginBottom(computedStyle),\n height: rect.height,\n };\n}\n\nfunction readMarginBottom(computedStyle: CSSStyleDeclaration): number {\n const marginBottom: number = parseFloat(computedStyle.marginBottom);\n return Number.isFinite(marginBottom) ? marginBottom : 0;\n}\n\nfunction isOutOfFlowDecoration(computedStyle: CSSStyleDeclaration): boolean {\n if (computedStyle.position === \"fixed\") return true;\n return computedStyle.position === \"absolute\" && computedStyle.pointerEvents === \"none\";\n}\n\n// A \"stretched container\" spans the full viewport top-to-bottom. Requires\n// BOTH `bottom ≈ viewportBottom` AND `height ≈ viewportHeight` — otherwise an\n// in-flow section that just happens to end at viewportBottom (e.g. when the\n// iframe has been content-sized to the previous measurement) gets falsely\n// filtered, undermeasuring the page.\nfunction isViewportStretchedContainer(\n metrics: ElementMetrics,\n childBottom: number,\n viewportHeight: number,\n viewportBottom: number,\n): boolean {\n return (\n childBottom > 0 &&\n Math.abs(metrics.bottom - viewportBottom) <= 1 &&\n Math.abs(metrics.height - viewportHeight) <= 1 &&\n metrics.bottom - childBottom > 8\n );\n}\n\nfunction createDebouncer(fn: () => void, delayMs: number): Debouncer {\n let timer: number | undefined;\n return {\n trigger: (): void => {\n if (timer !== undefined) window.clearTimeout(timer);\n timer = window.setTimeout(fn, delayMs);\n },\n cancel: (): void => {\n if (timer !== undefined) {\n window.clearTimeout(timer);\n timer = undefined;\n }\n },\n };\n}\n","import { findElementsById, updateElementClasses, updateElementAttribute, collectAllowedAttributes, ALLOWED_ATTRIBUTES, getElementSelectorId, stopAnimations, resumeAnimations, findInstrumentedElement, resolveHoverTarget, positionLabel } from \"./utils.js\";\nimport { createLayerController } from \"./layer-dropdown/controller.js\";\nimport { LAYER_DROPDOWN_ATTR } from \"./layer-dropdown/consts.js\";\nimport { createInlineEditController } from \"../capabilities/inline-edit/index.js\";\nimport { THEME_FONT_PREVIEW_ID } from \"../consts.js\";\nimport { createCanvasWheelZoomBridgeController } from \"./canvas-wheel-zoom-bridge.js\";\nimport { createPageHeightBridgeController } from \"./page-height-bridge.js\";\n\nconst REPOSITION_DELAY_MS = 50;\n\nexport function setupVisualEditAgent() {\n const canvasWheelZoomBridge = createCanvasWheelZoomBridgeController();\n const pageHeightBridge = createPageHeightBridgeController();\n\n // State variables (replacing React useState/useRef)\n let isVisualEditMode = false;\n let isPopoverDragging = false;\n let isDropdownOpen = false;\n let hoverOverlays: HTMLDivElement[] = [];\n let selectedOverlays: HTMLDivElement[] = [];\n let currentHighlightedElements: Element[] = [];\n let selectedElementId: string | null = null;\n let selectedElement: Element | null = null;\n\n // Create overlay element\n const createOverlay = (isSelected = false): HTMLDivElement => {\n const overlay = document.createElement(\"div\");\n overlay.style.position = \"absolute\";\n overlay.style.pointerEvents = \"none\";\n overlay.style.transition = \"all 0.1s ease-in-out\";\n overlay.style.zIndex = \"9999\";\n\n if (isSelected) {\n overlay.style.border = \"2px solid #2563EB\";\n } else {\n overlay.style.border = \"2px solid #95a5fc\";\n overlay.style.backgroundColor = \"rgba(99, 102, 241, 0.05)\";\n }\n\n return overlay;\n };\n\n // Position overlay relative to element\n const positionOverlay = (\n overlay: HTMLDivElement,\n element: Element,\n isSelected = false\n ) => {\n if (!element || !isVisualEditMode) return;\n\n const htmlElement = element as HTMLElement;\n // Force layout recalculation\n void htmlElement.offsetWidth;\n\n const rect = element.getBoundingClientRect();\n overlay.style.top = `${rect.top + window.scrollY}px`;\n overlay.style.left = `${rect.left + window.scrollX}px`;\n overlay.style.width = `${rect.width}px`;\n overlay.style.height = `${rect.height}px`;\n\n // Check if label already exists in overlay\n let label = overlay.querySelector(\"div\") as HTMLDivElement | null;\n\n if (!label) {\n label = document.createElement(\"div\");\n label.textContent = element.tagName.toLowerCase();\n label.style.position = \"absolute\";\n label.style.left = \"-2px\";\n label.style.padding = \"2px 8px\";\n label.style.fontSize = \"11px\";\n label.style.fontWeight = isSelected ? \"500\" : \"400\";\n label.style.color = isSelected ? \"#ffffff\" : \"#526cff\";\n label.style.backgroundColor = isSelected ? \"#2563EB\" : \"#DBEAFE\";\n label.style.borderRadius = \"3px\";\n label.style.minWidth = \"24px\";\n label.style.textAlign = \"center\";\n overlay.appendChild(label);\n }\n\n positionLabel(label, rect);\n };\n\n // --- Inline edit controller ---\n const inlineEdit = createInlineEditController({\n findElementsById,\n getSelectedElementId: () => selectedElementId,\n getSelectedOverlays: () => selectedOverlays,\n positionOverlay,\n clearSelection: () => {\n inlineEdit.clearSelectedMarks(selectedElementId);\n clearSelectedOverlays();\n selectedElementId = null;\n selectedElement = null;\n },\n createSelectionOverlays: (elements, elementId) => {\n elements.forEach((el) => {\n const overlay = createOverlay(true);\n document.body.appendChild(overlay);\n selectedOverlays.push(overlay);\n positionOverlay(overlay, el, true);\n });\n selectedElementId = elementId;\n },\n });\n\n const clearSelection = () => {\n inlineEdit.clearSelectedMarks(selectedElementId);\n clearSelectedOverlays();\n selectedElementId = null;\n selectedElement = null;\n };\n\n // Clear hover overlays\n const clearHoverOverlays = () => {\n hoverOverlays.forEach((overlay) => {\n if (overlay && overlay.parentNode) {\n overlay.remove();\n }\n });\n hoverOverlays = [];\n currentHighlightedElements = [];\n };\n\n const clearSelectedOverlays = () => {\n selectedOverlays.forEach((overlay) => {\n if (overlay && overlay.parentNode) {\n overlay.remove();\n }\n });\n selectedOverlays = [];\n };\n\n const TEXT_TAGS = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'a', 'label'];\n\n const notifyElementSelected = (element: Element) => {\n const htmlElement = element as HTMLElement;\n const rect = element.getBoundingClientRect();\n const svgElement = element as SVGElement;\n const isTextElement = TEXT_TAGS.includes(element.tagName?.toLowerCase());\n\n const arrEl = htmlElement.closest(\"[data-arr-variable-name]\") as HTMLElement | null;\n const staticArrayName = arrEl?.dataset?.arrVariableName || null;\n const rawIdx = arrEl?.dataset?.arrIndex;\n const staticArrayIndex = rawIdx != null ? parseInt(rawIdx, 10) : null;\n const staticArrayField = htmlElement.dataset?.arrField || null;\n\n const collectionEl = htmlElement.closest(\"[data-collection-id]\") as HTMLElement | null;\n const itemFieldEl = htmlElement.closest(\"[data-collection-item-field]\") as HTMLElement | null;\n const itemIdEl = htmlElement.closest(\"[data-collection-item-id]\") as HTMLElement | null;\n\n window.parent.postMessage({\n type: \"element-selected\",\n tagName: element.tagName,\n classes:\n (svgElement.className as unknown as SVGAnimatedString)?.baseVal ||\n element.className ||\n \"\",\n visualSelectorId: getElementSelectorId(element),\n content: isTextElement ? htmlElement.innerText : undefined,\n dataSourceLocation: htmlElement.dataset.sourceLocation,\n isDynamicContent: htmlElement.dataset.dynamicContent === \"true\",\n linenumber: htmlElement.dataset.linenumber,\n filename: htmlElement.dataset.filename,\n position: {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n },\n attributes: collectAllowedAttributes(element, ALLOWED_ATTRIBUTES),\n isTextElement,\n staticArrayName,\n staticArrayIndex,\n staticArrayField,\n collectionId: collectionEl?.dataset?.collectionId || null,\n collectionItemField: itemFieldEl?.dataset?.collectionItemField || null,\n collectionItemId: itemIdEl?.dataset?.collectionItemId || null,\n }, \"*\");\n };\n\n // Select an element: create overlays, update state, notify parent\n const selectElement = (element: Element): HTMLDivElement | undefined => {\n const visualSelectorId = getElementSelectorId(element);\n\n clearSelectedOverlays();\n\n const elements = findElementsById(visualSelectorId || null);\n elements.forEach((el) => {\n const overlay = createOverlay(true);\n document.body.appendChild(overlay);\n selectedOverlays.push(overlay);\n positionOverlay(overlay, el, true);\n });\n\n selectedElementId = visualSelectorId || null;\n selectedElement = element;\n clearHoverOverlays();\n notifyElementSelected(element);\n\n return selectedOverlays[0];\n };\n\n const notifyDeselection = (): void => {\n selectedElementId = null;\n window.parent.postMessage({ type: \"unselect-element\" }, \"*\");\n };\n\n // Hover detection via mousemove + elementFromPoint (since app elements have pointer-events: none)\n let lastHoveredSelectorId: string | null = null;\n let pendingMouseMoveRaf: number | null = null;\n\n const clearHoverState = () => {\n clearHoverOverlays();\n lastHoveredSelectorId = null;\n };\n\n const applyHoverOverlays = (selectorId: string) => {\n const elements = findElementsById(selectorId);\n clearHoverOverlays();\n\n elements.forEach((el) => {\n const overlay = createOverlay(false);\n document.body.appendChild(overlay);\n hoverOverlays.push(overlay);\n positionOverlay(overlay, el);\n });\n\n currentHighlightedElements = elements;\n lastHoveredSelectorId = selectorId;\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!isVisualEditMode || isPopoverDragging || inlineEdit.isEditing()) return;\n\n if (pendingMouseMoveRaf !== null) return;\n pendingMouseMoveRaf = requestAnimationFrame(() => {\n pendingMouseMoveRaf = null;\n\n if (isDropdownOpen) { clearHoverState(); return; }\n\n const selectorId = resolveHoverTarget(e.clientX, e.clientY, selectedElementId);\n if (!selectorId) { clearHoverState(); return; }\n if (lastHoveredSelectorId === selectorId) return;\n\n applyHoverOverlays(selectorId);\n });\n };\n\n // Clear hover overlays when mouse leaves the viewport\n const handleMouseLeave = () => {\n if (pendingMouseMoveRaf !== null) {\n cancelAnimationFrame(pendingMouseMoveRaf);\n pendingMouseMoveRaf = null;\n }\n clearHoverState();\n };\n\n // Handle element click\n const handleElementClick = (e: MouseEvent) => {\n if (!isVisualEditMode) return;\n\n const target = e.target as Element;\n\n // Let layer dropdown clicks pass through without interference\n if (target.closest(`[${LAYER_DROPDOWN_ATTR}]`)) return;\n\n // Let clicks inside the editable element pass through to the browser\n // so the user can reposition the cursor and select text naturally.\n if (inlineEdit.enabled && target instanceof HTMLElement && target.contentEditable === \"true\") {\n return;\n }\n\n // Clicking outside the editable element exits inline editing mode.\n if (inlineEdit.isEditing()) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n inlineEdit.stopEditing();\n return;\n }\n\n // Close dropdowns when clicking anywhere in iframe if a dropdown is open\n if (isDropdownOpen) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n window.parent.postMessage({ type: \"close-dropdowns\" }, \"*\");\n return;\n }\n\n // Prevent default behavior immediately when in visual edit mode\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n const element = findInstrumentedElement(e.clientX, e.clientY);\n if (!element) {\n return;\n }\n\n const htmlElement = element as HTMLElement;\n const visualSelectorId = getElementSelectorId(element);\n\n const isAlreadySelected =\n selectedElementId === visualSelectorId &&\n htmlElement.dataset.selected === \"true\";\n\n if (isAlreadySelected && inlineEdit.enabled && inlineEdit.canEdit(htmlElement)) {\n inlineEdit.startEditing(htmlElement);\n return;\n }\n\n inlineEdit.stopEditing();\n\n if (inlineEdit.enabled) {\n inlineEdit.markElementsSelected(findElementsById(visualSelectorId));\n }\n\n const selectedOverlay = selectElement(element);\n layerController.attachToOverlay(selectedOverlay, element);\n };\n\n const unselectElement = () => {\n inlineEdit.stopEditing();\n clearSelection();\n };\n\n const updateElementClassesAndReposition = (visualSelectorId: string, classes: string) => {\n const elements = findElementsById(visualSelectorId);\n if (elements.length === 0) return;\n\n updateElementClasses(elements, classes);\n\n // Use a small delay to allow the browser to recalculate layout before repositioning\n setTimeout(() => {\n // Reposition selected overlays\n if (selectedElementId === visualSelectorId) {\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n\n // Reposition hover overlays if needed\n if (currentHighlightedElements.length > 0) {\n const hoveredElement = currentHighlightedElements[0] as HTMLElement;\n const hoveredId = hoveredElement?.dataset?.visualSelectorId;\n if (hoveredId === visualSelectorId) {\n hoverOverlays.forEach((overlay, index) => {\n if (index < currentHighlightedElements.length) {\n positionOverlay(overlay, currentHighlightedElements[index]!);\n }\n });\n }\n }\n }, REPOSITION_DELAY_MS);\n };\n\n // Update element attribute by visual selector ID\n const updateElementAttributeAndReposition = (\n visualSelectorId: string,\n attribute: string,\n value: string\n ) => {\n const elements = findElementsById(visualSelectorId);\n if (elements.length === 0) return;\n\n updateElementAttribute(elements, attribute, value);\n\n // Reposition overlays after attribute change (e.g. image src swap can affect layout)\n setTimeout(() => {\n if (selectedElementId === visualSelectorId) {\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n }, REPOSITION_DELAY_MS);\n };\n\n const updateElementContent = (visualSelectorId: string, content: string, arrIndex?: number) => {\n let elements = findElementsById(visualSelectorId);\n\n if (elements.length === 0) {\n return;\n }\n\n if (arrIndex != null) {\n elements = elements.filter(\n (el) => (el as HTMLElement).dataset.arrIndex === String(arrIndex)\n );\n }\n\n elements.forEach((element) => {\n (element as HTMLElement).innerText = content;\n });\n\n setTimeout(() => {\n if (selectedElementId === visualSelectorId) {\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n }, REPOSITION_DELAY_MS);\n };\n\n // --- Layer dropdown controller ---\n const layerController = createLayerController({\n createPreviewOverlay: (element: Element) => {\n const overlay = createOverlay(false);\n overlay.style.zIndex = \"9998\";\n document.body.appendChild(overlay);\n positionOverlay(overlay, element);\n return overlay;\n },\n getSelectedElementId: () => selectedElementId,\n selectElement,\n onDeselect: notifyDeselection,\n });\n\n // Toggle visual edit mode\n const toggleVisualEditMode = (isEnabled: boolean) => {\n isVisualEditMode = isEnabled;\n\n if (!isEnabled) {\n canvasWheelZoomBridge.disable();\n resumeAnimations();\n inlineEdit.stopEditing();\n clearSelection();\n layerController.cleanup();\n handleMouseLeave();\n document.body.style.cursor = \"default\";\n\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseleave\", handleMouseLeave);\n document.removeEventListener(\"click\", handleElementClick, true);\n } else {\n document.body.style.cursor = \"crosshair\";\n stopAnimations();\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseleave\", handleMouseLeave);\n document.addEventListener(\"click\", handleElementClick, true);\n }\n };\n\n // Handle scroll events to update popover position\n const handleScroll = () => {\n if (selectedElementId) {\n const element = selectedElement;\n if (element && element.isConnected) {\n const rect = element.getBoundingClientRect();\n\n const viewportHeight = window.innerHeight;\n const viewportWidth = window.innerWidth;\n const isInViewport =\n rect.top < viewportHeight &&\n rect.bottom > 0 &&\n rect.left < viewportWidth &&\n rect.right > 0;\n\n const elementPosition = {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n };\n\n window.parent.postMessage(\n {\n type: \"element-position-update\",\n position: elementPosition,\n isInViewport: isInViewport,\n visualSelectorId: selectedElementId,\n },\n \"*\"\n );\n }\n }\n };\n\n // Handle messages from parent window\n const handleMessage = (event: MessageEvent) => {\n const message = event.data;\n\n switch (message.type) {\n case \"toggle-visual-edit-mode\":\n toggleVisualEditMode(message.data.enabled);\n if (message.data.specs?.newInlineEditEnabled !== undefined) {\n inlineEdit.enabled = message.data.specs.newInlineEditEnabled;\n }\n break;\n\n case \"update-classes\":\n if (message.data && message.data.classes !== undefined) {\n updateElementClassesAndReposition(\n message.data.visualSelectorId,\n message.data.classes\n );\n } else {\n console.warn(\n \"[VisualEditAgent] Invalid update-classes message:\",\n message\n );\n }\n break;\n\n case \"update-attribute\":\n if (\n message.data &&\n message.data.visualSelectorId &&\n message.data.attribute !== undefined &&\n message.data.value !== undefined\n ) {\n updateElementAttributeAndReposition(\n message.data.visualSelectorId,\n message.data.attribute,\n message.data.value\n );\n } else {\n console.warn(\n \"[VisualEditAgent] Invalid update-attribute message:\",\n message\n );\n }\n break;\n\n case \"unselect-element\":\n unselectElement();\n break;\n\n case \"refresh-page\":\n window.location.reload();\n break;\n\n case \"update-content\":\n if (message.data && message.data.content !== undefined) {\n updateElementContent(\n message.data.visualSelectorId,\n message.data.content,\n message.data.arrIndex\n );\n } else {\n console.warn(\n \"[VisualEditAgent] Invalid update-content message:\",\n message\n );\n }\n break;\n\n case \"request-element-position\":\n if (selectedElementId && selectedElement && selectedElement.isConnected) {\n const rect = selectedElement.getBoundingClientRect();\n\n const viewportHeight = window.innerHeight;\n const viewportWidth = window.innerWidth;\n const isInViewport =\n rect.top < viewportHeight &&\n rect.bottom > 0 &&\n rect.left < viewportWidth &&\n rect.right > 0;\n\n const elementPosition = {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n };\n\n window.parent.postMessage(\n {\n type: \"element-position-update\",\n position: elementPosition,\n isInViewport: isInViewport,\n visualSelectorId: selectedElementId,\n },\n \"*\"\n );\n }\n break;\n\n case \"popover-drag-state\":\n if (message.data && message.data.isDragging !== undefined) {\n isPopoverDragging = message.data.isDragging;\n if (message.data.isDragging) {\n clearHoverOverlays();\n }\n }\n break;\n\n case \"dropdown-state\":\n if (message.data && message.data.isOpen !== undefined) {\n isDropdownOpen = message.data.isOpen;\n if (message.data.isOpen) {\n clearHoverOverlays();\n }\n }\n break;\n\n case \"update-theme-variables\":\n if (message.data?.variables) {\n const target = message.data.mode === 'dark'\n ? document.querySelector('.dark') as HTMLElement\n : document.documentElement;\n if (target) {\n for (const [name, value] of Object.entries(message.data.variables)) {\n target.style.setProperty(name, value as string);\n }\n }\n }\n break;\n\n case \"inject-font-import\":\n if (message.data?.fontUrl) {\n let fontStyle = document.getElementById(THEME_FONT_PREVIEW_ID) as HTMLStyleElement | null;\n if (!fontStyle) {\n fontStyle = document.createElement('style');\n fontStyle.id = THEME_FONT_PREVIEW_ID;\n document.head.appendChild(fontStyle);\n }\n fontStyle.textContent = `@import url('${message.data.fontUrl}');`;\n }\n break;\n\n case \"toggle-inline-edit-mode\":\n if (message.data) {\n inlineEdit.handleToggleMessage(message.data);\n }\n break;\n\n case \"freeze-vh-units\":\n pageHeightBridge.freezeVhUnits(\n typeof message.referenceVhBase === \"number\"\n ? message.referenceVhBase\n : undefined\n );\n break;\n\n case \"measure-page-height\":\n pageHeightBridge.measurePageHeight(\n event.origin && event.origin !== \"null\" ? event.origin : \"*\",\n typeof message.settleMs === \"number\" ? message.settleMs : undefined\n );\n break;\n\n case \"toggle-canvas-wheel-zoom-bridge\":\n canvasWheelZoomBridge.enable();\n break;\n\n default:\n break;\n }\n };\n\n // Handle window resize to reposition overlays\n const handleResize = () => {\n if (selectedElementId) {\n const elements = findElementsById(selectedElementId);\n selectedOverlays.forEach((overlay, index) => {\n if (index < elements.length) {\n positionOverlay(overlay, elements[index]!);\n }\n });\n }\n\n if (currentHighlightedElements.length > 0) {\n hoverOverlays.forEach((overlay, index) => {\n if (index < currentHighlightedElements.length) {\n positionOverlay(overlay, currentHighlightedElements[index]!);\n }\n });\n }\n };\n\n // Initialize: Add IDs to elements that don't have them but have linenumbers\n const elementsWithLineNumber = document.querySelectorAll(\n \"[data-linenumber]:not([data-visual-selector-id])\"\n );\n elementsWithLineNumber.forEach((el, index) => {\n const htmlEl = el as HTMLElement;\n const id = `visual-id-${htmlEl.dataset.filename}-${htmlEl.dataset.linenumber}-${index}`;\n htmlEl.dataset.visualSelectorId = id;\n });\n\n // Create mutation observer to detect layout changes\n const mutationObserver = new MutationObserver((mutations) => {\n const needsUpdate = mutations.some((mutation) => {\n const hasVisualId = (node: Node): boolean => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n if (el.dataset && el.dataset.visualSelectorId) {\n return true;\n }\n for (let i = 0; i < el.children.length; i++) {\n if (hasVisualId(el.children[i]!)) {\n return true;\n }\n }\n }\n return false;\n };\n\n const isLayoutChange =\n mutation.type === \"attributes\" &&\n (mutation.attributeName === \"style\" ||\n mutation.attributeName === \"class\" ||\n mutation.attributeName === \"width\" ||\n mutation.attributeName === \"height\");\n\n return isLayoutChange && hasVisualId(mutation.target);\n });\n\n if (needsUpdate) {\n setTimeout(handleResize, REPOSITION_DELAY_MS);\n }\n });\n\n // Set up event listeners\n window.addEventListener(\"message\", handleMessage);\n window.addEventListener(\"scroll\", handleScroll, true);\n document.addEventListener(\"scroll\", handleScroll, true);\n window.addEventListener(\"resize\", handleResize);\n window.addEventListener(\"scroll\", handleResize);\n\n // Start observing DOM mutations\n mutationObserver.observe(document.body, {\n attributes: true,\n childList: true,\n subtree: true,\n attributeFilter: [\"style\", \"class\", \"width\", \"height\"],\n });\n\n // Send ready message to parent\n window.parent.postMessage({ type: \"visual-edit-agent-ready\" }, \"*\");\n}\n"],"mappings":"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","names":["positionLabel","label","rect","nearTop","tallEnough","isFullWidth","edgeLeft","insideLeft","isInstrumentedElement","element","htmlEl","getElementSelectorId","ALLOWED_ATTRIBUTES","PLUGIN_ELEMENT_ATTR","findElementsById","id","sourceElements","updateElementClasses","elements","classes","updateElementAttribute","attribute","value","collectAllowedAttributes","allowedAttributes","attributes","attr","val","stopAnimations","animStyle","pointerStyle","target","a","animTarget","resumeAnimations","findInstrumentedElement","x","y","el","resolveHoverTarget","selectedElementId","selectorId","DROPDOWN_CONTAINER_STYLES","DROPDOWN_ITEM_BASE_STYLES","DROPDOWN_ITEM_ACTIVE_COLOR","DROPDOWN_ITEM_ACTIVE_BG","DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT","DROPDOWN_ITEM_HOVER_BG","DEPTH_INDENT_PX","CHEVRON_COLLAPSED","CHEVRON_EXPANDED","CHEVRON_ATTR","BASE_PADDING_PX","LAYER_DROPDOWN_ATTR","MAX_PARENT_DEPTH","MAX_CHILD_DEPTH","applyStyles","element","styles","key","m","getLayerDisplayName","layer","toLayerInfo","depth","info","getElementSelectorId","getInstrumentedDescendants","parent","maxDepth","startDepth","result","walk","el","instrDepth","i","child","isInstrumentedElement","collectInstrumentedParents","selectedElement","parents","current","MAX_PARENT_DEPTH","addParentsToChain","chain","p","addSelfAndDescendantsToChain","selfDepth","descendants","MAX_CHILD_DEPTH","getImmediateInstrParent","collectSiblings","siblings","s","appendSiblingsWithSelected","selectedSelectorId","seen","sibling","id","buildLayerChain","instrParent","activeDropdown","activeLabel","outsideMousedownHandler","activeOnHoverEnd","activeKeydownHandler","createDropdownItem","layer","isActive","onSelect","onHover","onHoverEnd","item","getLayerDisplayName","applyStyles","DROPDOWN_ITEM_BASE_STYLES","depth","BASE_PADDING_PX","DEPTH_INDENT_PX","DROPDOWN_ITEM_ACTIVE_COLOR","DROPDOWN_ITEM_ACTIVE_BG","DROPDOWN_ITEM_ACTIVE_FONT_WEIGHT","DROPDOWN_ITEM_HOVER_BG","e","createDropdownElement","layers","currentElement","callbacks","container","LAYER_DROPDOWN_ATTR","PLUGIN_ELEMENT_ATTR","DROPDOWN_CONTAINER_STYLES","enhanceLabelWithChevron","label","CHEVRON_ATTR","chevron","CHEVRON_COLLAPSED","setupKeyboardNavigation","dropdown","items","focusedIndex","l","setFocusedItem","index","prev","cur","closeDropdown","setupOutsideClickHandler","skipFirst","target","showDropdown","overlay","chevronEl","CHEVRON_EXPANDED","isDropdownOpen","createLayerController","config","layerPreviewOverlay","escapeHandler","dropdownSourceLayer","clearLayerPreview","showLayerPreview","layer","getElementSelectorId","selectLayer","closeDropdown","firstOverlay","attachToOverlay","restoreSelection","handleLabelClick","e","label","element","layers","currentId","isDropdownOpen","ev","showDropdown","overlay","buildLayerChain","enhanceLabelWithChevron","FOCUS_STYLE_ID","EDITABLE_TAGS","isStaticArrayTextElement","element","passesStructuralChecks","injectFocusOutlineCSS","style","removeFocusOutlineCSS","selectText","range","selection","isEditableTextElement","shouldEnterInlineEditingMode","DEBOUNCE_MS","createInlineEditController","host","currentEditingElement","debouncedSendTimeout","enabled","listenerAbortControllers","repositionOverlays","selectedId","elements","overlay","i","reportEdit","element","originalContent","newContent","svgElement","rect","message","isStaticArrayTextElement","debouncedReport","onTextInput","handleInputEvent","makeEditable","injectFocusOutlineCSS","PLUGIN_ELEMENT_ATTR","abortController","selectText","makeNonEditable","removeFocusOutlineCSS","value","shouldEnterInlineEditingMode","o","el","elementId","data","THEME_FONT_PREVIEW_ID","elementFromEventTarget","target","isPluginOwnedTarget","PLUGIN_ELEMENT_ATTR","createCanvasWheelZoomBridgeController","isEnabled","onWheel","event","panData","REFERENCE_VH_BASE_VAR","createPageHeightBridgeController","vhCleanups","vhForceRun","pendingSettle","pendingTick","pendingOrigin","cancelPending","override","referenceVhBase","resolveReferenceVhBase","setReferenceVhBase","startVhNeutralizer","origin","settleMs","deadline","nowMs","lastHeight","stableSamples","respond","height","tick","measureContentHeight","c","detected","REFERENCE_VH_BASE_VAR","cleanups","VH_RE","processedStyles","processedSheets","watchedStyles","styleObservers","unscrolled","rewrite","input","_match","n","formatVhFactor","unscrollY","el","ovY","unscrollSubtree","root","rewriteInlineStyle","style","props","i","prop","value","next","debouncer","createDebouncer","watchStyleEl","text","sheet","rules","rewriteVhInRules","debouncedNeutralize","obs","headObserver","mutations","m","containsStylesheetNode","attachHeadObserver","scanSubtreeForInlineVh","node","attr","inlineStyleObserver","target","rule","j","nodes","scrollHeight","readReferenceVhBase","viewportHeight","contentBottom","measureElementContentBottom","parsed","elements","contentBottoms","viewportBottom","childContentBottom","readChildrenContentBottom","metrics","readElementMetrics","selfBottom","isViewportStretchedContainer","child","computedStyle","isOutOfFlowDecoration","rect","readMarginBottom","marginBottom","childBottom","fn","delayMs","timer","REPOSITION_DELAY_MS","setupVisualEditAgent","canvasWheelZoomBridge","createCanvasWheelZoomBridgeController","pageHeightBridge","createPageHeightBridgeController","isVisualEditMode","isPopoverDragging","isDropdownOpen","hoverOverlays","selectedOverlays","currentHighlightedElements","selectedElementId","selectedElement","createOverlay","isSelected","overlay","positionOverlay","element","rect","label","positionLabel","inlineEdit","createInlineEditController","findElementsById","clearSelectedOverlays","elements","elementId","el","clearSelection","clearHoverOverlays","TEXT_TAGS","notifyElementSelected","htmlElement","svgElement","isTextElement","arrEl","staticArrayName","rawIdx","staticArrayIndex","staticArrayField","collectionEl","itemFieldEl","itemIdEl","getElementSelectorId","collectAllowedAttributes","ALLOWED_ATTRIBUTES","selectElement","visualSelectorId","notifyDeselection","lastHoveredSelectorId","pendingMouseMoveRaf","clearHoverState","applyHoverOverlays","selectorId","handleMouseMove","e","resolveHoverTarget","handleMouseLeave","handleElementClick","target","LAYER_DROPDOWN_ATTR","findInstrumentedElement","selectedOverlay","layerController","unselectElement","updateElementClassesAndReposition","classes","updateElementClasses","index","updateElementAttributeAndReposition","attribute","value","updateElementAttribute","updateElementContent","content","arrIndex","createLayerController","toggleVisualEditMode","isEnabled","stopAnimations","resumeAnimations","handleScroll","viewportHeight","viewportWidth","isInViewport","elementPosition","handleMessage","event","message","name","fontStyle","THEME_FONT_PREVIEW_ID","handleResize","htmlEl","id","mutationObserver","mutations","mutation","hasVisualId","node","i"]}