import { useState, type ReactNode } from "react"; import { Icon, Tree, fileIconName } from "@/ui"; import { DiffEditor } from "./DiffEditor"; import { diffInput, openDiff, type DiffData } from "./diffInput"; import { dirKeys, type FileTreeNode } from "./fileTree"; import styles from "./common.module.css"; /** Shared changes tree and on-demand diff surface for revisions and disk folders. */ export function ComparisonTree({ tree, current, onSelect, diffFor, renderDetails, ariaLabel, openOnActivate = false, getColor, onOpen, }: { tree: FileTreeNode[]; current: F | null; onSelect: (entry: F | null) => void; diffFor: (entry: F) => DiffData | null; renderDetails: (node: FileTreeNode) => ReactNode; ariaLabel: string; openOnActivate?: boolean; getColor?: (entry: F) => string | undefined; onOpen?: () => void; }) { const [selected, setSelected] = useState>(new Set()); const [expanded, setExpanded] = useState | null>(null); const data = current && diffFor(current); const input = data ? diffInput(data) : null; return (
> roots={tree} getKey={(n) => n.key} getLabel={(n) => n.name} getChildren={(n) => (n.file ? undefined : n.children)} isExpandable={(n) => !n.file} expanded={expanded ?? new Set(dirKeys(tree))} onExpandedChange={setExpanded} selected={selected} onSelectionChange={(sel, lead) => { setSelected(sel); onSelect(lead?.file ?? lead?.directory ?? null); }} onActivate={(n) => { const entry = n.file ?? n.directory; if (!entry) return; onSelect(entry); const diff = diffFor(entry); if (openOnActivate && diff) { void openDiff(diff); onOpen?.(); } }} aria-label={ariaLabel} className={styles.comparisonTree} renderNode={(n) => ( {n.name} {renderDetails(n)} )} /> {input && (
)}
); }