"use client"; import { useRef, useState, useTransition } from "react"; import { FIELD_MAX_BYTES, compressionSummary } from "@/lib/image-compress"; import { prepareImageFile } from "@/lib/image-compress-dom"; export function ImageField({ name, label, defaultValue = "", height = 130, fit = "cover", maxBytes = FIELD_MAX_BYTES, }: { name: string; label: string; defaultValue?: string; height?: number; fit?: "cover" | "contain"; maxBytes?: number; }) { const [value, setValue] = useState(defaultValue); const [note, setNote] = useState(null); const [error, setError] = useState(null); const [busy, setBusy] = useState(false); const [, startTransition] = useTransition(); const fileRef = useRef(null); async function onFile(event: React.ChangeEvent) { const file = event.target.files?.[0]; if (!file) return; setError(null); setNote(null); setBusy(true); try { // Plus de refus « image trop lourde » : le navigateur redimensionne et // compresse lui-même, en ne descendant que le nécessaire. const prepared = await prepareImageFile(file, { maxBytes }); startTransition(() => { setValue(prepared.dataUri); setNote(compressionSummary(prepared)); }); } catch (cause) { setError(cause instanceof Error ? cause.message : "Image refusée."); if (fileRef.current) fileRef.current.value = ""; } finally { setBusy(false); } } function clear() { setValue(""); setError(null); setNote(null); if (fileRef.current) fileRef.current.value = ""; } return (
{value && fit === "contain" && ( // eslint-disable-next-line @next/next/no-img-element )} {!value && {busy ? "Compression en cours…" : "Aucune image"}}
{value && !busy && ( )}
{note && !error &&
{note}
} {error &&
{error}
}
); }