Spaces:
Running
Running
File size: 3,826 Bytes
6918275 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | // Custom confirmation dialog. CSS in /css/modals.css
import { callJsExtensions } from "/js/extensions.js";
const DIALOG_TYPES = {
warning: { icon: 'warning', color: 'var(--color-warning, #f59e0b)' },
danger: { icon: 'error', color: 'var(--color-error, #ef4444)' },
info: { icon: 'info', color: 'var(--color-primary, #3b82f6)' }
};
export function showConfirmDialog(options) {
const {
title = 'Confirm',
message = '',
confirmText = 'Confirm',
cancelText = 'Cancel',
type = 'warning',
extensionContext = null,
} = options;
const typeConfig = DIALOG_TYPES[type] || DIALOG_TYPES.warning;
return new Promise((resolve) => {
// Create backdrop
const backdrop = document.createElement('div');
backdrop.className = 'confirm-dialog-backdrop';
// Create dialog
const dialog = document.createElement('div');
dialog.className = 'confirm-dialog';
dialog.innerHTML = `
<div class="confirm-dialog-header">
<x-icon class="confirm-dialog-icon" style="color: ${typeConfig.color}" name="${typeConfig.icon}"></x-icon>
<span class="confirm-dialog-title">${title}</span>
</div>
<div class="confirm-dialog-body">${message}</div>
<div class="confirm-dialog-footer">
<button class="button cancel confirm-dialog-cancel">${cancelText}</button>
<button class="button confirm confirm-dialog-confirm">${confirmText}</button>
</div>
`;
backdrop.appendChild(dialog);
document.body.appendChild(backdrop);
const titleElement = dialog.querySelector('.confirm-dialog-title');
const bodyElement = dialog.querySelector('.confirm-dialog-body');
const footerElement = dialog.querySelector('.confirm-dialog-footer');
const cancelButton = dialog.querySelector('.confirm-dialog-cancel');
const confirmButton = dialog.querySelector('.confirm-dialog-confirm');
let isClosed = false;
// Show with animation
const showDialog = () => {
requestAnimationFrame(() => {
backdrop.classList.add('visible');
cancelButton?.focus();
});
};
// Close handler
const close = (result) => {
if (isClosed) return;
isClosed = true;
backdrop.classList.remove('visible');
document.removeEventListener('keydown', handleKeydown);
setTimeout(() => {
backdrop.remove();
resolve(result);
}, 200);
};
// Event listeners
cancelButton.addEventListener('click', () => close(false));
confirmButton.addEventListener('click', () => close(true));
backdrop.addEventListener('click', (e) => e.target === backdrop && close(false));
// Keyboard handling
const handleKeydown = (e) => {
if (e.key === 'Escape') {
e.preventDefault();
close(false);
return;
}
if (e.key !== 'Enter') return;
const activeElement = document.activeElement;
if (
activeElement
&& dialog.contains(activeElement)
&& (
activeElement.tagName === 'BUTTON'
|| activeElement.tagName === 'A'
|| activeElement.tagName === 'INPUT'
|| activeElement.tagName === 'TEXTAREA'
|| activeElement.tagName === 'SELECT'
|| activeElement.isContentEditable
)
) {
return;
}
e.preventDefault();
close(true);
};
document.addEventListener('keydown', handleKeydown);
const extensionData = {
options,
dialog,
backdrop,
titleElement,
bodyElement,
footerElement,
confirmButton,
cancelButton,
close,
title,
message,
type,
confirmText,
cancelText,
extensionContext,
};
callJsExtensions('confirm_dialog_after_render', extensionData)
.finally(showDialog);
});
}
|