@@ -8,36 +8,6 @@ import RemoveIcon from "@mui/icons-material/DeleteOutline";
8
8
import FileIcon from "@mui/icons-material/FolderOutlined" ;
9
9
import { css , type Interpolation , type Theme } from "@emotion/react" ;
10
10
11
- const useFileDrop = (
12
- callback : ( file : File ) => void ,
13
- fileTypeRequired ?: string ,
14
- ) : {
15
- onDragOver : ( e : DragEvent < HTMLDivElement > ) => void ;
16
- onDrop : ( e : DragEvent < HTMLDivElement > ) => void ;
17
- } => {
18
- const onDragOver = ( e : DragEvent < HTMLDivElement > ) => {
19
- e . preventDefault ( ) ;
20
- } ;
21
-
22
- const onDrop = ( e : DragEvent < HTMLDivElement > ) => {
23
- e . preventDefault ( ) ;
24
- const file = e . dataTransfer . files [ 0 ] ;
25
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- file can be undefined
26
- if ( ! file ) {
27
- return ;
28
- }
29
- if ( fileTypeRequired && file . type !== fileTypeRequired ) {
30
- return ;
31
- }
32
- callback ( file ) ;
33
- } ;
34
-
35
- return {
36
- onDragOver,
37
- onDrop,
38
- } ;
39
- } ;
40
-
41
11
export interface FileUploadProps {
42
12
isUploading : boolean ;
43
13
onUpload : ( file : File ) => void ;
@@ -46,8 +16,7 @@ export interface FileUploadProps {
46
16
removeLabel : string ;
47
17
title : string ;
48
18
description ?: ReactNode ;
49
- extension ?: string ;
50
- fileTypeRequired ?: string ;
19
+ extensions ?: string [ ] ;
51
20
}
52
21
53
22
export const FileUpload : FC < FileUploadProps > = ( {
@@ -58,10 +27,9 @@ export const FileUpload: FC<FileUploadProps> = ({
58
27
removeLabel,
59
28
title,
60
29
description,
61
- extension,
62
- fileTypeRequired,
30
+ extensions,
63
31
} ) => {
64
- const tarDrop = useFileDrop ( onUpload , fileTypeRequired ) ;
32
+ const fileDrop = useFileDrop ( onUpload , extensions ) ;
65
33
const inputRef = useRef < HTMLInputElement > ( null ) ;
66
34
const clickable = useClickable < HTMLDivElement > (
67
35
( ) => inputRef . current ?. click ( ) ,
@@ -90,9 +58,10 @@ export const FileUpload: FC<FileUploadProps> = ({
90
58
return (
91
59
< >
92
60
< div
61
+ data-testid = "drop-zone"
93
62
css = { [ styles . root , isUploading && styles . disabled ] }
94
63
{ ...clickable }
95
- { ...tarDrop }
64
+ { ...fileDrop }
96
65
>
97
66
< Stack alignItems = "center" spacing = { 1 } >
98
67
{ isUploading ? (
@@ -113,7 +82,7 @@ export const FileUpload: FC<FileUploadProps> = ({
113
82
data-testid = "file-upload"
114
83
ref = { inputRef }
115
84
css = { styles . input }
116
- accept = { extension }
85
+ accept = { extensions ?. map ( ( ext ) => `. ${ ext } ` ) . join ( "," ) }
117
86
onChange = { ( event ) => {
118
87
const file = event . currentTarget . files ?. [ 0 ] ;
119
88
if ( file ) {
@@ -125,6 +94,47 @@ export const FileUpload: FC<FileUploadProps> = ({
125
94
) ;
126
95
} ;
127
96
97
+ const useFileDrop = (
98
+ callback : ( file : File ) => void ,
99
+ extensions ?: string [ ] ,
100
+ ) : {
101
+ onDragOver : ( e : DragEvent < HTMLDivElement > ) => void ;
102
+ onDrop : ( e : DragEvent < HTMLDivElement > ) => void ;
103
+ } => {
104
+ const onDragOver = ( e : DragEvent < HTMLDivElement > ) => {
105
+ e . preventDefault ( ) ;
106
+ } ;
107
+
108
+ const onDrop = ( e : DragEvent < HTMLDivElement > ) => {
109
+ e . preventDefault ( ) ;
110
+ const file = e . dataTransfer . files [ 0 ] as File | undefined ;
111
+
112
+ if ( ! file ) {
113
+ return ;
114
+ }
115
+
116
+ if ( ! extensions ) {
117
+ callback ( file ) ;
118
+ return ;
119
+ }
120
+
121
+ const extension = file . name . split ( "." ) . pop ( ) ;
122
+
123
+ if ( ! extension ) {
124
+ throw new Error ( `File has no extension to compare with ${ extensions } ` ) ;
125
+ }
126
+
127
+ if ( extensions . includes ( extension ) ) {
128
+ callback ( file ) ;
129
+ }
130
+ } ;
131
+
132
+ return {
133
+ onDragOver,
134
+ onDrop,
135
+ } ;
136
+ } ;
137
+
128
138
const styles = {
129
139
root : ( theme ) => css `
130
140
display : flex;
@@ -151,12 +161,16 @@ const styles = {
151
161
152
162
title : {
153
163
fontSize : 16 ,
164
+ lineHeight : "1" ,
154
165
} ,
155
166
156
167
description : ( theme ) => ( {
157
168
color : theme . palette . text . secondary ,
158
169
textAlign : "center" ,
159
170
maxWidth : 400 ,
171
+ fontSize : 14 ,
172
+ lineHeight : "1.5" ,
173
+ marginTop : 4 ,
160
174
} ) ,
161
175
162
176
input : {
0 commit comments