Spaces:
Running
Running
File size: 3,506 Bytes
9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a 3225df7 9659b5a | 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 | /* LilyScript layout fitter.
*
* Sets two CSS variables on :root that drive the workspace panel heights:
* --ls-fill-h height of the bottom "Score List | editor" row (left column)
* --ls-sheet-h height of the right "Sheet music" preview panel
*
* Two modes, because the embedding context decides what "fill the screen" means:
*
* • Standalone (the app is the top-level page): size to the real viewport, so the
* bottom row fills the space under Compose + Logs and the sheet panel fills the
* window. Recompute on resize + when the left column changes (ResizeObserver).
*
* • Embedded in an auto-height iframe (Hugging Face Spaces wraps the Gradio app in
* an iframe that grows to fit its content): here window.innerHeight / 100vh are
* NOT stable — they track the iframe, which tracks the content, which we'd be
* sizing from the viewport… an unbounded feedback loop (the page scroll height
* grows forever). So when embedded we use FIXED pixel heights and install no
* viewport/resize observers. Nothing references the viewport, so nothing loops.
*/
(function () {
'use strict';
var BOTTOM_GAP = 16; // breathing room below the fill row (standalone)
var MIN_FILL = 360; // floor for the bottom row
// Fixed heights used when embedded (no viewport to measure against).
var EMBED_FILL_H = 460; // Score List | editor row
var EMBED_SHEET_H = 720; // Sheet music preview
// True when running inside an iframe (HF Spaces, blog embeds, etc.). Accessing
// window.top across origins throws — treat that as "embedded" too.
var embedded = (function () {
try { return window.self !== window.top; } catch (e) { return true; }
})();
function setVar (name, px) {
document.documentElement.style.setProperty(name, px + 'px');
}
function fillEl () {
var col = document.getElementById('compose-col');
return col ? col.querySelector(':scope > .lp-fill') : null;
}
// Standalone: derive the bottom row height from the live viewport.
function recompute () {
var fill = fillEl();
if (!fill) return;
var top = fill.getBoundingClientRect().top; // viewport-relative
var avail = window.innerHeight - top - BOTTOM_GAP;
if (avail < MIN_FILL) avail = MIN_FILL;
setVar('--ls-fill-h', avail);
setVar('--ls-sheet-h', Math.max(320, window.innerHeight - 110));
}
var raf = null;
function schedule () {
if (raf) return;
raf = requestAnimationFrame(function () { raf = null; recompute(); });
}
function boot () {
var col = document.getElementById('compose-col');
if (embedded) {
// Fixed heights — no viewport reads, no observers, no loop.
setVar('--ls-fill-h', EMBED_FILL_H);
setVar('--ls-sheet-h', EMBED_SHEET_H);
if (!col) setTimeout(boot, 300); // wait for Gradio to mount, then set once
return;
}
recompute();
window.addEventListener('resize', schedule);
if (col && window.ResizeObserver) {
var ro = new ResizeObserver(schedule);
ro.observe(col);
// the two fixed blocks (Compose, Logs) drive the fill row's top
var fixed = col.querySelectorAll(':scope > .lp-fixed');
for (var i = 0; i < fixed.length; i++) ro.observe(fixed[i]);
}
if (!col) setTimeout(boot, 300);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', boot);
} else {
boot();
}
if (!embedded) setTimeout(recompute, 1200); // late pass after fonts/player settle
console.log('[layout-fit] loaded (embedded=' + embedded + ')');
})();
|