"use client"; import { useEffect, useRef } from "react"; /** * Shared -based modal shell. Owners pass form contents and a * submit handler; this component handles open/close imperatively, Esc * cancellation, and backdrop click cancellation. Native gives * us focus trapping and ::backdrop styling for free. */ export default function FormDialogShell({ open, onCancel, onSubmit, title, children, cancelLabel = "Cancel", submitLabel = "Save", destructive = false, pending = false, error, }: { open: boolean; onCancel: () => void; onSubmit: () => void; title: string; children: React.ReactNode; cancelLabel?: string; submitLabel?: string; destructive?: boolean; pending?: boolean; error?: string | null; }) { const ref = useRef(null); useEffect(() => { const dialog = ref.current; if (!dialog) return; if (open && !dialog.open) dialog.showModal(); else if (!open && dialog.open) dialog.close(); }, [open]); return ( { if (!pending) onCancel(); }} onClick={(e) => { if (pending) return; if (e.target === ref.current) onCancel(); }} className="m-auto w-[min(92vw,480px)] rounded-2xl bg-white p-0 ring-1 ring-zinc-200/60 backdrop:bg-zinc-900/50 backdrop:backdrop-blur-sm" >
{ e.preventDefault(); onSubmit(); }} className="flex flex-col gap-4 p-6" >

{title}

{children}
{error && (

{error}

)}
); } /** * A labelled text input that uses 16px font-size on phones (preventing * iOS Safari auto-zoom-on-focus) and falls back to a tighter 13px on * tablets/desktop where there's no auto-zoom behavior. */ export function Field({ label, required, hint, children, }: { label: string; required?: boolean; hint?: string; children: React.ReactNode; }) { return ( ); } export const inputClass = "w-full min-w-0 rounded-md border-0 bg-zinc-100 px-3 py-2 font-mono text-base text-zinc-900 outline-none ring-1 ring-zinc-300 transition-colors focus:bg-white focus:ring-2 focus:ring-zinc-900 disabled:opacity-60 sm:text-[13px]";