'use client' import type { FileAppearanceType } from '@/app/components/base/file-uploader/types' import type { SandboxFileTreeNode } from '@/types/sandbox-file' import * as React from 'react' import { useCallback, useState } from 'react' import FileTypeIcon from '@/app/components/base/file-uploader/file-type-icon' import { cn } from '@/utils/classnames' import { getFileIconType } from '../../utils/file-utils' import TreeGuideLines from '../tree/tree-guide-lines' const INDENT_SIZE = 20 type ArtifactsTreeProps = { data: SandboxFileTreeNode[] | undefined onDownload: (node: SandboxFileTreeNode) => void onSelect?: (node: SandboxFileTreeNode) => void selectedPath?: string isDownloading?: boolean } type ArtifactsTreeNodeProps = { node: SandboxFileTreeNode depth: number onDownload: (node: SandboxFileTreeNode) => void onSelect?: (node: SandboxFileTreeNode) => void selectedPath?: string isDownloading?: boolean } const ArtifactsTreeNode = ({ node, depth, onDownload, onSelect, selectedPath, isDownloading, }: ArtifactsTreeNodeProps) => { const [isExpanded, setIsExpanded] = useState(false) const isFolder = node.node_type === 'folder' const hasChildren = isFolder && node.children.length > 0 const isSelected = !isFolder && selectedPath === node.path const handleClick = useCallback(() => { if (isFolder) { setIsExpanded(prev => !prev) } else { onSelect?.(node) } }, [isFolder, node, onSelect]) const handleDownload = useCallback((e: React.MouseEvent) => { e.stopPropagation() onDownload(node) }, [node, onDownload]) const fileIconType = !isFolder ? getFileIconType(node.name, node.extension) : null return (
{ if (e.key === 'Enter' || e.key === ' ') handleClick() }} className={cn( 'group relative flex h-6 cursor-pointer items-center rounded-md px-2', 'hover:bg-state-base-hover focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-components-input-border-active', isSelected && 'bg-state-base-hover', )} style={{ paddingLeft: `${8 + depth * INDENT_SIZE}px` }} >
{isFolder ? ( isExpanded ?
{node.name} {!isFolder && ( )}
{isFolder && isExpanded && hasChildren && (
{node.children.map(child => ( ))}
)}
) } const ArtifactsTree = ({ data, onDownload, onSelect, selectedPath, isDownloading, }: ArtifactsTreeProps) => { if (!data || data.length === 0) return null return (
{data.map(node => ( ))}
) } export default React.memo(ArtifactsTree)