diff --git a/frontend/src/shared/components/CameraCapture/useImageCrop.ts b/frontend/src/shared/components/CameraCapture/useImageCrop.ts index 562d1b3..5399273 100644 --- a/frontend/src/shared/components/CameraCapture/useImageCrop.ts +++ b/frontend/src/shared/components/CameraCapture/useImageCrop.ts @@ -95,10 +95,6 @@ export function useImageCrop(options: UseImageCropOptions = {}): UseImageCropRet const drawOriginRef = useRef({ x: 0, y: 0 }); const cropAreaRef = useRef(cropArea); - useEffect(() => { - cropAreaRef.current = cropArea; - }, [cropArea]); - const setCropArea = useCallback( (area: CropArea) => { setCropAreaState(getAspectRatioAdjustedCrop(area)); @@ -177,7 +173,9 @@ export function useImageCrop(options: UseImageCropOptions = {}): UseImageCropRet startPosRef.current = { x: clientX, y: clientY }; drawOriginRef.current = { x, y }; - setCropAreaState({ x, y, width: 0, height: 0 }); + const initial = { x, y, width: 0, height: 0 }; + setCropAreaState(initial); + cropAreaRef.current = initial; isDrawingRef.current = true; activeHandleRef.current = null; @@ -203,18 +201,24 @@ export function useImageCrop(options: UseImageCropOptions = {}): UseImageCropRet const originX = drawOriginRef.current.x; const originY = drawOriginRef.current.y; - let newCrop: CropArea = { + const drawnWidth = Math.abs(currentX - originX); + const drawnHeight = aspectRatio + ? drawnWidth / aspectRatio + : Math.abs(currentY - originY); + let drawnY = Math.min(originY, currentY); + // Clamp so crop doesn't exceed container bounds when aspect ratio forces height + if (aspectRatio && drawnY + drawnHeight > 100) { + drawnY = Math.max(0, 100 - drawnHeight); + } + const newCrop: CropArea = { x: Math.min(originX, currentX), - y: Math.min(originY, currentY), - width: Math.abs(currentX - originX), - height: Math.abs(currentY - originY), + y: drawnY, + width: drawnWidth, + height: drawnHeight, }; - if (aspectRatio) { - newCrop.height = newCrop.width / aspectRatio; - } - setCropAreaState(newCrop); + cropAreaRef.current = newCrop; return; } @@ -303,7 +307,9 @@ export function useImageCrop(options: UseImageCropOptions = {}): UseImageCropRet break; } - setCropAreaState(constrainCrop(newCrop)); + const constrained = constrainCrop(newCrop); + setCropAreaState(constrained); + cropAreaRef.current = constrained; }, [isDragging, constrainCrop, aspectRatio] ); @@ -312,13 +318,17 @@ export function useImageCrop(options: UseImageCropOptions = {}): UseImageCropRet if (isDrawingRef.current) { isDrawingRef.current = false; const area = cropAreaRef.current; - if (area.width >= minSize && area.height >= minSize) { + // When aspect ratio constrains one dimension, only check the free dimension + const meetsMinSize = aspectRatio + ? area.width >= minSize + : area.width >= minSize && area.height >= minSize; + if (meetsMinSize) { setCropDrawn(true); } } activeHandleRef.current = null; setIsDragging(false); - }, [minSize]); + }, [minSize, aspectRatio]); // Add global event listeners for drag useEffect(() => {