/** * User confirmation utility * Wrapper for window.confirm() - note: this violates no-alert rule but is required * for critical user confirmations that cannot be replaced with React modals. * This function should be used sparingly and only when absolutely necessary. * * Technical justification: window.confirm() is a blocking synchronous API * that cannot be replicated with React modals without significant refactoring. * Used only for critical destructive actions (delete operations). */ export function userConfirm(message: string): Promise { return confirmOverlay(message) } function confirmOverlay(message: string): Promise { const doc = globalThis.document if (!doc) { return Promise.resolve(false) } return new Promise((resolve) => { const overlay = doc.createElement('div') overlay.setAttribute('role', 'dialog') overlay.setAttribute('aria-modal', 'true') overlay.tabIndex = -1 overlay.style.position = 'fixed' overlay.style.inset = '0' overlay.style.background = 'rgba(0,0,0,0.6)' overlay.style.display = 'flex' overlay.style.alignItems = 'center' overlay.style.justifyContent = 'center' overlay.style.zIndex = '9999' const panel = doc.createElement('div') panel.style.background = '#fff' panel.style.borderRadius = '12px' panel.style.padding = '16px' panel.style.maxWidth = '520px' panel.style.width = 'calc(100% - 32px)' panel.style.boxShadow = '0 10px 30px rgba(0,0,0,0.35)' const text = doc.createElement('p') text.textContent = message text.style.margin = '0 0 16px 0' text.style.color = '#111827' const buttons = doc.createElement('div') buttons.style.display = 'flex' buttons.style.gap = '12px' buttons.style.justifyContent = 'flex-end' const cancel = doc.createElement('button') cancel.type = 'button' cancel.textContent = 'Cancel' cancel.style.padding = '8px 12px' cancel.style.borderRadius = '10px' cancel.style.border = '1px solid #e5e7eb' cancel.style.background = '#f3f4f6' const confirm = doc.createElement('button') confirm.type = 'button' confirm.textContent = 'Confirm' confirm.style.padding = '8px 12px' confirm.style.borderRadius = '10px' confirm.style.border = '1px solid #ef4444' confirm.style.background = '#fee2e2' confirm.style.color = '#991b1b' buttons.append(cancel, confirm) panel.append(text, buttons) overlay.append(panel) doc.body.append(overlay) overlay.focus() let resolved = false const resolveOnce = (next: boolean): void => { if (resolved) { return } resolved = true cleanup() resolve(next) } function onCancel(): void { resolveOnce(false) } function onConfirm(): void { resolveOnce(true) } function onKeyDown(e: KeyboardEvent): void { if (e.key === 'Escape') { e.preventDefault() resolveOnce(false) return } if (e.key === 'Enter') { e.preventDefault() resolveOnce(true) } } function cleanup(): void { overlay.removeEventListener('keydown', onKeyDown) cancel.removeEventListener('click', onCancel) confirm.removeEventListener('click', onConfirm) overlay.remove() } cancel.addEventListener('click', onCancel) confirm.addEventListener('click', onConfirm) overlay.addEventListener('keydown', onKeyDown) }) }