From c431b212ac0bc8923aee1fd0d8a0c345895bdac3 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Thu, 22 Jan 2026 18:11:28 -0300 Subject: [PATCH] feat: [US-032] - Display conditions on edges Co-Authored-By: Claude Opus 4.5 --- .../editor/[projectId]/FlowchartEditor.tsx | 15 +++- .../editor/edges/ConditionalEdge.tsx | 71 +++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 src/components/editor/edges/ConditionalEdge.tsx diff --git a/src/app/editor/[projectId]/FlowchartEditor.tsx b/src/app/editor/[projectId]/FlowchartEditor.tsx index 3ecefad..0df0156 100644 --- a/src/app/editor/[projectId]/FlowchartEditor.tsx +++ b/src/app/editor/[projectId]/FlowchartEditor.tsx @@ -14,6 +14,7 @@ import ReactFlow, { Node, Edge, NodeTypes, + EdgeTypes, MarkerType, NodeMouseHandler, EdgeMouseHandler, @@ -24,6 +25,7 @@ import Toolbar from '@/components/editor/Toolbar' import DialogueNode from '@/components/editor/nodes/DialogueNode' import ChoiceNode from '@/components/editor/nodes/ChoiceNode' import VariableNode from '@/components/editor/nodes/VariableNode' +import ConditionalEdge from '@/components/editor/edges/ConditionalEdge' import ContextMenu, { ContextMenuType } from '@/components/editor/ContextMenu' import ConditionEditor from '@/components/editor/ConditionEditor' import type { FlowchartData, FlowchartNode, FlowchartEdge, Condition } from '@/types/flowchart' @@ -65,7 +67,7 @@ function toReactFlowEdges(edges: FlowchartEdge[]): Edge[] { target: edge.target, targetHandle: edge.targetHandle, data: edge.data, - type: 'smoothstep', + type: 'conditional', markerEnd: { type: MarkerType.ArrowClosed, }, @@ -84,6 +86,14 @@ function FlowchartEditorInner({ initialData }: FlowchartEditorProps) { [] ) + // Define custom edge types - memoized to prevent re-renders + const edgeTypes: EdgeTypes = useMemo( + () => ({ + conditional: ConditionalEdge, + }), + [] + ) + const { getViewport, screenToFlowPosition } = useReactFlow() const [contextMenu, setContextMenu] = useState(null) @@ -105,7 +115,7 @@ function FlowchartEditorInner({ initialData }: FlowchartEditorProps) { target: params.target, sourceHandle: params.sourceHandle, targetHandle: params.targetHandle, - type: 'smoothstep', + type: 'conditional', markerEnd: { type: MarkerType.ArrowClosed, }, @@ -376,6 +386,7 @@ function FlowchartEditorInner({ initialData }: FlowchartEditorProps) { nodes={nodes} edges={edges} nodeTypes={nodeTypes} + edgeTypes={edgeTypes} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onEdgesDelete={onEdgesDelete} diff --git a/src/components/editor/edges/ConditionalEdge.tsx b/src/components/editor/edges/ConditionalEdge.tsx new file mode 100644 index 0000000..c49a99d --- /dev/null +++ b/src/components/editor/edges/ConditionalEdge.tsx @@ -0,0 +1,71 @@ +'use client' + +import { + BaseEdge, + EdgeLabelRenderer, + EdgeProps, + getSmoothStepPath, +} from 'reactflow' +import type { Condition } from '@/types/flowchart' + +type ConditionalEdgeData = { + condition?: Condition +} + +export default function ConditionalEdge({ + id, + sourceX, + sourceY, + targetX, + targetY, + sourcePosition, + targetPosition, + data, + markerEnd, + selected, +}: EdgeProps) { + const [edgePath, labelX, labelY] = getSmoothStepPath({ + sourceX, + sourceY, + sourcePosition, + targetX, + targetY, + targetPosition, + }) + + const hasCondition = !!data?.condition + + // Format condition as readable label + const conditionLabel = hasCondition + ? `${data.condition!.variableName} ${data.condition!.operator} ${data.condition!.value}` + : null + + return ( + <> + + {conditionLabel && ( + +
+ {conditionLabel} +
+
+ )} + + ) +}