/* Rune Labs: inside surogate.ai a demo drops its own header (the page row already names it) and reports its height, so the page sizes the frame to fit and nothing scrolls inside it. The height is the bottom of main's children, not of main itself: Gradio stretches
to fill the frame, so measuring it would grow the frame, which grows main, forever. surogate.ai asks for this with ?embed=surogate. Being in a frame is not enough: huggingface.co shows every Space in one too, and there the header and footer should stay. */ (() => { if (window.self === window.top || !new URLSearchParams(location.search).has("embed")) return; document.documentElement.classList.add("rune-embedded"); let last = 0; const contentBottom = (main) => { let bottom = 0; for (const child of main.children) bottom = Math.max(bottom, child.getBoundingClientRect().bottom); return bottom + window.scrollY + parseFloat(getComputedStyle(main).paddingBottom || "0"); }; const send = () => { const main = document.querySelector("main"); if (!main) return; const height = Math.ceil(contentBottom(main) + 28); if (Math.abs(height - last) < 2) return; last = height; window.parent.postMessage({ type: "rune-labs:height", height }, "*"); }; // Gradio renders on the server, then replaces
when the browser takes over, and components keep // filling in after that. So watch the whole body, and let each measurement find the
of the moment. let queued = false; const schedule = () => { if (queued) return; queued = true; requestAnimationFrame(() => { queued = false; send(); }); }; const sizes = new ResizeObserver(schedule); const start = () => { new MutationObserver(() => { const main = document.querySelector("main"); if (main) for (const child of main.children) sizes.observe(child); schedule(); }).observe(document.body, { childList: true, subtree: true, attributes: true, characterData: true }); addEventListener("load", schedule); schedule(); }; // One "used" note on the first real interaction, so the page can tell a demo opened from a demo tried. const used = () => window.parent.postMessage({ type: "rune-labs:used" }, "*"); addEventListener("pointerdown", used, { once: true, capture: true }); addEventListener("keydown", used, { once: true, capture: true }); if (document.readyState === "loading") addEventListener("DOMContentLoaded", start); else start(); })();