diff --git a/web/comfyui/loras_widget.js b/web/comfyui/loras_widget.js index 18828616..a6db8a52 100644 --- a/web/comfyui/loras_widget.js +++ b/web/comfyui/loras_widget.js @@ -5,13 +5,13 @@ import { updateWidgetHeight, shouldShowClipEntry, syncClipStrengthIfCollapsed, - LORA_ENTRY_HEIGHT, - HEADER_HEIGHT, - CONTAINER_PADDING, - EMPTY_CONTAINER_HEIGHT + LORA_ENTRY_HEIGHT, + HEADER_HEIGHT, + CONTAINER_PADDING, + EMPTY_CONTAINER_HEIGHT } from "./loras_widget_utils.js"; import { initDrag, createContextMenu, initHeaderDrag, initReorderDrag, handleKeyboardNavigation } from "./loras_widget_events.js"; -import { forwardMiddleMouseToCanvas, forwardWheelToCanvas, enableListWheelScroll } from "./utils.js"; +import { forwardMiddleMouseToCanvas, forwardWheelToCanvas } from "./utils.js"; import { PreviewTooltip } from "./preview_tooltip.js"; import { ensureLmStyles } from "./lm_styles_loader.js"; import { getStrengthStepPreference } from "./settings.js"; @@ -24,18 +24,11 @@ export function addLorasWidget(node, name, opts, callback) { container.className = "lm-loras-container"; forwardMiddleMouseToCanvas(container); - // Capture-phase handler: scroll the list with the wheel when it overflows. - // Falls through to forwardWheelToCanvas (canvas zoom) when the list is short. - enableListWheelScroll(container); forwardWheelToCanvas(container); // Set initial height using CSS variables approach const defaultHeight = 200; - // Content height (capped at 12 rows by renderLoras), kept up to date and used - // to fix the widget/node height in both Canvas and Nodes 2.0 (Vue) modes. - let currentContentHeight = defaultHeight; - // Check if this is a randomizer node (lock button instead of drag handle) const isRandomizerNode = opts?.isRandomizerNode === true; @@ -205,7 +198,7 @@ export function addLorasWidget(node, name, opts, callback) { container.appendChild(emptyMessage); // Set fixed height for empty state - currentContentHeight = updateWidgetHeight(container, EMPTY_CONTAINER_HEIGHT, defaultHeight, node); + updateWidgetHeight(container, EMPTY_CONTAINER_HEIGHT, defaultHeight, node); return; } @@ -652,7 +645,7 @@ export function addLorasWidget(node, name, opts, callback) { // Calculate height based on number of loras and fixed sizes const calculatedHeight = CONTAINER_PADDING + HEADER_HEIGHT + (Math.min(totalVisibleEntries, 12) * LORA_ENTRY_HEIGHT); - currentContentHeight = updateWidgetHeight(container, calculatedHeight, defaultHeight, node); + updateWidgetHeight(container, calculatedHeight, defaultHeight, node); // After all LoRA elements are created, apply selection state as the last step // This ensures the selection state is not overwritten @@ -734,31 +727,12 @@ export function addLorasWidget(node, name, opts, callback) { widgetValue = updatedValue; renderLoras(widgetValue, widget); }, - // The list area is capped at 12 rows (see calculatedHeight); beyond that the - // container scrolls. Report that capped height as both the min and preferred - // size so the node height stays fixed to the list, matching Canvas mode. - getMinHeight: () => currentContentHeight, - getHeight: () => currentContentHeight, hideOnZoom: true, selectOn: ['click', 'focus'] }); widget.value = defaultValue; - - // Canonical LiteGraph sizing hook (Canvas mode): fix the widget to the capped - // content height. Rows beyond the 12-row cap scroll inside the container. - widget.computeSize = (width) => [width, currentContentHeight]; - - // Nodes 2.0 / Vue mode reads computeLayoutSize for the node's size. Pin both - // the min and max to the capped content height so the list area is fixed to - // 12 rows (scrolling beyond), matching Canvas mode, instead of the layout - // engine measuring the full DOM and locking the node fully expanded. - widget.computeLayoutSize = () => ({ - minHeight: currentContentHeight, - maxHeight: currentContentHeight, - minWidth: 400, - }); - + widget.callback = callback; widget.onRemove = () => { diff --git a/web/comfyui/loras_widget_utils.js b/web/comfyui/loras_widget_utils.js index dec430fa..91484965 100644 --- a/web/comfyui/loras_widget_utils.js +++ b/web/comfyui/loras_widget_utils.js @@ -18,28 +18,21 @@ export function formatLoraValue(loras) { return loras; } -// Resolve the capped (12-row) height of the widget and physically cap the -// container so the list area never grows past it. -// `height` is the raw content height (already capped at 12 rows by the caller); -// the result never drops below defaultHeight. -// The max-height is the reliable lever: Nodes 2.0 / Vue mode measures the -// rendered DOM to size the node, so without an actual height cap on the element -// the list always shows every row. max-height bounds the element regardless of -// what the layout engine measures, and the overflow makes the extra rows scroll. -// Returns the resolved height so callers can also report it to ComfyUI. +// Function to update widget height consistently export function updateWidgetHeight(container, height, defaultHeight, node) { - const cappedHeight = Math.max(defaultHeight, height); - - container.style.maxHeight = `${cappedHeight}px`; - - // Force node to redraw after a short delay to ensure the DOM is updated. + // Ensure minimum height + const finalHeight = Math.max(defaultHeight, height); + + // Update CSS variables + container.style.setProperty('--comfy-widget-min-height', `${finalHeight}px`); + container.style.setProperty('--comfy-widget-height', `${finalHeight}px`); + + // Force node to update size after a short delay to ensure DOM is updated if (node) { setTimeout(() => { node.setDirtyCanvas(true, true); }, 10); } - - return cappedHeight; } // Determine if clip entry should be shown - now based on expanded property or initial diff values diff --git a/web/comfyui/utils.js b/web/comfyui/utils.js index 86963e88..34d3acb1 100644 --- a/web/comfyui/utils.js +++ b/web/comfyui/utils.js @@ -784,59 +784,6 @@ export function forwardWheelToCanvas(container, options = {}) { }, { passive: false }); } -// Marks elements whose wheel scrolling must win over the canvas zoom. -const LIST_WHEEL_SCROLL_CLASS = 'lm-wheel-scrollable'; -let listWheelScrollHookInstalled = false; - -/** - * Keep vertical wheel scrolling inside a scrollable widget container instead of - * letting ComfyUI zoom the canvas. - * - * In Nodes 2.0 / Vue mode ComfyUI's wheel→zoom handler runs on the document / - * canvas in the capture phase, which is *outer* than the widget, so a listener - * on the container (even in capture) fires too late. The reliable place to win - * is a single hook on `window` in the capture phase — the very first step of - * event dispatch. When the wheel is over a marked, scrollable element we scroll - * it manually and fully consume the event; otherwise we leave it alone so canvas - * zoom keeps working. - * @param {HTMLElement} container - The scrollable element (overflow: auto) - */ -export function enableListWheelScroll(container) { - if (!container) return; - container.classList.add(LIST_WHEEL_SCROLL_CLASS); - - if (listWheelScrollHookInstalled) return; - listWheelScrollHookInstalled = true; - - window.addEventListener('wheel', (event) => { - // Let pinch/zoom and horizontal gestures fall through to the canvas. - if (event.ctrlKey) return; - if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) return; - - const target = event.target; - if (!target || typeof target.closest !== 'function') return; - const el = target.closest(`.${LIST_WHEEL_SCROLL_CLASS}`); - if (!el) return; - - const canScrollY = el.scrollHeight > el.clientHeight + 1; - if (!canScrollY) return; // Nothing to scroll → allow canvas zoom. - - // Translate the wheel delta to pixels (line / page modes → approx px). - const unit = event.deltaMode === 1 - ? 16 - : event.deltaMode === 2 - ? el.clientHeight - : 1; - - el.scrollTop += event.deltaY * unit; - - // Consume the event so neither ComfyUI's zoom nor forwardWheelToCanvas react. - event.preventDefault(); - event.stopPropagation(); - event.stopImmediatePropagation(); - }, { capture: true, passive: false }); -} - // Get connected Lora Pool node from pool_config input export function getConnectedPoolConfigNode(node) { if (!node?.inputs) {