diff --git a/src/app/globals.css b/src/app/globals.css index 203e5de1..4899a54b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -55,6 +55,10 @@ body { transition: opacity 250ms ease-in-out; } +.react-flow__node:not(.switch-dimmed) { + transition: opacity 250ms ease-in-out; +} + /* Base handle styles */ .react-flow__handle { width: 14px; diff --git a/src/components/GroupsOverlay.tsx b/src/components/GroupsOverlay.tsx index 5f55d296..6c2a0a1b 100644 --- a/src/components/GroupsOverlay.tsx +++ b/src/components/GroupsOverlay.tsx @@ -1,7 +1,7 @@ "use client"; import { useCallback, useState, useRef, useEffect } from "react"; -import { useStore, ViewportPortal } from "@xyflow/react"; +import { useViewport, ViewportPortal } from "@xyflow/react"; import { useWorkflowStore, GROUP_COLORS } from "@/store/workflowStore"; import { GroupColor } from "@/types"; @@ -492,7 +492,7 @@ export function GroupBackgroundsPortal() { // Renders group controls (headers, resize handles) using ViewportPortal above nodes export function GroupControlsOverlay() { const { groups } = useWorkflowStore(); - const zoom = useStore((s) => s.transform[2]); + const { zoom } = useViewport(); const groupIds = Object.keys(groups); diff --git a/src/components/WorkflowCanvas.tsx b/src/components/WorkflowCanvas.tsx index 665ae600..1a5103b8 100644 --- a/src/components/WorkflowCanvas.tsx +++ b/src/components/WorkflowCanvas.tsx @@ -331,11 +331,6 @@ export function WorkflowCanvas() { // Apply dimming className to nodes downstream of disabled Switch outputs const allNodes = useMemo(() => { - // Fast path: no dimming active and no stale dimmed classes to clean up - if (dimmedNodeIds.size === 0 && !nodes.some((n) => n.className?.includes("switch-dimmed"))) { - return nodes; - } - return nodes.map((node) => { // Never dim Switch or ConditionalSwitch nodes themselves if (node.type === "switch" || node.type === "conditionalSwitch") return node; diff --git a/src/components/nodes/BaseNode.tsx b/src/components/nodes/BaseNode.tsx index bbca1716..ba44b363 100644 --- a/src/components/nodes/BaseNode.tsx +++ b/src/components/nodes/BaseNode.tsx @@ -100,36 +100,27 @@ export function BaseNode({ const panelEl = settingsPanelRef.current; if (!panelEl) return; - let rafId: number | null = null; - const observer = new ResizeObserver((entries) => { - if (rafId !== null) cancelAnimationFrame(rafId); - rafId = requestAnimationFrame(() => { - rafId = null; - for (const entry of entries) { - const newPanelHeight = entry.contentRect.height; - if (newPanelHeight === 0) continue; - const delta = newPanelHeight - trackedSettingsHeightRef.current; - if (Math.abs(delta) < 2) continue; // Ignore sub-pixel changes - - trackedSettingsHeightRef.current = newPanelHeight; - setNodes((nodes) => - nodes.map((node) => { - if (node.id !== id) return node; - const currentHeight = getNodeDimension(node, "height"); - const newHeight = Math.max(minHeight, currentHeight + delta); - return applyNodeDimensions(node, getNodeDimension(node, "width"), newHeight); - }) - ); - } - }); + for (const entry of entries) { + const newPanelHeight = entry.contentRect.height; + if (newPanelHeight === 0) continue; + const delta = newPanelHeight - trackedSettingsHeightRef.current; + if (Math.abs(delta) < 2) continue; // Ignore sub-pixel changes + + trackedSettingsHeightRef.current = newPanelHeight; + setNodes((nodes) => + nodes.map((node) => { + if (node.id !== id) return node; + const currentHeight = getNodeDimension(node, "height"); + const newHeight = Math.max(minHeight, currentHeight + delta); + return applyNodeDimensions(node, getNodeDimension(node, "width"), newHeight); + }) + ); + } }); observer.observe(panelEl); - return () => { - if (rafId !== null) cancelAnimationFrame(rafId); - observer.disconnect(); - }; + return () => observer.disconnect(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [settingsExpanded, settingsPanel]); diff --git a/src/components/nodes/GenerateImageNode.tsx b/src/components/nodes/GenerateImageNode.tsx index f90716c4..4309899d 100644 --- a/src/components/nodes/GenerateImageNode.tsx +++ b/src/components/nodes/GenerateImageNode.tsx @@ -825,7 +825,7 @@ export function GenerateImageNode({ id, data, selected }: NodeProps setIsBrowseDialogOpen(false)} onModelSelected={handleBrowseModelSelect} - capabilities={IMAGE_CAPABILITIES} + initialCapabilityFilter="image" /> )} diff --git a/src/store/workflowStore.ts b/src/store/workflowStore.ts index 49632a4e..472206ab 100644 --- a/src/store/workflowStore.ts +++ b/src/store/workflowStore.ts @@ -526,7 +526,7 @@ const workflowStoreImpl: StateCreator = (set, get) => ({ }, setHoveredNodeId: (id: string | null) => { - if (get().hoveredNodeId !== id) set({ hoveredNodeId: id }); + set({ hoveredNodeId: id }); }, addNode: (type: NodeType, position: XYPosition, initialData?: Partial) => {