| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 | import {  RiCloseLine,  RiDownloadLine,} from '@remixicon/react'import {  downloadFile,  fileIsUploaded,  getFileAppearanceType,  getFileExtension,} from '../utils'import FileTypeIcon from '../file-type-icon'import type { FileEntity } from '../types'import cn from '@/utils/classnames'import { formatFileSize } from '@/utils/format'import ProgressCircle from '@/app/components/base/progress-bar/progress-circle'import { ReplayLine } from '@/app/components/base/icons/src/vender/other'import ActionButton from '@/app/components/base/action-button'import Button from '@/app/components/base/button'type FileItemProps = {  file: FileEntity  showDeleteAction?: boolean  showDownloadAction?: boolean  onRemove?: (fileId: string) => void  onReUpload?: (fileId: string) => void}const FileItem = ({  file,  showDeleteAction,  showDownloadAction = true,  onRemove,  onReUpload,}: FileItemProps) => {  const { id, name, type, progress, url, isRemote } = file  const ext = getFileExtension(name, type, isRemote)  const uploadError = progress === -1  return (    <div      className={cn(        'group/file-item relative p-2 w-[144px] h-[68px] rounded-lg border-[0.5px] border-components-panel-border bg-components-card-bg shadow-xs',        !uploadError && 'hover:bg-components-card-bg-alt',        uploadError && 'border border-state-destructive-border bg-state-destructive-hover',        uploadError && 'hover:border-[0.5px] hover:border-state-destructive-border bg-state-destructive-hover-alt',      )}    >      {        showDeleteAction && (          <Button            className='hidden group-hover/file-item:flex absolute -right-1.5 -top-1.5 p-0 w-5 h-5 rounded-full z-[11]'            onClick={() => onRemove?.(id)}          >            <RiCloseLine className='w-4 h-4 text-components-button-secondary-text' />          </Button>        )      }      <div        className='mb-1 h-8 line-clamp-2 system-xs-medium text-text-tertiary break-all'        title={name}      >        {name}      </div>      <div className='relative flex items-center justify-between'>        <div className='flex items-center system-2xs-medium-uppercase text-text-tertiary'>          <FileTypeIcon            size='sm'            type={getFileAppearanceType(name, type)}            className='mr-1'          />          {            ext && (              <>                {ext}                <div className='mx-1'>·</div>              </>            )          }          {            !!file.size && formatFileSize(file.size)          }        </div>        {          showDownloadAction && url && (            <ActionButton              size='m'              className='hidden group-hover/file-item:flex absolute -right-1 -top-1'              onClick={(e) => {                e.stopPropagation()                downloadFile(url || '', name)              }}            >              <RiDownloadLine className='w-3.5 h-3.5 text-text-tertiary' />            </ActionButton>          )        }        {          progress >= 0 && !fileIsUploaded(file) && (            <ProgressCircle              percentage={progress}              size={12}              className='shrink-0'            />          )        }        {          uploadError && (            <ReplayLine              className='w-4 h-4 text-text-tertiary'              onClick={() => onReUpload?.(id)}            />          )        }      </div>    </div>  )}export default FileItem
 |