Files

78 lines
3.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useCallback, useState } from 'react';
import { createPortal } from 'react-dom';
import Cropper, { type Area } from 'react-easy-crop';
import { getCroppedImage } from '../lib/cropImage';
interface ImageCropModalProps {
src: string;
fileName: string;
onCancel: () => void;
onConfirm: (file: File) => void;
}
export default function ImageCropModal({ src, fileName, onCancel, onConfirm }: ImageCropModalProps) {
const [crop, setCrop] = useState({ x: 0, y: 0 });
const [zoom, setZoom] = useState(1);
const [area, setArea] = useState<Area | null>(null);
const [processing, setProcessing] = useState(false);
const onCropComplete = useCallback((_: Area, pixels: Area) => setArea(pixels), []);
const handleConfirm = async () => {
if (!area) return;
setProcessing(true);
try {
const file = await getCroppedImage(src, area, fileName);
onConfirm(file);
} finally {
setProcessing(false);
}
};
return createPortal(
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4" dir="rtl">
<div className="w-full max-w-md rounded-2xl bg-[var(--surface)] shadow-2xl overflow-hidden">
<div className="flex items-center justify-between px-5 py-4 border-b border-[var(--border)]">
<p className="text-base font-bold text-[var(--text)]">برش تصویر</p>
<button onClick={onCancel}
className="text-[var(--text-3)] hover:text-[var(--text-2)] text-xl leading-none">×</button>
</div>
<div className="relative w-full h-72 bg-[var(--surface-2)]">
<Cropper
image={src}
crop={crop}
zoom={zoom}
aspect={1}
cropShape="round"
showGrid={false}
onCropChange={setCrop}
onZoomChange={setZoom}
onCropComplete={onCropComplete}
/>
</div>
<div className="px-5 py-4 space-y-4">
<div className="flex items-center gap-3">
<span className="text-xs text-[var(--text-2)] shrink-0">بزرگ‌نمایی</span>
<input type="range" min={1} max={3} step={0.01} value={zoom}
onChange={e => setZoom(Number(e.target.value))}
className="w-full accent-[var(--primary)]" />
</div>
<div className="flex items-center justify-end gap-3">
<button onClick={onCancel} disabled={processing}
className="px-4 py-2 rounded-xl text-sm font-medium text-[var(--text-2)] bg-[var(--surface-2)] hover:bg-[var(--surface-3)] dark:hover:bg-[var(--surface-2)] disabled:opacity-50">
انصراف
</button>
<button onClick={handleConfirm} disabled={processing || !area}
className="px-4 py-2 rounded-xl text-sm font-medium text-[var(--on-primary)] bg-[var(--primary-600)] hover:bg-[var(--primary-700)] disabled:opacity-50">
{processing ? 'در حال برش...' : 'ذخیره'}
</button>
</div>
</div>
</div>
</div>,
document.body,
);
}