"use client"; /** * Dialog — minimal fixed-overlay shell shared by the workspace dialogs * (create, share, invite, template). Escape / backdrop closes. Mirrors the * behavior of the core ConfirmDialog without coupling to it. */ import { useEffect, type ReactNode } from "react"; import { X } from "lucide-react"; export interface DialogProps { open: boolean; title: string; description?: ReactNode; onClose: () => void; children: ReactNode; /** Footer button row (Cancel / Confirm). Omit for custom footers. */ footer?: ReactNode; /** Width class (default max-w-lg). */ width?: string; /** tests/README.md selector convention (e.g. `move-dialog`). */ testId?: string; } export function Dialog({ open, title, description, onClose, children, footer, width = "max-w-lg", testId }: DialogProps) { useEffect(() => { if (!open) return; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [open, onClose]); if (!open) return null; return (

{title}

{description ?
{description}
: null}
{children}
{footer ?
{footer}
: null}
); } /** Standard footer: Cancel + a primary action (optionally destructive/busy). */ export function DialogFooter({ onCancel, onAction, actionLabel, busy, destructive, disabled, testId }: { onCancel: () => void; onAction: () => void; actionLabel: string; busy?: boolean; destructive?: boolean; disabled?: boolean; /** tests/README.md selector on the primary button (e.g. `move-dialog-confirm`). */ testId?: string; }) { return ( <> ); }