react-dropzone 4.0.0 → 4.1.2

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.
package/src/index.js CHANGED
@@ -2,39 +2,35 @@
2
2
 
3
3
  import React from 'react'
4
4
  import PropTypes from 'prop-types'
5
- import accepts from 'attr-accept'
6
- import getDataTransferItems from './getDataTransferItems'
7
-
8
- const supportMultiple = typeof document !== 'undefined' && document && document.createElement
9
- ? 'multiple' in document.createElement('input')
10
- : true
11
-
12
- function fileAccepted(file, accept) {
13
- // Firefox versions prior to 53 return a bogus MIME type for every file drag, so dragovers with
14
- // that MIME type will always be accepted
15
- return file.type === 'application/x-moz-file' || accepts(file, accept)
16
- }
5
+ import {
6
+ supportMultiple,
7
+ fileAccepted,
8
+ allFilesAccepted,
9
+ fileMatchSize,
10
+ onDocumentDragOver,
11
+ getDataTransferItems
12
+ } from './utils'
13
+ import styles from './utils/styles'
17
14
 
18
15
  class Dropzone extends React.Component {
19
- static onDocumentDragOver(evt) {
20
- // allow the entire document to be a drag target
21
- evt.preventDefault()
22
- }
23
-
24
16
  constructor(props, context) {
25
17
  super(props, context)
18
+ this.composeHandlers = this.composeHandlers.bind(this)
26
19
  this.onClick = this.onClick.bind(this)
27
20
  this.onDocumentDrop = this.onDocumentDrop.bind(this)
28
- this.onDragStart = this.onDragStart.bind(this)
29
21
  this.onDragEnter = this.onDragEnter.bind(this)
30
22
  this.onDragLeave = this.onDragLeave.bind(this)
31
23
  this.onDragOver = this.onDragOver.bind(this)
24
+ this.onDragStart = this.onDragStart.bind(this)
32
25
  this.onDrop = this.onDrop.bind(this)
33
26
  this.onFileDialogCancel = this.onFileDialogCancel.bind(this)
27
+ this.onInputElementClick = this.onInputElementClick.bind(this)
28
+
34
29
  this.setRef = this.setRef.bind(this)
35
30
  this.setRefs = this.setRefs.bind(this)
36
- this.onInputElementClick = this.onInputElementClick.bind(this)
31
+
37
32
  this.isFileDialogActive = false
33
+
38
34
  this.state = {
39
35
  draggedFiles: [],
40
36
  acceptedFiles: [],
@@ -47,7 +43,7 @@ class Dropzone extends React.Component {
47
43
  this.dragTargets = []
48
44
 
49
45
  if (preventDropOnDocument) {
50
- document.addEventListener('dragover', Dropzone.onDocumentDragOver, false)
46
+ document.addEventListener('dragover', onDocumentDragOver, false)
51
47
  document.addEventListener('drop', this.onDocumentDrop, false)
52
48
  }
53
49
  this.fileInputEl.addEventListener('click', this.onInputElementClick, false)
@@ -58,7 +54,7 @@ class Dropzone extends React.Component {
58
54
  componentWillUnmount() {
59
55
  const { preventDropOnDocument } = this.props
60
56
  if (preventDropOnDocument) {
61
- document.removeEventListener('dragover', Dropzone.onDocumentDragOver)
57
+ document.removeEventListener('dragover', onDocumentDragOver)
62
58
  document.removeEventListener('drop', this.onDocumentDrop)
63
59
  }
64
60
  this.fileInputEl.removeEventListener('click', this.onInputElementClick, false)
@@ -66,6 +62,14 @@ class Dropzone extends React.Component {
66
62
  document.body.onfocus = null
67
63
  }
68
64
 
65
+ composeHandlers(handler) {
66
+ if (this.props.disabled) {
67
+ return null
68
+ }
69
+
70
+ return handler
71
+ }
72
+
69
73
  onDocumentDrop(evt) {
70
74
  if (this.node.contains(evt.target)) {
71
75
  // if we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
@@ -159,7 +163,10 @@ class Dropzone extends React.Component {
159
163
  }
160
164
  }
161
165
 
162
- if (fileAccepted(file, accept) && this.fileMatchSize(file)) {
166
+ if (
167
+ fileAccepted(file, accept) &&
168
+ fileMatchSize(file, this.props.maxSize, this.props.minSize)
169
+ ) {
163
170
  acceptedFiles.push(file)
164
171
  } else {
165
172
  rejectedFiles.push(file)
@@ -207,7 +214,7 @@ class Dropzone extends React.Component {
207
214
 
208
215
  // in IE11/Edge the file-browser dialog is blocking, ensure this is behind setTimeout
209
216
  // this is so react can handle state changes in the onClick prop above above
210
- // see: https://github.com/okonet/react-dropzone/issues/450
217
+ // see: https://github.com/react-dropzone/react-dropzone/issues/450
211
218
  setTimeout(this.open.bind(this), 0)
212
219
  }
213
220
  }
@@ -245,15 +252,6 @@ class Dropzone extends React.Component {
245
252
  setRefs(ref) {
246
253
  this.fileInputEl = ref
247
254
  }
248
-
249
- fileMatchSize(file) {
250
- return file.size <= this.props.maxSize && file.size >= this.props.minSize
251
- }
252
-
253
- allFilesAccepted(files) {
254
- return files.every(file => fileAccepted(file, this.props.accept))
255
- }
256
-
257
255
  /**
258
256
  * Open system file upload dialog.
259
257
  *
@@ -267,7 +265,12 @@ class Dropzone extends React.Component {
267
265
 
268
266
  renderChildren = (children, isDragActive, isDragAccept, isDragReject) => {
269
267
  if (typeof children === 'function') {
270
- return children({ ...this.state, isDragActive, isDragAccept, isDragReject })
268
+ return children({
269
+ ...this.state,
270
+ isDragActive,
271
+ isDragAccept,
272
+ isDragReject
273
+ })
271
274
  }
272
275
  return children
273
276
  }
@@ -277,11 +280,13 @@ class Dropzone extends React.Component {
277
280
  accept,
278
281
  acceptClassName,
279
282
  activeClassName,
283
+ children,
284
+ disabled,
285
+ disabledClassName,
280
286
  inputProps,
281
287
  multiple,
282
288
  name,
283
289
  rejectClassName,
284
- children,
285
290
  ...rest
286
291
  } = this.props
287
292
 
@@ -289,6 +294,7 @@ class Dropzone extends React.Component {
289
294
  acceptStyle,
290
295
  activeStyle,
291
296
  className,
297
+ disabledStyle,
292
298
  rejectStyle,
293
299
  style,
294
300
  ...props // eslint-disable-line prefer-const
@@ -297,9 +303,11 @@ class Dropzone extends React.Component {
297
303
  const { isDragActive, draggedFiles } = this.state
298
304
  const filesCount = draggedFiles.length
299
305
  const isMultipleAllowed = multiple || filesCount <= 1
300
- const isDragAccept = filesCount > 0 && this.allFilesAccepted(draggedFiles)
306
+ const isDragAccept = filesCount > 0 && allFilesAccepted(draggedFiles, this.props.accept)
301
307
  const isDragReject = filesCount > 0 && (!isDragAccept || !isMultipleAllowed)
302
308
  className = className || ''
309
+ const noStyles =
310
+ !className && !style && !activeStyle && !acceptStyle && !rejectStyle && !disabledStyle
303
311
 
304
312
  if (isDragActive && activeClassName) {
305
313
  className += ' ' + activeClassName
@@ -310,27 +318,16 @@ class Dropzone extends React.Component {
310
318
  if (isDragReject && rejectClassName) {
311
319
  className += ' ' + rejectClassName
312
320
  }
321
+ if (disabled && disabledClassName) {
322
+ className += ' ' + disabledClassName
323
+ }
313
324
 
314
- if (!className && !style && !activeStyle && !acceptStyle && !rejectStyle) {
315
- style = {
316
- width: 200,
317
- height: 200,
318
- borderWidth: 2,
319
- borderColor: '#666',
320
- borderStyle: 'dashed',
321
- borderRadius: 5
322
- }
323
- activeStyle = {
324
- borderStyle: 'solid',
325
- borderColor: '#6c6',
326
- backgroundColor: '#eee'
327
- }
328
- acceptStyle = activeStyle
329
- rejectStyle = {
330
- borderStyle: 'solid',
331
- borderColor: '#c66',
332
- backgroundColor: '#eee'
333
- }
325
+ if (noStyles) {
326
+ style = styles.default
327
+ activeStyle = styles.active
328
+ acceptStyle = style.active
329
+ rejectStyle = styles.rejected
330
+ disabledStyle = styles.disabled
334
331
  }
335
332
 
336
333
  let appliedStyle = { ...style }
@@ -345,20 +342,29 @@ class Dropzone extends React.Component {
345
342
  ...appliedStyle,
346
343
  ...acceptStyle
347
344
  }
348
- } else if (rejectStyle && isDragReject) {
345
+ }
346
+ if (rejectStyle && isDragReject) {
349
347
  appliedStyle = {
350
348
  ...appliedStyle,
351
349
  ...rejectStyle
352
350
  }
353
351
  }
352
+ if (disabledStyle && disabled) {
353
+ appliedStyle = {
354
+ ...style,
355
+ ...disabledStyle
356
+ }
357
+ }
354
358
 
355
359
  const inputAttributes = {
356
360
  accept,
361
+ disabled,
357
362
  type: 'file',
358
363
  style: { display: 'none' },
359
364
  multiple: supportMultiple && multiple,
360
365
  ref: this.setRefs,
361
- onChange: this.onDrop
366
+ onChange: this.onDrop,
367
+ autoComplete: 'off'
362
368
  }
363
369
 
364
370
  if (name && name.length) {
@@ -385,13 +391,14 @@ class Dropzone extends React.Component {
385
391
  className={className}
386
392
  style={appliedStyle}
387
393
  {...divProps /* expand user provided props first so event handlers are never overridden */}
388
- onClick={this.onClick}
389
- onDragStart={this.onDragStart}
390
- onDragEnter={this.onDragEnter}
391
- onDragOver={this.onDragOver}
392
- onDragLeave={this.onDragLeave}
393
- onDrop={this.onDrop}
394
+ onClick={this.composeHandlers(this.onClick)}
395
+ onDragStart={this.composeHandlers(this.onDragStart)}
396
+ onDragEnter={this.composeHandlers(this.onDragEnter)}
397
+ onDragOver={this.composeHandlers(this.onDragOver)}
398
+ onDragLeave={this.composeHandlers(this.onDragLeave)}
399
+ onDrop={this.composeHandlers(this.onDrop)}
394
400
  ref={this.setRef}
401
+ aria-disabled={disabled}
395
402
  >
396
403
  {this.renderChildren(children, isDragActive, isDragAccept, isDragReject)}
397
404
  <input
@@ -403,13 +410,15 @@ class Dropzone extends React.Component {
403
410
  }
404
411
  }
405
412
 
413
+ export default Dropzone
414
+
406
415
  Dropzone.propTypes = {
407
416
  /**
408
417
  * Allow specific types of files. See https://github.com/okonet/attr-accept for more information.
409
- * Keep in mind that mime type determination is not reliable accross platforms. CSV files,
418
+ * Keep in mind that mime type determination is not reliable across platforms. CSV files,
410
419
  * for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
411
420
  * Windows. In some cases there might not be a mime type set at all.
412
- * See: https://github.com/okonet/react-dropzone/issues/276
421
+ * See: https://github.com/react-dropzone/react-dropzone/issues/276
413
422
  */
414
423
  accept: PropTypes.string,
415
424
 
@@ -423,6 +432,11 @@ Dropzone.propTypes = {
423
432
  */
424
433
  disableClick: PropTypes.bool,
425
434
 
435
+ /**
436
+ * Enable/disable the dropzone entirely
437
+ */
438
+ disabled: PropTypes.bool,
439
+
426
440
  /**
427
441
  * Enable/disable preview generation
428
442
  */
@@ -478,6 +492,11 @@ Dropzone.propTypes = {
478
492
  */
479
493
  rejectClassName: PropTypes.string,
480
494
 
495
+ /**
496
+ * className for disabled state
497
+ */
498
+ disabledClassName: PropTypes.string,
499
+
481
500
  /**
482
501
  * CSS styles to apply
483
502
  */
@@ -498,6 +517,11 @@ Dropzone.propTypes = {
498
517
  */
499
518
  rejectStyle: PropTypes.object,
500
519
 
520
+ /**
521
+ * CSS styles to apply when dropzone is disabled
522
+ */
523
+ disabledStyle: PropTypes.object,
524
+
501
525
  /**
502
526
  * onClick callback
503
527
  * @param {Event} event
@@ -547,11 +571,10 @@ Dropzone.propTypes = {
547
571
 
548
572
  Dropzone.defaultProps = {
549
573
  preventDropOnDocument: true,
574
+ disabled: false,
550
575
  disablePreview: false,
551
576
  disableClick: false,
552
577
  multiple: true,
553
578
  maxSize: Infinity,
554
579
  minSize: 0
555
580
  }
556
-
557
- export default Dropzone
package/src/index.spec.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import React from 'react'
2
2
  import { mount, render } from 'enzyme'
3
3
  import { spy, stub } from 'sinon'
4
+ import { onDocumentDragOver } from './utils'
4
5
 
5
6
  const Dropzone = require(process.env.NODE_ENV === 'production' ? '../dist/index' : './index') // eslint-disable-line import/no-dynamic-require
6
7
  const DummyChildComponent = () => null
@@ -8,6 +9,19 @@ const DummyChildComponent = () => null
8
9
  let files
9
10
  let images
10
11
 
12
+ const rejectColor = 'red'
13
+ const acceptColor = 'green'
14
+
15
+ const rejectStyle = {
16
+ color: rejectColor,
17
+ borderColor: 'black'
18
+ }
19
+
20
+ const acceptStyle = {
21
+ color: acceptColor,
22
+ borderWidth: '5px'
23
+ }
24
+
11
25
  describe('Dropzone', () => {
12
26
  beforeEach(() => {
13
27
  files = [
@@ -85,16 +99,8 @@ describe('Dropzone', () => {
85
99
 
86
100
  it('should render children function', () => {
87
101
  const content = <p>some content</p>
88
- const dropzone = mount(
89
- <Dropzone>
90
- {content}
91
- </Dropzone>
92
- )
93
- const dropzoneWithFunction = mount(
94
- <Dropzone>
95
- {() => content}
96
- </Dropzone>
97
- )
102
+ const dropzone = mount(<Dropzone>{content}</Dropzone>)
103
+ const dropzoneWithFunction = mount(<Dropzone>{() => content}</Dropzone>)
98
104
  expect(dropzoneWithFunction.html()).toEqual(dropzone.html())
99
105
  })
100
106
  })
@@ -126,7 +132,11 @@ describe('Dropzone', () => {
126
132
  }
127
133
 
128
134
  it('installs hooks to prevent stray drops from taking over the browser window', () => {
129
- dropzone = mount(<Dropzone><p>Content</p></Dropzone>)
135
+ dropzone = mount(
136
+ <Dropzone>
137
+ <p>Content</p>
138
+ </Dropzone>
139
+ )
130
140
  expect(dropzone.html()).toMatchSnapshot()
131
141
  expect(document.addEventListener.callCount).toEqual(2)
132
142
  addEventCalls = collectEventListenerCalls(document.addEventListener.args)
@@ -138,7 +148,7 @@ describe('Dropzone', () => {
138
148
 
139
149
  it('terminates drags and drops on elements outside our dropzone', () => {
140
150
  const event = { preventDefault: spy() }
141
- Dropzone.onDocumentDragOver(event)
151
+ onDocumentDragOver(event)
142
152
  expect(event.preventDefault.callCount).toEqual(1)
143
153
  event.preventDefault.reset()
144
154
 
@@ -206,10 +216,25 @@ describe('Dropzone', () => {
206
216
 
207
217
  it('should reset the value of input', () => {
208
218
  const dropzone = mount(<Dropzone />)
209
- expect(dropzone.render().find('input').attr('value')).toBeUndefined()
210
- expect(dropzone.render().find('input').attr('value', 10)).not.toBeUndefined()
219
+ expect(
220
+ dropzone
221
+ .render()
222
+ .find('input')
223
+ .attr('value')
224
+ ).toBeUndefined()
225
+ expect(
226
+ dropzone
227
+ .render()
228
+ .find('input')
229
+ .attr('value', 10)
230
+ ).not.toBeUndefined()
211
231
  dropzone.simulate('click')
212
- expect(dropzone.render().find('input').attr('value')).toBeUndefined()
232
+ expect(
233
+ dropzone
234
+ .render()
235
+ .find('input')
236
+ .attr('value')
237
+ ).toBeUndefined()
213
238
  })
214
239
 
215
240
  it('should trigger click even on the input', done => {
@@ -320,9 +345,7 @@ describe('Dropzone', () => {
320
345
  )
321
346
 
322
347
  // And using then we'll call the onDragOver with the proxy instead of event
323
- const dragOverSpy = stub(
324
- component.instance(),
325
- 'onDragOver',
348
+ const dragOverSpy = stub(component.instance(), 'onDragOver').callsFake(
326
349
  component.instance().onDragOver(eventProxy)
327
350
  )
328
351
 
@@ -339,11 +362,7 @@ describe('Dropzone', () => {
339
362
  })
340
363
 
341
364
  it('should set proper dragActive state on dragEnter', () => {
342
- const dropzone = mount(
343
- <Dropzone>
344
- {props => <DummyChildComponent {...props} />}
345
- </Dropzone>
346
- )
365
+ const dropzone = mount(<Dropzone>{props => <DummyChildComponent {...props} />}</Dropzone>)
347
366
  const child = dropzone.find(DummyChildComponent)
348
367
  dropzone.simulate('dragEnter', { dataTransfer: { files } })
349
368
  expect(child).toHaveProp('isDragActive', true)
@@ -353,12 +372,12 @@ describe('Dropzone', () => {
353
372
 
354
373
  it('should set proper dragReject state on dragEnter', () => {
355
374
  const dropzone = mount(
356
- <Dropzone accept="image/*">
357
- {props => <DummyChildComponent {...props} />}
358
- </Dropzone>
375
+ <Dropzone accept="image/*">{props => <DummyChildComponent {...props} />}</Dropzone>
359
376
  )
360
377
  const child = dropzone.find(DummyChildComponent)
361
- dropzone.simulate('dragEnter', { dataTransfer: { files: files.concat(images) } })
378
+ dropzone.simulate('dragEnter', {
379
+ dataTransfer: { files: files.concat(images) }
380
+ })
362
381
  expect(child).toHaveProp('isDragActive', true)
363
382
  expect(child).toHaveProp('isDragAccept', false)
364
383
  expect(child).toHaveProp('isDragReject', true)
@@ -390,12 +409,62 @@ describe('Dropzone', () => {
390
409
  expect(child).toHaveProp('isDragReject', true)
391
410
  })
392
411
 
393
- it('should set proper dragActive state if accept prop changes mid-drag', () => {
412
+ it('should apply acceptStyle if multiple is false and single file', () => {
394
413
  const dropzone = mount(
395
- <Dropzone accept="image/*">
414
+ <Dropzone
415
+ accept="image/*"
416
+ multiple={false}
417
+ acceptStyle={acceptStyle}
418
+ rejectStyle={rejectStyle}
419
+ >
420
+ {props => <DummyChildComponent {...props} />}
421
+ </Dropzone>
422
+ )
423
+ dropzone.simulate('dragEnter', { dataTransfer: { files: [images[0]] } })
424
+ const mainDiv = dropzone.find('div').at(0)
425
+ expect(mainDiv).toHaveProp('style', acceptStyle)
426
+ })
427
+
428
+ it('should apply rejectStyle if multiple is false and single bad file type', () => {
429
+ const dropzone = mount(
430
+ <Dropzone
431
+ accept="image/*"
432
+ multiple={false}
433
+ acceptStyle={acceptStyle}
434
+ rejectStyle={rejectStyle}
435
+ >
436
+ {props => <DummyChildComponent {...props} />}
437
+ </Dropzone>
438
+ )
439
+ dropzone.simulate('dragEnter', { dataTransfer: { files: [files[0]] } })
440
+ const mainDiv = dropzone.find('div').at(0)
441
+ expect(mainDiv).toHaveProp('style', rejectStyle)
442
+ })
443
+
444
+ it('should apply acceptStyle + rejectStyle if multiple is false and multiple good file types', () => {
445
+ const dropzone = mount(
446
+ <Dropzone
447
+ accept="image/*"
448
+ multiple={false}
449
+ acceptStyle={acceptStyle}
450
+ rejectStyle={rejectStyle}
451
+ >
396
452
  {props => <DummyChildComponent {...props} />}
397
453
  </Dropzone>
398
454
  )
455
+ dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
456
+ const mainDiv = dropzone.find('div').at(0)
457
+ const expectedStyle = {
458
+ ...acceptStyle,
459
+ ...rejectStyle
460
+ }
461
+ expect(mainDiv).toHaveProp('style', expectedStyle)
462
+ })
463
+
464
+ it('should set proper dragActive state if accept prop changes mid-drag', () => {
465
+ const dropzone = mount(
466
+ <Dropzone accept="image/*">{props => <DummyChildComponent {...props} />}</Dropzone>
467
+ )
399
468
  const child = dropzone.find(DummyChildComponent)
400
469
  dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
401
470
  expect(child).toHaveProp('isDragActive', true)
@@ -507,7 +576,9 @@ describe('Dropzone', () => {
507
576
 
508
577
  it('should add invalid files to rejected when multiple is false', () => {
509
578
  const dropzone = mount(<Dropzone accept="image/*" onDrop={dropSpy} multiple={false} />)
510
- dropzone.simulate('drop', { dataTransfer: { files: images.concat(files) } })
579
+ dropzone.simulate('drop', {
580
+ dataTransfer: { files: images.concat(files) }
581
+ })
511
582
  const rejected = dropSpy.firstCall.args[1]
512
583
  expect(rejected.length).toEqual(2)
513
584
  })
@@ -551,7 +622,9 @@ describe('Dropzone', () => {
551
622
  dropzone.simulate('drop', { dataTransfer: { files: images } })
552
623
  expect(dropSpy.callCount).toEqual(2)
553
624
  expect(dropSpy.lastCall.args[0]).toEqual([...images], [])
554
- dropzone.simulate('drop', { dataTransfer: { files: files.concat(images) } })
625
+ dropzone.simulate('drop', {
626
+ dataTransfer: { files: files.concat(images) }
627
+ })
555
628
  expect(dropSpy.callCount).toEqual(3)
556
629
  expect(dropSpy.lastCall.args[0]).toEqual([...images], [...files])
557
630
  })
@@ -570,7 +643,9 @@ describe('Dropzone', () => {
570
643
  dropzone.simulate('drop', { dataTransfer: { files: images } })
571
644
  expect(dropAcceptedSpy.callCount).toEqual(1)
572
645
  expect(dropAcceptedSpy.lastCall.args[0]).toEqual([...images])
573
- dropzone.simulate('drop', { dataTransfer: { files: files.concat(images) } })
646
+ dropzone.simulate('drop', {
647
+ dataTransfer: { files: files.concat(images) }
648
+ })
574
649
  expect(dropAcceptedSpy.callCount).toEqual(2)
575
650
  expect(dropAcceptedSpy.lastCall.args[0]).toEqual([...images])
576
651
  })
@@ -589,7 +664,9 @@ describe('Dropzone', () => {
589
664
  expect(dropRejectedSpy.lastCall.args[0]).toEqual([...files])
590
665
  dropzone.simulate('drop', { dataTransfer: { files: images } })
591
666
  expect(dropRejectedSpy.callCount).toEqual(1)
592
- dropzone.simulate('drop', { dataTransfer: { files: files.concat(images) } })
667
+ dropzone.simulate('drop', {
668
+ dataTransfer: { files: files.concat(images) }
669
+ })
593
670
  expect(dropRejectedSpy.callCount).toEqual(2)
594
671
  expect(dropRejectedSpy.lastCall.args[0]).toEqual([...files])
595
672
  })
@@ -665,7 +742,9 @@ describe('Dropzone', () => {
665
742
  onDropRejected={dropRejectedSpy}
666
743
  />
667
744
  )
668
- dropzone.simulate('drop', { dataTransfer: { files: files.concat(images) } })
745
+ dropzone.simulate('drop', {
746
+ dataTransfer: { files: files.concat(images) }
747
+ })
669
748
  expect(dropSpy.callCount).toEqual(1)
670
749
  expect(dropSpy.firstCall.args[0]).toHaveLength(3)
671
750
  expect(dropSpy.firstCall.args[1]).toHaveLength(0)
@@ -755,7 +834,9 @@ describe('Dropzone', () => {
755
834
  onDropRejected={dropRejectedSpy}
756
835
  />
757
836
  )
758
- dropzone.simulate('drop', { dataTransfer: { files: files.concat(images) } })
837
+ dropzone.simulate('drop', {
838
+ dataTransfer: { files: files.concat(images) }
839
+ })
759
840
  expect(dropSpy.callCount).toEqual(1)
760
841
  expect(dropSpy.firstCall.args[0]).toHaveLength(3)
761
842
  expect(dropSpy.firstCall.args[1]).toHaveLength(0)
@@ -897,7 +978,9 @@ describe('Dropzone', () => {
897
978
  })
898
979
 
899
980
  it('does dragEnter on both dropzones', () => {
900
- innerDropzone.simulate('dragEnter', { dataTransfer: { files: images } })
981
+ innerDropzone.simulate('dragEnter', {
982
+ dataTransfer: { files: images }
983
+ })
901
984
  expect(innerDropzone).toHaveProp('isDragActive', true)
902
985
  expect(innerDropzone).toHaveProp('isDragReject', false)
903
986
  expect(innerDropzone.find(InnerDragAccepted).exists()).toEqual(true)
@@ -905,7 +988,9 @@ describe('Dropzone', () => {
905
988
  })
906
989
 
907
990
  it('drops on the child dropzone', () => {
908
- innerDropzone.simulate('drop', { dataTransfer: { files: files.concat(images) } })
991
+ innerDropzone.simulate('drop', {
992
+ dataTransfer: { files: files.concat(images) }
993
+ })
909
994
  })
910
995
 
911
996
  it('accepts the drop on the inner dropzone', () => {
@@ -941,5 +1026,29 @@ describe('Dropzone', () => {
941
1026
  const fn = () => dropzone.simulate('drop', { dataTransfer: { files: [] } })
942
1027
  expect(fn).not.toThrow()
943
1028
  })
1029
+
1030
+ it('does not allow actions when disabled props is true', done => {
1031
+ const dropzone = mount(<Dropzone disabled />)
1032
+
1033
+ spy(dropzone.instance(), 'open')
1034
+ dropzone.simulate('click')
1035
+ setTimeout(() => {
1036
+ expect(dropzone.instance().open.callCount).toEqual(0)
1037
+ done()
1038
+ }, 0)
1039
+ })
1040
+
1041
+ it('when toggle disabled props, Dropzone works as expected', done => {
1042
+ const dropzone = mount(<Dropzone disabled />)
1043
+ spy(dropzone.instance(), 'open')
1044
+
1045
+ dropzone.setProps({ disabled: false })
1046
+
1047
+ dropzone.simulate('click')
1048
+ setTimeout(() => {
1049
+ expect(dropzone.instance().open.callCount).toEqual(1)
1050
+ done()
1051
+ }, 0)
1052
+ })
944
1053
  })
945
1054
  })
@@ -0,0 +1,43 @@
1
+ import accepts from 'attr-accept'
2
+
3
+ export const supportMultiple =
4
+ typeof document !== 'undefined' && document && document.createElement
5
+ ? 'multiple' in document.createElement('input')
6
+ : true
7
+
8
+ export function getDataTransferItems(event) {
9
+ let dataTransferItemsList = []
10
+ if (event.dataTransfer) {
11
+ const dt = event.dataTransfer
12
+ if (dt.files && dt.files.length) {
13
+ dataTransferItemsList = dt.files
14
+ } else if (dt.items && dt.items.length) {
15
+ // During the drag even the dataTransfer.files is null
16
+ // but Chrome implements some drag store, which is accesible via dataTransfer.items
17
+ dataTransferItemsList = dt.items
18
+ }
19
+ } else if (event.target && event.target.files) {
20
+ dataTransferItemsList = event.target.files
21
+ }
22
+ // Convert from DataTransferItemsList to the native Array
23
+ return Array.prototype.slice.call(dataTransferItemsList)
24
+ }
25
+
26
+ // Firefox versions prior to 53 return a bogus MIME type for every file drag, so dragovers with
27
+ // that MIME type will always be accepted
28
+ export function fileAccepted(file, accept) {
29
+ return file.type === 'application/x-moz-file' || accepts(file, accept)
30
+ }
31
+
32
+ export function fileMatchSize(file, maxSize, minSize) {
33
+ return file.size <= maxSize && file.size >= minSize
34
+ }
35
+
36
+ export function allFilesAccepted(files, accept) {
37
+ return files.every(file => fileAccepted(file, accept))
38
+ }
39
+
40
+ // allow the entire document to be a drag target
41
+ export function onDocumentDragOver(evt) {
42
+ evt.preventDefault()
43
+ }