{"version":3,"file":"useCropImg.mjs","sources":["../../../../../../../admin/src/future/pages/Assets/components/AssetDetails/useCropImg.ts"],"sourcesContent":["import * as React from 'react';\n\nconst QUALITY = 1;\n\ninterface NaturalSize {\n width: number;\n height: number;\n}\n\nexport interface CropRect {\n /** Origin in natural-px from the image top-left. */\n x: number;\n y: number;\n /** Crop area dimensions in natural px. */\n width: number;\n height: number;\n}\n\n/**\n * Resolve a corner-resize drag into a crop rect, keeping the opposite corner\n * (`anchor`) fixed. When `aspectRatio` is set, one dimension is snapped to the\n * ratio first (driven by whichever axis the pointer pushed furthest), then the\n * position is derived from the anchor — so a locked resize never drifts the\n * anchored corner. Pure (no clamping to image bounds; the caller clamps).\n */\nexport const resolveCornerResize = ({\n anchorX,\n anchorY,\n point,\n aspectRatio,\n}: {\n anchorX: number;\n anchorY: number;\n point: { x: number; y: number };\n aspectRatio: number | null;\n}): CropRect => {\n let width = Math.abs(point.x - anchorX);\n let height = Math.abs(point.y - anchorY);\n\n if (aspectRatio) {\n if (width / aspectRatio >= height) {\n height = width / aspectRatio;\n } else {\n width = height * aspectRatio;\n }\n }\n\n const x = point.x < anchorX ? anchorX - width : anchorX;\n const y = point.y < anchorY ? anchorY - height : anchorY;\n\n return { x, y, width, height };\n};\n\n/**\n * Custom crop state + file producer. Replaces a cropperjs-based version: the\n * crop rectangle is stored in natural-image pixels (so it stays locked across\n * window resizes), and `AssetCropEditor` overlays a div sized by\n * (cropNatural × displayRatio). produceFile draws the natural-px crop region\n * straight to a canvas.\n */\nexport const useCropImg = () => {\n const [naturalSize, setNaturalSize] = React.useState({ width: 0, height: 0 });\n const [crop, setCrop] = React.useState({ x: 0, y: 0, width: 0, height: 0 });\n const [aspectRatio, setAspectRatioState] = React.useState(null);\n const imageRef = React.useRef(null);\n\n /**\n * Call from the onLoad handler. Captures the natural dimensions and\n * seeds the crop to the full image (auto-crop area = 1).\n */\n const init = React.useCallback((image: HTMLImageElement) => {\n imageRef.current = image;\n const next: NaturalSize = { width: image.naturalWidth, height: image.naturalHeight };\n setNaturalSize(next);\n setCrop({ x: 0, y: 0, width: next.width, height: next.height });\n }, []);\n\n const clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\n /** Update crop dimensions, clamping to remain inside the image bounds. */\n const setCropSize = React.useCallback(\n (next: Partial>) => {\n setCrop((prev) => {\n const maxW = naturalSize.width - prev.x;\n const maxH = naturalSize.height - prev.y;\n let width = next.width !== undefined ? clamp(next.width, 1, maxW) : prev.width;\n let height = next.height !== undefined ? clamp(next.height, 1, maxH) : prev.height;\n\n if (aspectRatio) {\n // When aspect locked, the axis the user is editing wins; the other\n // axis follows. If both changed in one call, prefer width.\n if (next.width !== undefined) {\n height = clamp(width / aspectRatio, 1, maxH);\n } else if (next.height !== undefined) {\n width = clamp(height * aspectRatio, 1, maxW);\n }\n }\n\n return { ...prev, width, height };\n });\n },\n [naturalSize.width, naturalSize.height, aspectRatio]\n );\n\n /** Update crop origin, clamping so the crop stays inside the image. */\n const setCropPosition = React.useCallback(\n (next: Partial>) => {\n setCrop((prev) => {\n const x = next.x !== undefined ? clamp(next.x, 0, naturalSize.width - prev.width) : prev.x;\n const y =\n next.y !== undefined ? clamp(next.y, 0, naturalSize.height - prev.height) : prev.y;\n return { ...prev, x, y };\n });\n },\n [naturalSize.width, naturalSize.height]\n );\n\n /** Lock or release the crop aspect ratio. Pass `null` to free it. */\n const setAspectRatio = React.useCallback(\n (ratio: number | null) => {\n setAspectRatioState(ratio);\n if (ratio) {\n setCrop((prev) => {\n // Bring the current rect into the requested ratio without escaping\n // the image bounds.\n const maxW = naturalSize.width - prev.x;\n const maxH = naturalSize.height - prev.y;\n let width = prev.width;\n let height = width / ratio;\n if (height > maxH) {\n height = maxH;\n width = height * ratio;\n }\n if (width > maxW) {\n width = maxW;\n height = width / ratio;\n }\n return { ...prev, width: Math.round(width), height: Math.round(height) };\n });\n }\n },\n [naturalSize.width, naturalSize.height]\n );\n\n /**\n * Draw the crop region from the loaded image element straight to a canvas\n * and produce a File. The image must be CORS-clean (set crossOrigin on the\n * ); otherwise canvas.toBlob throws on tainted canvas.\n */\n const produceFile = React.useCallback(\n (name: string, mimeType: string, lastModifiedDate?: string): Promise =>\n new Promise((resolve, reject) => {\n const image = imageRef.current;\n if (!image) {\n reject(new Error('Image not ready: call init() before produceFile().'));\n return;\n }\n const canvas = document.createElement('canvas');\n canvas.width = Math.max(1, Math.round(crop.width));\n canvas.height = Math.max(1, Math.round(crop.height));\n const context = canvas.getContext('2d');\n if (!context) {\n reject(new Error('Could not get a 2D canvas context to crop the image.'));\n return;\n }\n context.drawImage(\n image,\n crop.x,\n crop.y,\n crop.width,\n crop.height,\n 0,\n 0,\n canvas.width,\n canvas.height\n );\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error('Could not export the cropped image to a blob.'));\n return;\n }\n resolve(\n new File([blob], name, {\n type: mimeType,\n lastModified: lastModifiedDate ? new Date(lastModifiedDate).getTime() : Date.now(),\n })\n );\n },\n mimeType,\n QUALITY\n );\n }),\n [crop.x, crop.y, crop.width, crop.height]\n );\n\n return {\n init,\n crop,\n naturalSize,\n aspectRatio,\n setCropSize,\n setCropPosition,\n setAspectRatio,\n produceFile,\n // Round-aware getters for the px inputs.\n width: Math.round(crop.width),\n height: Math.round(crop.height),\n };\n};\n"],"names":["QUALITY","resolveCornerResize","anchorX","anchorY","point","aspectRatio","width","Math","abs","x","height","y","useCropImg","naturalSize","setNaturalSize","React","useState","crop","setCrop","setAspectRatioState","imageRef","useRef","init","useCallback","image","current","next","naturalWidth","naturalHeight","clamp","value","min","max","setCropSize","prev","maxW","maxH","undefined","setCropPosition","setAspectRatio","ratio","round","produceFile","name","mimeType","lastModifiedDate","Promise","resolve","reject","Error","canvas","document","createElement","context","getContext","drawImage","toBlob","blob","File","type","lastModified","Date","getTime","now"],"mappings":"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"}