diff --git a/web/comfyui/lm_styles.css b/web/comfyui/lm_styles.css index 7b4eec42..556bdcfc 100644 --- a/web/comfyui/lm_styles.css +++ b/web/comfyui/lm_styles.css @@ -120,6 +120,15 @@ outline: none; } +/* Vue node mode: prevent content from pushing node size via ResizeObserver. + contain:size breaks the feedback loop — the container's intrinsic size + is determined solely by CSS, not by how many LoRAs are inside. */ +.lm-loras-container.lm-vue-node { + height: 100%; + min-height: var(--comfy-widget-min-height, 200px); + contain: layout size; +} + .lm-loras-container:focus { outline: none; } diff --git a/web/comfyui/loras_widget.js b/web/comfyui/loras_widget.js index bbabb1c8..69086edd 100644 --- a/web/comfyui/loras_widget.js +++ b/web/comfyui/loras_widget.js @@ -2,19 +2,14 @@ import { createToggle, createArrowButton, createDragHandle, updateEntrySelection import { parseLoraValue, formatLoraValue, - updateWidgetHeight, shouldShowClipEntry, - syncClipStrengthIfCollapsed, - LORA_ENTRY_HEIGHT, - HEADER_HEIGHT, - CONTAINER_PADDING, - EMPTY_CONTAINER_HEIGHT + syncClipStrengthIfCollapsed } from "./loras_widget_utils.js"; import { initDrag, createContextMenu, initHeaderDrag, initReorderDrag, handleKeyboardNavigation } from "./loras_widget_events.js"; import { forwardMiddleMouseToCanvas, forwardWheelToCanvas, enableListWheelScroll } from "./utils.js"; import { PreviewTooltip } from "./preview_tooltip.js"; import { ensureLmStyles } from "./lm_styles_loader.js"; -import { getStrengthStepPreference, getLoraWidgetMaxVisibleLoras } from "./settings.js"; +import { getStrengthStepPreference } from "./settings.js"; export function addLorasWidget(node, name, opts, callback) { ensureLmStyles(); @@ -29,15 +24,13 @@ export function addLorasWidget(node, name, opts, callback) { // Set initial height using CSS variables approach const defaultHeight = 200; - // In Vue/node-2.0 mode, cap the widget height so it shows at most N entries. - // This prevents content from driving the node size beyond the cap. - // canvas/legacy mode is unaffected. + // Set a fixed minimum height so the node has a reasonable starting size. + // Adding or removing LoRAs does NOT change the node size — the container + // scrolls when content exceeds the allocated space. + container.style.setProperty('--comfy-widget-min-height', `${defaultHeight}px`); + if (typeof LiteGraph !== 'undefined' && LiteGraph.vueNodesMode) { - const maxLoras = getLoraWidgetMaxVisibleLoras(); - const gap = 5; // flex gap from .lm-loras-container CSS - const maxH = CONTAINER_PADDING + HEADER_HEIGHT + maxLoras * LORA_ENTRY_HEIGHT + maxLoras * gap; - container.style.maxHeight = `${maxH}px`; - container.style.setProperty('--comfy-widget-max-height', `${maxH}px`); + container.classList.add('lm-vue-node'); // Window capture-phase hook: scroll the widget instead of zooming the canvas // when the wheel is over a scrollable loras list. enableListWheelScroll(container); @@ -210,9 +203,6 @@ export function addLorasWidget(node, name, opts, callback) { emptyMessage.textContent = "No LoRAs added"; emptyMessage.className = "lm-lora-empty-state"; container.appendChild(emptyMessage); - - // Set fixed height for empty state - updateWidgetHeight(container, EMPTY_CONTAINER_HEIGHT, defaultHeight, node); return; } @@ -259,9 +249,6 @@ export function addLorasWidget(node, name, opts, callback) { // Initialize the header drag functionality initHeaderDrag(header, widget, renderLoras); - // Track the total visible entries for height calculation - let totalVisibleEntries = lorasData.length; - // Render each lora entry lorasData.forEach((loraData) => { const { name, strength, clipStrength, active } = loraData; @@ -533,7 +520,6 @@ export function addLorasWidget(node, name, opts, callback) { // If expanded, show the clip entry if (isExpanded) { - totalVisibleEntries++; const clipEl = document.createElement("div"); clipEl.className = "lm-lora-clip-entry"; @@ -657,10 +643,6 @@ 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); - 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 container.querySelectorAll('.lm-lora-entry').forEach(entry => { diff --git a/web/comfyui/loras_widget_utils.js b/web/comfyui/loras_widget_utils.js index 91484965..bcc8eeb9 100644 --- a/web/comfyui/loras_widget_utils.js +++ b/web/comfyui/loras_widget_utils.js @@ -1,12 +1,5 @@ import { app } from "../../scripts/app.js"; -// Fixed sizes for component calculations -export const LORA_ENTRY_HEIGHT = 40; // Height of a single lora entry -export const CLIP_ENTRY_HEIGHT = 40; // Height of a clip entry -export const HEADER_HEIGHT = 32; // Height of the header section -export const CONTAINER_PADDING = 12; // Top and bottom padding -export const EMPTY_CONTAINER_HEIGHT = 100; // Height when no loras are present - // Parse LoRA entries from value export function parseLoraValue(value) { if (!value) return []; @@ -18,23 +11,6 @@ export function formatLoraValue(loras) { return loras; } -// Function to update widget height consistently -export function updateWidgetHeight(container, height, defaultHeight, node) { - // 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); - } -} - // Determine if clip entry should be shown - now based on expanded property or initial diff values export function shouldShowClipEntry(loraData) { // If expanded property exists, use that diff --git a/web/comfyui/settings.js b/web/comfyui/settings.js index 05b1f63d..fedd4957 100644 --- a/web/comfyui/settings.js +++ b/web/comfyui/settings.js @@ -39,9 +39,6 @@ const NEW_TAB_ZOOM_LEVEL = 0.8; const STRENGTH_STEP_SETTING_ID = "loramanager.strength_step"; const STRENGTH_STEP_DEFAULT = 0.05; -const LORA_WIDGET_MAX_VISIBLE_SETTING_ID = "loramanager.lora_widget_max_visible_loras"; -const LORA_WIDGET_MAX_VISIBLE_DEFAULT = 12; - // ============================================================================ // Helper Functions // ============================================================================ @@ -363,32 +360,6 @@ const getStrengthStepPreference = (() => { }; })(); -const getLoraWidgetMaxVisibleLoras = (() => { - let settingsUnavailableLogged = false; - - return () => { - const settingManager = app?.extensionManager?.setting; - if (!settingManager || typeof settingManager.get !== "function") { - if (!settingsUnavailableLogged) { - console.warn("LoRA Manager: settings API unavailable, using default max visible loras."); - settingsUnavailableLogged = true; - } - return LORA_WIDGET_MAX_VISIBLE_DEFAULT; - } - - try { - const value = settingManager.get(LORA_WIDGET_MAX_VISIBLE_SETTING_ID); - return value ?? LORA_WIDGET_MAX_VISIBLE_DEFAULT; - } catch (error) { - if (!settingsUnavailableLogged) { - console.warn("LoRA Manager: unable to read max visible loras setting, using default.", error); - settingsUnavailableLogged = true; - } - return LORA_WIDGET_MAX_VISIBLE_DEFAULT; - } - }; -})(); - // ============================================================================ // Register Extension with All Settings // ============================================================================ @@ -492,19 +463,6 @@ app.registerExtension({ tooltip: "Step size for adjusting LoRA strength via arrow buttons or keyboard (default: 0.05)", category: ["LoRA Manager", "LoRA Widget", "Strength Step"], }, - { - id: LORA_WIDGET_MAX_VISIBLE_SETTING_ID, - name: "Node 2.0: Maximum visible LoRA entries", - type: "slider", - attrs: { - min: 3, - max: 50, - step: 1, - }, - defaultValue: LORA_WIDGET_MAX_VISIBLE_DEFAULT, - tooltip: "When using Node 2.0 rendering, limit the loras widget height to show at most this many entries (default: 12). Excess entries are accessible via scrollbar.", - category: ["LoRA Manager", "LoRA Widget", "Max Visible"], - }, ], async setup() { await loadWorkflowOptions(); @@ -591,5 +549,4 @@ export { getUsageStatisticsPreference, getNewTabTemplatePreference, getStrengthStepPreference, - getLoraWidgetMaxVisibleLoras, };