// run-modal.js — homepage click-hijack for embedding links. Opens a // that renders the run's embedding via panel-grid.js. import { mountPanels } from './panel-grid.js?v=1'; const dialog = document.getElementById('run-modal'); const host = document.getElementById('modal-panel-host'); const controls = document.getElementById('modal-compare-controls'); const closeBtn = document.getElementById('run-modal-close'); const runsSlot = document.getElementById('runs-slot'); let active = null; // { destroy } returned by mountPanels function openFor(stem) { if (!dialog || !host || !controls) return; if (active) { try { active.destroy(); } catch (_) {} active = null; } active = mountPanels({ host, controls, stems: [stem] }); if (typeof dialog.showModal === 'function') dialog.showModal(); else dialog.setAttribute('open', ''); } function closeModal() { if (!dialog) return; if (dialog.open) dialog.close(); if (active) { try { active.destroy(); } catch (_) {} active = null; } } function onRunsClick(ev) { if (ev.defaultPrevented) return; if (ev.button !== undefined && ev.button !== 0) return; if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return; const a = ev.target.closest('a[data-role="embedding-link"]'); if (!a) return; if (!runsSlot || !runsSlot.contains(a)) return; const stem = a.dataset.stem; if (!stem) return; ev.preventDefault(); openFor(stem); } function wire() { if (!dialog) return; if (runsSlot) runsSlot.addEventListener('click', onRunsClick); if (closeBtn) closeBtn.addEventListener('click', closeModal); dialog.addEventListener('close', () => { if (active) { try { active.destroy(); } catch (_) {} active = null; } }); // Clicking the backdrop (native behavior fires a click on the dialog // itself, with target === dialog) closes the modal. dialog.addEventListener('click', (ev) => { if (ev.target === dialog) closeModal(); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', wire); } else { wire(); } // htmx re-renders #runs-slot every 3s. Delegation on #runs-slot survives the // swap (the slot element itself is stable), so we don't need to re-bind — // but we keep the hook in case a consumer ever replaces the slot wholesale. document.body.addEventListener('htmx:afterSwap', (ev) => { if (ev.detail?.target?.id === 'runs-slot' && runsSlot && !runsSlot._runModalWired) { runsSlot.addEventListener('click', onRunsClick); runsSlot._runModalWired = true; } });