Files
2026-02-02 18:19:00 +00:00

112 lines
2.6 KiB
TypeScript

'use client';
import { ChevronRight, ChevronDown } from 'lucide-react';
import { DOMAIN_TEXT_COLORS } from '@/lib/taxonomy/types';
interface TreeNodeProps {
code: string;
name: string;
count?: number;
isExpanded?: boolean;
isSelected?: boolean;
isLeaf?: boolean;
level: 'domain' | 'category' | 'subcode';
domainKey: string;
onToggle?: () => void;
onClick?: () => void;
searchMatch?: boolean;
children?: React.ReactNode;
}
export default function TreeNode({
code,
name,
count,
isExpanded = false,
isSelected = false,
isLeaf = false,
level,
domainKey,
onToggle,
onClick,
searchMatch = false,
children,
}: TreeNodeProps) {
const textColor = DOMAIN_TEXT_COLORS[domainKey] || 'text-gray-400';
const handleClick = (e: React.MouseEvent) => {
e.stopPropagation();
if (isLeaf) {
onClick?.();
} else {
onToggle?.();
}
};
const handleChevronClick = (e: React.MouseEvent) => {
e.stopPropagation();
onToggle?.();
};
const getPadding = () => {
switch (level) {
case 'domain':
return 'pl-2';
case 'category':
return 'pl-6';
case 'subcode':
return 'pl-10';
default:
return 'pl-2';
}
};
return (
<div>
<div
onClick={handleClick}
className={`
flex items-center gap-2 py-1.5 px-2 rounded cursor-pointer transition-colors
${getPadding()}
${isSelected ? 'bg-gray-700' : 'hover:bg-gray-800/50'}
${searchMatch ? 'ring-1 ring-yellow-500/50' : ''}
`}
>
{/* Expand/Collapse Icon */}
{!isLeaf ? (
<button
onClick={handleChevronClick}
className="w-4 h-4 flex items-center justify-center text-gray-500 hover:text-gray-300"
>
{isExpanded ? (
<ChevronDown className="w-4 h-4" />
) : (
<ChevronRight className="w-4 h-4" />
)}
</button>
) : (
<span className="w-4 h-4 flex items-center justify-center text-gray-600">
<span className="w-1.5 h-1.5 rounded-full bg-current" />
</span>
)}
{/* Code */}
<span className={`font-mono text-sm ${textColor}`}>{code}</span>
{/* Name */}
<span className="text-sm text-gray-300 truncate flex-1">{name}</span>
{/* Count Badge */}
{count !== undefined && (
<span className="text-xs text-gray-500 bg-gray-800 px-1.5 py-0.5 rounded">
{count}
</span>
)}
</div>
{/* Children (expanded content) */}
{isExpanded && children && <div>{children}</div>}
</div>
);
}