export type SquareImageCropRect = { x: number; y: number; size: number; }; export function clampNumber(value: number, min: number, max: number) { return Math.max(min, Math.min(max, value)); } export function getSquareCropSizeBounds(imageSize: { width: number; height: number; }) { const maxSize = Math.max(1, Math.min(imageSize.width, imageSize.height)); const minSize = Math.min(maxSize, Math.max(48, maxSize * 0.18)); return { minSize, maxSize }; } export function buildCenteredSquareImageCropRect(imageSize: { width: number; height: number; }): SquareImageCropRect { const size = Math.max(1, Math.min(imageSize.width, imageSize.height)); return { x: Math.max(0, (imageSize.width - size) / 2), y: Math.max(0, (imageSize.height - size) / 2), size, }; } export function clampSquareImageCropRect( imageSize: { width: number; height: number }, crop: SquareImageCropRect, ): SquareImageCropRect { const { minSize, maxSize } = getSquareCropSizeBounds(imageSize); const size = clampNumber(crop.size, minSize, maxSize); return { x: clampNumber(crop.x, 0, Math.max(0, imageSize.width - size)), y: clampNumber(crop.y, 0, Math.max(0, imageSize.height - size)), size, }; }