import type { ConfirmDialogOptions, ConfirmDialogVariant } from "@t3tools/contracts"; export type ConfirmDialogState = | { readonly status: "idle" } | { readonly status: "confirming"; readonly message: string; readonly variant: ConfirmDialogVariant; } | { readonly status: "closing"; readonly message: string; readonly variant: ConfirmDialogVariant; }; type PendingConfirmation = { readonly message: string; readonly variant: ConfirmDialogVariant; readonly resolve: (confirmed: boolean) => void; }; const idleState: ConfirmDialogState = { status: "idle" }; let state: ConfirmDialogState = idleState; let activeConfirmation: PendingConfirmation | null = null; let queuedConfirmations: PendingConfirmation[] = []; let registeredHostCount = 0; const listeners = new Set<() => void>(); function publish(next: ConfirmDialogState): void { state = next; for (const listener of listeners) { listener(); } } function resolvePendingConfirmations(confirmed: boolean): void { activeConfirmation?.resolve(confirmed); for (const confirmation of queuedConfirmations) { confirmation.resolve(confirmed); } activeConfirmation = null; queuedConfirmations = []; } export function readConfirmDialogState(): ConfirmDialogState { return state; } export function subscribeConfirmDialog(listener: () => void): () => void { listeners.add(listener); return () => { listeners.delete(listener); }; } /** * Registers the renderer host that can present themed confirmations. The * returned cleanup function also cancels any request left without a host. */ export function registerConfirmDialogHost(): () => void { registeredHostCount += 1; let registered = true; return () => { if (!registered) return; registered = false; registeredHostCount = Math.max(0, registeredHostCount - 1); if (registeredHostCount === 0) { resolvePendingConfirmations(false); publish(idleState); } }; } /** * Requests a themed confirmation when a host is mounted. An undefined result * means no themed host is currently available. */ export function requestConfirmDialog( message: string, options?: ConfirmDialogOptions, ): Promise | undefined { if (registeredHostCount === 0) return undefined; const confirmation = new Promise((resolve) => { const pending = { message, variant: options?.variant ?? "default", resolve, } satisfies PendingConfirmation; if (activeConfirmation || state.status === "closing") { queuedConfirmations.push(pending); return; } activeConfirmation = pending; publish({ status: "confirming", message, variant: pending.variant }); }); return confirmation; } export function respondToConfirmDialog(confirmed: boolean): void { if (state.status !== "confirming" || !activeConfirmation) return; const confirmation = activeConfirmation; activeConfirmation = null; confirmation.resolve(confirmed); publish({ status: "closing", message: state.message, variant: state.variant }); } export function completeConfirmDialogClose(): void { if (state.status !== "closing") return; const next = queuedConfirmations.shift(); if (!next) { publish(idleState); return; } activeConfirmation = next; publish({ status: "confirming", message: next.message, variant: next.variant }); } export function resetConfirmDialogForTests(): void { resolvePendingConfirmations(false); registeredHostCount = 0; publish(idleState); listeners.clear(); }