import type { DiagramNode as DiagramNodeType } from '../../api/queries/diagrams'; import type { NodeConfig } from './types'; import { colorForType, iconForType } from './node-colors'; import { ConfigBadge } from './ConfigBadge'; const TOP_BAR_HEIGHT = 6; const CORNER_RADIUS = 4; interface DiagramNodeProps { node: DiagramNodeType; isHovered: boolean; isSelected: boolean; config?: NodeConfig; onClick: () => void; onDoubleClick?: () => void; onMouseEnter: () => void; onMouseLeave: () => void; } export function DiagramNode({ node, isHovered, isSelected, config, onClick, onDoubleClick, onMouseEnter, onMouseLeave, }: DiagramNodeProps) { const x = node.x ?? 0; const y = node.y ?? 0; const w = node.width ?? 120; const h = node.height ?? 40; const color = colorForType(node.type); const icon = iconForType(node.type); // Extract label parts: type name and detail const typeName = node.type?.replace(/^EIP_/, '').replace(/_/g, ' ') ?? ''; const detail = node.label || ''; return ( { e.stopPropagation(); onClick(); }} onDoubleClick={(e) => { e.stopPropagation(); onDoubleClick?.(); }} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} style={{ cursor: 'pointer' }} > {/* Selection ring */} {isSelected && ( )} {/* Card background */} {/* Colored top bar */} {/* Icon */} {icon} {/* Type name */} {typeName} {/* Detail label (truncated) */} {detail && detail !== typeName && ( {detail.length > 22 ? detail.slice(0, 20) + '...' : detail} )} {/* Config badges */} {config && } ); }