| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 | 
							- import React, { ReactNode, CSSProperties, RefObject, ChangeEvent, DragEvent } from 'react';
 
- import cls from 'classnames';
 
- import PropTypes from 'prop-types';
 
- import { noop, pick } from 'lodash';
 
- import UploadFoundation from '@douyinfe/semi-foundation/upload/foundation';
 
- import { strings, cssClasses } from '@douyinfe/semi-foundation/upload/constants';
 
- import FileCard from './fileCard';
 
- import BaseComponent from '../_base/baseComponent';
 
- import LocaleConsumer from '../locale/localeConsumer';
 
- import { IconUpload } from '@douyinfe/semi-icons';
 
- import type {
 
-     FileItem,
 
-     RenderFileItemProps,
 
-     UploadListType,
 
-     PromptPositionType,
 
-     BeforeUploadProps,
 
-     AfterUploadProps,
 
-     OnChangeProps,
 
-     customRequestArgs,
 
-     CustomError,
 
-     RenderPictureCloseProps,
 
- } from './interface';
 
- import { Locale } from '../locale/interface';
 
- import '@douyinfe/semi-foundation/upload/upload.scss';
 
- import type {
 
-     CustomFile,
 
-     UploadAdapter,
 
-     BeforeUploadObjectResult,
 
-     AfterUploadResult,
 
-     FileItemStatus
 
- } from '@douyinfe/semi-foundation/upload/foundation';
 
- import type { ValidateStatus } from '../_base/baseComponent';
 
- import { ShowTooltip } from '../typography';
 
- const prefixCls = cssClasses.PREFIX;
 
- export type {
 
-     FileItem,
 
-     FileItemStatus,
 
-     RenderFileItemProps,
 
-     UploadListType,
 
-     PromptPositionType,
 
-     BeforeUploadProps,
 
-     AfterUploadProps,
 
-     OnChangeProps,
 
-     customRequestArgs,
 
-     CustomError,
 
-     BeforeUploadObjectResult,
 
-     AfterUploadResult,
 
- };
 
- export interface UploadProps {
 
-     accept?: string;
 
-     action: string;
 
-     afterUpload?: (object: AfterUploadProps) => AfterUploadResult;
 
-     beforeUpload?: (
 
-         object: BeforeUploadProps
 
-     ) => BeforeUploadObjectResult | Promise<BeforeUploadObjectResult> | boolean;
 
-     beforeClear?: (fileList: Array<FileItem>) => boolean | Promise<boolean>;
 
-     beforeRemove?: (file: FileItem, fileList: Array<FileItem>) => boolean | Promise<boolean>;
 
-     capture?: boolean | 'user' | 'environment' | undefined;
 
-     children?: ReactNode;
 
-     className?: string;
 
-     customRequest?: (object: customRequestArgs) => void;
 
-     data?: Record<string, any> | ((file: File) => Record<string, unknown>);
 
-     defaultFileList?: Array<FileItem>;
 
-     directory?: boolean;
 
-     disabled?: boolean;
 
-     dragIcon?: ReactNode;
 
-     dragMainText?: ReactNode;
 
-     dragSubText?: ReactNode;
 
-     draggable?: boolean;
 
-     addOnPasting?: boolean;
 
-     fileList?: Array<FileItem>;
 
-     fileName?: string;
 
-     headers?: Record<string, any> | ((file: File) => Record<string, string>);
 
-     hotSpotLocation?: 'start' | 'end';
 
-     itemStyle?: CSSProperties;
 
-     limit?: number;
 
-     listType?: UploadListType;
 
-     maxSize?: number;
 
-     minSize?: number;
 
-     multiple?: boolean;
 
-     name?: string;
 
-     onAcceptInvalid?: (files: File[]) => void;
 
-     onChange?: (object: OnChangeProps) => void;
 
-     onClear?: () => void;
 
-     onDrop?: (e: Event, files: Array<File>, fileList: Array<FileItem>) => void;
 
-     onError?: (e: CustomError, file: File, fileList: Array<FileItem>, xhr: XMLHttpRequest) => void;
 
-     onPastingError?: (error: Error | PermissionStatus) => void;
 
-     onExceed?: (fileList: Array<File>) => void;
 
-     onFileChange?: (files: Array<File>) => void;
 
-     onOpenFileDialog?: () => void;
 
-     onPreviewClick?: (fileItem: FileItem) => void;
 
-     onProgress?: (percent: number, file: File, fileList: Array<FileItem>) => void;
 
-     onRemove?: (currentFile: File, fileList: Array<FileItem>, currentFileItem: FileItem) => void;
 
-     onRetry?: (fileItem: FileItem) => void;
 
-     onSizeError?: (file: File, fileList: Array<FileItem>) => void;
 
-     onSuccess?: (responseBody: any, file: File, fileList: Array<FileItem>) => void;
 
-     previewFile?: (renderFileItemProps: RenderFileItemProps) => ReactNode;
 
-     prompt?: ReactNode;
 
-     promptPosition?: PromptPositionType;
 
-     picHeight?: string | number;
 
-     picWidth?: string | number;
 
-     renderFileItem?: (renderFileItemProps: RenderFileItemProps) => ReactNode;
 
-     renderPicInfo?: (renderFileItemProps: RenderFileItemProps) => ReactNode;
 
-     renderThumbnail?: (renderFileItemProps: RenderFileItemProps) => ReactNode;
 
-     renderPicPreviewIcon?: (renderFileItemProps: RenderFileItemProps) => ReactNode;
 
-     renderPicClose?: (renderPicCloseProps: RenderPictureCloseProps) => ReactNode;
 
-     renderFileOperation?: (fileItem: RenderFileItemProps) => ReactNode;
 
-     showClear?: boolean;
 
-     showPicInfo?: boolean; // Show pic info in picture wall
 
-     showReplace?: boolean; // Display replacement function
 
-     showRetry?: boolean;
 
-     showUploadList?: boolean;
 
-     style?: CSSProperties;
 
-     timeout?: number;
 
-     transformFile?: (file: File) => FileItem;
 
-     uploadTrigger?: 'auto' | 'custom';
 
-     validateMessage?: ReactNode;
 
-     validateStatus?: ValidateStatus;
 
-     withCredentials?: boolean;
 
-     showTooltip?: boolean | ShowTooltip
 
- }
 
- export interface UploadState {
 
-     dragAreaStatus: 'default' | 'legal' | 'illegal'; // Status of the drag zone
 
-     fileList: Array<FileItem>;
 
-     inputKey: number;
 
-     localUrls: Array<string>;
 
-     replaceIdx: number;
 
-     replaceInputKey: number
 
- }
 
- class Upload extends BaseComponent<UploadProps, UploadState> {
 
-     static propTypes = {
 
-         accept: PropTypes.string, // Limit allowed file types
 
-         action: PropTypes.string.isRequired,
 
-         addOnPasting: PropTypes.bool,
 
-         afterUpload: PropTypes.func,
 
-         beforeClear: PropTypes.func,
 
-         beforeRemove: PropTypes.func,
 
-         beforeUpload: PropTypes.func,
 
-         children: PropTypes.node,
 
-         className: PropTypes.string,
 
-         customRequest: PropTypes.func,
 
-         data: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), // Extra parameters attached when uploading
 
-         defaultFileList: PropTypes.array,
 
-         directory: PropTypes.bool, // Support folder upload
 
-         disabled: PropTypes.bool,
 
-         dragIcon: PropTypes.node,
 
-         dragMainText: PropTypes.node,
 
-         dragSubText: PropTypes.node,
 
-         draggable: PropTypes.bool,
 
-         fileList: PropTypes.array, // files had been uploaded
 
-         fileName: PropTypes.string, // same as name, to avoid props conflict in Form.Upload
 
-         headers: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
 
-         hotSpotLocation: PropTypes.oneOf(['start', 'end']),
 
-         itemStyle: PropTypes.object,
 
-         limit: PropTypes.number, // 最大允许上传文件个数
 
-         listType: PropTypes.oneOf<UploadProps['listType']>(strings.LIST_TYPE),
 
-         maxSize: PropTypes.number, // 文件大小限制,单位kb
 
-         minSize: PropTypes.number, // 文件大小限制,单位kb
 
-         multiple: PropTypes.bool,
 
-         name: PropTypes.string, // file name
 
-         onAcceptInvalid: PropTypes.func,
 
-         onChange: PropTypes.func,
 
-         onClear: PropTypes.func,
 
-         onDrop: PropTypes.func,
 
-         onError: PropTypes.func,
 
-         onExceed: PropTypes.func, // Callback exceeding limit
 
-         onFileChange: PropTypes.func, // Callback when file is selected
 
-         onOpenFileDialog: PropTypes.func,
 
-         onPreviewClick: PropTypes.func,
 
-         onProgress: PropTypes.func,
 
-         onRemove: PropTypes.func,
 
-         onRetry: PropTypes.func,
 
-         onSizeError: PropTypes.func, // Callback with invalid file size
 
-         onSuccess: PropTypes.func,
 
-         onPastingError: PropTypes.func,
 
-         previewFile: PropTypes.func, // Custom preview
 
-         prompt: PropTypes.node,
 
-         promptPosition: PropTypes.oneOf<UploadProps['promptPosition']>(strings.PROMPT_POSITION),
 
-         picWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
 
-         picHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
 
-         renderFileItem: PropTypes.func,
 
-         renderPicPreviewIcon: PropTypes.func,
 
-         renderFileOperation: PropTypes.func,
 
-         renderPicClose: PropTypes.func,
 
-         renderPicInfo: PropTypes.func,
 
-         renderThumbnail: PropTypes.func,
 
-         showClear: PropTypes.bool,
 
-         showPicInfo: PropTypes.bool,
 
-         showReplace: PropTypes.bool,
 
-         showRetry: PropTypes.bool,
 
-         showUploadList: PropTypes.bool, // whether to show fileList
 
-         style: PropTypes.object,
 
-         timeout: PropTypes.number,
 
-         transformFile: PropTypes.func,
 
-         uploadTrigger: PropTypes.oneOf<UploadProps['uploadTrigger']>(strings.UPLOAD_TRIGGER), // auto、custom
 
-         validateMessage: PropTypes.node,
 
-         validateStatus: PropTypes.oneOf<UploadProps['validateStatus']>(strings.VALIDATE_STATUS),
 
-         withCredentials: PropTypes.bool,
 
-         showTooltip: PropTypes.oneOfType([PropTypes.bool, PropTypes.object])
 
-     };
 
-     static defaultProps: Partial<UploadProps> = {
 
-         defaultFileList: [],
 
-         disabled: false,
 
-         listType: 'list' as const,
 
-         hotSpotLocation: 'end',
 
-         multiple: false,
 
-         onAcceptInvalid: noop,
 
-         onChange: noop,
 
-         beforeRemove: () => true,
 
-         beforeClear: () => true,
 
-         onClear: noop,
 
-         onDrop: noop,
 
-         onError: noop,
 
-         onExceed: noop,
 
-         onFileChange: noop,
 
-         onOpenFileDialog: noop,
 
-         onProgress: noop,
 
-         onRemove: noop,
 
-         onRetry: noop,
 
-         onSizeError: noop,
 
-         onSuccess: noop,
 
-         onPastingError: noop,
 
-         promptPosition: 'right' as const,
 
-         showClear: true,
 
-         showPicInfo: false,
 
-         showReplace: false,
 
-         showRetry: true,
 
-         showUploadList: true,
 
-         uploadTrigger: 'auto' as const,
 
-         withCredentials: false,
 
-         showTooltip: true,
 
-     };
 
-     static FileCard = FileCard;
 
-     constructor(props: UploadProps) {
 
-         super(props);
 
-         this.state = {
 
-             fileList: props.defaultFileList || [],
 
-             replaceIdx: -1,
 
-             inputKey: Math.random(),
 
-             replaceInputKey: Math.random(),
 
-             // Status of the drag zone
 
-             dragAreaStatus: 'default',
 
-             localUrls: [],
 
-         };
 
-         this.foundation = new UploadFoundation(this.adapter);
 
-         this.inputRef = React.createRef<HTMLInputElement>();
 
-         this.replaceInputRef = React.createRef<HTMLInputElement>();
 
-     }
 
-     /**
 
-      * Notes: 
 
-      *   The input parameter and return value here do not declare the type, otherwise tsc may report an error in form/fields.tsx when wrap after withField
 
-      *   `The types of the parameters "props" and "nextProps" are incompatible.
 
-            The attribute "action" is missing in the type "Readonly<any>", but it is required in the type "UploadProps".`
 
-      *   which seems to be a bug, remove props type declare here
 
-      */
 
-     static getDerivedStateFromProps(props) {
 
-         const { fileList } = props;
 
-         if ('fileList' in props) {
 
-             return {
 
-                 fileList: fileList || [],
 
-             };
 
-         }
 
-         return null;
 
-     }
 
-     get adapter(): UploadAdapter<UploadProps, UploadState> {
 
-         return {
 
-             ...super.adapter,
 
-             notifyFileSelect: (files): void => this.props.onFileChange(files),
 
-             notifyError: (error, fileInstance, fileList, xhr): void =>
 
-                 this.props.onError(error, fileInstance, fileList, xhr),
 
-             notifySuccess: (responseBody, file, fileList): void => this.props.onSuccess(responseBody, file, fileList),
 
-             notifyProgress: (percent, file, fileList): void => this.props.onProgress(percent, file, fileList),
 
-             notifyRemove: (file, fileList, fileItem): void => this.props.onRemove(file, fileList, fileItem),
 
-             notifySizeError: (file, fileList): void => this.props.onSizeError(file, fileList),
 
-             notifyExceed: (fileList): void => this.props.onExceed(fileList),
 
-             updateFileList: (fileList, cb): void => {
 
-                 if (typeof cb === 'function') {
 
-                     this.setState({ fileList }, cb);
 
-                 } else {
 
-                     this.setState({ fileList });
 
-                 }
 
-             },
 
-             notifyBeforeUpload: ({
 
-                 file,
 
-                 fileList,
 
-             }): boolean | BeforeUploadObjectResult | Promise<BeforeUploadObjectResult> =>
 
-                 this.props.beforeUpload({ file, fileList }),
 
-             notifyAfterUpload: ({ response, file, fileList }): AfterUploadResult =>
 
-                 this.props.afterUpload({ response, file, fileList }),
 
-             resetInput: (): void => {
 
-                 this.setState(prevState => ({
 
-                     inputKey: Math.random(),
 
-                 }));
 
-             },
 
-             resetReplaceInput: (): void => {
 
-                 this.setState(prevState => ({
 
-                     replaceInputKey: Math.random(),
 
-                 }));
 
-             },
 
-             isMac: (): boolean => {
 
-                 return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
 
-             },
 
-             registerPastingHandler: (cb?: (e: KeyboardEvent) => void): void => {
 
-                 document.body.addEventListener('keydown', cb);
 
-                 this.pastingCb = cb;
 
-             },
 
-             unRegisterPastingHandler: (): void => {
 
-                 if (this.pastingCb) {
 
-                     document.body.removeEventListener('keydown', this.pastingCb);
 
-                 }
 
-             },
 
-             notifyPastingError: (error): void => this.props.onPastingError(error),
 
-             updateDragAreaStatus: (dragAreaStatus: string): void =>
 
-                 this.setState({ dragAreaStatus } as { dragAreaStatus: 'default' | 'legal' | 'illegal' }),
 
-             notifyChange: ({ currentFile, fileList }): void => this.props.onChange({ currentFile, fileList }),
 
-             updateLocalUrls: (urls): void => this.setState({ localUrls: urls }),
 
-             notifyClear: (): void => this.props.onClear(),
 
-             notifyPreviewClick: (file): void => this.props.onPreviewClick(file),
 
-             notifyDrop: (e, files, fileList): void => this.props.onDrop(e, files, fileList),
 
-             notifyAcceptInvalid: (invalidFiles): void => this.props.onAcceptInvalid(invalidFiles),
 
-             notifyBeforeRemove: (file, fileList): boolean | Promise<boolean> => this.props.beforeRemove(file, fileList),
 
-             notifyBeforeClear: (fileList): boolean | Promise<boolean> => this.props.beforeClear(fileList),
 
-         };
 
-     }
 
-     foundation: UploadFoundation;
 
-     inputRef: RefObject<HTMLInputElement> = null;
 
-     replaceInputRef: RefObject<HTMLInputElement> = null;
 
-     pastingCb: null | ((params: any) => void);
 
-     componentDidMount(): void {
 
-         this.foundation.init();
 
-     }
 
-     componentWillUnmount(): void {
 
-         this.foundation.destroy();
 
-     }
 
-     onClick = (): void => {
 
-         const { inputRef, props } = this;
 
-         const { onOpenFileDialog } = props;
 
-         const isDisabled = Boolean(this.props.disabled);
 
-         if (isDisabled || !inputRef || !inputRef.current) {
 
-             return;
 
-         }
 
-         inputRef.current.click();
 
-         if (onOpenFileDialog && typeof onOpenFileDialog) {
 
-             onOpenFileDialog();
 
-         }
 
-     };
 
-     onChange = (e: ChangeEvent<HTMLInputElement>): void => {
 
-         const { files } = e.target;
 
-         this.foundation.handleChange(files);
 
-     };
 
-     replace = (index: number): void => {
 
-         this.setState({ replaceIdx: index }, () => {
 
-             this.replaceInputRef.current.click();
 
-         });
 
-     };
 
-     onReplaceChange = (e: ChangeEvent<HTMLInputElement>): void => {
 
-         const { files } = e.target;
 
-         this.foundation.handleReplaceChange(files);
 
-     };
 
-     clear = (): void => {
 
-         this.foundation.handleClear();
 
-     };
 
-     remove = (fileItem: FileItem): void => {
 
-         this.foundation.handleRemove(fileItem);
 
-     };
 
-     /**
 
-      * ref method
 
-      * insert files at index
 
-      * @param files Array<CustomFile>
 
-      * @param index number
 
-      * @returns
 
-      */
 
-     insert = (files: Array<CustomFile>, index?: number): void => {
 
-         return this.foundation.insertFileToList(files, index);
 
-     };
 
-     /**
 
-      * ref method
 
-      * manual upload by user
 
-      */
 
-     upload = (): void => {
 
-         this.foundation.manualUpload();
 
-     };
 
-     /**
 
-      * ref method
 
-      * manual open file select dialog
 
-      */
 
-     openFileDialog = (): void => {
 
-         this.onClick();
 
-     };
 
-     renderFile = (file: FileItem, index: number, locale: Locale['Upload']): ReactNode => {
 
-         const { name, status, validateMessage, _sizeInvalid, uid } = file;
 
-         const {
 
-             previewFile,
 
-             listType,
 
-             itemStyle,
 
-             showPicInfo,
 
-             renderPicInfo,
 
-             renderPicClose,
 
-             renderPicPreviewIcon,
 
-             renderFileOperation,
 
-             renderFileItem,
 
-             renderThumbnail,
 
-             disabled,
 
-             onPreviewClick,
 
-             picWidth,
 
-             picHeight,
 
-             showTooltip,
 
-         } = this.props;
 
-         const onRemove = (): void => this.remove(file);
 
-         const onRetry = (): void => {
 
-             this.foundation.retry(file);
 
-         };
 
-         const onReplace = (): void => {
 
-             this.replace(index);
 
-         };
 
-         const fileCardProps = {
 
-             ...pick(this.props, ['showRetry', 'showReplace', '']),
 
-             ...file,
 
-             previewFile,
 
-             listType,
 
-             onRemove,
 
-             onRetry,
 
-             index,
 
-             key: uid || `${name}${index}`,
 
-             style: itemStyle,
 
-             disabled,
 
-             showPicInfo,
 
-             renderPicInfo,
 
-             renderPicPreviewIcon,
 
-             renderPicClose,
 
-             renderFileOperation,
 
-             renderThumbnail,
 
-             onReplace,
 
-             onPreviewClick:
 
-                 typeof onPreviewClick !== 'undefined'
 
-                     ? (): void => this.foundation.handlePreviewClick(file)
 
-                     : undefined,
 
-             picWidth,
 
-             picHeight,
 
-             showTooltip,
 
-         };
 
-         if (status === strings.FILE_STATUS_UPLOAD_FAIL && !validateMessage) {
 
-             fileCardProps.validateMessage = locale.fail;
 
-         }
 
-         if (_sizeInvalid && !validateMessage) {
 
-             fileCardProps.validateMessage = locale.illegalSize;
 
-         }
 
-         if (typeof renderFileItem === 'undefined') {
 
-             return <FileCard {...fileCardProps} />;
 
-         } else {
 
-             return renderFileItem(fileCardProps);
 
-         }
 
-     };
 
-     renderFileList = (): ReactNode => {
 
-         const { listType } = this.props;
 
-         if (listType === strings.FILE_LIST_PIC) {
 
-             return this.renderFileListPic();
 
-         }
 
-         if (listType === strings.FILE_LIST_DEFAULT) {
 
-             return this.renderFileListDefault();
 
-         }
 
-         return null;
 
-     };
 
-     renderFileListPic = () => {
 
-         const { showUploadList, limit, disabled, children, draggable, hotSpotLocation, picHeight, picWidth } = this.props;
 
-         const { fileList: stateFileList, dragAreaStatus } = this.state;
 
-         const fileList = this.props.fileList || stateFileList;
 
-         const showAddTriggerInList = limit ? limit > fileList.length : true;
 
-         const dragAreaBaseCls = `${prefixCls}-drag-area`;
 
-         const uploadAddCls = cls(`${prefixCls}-add`, {
 
-             [`${prefixCls}-picture-add`]: true,
 
-             [`${prefixCls}-picture-add-disabled`]: disabled,
 
-         });
 
-         const fileListCls = cls(`${prefixCls}-file-list`, {
 
-             [`${prefixCls}-picture-file-list`]: true,
 
-         });
 
-         const dragAreaCls = cls({
 
-             [`${dragAreaBaseCls}-legal`]: dragAreaStatus === strings.DRAG_AREA_LEGAL,
 
-             [`${dragAreaBaseCls}-illegal`]: dragAreaStatus === strings.DRAG_AREA_ILLEGAL,
 
-         });
 
-         const mainCls = `${prefixCls}-file-list-main`;
 
-         const addContentProps = {
 
-             role: 'button',
 
-             className: uploadAddCls,
 
-             onClick: this.onClick,
 
-             style: {
 
-                 height: picHeight,
 
-                 width: picWidth
 
-             }
 
-         };
 
-         const containerProps = {
 
-             className: fileListCls,
 
-         };
 
-         const draggableProps = {
 
-             onDrop: this.onDrop,
 
-             onDragOver: this.onDragOver,
 
-             onDragLeave: this.onDragLeave,
 
-             onDragEnter: this.onDragEnter,
 
-         };
 
-         if (draggable) {
 
-             Object.assign(addContentProps, draggableProps, { className: cls(uploadAddCls, dragAreaCls) });
 
-         }
 
-         const addContent = (
 
-             <div {...addContentProps} x-semi-prop="children">
 
-                 {children}
 
-             </div>
 
-         );
 
-         if (!showUploadList || !fileList.length) {
 
-             if (showAddTriggerInList) {
 
-                 return addContent;
 
-             }
 
-             return null;
 
-         }
 
-         return (
 
-             <LocaleConsumer componentName="Upload">
 
-                 {(locale: Locale['Upload']) => (
 
-                     <div {...containerProps}>
 
-                         <div className={mainCls} role="list" aria-label="picture list">
 
-                             {showAddTriggerInList && hotSpotLocation === 'start' ? addContent : null}
 
-                             {fileList.map((file, index) => this.renderFile(file, index, locale))}
 
-                             {showAddTriggerInList && hotSpotLocation === 'end' ? addContent : null}
 
-                         </div>
 
-                     </div>
 
-                 )}
 
-             </LocaleConsumer>
 
-         );
 
-     };
 
-     renderFileListDefault = () => {
 
-         const { showUploadList, limit, disabled } = this.props;
 
-         const { fileList: stateFileList } = this.state;
 
-         const fileList = this.props.fileList || stateFileList;
 
-         const fileListCls = cls(`${prefixCls}-file-list`);
 
-         const titleCls = `${prefixCls}-file-list-title`;
 
-         const mainCls = `${prefixCls}-file-list-main`;
 
-         const showTitle = limit !== 1 && fileList.length;
 
-         const showClear = this.props.showClear && !disabled;
 
-         const containerProps = {
 
-             className: fileListCls,
 
-         };
 
-         if (!showUploadList || !fileList.length) {
 
-             return null;
 
-         }
 
-         return (
 
-             <LocaleConsumer componentName="Upload">
 
-                 {(locale: Locale['Upload']) => (
 
-                     <div {...containerProps}>
 
-                         {showTitle ? (
 
-                             <div className={titleCls}>
 
-                                 <span className={`${titleCls}-choosen`}>{locale.selectedFiles}</span>
 
-                                 {showClear ? (
 
-                                     <span
 
-                                         role="button"
 
-                                         tabIndex={0}
 
-                                         onClick={this.clear}
 
-                                         className={`${titleCls}-clear`}
 
-                                     >
 
-                                         {locale.clear}
 
-                                     </span>
 
-                                 ) : null}
 
-                             </div>
 
-                         ) : null}
 
-                         <div className={mainCls} role="list" aria-label="file list">
 
-                             {fileList.map((file, index) => this.renderFile(file, index, locale))}
 
-                         </div>
 
-                     </div>
 
-                 )}
 
-             </LocaleConsumer>
 
-         );
 
-     };
 
-     onDrop = (e: DragEvent<HTMLDivElement>): void => {
 
-         this.foundation.handleDrop(e);
 
-     };
 
-     onDragOver = (e: DragEvent<HTMLDivElement>): void => {
 
-         // When a drag element moves within the target element
 
-         this.foundation.handleDragOver(e);
 
-     };
 
-     onDragLeave = (e: DragEvent<HTMLDivElement>): void => {
 
-         this.foundation.handleDragLeave(e);
 
-     };
 
-     onDragEnter = (e: DragEvent<HTMLDivElement>): void => {
 
-         this.foundation.handleDragEnter(e);
 
-     };
 
-     renderAddContent = () => {
 
-         const { draggable, children, listType, disabled } = this.props;
 
-         const uploadAddCls = cls(`${prefixCls}-add`);
 
-         if (listType === strings.FILE_LIST_PIC) {
 
-             return null;
 
-         }
 
-         if (draggable) {
 
-             return this.renderDragArea();
 
-         }
 
-         return (
 
-             <div role="button" tabIndex={0} aria-disabled={disabled} className={uploadAddCls} onClick={this.onClick}>
 
-                 {children}
 
-             </div>
 
-         );
 
-     };
 
-     renderDragArea = (): ReactNode => {
 
-         const { dragAreaStatus } = this.state;
 
-         const { children, dragIcon, dragMainText, dragSubText, disabled } = this.props;
 
-         const dragAreaBaseCls = `${prefixCls}-drag-area`;
 
-         const dragAreaCls = cls(dragAreaBaseCls, {
 
-             [`${dragAreaBaseCls}-legal`]: dragAreaStatus === strings.DRAG_AREA_LEGAL,
 
-             [`${dragAreaBaseCls}-illegal`]: dragAreaStatus === strings.DRAG_AREA_ILLEGAL,
 
-             [`${dragAreaBaseCls}-custom`]: children,
 
-         });
 
-         return (
 
-             <LocaleConsumer componentName="Upload">
 
-                 {(locale: Locale['Upload']): ReactNode => (
 
-                     <div
 
-                         role="button"
 
-                         tabIndex={0}
 
-                         aria-disabled={disabled}
 
-                         className={dragAreaCls}
 
-                         onDrop={this.onDrop}
 
-                         onDragOver={this.onDragOver}
 
-                         onDragLeave={this.onDragLeave}
 
-                         onDragEnter={this.onDragEnter}
 
-                         onClick={this.onClick}
 
-                     >
 
-                         {children ? (
 
-                             children
 
-                         ) : (
 
-                             <>
 
-                                 <div className={`${dragAreaBaseCls}-icon`} x-semi-prop="dragIcon">
 
-                                     {dragIcon || <IconUpload size="extra-large" />}
 
-                                 </div>
 
-                                 <div className={`${dragAreaBaseCls}-text`}>
 
-                                     <div className={`${dragAreaBaseCls}-main-text`} x-semi-prop="dragMainText">
 
-                                         {dragMainText || locale.mainText}
 
-                                     </div>
 
-                                     <div className={`${dragAreaBaseCls}-sub-text`} x-semi-prop="dragSubText">
 
-                                         {dragSubText}
 
-                                     </div>
 
-                                     <div className={`${dragAreaBaseCls}-tips`}>
 
-                                         {dragAreaStatus === strings.DRAG_AREA_LEGAL && (
 
-                                             <span className={`${dragAreaBaseCls}-tips-legal`}>{locale.legalTips}</span>
 
-                                         )}
 
-                                         {dragAreaStatus === strings.DRAG_AREA_ILLEGAL && (
 
-                                             <span className={`${dragAreaBaseCls}-tips-illegal`}>
 
-                                                 {locale.illegalTips}
 
-                                             </span>
 
-                                         )}
 
-                                     </div>
 
-                                 </div>
 
-                             </>
 
-                         )}
 
-                     </div>
 
-                 )}
 
-             </LocaleConsumer>
 
-         );
 
-     };
 
-     render(): ReactNode {
 
-         const {
 
-             style,
 
-             className,
 
-             multiple,
 
-             accept,
 
-             disabled,
 
-             children,
 
-             capture,
 
-             listType,
 
-             prompt,
 
-             promptPosition,
 
-             draggable,
 
-             validateMessage,
 
-             validateStatus,
 
-             directory,
 
-             ...rest
 
-         } = this.props;
 
-         const uploadCls = cls(
 
-             prefixCls,
 
-             {
 
-                 [`${prefixCls}-picture`]: listType === strings.FILE_LIST_PIC,
 
-                 [`${prefixCls}-disabled`]: disabled,
 
-                 [`${prefixCls}-default`]: validateStatus === 'default',
 
-                 [`${prefixCls}-error`]: validateStatus === 'error',
 
-                 [`${prefixCls}-warning`]: validateStatus === 'warning',
 
-                 [`${prefixCls}-success`]: validateStatus === 'success',
 
-             },
 
-             className
 
-         );
 
-         const inputCls = cls(`${prefixCls}-hidden-input`);
 
-         const inputReplaceCls = cls(`${prefixCls}-hidden-input-replace`);
 
-         const promptCls = cls(`${prefixCls}-prompt`);
 
-         const validateMsgCls = cls(`${prefixCls}-validate-message`);
 
-         const dirProps = directory ? { directory: 'directory', webkitdirectory: 'webkitdirectory' } : {};
 
-         return (
 
-             <div className={uploadCls} style={style} x-prompt-pos={promptPosition} {...this.getDataAttr(rest)}>
 
-                 <input
 
-                     key={this.state.inputKey}
 
-                     capture={capture}
 
-                     multiple={multiple}
 
-                     accept={accept}
 
-                     onChange={this.onChange}
 
-                     type="file"
 
-                     autoComplete="off"
 
-                     tabIndex={-1}
 
-                     className={inputCls}
 
-                     ref={this.inputRef}
 
-                     {...dirProps}
 
-                 />
 
-                 <input
 
-                     key={this.state.replaceInputKey}
 
-                     multiple={false}
 
-                     accept={accept}
 
-                     onChange={this.onReplaceChange}
 
-                     type="file"
 
-                     autoComplete="off"
 
-                     tabIndex={-1}
 
-                     className={inputReplaceCls}
 
-                     ref={this.replaceInputRef}
 
-                 />
 
-                 {this.renderAddContent()}
 
-                 {prompt ? (
 
-                     <div className={promptCls} x-semi-prop="prompt">
 
-                         {prompt}
 
-                     </div>
 
-                 ) : null}
 
-                 {validateMessage ? (
 
-                     <div className={validateMsgCls} x-semi-prop="validateMessage">
 
-                         {validateMessage}
 
-                     </div>
 
-                 ) : null}
 
-                 {this.renderFileList()}
 
-             </div>
 
-         );
 
-     }
 
- }
 
- export default Upload;
 
 
  |