import { useEffect, useRef, useState, type ReactNode } from 'react';
import { DialogRoot, DialogContent, DialogFooter } from './ui/dialog';
import { Input } from './ui/input';
import { buttonVariants } from './ui/button';
import { cn } from '../lib/utils';
export interface ConfirmOptions {
title: string;
body?: ReactNode;
confirmLabel?: string;
cancelLabel?: string;
danger?: boolean;
/** When set, the confirm button stays disabled until this exact text is typed. */
requireText?: string;
requireTextLabel?: string;
}
interface ConfirmRequest {
options: ConfirmOptions;
resolve: (ok: boolean) => void;
}
export function ConfirmDialog({request, onClose}: {request: ConfirmRequest | undefined; onClose: (ok: boolean) => void}) {
const [typed, setTyped] = useState('');
useEffect(() => { setTyped(''); }, [request]);
const options = request?.options;
const needsText = !!options?.requireText;
const confirmed = !needsText || typed === options?.requireText;
return { if (!open) onClose(false); }}>
{options && { if (!needsText) return; e.preventDefault(); }}>
{options.body && {options.body}
}
{needsText && }
}
;
}
/**
* Promise-based replacement for window.confirm / window.prompt(confirm-id).
* Render {confirm.element} once near the page root; ask() resolves true/false.
* Plain functions (no useCallback) keep it usable in bare vnode-tree tests.
*/
export function useConfirm() {
const [request, setRequest] = useState();
// A ref tracks the live request so back-to-back ask() calls (e.g. a fast
// double submit before re-render) cancel the previous promise instead of
// leaking it. Direct value sets keep bare vnode-tree tests working.
const current = useRef(undefined);
useEffect(() => () => {
current.current?.resolve(false);
current.current = undefined;
}, []);
const ask = (options: ConfirmOptions) => new Promise(resolve => {
current.current?.resolve(false);
const next: ConfirmRequest = {options, resolve};
current.current = next;
setRequest(next);
});
const close = (ok: boolean) => {
current.current?.resolve(ok);
current.current = undefined;
setRequest(undefined);
};
return {ask, element: };
}