From e405e46bf9a62516004b4ef6b539b4bc55901aae Mon Sep 17 00:00:00 2001 From: shrimbly Date: Sun, 8 Mar 2026 23:08:37 +1300 Subject: [PATCH] feat(47-01): add inline parameters infrastructure - types, hook, and panel component - Add parametersExpanded field to 5 generation node data types (NanoBanana, GenerateVideo, Generate3D, GenerateAudio, LLMGenerate) - Create useInlineParameters hook for localStorage-backed global setting (default: false) - Create InlineParameterPanel component with collapsible UI and chevron toggle - All TypeScript compiles without new errors --- src/components/nodes/InlineParameterPanel.tsx | 62 +++++++++++++++++++ src/hooks/useInlineParameters.ts | 24 +++++++ src/types/nodes.ts | 5 ++ 3 files changed, 91 insertions(+) create mode 100644 src/components/nodes/InlineParameterPanel.tsx create mode 100644 src/hooks/useInlineParameters.ts diff --git a/src/components/nodes/InlineParameterPanel.tsx b/src/components/nodes/InlineParameterPanel.tsx new file mode 100644 index 00000000..01e00269 --- /dev/null +++ b/src/components/nodes/InlineParameterPanel.tsx @@ -0,0 +1,62 @@ +"use client"; + +import { ReactNode } from "react"; + +interface InlineParameterPanelProps { + expanded: boolean; + onToggle: () => void; + children: ReactNode; + nodeId: string; +} + +/** + * Collapsible parameter container for inline display within generation nodes. + * Provides a chevron toggle button and smooth expand/collapse transitions. + */ +export function InlineParameterPanel({ + expanded, + onToggle, + children, + nodeId, +}: InlineParameterPanelProps) { + return ( +
+ {/* Chevron toggle button - acts as visual boundary */} + + + {/* Collapsible content area */} +
+
+
{children}
+
+
+
+ ); +} diff --git a/src/hooks/useInlineParameters.ts b/src/hooks/useInlineParameters.ts new file mode 100644 index 00000000..455742d4 --- /dev/null +++ b/src/hooks/useInlineParameters.ts @@ -0,0 +1,24 @@ +import { useState, useCallback } from "react"; + +const INLINE_PARAMS_KEY = "node-banana-inline-parameters"; + +export function useInlineParameters() { + const [enabled, setEnabled] = useState(() => { + try { + return localStorage.getItem(INLINE_PARAMS_KEY) === "true"; + } catch { + return false; + } + }); + + const setInlineParameters = useCallback((value: boolean) => { + try { + localStorage.setItem(INLINE_PARAMS_KEY, String(value)); + } catch { + // localStorage not available + } + setEnabled(value); + }, []); + + return { inlineParametersEnabled: enabled, setInlineParameters }; +} diff --git a/src/types/nodes.ts b/src/types/nodes.ts index 65725dbd..963c41f7 100644 --- a/src/types/nodes.ts +++ b/src/types/nodes.ts @@ -177,6 +177,7 @@ export interface NanoBananaNodeData extends BaseNodeData { useImageSearch: boolean; // Only available for Nano Banana 2 parameters?: Record; // Model-specific parameters for external providers inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles + parametersExpanded?: boolean; // Collapse state for inline parameter display status: NodeStatus; error: string | null; imageHistory: CarouselImageItem[]; // Carousel history (IDs only) @@ -195,6 +196,7 @@ export interface GenerateVideoNodeData extends BaseNodeData { selectedModel?: SelectedModel; // Required for video generation (no legacy fallback) parameters?: Record; // Model-specific parameters inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles + parametersExpanded?: boolean; // Collapse state for inline parameter display status: NodeStatus; error: string | null; videoHistory: CarouselVideoItem[]; // Carousel history (IDs only) @@ -214,6 +216,7 @@ export interface Generate3DNodeData extends BaseNodeData { selectedModel?: SelectedModel; parameters?: Record; inputSchema?: ModelInputDef[]; + parametersExpanded?: boolean; // Collapse state for inline parameter display status: NodeStatus; error: string | null; } @@ -238,6 +241,7 @@ export interface GenerateAudioNodeData extends BaseNodeData { selectedModel?: SelectedModel; // Required for audio generation parameters?: Record; // Model-specific parameters (voice, speed, etc.) inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles + parametersExpanded?: boolean; // Collapse state for inline parameter display status: NodeStatus; error: string | null; audioHistory: CarouselAudioItem[]; // Carousel history (IDs only) @@ -258,6 +262,7 @@ export interface LLMGenerateNodeData extends BaseNodeData { model: LLMModelType; temperature: number; maxTokens: number; + parametersExpanded?: boolean; // Collapse state for inline parameter display status: NodeStatus; error: string | null; }