"use client"; import { useRef, useState, type ComponentProps, type ReactNode } from "react"; import { useFormStatus } from "react-dom"; function FormFields({ children }: { children: ReactNode }) { const { pending } = useFormStatus(); return (
{children}
); } /** Keeps action errors beside the submitted form, without losing entered values. */ export function ActionForm({ action, children, ...props }: Omit, "action"> & { action: (data: FormData) => Promise; }) { const preserveValues = useRef(false); const [message, setMessage] = useState(""); const [failed, setFailed] = useState(false); return (
{ if (preserveValues.current) event.preventDefault(); }} onChange={() => setMessage("")} onKeyDown={(event) => { if ((event.metaKey || event.ctrlKey) && event.key === "Enter") { event.preventDefault(); const button = event.currentTarget.querySelector( 'button[type="submit"]', ); if (button && !button.disabled) button.click(); } }} action={async (data) => { setMessage(""); preserveValues.current = false; try { await action(data); setFailed(false); setMessage("已保存"); } catch { preserveValues.current = true; setFailed(true); setMessage("操作失败,请检查输入后重试。填写内容已保留。"); } }} > {children} {message && (

{message}

)} ); }