/** * DirectoryTreeNode - Recursive component for rendering directory tree nodes. */ import React, { useState } from 'react'; import { CopyablePath } from '@renderer/components/common/CopyablePath'; import { COLOR_TEXT_MUTED, COLOR_TEXT_SECONDARY } from '@renderer/constants/cssVariables'; import { ChevronRight } from 'lucide-react'; import { formatTokens } from '../utils/formatting'; import { formatFirstSeen, parseTurnIndex } from '../utils/pathParsing'; import type { TreeNode } from './types'; interface DirectoryTreeNodeProps { node: TreeNode; depth?: number; onNavigateToTurn?: (turnIndex: number) => void; } export const DirectoryTreeNode = ({ node, depth = 0, onNavigateToTurn, }: Readonly): React.ReactElement | null => { const [expanded, setExpanded] = useState(true); const indent = depth * 12; const sortedChildren = Array.from(node.children.values()).sort((a, b) => { if (a.isFile && !b.isFile) return -1; if (!a.isFile && b.isFile) return 1; return a.name.localeCompare(b.name); }); if (node.isFile) { const turnIndex = node.firstSeenInGroup ? parseTurnIndex(node.firstSeenInGroup) : -1; const isClickable = onNavigateToTurn && turnIndex >= 0; return (
(~{formatTokens(node.tokens ?? 0)}) {node.firstSeenInGroup && (isClickable ? ( ) : ( @{formatFirstSeen(node.firstSeenInGroup)} ))}
); } return (
{node.name && (
{ e.stopPropagation(); setExpanded(!expanded); }} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); e.stopPropagation(); setExpanded(!expanded); } }} > {node.name}/
)} {expanded && sortedChildren.map((child) => ( ))}
); };