import { ArrowRight, ArrowUp, Clock } from 'lucide-react' import { cn } from 'ui' import { CostIndicator } from './ExplainVisualizer.CostIndicator' import { RowCountIndicator } from './ExplainVisualizer.RowCountIndicator' import { getOperationColor, getOperationDescription, getOperationIcon, } from './ExplainVisualizer.utils' import type { ExplainNode } from './ExplainVisualizer.types' import { useMemo } from 'react' export interface ExplainNodeRendererProps { node: ExplainNode depth: number maxCost: number isRoot?: boolean } export function ExplainNodeRenderer({ node, depth, maxCost, isRoot = false, }: ExplainNodeRendererProps) { const Icon = getOperationIcon(node.operation) const colorClass = getOperationColor(node.operation) const description = getOperationDescription(node.operation) const isLeaf = node.children.length === 0 const detailLines = node.details ? node.details.split('\n').filter(Boolean) : [] const hasNonColonPrefixedFirstLine = detailLines.length > 0 && !detailLines[0].includes(':') const targetName = hasNonColonPrefixedFirstLine ? detailLines[0] : null const pipelineIndicatorClass = useMemo(() => { if (isRoot) return 'bg-brand/20 text-brand' if (isLeaf) return 'bg-surface-300 text-foreground-light' return 'bg-surface-200 text-foreground-muted' }, [isRoot, isLeaf]) return (
{/* Node content */}
{/* Pipeline flow indicator */}
{isRoot ? ( ) : ( )}
{/* Icon */}
{/* Content */}
{/* Operation name and target */}
{node.operation} {targetName && ( {targetName} )}
{/* Description */} {description &&

{description}

} {/* Metrics row */}
{/* Cost visualization bar */} {node.cost && } {node.actualTime && ( <> |
{node.actualTime.end.toFixed(2)}ms
)} {/* Row count */} {(node.actualRows !== undefined || node.rows !== undefined) && ( <> | )}
{/* Detail lines (Filter, Hash Cond, etc.) */} {detailLines.length > 0 && (
{detailLines.map((detail, idx) => { // Skip the first line if it was already shown as the target if (idx === 0 && !detail.includes(':')) return null // Skip "Rows Removed" as we show it in the flow visualization if (detail.includes('Rows Removed by Filter')) return null return (
{detail}
) })}
)}
{/* Render children */} {node.children.length > 0 && (
{node.children.map((child, idx) => ( ))}
)}
) }