react-dropzone 11.7.0 → 12.0.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
@@ -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,341 +457,366 @@ 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 (
472
+ window.isSecureContext &&
473
+ useFsAccessApi &&
474
+ canUseFileSystemAccessAPI()
475
+ ) {
476
+ return () => {};
457
477
  }
458
478
 
459
- window.addEventListener('focus', onWindowFocus, false)
479
+ window.addEventListener("focus", onWindowFocus, false);
460
480
  return () => {
461
- window.removeEventListener('focus', onWindowFocus, false)
462
- }
463
- }, [inputRef, isFileDialogActive, onFileDialogCancelCb])
481
+ window.removeEventListener("focus", onWindowFocus, false);
482
+ };
483
+ }, [inputRef, isFileDialogActive, onFileDialogCancelCb, useFsAccessApi]);
464
484
 
465
- const dragTargetsRef = useRef([])
466
- const onDocumentDrop = event => {
485
+ const dragTargetsRef = useRef([]);
486
+ const onDocumentDrop = (event) => {
467
487
  if (rootRef.current && rootRef.current.contains(event.target)) {
468
488
  // If we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
469
- return
489
+ return;
470
490
  }
471
- event.preventDefault()
472
- dragTargetsRef.current = []
473
- }
491
+ event.preventDefault();
492
+ dragTargetsRef.current = [];
493
+ };
474
494
 
475
495
  useEffect(() => {
476
496
  if (preventDropOnDocument) {
477
- document.addEventListener('dragover', onDocumentDragOver, false)
478
- document.addEventListener('drop', onDocumentDrop, false)
497
+ document.addEventListener("dragover", onDocumentDragOver, false);
498
+ document.addEventListener("drop", onDocumentDrop, false);
479
499
  }
480
500
 
481
501
  return () => {
482
502
  if (preventDropOnDocument) {
483
- document.removeEventListener('dragover', onDocumentDragOver)
484
- document.removeEventListener('drop', onDocumentDrop)
503
+ document.removeEventListener("dragover", onDocumentDragOver);
504
+ document.removeEventListener("drop", onDocumentDrop);
485
505
  }
486
- }
487
- }, [rootRef, preventDropOnDocument])
506
+ };
507
+ }, [rootRef, preventDropOnDocument]);
488
508
 
489
509
  const onDragEnterCb = useCallback(
490
- event => {
491
- event.preventDefault()
510
+ (event) => {
511
+ event.preventDefault();
492
512
  // Persist here because we need the event later after getFilesFromEvent() is done
493
- event.persist()
494
- stopPropagation(event)
513
+ event.persist();
514
+ stopPropagation(event);
495
515
 
496
- dragTargetsRef.current = [...dragTargetsRef.current, event.target]
516
+ dragTargetsRef.current = [...dragTargetsRef.current, event.target];
497
517
 
498
518
  if (isEvtWithFiles(event)) {
499
- Promise.resolve(getFilesFromEvent(event)).then(draggedFiles => {
519
+ Promise.resolve(getFilesFromEvent(event)).then((draggedFiles) => {
500
520
  if (isPropagationStopped(event) && !noDragEventsBubbling) {
501
- return
521
+ return;
502
522
  }
503
523
 
504
524
  dispatch({
505
525
  draggedFiles,
506
526
  isDragActive: true,
507
- type: 'setDraggedFiles'
508
- })
527
+ type: "setDraggedFiles",
528
+ });
509
529
 
510
530
  if (onDragEnter) {
511
- onDragEnter(event)
531
+ onDragEnter(event);
512
532
  }
513
- })
533
+ });
514
534
  }
515
535
  },
516
536
  [getFilesFromEvent, onDragEnter, noDragEventsBubbling]
517
- )
537
+ );
518
538
 
519
539
  const onDragOverCb = useCallback(
520
- event => {
521
- event.preventDefault()
522
- event.persist()
523
- stopPropagation(event)
540
+ (event) => {
541
+ event.preventDefault();
542
+ event.persist();
543
+ stopPropagation(event);
524
544
 
525
545
  const hasFiles = isEvtWithFiles(event);
526
546
  if (hasFiles && event.dataTransfer) {
527
547
  try {
528
- event.dataTransfer.dropEffect = 'copy'
548
+ event.dataTransfer.dropEffect = "copy";
529
549
  } catch {} /* eslint-disable-line no-empty */
530
550
  }
531
551
 
532
552
  if (hasFiles && onDragOver) {
533
- onDragOver(event)
553
+ onDragOver(event);
534
554
  }
535
555
 
536
- return false
556
+ return false;
537
557
  },
538
558
  [onDragOver, noDragEventsBubbling]
539
- )
559
+ );
540
560
 
541
561
  const onDragLeaveCb = useCallback(
542
- event => {
543
- event.preventDefault()
544
- event.persist()
545
- stopPropagation(event)
562
+ (event) => {
563
+ event.preventDefault();
564
+ event.persist();
565
+ stopPropagation(event);
546
566
 
547
567
  // Only deactivate once the dropzone and all children have been left
548
568
  const targets = dragTargetsRef.current.filter(
549
- target => rootRef.current && rootRef.current.contains(target)
550
- )
569
+ (target) => rootRef.current && rootRef.current.contains(target)
570
+ );
551
571
  // Make sure to remove a target present multiple times only once
552
572
  // (Firefox may fire dragenter/dragleave multiple times on the same element)
553
- const targetIdx = targets.indexOf(event.target)
573
+ const targetIdx = targets.indexOf(event.target);
554
574
  if (targetIdx !== -1) {
555
- targets.splice(targetIdx, 1)
575
+ targets.splice(targetIdx, 1);
556
576
  }
557
- dragTargetsRef.current = targets
577
+ dragTargetsRef.current = targets;
558
578
  if (targets.length > 0) {
559
- return
579
+ return;
560
580
  }
561
581
 
562
582
  dispatch({
563
583
  isDragActive: false,
564
- type: 'setDraggedFiles',
565
- draggedFiles: []
566
- })
584
+ type: "setDraggedFiles",
585
+ draggedFiles: [],
586
+ });
567
587
 
568
588
  if (isEvtWithFiles(event) && onDragLeave) {
569
- onDragLeave(event)
589
+ onDragLeave(event);
570
590
  }
571
591
  },
572
592
  [rootRef, onDragLeave, noDragEventsBubbling]
573
- )
593
+ );
574
594
 
575
- const setFiles = useCallback((files, event) => {
576
- const acceptedFiles = []
577
- const fileRejections = []
595
+ const setFiles = useCallback(
596
+ (files, event) => {
597
+ const acceptedFiles = [];
598
+ const fileRejections = [];
578
599
 
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;
600
+ files.forEach((file) => {
601
+ const [accepted, acceptError] = fileAccepted(file, accept);
602
+ const [sizeMatch, sizeError] = fileMatchSize(file, minSize, maxSize);
603
+ const customErrors = validator ? validator(file) : null;
583
604
 
584
- if (accepted && sizeMatch && !customErrors) {
585
- acceptedFiles.push(file)
586
- } else {
587
- let errors = [acceptError, sizeError];
605
+ if (accepted && sizeMatch && !customErrors) {
606
+ acceptedFiles.push(file);
607
+ } else {
608
+ let errors = [acceptError, sizeError];
588
609
 
589
- if (customErrors) {
590
- errors = errors.concat(customErrors);
591
- }
610
+ if (customErrors) {
611
+ errors = errors.concat(customErrors);
612
+ }
592
613
 
593
- fileRejections.push({file, errors: errors.filter(e => e)})
614
+ fileRejections.push({ file, errors: errors.filter((e) => e) });
615
+ }
616
+ });
617
+
618
+ if (
619
+ (!multiple && acceptedFiles.length > 1) ||
620
+ (multiple && maxFiles >= 1 && acceptedFiles.length > maxFiles)
621
+ ) {
622
+ // Reject everything and empty accepted files
623
+ acceptedFiles.forEach((file) => {
624
+ fileRejections.push({ file, errors: [TOO_MANY_FILES_REJECTION] });
625
+ });
626
+ acceptedFiles.splice(0);
594
627
  }
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
628
 
605
- dispatch({
606
- acceptedFiles,
607
- fileRejections,
608
- type: 'setFiles'
609
- })
629
+ dispatch({
630
+ acceptedFiles,
631
+ fileRejections,
632
+ type: "setFiles",
633
+ });
610
634
 
611
- if (onDrop) {
612
- onDrop(acceptedFiles, fileRejections, event)
613
- }
635
+ if (onDrop) {
636
+ onDrop(acceptedFiles, fileRejections, event);
637
+ }
614
638
 
615
- if (fileRejections.length > 0 && onDropRejected) {
616
- onDropRejected(fileRejections, event)
617
- }
639
+ if (fileRejections.length > 0 && onDropRejected) {
640
+ onDropRejected(fileRejections, event);
641
+ }
618
642
 
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
- ]);
643
+ if (acceptedFiles.length > 0 && onDropAccepted) {
644
+ onDropAccepted(acceptedFiles, event);
645
+ }
646
+ },
647
+ [
648
+ dispatch,
649
+ multiple,
650
+ accept,
651
+ minSize,
652
+ maxSize,
653
+ maxFiles,
654
+ onDrop,
655
+ onDropAccepted,
656
+ onDropRejected,
657
+ validator,
658
+ ]
659
+ );
634
660
 
635
661
  const onDropCb = useCallback(
636
- event => {
637
- event.preventDefault()
662
+ (event) => {
663
+ event.preventDefault();
638
664
  // Persist here because we need the event later after getFilesFromEvent() is done
639
- event.persist()
640
- stopPropagation(event)
665
+ event.persist();
666
+ stopPropagation(event);
641
667
 
642
- dragTargetsRef.current = []
668
+ dragTargetsRef.current = [];
643
669
 
644
670
  if (isEvtWithFiles(event)) {
645
- Promise.resolve(getFilesFromEvent(event)).then(files => {
671
+ Promise.resolve(getFilesFromEvent(event)).then((files) => {
646
672
  if (isPropagationStopped(event) && !noDragEventsBubbling) {
647
- return
673
+ return;
648
674
  }
649
- setFiles(files, event)
650
- })
675
+ setFiles(files, event);
676
+ });
651
677
  }
652
- dispatch({type: 'reset'})
678
+ dispatch({ type: "reset" });
653
679
  },
654
- [
655
- getFilesFromEvent,
656
- setFiles,
657
- noDragEventsBubbling
658
- ]
659
- )
680
+ [getFilesFromEvent, setFiles, noDragEventsBubbling]
681
+ );
660
682
 
661
683
  // Fn for opening the file dialog programmatically
662
684
  const openFileDialog = useCallback(() => {
663
- if (canUseFileSystemAccessAPI()) {
664
- dispatch({type: 'openDialog'})
665
- onFileDialogOpenCb()
685
+ // No point to use FS access APIs if context is not secure
686
+ // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection
687
+ if (
688
+ window.isSecureContext &&
689
+ useFsAccessApi &&
690
+ canUseFileSystemAccessAPI()
691
+ ) {
692
+ dispatch({ type: "openDialog" });
693
+ onFileDialogOpenCb();
666
694
  // https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker
667
695
  const opts = {
668
696
  multiple,
669
- types: filePickerOptionsTypes(accept)
697
+ types: filePickerOptionsTypes(accept),
670
698
  };
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
699
+ window
700
+ .showOpenFilePicker(opts)
701
+ .then((handles) => getFilesFromEvent(handles))
702
+ .then((files) => setFiles(files, null))
703
+ .catch((e) => onFileDialogCancelCb(e))
704
+ .finally(() => dispatch({ type: "closeDialog" }));
705
+ return;
677
706
  }
678
707
 
679
708
  if (inputRef.current) {
680
- dispatch({type: 'openDialog'})
681
- onFileDialogOpenCb()
682
- inputRef.current.value = null
683
- inputRef.current.click()
709
+ dispatch({ type: "openDialog" });
710
+ onFileDialogOpenCb();
711
+ inputRef.current.value = null;
712
+ inputRef.current.click();
684
713
  }
685
714
  }, [
686
715
  dispatch,
687
716
  onFileDialogOpenCb,
688
717
  onFileDialogCancelCb,
718
+ useFsAccessApi,
689
719
  setFiles,
690
720
  accept,
691
- multiple
692
- ])
721
+ multiple,
722
+ ]);
693
723
 
694
724
  // Cb to open the file dialog when SPACE/ENTER occurs on the dropzone
695
725
  const onKeyDownCb = useCallback(
696
- event => {
726
+ (event) => {
697
727
  // Ignore keyboard events bubbling up the DOM tree
698
728
  if (!rootRef.current || !rootRef.current.isEqualNode(event.target)) {
699
- return
729
+ return;
700
730
  }
701
731
 
702
732
  if (event.keyCode === 32 || event.keyCode === 13) {
703
- event.preventDefault()
704
- openFileDialog()
733
+ event.preventDefault();
734
+ openFileDialog();
705
735
  }
706
736
  },
707
737
  [rootRef, inputRef, openFileDialog]
708
- )
738
+ );
709
739
 
710
740
  // Update focus state for the dropzone
711
741
  const onFocusCb = useCallback(() => {
712
- dispatch({type: 'focus'})
713
- }, [])
742
+ dispatch({ type: "focus" });
743
+ }, []);
714
744
  const onBlurCb = useCallback(() => {
715
- dispatch({type: 'blur'})
716
- }, [])
745
+ dispatch({ type: "blur" });
746
+ }, []);
717
747
 
718
748
  // Cb to open the file dialog when click occurs on the dropzone
719
749
  const onClickCb = useCallback(() => {
720
750
  if (noClick) {
721
- return
751
+ return;
722
752
  }
723
753
 
724
754
  // In IE11/Edge the file-browser dialog is blocking, therefore, use setTimeout()
725
755
  // to ensure React can handle state changes
726
756
  // See: https://github.com/react-dropzone/react-dropzone/issues/450
727
757
  if (isIeOrEdge()) {
728
- setTimeout(openFileDialog, 0)
758
+ setTimeout(openFileDialog, 0);
729
759
  } else {
730
- openFileDialog()
760
+ openFileDialog();
731
761
  }
732
- }, [inputRef, noClick, openFileDialog])
762
+ }, [inputRef, noClick, openFileDialog]);
733
763
 
734
- const composeHandler = fn => {
735
- return disabled ? null : fn
736
- }
764
+ const composeHandler = (fn) => {
765
+ return disabled ? null : fn;
766
+ };
737
767
 
738
- const composeKeyboardHandler = fn => {
739
- return noKeyboard ? null : composeHandler(fn)
740
- }
768
+ const composeKeyboardHandler = (fn) => {
769
+ return noKeyboard ? null : composeHandler(fn);
770
+ };
741
771
 
742
- const composeDragHandler = fn => {
743
- return noDrag ? null : composeHandler(fn)
744
- }
772
+ const composeDragHandler = (fn) => {
773
+ return noDrag ? null : composeHandler(fn);
774
+ };
745
775
 
746
- const stopPropagation = event => {
776
+ const stopPropagation = (event) => {
747
777
  if (noDragEventsBubbling) {
748
- event.stopPropagation()
778
+ event.stopPropagation();
749
779
  }
750
- }
780
+ };
751
781
 
752
782
  const getRootProps = useMemo(
753
- () => ({
754
- refKey = 'ref',
755
- role,
756
- onKeyDown,
757
- onFocus,
758
- onBlur,
759
- onClick,
760
- onDragEnter,
761
- onDragOver,
762
- onDragLeave,
763
- onDrop,
764
- ...rest
765
- } = {}) => ({
766
- onKeyDown: composeKeyboardHandler(composeEventHandlers(onKeyDown, onKeyDownCb)),
767
- onFocus: composeKeyboardHandler(composeEventHandlers(onFocus, onFocusCb)),
768
- onBlur: composeKeyboardHandler(composeEventHandlers(onBlur, onBlurCb)),
769
- onClick: composeHandler(composeEventHandlers(onClick, onClickCb)),
770
- onDragEnter: composeDragHandler(composeEventHandlers(onDragEnter, onDragEnterCb)),
771
- onDragOver: composeDragHandler(composeEventHandlers(onDragOver, onDragOverCb)),
772
- onDragLeave: composeDragHandler(composeEventHandlers(onDragLeave, onDragLeaveCb)),
773
- onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),
774
- role: typeof role === 'string' && role !== '' ? role : 'button',
775
- [refKey]: rootRef,
776
- ...(!disabled && !noKeyboard ? {tabIndex: 0} : {}),
777
- ...rest
778
- }),
783
+ () =>
784
+ ({
785
+ refKey = "ref",
786
+ role,
787
+ onKeyDown,
788
+ onFocus,
789
+ onBlur,
790
+ onClick,
791
+ onDragEnter,
792
+ onDragOver,
793
+ onDragLeave,
794
+ onDrop,
795
+ ...rest
796
+ } = {}) => ({
797
+ onKeyDown: composeKeyboardHandler(
798
+ composeEventHandlers(onKeyDown, onKeyDownCb)
799
+ ),
800
+ onFocus: composeKeyboardHandler(
801
+ composeEventHandlers(onFocus, onFocusCb)
802
+ ),
803
+ onBlur: composeKeyboardHandler(composeEventHandlers(onBlur, onBlurCb)),
804
+ onClick: composeHandler(composeEventHandlers(onClick, onClickCb)),
805
+ onDragEnter: composeDragHandler(
806
+ composeEventHandlers(onDragEnter, onDragEnterCb)
807
+ ),
808
+ onDragOver: composeDragHandler(
809
+ composeEventHandlers(onDragOver, onDragOverCb)
810
+ ),
811
+ onDragLeave: composeDragHandler(
812
+ composeEventHandlers(onDragLeave, onDragLeaveCb)
813
+ ),
814
+ onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),
815
+ role: typeof role === "string" && role !== "" ? role : "button",
816
+ [refKey]: rootRef,
817
+ ...(!disabled && !noKeyboard ? { tabIndex: 0 } : {}),
818
+ ...rest,
819
+ }),
779
820
  [
780
821
  rootRef,
781
822
  onKeyDownCb,
@@ -788,39 +829,51 @@ export function useDropzone(options = {}) {
788
829
  onDropCb,
789
830
  noKeyboard,
790
831
  noDrag,
791
- disabled
832
+ disabled,
792
833
  ]
793
- )
834
+ );
794
835
 
795
- const onInputElementClick = useCallback(event => {
796
- event.stopPropagation()
797
- }, [])
836
+ const onInputElementClick = useCallback((event) => {
837
+ event.stopPropagation();
838
+ }, []);
798
839
 
799
840
  const getInputProps = useMemo(
800
- () => ({refKey = 'ref', onChange, onClick, ...rest} = {}) => {
801
- const inputProps = {
802
- accept,
803
- multiple,
804
- type: 'file',
805
- style: {display: 'none'},
806
- onChange: composeHandler(composeEventHandlers(onChange, onDropCb)),
807
- onClick: composeHandler(composeEventHandlers(onClick, onInputElementClick)),
808
- autoComplete: 'off',
809
- tabIndex: -1,
810
- [refKey]: inputRef
811
- }
812
-
813
- return {
814
- ...inputProps,
815
- ...rest
816
- }
817
- },
841
+ () =>
842
+ ({ refKey = "ref", onChange, onClick, ...rest } = {}) => {
843
+ const inputProps = {
844
+ accept,
845
+ multiple,
846
+ type: "file",
847
+ style: { display: "none" },
848
+ onChange: composeHandler(composeEventHandlers(onChange, onDropCb)),
849
+ onClick: composeHandler(
850
+ composeEventHandlers(onClick, onInputElementClick)
851
+ ),
852
+ autoComplete: "off",
853
+ tabIndex: -1,
854
+ [refKey]: inputRef,
855
+ };
856
+
857
+ return {
858
+ ...inputProps,
859
+ ...rest,
860
+ };
861
+ },
818
862
  [inputRef, accept, multiple, onDropCb, disabled]
819
- )
820
-
821
- const fileCount = draggedFiles.length
822
- const isDragAccept = fileCount > 0 && allFilesAccepted({files: draggedFiles, accept, minSize, maxSize, multiple, maxFiles})
823
- const isDragReject = fileCount > 0 && !isDragAccept
863
+ );
864
+
865
+ const fileCount = draggedFiles.length;
866
+ const isDragAccept =
867
+ fileCount > 0 &&
868
+ allFilesAccepted({
869
+ files: draggedFiles,
870
+ accept,
871
+ minSize,
872
+ maxSize,
873
+ multiple,
874
+ maxFiles,
875
+ });
876
+ const isDragReject = fileCount > 0 && !isDragAccept;
824
877
 
825
878
  return {
826
879
  ...state,
@@ -831,56 +884,56 @@ export function useDropzone(options = {}) {
831
884
  getInputProps,
832
885
  rootRef,
833
886
  inputRef,
834
- open: composeHandler(openFileDialog)
835
- }
887
+ open: composeHandler(openFileDialog),
888
+ };
836
889
  }
837
890
 
838
891
  function reducer(state, action) {
839
892
  /* istanbul ignore next */
840
893
  switch (action.type) {
841
- case 'focus':
894
+ case "focus":
842
895
  return {
843
896
  ...state,
844
- isFocused: true
845
- }
846
- case 'blur':
897
+ isFocused: true,
898
+ };
899
+ case "blur":
847
900
  return {
848
901
  ...state,
849
- isFocused: false
850
- }
851
- case 'openDialog':
902
+ isFocused: false,
903
+ };
904
+ case "openDialog":
852
905
  return {
853
906
  ...initialState,
854
- isFileDialogActive: true
855
- }
856
- case 'closeDialog':
907
+ isFileDialogActive: true,
908
+ };
909
+ case "closeDialog":
857
910
  return {
858
911
  ...state,
859
- isFileDialogActive: false
860
- }
861
- case 'setDraggedFiles':
912
+ isFileDialogActive: false,
913
+ };
914
+ case "setDraggedFiles":
862
915
  /* eslint no-case-declarations: 0 */
863
- const {isDragActive, draggedFiles} = action
916
+ const { isDragActive, draggedFiles } = action;
864
917
  return {
865
918
  ...state,
866
919
  draggedFiles,
867
- isDragActive
868
- }
869
- case 'setFiles':
920
+ isDragActive,
921
+ };
922
+ case "setFiles":
870
923
  return {
871
924
  ...state,
872
925
  acceptedFiles: action.acceptedFiles,
873
- fileRejections: action.fileRejections
874
- }
875
- case 'reset':
926
+ fileRejections: action.fileRejections,
927
+ };
928
+ case "reset":
876
929
  return {
877
- ...initialState
878
- }
930
+ ...initialState,
931
+ };
879
932
  default:
880
- return state
933
+ return state;
881
934
  }
882
935
  }
883
936
 
884
937
  function noop() {}
885
938
 
886
- export {ErrorCode} from './utils'
939
+ export { ErrorCode } from "./utils";