feat: [US-032] - Display conditions on edges

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Gustavo Henrique Santos Souza de Miranda 2026-01-22 18:11:28 -03:00
parent e686719f29
commit c431b212ac
2 changed files with 84 additions and 2 deletions

View File

@ -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<ContextMenuState>(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}

View File

@ -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<ConditionalEdgeData>) {
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 (
<>
<BaseEdge
id={id}
path={edgePath}
markerEnd={markerEnd}
style={{
strokeDasharray: hasCondition ? '5 5' : undefined,
stroke: selected ? '#3b82f6' : hasCondition ? '#f59e0b' : '#64748b',
strokeWidth: selected ? 2 : 1.5,
}}
/>
{conditionLabel && (
<EdgeLabelRenderer>
<div
style={{
position: 'absolute',
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
pointerEvents: 'all',
}}
className="rounded border border-amber-300 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-800 dark:border-amber-600 dark:bg-amber-900 dark:text-amber-200"
>
{conditionLabel}
</div>
</EdgeLabelRenderer>
)}
</>
)
}