import React, { useEffect, useRef, useState } from "react"; import { Textarea } from "../ui/textarea"; import { Button } from "../ui/button"; import { addHighlight, getAdjustedCoordinates, removeHighlight } from "./utils"; interface EditPopupProps { event: MouseEvent | null; inSelectAndEditMode: boolean; doUpdate: (updateInstruction: string, selectedElement?: HTMLElement) => void; iframeRef: React.RefObject; } const EditPopup: React.FC = ({ event, inSelectAndEditMode, doUpdate, iframeRef, }) => { // Edit state const [selectedElement, setSelectedElement] = useState< HTMLElement | undefined >(undefined); const [updateText, setUpdateText] = useState(""); // Popup state const [popupVisible, setPopupVisible] = useState(false); const [popupPosition, setPopupPosition] = useState({ x: 0, y: 0 }); // Create a wrapper ref to store inSelectAndEditMode so the value is not stale // in a event listener const inSelectAndEditModeRef = useRef(inSelectAndEditMode); // Textarea ref for focusing const textareaRef = useRef(null); function onUpdate(updateText: string) { // Perform the update doUpdate( updateText, selectedElement ? removeHighlight(selectedElement) : selectedElement ); // Unselect the element setSelectedElement(undefined); // Hide the popup setPopupVisible(false); } // Update the ref whenever the state changes useEffect(() => { inSelectAndEditModeRef.current = inSelectAndEditMode; }, [inSelectAndEditMode]); // Remove highlight and reset state when not in select and edit mode useEffect(() => { if (!inSelectAndEditMode) { if (selectedElement) removeHighlight(selectedElement); setSelectedElement(undefined); setPopupVisible(false); } }, [inSelectAndEditMode, selectedElement]); // Handle the click event useEffect(() => { // Return if not in select and edit mode if (!inSelectAndEditModeRef.current || !event) { return; } // Prevent default to avoid issues like label clicks triggering textareas, etc. event.preventDefault(); const targetElement = event.target as HTMLElement; // Return if no target element if (!targetElement) return; // Highlight and set the selected element setSelectedElement((prev) => { // Remove style from previous element if (prev) { removeHighlight(prev); } return addHighlight(targetElement); }); // Calculate adjusted coordinates const adjustedCoordinates = getAdjustedCoordinates( event.clientX, event.clientY, iframeRef.current?.getBoundingClientRect() ); // Show the popup at the click position setPopupVisible(true); setPopupPosition({ x: adjustedCoordinates.x, y: adjustedCoordinates.y }); // Reset the update text setUpdateText(""); // Focus the textarea textareaRef.current?.focus(); }, [event, iframeRef]); if (!popupVisible) return; return (