import { useMemo, useRef, useState } from "react"; import { Button, Popover, Input } from "@douyinfe/semi-ui"; import ColorPicker from "../EditorSidePanel/ColorPicker"; import { IconEdit, IconDeleteStroked, IconLock, IconUnlock, } from "@douyinfe/semi-icons"; import { Tab, Action, ObjectType, State } from "../../data/constants"; import { useLayout, useSettings, useUndoRedo, useSelect, useAreas, useSaveState, } from "../../hooks"; import { useTranslation } from "react-i18next"; import { useHover } from "usehooks-ts"; export default function Area({ data, onPointerDown, setResize, setInitDimensions, }) { const ref = useRef(null); const isHovered = useHover(ref); const { layout } = useLayout(); const { settings } = useSettings(); const { setSaveState } = useSaveState(); const { updateArea } = useAreas(); const { selectedElement, setSelectedElement, bulkSelectedElements, setBulkSelectedElements, } = useSelect(); const handleResize = (e, dir) => { setResize({ id: data.id, dir: dir }); setInitDimensions({ x: data.x, y: data.y, width: data.width, height: data.height, }); }; const lockUnlockArea = (e) => { const locking = !data.locked; updateArea(data.id, { locked: locking }); const lockArea = () => { setSelectedElement({ ...selectedElement, element: ObjectType.NONE, id: -1, open: false, }); setBulkSelectedElements((prev) => prev.filter((el) => el.id !== data.id || el.type !== ObjectType.AREA), ); }; const unlockArea = () => { const elementInBulk = { id: data.id, type: ObjectType.AREA, initialCoords: { x: data.x, y: data.y }, currentCoords: { x: data.x, y: data.y }, }; if (e.ctrlKey || e.metaKey) { setBulkSelectedElements((prev) => [...prev, elementInBulk]); } else { setBulkSelectedElements([elementInBulk]); } setSelectedElement((prev) => ({ ...prev, element: ObjectType.AREA, id: data.id, open: false, })); }; if (locking) { lockArea(); } else { unlockArea(); } }; const edit = () => { if (layout.sidebar) { setSelectedElement((prev) => ({ ...prev, element: ObjectType.AREA, id: data.id, currentTab: Tab.AREAS, open: true, })); if (selectedElement.currentTab !== Tab.AREAS) return; document .getElementById(`scroll_area_${data.id}`) .scrollIntoView({ behavior: "smooth" }); } else { setSelectedElement((prev) => ({ ...prev, element: ObjectType.AREA, id: data.id, open: true, })); } }; const onClickOutSide = () => { if (selectedElement.editFromToolbar) { setSelectedElement((prev) => ({ ...prev, editFromToolbar: false, })); return; } setSelectedElement((prev) => ({ ...prev, open: false, })); setSaveState(State.SAVING); }; const areaIsOpen = () => selectedElement.element === ObjectType.AREA && selectedElement.id === data.id && selectedElement.open; const isSelected = useMemo(() => { return ( (selectedElement.id === data.id && selectedElement.element === ObjectType.AREA) || bulkSelectedElements.some( (e) => e.type === ObjectType.AREA && e.id === data.id, ) ); }, [selectedElement, data, bulkSelectedElements]); return ( 0 ? data.width : 0} height={data.height > 0 ? data.height : 0} onPointerDown={onPointerDown} >
{data.name}
{(isHovered || (areaIsOpen() && !layout.sidebar)) && (
)}
{isHovered && ( <> e.isPrimary && handleResize(e, "tl")} /> e.isPrimary && handleResize(e, "tr")} /> e.isPrimary && handleResize(e, "bl")} /> e.isPrimary && handleResize(e, "br")} /> )}
); } function EditPopoverContent({ data }) { const [editField, setEditField] = useState({}); const { updateArea, deleteArea } = useAreas(); const { setUndoStack, setRedoStack } = useUndoRedo(); const { t } = useTranslation(); const {layout} = useLayout(); const initialColorRef = useRef(data.color); const handleColorPick = (color) => { setUndoStack((prev) => { let undoColor = initialColorRef.current; const lastColorChange = prev.findLast( (e) => e.element === ObjectType.AREA && e.aid === data.id && e.action === Action.EDIT && e.redo?.color, ); if (lastColorChange) { undoColor = lastColorChange.redo.color; } if (color === undoColor) return prev; const newStack = [ ...prev, { action: Action.EDIT, element: ObjectType.AREA, aid: data.id, undo: { color: undoColor }, redo: { color: color }, message: t("edit_area", { areaName: data.name, extra: "[color]", }), }, ]; return newStack; }); setRedoStack([]); }; return (
{t("edit")}
updateArea(data.id, { name: value })} onFocus={(e) => setEditField({ name: e.target.value })} onBlur={(e) => { if (e.target.value === editField.name) return; setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.AREA, aid: data.id, undo: editField, redo: { name: e.target.value }, message: t("edit_area", { areaName: e.target.value, extra: "[name]", }), }, ]); setRedoStack([]); }} /> updateArea(data.id, { color })} onColorPick={(color) => handleColorPick(color)} />
); }