import React, { useState, useCallback } from 'react'; import Cropper, { Area, Point } from 'react-easy-crop'; import { Check, X, ZoomIn, ZoomOut } from 'lucide-react'; import { motion } from 'motion/react'; interface ImageCropperProps { image; aspect; onCropComplete(croppedImage) => void; onCancel() => void; circularCrop?; } export const ImageCropper.FC = ({ image, aspect, onCropComplete, onCancel, circularCrop = false }) => { const [crop, setCrop] = useState({ x}); const [zoom, setZoom] = useState(1); const [croppedAreaPixels, setCroppedAreaPixels] = useState(null); const onCropChange = (crop) => { setCrop(crop); }; const onZoomChange = (zoom) => { setZoom(zoom); }; const onCropCompleteInternal = useCallback((_croppedArea) => { setCroppedAreaPixels(croppedAreaPixels); }, []); const createImage = (url)=> new Promise((resolve, reject) => { const image = new Image(); image.addEventListener('load', () => resolve(image)); image.addEventListener('error', (error) => reject(error)); image.setAttribute('crossOrigin', 'anonymous'); image.src = url; }); const getCroppedImg = async ( imageSrc)=> { const image = await createImage(imageSrc); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (!ctx) { throw new Error('No 2d context'); } canvas.width = pixelCrop.width; canvas.height = pixelCrop.height; ctx.drawImage( image, pixelCrop.x, pixelCrop.y, pixelCrop.width, pixelCrop.height, 0, 0, pixelCrop.width, pixelCrop.height ); return new Promise((resolve, reject) => { canvas.toBlob((blob) => { if (!blob) { reject(new Error('Canvas is empty')); return; } resolve(blob); }, 'image/jpeg'); }); }; const handleDone = async () => { if (croppedAreaPixels) { try { const croppedImage = await getCroppedImg(image, croppedAreaPixels); onCropComplete(croppedImage); } catch (e) { console.error(e); } } }; return ( setZoom(Number(e.target.value))} className="flex-1 h-1.5 bg-white/10 rounded-lg appearance-none cursor-pointer accent-orange-500" /> Cancel Apply ); };