From 8e98dc4b43d82ba6acf2278d37c2f75f590f2cbd Mon Sep 17 00:00:00 2001 From: shrimbly Date: Mon, 2 Mar 2026 22:32:58 +1300 Subject: [PATCH] feat(46-03): remove header props from 9 node components (batch 1) - EaseCurveNode.tsx - Generate3DNode.tsx - GenerateAudioNode.tsx - GenerateImageNode.tsx - GenerateVideoNode.tsx - GLBViewerNode.tsx - ImageCompareNode.tsx - LLMGenerateNode.tsx - OutputGalleryNode.tsx Removed deprecated BaseNode props: title, customTitle, comment, onCustomTitleChange, onCommentChange, commentNavigation, headerAction, headerButtons, titlePrefix, onExpand, onRun Also removed unused useCommentNavigation imports and variables. Co-Authored-By: Claude Opus 4.6 --- src/components/nodes/EaseCurveNode.tsx | 21 ---------- src/components/nodes/GLBViewerNode.tsx | 8 ---- src/components/nodes/Generate3DNode.tsx | 48 ---------------------- src/components/nodes/GenerateAudioNode.tsx | 26 ------------ src/components/nodes/GenerateImageNode.tsx | 11 ----- src/components/nodes/GenerateVideoNode.tsx | 11 ----- src/components/nodes/ImageCompareNode.tsx | 12 ------ src/components/nodes/LLMGenerateNode.tsx | 9 ---- src/components/nodes/OutputGalleryNode.tsx | 8 ---- 9 files changed, 154 deletions(-) diff --git a/src/components/nodes/EaseCurveNode.tsx b/src/components/nodes/EaseCurveNode.tsx index c27aa275..e6f9e435 100644 --- a/src/components/nodes/EaseCurveNode.tsx +++ b/src/components/nodes/EaseCurveNode.tsx @@ -4,7 +4,6 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react" import { createPortal } from "react-dom"; import { Handle, Position, NodeProps, Node, useReactFlow } from "@xyflow/react"; import { BaseNode } from "./BaseNode"; -import { useCommentNavigation } from "@/hooks/useCommentNavigation"; import { useWorkflowStore } from "@/store/workflowStore"; import { EaseCurveNodeData } from "@/types"; import { checkEncoderSupport } from "@/hooks/useStitchVideos"; @@ -40,7 +39,6 @@ const PRESET_NAMES = new Set(EASING_PRESETS); export function EaseCurveNode({ id, data, selected }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const regenerateNode = useWorkflowStore((state) => state.regenerateNode); const isRunning = useWorkflowStore((state) => state.isRunning); @@ -300,13 +298,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} selected={selected} - commentNavigation={commentNavigation ?? undefined} minWidth={340} minHeight={480} > @@ -336,13 +328,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} selected={selected} - commentNavigation={commentNavigation ?? undefined} minWidth={340} minHeight={480} > @@ -363,16 +349,9 @@ export function EaseCurveNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} - onRun={handleRun} selected={selected} isExecuting={isRunning} hasError={nodeData.status === "error"} - commentNavigation={commentNavigation ?? undefined} minWidth={340} minHeight={VIDEO_HEIGHT} > diff --git a/src/components/nodes/GLBViewerNode.tsx b/src/components/nodes/GLBViewerNode.tsx index 696e547c..7dae3e4d 100644 --- a/src/components/nodes/GLBViewerNode.tsx +++ b/src/components/nodes/GLBViewerNode.tsx @@ -5,7 +5,6 @@ import { Handle, Position, NodeProps, Node } from "@xyflow/react"; import { Canvas, useThree, useFrame } from "@react-three/fiber"; import { OrbitControls } from "@react-three/drei"; import { BaseNode } from "./BaseNode"; -import { useCommentNavigation } from "@/hooks/useCommentNavigation"; import { useWorkflowStore } from "@/store/workflowStore"; import { useToast } from "@/components/Toast"; import { GLBViewerNodeData } from "@/types"; @@ -202,7 +201,6 @@ function LoadingIndicator() { export function GLBViewerNode({ id, data, selected }: NodeProps) { const nodeData = data as GLBViewerNodeData; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const fileInputRef = useRef(null); const captureRef = useRef<(() => string | null) | null>(null); @@ -360,13 +358,7 @@ export function GLBViewerNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} selected={selected} - commentNavigation={commentNavigation ?? undefined} contentClassName={nodeData.glbUrl ? "flex-1 min-h-0 overflow-hidden flex flex-col" : undefined} > ; export function Generate3DNode({ id, data, selected }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const { replicateApiKey, falApiKey, kieApiKey } = useProviderApiKeys(); const [isBrowseDialogOpen, setIsBrowseDialogOpen] = useState(false); @@ -88,43 +86,6 @@ export function Generate3DNode({ id, data, selected }: NodeProps ( - - ), [currentProvider]); - - // Compute model page URL for external link - const modelPageUrl = useMemo(() => { - if (!nodeData.selectedModel?.modelId) return null; - return getModelPageUrl(currentProvider, nodeData.selectedModel.modelId); - }, [currentProvider, nodeData.selectedModel?.modelId]); - - // Header action element - external link + browse button - const headerAction = useMemo(() => ( - <> - {modelPageUrl && nodeData.selectedModel?.modelId && ( - e.stopPropagation()} - className="nodrag nopan text-neutral-500 hover:text-neutral-300 transition-colors" - title={`View on ${getProviderDisplayName(currentProvider)}`} - > - - - - - )} - - - ), [modelPageUrl, nodeData.selectedModel?.modelId, currentProvider]); - // Track previous status to detect error transitions const prevStatusRef = useRef(nodeData.status); @@ -144,18 +105,9 @@ export function Generate3DNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} - onRun={handleRegenerate} selected={selected} isExecuting={isRunning} hasError={nodeData.status === "error"} - headerAction={headerAction} - titlePrefix={titlePrefix} - commentNavigation={commentNavigation ?? undefined} > {/* Dynamic input handles based on model schema */} {nodeData.inputSchema && nodeData.inputSchema.length > 0 ? ( diff --git a/src/components/nodes/GenerateAudioNode.tsx b/src/components/nodes/GenerateAudioNode.tsx index 123cab37..17197d1c 100644 --- a/src/components/nodes/GenerateAudioNode.tsx +++ b/src/components/nodes/GenerateAudioNode.tsx @@ -4,7 +4,6 @@ import React, { useCallback, useState, useEffect, useMemo } from "react"; import { Handle, Position, NodeProps, Node, useReactFlow } from "@xyflow/react"; import { BaseNode } from "./BaseNode"; import { ProviderBadge } from "./ProviderBadge"; -import { useCommentNavigation } from "@/hooks/useCommentNavigation"; import { ModelParameters } from "./ModelParameters"; import { useWorkflowStore } from "@/store/workflowStore"; import { GenerateAudioNodeData, ProviderType, SelectedModel, ModelInputDef } from "@/types"; @@ -17,7 +16,6 @@ type GenerateAudioNodeType = Node; export function GenerateAudioNode({ id, data, selected }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const generationsPath = useWorkflowStore((state) => state.generationsPath); const [isBrowseDialogOpen, setIsBrowseDialogOpen] = useState(false); @@ -191,21 +189,6 @@ export function GenerateAudioNode({ id, data, selected }: NodeProps ( - - ), [currentProvider]); - - // Header action element - browse button - const headerAction = useMemo(() => ( - - ), []); - // Dynamic handles based on inputSchema const dynamicHandles = useMemo(() => { if (!nodeData.inputSchema || nodeData.inputSchema.length === 0) return null; @@ -233,18 +216,9 @@ export function GenerateAudioNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} - onRun={handleRegenerate} selected={selected} isExecuting={isRunning} hasError={nodeData.status === "error"} - commentNavigation={commentNavigation ?? undefined} minWidth={300} minHeight={250} > diff --git a/src/components/nodes/GenerateImageNode.tsx b/src/components/nodes/GenerateImageNode.tsx index 6cf19bde..878a6d92 100644 --- a/src/components/nodes/GenerateImageNode.tsx +++ b/src/components/nodes/GenerateImageNode.tsx @@ -3,7 +3,6 @@ import React, { useCallback, useState, useEffect, useMemo, useRef } from "react"; import { Handle, Position, NodeProps, Node, useReactFlow } from "@xyflow/react"; import { BaseNode } from "./BaseNode"; -import { useCommentNavigation } from "@/hooks/useCommentNavigation"; import { ModelParameters } from "./ModelParameters"; import { useWorkflowStore, saveNanoBananaDefaults, useProviderApiKeys } from "@/store/workflowStore"; import { deduplicatedFetch } from "@/utils/deduplicatedFetch"; @@ -39,7 +38,6 @@ type NanoBananaNodeType = Node; export function GenerateImageNode({ id, data, selected }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const generationsPath = useWorkflowStore((state) => state.generationsPath); // Use stable selector for API keys to prevent unnecessary re-fetches @@ -485,18 +483,9 @@ export function GenerateImageNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} - onRun={handleRegenerate} selected={selected} isExecuting={isRunning} hasError={nodeData.status === "error"} - headerAction={headerAction} - titlePrefix={titlePrefix} - commentNavigation={commentNavigation ?? undefined} > {/* Input handles - ALWAYS use same IDs and positions for connection stability */} {/* Image input at 35%, Text input at 65% - never changes regardless of model */} diff --git a/src/components/nodes/GenerateVideoNode.tsx b/src/components/nodes/GenerateVideoNode.tsx index a96fafe2..1702e9d3 100644 --- a/src/components/nodes/GenerateVideoNode.tsx +++ b/src/components/nodes/GenerateVideoNode.tsx @@ -3,7 +3,6 @@ import React, { useCallback, useState, useEffect, useMemo, useRef } from "react"; import { Handle, Position, NodeProps, Node, useReactFlow } from "@xyflow/react"; import { BaseNode } from "./BaseNode"; -import { useCommentNavigation } from "@/hooks/useCommentNavigation"; import { ModelParameters } from "./ModelParameters"; import { useWorkflowStore, useProviderApiKeys } from "@/store/workflowStore"; import { deduplicatedFetch } from "@/utils/deduplicatedFetch"; @@ -48,7 +47,6 @@ type GenerateVideoNodeType = Node; export function GenerateVideoNode({ id, data, selected }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); // Use stable selector for API keys to prevent unnecessary re-fetches const { geminiApiKey, replicateApiKey, falApiKey, kieApiKey, replicateEnabled, kieEnabled } = useProviderApiKeys(); @@ -414,18 +412,9 @@ export function GenerateVideoNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} - onRun={handleRegenerate} selected={selected} isExecuting={isRunning} hasError={nodeData.status === "error"} - headerAction={headerAction} - titlePrefix={titlePrefix} - commentNavigation={commentNavigation ?? undefined} > {/* Dynamic input handles based on model schema */} {nodeData.inputSchema && nodeData.inputSchema.length > 0 ? ( diff --git a/src/components/nodes/ImageCompareNode.tsx b/src/components/nodes/ImageCompareNode.tsx index 612b862c..409fdcb8 100644 --- a/src/components/nodes/ImageCompareNode.tsx +++ b/src/components/nodes/ImageCompareNode.tsx @@ -7,7 +7,6 @@ import { ReactCompareSliderImage, } from "react-compare-slider"; import { BaseNode } from "./BaseNode"; -import { useCommentNavigation } from "@/hooks/useCommentNavigation"; import { useWorkflowStore } from "@/store/workflowStore"; import { ImageCompareNodeData } from "@/types"; @@ -19,7 +18,6 @@ export function ImageCompareNode({ selected, }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const edges = useWorkflowStore((state) => state.edges); const nodes = useWorkflowStore((state) => state.nodes); @@ -66,18 +64,8 @@ export function ImageCompareNode({ return ( - updateNodeData(id, { customTitle: title || undefined }) - } - onCommentChange={(comment) => - updateNodeData(id, { comment: comment || undefined }) - } selected={selected} className="min-w-[200px]" - commentNavigation={commentNavigation ?? undefined} > {/* Two labeled image input handles */} ; export function LLMGenerateNode({ id, data, selected }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const handleProviderChange = useCallback( @@ -112,15 +110,8 @@ export function LLMGenerateNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} selected={selected} hasError={nodeData.status === "error"} - commentNavigation={commentNavigation ?? undefined} - onRun={handleRegenerate} isExecuting={isRunning} > {/* Image input - optional */} diff --git a/src/components/nodes/OutputGalleryNode.tsx b/src/components/nodes/OutputGalleryNode.tsx index 48e809e6..b4664487 100644 --- a/src/components/nodes/OutputGalleryNode.tsx +++ b/src/components/nodes/OutputGalleryNode.tsx @@ -4,7 +4,6 @@ import { useState, useCallback, useMemo, useEffect } from "react"; import { createPortal } from "react-dom"; import { Handle, Position, NodeProps, Node } from "@xyflow/react"; import { BaseNode } from "./BaseNode"; -import { useCommentNavigation } from "@/hooks/useCommentNavigation"; import { useWorkflowStore } from "@/store/workflowStore"; import { OutputGalleryNodeData } from "@/types"; @@ -12,7 +11,6 @@ type OutputGalleryNodeType = Node; export function OutputGalleryNode({ id, data, selected }: NodeProps) { const nodeData = data; - const commentNavigation = useCommentNavigation(id); const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const edges = useWorkflowStore((state) => state.edges); const nodes = useWorkflowStore((state) => state.nodes); @@ -113,14 +111,8 @@ export function OutputGalleryNode({ id, data, selected }: NodeProps updateNodeData(id, { customTitle: title || undefined })} - onCommentChange={(comment) => updateNodeData(id, { comment: comment || undefined })} selected={selected} className="min-w-[200px]" - commentNavigation={commentNavigation ?? undefined} >