react-dropzone 12.0.6 → 14.0.0
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/README.md +9 -19
- package/dist/es/index.js +106 -74
- package/dist/es/utils/index.js +88 -20
- package/dist/index.js +3 -3
- package/examples/accept/README.md +19 -16
- package/examples/pintura/README.md +3 -1
- package/examples/previews/README.md +3 -1
- package/examples/styling/README.md +2 -2
- package/package.json +8 -8
- package/src/index.js +116 -72
- package/src/index.spec.js +599 -616
- package/src/utils/index.js +82 -26
- package/src/utils/index.spec.js +124 -58
- package/typings/react-dropzone.d.ts +5 -2
- package/typings/tests/accept.tsx +3 -37
- package/typings/tests/all.tsx +3 -1
package/README.md
CHANGED
|
@@ -230,7 +230,7 @@ dropzoneRef.open()
|
|
|
230
230
|
```js static
|
|
231
231
|
import React from 'react'
|
|
232
232
|
import Dropzone from 'react-dropzone'
|
|
233
|
-
import {act, fireEvent, render
|
|
233
|
+
import {act, fireEvent, render} from '@testing-library/react'
|
|
234
234
|
|
|
235
235
|
test('invoke onDragEnter when dragenter event occurs', async () => {
|
|
236
236
|
const file = new File([
|
|
@@ -248,25 +248,17 @@ test('invoke onDragEnter when dragenter event occurs', async () => {
|
|
|
248
248
|
)}
|
|
249
249
|
</Dropzone>
|
|
250
250
|
)
|
|
251
|
-
const { container
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
251
|
+
const { container } = render(ui)
|
|
252
|
+
|
|
253
|
+
await act(
|
|
254
|
+
() => fireEvent.dragEnter(
|
|
255
|
+
container.querySelector('div'),
|
|
256
|
+
data,
|
|
257
|
+
)
|
|
258
|
+
);
|
|
257
259
|
expect(onDragEnter).toHaveBeenCalled()
|
|
258
260
|
})
|
|
259
261
|
|
|
260
|
-
async function flushPromises(rerender, ui) {
|
|
261
|
-
await act(() => waitFor(() => rerender(ui)))
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function dispatchEvt(node, type, data) {
|
|
265
|
-
const event = new Event(type, { bubbles: true })
|
|
266
|
-
Object.assign(event, data)
|
|
267
|
-
fireEvent(node, event)
|
|
268
|
-
}
|
|
269
|
-
|
|
270
262
|
function mockData(files) {
|
|
271
263
|
return {
|
|
272
264
|
dataTransfer: {
|
|
@@ -343,8 +335,6 @@ As one can imagine, this doesn't really work if there's a lot of files or large
|
|
|
343
335
|
|
|
344
336
|
Fortunately, there's the [File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API), which is currently a working draft and some browsers support it (see [browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker#browser_compatibility)), that provides a reliable way to prompt the user for file selection and capture cancellation.
|
|
345
337
|
|
|
346
|
-
And this lib makes use of it if available. Though, there's a small catch: using file extensions for the `accept` property is not supported; you must use MIME types as described in [common MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types). Also check [accepting specific file types](https://react-dropzone.js.org/#section-accepting-specific-file-types) for more info on the subject of `accept` limitations.
|
|
347
|
-
|
|
348
338
|
Also keep in mind that the FS access API can only be used in [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
|
|
349
339
|
|
|
350
340
|
**NOTE** You can disable using the FS access API with the `useFsAccessApi` property: `useDropzone({useFsAccessApi: false})`.
|
package/dist/es/index.js
CHANGED
|
@@ -37,7 +37,7 @@ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) r
|
|
|
37
37
|
import React, { forwardRef, Fragment, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef } from "react";
|
|
38
38
|
import PropTypes from "prop-types";
|
|
39
39
|
import { fromEvent } from "file-selector";
|
|
40
|
-
import { allFilesAccepted, composeEventHandlers, fileAccepted, fileMatchSize,
|
|
40
|
+
import { acceptPropAsAcceptAttr, allFilesAccepted, composeEventHandlers, fileAccepted, fileMatchSize, canUseFileSystemAccessAPI, isAbort, isEvtWithFiles, isIeOrEdge, isPropagationStopped, isSecurityError, onDocumentDragOver, pickerOptionsFromAccept, TOO_MANY_FILES_REJECTION } from "./utils/index";
|
|
41
41
|
/**
|
|
42
42
|
* Convenience wrapper component for the `useDropzone` hook
|
|
43
43
|
*
|
|
@@ -102,7 +102,6 @@ Dropzone.propTypes = {
|
|
|
102
102
|
* @param {boolean} params.isDragActive Active drag is in progress
|
|
103
103
|
* @param {boolean} params.isDragAccept Dragged files are accepted
|
|
104
104
|
* @param {boolean} params.isDragReject Some dragged files are rejected
|
|
105
|
-
* @param {File[]} params.draggedFiles Files in active drag
|
|
106
105
|
* @param {File[]} params.acceptedFiles Accepted files
|
|
107
106
|
* @param {FileRejection[]} params.fileRejections Rejected files and why they were rejected
|
|
108
107
|
*/
|
|
@@ -110,13 +109,12 @@ Dropzone.propTypes = {
|
|
|
110
109
|
|
|
111
110
|
/**
|
|
112
111
|
* Set accepted file types.
|
|
113
|
-
*
|
|
112
|
+
* Checkout https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker types option for more information.
|
|
114
113
|
* Keep in mind that mime type determination is not reliable across platforms. CSV files,
|
|
115
114
|
* for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
|
|
116
|
-
* Windows. In some cases there might not be a mime type set at all.
|
|
117
|
-
* See: https://github.com/react-dropzone/react-dropzone/issues/276
|
|
115
|
+
* Windows. In some cases there might not be a mime type set at all (https://github.com/react-dropzone/react-dropzone/issues/276).
|
|
118
116
|
*/
|
|
119
|
-
accept: PropTypes.
|
|
117
|
+
accept: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.string)),
|
|
120
118
|
|
|
121
119
|
/**
|
|
122
120
|
* Allow drag 'n' drop (or selection from the file dialog) of multiple files
|
|
@@ -264,6 +262,13 @@ Dropzone.propTypes = {
|
|
|
264
262
|
*/
|
|
265
263
|
onDropRejected: PropTypes.func,
|
|
266
264
|
|
|
265
|
+
/**
|
|
266
|
+
* Cb for when there's some error from any of the promises.
|
|
267
|
+
*
|
|
268
|
+
* @param {Error} error
|
|
269
|
+
*/
|
|
270
|
+
onError: PropTypes.func,
|
|
271
|
+
|
|
267
272
|
/**
|
|
268
273
|
* Custom validation function
|
|
269
274
|
* @param {File} file
|
|
@@ -320,29 +325,33 @@ export default Dropzone;
|
|
|
320
325
|
*/
|
|
321
326
|
|
|
322
327
|
/**
|
|
323
|
-
* An object with the current dropzone state
|
|
328
|
+
* An object with the current dropzone state.
|
|
324
329
|
*
|
|
325
330
|
* @typedef {object} DropzoneState
|
|
326
|
-
* @property {Function} getRootProps Returns the props you should apply to the root drop container you render
|
|
327
|
-
* @property {Function} getInputProps Returns the props you should apply to hidden file input you render
|
|
328
|
-
* @property {Function} open Open the native file selection dialog
|
|
329
331
|
* @property {boolean} isFocused Dropzone area is in focus
|
|
330
332
|
* @property {boolean} isFileDialogActive File dialog is opened
|
|
331
333
|
* @property {boolean} isDragActive Active drag is in progress
|
|
332
334
|
* @property {boolean} isDragAccept Dragged files are accepted
|
|
333
335
|
* @property {boolean} isDragReject Some dragged files are rejected
|
|
334
|
-
* @property {File[]} draggedFiles Files in active drag
|
|
335
336
|
* @property {File[]} acceptedFiles Accepted files
|
|
336
337
|
* @property {FileRejection[]} fileRejections Rejected files and why they were rejected
|
|
337
338
|
*/
|
|
338
339
|
|
|
340
|
+
/**
|
|
341
|
+
* An object with the dropzone methods.
|
|
342
|
+
*
|
|
343
|
+
* @typedef {object} DropzoneMethods
|
|
344
|
+
* @property {Function} getRootProps Returns the props you should apply to the root drop container you render
|
|
345
|
+
* @property {Function} getInputProps Returns the props you should apply to hidden file input you render
|
|
346
|
+
* @property {Function} open Open the native file selection dialog
|
|
347
|
+
*/
|
|
348
|
+
|
|
339
349
|
var initialState = {
|
|
340
350
|
isFocused: false,
|
|
341
351
|
isFileDialogActive: false,
|
|
342
352
|
isDragActive: false,
|
|
343
353
|
isDragAccept: false,
|
|
344
354
|
isDragReject: false,
|
|
345
|
-
draggedFiles: [],
|
|
346
355
|
acceptedFiles: [],
|
|
347
356
|
fileRejections: []
|
|
348
357
|
};
|
|
@@ -368,12 +377,11 @@ var initialState = {
|
|
|
368
377
|
* @function useDropzone
|
|
369
378
|
*
|
|
370
379
|
* @param {object} props
|
|
371
|
-
* @param {
|
|
372
|
-
*
|
|
380
|
+
* @param {import("./utils").AcceptProp} [props.accept] Set accepted file types.
|
|
381
|
+
* Checkout https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker types option for more information.
|
|
373
382
|
* Keep in mind that mime type determination is not reliable across platforms. CSV files,
|
|
374
383
|
* for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
|
|
375
|
-
* Windows. In some cases there might not be a mime type set at all.
|
|
376
|
-
* See: https://github.com/react-dropzone/react-dropzone/issues/276
|
|
384
|
+
* Windows. In some cases there might not be a mime type set at all (https://github.com/react-dropzone/react-dropzone/issues/276).
|
|
377
385
|
* @param {boolean} [props.multiple=true] Allow drag 'n' drop (or selection from the file dialog) of multiple files
|
|
378
386
|
* @param {boolean} [props.preventDropOnDocument=true] If false, allow dropped items to take over the current browser window
|
|
379
387
|
* @param {boolean} [props.noClick=false] If true, disables click to open the native file selection dialog
|
|
@@ -396,7 +404,7 @@ var initialState = {
|
|
|
396
404
|
* Note that this callback is invoked after the `getFilesFromEvent` callback is done.
|
|
397
405
|
*
|
|
398
406
|
* Files are accepted or rejected based on the `accept`, `multiple`, `minSize` and `maxSize` props.
|
|
399
|
-
* `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)
|
|
407
|
+
* `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).
|
|
400
408
|
* If `multiple` is set to false and additional files are dropped,
|
|
401
409
|
* all files besides the first will be rejected.
|
|
402
410
|
* Any file which does not have a size in the [`minSize`, `maxSize`] range, will be rejected as well.
|
|
@@ -418,37 +426,45 @@ var initialState = {
|
|
|
418
426
|
* ```
|
|
419
427
|
* @param {dropAcceptedCb} [props.onDropAccepted]
|
|
420
428
|
* @param {dropRejectedCb} [props.onDropRejected]
|
|
429
|
+
* @param {(error: Error) => void} [props.onError]
|
|
421
430
|
*
|
|
422
|
-
* @returns {DropzoneState}
|
|
431
|
+
* @returns {DropzoneState & DropzoneMethods}
|
|
423
432
|
*/
|
|
424
433
|
|
|
425
434
|
export function useDropzone() {
|
|
426
|
-
var
|
|
427
|
-
|
|
428
|
-
var _defaultProps$
|
|
429
|
-
accept = _defaultProps$
|
|
430
|
-
disabled = _defaultProps$
|
|
431
|
-
getFilesFromEvent = _defaultProps$
|
|
432
|
-
maxSize = _defaultProps$
|
|
433
|
-
minSize = _defaultProps$
|
|
434
|
-
multiple = _defaultProps$
|
|
435
|
-
maxFiles = _defaultProps$
|
|
436
|
-
onDragEnter = _defaultProps$
|
|
437
|
-
onDragLeave = _defaultProps$
|
|
438
|
-
onDragOver = _defaultProps$
|
|
439
|
-
onDrop = _defaultProps$
|
|
440
|
-
onDropAccepted = _defaultProps$
|
|
441
|
-
onDropRejected = _defaultProps$
|
|
442
|
-
onFileDialogCancel = _defaultProps$
|
|
443
|
-
onFileDialogOpen = _defaultProps$
|
|
444
|
-
useFsAccessApi = _defaultProps$
|
|
445
|
-
preventDropOnDocument = _defaultProps$
|
|
446
|
-
noClick = _defaultProps$
|
|
447
|
-
noKeyboard = _defaultProps$
|
|
448
|
-
noDrag = _defaultProps$
|
|
449
|
-
noDragEventsBubbling = _defaultProps$
|
|
450
|
-
|
|
451
|
-
|
|
435
|
+
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
436
|
+
|
|
437
|
+
var _defaultProps$props = _objectSpread(_objectSpread({}, defaultProps), props),
|
|
438
|
+
accept = _defaultProps$props.accept,
|
|
439
|
+
disabled = _defaultProps$props.disabled,
|
|
440
|
+
getFilesFromEvent = _defaultProps$props.getFilesFromEvent,
|
|
441
|
+
maxSize = _defaultProps$props.maxSize,
|
|
442
|
+
minSize = _defaultProps$props.minSize,
|
|
443
|
+
multiple = _defaultProps$props.multiple,
|
|
444
|
+
maxFiles = _defaultProps$props.maxFiles,
|
|
445
|
+
onDragEnter = _defaultProps$props.onDragEnter,
|
|
446
|
+
onDragLeave = _defaultProps$props.onDragLeave,
|
|
447
|
+
onDragOver = _defaultProps$props.onDragOver,
|
|
448
|
+
onDrop = _defaultProps$props.onDrop,
|
|
449
|
+
onDropAccepted = _defaultProps$props.onDropAccepted,
|
|
450
|
+
onDropRejected = _defaultProps$props.onDropRejected,
|
|
451
|
+
onFileDialogCancel = _defaultProps$props.onFileDialogCancel,
|
|
452
|
+
onFileDialogOpen = _defaultProps$props.onFileDialogOpen,
|
|
453
|
+
useFsAccessApi = _defaultProps$props.useFsAccessApi,
|
|
454
|
+
preventDropOnDocument = _defaultProps$props.preventDropOnDocument,
|
|
455
|
+
noClick = _defaultProps$props.noClick,
|
|
456
|
+
noKeyboard = _defaultProps$props.noKeyboard,
|
|
457
|
+
noDrag = _defaultProps$props.noDrag,
|
|
458
|
+
noDragEventsBubbling = _defaultProps$props.noDragEventsBubbling,
|
|
459
|
+
onError = _defaultProps$props.onError,
|
|
460
|
+
validator = _defaultProps$props.validator;
|
|
461
|
+
|
|
462
|
+
var acceptAttr = useMemo(function () {
|
|
463
|
+
return acceptPropAsAcceptAttr(accept);
|
|
464
|
+
}, [accept]);
|
|
465
|
+
var pickerTypes = useMemo(function () {
|
|
466
|
+
return pickerOptionsFromAccept(accept);
|
|
467
|
+
}, [accept]);
|
|
452
468
|
var onFileDialogOpenCb = useMemo(function () {
|
|
453
469
|
return typeof onFileDialogOpen === "function" ? onFileDialogOpen : noop;
|
|
454
470
|
}, [onFileDialogOpen]);
|
|
@@ -464,8 +480,7 @@ export function useDropzone() {
|
|
|
464
480
|
dispatch = _useReducer2[1];
|
|
465
481
|
|
|
466
482
|
var isFocused = state.isFocused,
|
|
467
|
-
isFileDialogActive = state.isFileDialogActive
|
|
468
|
-
draggedFiles = state.draggedFiles;
|
|
483
|
+
isFileDialogActive = state.isFileDialogActive;
|
|
469
484
|
var fsAccessApiWorksRef = useRef(typeof window !== "undefined" && window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI()); // Update file dialog active state when the window is focused on
|
|
470
485
|
|
|
471
486
|
var onWindowFocus = function onWindowFocus() {
|
|
@@ -517,6 +532,14 @@ export function useDropzone() {
|
|
|
517
532
|
}
|
|
518
533
|
};
|
|
519
534
|
}, [rootRef, preventDropOnDocument]);
|
|
535
|
+
var onErrCb = useCallback(function (e) {
|
|
536
|
+
if (onError) {
|
|
537
|
+
onError(e);
|
|
538
|
+
} else {
|
|
539
|
+
// Let the user know something's gone wrong if they haven't provided the onError cb.
|
|
540
|
+
console.error(e);
|
|
541
|
+
}
|
|
542
|
+
}, [onError]);
|
|
520
543
|
var onDragEnterCb = useCallback(function (event) {
|
|
521
544
|
event.preventDefault(); // Persist here because we need the event later after getFilesFromEvent() is done
|
|
522
545
|
|
|
@@ -525,13 +548,24 @@ export function useDropzone() {
|
|
|
525
548
|
dragTargetsRef.current = [].concat(_toConsumableArray(dragTargetsRef.current), [event.target]);
|
|
526
549
|
|
|
527
550
|
if (isEvtWithFiles(event)) {
|
|
528
|
-
Promise.resolve(getFilesFromEvent(event)).then(function (
|
|
551
|
+
Promise.resolve(getFilesFromEvent(event)).then(function (files) {
|
|
529
552
|
if (isPropagationStopped(event) && !noDragEventsBubbling) {
|
|
530
553
|
return;
|
|
531
554
|
}
|
|
532
555
|
|
|
556
|
+
var fileCount = files.length;
|
|
557
|
+
var isDragAccept = fileCount > 0 && allFilesAccepted({
|
|
558
|
+
files: files,
|
|
559
|
+
accept: acceptAttr,
|
|
560
|
+
minSize: minSize,
|
|
561
|
+
maxSize: maxSize,
|
|
562
|
+
multiple: multiple,
|
|
563
|
+
maxFiles: maxFiles
|
|
564
|
+
});
|
|
565
|
+
var isDragReject = fileCount > 0 && !isDragAccept;
|
|
533
566
|
dispatch({
|
|
534
|
-
|
|
567
|
+
isDragAccept: isDragAccept,
|
|
568
|
+
isDragReject: isDragReject,
|
|
535
569
|
isDragActive: true,
|
|
536
570
|
type: "setDraggedFiles"
|
|
537
571
|
});
|
|
@@ -539,9 +573,11 @@ export function useDropzone() {
|
|
|
539
573
|
if (onDragEnter) {
|
|
540
574
|
onDragEnter(event);
|
|
541
575
|
}
|
|
576
|
+
}).catch(function (e) {
|
|
577
|
+
return onErrCb(e);
|
|
542
578
|
});
|
|
543
579
|
}
|
|
544
|
-
}, [getFilesFromEvent, onDragEnter, noDragEventsBubbling]);
|
|
580
|
+
}, [getFilesFromEvent, onDragEnter, onErrCb, noDragEventsBubbling, acceptAttr, minSize, maxSize, multiple, maxFiles]);
|
|
545
581
|
var onDragOverCb = useCallback(function (event) {
|
|
546
582
|
event.preventDefault();
|
|
547
583
|
event.persist();
|
|
@@ -585,9 +621,10 @@ export function useDropzone() {
|
|
|
585
621
|
}
|
|
586
622
|
|
|
587
623
|
dispatch({
|
|
588
|
-
isDragActive: false,
|
|
589
624
|
type: "setDraggedFiles",
|
|
590
|
-
|
|
625
|
+
isDragActive: false,
|
|
626
|
+
isDragAccept: false,
|
|
627
|
+
isDragReject: false
|
|
591
628
|
});
|
|
592
629
|
|
|
593
630
|
if (isEvtWithFiles(event) && onDragLeave) {
|
|
@@ -598,7 +635,7 @@ export function useDropzone() {
|
|
|
598
635
|
var acceptedFiles = [];
|
|
599
636
|
var fileRejections = [];
|
|
600
637
|
files.forEach(function (file) {
|
|
601
|
-
var _fileAccepted = fileAccepted(file,
|
|
638
|
+
var _fileAccepted = fileAccepted(file, acceptAttr),
|
|
602
639
|
_fileAccepted2 = _slicedToArray(_fileAccepted, 2),
|
|
603
640
|
accepted = _fileAccepted2[0],
|
|
604
641
|
acceptError = _fileAccepted2[1];
|
|
@@ -656,7 +693,7 @@ export function useDropzone() {
|
|
|
656
693
|
if (acceptedFiles.length > 0 && onDropAccepted) {
|
|
657
694
|
onDropAccepted(acceptedFiles, event);
|
|
658
695
|
}
|
|
659
|
-
}, [dispatch, multiple,
|
|
696
|
+
}, [dispatch, multiple, acceptAttr, minSize, maxSize, maxFiles, onDrop, onDropAccepted, onDropRejected, validator]);
|
|
660
697
|
var onDropCb = useCallback(function (event) {
|
|
661
698
|
event.preventDefault(); // Persist here because we need the event later after getFilesFromEvent() is done
|
|
662
699
|
|
|
@@ -671,13 +708,15 @@ export function useDropzone() {
|
|
|
671
708
|
}
|
|
672
709
|
|
|
673
710
|
setFiles(files, event);
|
|
711
|
+
}).catch(function (e) {
|
|
712
|
+
return onErrCb(e);
|
|
674
713
|
});
|
|
675
714
|
}
|
|
676
715
|
|
|
677
716
|
dispatch({
|
|
678
717
|
type: "reset"
|
|
679
718
|
});
|
|
680
|
-
}, [getFilesFromEvent, setFiles, noDragEventsBubbling]); // Fn for opening the file dialog programmatically
|
|
719
|
+
}, [getFilesFromEvent, setFiles, onErrCb, noDragEventsBubbling]); // Fn for opening the file dialog programmatically
|
|
681
720
|
|
|
682
721
|
var openFileDialog = useCallback(function () {
|
|
683
722
|
// No point to use FS access APIs if context is not secure
|
|
@@ -690,7 +729,7 @@ export function useDropzone() {
|
|
|
690
729
|
|
|
691
730
|
var opts = {
|
|
692
731
|
multiple: multiple,
|
|
693
|
-
types:
|
|
732
|
+
types: pickerTypes
|
|
694
733
|
};
|
|
695
734
|
window.showOpenFilePicker(opts).then(function (handles) {
|
|
696
735
|
return getFilesFromEvent(handles);
|
|
@@ -714,6 +753,8 @@ export function useDropzone() {
|
|
|
714
753
|
inputRef.current.value = null;
|
|
715
754
|
inputRef.current.click();
|
|
716
755
|
}
|
|
756
|
+
} else {
|
|
757
|
+
onErrCb(e);
|
|
717
758
|
}
|
|
718
759
|
});
|
|
719
760
|
return;
|
|
@@ -727,7 +768,7 @@ export function useDropzone() {
|
|
|
727
768
|
inputRef.current.value = null;
|
|
728
769
|
inputRef.current.click();
|
|
729
770
|
}
|
|
730
|
-
}, [dispatch, onFileDialogOpenCb, onFileDialogCancelCb, useFsAccessApi, setFiles,
|
|
771
|
+
}, [dispatch, onFileDialogOpenCb, onFileDialogCancelCb, useFsAccessApi, setFiles, onErrCb, pickerTypes, multiple]); // Cb to open the file dialog when SPACE/ENTER occurs on the dropzone
|
|
731
772
|
|
|
732
773
|
var onKeyDownCb = useCallback(function (event) {
|
|
733
774
|
// Ignore keyboard events bubbling up the DOM tree
|
|
@@ -829,7 +870,7 @@ export function useDropzone() {
|
|
|
829
870
|
rest = _objectWithoutProperties(_ref3, _excluded4);
|
|
830
871
|
|
|
831
872
|
var inputProps = _defineProperty({
|
|
832
|
-
accept:
|
|
873
|
+
accept: acceptAttr,
|
|
833
874
|
multiple: multiple,
|
|
834
875
|
type: "file",
|
|
835
876
|
style: {
|
|
@@ -843,19 +884,7 @@ export function useDropzone() {
|
|
|
843
884
|
return _objectSpread(_objectSpread({}, inputProps), rest);
|
|
844
885
|
};
|
|
845
886
|
}, [inputRef, accept, multiple, onDropCb, disabled]);
|
|
846
|
-
var fileCount = draggedFiles.length;
|
|
847
|
-
var isDragAccept = fileCount > 0 && allFilesAccepted({
|
|
848
|
-
files: draggedFiles,
|
|
849
|
-
accept: accept,
|
|
850
|
-
minSize: minSize,
|
|
851
|
-
maxSize: maxSize,
|
|
852
|
-
multiple: multiple,
|
|
853
|
-
maxFiles: maxFiles
|
|
854
|
-
});
|
|
855
|
-
var isDragReject = fileCount > 0 && !isDragAccept;
|
|
856
887
|
return _objectSpread(_objectSpread({}, state), {}, {
|
|
857
|
-
isDragAccept: isDragAccept,
|
|
858
|
-
isDragReject: isDragReject,
|
|
859
888
|
isFocused: isFocused && !disabled,
|
|
860
889
|
getRootProps: getRootProps,
|
|
861
890
|
getInputProps: getInputProps,
|
|
@@ -864,6 +893,11 @@ export function useDropzone() {
|
|
|
864
893
|
open: composeHandler(openFileDialog)
|
|
865
894
|
});
|
|
866
895
|
}
|
|
896
|
+
/**
|
|
897
|
+
* @param {DropzoneState} state
|
|
898
|
+
* @param {{type: string} & DropzoneState} action
|
|
899
|
+
* @returns {DropzoneState}
|
|
900
|
+
*/
|
|
867
901
|
|
|
868
902
|
function reducer(state, action) {
|
|
869
903
|
/* istanbul ignore next */
|
|
@@ -889,12 +923,10 @@ function reducer(state, action) {
|
|
|
889
923
|
});
|
|
890
924
|
|
|
891
925
|
case "setDraggedFiles":
|
|
892
|
-
/* eslint no-case-declarations: 0 */
|
|
893
|
-
var isDragActive = action.isDragActive,
|
|
894
|
-
draggedFiles = action.draggedFiles;
|
|
895
926
|
return _objectSpread(_objectSpread({}, state), {}, {
|
|
896
|
-
|
|
897
|
-
|
|
927
|
+
isDragActive: action.isDragActive,
|
|
928
|
+
isDragAccept: action.isDragAccept,
|
|
929
|
+
isDragReject: action.isDragReject
|
|
898
930
|
});
|
|
899
931
|
|
|
900
932
|
case "setFiles":
|
package/dist/es/utils/index.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
function
|
|
1
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
2
2
|
|
|
3
|
-
function
|
|
3
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
|
|
5
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
6
|
+
|
|
7
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
4
8
|
|
|
5
9
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
10
|
|
|
@@ -183,25 +187,67 @@ export function canUseFileSystemAccessAPI() {
|
|
|
183
187
|
return "showOpenFilePicker" in window;
|
|
184
188
|
}
|
|
185
189
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* @param {
|
|
190
|
+
* Convert the `{accept}` dropzone prop to the
|
|
191
|
+
* `{types}` option for https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker
|
|
192
|
+
*
|
|
193
|
+
* @param {AcceptProp} accept
|
|
194
|
+
* @returns {{accept: string[]}[]}
|
|
190
195
|
*/
|
|
191
196
|
|
|
192
|
-
export function
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
197
|
+
export function pickerOptionsFromAccept(accept) {
|
|
198
|
+
if (isDefined(accept)) {
|
|
199
|
+
return Object.entries(accept).filter(function (_ref2) {
|
|
200
|
+
var _ref3 = _slicedToArray(_ref2, 2),
|
|
201
|
+
mimeType = _ref3[0],
|
|
202
|
+
ext = _ref3[1];
|
|
203
|
+
|
|
204
|
+
var ok = true;
|
|
205
|
+
|
|
206
|
+
if (!isMIMEType(mimeType)) {
|
|
207
|
+
console.warn("Skipped \"".concat(mimeType, "\" because it is not a valid MIME type. Check https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types for a list of valid MIME types."));
|
|
208
|
+
ok = false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!Array.isArray(ext) || !ext.every(isExt)) {
|
|
212
|
+
console.warn("Skipped \"".concat(mimeType, "\" because an invalid file extension was provided."));
|
|
213
|
+
ok = false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return ok;
|
|
217
|
+
}).map(function (_ref4) {
|
|
218
|
+
var _ref5 = _slicedToArray(_ref4, 2),
|
|
219
|
+
mimeType = _ref5[0],
|
|
220
|
+
ext = _ref5[1];
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
accept: _defineProperty({}, mimeType, ext)
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return accept;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Convert the `{accept}` dropzone prop to an array of MIME types/extensions.
|
|
232
|
+
* @param {AcceptProp} accept
|
|
233
|
+
* @returns {string}
|
|
234
|
+
*/
|
|
235
|
+
|
|
236
|
+
export function acceptPropAsAcceptAttr(accept) {
|
|
237
|
+
if (isDefined(accept)) {
|
|
238
|
+
return Object.entries(accept).reduce(function (a, _ref6) {
|
|
239
|
+
var _ref7 = _slicedToArray(_ref6, 2),
|
|
240
|
+
mimeType = _ref7[0],
|
|
241
|
+
ext = _ref7[1];
|
|
242
|
+
|
|
243
|
+
return [].concat(_toConsumableArray(a), [mimeType], _toConsumableArray(ext));
|
|
244
|
+
}, []) // Silently discard invalid entries as pickerOptionsFromAccept warns about these
|
|
245
|
+
.filter(function (v) {
|
|
246
|
+
return isMIMEType(v) || isExt(v);
|
|
247
|
+
}).join(",");
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return undefined;
|
|
205
251
|
}
|
|
206
252
|
/**
|
|
207
253
|
* Check if v is an exception caused by aborting a request (e.g window.showOpenFilePicker()).
|
|
@@ -224,4 +270,26 @@ export function isAbort(v) {
|
|
|
224
270
|
|
|
225
271
|
export function isSecurityError(v) {
|
|
226
272
|
return v instanceof DOMException && (v.name === "SecurityError" || v.code === v.SECURITY_ERR);
|
|
227
|
-
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Check if v is a MIME type string.
|
|
276
|
+
*
|
|
277
|
+
* See accepted format: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers.
|
|
278
|
+
*
|
|
279
|
+
* @param {string} v
|
|
280
|
+
*/
|
|
281
|
+
|
|
282
|
+
export function isMIMEType(v) {
|
|
283
|
+
return v === "audio/*" || v === "video/*" || v === "image/*" || v === "text/*" || /\w+\/[-+.\w]+/g.test(v);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Check if v is a file extension.
|
|
287
|
+
* @param {string} v
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
export function isExt(v) {
|
|
291
|
+
return /^.*\.[\w]+$/.test(v);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* @typedef {Object.<string, string[]>} AcceptProp
|
|
295
|
+
*/
|