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;
|
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) {
|
function setupWave(node) {
|
||||||
const st = { duration: 0, peaks: null, audio: new Audio(), playing: false };
|
const st = { duration: 0, peaks: null, audio: new Audio(), playing: false };
|
||||||
node._wave = st;
|
node._wave = st;
|
||||||
@@ -38,7 +89,12 @@ function setupWave(node) {
|
|||||||
canvas.width = 640; canvas.height = 160;
|
canvas.width = 640; canvas.height = 160;
|
||||||
canvas.style.cssText = "width:100%;height:160px;background:#141418;border-radius:4px;cursor:pointer;";
|
canvas.style.cssText = "width:100%;height:160px;background:#141418;border-radius:4px;cursor:pointer;";
|
||||||
wrap.append(bar, canvas);
|
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 ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
const sjw = getW(node, "segments_json"); // machine field — hide it
|
const sjw = getW(node, "segments_json"); // machine field — hide it
|
||||||
|
|||||||
Reference in New Issue
Block a user