Spaces:
Build error
Build error
import type { FC } from 'react' | |
import { useState } from 'react' | |
import { useTranslation } from 'react-i18next' | |
import { | |
RiCloseLine, | |
RiLoader2Line, | |
} from '@remixicon/react' | |
import cn from '@/utils/classnames' | |
import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows' | |
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' | |
import Tooltip from '@/app/components/base/tooltip' | |
import type { ImageFile } from '@/types/app' | |
import { TransferMethod } from '@/types/app' | |
import ImagePreview from '@/app/components/base/image-uploader/image-preview' | |
type ImageListProps = { | |
list: ImageFile[] | |
readonly?: boolean | |
onRemove?: (imageFileId: string) => void | |
onReUpload?: (imageFileId: string) => void | |
onImageLinkLoadSuccess?: (imageFileId: string) => void | |
onImageLinkLoadError?: (imageFileId: string) => void | |
} | |
const ImageList: FC<ImageListProps> = ({ | |
list, | |
readonly, | |
onRemove, | |
onReUpload, | |
onImageLinkLoadSuccess, | |
onImageLinkLoadError, | |
}) => { | |
const { t } = useTranslation() | |
const [imagePreviewUrl, setImagePreviewUrl] = useState('') | |
const handleImageLinkLoadSuccess = (item: ImageFile) => { | |
if ( | |
item.type === TransferMethod.remote_url | |
&& onImageLinkLoadSuccess | |
&& item.progress !== -1 | |
) | |
onImageLinkLoadSuccess(item._id) | |
} | |
const handleImageLinkLoadError = (item: ImageFile) => { | |
if (item.type === TransferMethod.remote_url && onImageLinkLoadError) | |
onImageLinkLoadError(item._id) | |
} | |
return ( | |
<div className="flex flex-wrap"> | |
{list.map(item => ( | |
<div | |
key={item._id} | |
className="group relative mr-1 border-[0.5px] border-black/5 rounded-lg" | |
> | |
{item.type === TransferMethod.local_file && item.progress !== 100 && ( | |
<> | |
<div | |
className="absolute inset-0 flex items-center justify-center z-[1] bg-black/30" | |
style={{ left: item.progress > -1 ? `${item.progress}%` : 0 }} | |
> | |
{item.progress === -1 && ( | |
<RefreshCcw01 | |
className="w-5 h-5 text-white" | |
onClick={() => onReUpload && onReUpload(item._id)} | |
/> | |
)} | |
</div> | |
{item.progress > -1 && ( | |
<span className="absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] text-sm text-white mix-blend-lighten z-[1]"> | |
{item.progress}% | |
</span> | |
)} | |
</> | |
)} | |
{item.type === TransferMethod.remote_url && item.progress !== 100 && ( | |
<div | |
className={` | |
absolute inset-0 flex items-center justify-center rounded-lg z-[1] border | |
${item.progress === -1 | |
? 'bg-[#FEF0C7] border-[#DC6803]' | |
: 'bg-black/[0.16] border-transparent' | |
} | |
`} | |
> | |
{item.progress > -1 && ( | |
<RiLoader2Line className="animate-spin w-5 h-5 text-white" /> | |
)} | |
{item.progress === -1 && ( | |
<Tooltip | |
popupContent={t('common.imageUploader.pasteImageLinkInvalid')} | |
> | |
<AlertTriangle className="w-4 h-4 text-[#DC6803]" /> | |
</Tooltip> | |
)} | |
</div> | |
)} | |
<img | |
className="w-16 h-16 rounded-lg object-cover cursor-pointer border-[0.5px] border-black/5" | |
alt={item.file?.name} | |
onLoad={() => handleImageLinkLoadSuccess(item)} | |
onError={() => handleImageLinkLoadError(item)} | |
src={ | |
item.type === TransferMethod.remote_url | |
? item.url | |
: item.base64Url | |
} | |
onClick={() => | |
item.progress === 100 | |
&& setImagePreviewUrl( | |
(item.type === TransferMethod.remote_url | |
? item.url | |
: item.base64Url) as string, | |
) | |
} | |
/> | |
{!readonly && ( | |
<button | |
type="button" | |
className={cn( | |
'absolute z-10 -top-[9px] -right-[9px] items-center justify-center w-[18px] h-[18px]', | |
'bg-white hover:bg-gray-50 border-[0.5px] border-black/2 rounded-2xl shadow-lg', | |
item.progress === -1 ? 'flex' : 'hidden group-hover:flex', | |
)} | |
onClick={() => onRemove && onRemove(item._id)} | |
> | |
<RiCloseLine className="w-3 h-3 text-gray-500" /> | |
</button> | |
)} | |
</div> | |
))} | |
{imagePreviewUrl && ( | |
<ImagePreview | |
url={imagePreviewUrl} | |
onCancel={() => setImagePreviewUrl('')} | |
title='' | |
/> | |
)} | |
</div> | |
) | |
} | |
export default ImageList | |