"use client"; import { useUpdateEffect } from "react-use"; import { useMemo, useState } from "react"; import classNames from "classnames"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; import { GridPattern } from "@/components/magic-ui/grid-pattern"; import { htmlTagToText } from "@/lib/html-tag-to-text"; export const Preview = ({ html, isResizing, isAiWorking, ref, device, currentTab, iframeRef, isEditableModeEnabled, onClickElement, }: { html: string; isResizing: boolean; isAiWorking: boolean; ref: React.RefObject; iframeRef?: React.RefObject; device: "desktop" | "mobile"; currentTab: string; isEditableModeEnabled?: boolean; onClickElement?: (element: HTMLElement) => void; }) => { const [hoveredElement, setHoveredElement] = useState( null ); // add event listener to the iframe to track hovered elements const handleMouseOver = (event: MouseEvent) => { if (iframeRef?.current) { const iframeDocument = iframeRef.current.contentDocument; if (iframeDocument) { const targetElement = event.target as HTMLElement; if ( hoveredElement !== targetElement && targetElement !== iframeDocument.body ) { setHoveredElement(targetElement); targetElement.classList.add("hovered-element"); } else { return setHoveredElement(null); } } } }; const handleMouseOut = () => { setHoveredElement(null); }; const handleClick = (event: MouseEvent) => { if (iframeRef?.current) { const iframeDocument = iframeRef.current.contentDocument; if (iframeDocument) { const targetElement = event.target as HTMLElement; if (targetElement !== iframeDocument.body) { onClickElement?.(targetElement); } } } }; useUpdateEffect(() => { const cleanupListeners = () => { if (iframeRef?.current?.contentDocument) { const iframeDocument = iframeRef.current.contentDocument; iframeDocument.removeEventListener("mouseover", handleMouseOver); iframeDocument.removeEventListener("mouseout", handleMouseOut); iframeDocument.removeEventListener("click", handleClick); } }; if (iframeRef?.current) { const iframeDocument = iframeRef.current.contentDocument; if (iframeDocument) { // Clean up existing listeners first cleanupListeners(); if (isEditableModeEnabled) { iframeDocument.addEventListener("mouseover", handleMouseOver); iframeDocument.addEventListener("mouseout", handleMouseOut); iframeDocument.addEventListener("click", handleClick); } } } // Clean up when component unmounts or dependencies change return cleanupListeners; }, [iframeRef, isEditableModeEnabled]); const selectedElement = useMemo(() => { if (!isEditableModeEnabled) return null; if (!hoveredElement) return null; return hoveredElement; }, [hoveredElement, isEditableModeEnabled]); return (
{ if (isAiWorking) { e.preventDefault(); e.stopPropagation(); toast.warning("Please wait for the AI to finish working."); } }} > {!isAiWorking && hoveredElement && selectedElement && (
{htmlTagToText(selectedElement.tagName.toLowerCase())}
)}