1
1
import * as React from 'react' ;
2
- import Dropzone , { DropzoneProps , DropzoneInputProps , DropFileEventHandler } from 'react-dropzone' ;
2
+ import { DropEvent , DropzoneInputProps , DropzoneOptions , FileRejection , useDropzone } from 'react-dropzone' ;
3
3
import { FileUploadField , FileUploadFieldProps } from './FileUploadField' ;
4
4
import { readFile , fileReaderType } from '../../helpers/fileUtils' ;
5
5
import { fromEvent } from 'file-selector' ;
6
6
7
- interface DropzoneInputPropsWithRef extends DropzoneInputProps {
8
- ref : React . RefCallback < HTMLInputElement > ; // Working around an issue in react-dropzone 9.0.0's types. Should not be necessary in later versions.
9
- }
10
-
11
7
export interface FileUploadProps
12
8
extends Omit <
13
9
FileUploadFieldProps ,
@@ -29,11 +25,11 @@ export interface FileUploadProps
29
25
filename : string ,
30
26
event :
31
27
| React . MouseEvent < HTMLButtonElement , MouseEvent > // Clear button was clicked
32
- | React . DragEvent < HTMLElement > // User dragged/dropped a file
33
28
| React . ChangeEvent < HTMLElement > // User typed in the TextArea
29
+ | DropEvent
34
30
) => void ;
35
31
/** Change event emitted from the hidden \<input type="file" \> field associated with the component */
36
- onFileInputChange ?: ( event : React . ChangeEvent < HTMLInputElement > | React . DragEvent < HTMLElement > , file : File ) => void ;
32
+ onFileInputChange ?: ( event : DropEvent , file : File ) => void ;
37
33
/** Callback for clicking on the FileUploadField text area. By default, prevents a click in the text area from opening file dialog. */
38
34
onClick ?: ( event : React . MouseEvent ) => void ;
39
35
/** Additional classes added to the FileUpload container element. */
@@ -80,7 +76,7 @@ export interface FileUploadProps
80
76
/** A callback for when the FileReader API fails */
81
77
onReadFailed ?: ( error : DOMException , fileHandle : File ) => void ;
82
78
/** Optional extra props to customize react-dropzone. */
83
- dropzoneProps ?: DropzoneProps ;
79
+ dropzoneProps ?: DropzoneOptions ;
84
80
/** Clear button was clicked */
85
81
onClearClick ?: React . MouseEventHandler < HTMLButtonElement > ;
86
82
/** Text area text changed */
@@ -107,7 +103,7 @@ export const FileUpload: React.FunctionComponent<FileUploadProps> = ({
107
103
dropzoneProps = { } ,
108
104
...props
109
105
} : FileUploadProps ) => {
110
- const onDropAccepted : DropFileEventHandler = ( acceptedFiles , event ) => {
106
+ const onDropAccepted = ( acceptedFiles : File [ ] , event : DropEvent ) => {
111
107
if ( acceptedFiles . length > 0 ) {
112
108
const fileHandle = acceptedFiles [ 0 ] ;
113
109
if ( event . type === 'drop' ) {
@@ -135,71 +131,68 @@ export const FileUpload: React.FunctionComponent<FileUploadProps> = ({
135
131
dropzoneProps . onDropAccepted && dropzoneProps . onDropAccepted ( acceptedFiles , event ) ;
136
132
} ;
137
133
138
- const onDropRejected : DropFileEventHandler = ( rejectedFiles , event ) => {
134
+ const onDropRejected = ( rejectedFiles : FileRejection [ ] , event : DropEvent ) => {
139
135
if ( rejectedFiles . length > 0 ) {
140
- onChange ( '' , rejectedFiles [ 0 ] . name , event ) ;
136
+ onChange ( '' , rejectedFiles [ 0 ] . file . name , event ) ;
141
137
}
142
138
dropzoneProps . onDropRejected && dropzoneProps . onDropRejected ( rejectedFiles , event ) ;
143
139
} ;
144
140
145
- const fileInputRef = React . useRef < HTMLInputElement > ( ) ;
146
- const setFileValue = ( filename : string ) => {
147
- fileInputRef . current . value = filename ;
148
- } ;
149
-
150
141
const onClearButtonClick = ( event : React . MouseEvent < HTMLButtonElement , MouseEvent > ) => {
151
142
onChange ( '' , '' , event ) ;
152
143
onClearClick ?.( event ) ;
153
144
setFileValue ( null ) ;
154
145
} ;
155
146
156
- return (
157
- < Dropzone multiple = { false } { ...dropzoneProps } onDropAccepted = { onDropAccepted } onDropRejected = { onDropRejected } >
158
- { ( { getRootProps, getInputProps, isDragActive, open } ) => {
159
- const oldInputProps = getInputProps ( ) ;
160
- const inputProps : DropzoneInputProps = {
161
- ...oldInputProps ,
162
- onChange : async ( e : React . ChangeEvent < HTMLInputElement > ) => {
163
- oldInputProps . onChange ?.( e ) ;
164
- const files = await fromEvent ( e . nativeEvent ) ;
165
- if ( files . length === 1 ) {
166
- onFileInputChange ?.( e , files [ 0 ] as File ) ;
167
- }
168
- }
169
- } ;
147
+ const { getRootProps, getInputProps, isDragActive, open, inputRef } = useDropzone ( {
148
+ multiple : false ,
149
+ ...dropzoneProps ,
150
+ onDropAccepted,
151
+ onDropRejected
152
+ } ) ;
153
+
154
+ const setFileValue = ( filename : string ) => {
155
+ inputRef . current . value = filename ;
156
+ } ;
170
157
171
- return (
172
- < FileUploadField
173
- { ...getRootProps ( {
174
- ...props ,
175
- refKey : 'containerRef' ,
176
- onClick : event => event . preventDefault ( )
177
- } ) }
178
- tabIndex = { null } // Omit the unwanted tabIndex from react-dropzone's getRootProps
179
- id = { id }
180
- type = { type }
181
- filename = { filename }
182
- value = { value }
183
- onChange = { onChange }
184
- isDragActive = { isDragActive }
185
- onBrowseButtonClick = { open }
186
- onClearButtonClick = { onClearButtonClick }
187
- onTextAreaClick = { onClick }
188
- onTextChange = { onTextChange }
189
- >
190
- < input
191
- /* hidden, necessary for react-dropzone */
192
- { ...inputProps }
193
- ref = { input => {
194
- fileInputRef . current = input ;
195
- ( inputProps as DropzoneInputPropsWithRef ) . ref ( input ) ;
196
- } }
197
- />
198
- { children }
199
- </ FileUploadField >
200
- ) ;
201
- } }
202
- </ Dropzone >
158
+ const oldInputProps = getInputProps ( ) ;
159
+ const inputProps : DropzoneInputProps = {
160
+ ...oldInputProps ,
161
+ onChange : async ( e : React . ChangeEvent < HTMLInputElement > ) => {
162
+ oldInputProps . onChange ?.( e ) ;
163
+ const files = await fromEvent ( e . nativeEvent ) ;
164
+ if ( files . length === 1 ) {
165
+ onFileInputChange ?.( e , files [ 0 ] as File ) ;
166
+ }
167
+ }
168
+ } ;
169
+
170
+ return (
171
+ < FileUploadField
172
+ { ...getRootProps ( {
173
+ ...props ,
174
+ refKey : 'containerRef' ,
175
+ onClick : event => event . preventDefault ( )
176
+ } ) }
177
+ tabIndex = { null } // Omit the unwanted tabIndex from react-dropzone's getRootProps
178
+ id = { id }
179
+ type = { type }
180
+ filename = { filename }
181
+ value = { value }
182
+ onChange = { onChange }
183
+ isDragActive = { isDragActive }
184
+ onBrowseButtonClick = { open }
185
+ onClearButtonClick = { onClearButtonClick }
186
+ onTextAreaClick = { onClick }
187
+ onTextChange = { onTextChange }
188
+ >
189
+ < input
190
+ /* hidden, necessary for react-dropzone */
191
+ { ...inputProps }
192
+ ref = { inputRef }
193
+ />
194
+ { children }
195
+ </ FileUploadField >
203
196
) ;
204
197
} ;
205
198
FileUpload . displayName = 'FileUpload' ;
0 commit comments