+ selectedId?: string
+ focusedId: string | null
+ onToggle: (id: string) => void
+ onSelect?: (id: string) => void
+ onFocus: (id: string) => void
+}
+
+function TreeNodeRow({
+ node,
+ depth,
+ expandedSet,
+ selectedId,
+ focusedId,
+ onToggle,
+ onSelect,
+ onFocus,
+}: TreeNodeRowProps) {
+ const hasChildren = node.children && node.children.length > 0
+ const isExpanded = expandedSet.has(node.id)
+ const isSelected = selectedId === node.id
+ const isFocused = focusedId === node.id
+
+ function handleClick() {
+ if (hasChildren) {
+ onToggle(node.id)
+ }
+ onSelect?.(node.id)
+ }
+
+ const rowClass = [
+ styles.row,
+ isSelected ? styles.selected : '',
+ ]
+ .filter(Boolean)
+ .join(' ')
+
+ return (
+
+ onFocus(node.id)}
+ >
+
+ {hasChildren ? (
+
+ {isExpanded ? '▾' : '▸'}
+
+ ) : null}
+
+ {node.icon && (
+
+ {node.icon}
+
+ )}
+ {node.label}
+ {node.meta && (
+ {node.meta}
+ )}
+
+ {hasChildren && isExpanded && (
+
+ {node.children!.map((child) => (
+
+ ))}
+
+ )}
+
+ )
+}