clean up code even further

This commit is contained in:
Abi Raja 2024-05-29 17:28:09 -04:00
parent 2709312943
commit 43ae003c83
2 changed files with 72 additions and 61 deletions

View File

@ -1,12 +1,7 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { Textarea } from "../ui/textarea"; import { Textarea } from "../ui/textarea";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { addHighlight, getAdjustedCoordinates, removeHighlight } from "./utils";
function removeHighlight(element: HTMLElement) {
element.style.outline = "";
element.style.backgroundColor = "";
return element;
}
interface EditPopupProps { interface EditPopupProps {
event: MouseEvent | null; event: MouseEvent | null;
@ -24,50 +19,43 @@ const EditPopup: React.FC<EditPopupProps> = ({
doUpdate, doUpdate,
iframeRef, iframeRef,
}) => { }) => {
const [editText, setEditText] = useState(""); // Edit state
const [selectedElement, setSelectedElement] = useState< const [selectedElement, setSelectedElement] = useState<
HTMLElement | undefined HTMLElement | undefined
>(undefined); >(undefined);
const [updateText, setUpdateText] = useState("");
// Popup state
const [popupVisible, setPopupVisible] = useState(false); const [popupVisible, setPopupVisible] = useState(false);
const [popupPosition, setPopupPosition] = useState({ x: 0, y: 0 }); const [popupPosition, setPopupPosition] = useState({ x: 0, y: 0 });
const inSelectAndEditModeRef = useRef(inSelectAndEditMode); // Create a ref for the state // 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<HTMLTextAreaElement | null>(null); const textareaRef = useRef<HTMLTextAreaElement | null>(null);
function updateHighlight(targetElement: HTMLElement) { function onUpdate(updateText: string) {
setSelectedElement((prev) => { // Perform the update
// Remove style from previous element
if (prev) {
removeHighlight(prev);
}
// Add style to new element
targetElement.style.outline = "2px dashed #1846db";
targetElement.style.backgroundColor = "#bfcbf5";
return targetElement;
});
}
function handleEditSubmit(editText: string) {
doUpdate( doUpdate(
editText, updateText,
selectedElement ? removeHighlight(selectedElement) : selectedElement selectedElement ? removeHighlight(selectedElement) : selectedElement
); );
// Unselect the element
setSelectedElement(undefined); setSelectedElement(undefined);
// Hide the popup
setPopupVisible(false); setPopupVisible(false);
} }
// Update the ref whenever the state changes
useEffect(() => { useEffect(() => {
if (popupVisible && textareaRef.current) { inSelectAndEditModeRef.current = inSelectAndEditMode;
textareaRef.current.focus(); }, [inSelectAndEditMode]);
}
}, [popupVisible]);
useEffect(() => {
if (!popupVisible) {
setEditText("");
}
}, [popupVisible, setEditText]);
// Remove highlight and reset state when not in select and edit mode
useEffect(() => { useEffect(() => {
if (!inSelectAndEditMode) { if (!inSelectAndEditMode) {
if (selectedElement) removeHighlight(selectedElement); if (selectedElement) removeHighlight(selectedElement);
@ -76,48 +64,47 @@ const EditPopup: React.FC<EditPopupProps> = ({
} }
}, [inSelectAndEditMode, selectedElement]); }, [inSelectAndEditMode, selectedElement]);
// Handle the click event
useEffect(() => { useEffect(() => {
// Return if not in select and edit mode // Return if not in select and edit mode
if (!inSelectAndEditModeRef.current || !event) { if (!inSelectAndEditModeRef.current || !event) {
return; return;
} }
const { clientX, clientY } = event;
// Prevent default to avoid issues like label clicks triggering textareas, etc. // Prevent default to avoid issues like label clicks triggering textareas, etc.
event.preventDefault(); event.preventDefault();
const targetElement = event.target as HTMLElement; const targetElement = event.target as HTMLElement;
// Return if no target element // Return if no target element
if (!targetElement) { if (!targetElement) return;
return;
// Highlight and set the selected element
setSelectedElement((prev) => {
// Remove style from previous element
if (prev) {
removeHighlight(prev);
} }
return addHighlight(targetElement);
});
// Highlight the selected element // Calculate adjusted coordinates
updateHighlight(targetElement); const adjustedCoordinates = getAdjustedCoordinates(
event.clientX,
event.clientY,
iframeRef.current?.getBoundingClientRect()
);
// Show popup at click position, slightly offset to be right under the cursor // Show the popup at the click position
setPopupVisible(false);
// Calculate offsets
const rect = iframeRef.current?.getBoundingClientRect();
const offsetX = rect ? rect.left : 0;
const offsetY = rect ? rect.top : 0;
// Adjust for scale
const scale = 1; // the scale factor applied to the iframe
const scaledX = clientX / scale + offsetX;
const scaledY = clientY / scale + offsetY;
setPopupPosition({ x: scaledX, y: scaledY });
setPopupVisible(true); setPopupVisible(true);
}, [event]); setPopupPosition({ x: adjustedCoordinates.x, y: adjustedCoordinates.y });
// Update the ref whenever the state changes // Reset the update text
useEffect(() => { setUpdateText("");
inSelectAndEditModeRef.current = inSelectAndEditMode;
}, [inSelectAndEditMode]); // Focus the textarea
textareaRef.current?.focus();
}, [event, iframeRef]);
if (!popupVisible) return; if (!popupVisible) return;
@ -128,12 +115,12 @@ const EditPopup: React.FC<EditPopupProps> = ({
> >
<Textarea <Textarea
ref={textareaRef} ref={textareaRef}
value={editText} value={updateText}
onChange={(e) => setEditText(e.target.value)} onChange={(e) => setUpdateText(e.target.value)}
placeholder="Tell the AI what to change about this element..." placeholder="Tell the AI what to change about this element..."
/> />
<div className="flex justify-end mt-2"> <div className="flex justify-end mt-2">
<Button onClick={() => handleEditSubmit(editText)}>Update</Button> <Button onClick={() => onUpdate(updateText)}>Update</Button>
</div> </div>
</div> </div>
); );

View File

@ -0,0 +1,24 @@
export function removeHighlight(element: HTMLElement) {
element.style.outline = "";
element.style.backgroundColor = "";
return element;
}
export function addHighlight(element: HTMLElement) {
element.style.outline = "2px dashed #1846db";
element.style.backgroundColor = "#bfcbf5";
return element;
}
export function getAdjustedCoordinates(
x: number,
y: number,
rect: DOMRect | undefined
) {
const offsetX = rect ? rect.left : 0;
const offsetY = rect ? rect.top : 0;
// Adjust for scale
const scale = 1; // the scale factor applied to the iframe
return { x: x / scale + offsetX, y: y / scale + offsetY };
}