react-dropzone 11.6.0 → 12.0.1

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
@@ -7,10 +7,10 @@ import React, {
7
7
  useImperativeHandle,
8
8
  useMemo,
9
9
  useReducer,
10
- useRef
11
- } from 'react'
12
- import PropTypes from 'prop-types'
13
- import {fromEvent} from 'file-selector'
10
+ useRef,
11
+ } from "react";
12
+ import PropTypes from "prop-types";
13
+ import { fromEvent } from "file-selector";
14
14
  import {
15
15
  allFilesAccepted,
16
16
  composeEventHandlers,
@@ -22,8 +22,8 @@ import {
22
22
  isIeOrEdge,
23
23
  isPropagationStopped,
24
24
  onDocumentDragOver,
25
- TOO_MANY_FILES_REJECTION
26
- } from './utils/index'
25
+ TOO_MANY_FILES_REJECTION,
26
+ } from "./utils/index";
27
27
 
28
28
  /**
29
29
  * Convenience wrapper component for the `useDropzone` hook
@@ -39,16 +39,16 @@ import {
39
39
  * </Dropzone>
40
40
  * ```
41
41
  */
42
- const Dropzone = forwardRef(({children, ...params}, ref) => {
43
- const {open, ...props} = useDropzone(params)
42
+ const Dropzone = forwardRef(({ children, ...params }, ref) => {
43
+ const { open, ...props } = useDropzone(params);
44
44
 
45
- useImperativeHandle(ref, () => ({open}), [open])
45
+ useImperativeHandle(ref, () => ({ open }), [open]);
46
46
 
47
47
  // TODO: Figure out why react-styleguidist cannot create docs if we don't return a jsx element
48
- return <Fragment>{children({...props, open})}</Fragment>
49
- })
48
+ return <Fragment>{children({ ...props, open })}</Fragment>;
49
+ });
50
50
 
51
- Dropzone.displayName = 'Dropzone'
51
+ Dropzone.displayName = "Dropzone";
52
52
 
53
53
  // Add default props for react-docgen
54
54
  const defaultProps = {
@@ -63,10 +63,11 @@ const defaultProps = {
63
63
  noKeyboard: false,
64
64
  noDrag: false,
65
65
  noDragEventsBubbling: false,
66
- validator: null
67
- }
66
+ validator: null,
67
+ useFsAccessApi: true,
68
+ };
68
69
 
69
- Dropzone.defaultProps = defaultProps
70
+ Dropzone.defaultProps = defaultProps;
70
71
 
71
72
  Dropzone.propTypes = {
72
73
  /**
@@ -95,7 +96,10 @@ Dropzone.propTypes = {
95
96
  * Windows. In some cases there might not be a mime type set at all.
96
97
  * See: https://github.com/react-dropzone/react-dropzone/issues/276
97
98
  */
98
- accept: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
99
+ accept: PropTypes.oneOfType([
100
+ PropTypes.string,
101
+ PropTypes.arrayOf(PropTypes.string),
102
+ ]),
99
103
 
100
104
  /**
101
105
  * Allow drag 'n' drop (or selection from the file dialog) of multiple files
@@ -165,6 +169,12 @@ Dropzone.propTypes = {
165
169
  */
166
170
  onFileDialogOpen: PropTypes.func,
167
171
 
172
+ /**
173
+ * Set to true to use the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API
174
+ * to open the file picker instead of using an `<input type="file">` click event.
175
+ */
176
+ useFsAccessApi: PropTypes.bool,
177
+
168
178
  /**
169
179
  * Cb for when the `dragenter` event occurs.
170
180
  *
@@ -241,10 +251,10 @@ Dropzone.propTypes = {
241
251
  * @param {File} file
242
252
  * @returns {FileError|FileError[]}
243
253
  */
244
- validator: PropTypes.func
245
- }
254
+ validator: PropTypes.func,
255
+ };
246
256
 
247
- export default Dropzone
257
+ export default Dropzone;
248
258
 
249
259
  /**
250
260
  * A function that is invoked for the `dragenter`,
@@ -318,8 +328,8 @@ const initialState = {
318
328
  isDragReject: false,
319
329
  draggedFiles: [],
320
330
  acceptedFiles: [],
321
- fileRejections: []
322
- }
331
+ fileRejections: [],
332
+ };
323
333
 
324
334
  /**
325
335
  * A React hook that creates a drag 'n' drop area.
@@ -361,6 +371,8 @@ const initialState = {
361
371
  * @param {boolean} [props.disabled=false] Enable/disable the dropzone
362
372
  * @param {getFilesFromEvent} [props.getFilesFromEvent] Use this to provide a custom file aggregator
363
373
  * @param {Function} [props.onFileDialogCancel] Cb for when closing the file dialog with no selection
374
+ * @param {boolean} [props.useFsAccessApi] Set to true to use the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API
375
+ * to open the file picker instead of using an `<input type="file">` click event.
364
376
  * @param {Function} [props.onFileDialogOpen] Cb for when opening the file dialog
365
377
  * @param {dragCb} [props.onDragEnter] Cb for when the `dragenter` event occurs.
366
378
  * @param {dragCb} [props.onDragLeave] Cb for when the `dragleave` event occurs
@@ -411,29 +423,33 @@ export function useDropzone(options = {}) {
411
423
  onDropRejected,
412
424
  onFileDialogCancel,
413
425
  onFileDialogOpen,
426
+ useFsAccessApi,
414
427
  preventDropOnDocument,
415
428
  noClick,
416
429
  noKeyboard,
417
430
  noDrag,
418
431
  noDragEventsBubbling,
419
- validator
432
+ validator,
420
433
  } = {
421
434
  ...defaultProps,
422
- ...options
423
- }
435
+ ...options,
436
+ };
424
437
 
425
438
  const onFileDialogOpenCb = useMemo(
426
- () => typeof onFileDialogOpen === 'function' ? onFileDialogOpen : noop,
427
- [onFileDialogOpen])
439
+ () => (typeof onFileDialogOpen === "function" ? onFileDialogOpen : noop),
440
+ [onFileDialogOpen]
441
+ );
428
442
  const onFileDialogCancelCb = useMemo(
429
- () => typeof onFileDialogCancel === 'function' ? onFileDialogCancel : noop,
430
- [onFileDialogCancel])
443
+ () =>
444
+ typeof onFileDialogCancel === "function" ? onFileDialogCancel : noop,
445
+ [onFileDialogCancel]
446
+ );
431
447
 
432
- const rootRef = useRef(null)
433
- const inputRef = useRef(null)
448
+ const rootRef = useRef(null);
449
+ const inputRef = useRef(null);
434
450
 
435
- const [state, dispatch] = useReducer(reducer, initialState)
436
- const {isFocused, isFileDialogActive, draggedFiles} = state
451
+ const [state, dispatch] = useReducer(reducer, initialState);
452
+ const { isFocused, isFileDialogActive, draggedFiles } = state;
437
453
 
438
454
  // Update file dialog active state when the window is focused on
439
455
  const onWindowFocus = () => {
@@ -441,339 +457,356 @@ export function useDropzone(options = {}) {
441
457
  if (isFileDialogActive) {
442
458
  setTimeout(() => {
443
459
  if (inputRef.current) {
444
- const {files} = inputRef.current
460
+ const { files } = inputRef.current;
445
461
 
446
462
  if (!files.length) {
447
- dispatch({type: 'closeDialog'})
448
- onFileDialogCancelCb()
463
+ dispatch({ type: "closeDialog" });
464
+ onFileDialogCancelCb();
449
465
  }
450
466
  }
451
- }, 300)
467
+ }, 300);
452
468
  }
453
- }
469
+ };
454
470
  useEffect(() => {
455
- if (canUseFileSystemAccessAPI()) {
456
- return () => {}
471
+ if (useFsAccessApi && canUseFileSystemAccessAPI()) {
472
+ return () => {};
457
473
  }
458
474
 
459
- window.addEventListener('focus', onWindowFocus, false)
475
+ window.addEventListener("focus", onWindowFocus, false);
460
476
  return () => {
461
- window.removeEventListener('focus', onWindowFocus, false)
462
- }
463
- }, [inputRef, isFileDialogActive, onFileDialogCancelCb])
477
+ window.removeEventListener("focus", onWindowFocus, false);
478
+ };
479
+ }, [inputRef, isFileDialogActive, onFileDialogCancelCb, useFsAccessApi]);
464
480
 
465
- const dragTargetsRef = useRef([])
466
- const onDocumentDrop = event => {
481
+ const dragTargetsRef = useRef([]);
482
+ const onDocumentDrop = (event) => {
467
483
  if (rootRef.current && rootRef.current.contains(event.target)) {
468
484
  // If we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
469
- return
485
+ return;
470
486
  }
471
- event.preventDefault()
472
- dragTargetsRef.current = []
473
- }
487
+ event.preventDefault();
488
+ dragTargetsRef.current = [];
489
+ };
474
490
 
475
491
  useEffect(() => {
476
492
  if (preventDropOnDocument) {
477
- document.addEventListener('dragover', onDocumentDragOver, false)
478
- document.addEventListener('drop', onDocumentDrop, false)
493
+ document.addEventListener("dragover", onDocumentDragOver, false);
494
+ document.addEventListener("drop", onDocumentDrop, false);
479
495
  }
480
496
 
481
497
  return () => {
482
498
  if (preventDropOnDocument) {
483
- document.removeEventListener('dragover', onDocumentDragOver)
484
- document.removeEventListener('drop', onDocumentDrop)
499
+ document.removeEventListener("dragover", onDocumentDragOver);
500
+ document.removeEventListener("drop", onDocumentDrop);
485
501
  }
486
- }
487
- }, [rootRef, preventDropOnDocument])
502
+ };
503
+ }, [rootRef, preventDropOnDocument]);
488
504
 
489
505
  const onDragEnterCb = useCallback(
490
- event => {
491
- event.preventDefault()
506
+ (event) => {
507
+ event.preventDefault();
492
508
  // Persist here because we need the event later after getFilesFromEvent() is done
493
- event.persist()
494
- stopPropagation(event)
509
+ event.persist();
510
+ stopPropagation(event);
495
511
 
496
- dragTargetsRef.current = [...dragTargetsRef.current, event.target]
512
+ dragTargetsRef.current = [...dragTargetsRef.current, event.target];
497
513
 
498
514
  if (isEvtWithFiles(event)) {
499
- Promise.resolve(getFilesFromEvent(event)).then(draggedFiles => {
515
+ Promise.resolve(getFilesFromEvent(event)).then((draggedFiles) => {
500
516
  if (isPropagationStopped(event) && !noDragEventsBubbling) {
501
- return
517
+ return;
502
518
  }
503
519
 
504
520
  dispatch({
505
521
  draggedFiles,
506
522
  isDragActive: true,
507
- type: 'setDraggedFiles'
508
- })
523
+ type: "setDraggedFiles",
524
+ });
509
525
 
510
526
  if (onDragEnter) {
511
- onDragEnter(event)
527
+ onDragEnter(event);
512
528
  }
513
- })
529
+ });
514
530
  }
515
531
  },
516
532
  [getFilesFromEvent, onDragEnter, noDragEventsBubbling]
517
- )
533
+ );
518
534
 
519
535
  const onDragOverCb = useCallback(
520
- event => {
521
- event.preventDefault()
522
- event.persist()
523
- stopPropagation(event)
536
+ (event) => {
537
+ event.preventDefault();
538
+ event.persist();
539
+ stopPropagation(event);
524
540
 
525
541
  const hasFiles = isEvtWithFiles(event);
526
542
  if (hasFiles && event.dataTransfer) {
527
543
  try {
528
- event.dataTransfer.dropEffect = 'copy'
544
+ event.dataTransfer.dropEffect = "copy";
529
545
  } catch {} /* eslint-disable-line no-empty */
530
546
  }
531
547
 
532
548
  if (hasFiles && onDragOver) {
533
- onDragOver(event)
549
+ onDragOver(event);
534
550
  }
535
551
 
536
- return false
552
+ return false;
537
553
  },
538
554
  [onDragOver, noDragEventsBubbling]
539
- )
555
+ );
540
556
 
541
557
  const onDragLeaveCb = useCallback(
542
- event => {
543
- event.preventDefault()
544
- event.persist()
545
- stopPropagation(event)
558
+ (event) => {
559
+ event.preventDefault();
560
+ event.persist();
561
+ stopPropagation(event);
546
562
 
547
563
  // Only deactivate once the dropzone and all children have been left
548
564
  const targets = dragTargetsRef.current.filter(
549
- target => rootRef.current && rootRef.current.contains(target)
550
- )
565
+ (target) => rootRef.current && rootRef.current.contains(target)
566
+ );
551
567
  // Make sure to remove a target present multiple times only once
552
568
  // (Firefox may fire dragenter/dragleave multiple times on the same element)
553
- const targetIdx = targets.indexOf(event.target)
569
+ const targetIdx = targets.indexOf(event.target);
554
570
  if (targetIdx !== -1) {
555
- targets.splice(targetIdx, 1)
571
+ targets.splice(targetIdx, 1);
556
572
  }
557
- dragTargetsRef.current = targets
573
+ dragTargetsRef.current = targets;
558
574
  if (targets.length > 0) {
559
- return
575
+ return;
560
576
  }
561
577
 
562
578
  dispatch({
563
579
  isDragActive: false,
564
- type: 'setDraggedFiles',
565
- draggedFiles: []
566
- })
580
+ type: "setDraggedFiles",
581
+ draggedFiles: [],
582
+ });
567
583
 
568
584
  if (isEvtWithFiles(event) && onDragLeave) {
569
- onDragLeave(event)
585
+ onDragLeave(event);
570
586
  }
571
587
  },
572
588
  [rootRef, onDragLeave, noDragEventsBubbling]
573
- )
589
+ );
574
590
 
575
- const setFiles = useCallback((files, event) => {
576
- const acceptedFiles = []
577
- const fileRejections = []
591
+ const setFiles = useCallback(
592
+ (files, event) => {
593
+ const acceptedFiles = [];
594
+ const fileRejections = [];
578
595
 
579
- files.forEach(file => {
580
- const [accepted, acceptError] = fileAccepted(file, accept)
581
- const [sizeMatch, sizeError] = fileMatchSize(file, minSize, maxSize)
582
- const customErrors = validator ? validator(file) : null;
596
+ files.forEach((file) => {
597
+ const [accepted, acceptError] = fileAccepted(file, accept);
598
+ const [sizeMatch, sizeError] = fileMatchSize(file, minSize, maxSize);
599
+ const customErrors = validator ? validator(file) : null;
583
600
 
584
- if (accepted && sizeMatch && !customErrors) {
585
- acceptedFiles.push(file)
586
- } else {
587
- let errors = [acceptError, sizeError];
601
+ if (accepted && sizeMatch && !customErrors) {
602
+ acceptedFiles.push(file);
603
+ } else {
604
+ let errors = [acceptError, sizeError];
588
605
 
589
- if (customErrors) {
590
- errors = errors.concat(customErrors);
591
- }
606
+ if (customErrors) {
607
+ errors = errors.concat(customErrors);
608
+ }
592
609
 
593
- fileRejections.push({file, errors: errors.filter(e => e)})
610
+ fileRejections.push({ file, errors: errors.filter((e) => e) });
611
+ }
612
+ });
613
+
614
+ if (
615
+ (!multiple && acceptedFiles.length > 1) ||
616
+ (multiple && maxFiles >= 1 && acceptedFiles.length > maxFiles)
617
+ ) {
618
+ // Reject everything and empty accepted files
619
+ acceptedFiles.forEach((file) => {
620
+ fileRejections.push({ file, errors: [TOO_MANY_FILES_REJECTION] });
621
+ });
622
+ acceptedFiles.splice(0);
594
623
  }
595
- })
596
-
597
- if ((!multiple && acceptedFiles.length > 1) || (multiple && maxFiles >= 1 && acceptedFiles.length > maxFiles)) {
598
- // Reject everything and empty accepted files
599
- acceptedFiles.forEach(file => {
600
- fileRejections.push({file, errors: [TOO_MANY_FILES_REJECTION]})
601
- })
602
- acceptedFiles.splice(0)
603
- }
604
624
 
605
- dispatch({
606
- acceptedFiles,
607
- fileRejections,
608
- type: 'setFiles'
609
- })
625
+ dispatch({
626
+ acceptedFiles,
627
+ fileRejections,
628
+ type: "setFiles",
629
+ });
610
630
 
611
- if (onDrop) {
612
- onDrop(acceptedFiles, fileRejections, event)
613
- }
631
+ if (onDrop) {
632
+ onDrop(acceptedFiles, fileRejections, event);
633
+ }
614
634
 
615
- if (fileRejections.length > 0 && onDropRejected) {
616
- onDropRejected(fileRejections, event)
617
- }
635
+ if (fileRejections.length > 0 && onDropRejected) {
636
+ onDropRejected(fileRejections, event);
637
+ }
618
638
 
619
- if (acceptedFiles.length > 0 && onDropAccepted) {
620
- onDropAccepted(acceptedFiles, event)
621
- }
622
- }, [
623
- dispatch,
624
- multiple,
625
- accept,
626
- minSize,
627
- maxSize,
628
- maxFiles,
629
- onDrop,
630
- onDropAccepted,
631
- onDropRejected,
632
- validator
633
- ]);
639
+ if (acceptedFiles.length > 0 && onDropAccepted) {
640
+ onDropAccepted(acceptedFiles, event);
641
+ }
642
+ },
643
+ [
644
+ dispatch,
645
+ multiple,
646
+ accept,
647
+ minSize,
648
+ maxSize,
649
+ maxFiles,
650
+ onDrop,
651
+ onDropAccepted,
652
+ onDropRejected,
653
+ validator,
654
+ ]
655
+ );
634
656
 
635
657
  const onDropCb = useCallback(
636
- event => {
637
- event.preventDefault()
658
+ (event) => {
659
+ event.preventDefault();
638
660
  // Persist here because we need the event later after getFilesFromEvent() is done
639
- event.persist()
640
- stopPropagation(event)
661
+ event.persist();
662
+ stopPropagation(event);
641
663
 
642
- dragTargetsRef.current = []
664
+ dragTargetsRef.current = [];
643
665
 
644
666
  if (isEvtWithFiles(event)) {
645
- Promise.resolve(getFilesFromEvent(event)).then(files => {
667
+ Promise.resolve(getFilesFromEvent(event)).then((files) => {
646
668
  if (isPropagationStopped(event) && !noDragEventsBubbling) {
647
- return
669
+ return;
648
670
  }
649
- setFiles(files, event)
650
- })
671
+ setFiles(files, event);
672
+ });
651
673
  }
652
- dispatch({type: 'reset'})
674
+ dispatch({ type: "reset" });
653
675
  },
654
- [
655
- getFilesFromEvent,
656
- setFiles,
657
- noDragEventsBubbling
658
- ]
659
- )
676
+ [getFilesFromEvent, setFiles, noDragEventsBubbling]
677
+ );
660
678
 
661
679
  // Fn for opening the file dialog programmatically
662
680
  const openFileDialog = useCallback(() => {
663
- if (canUseFileSystemAccessAPI()) {
664
- dispatch({type: 'openDialog'})
665
- onFileDialogOpenCb()
681
+ if (useFsAccessApi && canUseFileSystemAccessAPI()) {
682
+ dispatch({ type: "openDialog" });
683
+ onFileDialogOpenCb();
666
684
  // https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker
667
685
  const opts = {
668
686
  multiple,
669
- types: filePickerOptionsTypes(accept)
687
+ types: filePickerOptionsTypes(accept),
670
688
  };
671
- window.showOpenFilePicker(opts)
672
- .then(handles => getFilesFromEvent(handles))
673
- .then(files => setFiles(files, null))
674
- .catch(e => onFileDialogCancelCb(e))
675
- .finally(() => dispatch({type: 'closeDialog'}));
676
- return
689
+ window
690
+ .showOpenFilePicker(opts)
691
+ .then((handles) => getFilesFromEvent(handles))
692
+ .then((files) => setFiles(files, null))
693
+ .catch((e) => onFileDialogCancelCb(e))
694
+ .finally(() => dispatch({ type: "closeDialog" }));
695
+ return;
677
696
  }
678
697
 
679
698
  if (inputRef.current) {
680
- dispatch({type: 'openDialog'})
681
- onFileDialogOpenCb()
682
- inputRef.current.value = null
683
- inputRef.current.click()
699
+ dispatch({ type: "openDialog" });
700
+ onFileDialogOpenCb();
701
+ inputRef.current.value = null;
702
+ inputRef.current.click();
684
703
  }
685
704
  }, [
686
705
  dispatch,
687
706
  onFileDialogOpenCb,
688
707
  onFileDialogCancelCb,
708
+ useFsAccessApi,
689
709
  setFiles,
690
710
  accept,
691
- multiple
692
- ])
711
+ multiple,
712
+ ]);
693
713
 
694
714
  // Cb to open the file dialog when SPACE/ENTER occurs on the dropzone
695
715
  const onKeyDownCb = useCallback(
696
- event => {
716
+ (event) => {
697
717
  // Ignore keyboard events bubbling up the DOM tree
698
718
  if (!rootRef.current || !rootRef.current.isEqualNode(event.target)) {
699
- return
719
+ return;
700
720
  }
701
721
 
702
722
  if (event.keyCode === 32 || event.keyCode === 13) {
703
- event.preventDefault()
704
- openFileDialog()
723
+ event.preventDefault();
724
+ openFileDialog();
705
725
  }
706
726
  },
707
727
  [rootRef, inputRef, openFileDialog]
708
- )
728
+ );
709
729
 
710
730
  // Update focus state for the dropzone
711
731
  const onFocusCb = useCallback(() => {
712
- dispatch({type: 'focus'})
713
- }, [])
732
+ dispatch({ type: "focus" });
733
+ }, []);
714
734
  const onBlurCb = useCallback(() => {
715
- dispatch({type: 'blur'})
716
- }, [])
735
+ dispatch({ type: "blur" });
736
+ }, []);
717
737
 
718
738
  // Cb to open the file dialog when click occurs on the dropzone
719
739
  const onClickCb = useCallback(() => {
720
740
  if (noClick) {
721
- return
741
+ return;
722
742
  }
723
743
 
724
744
  // In IE11/Edge the file-browser dialog is blocking, therefore, use setTimeout()
725
745
  // to ensure React can handle state changes
726
746
  // See: https://github.com/react-dropzone/react-dropzone/issues/450
727
747
  if (isIeOrEdge()) {
728
- setTimeout(openFileDialog, 0)
748
+ setTimeout(openFileDialog, 0);
729
749
  } else {
730
- openFileDialog()
750
+ openFileDialog();
731
751
  }
732
- }, [inputRef, noClick, openFileDialog])
752
+ }, [inputRef, noClick, openFileDialog]);
733
753
 
734
- const composeHandler = fn => {
735
- return disabled ? null : fn
736
- }
754
+ const composeHandler = (fn) => {
755
+ return disabled ? null : fn;
756
+ };
737
757
 
738
- const composeKeyboardHandler = fn => {
739
- return noKeyboard ? null : composeHandler(fn)
740
- }
758
+ const composeKeyboardHandler = (fn) => {
759
+ return noKeyboard ? null : composeHandler(fn);
760
+ };
741
761
 
742
- const composeDragHandler = fn => {
743
- return noDrag ? null : composeHandler(fn)
744
- }
762
+ const composeDragHandler = (fn) => {
763
+ return noDrag ? null : composeHandler(fn);
764
+ };
745
765
 
746
- const stopPropagation = event => {
766
+ const stopPropagation = (event) => {
747
767
  if (noDragEventsBubbling) {
748
- event.stopPropagation()
768
+ event.stopPropagation();
749
769
  }
750
- }
770
+ };
751
771
 
752
772
  const getRootProps = useMemo(
753
- () => ({
754
- refKey = 'ref',
755
- onKeyDown,
756
- onFocus,
757
- onBlur,
758
- onClick,
759
- onDragEnter,
760
- onDragOver,
761
- onDragLeave,
762
- onDrop,
763
- ...rest
764
- } = {}) => ({
765
- onKeyDown: composeKeyboardHandler(composeEventHandlers(onKeyDown, onKeyDownCb)),
766
- onFocus: composeKeyboardHandler(composeEventHandlers(onFocus, onFocusCb)),
767
- onBlur: composeKeyboardHandler(composeEventHandlers(onBlur, onBlurCb)),
768
- onClick: composeHandler(composeEventHandlers(onClick, onClickCb)),
769
- onDragEnter: composeDragHandler(composeEventHandlers(onDragEnter, onDragEnterCb)),
770
- onDragOver: composeDragHandler(composeEventHandlers(onDragOver, onDragOverCb)),
771
- onDragLeave: composeDragHandler(composeEventHandlers(onDragLeave, onDragLeaveCb)),
772
- onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),
773
- [refKey]: rootRef,
774
- ...(!disabled && !noKeyboard ? {tabIndex: 0} : {}),
775
- ...rest
776
- }),
773
+ () =>
774
+ ({
775
+ refKey = "ref",
776
+ role,
777
+ onKeyDown,
778
+ onFocus,
779
+ onBlur,
780
+ onClick,
781
+ onDragEnter,
782
+ onDragOver,
783
+ onDragLeave,
784
+ onDrop,
785
+ ...rest
786
+ } = {}) => ({
787
+ onKeyDown: composeKeyboardHandler(
788
+ composeEventHandlers(onKeyDown, onKeyDownCb)
789
+ ),
790
+ onFocus: composeKeyboardHandler(
791
+ composeEventHandlers(onFocus, onFocusCb)
792
+ ),
793
+ onBlur: composeKeyboardHandler(composeEventHandlers(onBlur, onBlurCb)),
794
+ onClick: composeHandler(composeEventHandlers(onClick, onClickCb)),
795
+ onDragEnter: composeDragHandler(
796
+ composeEventHandlers(onDragEnter, onDragEnterCb)
797
+ ),
798
+ onDragOver: composeDragHandler(
799
+ composeEventHandlers(onDragOver, onDragOverCb)
800
+ ),
801
+ onDragLeave: composeDragHandler(
802
+ composeEventHandlers(onDragLeave, onDragLeaveCb)
803
+ ),
804
+ onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),
805
+ role: typeof role === "string" && role !== "" ? role : "button",
806
+ [refKey]: rootRef,
807
+ ...(!disabled && !noKeyboard ? { tabIndex: 0 } : {}),
808
+ ...rest,
809
+ }),
777
810
  [
778
811
  rootRef,
779
812
  onKeyDownCb,
@@ -786,39 +819,51 @@ export function useDropzone(options = {}) {
786
819
  onDropCb,
787
820
  noKeyboard,
788
821
  noDrag,
789
- disabled
822
+ disabled,
790
823
  ]
791
- )
824
+ );
792
825
 
793
- const onInputElementClick = useCallback(event => {
794
- event.stopPropagation()
795
- }, [])
826
+ const onInputElementClick = useCallback((event) => {
827
+ event.stopPropagation();
828
+ }, []);
796
829
 
797
830
  const getInputProps = useMemo(
798
- () => ({refKey = 'ref', onChange, onClick, ...rest} = {}) => {
799
- const inputProps = {
800
- accept,
801
- multiple,
802
- type: 'file',
803
- style: {display: 'none'},
804
- onChange: composeHandler(composeEventHandlers(onChange, onDropCb)),
805
- onClick: composeHandler(composeEventHandlers(onClick, onInputElementClick)),
806
- autoComplete: 'off',
807
- tabIndex: -1,
808
- [refKey]: inputRef
809
- }
810
-
811
- return {
812
- ...inputProps,
813
- ...rest
814
- }
815
- },
831
+ () =>
832
+ ({ refKey = "ref", onChange, onClick, ...rest } = {}) => {
833
+ const inputProps = {
834
+ accept,
835
+ multiple,
836
+ type: "file",
837
+ style: { display: "none" },
838
+ onChange: composeHandler(composeEventHandlers(onChange, onDropCb)),
839
+ onClick: composeHandler(
840
+ composeEventHandlers(onClick, onInputElementClick)
841
+ ),
842
+ autoComplete: "off",
843
+ tabIndex: -1,
844
+ [refKey]: inputRef,
845
+ };
846
+
847
+ return {
848
+ ...inputProps,
849
+ ...rest,
850
+ };
851
+ },
816
852
  [inputRef, accept, multiple, onDropCb, disabled]
817
- )
818
-
819
- const fileCount = draggedFiles.length
820
- const isDragAccept = fileCount > 0 && allFilesAccepted({files: draggedFiles, accept, minSize, maxSize, multiple, maxFiles})
821
- const isDragReject = fileCount > 0 && !isDragAccept
853
+ );
854
+
855
+ const fileCount = draggedFiles.length;
856
+ const isDragAccept =
857
+ fileCount > 0 &&
858
+ allFilesAccepted({
859
+ files: draggedFiles,
860
+ accept,
861
+ minSize,
862
+ maxSize,
863
+ multiple,
864
+ maxFiles,
865
+ });
866
+ const isDragReject = fileCount > 0 && !isDragAccept;
822
867
 
823
868
  return {
824
869
  ...state,
@@ -829,56 +874,56 @@ export function useDropzone(options = {}) {
829
874
  getInputProps,
830
875
  rootRef,
831
876
  inputRef,
832
- open: composeHandler(openFileDialog)
833
- }
877
+ open: composeHandler(openFileDialog),
878
+ };
834
879
  }
835
880
 
836
881
  function reducer(state, action) {
837
882
  /* istanbul ignore next */
838
883
  switch (action.type) {
839
- case 'focus':
884
+ case "focus":
840
885
  return {
841
886
  ...state,
842
- isFocused: true
843
- }
844
- case 'blur':
887
+ isFocused: true,
888
+ };
889
+ case "blur":
845
890
  return {
846
891
  ...state,
847
- isFocused: false
848
- }
849
- case 'openDialog':
892
+ isFocused: false,
893
+ };
894
+ case "openDialog":
850
895
  return {
851
896
  ...initialState,
852
- isFileDialogActive: true
853
- }
854
- case 'closeDialog':
897
+ isFileDialogActive: true,
898
+ };
899
+ case "closeDialog":
855
900
  return {
856
901
  ...state,
857
- isFileDialogActive: false
858
- }
859
- case 'setDraggedFiles':
902
+ isFileDialogActive: false,
903
+ };
904
+ case "setDraggedFiles":
860
905
  /* eslint no-case-declarations: 0 */
861
- const {isDragActive, draggedFiles} = action
906
+ const { isDragActive, draggedFiles } = action;
862
907
  return {
863
908
  ...state,
864
909
  draggedFiles,
865
- isDragActive
866
- }
867
- case 'setFiles':
910
+ isDragActive,
911
+ };
912
+ case "setFiles":
868
913
  return {
869
914
  ...state,
870
915
  acceptedFiles: action.acceptedFiles,
871
- fileRejections: action.fileRejections
872
- }
873
- case 'reset':
916
+ fileRejections: action.fileRejections,
917
+ };
918
+ case "reset":
874
919
  return {
875
- ...initialState
876
- }
920
+ ...initialState,
921
+ };
877
922
  default:
878
- return state
923
+ return state;
879
924
  }
880
925
  }
881
926
 
882
927
  function noop() {}
883
928
 
884
- export {ErrorCode} from './utils'
929
+ export { ErrorCode } from "./utils";