import { useEffect, useRef, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { updateStyleMap } from "../../store/reducers/treeReducer"; import styles from '../Resizable/resizable.module.css'; export function useResizer({ id }) { const styleMap = useSelector((state) => state.treeReducer.styleMap[id]); const virtualPos = useRef({ top: null, bottom: null, left: null, right: null, }); const [dim, setDim] = useState({ width: styleMap.width, height: styleMap.height, }); const divRef = useRef(); const dirRef = useRef(); const isResizingRef = useRef(false); const dispatch = useDispatch(); useEffect(() => { setDim({ width: styleMap.width, height: styleMap.height, }); }, [styleMap, id]); const calWidth = () => Math.floor( Math.max(0, virtualPos.current.right - virtualPos.current.left) ) + "px"; const calHeight = () => Math.floor( Math.max(0, virtualPos.current.bottom - virtualPos.current.top) ) + "px"; const initVirtualPosition = () => { if (divRef.current) { const rect = divRef.current.getBoundingClientRect(); virtualPos.current = { top: rect.top, left: rect.left, right: rect.right, bottom: rect.bottom, }; } }; const handleMouseMove = (e) => { if (!isResizingRef.current || !divRef.current) return; let newDim = { ...dim }; switch (dirRef.current) { case 0: virtualPos.current.top = e.clientY; newDim.height = calHeight(); break; case 1: virtualPos.current.right = e.clientX; newDim.width = calWidth(); break; case 2: virtualPos.current.bottom = e.clientY; newDim.height = calHeight(); break; case 3: virtualPos.current.left = e.clientX; newDim.width = calWidth(); break; } setDim(newDim); }; const handleMouseUp = () => { divRef.current.classList.remove(styles.layer) divRef.current.style.userSelect = ""; isResizingRef.current = false; dispatch( updateStyleMap({ id, style: { ...styleMap, width: Number(dirRef.current) % 2 ? calWidth() : styleMap.width, height: Number(dirRef.current) % 2 ? styleMap.height : calHeight(), }, }) ); dirRef.current = null; document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; const handleMouseDown = (e, direction) => { e.preventDefault(); e.stopPropagation(); divRef.current.classList.add(styles.layer) isResizingRef.current = true; dirRef.current = direction; initVirtualPosition(); divRef.current.style.userSelect = "none"; document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); }; return { divRef, dim, handleMouseDown, }; }