"use client"; import { useEffect, useRef, useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import { Pencil, Check, X, Loader2 } from "lucide-react"; interface Props { initialName: string; /** Server action that renames and returns the new slug/name (or null on no-op). */ onRename: (name: string) => Promise<{ slug?: string; name?: string } | null>; /** Path prefix for the post-rename redirect (e.g. "/studios/"). The new slug or URL-encoded name is appended. */ redirectBase?: string; /** Which field of the rename result to append to redirectBase. Defaults to "slug". */ redirectKey?: "slug" | "name"; } export function EntityRenameInline({ initialName, onRename, redirectBase, redirectKey = "slug" }: Props) { const router = useRouter(); const [editing, setEditing] = useState(false); const [value, setValue] = useState(initialName); const [pending, start] = useTransition(); const inputRef = useRef(null); useEffect(() => { setValue(initialName); }, [initialName]); useEffect(() => { if (editing) { inputRef.current?.focus(); inputRef.current?.select(); } }, [editing]); function cancel() { setEditing(false); setValue(initialName); } function save() { const next = value.trim(); if (!next || next === initialName) { cancel(); return; } start(async () => { const r = await onRename(next); setEditing(false); if (r && redirectBase) { const key = redirectKey === "name" ? r.name : r.slug; if (key) { router.push(`${redirectBase}${redirectKey === "name" ? encodeURIComponent(key) : key}`); return; } } router.refresh(); }); } if (!editing) { return ( ); } return (
{ e.preventDefault(); save(); }} className="flex items-center gap-1" > setValue(e.target.value)} onKeyDown={(e) => { if (e.key === "Escape") cancel(); }} maxLength={120} disabled={pending} className="glass rounded-lg px-2 py-1 text-sm outline-none focus:border-[var(--color-cyan)] w-64" />
); }