import { useEffect, useRef, useState } from 'react'; interface InspectorProps { isActive: boolean; iframeRef: React.RefObject; onElementSelect: (elementInfo: ElementInfo) => void; } export interface ElementInfo { displayText: string; tagName: string; className: string; id: string; textContent: string; styles: Record; // Changed from CSSStyleDeclaration rect: { x: number; y: number; width: number; height: number; top: number; left: number; }; } export const Inspector = ({ isActive, iframeRef, onElementSelect }: InspectorProps) => { const [hoveredElement, setHoveredElement] = useState(null); const overlayRef = useRef(null); useEffect(() => { if (!isActive || !iframeRef.current) { return undefined; } const iframe = iframeRef.current; // Listen for messages from the iframe const handleMessage = (event: MessageEvent) => { if (event.data.type === 'INSPECTOR_HOVER') { const elementInfo = event.data.elementInfo; // Adjust coordinates relative to iframe position const iframeRect = iframe.getBoundingClientRect(); elementInfo.rect.x += iframeRect.x; elementInfo.rect.y += iframeRect.y; elementInfo.rect.top += iframeRect.y; elementInfo.rect.left += iframeRect.x; setHoveredElement(elementInfo); } else if (event.data.type === 'INSPECTOR_CLICK') { const elementInfo = event.data.elementInfo; // Adjust coordinates relative to iframe position const iframeRect = iframe.getBoundingClientRect(); elementInfo.rect.x += iframeRect.x; elementInfo.rect.y += iframeRect.y; elementInfo.rect.top += iframeRect.y; elementInfo.rect.left += iframeRect.x; onElementSelect(elementInfo); } else if (event.data.type === 'INSPECTOR_LEAVE') { setHoveredElement(null); } }; window.addEventListener('message', handleMessage); // Send activation message to iframe const sendActivationMessage = () => { if (iframe.contentWindow) { iframe.contentWindow.postMessage( { type: 'INSPECTOR_ACTIVATE', active: isActive, }, '*', ); } }; // Try to send activation message immediately and on load sendActivationMessage(); iframe.addEventListener('load', sendActivationMessage); return () => { window.removeEventListener('message', handleMessage); iframe.removeEventListener('load', sendActivationMessage); // Deactivate inspector in iframe if (iframe.contentWindow) { iframe.contentWindow.postMessage( { type: 'INSPECTOR_ACTIVATE', active: false, }, '*', ); } }; }, [isActive, iframeRef, onElementSelect]); // Render overlay for hovered element return ( <> {isActive && hoveredElement && (
{/* Element info tooltip */}
{hoveredElement.tagName.toLowerCase()} {hoveredElement.id && `#${hoveredElement.id}`} {hoveredElement.className && `.${hoveredElement.className.split(' ')[0]}`}
)} ); };