import { ChevronDown, ChevronRight } from 'lucide-react' import { useState } from 'react' import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { parseDetailLines } from './ExplainVisualizer.parser' import { RowCountIndicator } from './ExplainVisualizer.RowCountIndicator' import type { ExplainNode } from './ExplainVisualizer.types' import { formatNodeDuration, getScanBarColor, getScanBorderColor } from './ExplainVisualizer.utils' interface ExplainNodeRowProps { node: ExplainNode depth: number /** Maximum duration across all nodes, used to calculate bar width as % */ maxDuration: number } export function ExplainNodeRow({ node, depth, maxDuration }: ExplainNodeRowProps) { const [isExpanded, setIsExpanded] = useState(false) const hasChildren = node.children.length > 0 const hasDetails = Boolean(node.details?.trim()) const canExpand = hasDetails const detailLines = parseDetailLines(node.details) const indentPx = depth * 24 // Calculate duration and bar width as % of max duration const duration = node.actualTime ? node.actualTime.end - node.actualTime.start : 0 const hasTimingData = node.actualTime && duration > 0 const barWidthPercent = maxDuration > 0 ? (duration / maxDuration) * 100 : 0 const barColorClass = getScanBarColor(node.operation) const borderColorClass = getScanBorderColor(node.operation) return ( <> {/* Wrapper for group hover */}
{/* Main row */}
{/* Left section: expand button + operation info */}
{/* Expand/collapse button */} {/* Operation name and cost info */}
{node.operation} (cost {node.cost?.end?.toFixed(1) ?? '-'}, estimated{' '} {node.rows?.toLocaleString() ?? '?'} {node.rows === 1 ? 'row' : 'rows'})
{/* Right section: duration bar visualization */}
{hasTimingData && ( <> {/* Duration bar - width represents % of slowest operation */}
{/* Duration and row count info */}
{formatNodeDuration(duration)}

Execution time: {formatNodeDuration(duration)}

This is how long this operation took to execute. The bar width shows this as a percentage of the slowest operation ({Math.round(barWidthPercent)}%) — wider bars indicate where more time is spent.

/
)}
{/* Expanded details section */} {isExpanded && detailLines.length > 0 && (
{detailLines.map((line, idx) => (
{line.label && {line.label}} {line.value}
))}
)}
{/* Render children recursively */} {hasChildren && node.children.map((child, idx) => ( ))} ) }