// Shared modal overlay utility (extracted from Sidebar.js in H4 4.0). // Builds a single `#app-modal-overlay` over the app, stopping propagation so // inputs/clicks inside the modal never reach the 3D controls. /** @typedef {import('../types.js').ModalOptions} ModalOptions */ /** * Show a custom modal overlay. Replaces any existing overlay. * @param {ModalOptions} options * @returns {void} */ export function showCustomModal({ title, contentHTML, onConfirm, onCancel, confirmText = "Confirm", cancelText = "Cancel", isAlert = false }) { // Clean old modal overlays const oldOverlay = document.getElementById('app-modal-overlay'); if (oldOverlay) oldOverlay.remove(); const overlay = document.createElement('div'); overlay.id = 'app-modal-overlay'; overlay.className = 'modal-overlay'; document.body.appendChild(overlay); overlay.innerHTML = `
`; // Prevent propagation so inputs/clicks inside modal don't affect 3D controls ['mousedown', 'click', 'keydown', 'keyup'].forEach(evt => { overlay.addEventListener(evt, (e) => e.stopPropagation()); }); const closeOverlay = () => { overlay.classList.remove('active'); setTimeout(() => overlay.remove(), 300); }; const confirmBtn = overlay.querySelector('#modal-confirm-btn'); if (confirmBtn) { confirmBtn.onclick = () => { if (onConfirm) onConfirm(overlay); closeOverlay(); }; } const cancelBtn = overlay.querySelector('#modal-cancel-btn'); if (cancelBtn) { cancelBtn.onclick = () => { if (onCancel) onCancel(); closeOverlay(); }; } const closeX = overlay.querySelector('#modal-close-x'); if (closeX) { closeX.onclick = () => { if (onCancel) onCancel(); closeOverlay(); }; } // Force reflow and activate transition overlay.offsetHeight; overlay.classList.add('active'); } /** * Open the bookmark naming modal and lock/unlock PointerLock camera flight controls. * @param {{ docId: string, chunkIndex: number, dimensionIndex: number, value: number }} coordinates * @param {function(string): void} callback * @param {object} [controls] * @returns {void} */ export function showBookmarkNamingModal(coordinates, callback, controls = null) { if (controls && controls.isLocked) { controls.unlock(); } const valStr = typeof coordinates.value === 'number' ? coordinates.value.toFixed(4) : coordinates.value; const contentHTML = `Bookmark: Document ${coordinates.docId} · Chunk ${coordinates.chunkIndex} · Dimension ${coordinates.dimensionIndex} (Value: ${valStr})