"use client"; import { useEffect, useState, useRef, useCallback } from "react"; const IDE_SCHEMES = [ { matches: ["antigravity"], createUrl: (locator: string) => `antigravity://file/${locator}`, }, { matches: ["cursor"], createUrl: (locator: string) => `cursor://file/${locator}`, }, { matches: ["vscode", "code"], createUrl: (locator: string) => `vscode://file/${locator}`, }, { matches: ["webstorm", "intellij"], createUrl: (locator: string) => `webstorm://open?file=${locator}`, }, { matches: ["sublime"], createUrl: (locator: string) => `subl://open?url=file://${locator}`, }, { matches: ["atom", "nova"], createUrl: (locator: string) => `atom://open?url=file://${locator}`, }, ] as const; function parseLocator(locator: string) { const match = locator.match(/^(.*):(\d+|unknown):(\d+|unknown)$/); if (!match) { return { filePath: locator, line: null, column: null }; } const [, filePath, line, column] = match; return { filePath, line: line === "unknown" ? null : Number(line), column: column === "unknown" ? null : Number(column), }; } function formatLocatorLabel(locator: string) { const { filePath, line } = parseLocator(locator); const parts = filePath.split(/[/\\]/); const shortPath = parts.slice(-2).join("/"); const lineInfo = line !== null ? `:${line}` : ""; return `${shortPath}${lineInfo}`; } function getHierarchy(startEl: Element | null): Element[] { const list: Element[] = []; let curr: Element | null = startEl; while (curr && curr !== document.body && curr !== document.documentElement) { if (curr.hasAttribute("data-locator")) { list.push(curr); } curr = curr.parentElement; } return list; // [0: innermost leaf, ..., N-1: outermost container] } function selectTargetElement( hierarchy: Element[], isInnerMode: boolean ): Element | null { if (hierarchy.length === 0) return null; if (hierarchy.length === 1) return hierarchy[0]; if (isInnerMode) { // Inner Mode (Alt + Ctrl): absolute innermost leaf element (, ,

, etc.) return hierarchy[0]; } // Outer Mode (Alt): Intermediate component wrapper / button (pushed one level inside) const leafTag = hierarchy[0].tagName.toLowerCase(); const isSvgLeaf = [ "path", "circle", "g", "rect", "line", "polyline", "polygon", "ellipse", "defs", ].includes(leafTag); if (isSvgLeaf) { // If leaf is inside an SVG, select the immediate element enclosing (e.g.

) const outsideSvgIndex = hierarchy.findIndex( (el, idx) => idx > 0 && el.tagName.toLowerCase() !== "svg" ); if (outsideSvgIndex !== -1) { return hierarchy[outsideSvgIndex]; } return hierarchy[1] || hierarchy[0]; } // For standard elements (e.g. inside
)} ); } export default DevClickToComponent;