export type ConfirmOptions = { title: string; message?: string; confirmLabel?: string; cancelLabel?: string; destructive?: boolean; /** If true, hide the cancel button — used for simple info/alert dialogs. */ infoOnly?: boolean; }; type PendingRequest = ConfirmOptions & { resolve: (result: boolean) => void; }; class ConfirmStore { pending = $state(null); ask(options: ConfirmOptions): Promise { // If another dialog is already open, close it as cancelled so we don't stack. if (this.pending) this.pending.resolve(false); return new Promise((resolve) => { this.pending = { ...options, resolve }; }); } answer(result: boolean): void { if (!this.pending) return; const p = this.pending; this.pending = null; p.resolve(result); } } export const confirmStore = new ConfirmStore(); /** * Show a modal confirmation dialog. Resolves to true on confirm, false on cancel/Escape. * Safe on the server: falls back to the native confirm() only in the browser. */ export function confirmAction(options: ConfirmOptions): Promise { if (typeof window === 'undefined') return Promise.resolve(false); return confirmStore.ask(options); } /** * Show a modal info dialog with a single OK button. Resolves when dismissed. * Use instead of window.alert(). */ export function alertAction(options: Omit): Promise { if (typeof window === 'undefined') return Promise.resolve(); return confirmStore .ask({ ...options, infoOnly: true, confirmLabel: options.confirmLabel ?? 'OK' }) .then(() => undefined); }