feat: add traversed/not-traversed visual states to DiagramEdge

Add green solid edges for traversed paths and dashed gray for
not-traversed when execution overlay is active. Includes green
arrowhead marker and overlay threading through CompoundNode and
ErrorSection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-27 18:47:59 +01:00
parent 2b805ec196
commit 3029704051
4 changed files with 61 additions and 21 deletions

View File

@@ -1,5 +1,6 @@
import type { DiagramNode as DiagramNodeType, DiagramEdge as DiagramEdgeType } from '../../api/queries/diagrams';
import type { NodeConfig } from './types';
import type { NodeExecutionState } from '../ExecutionDiagram/types';
import { colorForType, isCompoundType } from './node-colors';
import { DiagramNode } from './DiagramNode';
import { DiagramEdge } from './DiagramEdge';
@@ -17,6 +18,8 @@ interface CompoundNodeProps {
selectedNodeId?: string;
hoveredNodeId: string | null;
nodeConfigs?: Map<string, NodeConfig>;
/** Execution overlay for edge traversal coloring */
executionOverlay?: Map<string, NodeExecutionState>;
onNodeClick: (nodeId: string) => void;
onNodeDoubleClick?: (nodeId: string) => void;
onNodeEnter: (nodeId: string) => void;
@@ -25,7 +28,7 @@ interface CompoundNodeProps {
export function CompoundNode({
node, edges, parentX = 0, parentY = 0,
selectedNodeId, hoveredNodeId, nodeConfigs,
selectedNodeId, hoveredNodeId, nodeConfigs, executionOverlay,
onNodeClick, onNodeDoubleClick, onNodeEnter, onNodeLeave,
}: CompoundNodeProps) {
const x = (node.x ?? 0) - parentX;
@@ -78,15 +81,21 @@ export function CompoundNode({
{/* Internal edges (rendered after background, before children) */}
<g className="edges">
{internalEdges.map((edge, i) => (
<DiagramEdge
key={`${edge.sourceId}-${edge.targetId}-${i}`}
edge={{
...edge,
points: edge.points.map(p => [p[0] - absX, p[1] - absY]),
}}
/>
))}
{internalEdges.map((edge, i) => {
const isTraversed = executionOverlay
? (executionOverlay.has(edge.sourceId) && executionOverlay.has(edge.targetId))
: undefined;
return (
<DiagramEdge
key={`${edge.sourceId}-${edge.targetId}-${i}`}
edge={{
...edge,
points: edge.points.map(p => [p[0] - absX, p[1] - absY]),
}}
traversed={isTraversed}
/>
);
})}
</g>
{/* Children — recurse into compound children, render leaves as DiagramNode */}
@@ -102,6 +111,7 @@ export function CompoundNode({
selectedNodeId={selectedNodeId}
hoveredNodeId={hoveredNodeId}
nodeConfigs={nodeConfigs}
executionOverlay={executionOverlay}
onNodeClick={onNodeClick}
onNodeDoubleClick={onNodeDoubleClick}
onNodeEnter={onNodeEnter}