From 89c3ef93e024cea43717a4187c0e6087d77da3f4 Mon Sep 17 00:00:00 2001 From: Behnam Date: Thu, 25 Dec 2025 17:44:10 +0000 Subject: [PATCH 1/2] fix: allow nodes to collapse by skipping resize constraints When a node is collapsed, the onResize handler was enforcing minimum height constraints, preventing LiteGraph from shrinking the node to its collapsed state. This caused the image preview area to remain visible even when collapsed. Added collapsed state check at the start of both onResize handlers to skip constraint enforcement when the node is collapsed. Co-Authored-By: Behnam & Claude Code --- src/nodes/base/BaseNode.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nodes/base/BaseNode.ts b/src/nodes/base/BaseNode.ts index 4389501..f7993a7 100644 --- a/src/nodes/base/BaseNode.ts +++ b/src/nodes/base/BaseNode.ts @@ -420,6 +420,9 @@ export function createNodeClass( // Add resize handler with constraint enforcement (unless overridden by image preview) if (!config.showImagePreview) { this.onResize = function (size: [number, number]) { + // Don't enforce constraints when node is collapsed - let LiteGraph handle collapse sizing + if (this.flags?.collapsed) return + // Prevent circular updates if (this._isResizing) return this._isResizing = true @@ -694,6 +697,9 @@ export function createNodeClass( // Add onResize handler to sync widgets when manual resizing happens this.onResize = function (size: [number, number]) { + // Don't enforce constraints when node is collapsed - let LiteGraph handle collapse sizing + if (this.flags?.collapsed) return + // Prevent circular updates if (this._isResizing) return this._isResizing = true From 0d7d484fc7a63b73e5d01cad64d66b6171d469f4 Mon Sep 17 00:00:00 2001 From: Behnam Date: Thu, 25 Dec 2025 17:48:14 +0000 Subject: [PATCH 2/2] fix: add collapse support to custom nodes Extended the collapse fix to all custom nodes that don't use createNodeClass(): - PromptNode: Added onResize handler and collapsed check in onDrawForeground - NegativePromptNode: Added onResize handler and collapsed check - SeedNode: Added onResize handler and collapsed check - ImageSourceNode: Added onResize handler and collapsed check All nodes now properly collapse when clicking the collapse button. Co-Authored-By: Behnam & Claude Code --- src/nodes/input/ImageSourceNode.ts | 16 ++++++++++++++++ src/nodes/input/PromptNode.ts | 16 ++++++++++++++++ src/nodes/input/SeedNode.ts | 16 ++++++++++++++++ src/nodes/processing/NegativePromptNode.ts | 16 ++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/src/nodes/input/ImageSourceNode.ts b/src/nodes/input/ImageSourceNode.ts index b4cb534..6a2d739 100644 --- a/src/nodes/input/ImageSourceNode.ts +++ b/src/nodes/input/ImageSourceNode.ts @@ -5,6 +5,7 @@ import { extractWorkflowFromPngFile, type WorkflowMetadata } from '../../lib/png // Extend LGraphNode type for our custom properties interface ImageSourceNodeType extends LGraphNode { resizable?: boolean + onResize?: (size: [number, number]) => void _dropZoneRect?: { x: number; y: number; width: number; height: number } _isDragOver?: boolean _imageLoaded?: HTMLImageElement | null @@ -36,6 +37,18 @@ export function ImageSourceNode(this: ImageSourceNodeType) { this.color = NODE_TYPE_COLOURS.imageSource this.bgcolor = adjustBrightness(NODE_TYPE_COLOURS.imageSource, -40) + // Handle resize - skip constraints when collapsed to allow LiteGraph collapse + this.onResize = function (size: [number, number]) { + // Don't enforce constraints when node is collapsed + if (this.flags?.collapsed) return + + // Enforce minimum size for usability + const minWidth = 200 + const minHeight = 150 + if (size[0] < minWidth) size[0] = minWidth + if (size[1] < minHeight) size[1] = minHeight + } + // Store reference for callbacks // eslint-disable-next-line @typescript-eslint/no-this-alias const nodeRef = this @@ -131,6 +144,9 @@ export function ImageSourceNode(this: ImageSourceNodeType) { // Custom foreground drawing - draws image preview and drop zone this.onDrawForeground = function (ctx: CanvasRenderingContext2D) { + // Don't draw content when node is collapsed + if (this.flags?.collapsed) return + const titleHeight = 26 const slotHeight = 20 const widgetHeight = 30 diff --git a/src/nodes/input/PromptNode.ts b/src/nodes/input/PromptNode.ts index bf8f377..6fb8298 100644 --- a/src/nodes/input/PromptNode.ts +++ b/src/nodes/input/PromptNode.ts @@ -6,6 +6,7 @@ interface PromptNodeType extends LGraphNode { _textarea?: HTMLTextAreaElement _editing: boolean resizable?: boolean + onResize?: (size: [number, number]) => void } /** @@ -30,6 +31,18 @@ export function PromptNode(this: PromptNodeType) { this.size = [280, 180] this.resizable = true + // Handle resize - skip constraints when collapsed to allow LiteGraph collapse + this.onResize = function (size: [number, number]) { + // Don't enforce constraints when node is collapsed + if (this.flags?.collapsed) return + + // Enforce minimum size for usability + const minWidth = 180 + const minHeight = 100 + if (size[0] < minWidth) size[0] = minWidth + if (size[1] < minHeight) size[1] = minHeight + } + // Store reference for callbacks // eslint-disable-next-line @typescript-eslint/no-this-alias const nodeRef = this @@ -51,6 +64,9 @@ export function PromptNode(this: PromptNodeType) { // Custom foreground drawing - draws the textarea that fills the node this.onDrawForeground = function (ctx: CanvasRenderingContext2D) { + // Don't draw content when node is collapsed + if (this.flags?.collapsed) return + const bounds = getTextareaBounds() if (bounds.height < 20) return diff --git a/src/nodes/input/SeedNode.ts b/src/nodes/input/SeedNode.ts index 2e81195..6926c6a 100644 --- a/src/nodes/input/SeedNode.ts +++ b/src/nodes/input/SeedNode.ts @@ -4,6 +4,7 @@ import { NODE_TYPE_COLOURS } from '../../types/nodes' // Extend LGraphNode type for our custom properties interface SeedNodeType extends LGraphNode { resizable?: boolean + onResize?: (size: [number, number]) => void _randomizeRect?: { x: number; y: number; width: number; height: number } } @@ -33,6 +34,18 @@ export function SeedNode(this: SeedNodeType) { this.color = NODE_TYPE_COLOURS.seed this.bgcolor = adjustBrightness(NODE_TYPE_COLOURS.seed, -40) + // Handle resize - skip constraints when collapsed to allow LiteGraph collapse + this.onResize = function (size: [number, number]) { + // Don't enforce constraints when node is collapsed + if (this.flags?.collapsed) return + + // Enforce minimum size for usability + const minWidth = 150 + const minHeight = 100 + if (size[0] < minWidth) size[0] = minWidth + if (size[1] < minHeight) size[1] = minHeight + } + // Store reference for callbacks // eslint-disable-next-line @typescript-eslint/no-this-alias const nodeRef = this @@ -50,6 +63,9 @@ export function SeedNode(this: SeedNodeType) { // Custom foreground drawing - draws Randomize button this.onDrawForeground = function (ctx: CanvasRenderingContext2D) { + // Don't draw content when node is collapsed + if (this.flags?.collapsed) return + // Calculate button position (below widgets) const titleHeight = 26 const widgetHeight = 30 diff --git a/src/nodes/processing/NegativePromptNode.ts b/src/nodes/processing/NegativePromptNode.ts index 96d4bac..3dcc4d5 100644 --- a/src/nodes/processing/NegativePromptNode.ts +++ b/src/nodes/processing/NegativePromptNode.ts @@ -16,6 +16,7 @@ const COMMON_NEGATIVES: Record = { // Extend LGraphNode type for our custom properties interface NegativePromptNodeType extends LGraphNode { resizable?: boolean + onResize?: (size: [number, number]) => void _buttonRects: Array<{ x: number; y: number; width: number; height: number; label: string }> } @@ -42,6 +43,18 @@ export function NegativePromptNode(this: NegativePromptNodeType) { this.color = NODE_TYPE_COLOURS.negativePrompt this.bgcolor = adjustBrightness(NODE_TYPE_COLOURS.negativePrompt, -40) + // Handle resize - skip constraints when collapsed to allow LiteGraph collapse + this.onResize = function (size: [number, number]) { + // Don't enforce constraints when node is collapsed + if (this.flags?.collapsed) return + + // Enforce minimum size for usability + const minWidth = 180 + const minHeight = 150 + if (size[0] < minWidth) size[0] = minWidth + if (size[1] < minHeight) size[1] = minHeight + } + // Store button rectangles for click detection this._buttonRects = [] @@ -51,6 +64,9 @@ export function NegativePromptNode(this: NegativePromptNodeType) { // Custom foreground drawing - draws quick-add buttons this.onDrawForeground = function (ctx: CanvasRenderingContext2D) { + // Don't draw content when node is collapsed + if (this.flags?.collapsed) return + // Calculate button area (below the widget) const widgetHeight = 60 // Approximate height of textarea widget const titleHeight = 26