import { UIComponent } from '@/types/json-ui' import { getComponentDef } from '@/lib/component-definitions' import { cn } from '@/lib/utils' import * as Icons from '@phosphor-icons/react' interface ComponentTreeNodeProps { component: UIComponent isSelected: boolean isHovered: boolean isDraggedOver: boolean dropPosition: 'before' | 'after' | 'inside' | null onSelect: () => void onHover: () => void onHoverEnd: () => void onDragStart: (e: React.DragEvent) => void onDragOver: (e: React.DragEvent) => void onDragLeave: (e: React.DragEvent) => void onDrop: (e: React.DragEvent) => void depth?: number hasChildren?: boolean isExpanded?: boolean onToggleExpand?: () => void } export function ComponentTreeNode({ component, isSelected, isHovered, isDraggedOver, dropPosition, onSelect, onHover, onHoverEnd, onDragStart, onDragOver, onDragLeave, onDrop, depth = 0, hasChildren = false, isExpanded = false, onToggleExpand, }: ComponentTreeNodeProps) { const def = getComponentDef(component.type) const IconComponent = def ? (Icons as any)[def.icon] || Icons.Cube : Icons.Cube return (
{isDraggedOver && dropPosition === 'before' && (
)}
{ e.stopPropagation() onSelect() }} onMouseEnter={onHover} onMouseLeave={onHoverEnd} style={{ paddingLeft: `${depth * 16}px` }} className={cn( 'flex items-center gap-2 px-3 py-2 text-sm cursor-pointer', 'hover:bg-muted/50 transition-colors', 'border-l-2 border-transparent', isSelected && 'bg-accent/20 border-l-accent', isHovered && !isSelected && 'bg-muted/30', isDraggedOver && dropPosition === 'inside' && 'bg-primary/10' )} > {hasChildren ? ( ) : (
)} {def?.label || component.type} {component.id}
{isDraggedOver && dropPosition === 'after' && (
)}
) }