react-dropzone 12.1.0 → 14.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.
@@ -1,21 +1,17 @@
1
1
  By providing `accept` prop you can make the dropzone accept specific file types and reject the others.
2
2
 
3
- The value must be a comma-separated list of unique content type specifiers:
4
- * A file extension starting with the STOP character (U+002E). (e.g. .jpg, .png, .doc).
5
- * A valid MIME type with no extensions.
6
- * audio/* representing sound files.
7
- * video/* representing video files.
8
- * image/* representing image files.
3
+ The value must be an object with a common [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) as keys and an array of file extensions as values (similar to [showOpenFilePicker](https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker)'s types `accept` option).
4
+ ```js static
5
+ useDropzone({
6
+ accept: {
7
+ 'image/png': ['.png'],
8
+ 'text/html': ['.html', '.htm'],
9
+ }
10
+ })
11
+ ```
9
12
 
10
13
  For more information see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input.
11
14
 
12
- **IMPORTANT** As of [v12.0.0](https://github.com/react-dropzone/react-dropzone/releases/tag/v12.0.0), there has been some changes that affect how `accept` works.
13
- See [file dialog cancel callback](../../README.md#file-dialog-cancel-callback) to read more about why this change was introduced. In summary:
14
- 1. In browsers that **do not support** the FS access API, the `accept` attr works exactly the same as in previous versions of react-dropozone, for both file picker and dag 'n' drop
15
- 2. In browsers that **support** the FS access API, when passing file extensions to `accept` (e.g `".jpg,.png"`), the file picker will not apply those filters, but drag 'n' drop will - though, the [browser limitations](#browser-limitations) described in this document still apply
16
- 3. If you want the same behaviour in all browsers, regardless of using the FS access API or not, you need to use MIME types - [browser limitations](#browser-limitations) still apply
17
- 4. The use of FS access API can be turned off via `useDropzone({useFsAccessApi: false})`
18
-
19
15
  ```jsx harmony
20
16
  import React from 'react';
21
17
  import {useDropzone} from 'react-dropzone';
@@ -27,7 +23,10 @@ function Accept(props) {
27
23
  getRootProps,
28
24
  getInputProps
29
25
  } = useDropzone({
30
- accept: 'image/jpeg,image/png'
26
+ accept: {
27
+ 'image/jpeg': [],
28
+ 'image/png': []
29
+ }
31
30
  });
32
31
 
33
32
  const acceptedFileItems = acceptedFiles.map(file => (
@@ -85,7 +84,9 @@ function Accept(props) {
85
84
  isDragAccept,
86
85
  isDragReject
87
86
  } = useDropzone({
88
- accept: '.jpeg,.png'
87
+ accept: {
88
+ 'image/jpeg': ['.jpeg', '.png']
89
+ }
89
90
  });
90
91
 
91
92
  return (
@@ -117,7 +118,9 @@ function Accept(props) {
117
118
  isDragAccept,
118
119
  isDragReject
119
120
  } = useDropzone({
120
- accept: 'image/jpeg,image/png'
121
+ accept: {
122
+ 'image/*': ['.jpeg', '.png']
123
+ }
121
124
  });
122
125
 
123
126
  return (
@@ -77,7 +77,9 @@ const editImage = (image, done) => {
77
77
  function App() {
78
78
  const [files, setFiles] = useState([]);
79
79
  const { getRootProps, getInputProps } = useDropzone({
80
- accept: 'image/*',
80
+ accept: {
81
+ 'image/*': [],
82
+ },
81
83
  onDrop: (acceptedFiles) => {
82
84
  setFiles(
83
85
  acceptedFiles.map((file) =>
@@ -41,7 +41,9 @@ const img = {
41
41
  function Previews(props) {
42
42
  const [files, setFiles] = useState([]);
43
43
  const {getRootProps, getInputProps} = useDropzone({
44
- accept: 'image/*',
44
+ accept: {
45
+ 'image/*': []
46
+ },
45
47
  onDrop: acceptedFiles => {
46
48
  setFiles(acceptedFiles.map(file => Object.assign(file, {
47
49
  preview: URL.createObjectURL(file)
@@ -41,7 +41,7 @@ function StyledDropzone(props) {
41
41
  isFocused,
42
42
  isDragAccept,
43
43
  isDragReject
44
- } = useDropzone({accept: 'image/*'});
44
+ } = useDropzone({accept: {'image/*': []}});
45
45
 
46
46
  const style = useMemo(() => ({
47
47
  ...baseStyle,
@@ -110,7 +110,7 @@ function StyledDropzone(props) {
110
110
  isFocused,
111
111
  isDragAccept,
112
112
  isDragReject
113
- } = useDropzone({accept: 'image/*'});
113
+ } = useDropzone({accept: {'image/*': []}});
114
114
 
115
115
  return (
116
116
  <div className="container">
package/package.json CHANGED
@@ -95,7 +95,7 @@
95
95
  ],
96
96
  "license": "MIT",
97
97
  "peerDependencies": {
98
- "react": ">= 16.8"
98
+ "react": ">= 16.8 || 18.0.0"
99
99
  },
100
100
  "dependencies": {
101
101
  "attr-accept": "^2.2.2",
@@ -129,8 +129,8 @@
129
129
  "@size-limit/webpack-why": "^7.0.5",
130
130
  "@testing-library/dom": "^8.11.3",
131
131
  "@testing-library/jest-dom": "^5.16.1",
132
- "@testing-library/react": "^12.1.2",
133
- "@testing-library/react-hooks": "^7.0.2",
132
+ "@testing-library/react": "^13.1.1",
133
+ "@testing-library/react-hooks": "^8.0.0",
134
134
  "@types/react": "^17.0.0",
135
135
  "@types/react-dom": "^17.0.0",
136
136
  "@typescript-eslint/eslint-plugin": "^5.10.1",
@@ -156,10 +156,10 @@
156
156
  "markdownlint-cli": "^0.30.0",
157
157
  "pinst": "^2.1.6",
158
158
  "prettier": "^2.5.1",
159
- "react": "^17.0.0",
160
- "react-dom": "^17.0.0",
159
+ "react": "^18.1.0",
160
+ "react-dom": "^18.1.0",
161
161
  "react-styleguidist": "^11.2.0",
162
- "react-test-renderer": "^17.0.0",
162
+ "react-test-renderer": "^18.1.0",
163
163
  "rimraf": "^3.0.2",
164
164
  "rollup": "^2.66.1",
165
165
  "rollup-plugin-terser": "^7.0.2",
@@ -171,7 +171,7 @@
171
171
  "webpack-blocks": "^2.1.0"
172
172
  },
173
173
  "typings": "typings/react-dropzone.d.ts",
174
- "version": "12.1.0",
174
+ "version": "14.0.1",
175
175
  "engines": {
176
176
  "node": ">= 10.13"
177
177
  },
@@ -1,3 +1,3 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`useDropzone() hook behavior renders the root and input nodes with the necessary props 1`] = `"<div role=\\"button\\" tabindex=\\"0\\"><input multiple=\\"\\" type=\\"file\\" style=\\"display: none;\\" tabindex=\\"-1\\"></div>"`;
3
+ exports[`useDropzone() hook behavior renders the root and input nodes with the necessary props 1`] = `"<div role=\\"presentation\\" tabindex=\\"0\\"><input multiple=\\"\\" type=\\"file\\" style=\\"display: none;\\" tabindex=\\"-1\\"></div>"`;
package/src/index.js CHANGED
@@ -12,11 +12,11 @@ import React, {
12
12
  import PropTypes from "prop-types";
13
13
  import { fromEvent } from "file-selector";
14
14
  import {
15
+ acceptPropAsAcceptAttr,
15
16
  allFilesAccepted,
16
17
  composeEventHandlers,
17
18
  fileAccepted,
18
19
  fileMatchSize,
19
- filePickerOptionsTypes,
20
20
  canUseFileSystemAccessAPI,
21
21
  isAbort,
22
22
  isEvtWithFiles,
@@ -24,6 +24,7 @@ import {
24
24
  isPropagationStopped,
25
25
  isSecurityError,
26
26
  onDocumentDragOver,
27
+ pickerOptionsFromAccept,
27
28
  TOO_MANY_FILES_REJECTION,
28
29
  } from "./utils/index";
29
30
 
@@ -84,7 +85,6 @@ Dropzone.propTypes = {
84
85
  * @param {boolean} params.isDragActive Active drag is in progress
85
86
  * @param {boolean} params.isDragAccept Dragged files are accepted
86
87
  * @param {boolean} params.isDragReject Some dragged files are rejected
87
- * @param {File[]} params.draggedFiles Files in active drag
88
88
  * @param {File[]} params.acceptedFiles Accepted files
89
89
  * @param {FileRejection[]} params.fileRejections Rejected files and why they were rejected
90
90
  */
@@ -92,16 +92,12 @@ Dropzone.propTypes = {
92
92
 
93
93
  /**
94
94
  * Set accepted file types.
95
- * See https://github.com/okonet/attr-accept for more information.
95
+ * Checkout https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker types option for more information.
96
96
  * Keep in mind that mime type determination is not reliable across platforms. CSV files,
97
97
  * for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
98
- * Windows. In some cases there might not be a mime type set at all.
99
- * See: https://github.com/react-dropzone/react-dropzone/issues/276
98
+ * Windows. In some cases there might not be a mime type set at all (https://github.com/react-dropzone/react-dropzone/issues/276).
100
99
  */
101
- accept: PropTypes.oneOfType([
102
- PropTypes.string,
103
- PropTypes.arrayOf(PropTypes.string),
104
- ]),
100
+ accept: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.string)),
105
101
 
106
102
  /**
107
103
  * Allow drag 'n' drop (or selection from the file dialog) of multiple files
@@ -248,6 +244,13 @@ Dropzone.propTypes = {
248
244
  */
249
245
  onDropRejected: PropTypes.func,
250
246
 
247
+ /**
248
+ * Cb for when there's some error from any of the promises.
249
+ *
250
+ * @param {Error} error
251
+ */
252
+ onError: PropTypes.func,
253
+
251
254
  /**
252
255
  * Custom validation function
253
256
  * @param {File} file
@@ -306,29 +309,33 @@ export default Dropzone;
306
309
  */
307
310
 
308
311
  /**
309
- * An object with the current dropzone state and some helper functions.
312
+ * An object with the current dropzone state.
310
313
  *
311
314
  * @typedef {object} DropzoneState
312
- * @property {Function} getRootProps Returns the props you should apply to the root drop container you render
313
- * @property {Function} getInputProps Returns the props you should apply to hidden file input you render
314
- * @property {Function} open Open the native file selection dialog
315
315
  * @property {boolean} isFocused Dropzone area is in focus
316
316
  * @property {boolean} isFileDialogActive File dialog is opened
317
317
  * @property {boolean} isDragActive Active drag is in progress
318
318
  * @property {boolean} isDragAccept Dragged files are accepted
319
319
  * @property {boolean} isDragReject Some dragged files are rejected
320
- * @property {File[]} draggedFiles Files in active drag
321
320
  * @property {File[]} acceptedFiles Accepted files
322
321
  * @property {FileRejection[]} fileRejections Rejected files and why they were rejected
323
322
  */
324
323
 
324
+ /**
325
+ * An object with the dropzone methods.
326
+ *
327
+ * @typedef {object} DropzoneMethods
328
+ * @property {Function} getRootProps Returns the props you should apply to the root drop container you render
329
+ * @property {Function} getInputProps Returns the props you should apply to hidden file input you render
330
+ * @property {Function} open Open the native file selection dialog
331
+ */
332
+
325
333
  const initialState = {
326
334
  isFocused: false,
327
335
  isFileDialogActive: false,
328
336
  isDragActive: false,
329
337
  isDragAccept: false,
330
338
  isDragReject: false,
331
- draggedFiles: [],
332
339
  acceptedFiles: [],
333
340
  fileRejections: [],
334
341
  };
@@ -355,12 +362,11 @@ const initialState = {
355
362
  * @function useDropzone
356
363
  *
357
364
  * @param {object} props
358
- * @param {string|string[]} [props.accept] Set accepted file types.
359
- * See https://github.com/okonet/attr-accept for more information.
365
+ * @param {import("./utils").AcceptProp} [props.accept] Set accepted file types.
366
+ * Checkout https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker types option for more information.
360
367
  * Keep in mind that mime type determination is not reliable across platforms. CSV files,
361
368
  * for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
362
- * Windows. In some cases there might not be a mime type set at all.
363
- * See: https://github.com/react-dropzone/react-dropzone/issues/276
369
+ * Windows. In some cases there might not be a mime type set at all (https://github.com/react-dropzone/react-dropzone/issues/276).
364
370
  * @param {boolean} [props.multiple=true] Allow drag 'n' drop (or selection from the file dialog) of multiple files
365
371
  * @param {boolean} [props.preventDropOnDocument=true] If false, allow dropped items to take over the current browser window
366
372
  * @param {boolean} [props.noClick=false] If true, disables click to open the native file selection dialog
@@ -383,7 +389,7 @@ const initialState = {
383
389
  * Note that this callback is invoked after the `getFilesFromEvent` callback is done.
384
390
  *
385
391
  * Files are accepted or rejected based on the `accept`, `multiple`, `minSize` and `maxSize` props.
386
- * `accept` must be a valid [MIME type](http://www.iana.org/assignments/media-types/media-types.xhtml) according to [input element specification](https://www.w3.org/wiki/HTML/Elements/input/file) or a valid file extension.
392
+ * `accept` must be an object with keys as a valid [MIME type](http://www.iana.org/assignments/media-types/media-types.xhtml) according to [input element specification](https://www.w3.org/wiki/HTML/Elements/input/file) and the value an array of file extensions (optional).
387
393
  * If `multiple` is set to false and additional files are dropped,
388
394
  * all files besides the first will be rejected.
389
395
  * Any file which does not have a size in the [`minSize`, `maxSize`] range, will be rejected as well.
@@ -405,10 +411,11 @@ const initialState = {
405
411
  * ```
406
412
  * @param {dropAcceptedCb} [props.onDropAccepted]
407
413
  * @param {dropRejectedCb} [props.onDropRejected]
414
+ * @param {(error: Error) => void} [props.onError]
408
415
  *
409
- * @returns {DropzoneState}
416
+ * @returns {DropzoneState & DropzoneMethods}
410
417
  */
411
- export function useDropzone(options = {}) {
418
+ export function useDropzone(props = {}) {
412
419
  const {
413
420
  accept,
414
421
  disabled,
@@ -431,12 +438,16 @@ export function useDropzone(options = {}) {
431
438
  noKeyboard,
432
439
  noDrag,
433
440
  noDragEventsBubbling,
441
+ onError,
434
442
  validator,
435
443
  } = {
436
444
  ...defaultProps,
437
- ...options,
445
+ ...props,
438
446
  };
439
447
 
448
+ const acceptAttr = useMemo(() => acceptPropAsAcceptAttr(accept), [accept]);
449
+ const pickerTypes = useMemo(() => pickerOptionsFromAccept(accept), [accept]);
450
+
440
451
  const onFileDialogOpenCb = useMemo(
441
452
  () => (typeof onFileDialogOpen === "function" ? onFileDialogOpen : noop),
442
453
  [onFileDialogOpen]
@@ -451,7 +462,7 @@ export function useDropzone(options = {}) {
451
462
  const inputRef = useRef(null);
452
463
 
453
464
  const [state, dispatch] = useReducer(reducer, initialState);
454
- const { isFocused, isFileDialogActive, draggedFiles } = state;
465
+ const { isFocused, isFileDialogActive } = state;
455
466
 
456
467
  const fsAccessApiWorksRef = useRef(
457
468
  typeof window !== "undefined" &&
@@ -507,6 +518,18 @@ export function useDropzone(options = {}) {
507
518
  };
508
519
  }, [rootRef, preventDropOnDocument]);
509
520
 
521
+ const onErrCb = useCallback(
522
+ (e) => {
523
+ if (onError) {
524
+ onError(e);
525
+ } else {
526
+ // Let the user know something's gone wrong if they haven't provided the onError cb.
527
+ console.error(e);
528
+ }
529
+ },
530
+ [onError]
531
+ );
532
+
510
533
  const onDragEnterCb = useCallback(
511
534
  (event) => {
512
535
  event.preventDefault();
@@ -517,24 +540,50 @@ export function useDropzone(options = {}) {
517
540
  dragTargetsRef.current = [...dragTargetsRef.current, event.target];
518
541
 
519
542
  if (isEvtWithFiles(event)) {
520
- Promise.resolve(getFilesFromEvent(event)).then((draggedFiles) => {
521
- if (isPropagationStopped(event) && !noDragEventsBubbling) {
522
- return;
523
- }
524
-
525
- dispatch({
526
- draggedFiles,
527
- isDragActive: true,
528
- type: "setDraggedFiles",
529
- });
543
+ Promise.resolve(getFilesFromEvent(event))
544
+ .then((files) => {
545
+ if (isPropagationStopped(event) && !noDragEventsBubbling) {
546
+ return;
547
+ }
530
548
 
531
- if (onDragEnter) {
532
- onDragEnter(event);
533
- }
534
- });
549
+ const fileCount = files.length;
550
+ const isDragAccept =
551
+ fileCount > 0 &&
552
+ allFilesAccepted({
553
+ files,
554
+ accept: acceptAttr,
555
+ minSize,
556
+ maxSize,
557
+ multiple,
558
+ maxFiles,
559
+ });
560
+ const isDragReject = fileCount > 0 && !isDragAccept;
561
+
562
+ dispatch({
563
+ isDragAccept,
564
+ isDragReject,
565
+ isDragActive: true,
566
+ type: "setDraggedFiles",
567
+ });
568
+
569
+ if (onDragEnter) {
570
+ onDragEnter(event);
571
+ }
572
+ })
573
+ .catch((e) => onErrCb(e));
535
574
  }
536
575
  },
537
- [getFilesFromEvent, onDragEnter, noDragEventsBubbling]
576
+ [
577
+ getFilesFromEvent,
578
+ onDragEnter,
579
+ onErrCb,
580
+ noDragEventsBubbling,
581
+ acceptAttr,
582
+ minSize,
583
+ maxSize,
584
+ multiple,
585
+ maxFiles,
586
+ ]
538
587
  );
539
588
 
540
589
  const onDragOverCb = useCallback(
@@ -581,9 +630,10 @@ export function useDropzone(options = {}) {
581
630
  }
582
631
 
583
632
  dispatch({
584
- isDragActive: false,
585
633
  type: "setDraggedFiles",
586
- draggedFiles: [],
634
+ isDragActive: false,
635
+ isDragAccept: false,
636
+ isDragReject: false,
587
637
  });
588
638
 
589
639
  if (isEvtWithFiles(event) && onDragLeave) {
@@ -599,7 +649,7 @@ export function useDropzone(options = {}) {
599
649
  const fileRejections = [];
600
650
 
601
651
  files.forEach((file) => {
602
- const [accepted, acceptError] = fileAccepted(file, accept);
652
+ const [accepted, acceptError] = fileAccepted(file, acceptAttr);
603
653
  const [sizeMatch, sizeError] = fileMatchSize(file, minSize, maxSize);
604
654
  const customErrors = validator ? validator(file) : null;
605
655
 
@@ -648,7 +698,7 @@ export function useDropzone(options = {}) {
648
698
  [
649
699
  dispatch,
650
700
  multiple,
651
- accept,
701
+ acceptAttr,
652
702
  minSize,
653
703
  maxSize,
654
704
  maxFiles,
@@ -669,16 +719,18 @@ export function useDropzone(options = {}) {
669
719
  dragTargetsRef.current = [];
670
720
 
671
721
  if (isEvtWithFiles(event)) {
672
- Promise.resolve(getFilesFromEvent(event)).then((files) => {
673
- if (isPropagationStopped(event) && !noDragEventsBubbling) {
674
- return;
675
- }
676
- setFiles(files, event);
677
- });
722
+ Promise.resolve(getFilesFromEvent(event))
723
+ .then((files) => {
724
+ if (isPropagationStopped(event) && !noDragEventsBubbling) {
725
+ return;
726
+ }
727
+ setFiles(files, event);
728
+ })
729
+ .catch((e) => onErrCb(e));
678
730
  }
679
731
  dispatch({ type: "reset" });
680
732
  },
681
- [getFilesFromEvent, setFiles, noDragEventsBubbling]
733
+ [getFilesFromEvent, setFiles, onErrCb, noDragEventsBubbling]
682
734
  );
683
735
 
684
736
  // Fn for opening the file dialog programmatically
@@ -691,7 +743,7 @@ export function useDropzone(options = {}) {
691
743
  // https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker
692
744
  const opts = {
693
745
  multiple,
694
- types: filePickerOptionsTypes(accept),
746
+ types: pickerTypes,
695
747
  };
696
748
  window
697
749
  .showOpenFilePicker(opts)
@@ -713,6 +765,8 @@ export function useDropzone(options = {}) {
713
765
  inputRef.current.value = null;
714
766
  inputRef.current.click();
715
767
  }
768
+ } else {
769
+ onErrCb(e);
716
770
  }
717
771
  });
718
772
  return;
@@ -730,7 +784,8 @@ export function useDropzone(options = {}) {
730
784
  onFileDialogCancelCb,
731
785
  useFsAccessApi,
732
786
  setFiles,
733
- accept,
787
+ onErrCb,
788
+ pickerTypes,
734
789
  multiple,
735
790
  ]);
736
791
 
@@ -830,7 +885,7 @@ export function useDropzone(options = {}) {
830
885
  composeEventHandlers(onDragLeave, onDragLeaveCb)
831
886
  ),
832
887
  onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),
833
- role: typeof role === "string" && role !== "" ? role : "button",
888
+ role: typeof role === "string" && role !== "" ? role : "presentation",
834
889
  [refKey]: rootRef,
835
890
  ...(!disabled && !noKeyboard ? { tabIndex: 0 } : {}),
836
891
  ...rest,
@@ -859,7 +914,7 @@ export function useDropzone(options = {}) {
859
914
  () =>
860
915
  ({ refKey = "ref", onChange, onClick, ...rest } = {}) => {
861
916
  const inputProps = {
862
- accept,
917
+ accept: acceptAttr,
863
918
  multiple,
864
919
  type: "file",
865
920
  style: { display: "none" },
@@ -879,23 +934,8 @@ export function useDropzone(options = {}) {
879
934
  [inputRef, accept, multiple, onDropCb, disabled]
880
935
  );
881
936
 
882
- const fileCount = draggedFiles.length;
883
- const isDragAccept =
884
- fileCount > 0 &&
885
- allFilesAccepted({
886
- files: draggedFiles,
887
- accept,
888
- minSize,
889
- maxSize,
890
- multiple,
891
- maxFiles,
892
- });
893
- const isDragReject = fileCount > 0 && !isDragAccept;
894
-
895
937
  return {
896
938
  ...state,
897
- isDragAccept,
898
- isDragReject,
899
939
  isFocused: isFocused && !disabled,
900
940
  getRootProps,
901
941
  getInputProps,
@@ -905,6 +945,11 @@ export function useDropzone(options = {}) {
905
945
  };
906
946
  }
907
947
 
948
+ /**
949
+ * @param {DropzoneState} state
950
+ * @param {{type: string} & DropzoneState} action
951
+ * @returns {DropzoneState}
952
+ */
908
953
  function reducer(state, action) {
909
954
  /* istanbul ignore next */
910
955
  switch (action.type) {
@@ -929,12 +974,11 @@ function reducer(state, action) {
929
974
  isFileDialogActive: false,
930
975
  };
931
976
  case "setDraggedFiles":
932
- /* eslint no-case-declarations: 0 */
933
- const { isDragActive, draggedFiles } = action;
934
977
  return {
935
978
  ...state,
936
- draggedFiles,
937
- isDragActive,
979
+ isDragActive: action.isDragActive,
980
+ isDragAccept: action.isDragAccept,
981
+ isDragReject: action.isDragReject,
938
982
  };
939
983
  case "setFiles":
940
984
  return {