import React, { HTMLAttributes, ReactNode, useCallback, useRef, useState } from 'react' import cns from 'classnames' import { doAccept } from '../utils/file' import { BaseUploadRef, BaseUpload, BaseUploadProps } from './BaseUpload' import { usePrefix } from '../ConfigProvider' import { concat } from '../utils' import { WithRef } from '../utils/type' export interface DragUploadProps extends Omit { /** * 生成展示内容的方法,会覆盖掉 children * @param dragStatus 拖动事件的类型 */ renderContent?: (dragStatus: React.DragEvent['type']) => ReactNode /** 上传按钮的 html 属性 */ buttonHtmlProps?: WithRef, HTMLSpanElement> } export function Drag(props: DragUploadProps) { const { renderContent, children, buttonHtmlProps, ...baseProps } = props const { accept = '', disabled } = baseProps const [dragStatus, setDragStatus] = useState['type']>('drop') const prefix = usePrefix('upload') const typePrefix = concat(prefix, 'drag') const buttonPrefix = concat(prefix, 'button') const baseUploadRef = useRef(null) const onDragOver = useCallback((e: React.DragEvent) => { e.preventDefault() setDragStatus(e.type) }, []) const onDragLeave = useCallback((e: React.DragEvent) => { setDragStatus(e.type) }, []) const onDrop = useCallback((e: React.DragEvent) => { e.preventDefault() if (disabled) return setDragStatus(e.type) const files = e.dataTransfer.files if (files) { const list: File[] = Array.from(files).filter(file => doAccept(file, accept)) baseUploadRef.current?.uploadFiles(list) } }, [accept, disabled]) return ( baseUploadRef.current?.handleClick()} onDragOver={onDragOver} onDrop={onDrop} onDragLeave={onDragLeave} > {renderContent ? renderContent(dragStatus) : children} ) }