From bc718b0f510f1150b951d14e296eb194fb21791b Mon Sep 17 00:00:00 2001 From: madocto Date: Sat, 20 Jan 2024 18:25:27 +0800 Subject: [PATCH] feat: listen document paste event --- src/AjaxUploader.tsx | 35 ++++++++++++++++++++++++++--------- tests/uploader.spec.tsx | 4 ++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/AjaxUploader.tsx b/src/AjaxUploader.tsx index aaeb4c4..155384f 100644 --- a/src/AjaxUploader.tsx +++ b/src/AjaxUploader.tsx @@ -28,6 +28,8 @@ class AjaxUploader extends Component { private fileInput: HTMLInputElement; + private isMouseEnter: boolean; + private _isMounted: boolean; onChange = (e: React.ChangeEvent) => { @@ -66,9 +68,7 @@ class AjaxUploader extends Component { } }; - onFileDropOrPaste = ( - e: React.DragEvent | React.ClipboardEvent, - ) => { + onFileDropOrPaste = (e: React.DragEvent | ClipboardEvent) => { e.preventDefault(); if (e.type === 'dragover') { @@ -84,7 +84,7 @@ class AjaxUploader extends Component { items = [...(dataTransfer.items || [])]; files = [...(dataTransfer.files || [])]; } else if (e.type === 'paste') { - const clipboardData = (e as React.ClipboardEvent).clipboardData; + const clipboardData = (e as ClipboardEvent).clipboardData; items = [...(clipboardData.items || [])]; files = [...(clipboardData.files || [])]; } @@ -104,13 +104,21 @@ class AjaxUploader extends Component { } }; + onPrePaste(e: ClipboardEvent) { + if (this.isMouseEnter) { + this.onFileDropOrPaste(e); + } + } + componentDidMount() { this._isMounted = true; + document.addEventListener('paste', this.onPrePaste.bind(this)); } componentWillUnmount() { this._isMounted = false; this.abort(); + document.removeEventListener('paste', this.onPrePaste.bind(this)); } uploadFiles = (files: File[]) => { @@ -271,6 +279,18 @@ class AjaxUploader extends Component { this.fileInput = node; }; + handleMouseEnter = (e: React.MouseEvent) => { + this.isMouseEnter = true; + + this.props.onMouseEnter?.(e); + }; + + handleMouseLeave = (e: React.MouseEvent) => { + this.isMouseEnter = false; + + this.props.onMouseLeave?.(e); + }; + render() { const { component: Tag, @@ -287,8 +307,6 @@ class AjaxUploader extends Component { children, directory, openFileDialogOnClick, - onMouseEnter, - onMouseLeave, hasControlInside, ...otherProps } = this.props; @@ -306,11 +324,10 @@ class AjaxUploader extends Component { : { onClick: openFileDialogOnClick ? this.onClick : () => {}, onKeyDown: openFileDialogOnClick ? this.onKeyDown : () => {}, - onMouseEnter, - onMouseLeave, + onMouseEnter: this.handleMouseEnter, + onMouseLeave: this.handleMouseLeave, onDrop: this.onFileDropOrPaste, onDragOver: this.onFileDropOrPaste, - onPaste: this.onFileDropOrPaste, tabIndex: hasControlInside ? undefined : '0', }; return ( diff --git a/tests/uploader.spec.tsx b/tests/uploader.spec.tsx index 6917599..2fd2477 100644 --- a/tests/uploader.spec.tsx +++ b/tests/uploader.spec.tsx @@ -307,6 +307,7 @@ describe('uploader', () => { }); it('paste to upload', done => { + const rcUpload = uploader.container.querySelector('.rc-upload')!; const input = uploader.container.querySelector('input')!; const files = [ @@ -329,6 +330,7 @@ describe('uploader', () => { done(err); }; + fireEvent.mouseEnter(rcUpload); fireEvent.paste(input, { clipboardData: { files }, }); @@ -363,6 +365,7 @@ describe('uploader', () => { it('paste files with multiple false', done => { const { container } = render(); + const rcUpload = container.querySelector('.rc-upload')!; const input = container.querySelector('input')!; const files = [ new File([''], 'success.png', { type: 'image/png' }), @@ -395,6 +398,7 @@ describe('uploader', () => { value: files, }); + fireEvent.mouseEnter(rcUpload); fireEvent.paste(input, { clipboardData: { files } }); setTimeout(() => {