import type { DId } from '../../utils/types';
import type { DUploadFile } from './Upload';
import type { DUploadActionPrivateProps } from './UploadAction';
import { isNumber } from 'lodash';
import React, { useState } from 'react';
import { useImmer, useMount } from '@react-devui/hooks';
import { FileTwoTone } from '@react-devui/icons';
import { getClassName } from '@react-devui/utils';
import { TTANSITION_DURING_BASE } from '../../utils';
import { DTransition } from '../_transition';
import { DProgress } from '../progress';
import { usePrefixConfig, useTranslation } from '../root';
export interface DPictureProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'children'> {
children?: React.ReactNode;
dFileList: DUploadFile[];
dDefaultActions?: {
preview?: (file: DUploadFile) => void;
download?: (file: DUploadFile) => void;
};
dActions: (file: DUploadFile, index: number) => React.ReactNode[];
onRemove: (file: DUploadFile) => void;
}
export function DPicture(props: DPictureProps): JSX.Element | null {
const { children, dFileList, dDefaultActions, dActions, onRemove } = props;
const dPrefix = usePrefixConfig();
const [t] = useTranslation();
const [removeUIDs, setRemoveUIDs] = useImmer<DId[]>([]);
const [skipFirstTransition, setSkipFirstTransition] = useState(true);
useMount(() => {
setSkipFirstTransition(false);
});
return (
<ul className={`${dPrefix}upload__picture`}>
{dFileList.map((file, index) => {
const actions = dActions(file, index);
const isLoading = file && file.status === 'progress';
return (
<DTransition
key={file.uid}
dIn={!removeUIDs.includes(file.uid)}
dDuring={TTANSITION_DURING_BASE}
dSkipFirstTransition={skipFirstTransition}
afterLeave={() => {
setRemoveUIDs((draft) => {
draft.splice(
draft.findIndex((uid) => uid === file.uid),
1
);
});
onRemove(file);
}}
>
{(state) => {
let transitionStyle: React.CSSProperties = {};
switch (state) {
case 'enter':
transitionStyle = { transform: 'scale(0)' };
break;
case 'entering':
transitionStyle = {
transition: ['transform'].map((attr) => `${attr} ${TTANSITION_DURING_BASE}ms ease-out`).join(', '),
transformOrigin: 'top left',
};
break;
case 'leaving':
transitionStyle = {
transform: 'scale(0)',
transition: ['transform'].map((attr) => `${attr} ${TTANSITION_DURING_BASE}ms ease-in`).join(', '),
transformOrigin: 'top left',
};
break;
case 'leaved':
transitionStyle = { display: 'none' };
break;
default:
break;
}
return (
<li
className={getClassName(`${dPrefix}upload__picture-item`, `${dPrefix}upload__picture-item--${file.status}`, {
'is-disabled': isLoading,
})}
style={transitionStyle}
>
{file.status !== 'progress' ? (
<>
{file.thumbUrl ? (
<img className={`${dPrefix}upload__picture-preview`} src={file.thumbUrl} alt={file.name} />
) : (
<>
<FileTwoTone dSize={28} dTheme={file.status === 'error' ? 'danger' : 'primary'} />
<div className={`${dPrefix}upload__picture-name`}>{file.name}</div>
</>
)}
<div className={`${dPrefix}upload__picture-actions`}>
{React.Children.map(actions, (action: any) =>
React.cloneElement<DUploadActionPrivateProps>(action, {
__file: file,
__defaultActions: dDefaultActions,
__onRemove: () => {
setRemoveUIDs((draft) => {
draft.push(file.uid);
});
},
})
)}
</div>
</>
) : (
<>
<div className={`${dPrefix}upload__picture-text`}>{t('Upload', 'Uploading')}</div>
{isNumber(file.percent) && <DProgress dPercent={file.percent} dLineWidth={2} dLabel={false}></DProgress>}
</>
)}
</li>
);
}}
</DTransition>
);
})}
{children}
</ul>
);
}