Audio Wave JS: fix DOM-widget width-collapse (keepDomWidgetFullWidth) + explicit height
addDOMWidget widgets collapse to ~half width on select/re-layout; added the portable keepDomWidgetFullWidth helper (ResizeObserver + node.size[0] reference) called after addDOMWidget, with getMinHeight and cleanup on remove. Neutral widget type (not preview). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+57
-1
@@ -21,6 +21,57 @@ function computePeaks(buf, n) {
|
||||
return peaks;
|
||||
}
|
||||
|
||||
// Keep a ComfyUI DOM widget at full node width (fixes the collapse-to-half-width bug on
|
||||
// selection / re-layout). Portable helper; call once after addDOMWidget.
|
||||
function keepDomWidgetFullWidth(node, container) {
|
||||
const GRID_SEL = '[data-testid="node-widgets"], .lg-node-widgets';
|
||||
const ROW_SEL = '[data-testid="node-widget"], .lg-node-widget';
|
||||
const MAX_MARGIN = 40;
|
||||
let enforcing = false, marginLogical = Infinity, gridObserver = null;
|
||||
|
||||
function refFromDom() {
|
||||
const grid = container.closest(GRID_SEL);
|
||||
if (!grid) return 0;
|
||||
let w = 0;
|
||||
for (const row of Array.from(grid.querySelectorAll(ROW_SEL))) {
|
||||
if (row.contains(container)) continue;
|
||||
const c = row.lastElementChild;
|
||||
if (c && c.clientWidth > w) w = c.clientWidth;
|
||||
}
|
||||
if (!w && grid.clientWidth > 0) {
|
||||
const dot = grid.querySelector(`${ROW_SEL.split(",")[0]} > :first-child`);
|
||||
w = grid.clientWidth - (dot?.offsetWidth ?? 0);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
function refFromNodeSize(cw) {
|
||||
const nodeW = node.size?.[0] ?? 0;
|
||||
if (nodeW <= 0) return 0;
|
||||
if (cw > 0) { const m = nodeW - cw; if (m >= 0 && m < marginLogical) marginLogical = Math.min(m, MAX_MARGIN); }
|
||||
const margin = Number.isFinite(marginLogical) ? marginLogical : MAX_MARGIN / 2;
|
||||
return Math.round(nodeW - margin);
|
||||
}
|
||||
function reference(cw) {
|
||||
let w = refFromDom();
|
||||
if (!w) w = refFromNodeSize(cw);
|
||||
if (!w) for (const wd of node.widgets ?? []) { const el = wd.inputEl || wd.element; if (el && el !== container && el.offsetWidth > w) w = el.offsetWidth; }
|
||||
if (!w && container.parentElement) w = container.parentElement.clientWidth;
|
||||
return w;
|
||||
}
|
||||
function enforce() {
|
||||
if (enforcing) return;
|
||||
if (!gridObserver) { const grid = container.closest(GRID_SEL); if (grid) { gridObserver = new ResizeObserver(enforce); gridObserver.observe(grid); } }
|
||||
const cw = container.clientWidth;
|
||||
const ref = reference(cw);
|
||||
if (ref > 0 && Math.abs(cw - ref) > 2) { enforcing = true; container.style.width = ref + "px"; requestAnimationFrame(() => { enforcing = false; }); }
|
||||
}
|
||||
const ro = new ResizeObserver(enforce);
|
||||
ro.observe(container);
|
||||
const origOnResize = node.onResize;
|
||||
node.onResize = function (size) { origOnResize?.call(this, size); enforce(); };
|
||||
return () => { ro.disconnect(); gridObserver?.disconnect(); };
|
||||
}
|
||||
|
||||
function setupWave(node) {
|
||||
const st = { duration: 0, peaks: null, audio: new Audio(), playing: false };
|
||||
node._wave = st;
|
||||
@@ -38,7 +89,12 @@ function setupWave(node) {
|
||||
canvas.width = 640; canvas.height = 160;
|
||||
canvas.style.cssText = "width:100%;height:160px;background:#141418;border-radius:4px;cursor:pointer;";
|
||||
wrap.append(bar, canvas);
|
||||
node.addDOMWidget("wave", "wave", wrap, { serialize: false });
|
||||
// Neutral type (NOT "preview" — that triggers aspect-ratio sizing that collapses width),
|
||||
// with an explicit height, then pin the width against the collapse-on-select bug.
|
||||
node.addDOMWidget("wave", "wave", wrap, { serialize: false, getMinHeight: () => 205 });
|
||||
const cleanupWidth = keepDomWidgetFullWidth(node, wrap);
|
||||
const origRemoved = node.onRemoved;
|
||||
node.onRemoved = function () { try { cleanupWidth(); } catch (e) { /* ignore */ } return origRemoved?.apply(this, arguments); };
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
const sjw = getW(node, "segments_json"); // machine field — hide it
|
||||
|
||||
Reference in New Issue
Block a user