File size: 2,499 Bytes
6b6430f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
027e29f
 
 
 
 
 
 
 
 
6b6430f
027e29f
 
 
 
 
 
 
6b6430f
b2cddc3
 
 
 
6b6430f
 
 
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
/* 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 <main> 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 <main> when the browser takes over, and components keep
  // filling in after that. So watch the whole body, and let each measurement find the <main> 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();
})();