import { LoaderCircle } from "lucide-react"; import { type ReactNode, useState } from "react"; import { AlertDialog, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "~/components/ui/alert-dialog.tsx"; import { Button } from "~/components/ui/button.tsx"; /** * 确认弹窗。onConfirm 可返回 Promise:执行中按钮禁用并转圈,resolve 后自动关闭,reject 时保持打开 * (错误提示由调用方 toast)。受控(open/onOpenChange)或非受控(trigger)两种用法。 * 删除} title="删除实例?" * description="…" confirmLabel="删除" destructive onConfirm={() => del.mutateAsync(id)} /> */ export function ConfirmDialog({ trigger, open: openProp, onOpenChange, title, description, confirmLabel = "确认", cancelLabel = "取消", destructive = false, confirmDisabled = false, onConfirm, children, }: { trigger?: ReactNode; open?: boolean; onOpenChange?: (open: boolean) => void; title: ReactNode; description?: ReactNode; confirmLabel?: string; cancelLabel?: string; destructive?: boolean; /** 输入未填完整时禁用确认按钮 */ confirmDisabled?: boolean; onConfirm: () => unknown | Promise; /** 描述下方的额外内容(输入确认等) */ children?: ReactNode; }) { const [inner, setInner] = useState(false); const [pending, setPending] = useState(false); const open = openProp ?? inner; const setOpen = (o: boolean) => { if (pending) return; setInner(o); onOpenChange?.(o); }; const run = async () => { setPending(true); try { await onConfirm(); setPending(false); setInner(false); onOpenChange?.(false); } catch { setPending(false); } }; return ( {trigger ? {trigger} : null} {title} {description ? {description} : null} {children} {cancelLabel} ); }