diff --git a/src/components/nodes/ArrayNode.tsx b/src/components/nodes/ArrayNode.tsx index ce6ed0db..bce74194 100644 --- a/src/components/nodes/ArrayNode.tsx +++ b/src/components/nodes/ArrayNode.tsx @@ -19,12 +19,18 @@ function arraysEqual(a: string[], b: string[]): boolean { } export function ArrayNode({ id, data, selected }: NodeProps) { - const nodeData = data; const updateNodeData = useWorkflowStore((state) => state.updateNodeData); const addNode = useWorkflowStore((state) => state.addNode); const onConnect = useWorkflowStore((state) => state.onConnect); const nodes = useWorkflowStore((state) => state.nodes); const edges = useWorkflowStore((state) => state.edges); + + // Derive nodeData from the Zustand store (already subscribed via `nodes`) + // rather than React Flow props, so settings changes are reflected immediately. + const nodeData = useMemo(() => { + const n = nodes.find((nd) => nd.id === id); + return (n?.data as ArrayNodeData) ?? data; + }, [nodes, id, data]); const { setNodes, getNodes } = useReactFlow(); const lastSyncedInputRef = useRef(null); const lastDerivedWriteRef = useRef(null); @@ -103,11 +109,36 @@ export function ArrayNode({ id, data, selected }: NodeProps) { }); }, [id, nodeData.error, nodeData.outputItems, nodeData.outputText, parsed.error, parsed.items, updateNodeData]); + // Helper: reparse and update outputs atomically whenever any split setting changes. + // Reads fresh data from the Zustand store (not React Flow props) to avoid stale closures. + const updateSettingsAndReparse = useCallback( + (partialSettings: Partial>) => { + const freshNode = useWorkflowStore.getState().nodes.find((n) => n.id === id); + if (!freshNode) return; + const fresh = freshNode.data as ArrayNodeData; + const merged = { + splitMode: partialSettings.splitMode ?? fresh.splitMode, + delimiter: partialSettings.delimiter ?? fresh.delimiter, + regexPattern: partialSettings.regexPattern ?? fresh.regexPattern, + trimItems: partialSettings.trimItems ?? fresh.trimItems, + removeEmpty: partialSettings.removeEmpty ?? fresh.removeEmpty, + }; + const result = parseTextToArray(fresh.inputText, merged); + updateNodeData(id, { + ...partialSettings, + outputItems: result.items, + outputText: JSON.stringify(result.items), + error: result.error, + }); + }, + [id, updateNodeData] + ); + const handleBasicModeChange = useCallback( (e: React.ChangeEvent) => { - updateNodeData(id, { splitMode: e.target.value as ArrayNodeData["splitMode"] }); + updateSettingsAndReparse({ splitMode: e.target.value as ArrayNodeData["splitMode"] }); }, - [id, updateNodeData] + [updateSettingsAndReparse] ); const previewItems = parsed.items; @@ -203,8 +234,11 @@ export function ArrayNode({ id, data, selected }: NodeProps) { className="nodrag nopan absolute top-2 right-2 z-10 shrink-0 p-1 bg-[#1a1a1a] rounded-md text-neutral-400 hover:text-neutral-100 transition-colors disabled:opacity-50 disabled:cursor-not-allowed" title="Auto-route to Prompts" > - - + + + + + @@ -227,7 +261,7 @@ export function ArrayNode({ id, data, selected }: NodeProps) {