'use client' import type { FC } from 'react' import type { FileAppearanceType } from '@/app/components/base/file-uploader/types' import type { SandboxFileTreeNode } from '@/types/sandbox-file' import { RiDownloadLine, RiFolderLine, RiFolderOpenLine } from '@remixicon/react' 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-guide-lines' const INDENT_SIZE = 20 type ArtifactsTreeProps = { data: SandboxFileTreeNode[] | undefined onDownload: (node: SandboxFileTreeNode) => void isDownloading?: boolean } type ArtifactsTreeNodeProps = { node: SandboxFileTreeNode depth: number onDownload: (node: SandboxFileTreeNode) => void isDownloading?: boolean } const ArtifactsTreeNode: FC = ({ node, depth, onDownload, isDownloading, }) => { const [isExpanded, setIsExpanded] = useState(false) const isFolder = node.node_type === 'folder' const hasChildren = isFolder && node.children.length > 0 const handleToggle = useCallback(() => { if (isFolder) setIsExpanded(prev => !prev) }, [isFolder]) const handleDownload = useCallback((e: React.MouseEvent) => { e.stopPropagation() onDownload(node) }, [node, onDownload]) const fileIconType = !isFolder ? getFileIconType(node.name) : null return (
{ if (e.key === 'Enter' || e.key === ' ') handleToggle() } : undefined} className={cn( 'group relative flex h-6 items-center rounded-md px-2', isFolder && 'cursor-pointer hover:bg-state-base-hover focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-components-input-border-active', !isFolder && 'hover: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: FC = ({ data, onDownload, isDownloading, }) => { if (!data || data.length === 0) return null return (
{data.map(node => ( ))}
) } export default React.memo(ArtifactsTree)