From e31a0b7baeffc5e38d841f534d2009335792a3a2 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 21 Jan 2026 12:47:35 -0300 Subject: [PATCH] feat: [US-020] - Create custom dialogue node component Co-Authored-By: Claude Opus 4.5 --- .../editor/[projectId]/FlowchartEditor.tsx | 13 +++- src/components/editor/nodes/DialogueNode.tsx | 78 +++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/components/editor/nodes/DialogueNode.tsx diff --git a/src/app/editor/[projectId]/FlowchartEditor.tsx b/src/app/editor/[projectId]/FlowchartEditor.tsx index 81227b5..79e15f5 100644 --- a/src/app/editor/[projectId]/FlowchartEditor.tsx +++ b/src/app/editor/[projectId]/FlowchartEditor.tsx @@ -1,6 +1,6 @@ 'use client' -import { useCallback } from 'react' +import { useCallback, useMemo } from 'react' import ReactFlow, { Background, BackgroundVariant, @@ -11,9 +11,11 @@ import ReactFlow, { Connection, Node, Edge, + NodeTypes, } from 'reactflow' import 'reactflow/dist/style.css' import Toolbar from '@/components/editor/Toolbar' +import DialogueNode from '@/components/editor/nodes/DialogueNode' import type { FlowchartData, FlowchartNode, FlowchartEdge } from '@/types/flowchart' type FlowchartEditorProps = { @@ -46,6 +48,14 @@ function toReactFlowEdges(edges: FlowchartEdge[]): Edge[] { export default function FlowchartEditor({ initialData, }: FlowchartEditorProps) { + // Define custom node types - memoized to prevent re-renders + const nodeTypes: NodeTypes = useMemo( + () => ({ + dialogue: DialogueNode, + }), + [] + ) + const [nodes, setNodes, onNodesChange] = useNodesState( toReactFlowNodes(initialData.nodes) ) @@ -97,6 +107,7 @@ export default function FlowchartEditor({ ) { + const { setNodes } = useReactFlow() + + const updateNodeData = useCallback( + (field: keyof DialogueNodeData, value: string) => { + setNodes((nodes) => + nodes.map((node) => + node.id === id + ? { ...node, data: { ...node.data, [field]: value } } + : node + ) + ) + }, + [id, setNodes] + ) + + const handleSpeakerChange = useCallback( + (e: ChangeEvent) => { + updateNodeData('speaker', e.target.value) + }, + [updateNodeData] + ) + + const handleTextChange = useCallback( + (e: ChangeEvent) => { + updateNodeData('text', e.target.value) + }, + [updateNodeData] + ) + + return ( +
+ + +
+ Dialogue +
+ + + +