"use client"; import { useEffect, useRef, useState, useTransition } from "react"; type EditableCellProps = { value: string; onSave: (next: string) => Promise<{ ok: boolean; error?: string }>; label?: string; isCurrentlyEditing?: boolean; onEditStart?: () => void; onEditEnd?: () => void; }; export default function EditableCell({ value, onSave, label, isCurrentlyEditing, onEditStart, onEditEnd, }: EditableCellProps) { const [editing, setEditing] = useState(false); const [draft, setDraft] = useState(value); const [error, setError] = useState(null); const [isPending, startTransition] = useTransition(); const inputRef = useRef(null); useEffect(() => { if (!editing) setDraft(value); }, [value, editing]); useEffect(() => { if (!error) return; const id = setTimeout(() => setError(null), 3000); return () => clearTimeout(id); }, [error]); function begin() { setDraft(value); setEditing(true); onEditStart?.(); requestAnimationFrame(() => { inputRef.current?.focus(); inputRef.current?.select(); }); } function cancel() { setEditing(false); setDraft(value); setError(null); onEditEnd?.(); } function commit() { if (draft === value) { cancel(); return; } startTransition(async () => { const result = await onSave(draft); if (result.ok) { setEditing(false); setError(null); onEditEnd?.(); } else { setError(result.error ?? "Save failed"); } }); } if (!editing) { return ( ); } return (
setDraft(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); commit(); } else if (e.key === "Escape") { e.preventDefault(); cancel(); } }} disabled={isPending} className="w-full min-w-0 rounded-md border-0 bg-zinc-100 px-2 py-1 font-mono text-base text-zinc-900 outline-none ring-1 ring-zinc-300 focus:bg-white focus:ring-2 focus:ring-zinc-900 disabled:opacity-60 sm:text-[13px]" />
{error && (

{error}

)}
); }