@instructure/ui-file-drop 8.25.0 → 8.25.1-snapshot-7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,10 +22,10 @@
22
22
  * SOFTWARE.
23
23
  */
24
24
  /** @jsx jsx */
25
- import { Component } from 'react'
25
+ import React, { Component } from 'react'
26
26
  import keycode from 'keycode'
27
-
28
27
  import { FormFieldMessages } from '@instructure/ui-form-field'
28
+ import type { FormMessage } from '@instructure/ui-form-field'
29
29
  import { View } from '@instructure/ui-view'
30
30
  import { testable } from '@instructure/ui-testable'
31
31
  import {
@@ -34,7 +34,6 @@ import {
34
34
  getInteraction,
35
35
  withDeterministicId
36
36
  } from '@instructure/ui-react-utils'
37
- import { isEdge } from '@instructure/ui-utils'
38
37
 
39
38
  import { accepts, getAcceptList } from './utils/accepts'
40
39
  import { getEventFiles } from './utils/getEventFiles'
@@ -46,26 +45,15 @@ import generateComponentTheme from './theme'
46
45
  import { propTypes, allowedProps } from './props'
47
46
  import type { FileDropProps, FileDropState, FileDropStyleProps } from './props'
48
47
 
49
- function keyEventIsClickButton(e: any) {
48
+ function keyEventIsClickButton(e: React.KeyboardEvent) {
50
49
  return e.keyCode === keycode.codes.space || e.keyCode === keycode.codes.enter
51
50
  }
52
51
 
53
- // Used try-catch due to missing document/navigator references in Jenkins
54
- function isBrowserMS() {
55
- let result = false
56
- try {
57
- // @ts-expect-error ts-migrate(2551) FIXME: Property 'documentMode' does not exist on type 'Do... Remove this comment to see the full error message
58
- result = document.documentMode || isEdge
59
- } catch (e) {} // eslint-disable-line no-empty
60
- return result
61
- }
62
-
63
- const IS_MS = isBrowserMS()
64
-
65
52
  /**
66
53
  ---
67
54
  category: components
68
55
  ---
56
+ @tsProps
69
57
  **/
70
58
  @withDeterministicId()
71
59
  @withStyle(generateStyle, generateComponentTheme)
@@ -76,20 +64,7 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
76
64
  static propTypes = propTypes
77
65
  static allowedProps = allowedProps
78
66
  static defaultProps = {
79
- // @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
80
- onClick: function (e: any) {},
81
- // @ts-expect-error ts-migrate(6133) FIXME: 'accepted' is declared but its value is never read... Remove this comment to see the full error message
82
- onDrop: function (accepted: any, rejected: any, e: any) {},
83
- // @ts-expect-error ts-migrate(6133) FIXME: 'accepted' is declared but its value is never read... Remove this comment to see the full error message
84
- onDropAccepted: function (accepted: any, e: any) {},
85
- // @ts-expect-error ts-migrate(6133) FIXME: 'rejected' is declared but its value is never read... Remove this comment to see the full error message
86
- onDropRejected: function (rejected: any, e: any) {},
87
- // @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
88
- onDragEnter: function (e: any) {},
89
- // @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
90
- onDragOver: function (e: any) {},
91
- // @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
92
- onDragLeave: function (e: any) {},
67
+ onClick: function (_e: React.MouseEvent) {},
93
68
  shouldEnablePreview: false,
94
69
  shouldAllowMultiple: false,
95
70
  shouldAllowRepeats: true,
@@ -106,11 +81,17 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
106
81
  this.messagesId = props.deterministicId!('FileDrop-messages')
107
82
  }
108
83
  componentDidMount() {
109
- ;(this.props as any).makeStyles(this.makeStyleProps())
84
+ this.props.makeStyles?.(this.makeStyleProps())
110
85
  }
111
86
 
112
87
  componentDidUpdate() {
113
- ;(this.props as any).makeStyles(this.makeStyleProps())
88
+ this.props.makeStyles?.(this.makeStyleProps())
89
+ }
90
+
91
+ convertToFile(fileLikeItem: DataTransferItem | File) {
92
+ if (fileLikeItem instanceof DataTransferItem)
93
+ return fileLikeItem.getAsFile()
94
+ else return fileLikeItem
114
95
  }
115
96
 
116
97
  makeStyleProps = (): FileDropStyleProps => {
@@ -130,7 +111,7 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
130
111
  }
131
112
 
132
113
  enterCounter = 0
133
- fileInputEl = null
114
+ fileInputEl: HTMLInputElement | null = null
134
115
  defaultId: string | null = null
135
116
  messagesId = ''
136
117
 
@@ -145,9 +126,7 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
145
126
  }
146
127
 
147
128
  get hasMessages() {
148
- return (
149
- (this.props as any).messages && (this.props as any).messages.length > 0
150
- )
129
+ return this.props.messages && this.props.messages.length > 0
151
130
  }
152
131
 
153
132
  get interaction() {
@@ -155,28 +134,32 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
155
134
  }
156
135
 
157
136
  get invalid() {
158
- return (
159
- this.hasMessages &&
160
- (this.props as any).messages.findIndex((message: any) => {
137
+ return (this.hasMessages &&
138
+ this.props.messages!.findIndex((message: FormMessage) => {
161
139
  return message.type === 'error'
162
- }) >= 0
163
- )
140
+ }) >= 0) as boolean
164
141
  }
165
-
166
- getDataTransferItems(e: any, shouldEnablePreview: any) {
167
- let list = Array.from(getEventFiles(e, this.fileInputEl))
142
+ getDataTransferItems(
143
+ e: React.ChangeEvent | React.DragEvent,
144
+ shouldEnablePreview?: boolean
145
+ ): Array<File> {
146
+ let list: Array<File> = []
147
+ Array.from(getEventFiles(e, this.fileInputEl)).forEach((file) => {
148
+ const fileObj = this.convertToFile(file)
149
+ if (fileObj) list.push(fileObj)
150
+ })
168
151
  if (list.length > 1) {
169
- list = (this.props as any).shouldAllowMultiple ? list : [list[0]]
152
+ list = this.props.shouldAllowMultiple ? list : [list[0]]
170
153
  }
171
154
  if (shouldEnablePreview) {
172
- return list.map((file: any) =>
155
+ return list.map((file: File) =>
173
156
  Object.assign(file, { preview: window.URL.createObjectURL(file) })
174
157
  )
175
158
  }
176
159
  return list
177
160
  }
178
161
 
179
- handleDragEnter = (e: any) => {
162
+ handleDragEnter = (e: React.DragEvent) => {
180
163
  e.preventDefault()
181
164
  // Count the dropzone and any children that are entered.
182
165
  this.enterCounter += 1
@@ -184,16 +167,15 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
184
167
  if (this.enterCounter > 1) {
185
168
  return
186
169
  }
187
- // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
188
170
  const allFilesAccepted = this.allFilesAccepted(this.getDataTransferItems(e))
189
171
  this.setState({
190
172
  isDragAccepted: allFilesAccepted,
191
173
  isDragRejected: !allFilesAccepted
192
174
  })
193
- ;(this.props as any).onDragEnter(e)
175
+ this.props.onDragEnter?.(e)
194
176
  }
195
177
 
196
- handleDragOver = (e: any) => {
178
+ handleDragOver = (e: React.DragEvent) => {
197
179
  e.preventDefault()
198
180
  e.stopPropagation()
199
181
  try {
@@ -202,11 +184,11 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
202
184
  } catch (err) {
203
185
  // continue regardless of error
204
186
  }
205
- ;(this.props as any).onDragOver(e)
187
+ this.props.onDragOver?.(e)
206
188
  return false
207
189
  }
208
190
 
209
- handleDragLeave = (e: any) => {
191
+ handleDragLeave = (e: React.DragEvent) => {
210
192
  e.preventDefault()
211
193
  this.enterCounter -= 1
212
194
  // Only deactivate once the dropzone and all children was left
@@ -217,14 +199,19 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
217
199
  isDragAccepted: false,
218
200
  isDragRejected: false
219
201
  })
220
- ;(this.props as any).onDragLeave(e)
202
+ this.props.onDragLeave?.(e)
221
203
  }
222
204
 
223
- parseFiles(fileList: any) {
224
- const accepted: any = []
225
- const rejected: any = []
226
- fileList.forEach((file: any) => {
227
- if (this.fileAccepted(file) && this.fileMatchSize(file)) {
205
+ parseFiles(fileList: Array<DataTransferItem | File>) {
206
+ const accepted: typeof fileList = []
207
+ const rejected: typeof fileList = []
208
+ fileList.forEach((file: DataTransferItem | File) => {
209
+ const fileObj = this.convertToFile(file)
210
+ if (
211
+ fileObj &&
212
+ this.fileAccepted(fileObj) &&
213
+ this.fileMatchSize(fileObj)
214
+ ) {
228
215
  accepted.push(file)
229
216
  } else {
230
217
  rejected.push(file)
@@ -233,21 +220,18 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
233
220
  return [accepted, rejected]
234
221
  }
235
222
 
236
- handleChange = (e: any) => {
223
+ handleChange = (e: React.ChangeEvent | React.DragEvent) => {
237
224
  const { onDrop, onDropAccepted, onDropRejected, shouldEnablePreview } =
238
225
  this.props
239
226
  const fileList = this.getDataTransferItems(e, shouldEnablePreview)
240
227
  const [accepted, rejected] = this.parseFiles(fileList)
241
228
  e.preventDefault()
242
229
  this.enterCounter = 0
243
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefined'.
244
- onDrop(accepted, rejected, e)
245
- if (rejected.length > 0) {
246
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefined'.
230
+ onDrop && onDrop(accepted, rejected, e as React.DragEvent)
231
+ if (rejected.length > 0 && onDropRejected) {
247
232
  onDropRejected(rejected, e)
248
233
  }
249
- if (accepted.length > 0) {
250
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefined'.
234
+ if (accepted.length > 0 && onDropAccepted) {
251
235
  onDropAccepted(accepted, e)
252
236
  }
253
237
  this.setState({
@@ -257,24 +241,22 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
257
241
  })
258
242
  }
259
243
 
260
- fileAccepted = (file: any) => {
261
- return accepts(file, (this.props as any).accept)
244
+ fileAccepted = (file: File) => {
245
+ if (this.props.accept) return accepts(file, this.props.accept)
246
+ else return true
262
247
  }
263
248
 
264
- fileMatchSize(file: any) {
265
- return (
266
- file.size <= (this.props as any).maxSize &&
267
- file.size >= (this.props as any).minSize
268
- )
249
+ fileMatchSize(file: File) {
250
+ return file.size <= this.props.maxSize! && file.size >= this.props.minSize!
269
251
  }
270
252
 
271
- allFilesAccepted(files: any) {
253
+ allFilesAccepted(files: Array<File>) {
272
254
  return files.every(this.fileAccepted)
273
255
  }
274
256
 
275
257
  acceptStr() {
276
258
  const { accept } = this.props
277
- return accept ? getAcceptList(accept).join(',') : null
259
+ return accept ? getAcceptList(accept).join(',') : undefined
278
260
  }
279
261
 
280
262
  renderLabel() {
@@ -286,7 +268,7 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
286
268
  })
287
269
  }
288
270
 
289
- handleRef = (el: any) => {
271
+ handleRef = (el: HTMLInputElement) => {
290
272
  this.fileInputEl = el
291
273
  }
292
274
 
@@ -304,40 +286,27 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
304
286
  })
305
287
  }
306
288
 
307
- handleClick = (e: any) => {
308
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
309
- if (this.fileInputEl.value && (this.props as any).shouldAllowRepeats) {
310
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
311
- this.fileInputEl.value = null
289
+ handleClick = (e: React.MouseEvent) => {
290
+ if (this.fileInputEl!.value && this.props.shouldAllowRepeats) {
291
+ this.fileInputEl!.value = null as unknown as string
312
292
  }
313
293
  // focus the input (because FF won't)
314
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
315
- this.fileInputEl.focus()
316
- ;(this.props as any).onClick(e)
294
+ this.fileInputEl?.focus()
295
+ this.props.onClick!(e)
317
296
  this.setState({
318
297
  isFileBrowserDisplayed: true
319
298
  })
320
299
  }
321
300
 
322
- handleKeyDown = (e: any) => {
301
+ handleKeyDown = (e: React.KeyboardEvent) => {
323
302
  if (this.state.isFocused && keyEventIsClickButton(e)) {
324
- if ((this.props as any).shouldAllowRepeats) {
325
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
326
- this.fileInputEl.value = null
327
- }
328
- // This bit of logic is necessary for MS browsers but causes unwanted warnings in Firefox
329
- // So we need to apply this logic only on MS browsers
330
- /* istanbul ignore if */
331
- if (IS_MS) {
332
- e.stopPropagation()
333
- e.preventDefault()
334
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
335
- this.fileInputEl.click()
303
+ if (this.props.shouldAllowRepeats) {
304
+ this.fileInputEl!.value = null as unknown as string
336
305
  }
337
306
  }
338
307
  }
339
308
 
340
- handleKeyUp = (e: any) => {
309
+ handleKeyUp = (e: React.KeyboardEvent) => {
341
310
  // This is to handle the case where ESC is pressed inside a Dialog so that
342
311
  // closing the file browser dialog doesn't also close the Dialog.
343
312
  if (e.keyCode === keycode.codes.esc && this.state.isFileBrowserDisplayed) {
@@ -361,7 +330,7 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
361
330
  onDropRejected,
362
331
  ...props
363
332
  } = this.props
364
- const id = (this.props as any).id || this.defaultId
333
+ const id = this.props.id || this.defaultId!
365
334
  const focusColor =
366
335
  this.state.isDragRejected || this.invalid ? 'danger' : undefined
367
336
 
@@ -377,7 +346,7 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
377
346
  elementRef={this.handleElementRef}
378
347
  >
379
348
  <label
380
- css={(this.props as any).styles.fileDropLabel}
349
+ css={this.props.styles?.fileDropLabel}
381
350
  htmlFor={id}
382
351
  onDragEnter={this.handleDragEnter}
383
352
  onDragOver={this.handleDragOver}
@@ -392,8 +361,8 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
392
361
  focusColor={focusColor}
393
362
  height={height}
394
363
  >
395
- <span css={(this.props as any).styles.fileDropLabelContent}>
396
- <span css={(this.props as any).styles.fileDropLayout}>
364
+ <span css={this.props.styles?.fileDropLabelContent}>
365
+ <span css={this.props.styles?.fileDropLayout}>
397
366
  <View height={height}>{this.renderLabel()}</View>
398
367
  </span>
399
368
  </span>
@@ -403,24 +372,24 @@ class FileDrop extends Component<FileDropProps, FileDropState> {
403
372
  {...passthroughProps(props)}
404
373
  onClick={this.handleClick}
405
374
  type="file"
406
- css={(this.props as any).styles.fileDropInput}
375
+ css={this.props.styles?.fileDropInput}
407
376
  id={id}
408
377
  ref={this.handleRef}
409
378
  onFocus={this.handleFocus}
410
379
  onBlur={this.handleBlur}
411
380
  onKeyDown={this.handleKeyDown}
412
381
  onKeyUp={this.handleKeyUp}
413
- multiple={(this.props as any).shouldAllowMultiple}
382
+ multiple={this.props.shouldAllowMultiple}
414
383
  accept={this.acceptStr()}
415
384
  onChange={this.handleChange}
416
- aria-describedby={this.hasMessages ? (this as any).messagesId : null}
385
+ aria-describedby={this.hasMessages ? this.messagesId : undefined}
417
386
  disabled={this.functionallyDisabled}
418
387
  />
419
388
  {this.hasMessages ? (
420
389
  <View display="block" margin="small 0 0">
421
390
  <FormFieldMessages
422
- id={(this as any).messagesId}
423
- messages={(this.props as any).messages}
391
+ id={this.messagesId}
392
+ messages={this.props.messages}
424
393
  />
425
394
  </View>
426
395
  ) : null}
@@ -39,161 +39,176 @@ import type {
39
39
  OtherHTMLAttributes
40
40
  } from '@instructure/shared-types'
41
41
  import type { WithDeterministicIdProps } from '@instructure/ui-react-utils'
42
-
43
- type FileDropOwnProps = {
44
- id?: string
45
- renderLabel: ((...args: any[]) => any) | React.ReactNode
46
- accept?: string | string[]
47
- messages?: FormMessage[]
48
- onClick?: (...args: any[]) => any
49
- onDrop?: (...args: any[]) => any
50
- onDropAccepted?: (...args: any[]) => any
51
- onDropRejected?: (...args: any[]) => any
52
- onDragEnter?: (...args: any[]) => any
53
- onDragOver?: (...args: any[]) => any
54
- onDragLeave?: (...args: any[]) => any
55
- shouldEnablePreview?: boolean
56
- shouldAllowMultiple?: boolean
57
- shouldAllowRepeats?: boolean
58
- maxSize?: number
59
- minSize?: number
60
- interaction?: 'enabled' | 'disabled' | 'readonly'
61
- display?: 'block' | 'inline-block'
62
- height?: string | number
63
- width?: string | number
64
- maxWidth?: string | number
65
- minWidth?: string | number
66
- margin?: Spacing
67
- }
68
-
69
- type FileDropState = {
42
+ type RenderLabelProps = {
70
43
  isDragAccepted: boolean
71
44
  isDragRejected: boolean
72
- isFocused: boolean
73
- isFileBrowserDisplayed: boolean
45
+ interaction: boolean
74
46
  }
75
-
76
- type FileDropStyleProps = {
77
- functionallyDisabled: boolean
78
- visuallyDisabled: boolean
79
- dragRejected: boolean
80
- dragAccepted: boolean
81
- }
82
-
83
- type PropKeys = keyof FileDropOwnProps
84
-
85
- type AllowedPropKeys = Readonly<Array<PropKeys>>
86
-
87
- type FileDropProps = FileDropOwnProps &
88
- WithStyleProps<FileDropTheme, FileDropStyle> &
89
- OtherHTMLAttributes<FileDropOwnProps> & WithDeterministicIdProps
90
-
91
- type FileDropStyle = ComponentStyle<
92
- 'fileDropLabel' | 'fileDropInput' | 'fileDropLabelContent' | 'fileDropLayout'
93
- >
94
-
95
- const propTypes: PropValidators<PropKeys> = {
47
+ type FileDropOwnProps = {
96
48
  /**
97
49
  * The id of the input (to link it to its label for a11y)
98
50
  */
99
- id: PropTypes.string,
51
+ id?: string
100
52
  /**
101
53
  * The content of FileDrop; can be a component or React node.
102
54
  * Components receive `isDragAccepted` and `isDragRejected` as props.
103
55
  */
104
- renderLabel: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
56
+ renderLabel: ((props: RenderLabelProps) => React.ReactNode) | React.ReactNode
105
57
  /**
106
58
  * The mime media type/s or file extension/s allowed to be dropped inside
107
59
  */
108
- accept: PropTypes.oneOfType([
109
- PropTypes.string,
110
- PropTypes.arrayOf(PropTypes.string)
111
- ]),
60
+ accept?: string | string[]
112
61
  /**
113
62
  * object with shape: `{
114
63
  * text: PropTypes.node,
115
64
  * type: PropTypes.oneOf(['error', 'hint', 'success', 'screenreader-only'])
116
65
  * }`
117
66
  */
118
- messages: PropTypes.arrayOf(FormPropTypes.message),
67
+ messages?: FormMessage[]
119
68
  /**
120
69
  * Called when clicking on drop area to select files to upload
121
70
  */
122
- onClick: PropTypes.func,
71
+ onClick?: (e: React.MouseEvent) => void
123
72
  /**
124
73
  * Called when dropping files or when file dialog window exits successfully
125
74
  */
126
- onDrop: PropTypes.func,
75
+ onDrop?: (
76
+ accepted: ArrayLike<DataTransferItem | File>,
77
+ rejected: ArrayLike<DataTransferItem | File>,
78
+ e: React.DragEvent
79
+ ) => void
127
80
  /**
128
81
  * Called when dropping allowed files
129
82
  */
130
- onDropAccepted: PropTypes.func,
83
+ onDropAccepted?: (
84
+ accepted: ArrayLike<DataTransferItem | File>,
85
+ e: React.DragEvent | React.ChangeEvent
86
+ ) => void
131
87
  /**
132
88
  * Called when dropping rejected files
133
89
  */
134
- onDropRejected: PropTypes.func,
90
+ onDropRejected?: (
91
+ rejected: ArrayLike<DataTransferItem | File>,
92
+ e: React.DragEvent | React.ChangeEvent
93
+ ) => void
135
94
  /**
136
95
  * Called when dragging files
137
96
  * and passing through FileDrop's content for the first time
138
97
  */
139
- onDragEnter: PropTypes.func,
98
+ onDragEnter?: (e: React.DragEvent) => void
140
99
  /**
141
100
  * Called when dragging files and passing through FileDrop's content
142
101
  */
143
- onDragOver: PropTypes.func,
102
+ onDragOver?: (e: React.DragEvent) => void
144
103
  /**
145
104
  * Called when dragging files and leaving FileDrop's content
146
105
  */
147
- onDragLeave: PropTypes.func,
106
+ onDragLeave?: (e: React.DragEvent) => void
148
107
  /**
149
108
  * Flag to use window.URL.createObjectURL for each dropped file and pass it through file.preview
150
109
  */
151
- shouldEnablePreview: PropTypes.bool,
110
+ shouldEnablePreview?: boolean
152
111
  /**
153
112
  * Flag to allow multiple files to drop at once
154
113
  */
155
- shouldAllowMultiple: PropTypes.bool,
114
+ shouldAllowMultiple?: boolean
156
115
  /**
157
116
  * Flag to allow upload of the same file more than once
158
117
  */
159
- shouldAllowRepeats: PropTypes.bool,
118
+ shouldAllowRepeats?: boolean
160
119
  /**
161
120
  * the maximum file size allowed
162
121
  */
163
- maxSize: PropTypes.number,
122
+ maxSize?: number
164
123
  /**
165
124
  * the minimum file size allowed
166
125
  */
167
- minSize: PropTypes.number,
126
+ minSize?: number
168
127
  /**
169
128
  * Specifies if interaction with the input is enabled, disabled, or readonly.
170
129
  */
171
- interaction: PropTypes.oneOf(['enabled', 'disabled', 'readonly']),
130
+ interaction?: 'enabled' | 'disabled' | 'readonly'
172
131
  /**
173
132
  * Set the CSS `display` property on FileInput's outermost element
174
133
  */
175
- display: PropTypes.oneOf(['block', 'inline-block']),
134
+ display?: 'block' | 'inline-block'
176
135
  /**
177
136
  * Set the CSS `height` property on FileInput's outermost element
178
137
  */
179
- height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
138
+ height?: string | number
180
139
  /**
181
140
  * Set the CSS `width` property on FileInput's outermost element
182
141
  */
183
- width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
142
+ width?: string | number
184
143
  /**
185
144
  * Set the CSS `maxWidth` property on FileInput's outermost element
186
145
  */
187
- maxWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
146
+ maxWidth?: string | number
188
147
  /**
189
148
  * Set the CSS `minWidth` property on FileInput's outermost element
190
149
  */
191
- minWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
150
+ minWidth?: string | number
192
151
  /**
193
152
  * Valid values are 0, none, auto, xxx-small, xx-small, x-small, small,
194
153
  * medium, large, x-large, xx-large. Apply these values via familiar
195
154
  * CSS-like shorthand. For example: margin="small auto large".
196
155
  */
156
+ margin?: Spacing
157
+ }
158
+
159
+ type FileDropState = {
160
+ isDragAccepted: boolean
161
+ isDragRejected: boolean
162
+ isFocused: boolean
163
+ isFileBrowserDisplayed: boolean
164
+ }
165
+
166
+ type FileDropStyleProps = {
167
+ functionallyDisabled: boolean
168
+ visuallyDisabled: boolean
169
+ dragRejected: boolean
170
+ dragAccepted: boolean
171
+ }
172
+
173
+ type PropKeys = keyof FileDropOwnProps
174
+
175
+ type AllowedPropKeys = Readonly<Array<PropKeys>>
176
+
177
+ type FileDropProps = FileDropOwnProps &
178
+ WithStyleProps<FileDropTheme, FileDropStyle> &
179
+ OtherHTMLAttributes<FileDropOwnProps> &
180
+ WithDeterministicIdProps
181
+
182
+ type FileDropStyle = ComponentStyle<
183
+ 'fileDropLabel' | 'fileDropInput' | 'fileDropLabelContent' | 'fileDropLayout'
184
+ >
185
+
186
+ const propTypes: PropValidators<PropKeys> = {
187
+ id: PropTypes.string,
188
+ renderLabel: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
189
+ accept: PropTypes.oneOfType([
190
+ PropTypes.string,
191
+ PropTypes.arrayOf(PropTypes.string)
192
+ ]),
193
+ messages: PropTypes.arrayOf(FormPropTypes.message),
194
+ onClick: PropTypes.func,
195
+ onDrop: PropTypes.func,
196
+ onDropAccepted: PropTypes.func,
197
+ onDropRejected: PropTypes.func,
198
+ onDragEnter: PropTypes.func,
199
+ onDragOver: PropTypes.func,
200
+ onDragLeave: PropTypes.func,
201
+ shouldEnablePreview: PropTypes.bool,
202
+ shouldAllowMultiple: PropTypes.bool,
203
+ shouldAllowRepeats: PropTypes.bool,
204
+ maxSize: PropTypes.number,
205
+ minSize: PropTypes.number,
206
+ interaction: PropTypes.oneOf(['enabled', 'disabled', 'readonly']),
207
+ display: PropTypes.oneOf(['block', 'inline-block']),
208
+ height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
209
+ width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
210
+ maxWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
211
+ minWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
197
212
  margin: ThemeablePropTypes.spacing
198
213
  }
199
214
 
@@ -22,13 +22,13 @@
22
22
  * SOFTWARE.
23
23
  */
24
24
 
25
- function accepts(file: any, acceptProp: any) {
25
+ function accepts(file: File, acceptProp: string | string[]) {
26
26
  if (file && acceptProp && file.type !== 'application/x-moz-file') {
27
27
  const acceptList = getAcceptList(acceptProp)
28
28
  const mimeType = file.type || ''
29
29
  const baseMimeType = mimeType.replace(/\/.*$/, '')
30
30
 
31
- return acceptList.some((type: any) => {
31
+ return acceptList.some((type) => {
32
32
  if (type.charAt(0) === '.') {
33
33
  // type is an extension like .pdf
34
34
  if (!file.name) {
@@ -45,9 +45,9 @@ function accepts(file: any, acceptProp: any) {
45
45
  return true
46
46
  }
47
47
 
48
- function getAcceptList(accept: any) {
48
+ function getAcceptList(accept: string | string[]) {
49
49
  const list = Array.isArray(accept) ? accept : accept.split(',')
50
- return list.map((a: any) => a.trim().replace(/^\w+$/, '.$&'))
50
+ return list.map((a) => a.trim().replace(/^\w+$/, '.$&'))
51
51
  }
52
52
 
53
53
  export default accepts