import React, { useEffect, useState } from 'react'; import theme from '../../helpers/theme'; import useCursorPosition from '../../hooks/useCursorPosition'; import { getAbsoluteCoordinate } from '../../helpers/position'; import { calcDragAndDropScale } from '../../helpers/utility'; import generateCirclesData from './data'; import { SVG, Rect, Circle } from './styled'; type Props = { left: number; top: number; width: number; height: number; onMove?: (moveCoord: CoordType) => void; onScale?: (scaleCoord: CoordType) => void; onClick?: (event: React.MouseEvent) => void; onDoubleClick?: () => void; }; type ObjPositionType = { top: number; left: number; width: number; height: number; operator: string; clickX: number; clickY: number; }; const initState = { top: 0, left: 0, width: 0, height: 0, operator: '', clickX: 0, clickY: 0, }; const OuterRect: React.FC = ({ left, top, width, height, onMove, onScale, onClick, onDoubleClick, }: Props) => { const data = generateCirclesData(width, height); const [state, setState] = useState(initState); const [cursorPosition, setRef] = useCursorPosition(20); const handleMouseDown = (e: React.MouseEvent | React.TouchEvent): void => { e.preventDefault(); const operatorId = (e.target as HTMLElement).getAttribute( 'data-id', ) as string; const coord = getAbsoluteCoordinate(document.body, e); setRef(document.body); setState({ top, left, width, height, operator: operatorId, clickX: coord.x, clickY: coord.y, }); }; const handleMouseUp = (): void => { setRef(null); setState(initState); }; const calcMoveResult = ( currentPosition: PointType, startPosition: PointType, objPosition: ObjPositionType, ): CoordType => ({ left: currentPosition.x - (startPosition.x - objPosition.left), top: currentPosition.y - (startPosition.y - objPosition.top), width: objPosition.width, height: objPosition.height, }); const calcScaleResult = ( currentPosition: PointType, objPosition: ObjPositionType, ): CoordType => { const scaleData = calcDragAndDropScale({ ...objPosition, moveX: currentPosition.x || 0, moveY: currentPosition.y || 0, }); const scaleWidth = scaleData.width || 0; const scaleHeight = scaleData.height || 0; const maxTop = objPosition.top + objPosition.height; const maxLeft = objPosition.left + objPosition.width; scaleData.left = scaleData.left > maxLeft ? maxLeft : scaleData.left; scaleData.top = scaleData.top > maxTop ? maxTop : scaleData.top; scaleData.width = scaleWidth > 0 ? scaleWidth : 0; scaleData.height = scaleHeight > 0 ? scaleHeight : 0; return scaleData; }; useEffect(() => { if (cursorPosition.x && cursorPosition.y && state.clickX) { if (state.operator === 'move' && onMove) { onMove( calcMoveResult( { x: cursorPosition.x, y: cursorPosition.y }, { x: state.clickX, y: state.clickY }, state, ), ); } else if (onScale) { onScale( calcScaleResult( { x: cursorPosition.x, y: cursorPosition.y, }, state, ), ); } } }, [cursorPosition, state]); useEffect(() => { window.addEventListener('mouseup', handleMouseUp); window.addEventListener('touchend', handleMouseUp); return (): void => { window.removeEventListener('mouseup', handleMouseUp); window.removeEventListener('touchend', handleMouseUp); }; }, []); return ( {onScale && data.map((attr: CircleType) => ( ))} ); }; export default OuterRect;