"use client"; import React, { useState, useCallback } from "react"; import Cropper from "react-easy-crop"; const RATIOS = [ { label: "Hero Banner (Ultra Wide)", value: 21 / 9, text: "21/9" }, { label: "News Feed (Widescreen)", value: 16 / 9, text: "16/9" }, { label: "Profile / Post (Square)", value: 1 / 1, text: "1/1" }, ]; export default function PanelEditor() { const [image, setImage] = useState(null); const [crops, setCrops] = useState>( RATIOS.reduce((acc, r) => ({ ...acc, [r.text]: { x: 0, y: 0, zoom: 1 } }), {}) ); const [completedCrops, setCompletedCrops] = useState>({}); const [isExporting, setIsExporting] = useState(false); const [results, setResults] = useState>({}); const onSelectFile = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { const reader = new FileReader(); reader.onload = () => setImage(reader.result as string); reader.readAsDataURL(e.target.files[0]); } }; const handleExport = async () => { setIsExporting(true); const bundle: Record = {}; for (const ratio of RATIOS) { const crop = completedCrops[ratio.text]; if (crop) bundle[ratio.text] = await getCroppedImg(image!, crop); } setResults(bundle); setIsExporting(false); }; return (
FIX

IMAGE FRAMER PRO v3.0

{image && ( )}
{!image ? (
📁

Editor is Empty

Upload a high-resolution image to begin the multi-aspect framing process.

) : (
{RATIOS.map((ratio) => (
Aspect Ratio

{ratio.label}

Current Zoom

{Math.round((crops[ratio.text]?.zoom || 1) * 100)}%

setCrops((prev) => ({ ...prev, [ratio.text]: { ...prev[ratio.text], ...c } })) } onZoomChange={(z) => setCrops((prev) => ({ ...prev, [ratio.text]: { ...prev[ratio.text], zoom: z } })) } onCropComplete={(_, px) => setCompletedCrops((prev) => ({ ...prev, [ratio.text]: px })) } objectFit="cover" showGrid={true} />
Adjust Zoom setCrops((prev) => ({ ...prev, [ratio.text]: { ...prev[ratio.text], zoom: Number(e.target.value) }, })) } className="flex-1 accent-indigo-500 h-2 bg-zinc-800 rounded-lg appearance-none cursor-pointer" />
))}
)}
{Object.keys(results).length > 0 && (

EXPORT BUNDLE

{Object.entries(results).map(([ratio, b64]) => (
{ratio} Result
Crop preview