|
|
|
import * as React from 'react';
|
|
|
|
import CSSMotion from 'rc-motion';
|
|
|
|
import classNames from 'classnames';
|
|
|
|
import EyeOutlined from '@ant-design/icons/EyeOutlined';
|
|
|
|
import DeleteOutlined from '@ant-design/icons/DeleteOutlined';
|
|
|
|
import DownloadOutlined from '@ant-design/icons/DownloadOutlined';
|
|
|
|
import Tooltip from '../../tooltip';
|
|
|
|
import Progress from '../../progress';
|
|
|
|
import { ConfigContext } from '../../config-provider';
|
|
|
|
|
|
|
|
import type {
|
|
|
|
ItemRender,
|
|
|
|
UploadFile,
|
|
|
|
UploadListProgressProps,
|
|
|
|
UploadListType,
|
|
|
|
UploadLocale,
|
|
|
|
} from '../interface';
|
|
|
|
|
|
|
|
export interface ListItemProps {
|
|
|
|
prefixCls: string;
|
|
|
|
className?: string;
|
|
|
|
style?: React.CSSProperties;
|
|
|
|
locale: UploadLocale;
|
|
|
|
file: UploadFile;
|
|
|
|
items: UploadFile[];
|
|
|
|
listType?: UploadListType;
|
|
|
|
isImgUrl?: (file: UploadFile) => boolean;
|
|
|
|
showRemoveIcon?: boolean;
|
|
|
|
showDownloadIcon?: boolean;
|
|
|
|
showPreviewIcon?: boolean;
|
|
|
|
removeIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
|
|
|
downloadIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
|
|
|
previewIcon?: React.ReactNode | ((file: UploadFile) => React.ReactNode);
|
|
|
|
iconRender: (file: UploadFile) => React.ReactNode;
|
|
|
|
actionIconRender: (
|
|
|
|
customIcon: React.ReactNode,
|
|
|
|
callback: () => void,
|
|
|
|
prefixCls: string,
|
|
|
|
title?: string | undefined,
|
|
|
|
) => React.ReactNode;
|
|
|
|
itemRender?: ItemRender;
|
|
|
|
onPreview: (file: UploadFile, e: React.SyntheticEvent<HTMLElement>) => void;
|
|
|
|
onClose: (file: UploadFile) => void;
|
|
|
|
onDownload: (file: UploadFile) => void;
|
|
|
|
progress?: UploadListProgressProps;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ListItem = React.forwardRef(
|
|
|
|
(
|
|
|
|
{
|
|
|
|
prefixCls,
|
|
|
|
className,
|
|
|
|
style,
|
|
|
|
locale,
|
|
|
|
listType,
|
|
|
|
file,
|
|
|
|
items,
|
|
|
|
progress: progressProps,
|
|
|
|
iconRender,
|
|
|
|
actionIconRender,
|
|
|
|
itemRender,
|
|
|
|
isImgUrl,
|
|
|
|
showPreviewIcon,
|
|
|
|
showRemoveIcon,
|
|
|
|
showDownloadIcon,
|
|
|
|
previewIcon: customPreviewIcon,
|
|
|
|
removeIcon: customRemoveIcon,
|
|
|
|
downloadIcon: customDownloadIcon,
|
|
|
|
onPreview,
|
|
|
|
onDownload,
|
|
|
|
onClose,
|
|
|
|
}: ListItemProps,
|
|
|
|
ref: React.Ref<HTMLDivElement>,
|
|
|
|
) => {
|
|
|
|
// Delay to show the progress bar
|
|
|
|
const [showProgress, setShowProgress] = React.useState(false);
|
|
|
|
const progressRafRef = React.useRef<any>();
|
|
|
|
React.useEffect(() => {
|
|
|
|
progressRafRef.current = setTimeout(() => {
|
|
|
|
setShowProgress(true);
|
|
|
|
}, 300);
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
window.clearTimeout(progressRafRef.current);
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const iconNode = iconRender(file);
|
|
|
|
let icon = <div className={`${prefixCls}-icon`}>{iconNode}</div>;
|
|
|
|
if (listType === 'picture' || listType === 'picture-card') {
|
|
|
|
if (file.status === 'uploading' || (!file.thumbUrl && !file.url)) {
|
|
|
|
const uploadingClassName = classNames({
|
|
|
|
[`${prefixCls}-list-item-thumbnail`]: true,
|
|
|
|
[`${prefixCls}-list-item-file`]: file.status !== 'uploading',
|
|
|
|
});
|
|
|
|
icon = <div className={uploadingClassName}>{iconNode}</div>;
|
|
|
|
} else {
|
|
|
|
const thumbnail = isImgUrl?.(file) ? (
|
|
|
|
<img
|
|
|
|
src={file.thumbUrl || file.url}
|
|
|
|
alt={file.name}
|
|
|
|
className={`${prefixCls}-list-item-image`}
|
|
|
|
crossOrigin={file.crossOrigin}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
iconNode
|
|
|
|
);
|
|
|
|
const aClassName = classNames({
|
|
|
|
[`${prefixCls}-list-item-thumbnail`]: true,
|
|
|
|
[`${prefixCls}-list-item-file`]: isImgUrl && !isImgUrl(file),
|
|
|
|
});
|
|
|
|
icon = (
|
|
|
|
<a
|
|
|
|
className={aClassName}
|
|
|
|
onClick={e => onPreview(file, e)}
|
|
|
|
href={file.url || file.thumbUrl}
|
|
|
|
target="_blank"
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
>
|
|
|
|
{thumbnail}
|
|
|
|
</a>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const listItemClassName = classNames(
|
|
|
|
`${prefixCls}-list-item`,
|
|
|
|
`${prefixCls}-list-item-${file.status}`,
|
|
|
|
);
|
|
|
|
const linkProps =
|
|
|
|
typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps;
|
|
|
|
|
|
|
|
const removeIcon = showRemoveIcon
|
|
|
|
? actionIconRender(
|
|
|
|
(typeof customRemoveIcon === 'function' ? customRemoveIcon(file) : customRemoveIcon) || (
|
|
|
|
<DeleteOutlined />
|
|
|
|
),
|
|