react-dropzone 14.4.1 → 16.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.
Files changed (47) hide show
  1. package/README.md +3 -3
  2. package/dist/index.cjs +1077 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.js +1046 -2
  5. package/dist/index.js.map +1 -0
  6. package/package.json +62 -161
  7. package/src/{index.js → index.jsx} +10 -7
  8. package/typings/tests/tsconfig.json +12 -11
  9. package/.babelrc.js +0 -28
  10. package/.codeclimate.yml +0 -15
  11. package/.editorconfig +0 -13
  12. package/.eslintignore +0 -3
  13. package/.eslintrc +0 -37
  14. package/.gitpod.yml +0 -6
  15. package/.husky/commit-msg +0 -5
  16. package/.husky/pre-commit +0 -5
  17. package/.nvmrc +0 -1
  18. package/.releaserc.json +0 -27
  19. package/CHANGELOG.md +0 -6
  20. package/commitlint.config.js +0 -1
  21. package/dist/es/index.js +0 -1048
  22. package/dist/es/package.json +0 -1
  23. package/dist/es/utils/index.js +0 -366
  24. package/examples/.eslintrc +0 -5
  25. package/examples/accept/README.md +0 -144
  26. package/examples/basic/README.md +0 -70
  27. package/examples/class-component/README.md +0 -45
  28. package/examples/drag-overlay/README.md +0 -132
  29. package/examples/events/README.md +0 -164
  30. package/examples/file-dialog/README.md +0 -90
  31. package/examples/forms/README.md +0 -69
  32. package/examples/maxFiles/README.md +0 -58
  33. package/examples/no-jsx/README.md +0 -32
  34. package/examples/pintura/README.md +0 -146
  35. package/examples/plugins/README.md +0 -55
  36. package/examples/previews/README.md +0 -86
  37. package/examples/styling/README.md +0 -126
  38. package/examples/theme.css +0 -37
  39. package/examples/validator/README.md +0 -68
  40. package/rollup.config.js +0 -33
  41. package/src/.eslintrc +0 -37
  42. package/src/__snapshots__/index.spec.js.snap +0 -3
  43. package/src/index.spec.js +0 -3777
  44. package/src/utils/index.spec.js +0 -625
  45. package/styleguide.config.js +0 -107
  46. package/testSetup.js +0 -8
  47. package/typings/.eslintrc +0 -28
package/dist/es/index.js DELETED
@@ -1,1048 +0,0 @@
1
- var _excluded = ["children"],
2
- _excluded2 = ["open"],
3
- _excluded3 = ["refKey", "role", "onKeyDown", "onFocus", "onBlur", "onClick", "onDragEnter", "onDragOver", "onDragLeave", "onDrop"],
4
- _excluded4 = ["refKey", "onChange", "onClick"];
5
-
6
- function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
7
-
8
- 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."); }
9
-
10
- function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
11
-
12
- function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
13
-
14
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
15
-
16
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
17
-
18
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
19
-
20
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
21
-
22
- function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
23
-
24
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
25
-
26
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
27
-
28
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
29
-
30
- 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; }
31
-
32
- function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
33
-
34
- function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
35
-
36
- /* eslint prefer-template: 0 */
37
- import React, { forwardRef, Fragment, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef } from "react";
38
- import PropTypes from "prop-types";
39
- import { fromEvent } from "file-selector";
40
- import { acceptPropAsAcceptAttr, allFilesAccepted, composeEventHandlers, fileAccepted, fileMatchSize, canUseFileSystemAccessAPI, isAbort, isEvtWithFiles, isIeOrEdge, isPropagationStopped, isSecurityError, onDocumentDragOver, pickerOptionsFromAccept, TOO_MANY_FILES_REJECTION } from "./utils/index.js";
41
- /**
42
- * Convenience wrapper component for the `useDropzone` hook
43
- *
44
- * ```jsx
45
- * <Dropzone>
46
- * {({getRootProps, getInputProps}) => (
47
- * <div {...getRootProps()}>
48
- * <input {...getInputProps()} />
49
- * <p>Drag 'n' drop some files here, or click to select files</p>
50
- * </div>
51
- * )}
52
- * </Dropzone>
53
- * ```
54
- */
55
-
56
- var Dropzone = /*#__PURE__*/forwardRef(function (_ref, ref) {
57
- var children = _ref.children,
58
- params = _objectWithoutProperties(_ref, _excluded);
59
-
60
- var _useDropzone = useDropzone(params),
61
- open = _useDropzone.open,
62
- props = _objectWithoutProperties(_useDropzone, _excluded2);
63
-
64
- useImperativeHandle(ref, function () {
65
- return {
66
- open: open
67
- };
68
- }, [open]); // TODO: Figure out why react-styleguidist cannot create docs if we don't return a jsx element
69
-
70
- return /*#__PURE__*/React.createElement(Fragment, null, children(_objectSpread(_objectSpread({}, props), {}, {
71
- open: open
72
- })));
73
- });
74
- Dropzone.displayName = "Dropzone"; // Add default props for react-docgen
75
-
76
- var defaultProps = {
77
- disabled: false,
78
- getFilesFromEvent: fromEvent,
79
- maxSize: Infinity,
80
- minSize: 0,
81
- multiple: true,
82
- maxFiles: 0,
83
- preventDropOnDocument: true,
84
- noClick: false,
85
- noKeyboard: false,
86
- noDrag: false,
87
- noDragEventsBubbling: false,
88
- validator: null,
89
- useFsAccessApi: false,
90
- autoFocus: false
91
- };
92
- Dropzone.defaultProps = defaultProps;
93
- Dropzone.propTypes = {
94
- /**
95
- * Render function that exposes the dropzone state and prop getter fns
96
- *
97
- * @param {object} params
98
- * @param {Function} params.getRootProps Returns the props you should apply to the root drop container you render
99
- * @param {Function} params.getInputProps Returns the props you should apply to hidden file input you render
100
- * @param {Function} params.open Open the native file selection dialog
101
- * @param {boolean} params.isFocused Dropzone area is in focus
102
- * @param {boolean} params.isFileDialogActive File dialog is opened
103
- * @param {boolean} params.isDragActive Active drag is in progress
104
- * @param {boolean} params.isDragAccept Dragged files are accepted
105
- * @param {boolean} params.isDragReject Some dragged files are rejected
106
- * @param {boolean} params.isDragGlobal Files are being dragged anywhere on the document
107
- * @param {File[]} params.acceptedFiles Accepted files
108
- * @param {FileRejection[]} params.fileRejections Rejected files and why they were rejected
109
- */
110
- children: PropTypes.func,
111
-
112
- /**
113
- * Set accepted file types.
114
- * Checkout https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker types option for more information.
115
- * Keep in mind that mime type determination is not reliable across platforms. CSV files,
116
- * for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
117
- * Windows. In some cases there might not be a mime type set at all (https://github.com/react-dropzone/react-dropzone/issues/276).
118
- */
119
- accept: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.string)),
120
-
121
- /**
122
- * Allow drag 'n' drop (or selection from the file dialog) of multiple files
123
- */
124
- multiple: PropTypes.bool,
125
-
126
- /**
127
- * If false, allow dropped items to take over the current browser window
128
- */
129
- preventDropOnDocument: PropTypes.bool,
130
-
131
- /**
132
- * If true, disables click to open the native file selection dialog
133
- */
134
- noClick: PropTypes.bool,
135
-
136
- /**
137
- * If true, disables SPACE/ENTER to open the native file selection dialog.
138
- * Note that it also stops tracking the focus state.
139
- */
140
- noKeyboard: PropTypes.bool,
141
-
142
- /**
143
- * If true, disables drag 'n' drop
144
- */
145
- noDrag: PropTypes.bool,
146
-
147
- /**
148
- * If true, stops drag event propagation to parents
149
- */
150
- noDragEventsBubbling: PropTypes.bool,
151
-
152
- /**
153
- * Minimum file size (in bytes)
154
- */
155
- minSize: PropTypes.number,
156
-
157
- /**
158
- * Maximum file size (in bytes)
159
- */
160
- maxSize: PropTypes.number,
161
-
162
- /**
163
- * Maximum accepted number of files
164
- * The default value is 0 which means there is no limitation to how many files are accepted.
165
- */
166
- maxFiles: PropTypes.number,
167
-
168
- /**
169
- * Enable/disable the dropzone
170
- */
171
- disabled: PropTypes.bool,
172
-
173
- /**
174
- * Use this to provide a custom file aggregator
175
- *
176
- * @param {(DragEvent|Event|Array<FileSystemFileHandle>)} event A drag event or input change event (if files were selected via the file dialog)
177
- */
178
- getFilesFromEvent: PropTypes.func,
179
-
180
- /**
181
- * Cb for when closing the file dialog with no selection
182
- */
183
- onFileDialogCancel: PropTypes.func,
184
-
185
- /**
186
- * Cb for when opening the file dialog
187
- */
188
- onFileDialogOpen: PropTypes.func,
189
-
190
- /**
191
- * Set to true to use the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API
192
- * to open the file picker instead of using an `<input type="file">` click event.
193
- */
194
- useFsAccessApi: PropTypes.bool,
195
-
196
- /**
197
- * Set to true to focus the root element on render
198
- */
199
- autoFocus: PropTypes.bool,
200
-
201
- /**
202
- * Cb for when the `dragenter` event occurs.
203
- *
204
- * @param {DragEvent} event
205
- */
206
- onDragEnter: PropTypes.func,
207
-
208
- /**
209
- * Cb for when the `dragleave` event occurs
210
- *
211
- * @param {DragEvent} event
212
- */
213
- onDragLeave: PropTypes.func,
214
-
215
- /**
216
- * Cb for when the `dragover` event occurs
217
- *
218
- * @param {DragEvent} event
219
- */
220
- onDragOver: PropTypes.func,
221
-
222
- /**
223
- * Cb for when the `drop` event occurs.
224
- * Note that this callback is invoked after the `getFilesFromEvent` callback is done.
225
- *
226
- * Files are accepted or rejected based on the `accept`, `multiple`, `minSize` and `maxSize` props.
227
- * `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.
228
- * If `multiple` is set to false and additional files are dropped,
229
- * all files besides the first will be rejected.
230
- * Any file which does not have a size in the [`minSize`, `maxSize`] range, will be rejected as well.
231
- *
232
- * Note that the `onDrop` callback will always be invoked regardless if the dropped files were accepted or rejected.
233
- * If you'd like to react to a specific scenario, use the `onDropAccepted`/`onDropRejected` props.
234
- *
235
- * `onDrop` will provide you with an array of [File](https://developer.mozilla.org/en-US/docs/Web/API/File) objects which you can then process and send to a server.
236
- * For example, with [SuperAgent](https://github.com/visionmedia/superagent) as a http/ajax library:
237
- *
238
- * ```js
239
- * function onDrop(acceptedFiles) {
240
- * const req = request.post('/upload')
241
- * acceptedFiles.forEach(file => {
242
- * req.attach(file.name, file)
243
- * })
244
- * req.end(callback)
245
- * }
246
- * ```
247
- *
248
- * @param {File[]} acceptedFiles
249
- * @param {FileRejection[]} fileRejections
250
- * @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog)
251
- */
252
- onDrop: PropTypes.func,
253
-
254
- /**
255
- * Cb for when the `drop` event occurs.
256
- * Note that if no files are accepted, this callback is not invoked.
257
- *
258
- * @param {File[]} files
259
- * @param {(DragEvent|Event)} event
260
- */
261
- onDropAccepted: PropTypes.func,
262
-
263
- /**
264
- * Cb for when the `drop` event occurs.
265
- * Note that if no files are rejected, this callback is not invoked.
266
- *
267
- * @param {FileRejection[]} fileRejections
268
- * @param {(DragEvent|Event)} event
269
- */
270
- onDropRejected: PropTypes.func,
271
-
272
- /**
273
- * Cb for when there's some error from any of the promises.
274
- *
275
- * @param {Error} error
276
- */
277
- onError: PropTypes.func,
278
-
279
- /**
280
- * Custom validation function. It must return null if there's no errors.
281
- * @param {File} file
282
- * @returns {FileError|FileError[]|null}
283
- */
284
- validator: PropTypes.func
285
- };
286
- export default Dropzone;
287
- /**
288
- * A function that is invoked for the `dragenter`,
289
- * `dragover` and `dragleave` events.
290
- * It is not invoked if the items are not files (such as link, text, etc.).
291
- *
292
- * @callback dragCb
293
- * @param {DragEvent} event
294
- */
295
-
296
- /**
297
- * A function that is invoked for the `drop` or input change event.
298
- * It is not invoked if the items are not files (such as link, text, etc.).
299
- *
300
- * @callback dropCb
301
- * @param {File[]} acceptedFiles List of accepted files
302
- * @param {FileRejection[]} fileRejections List of rejected files and why they were rejected
303
- * @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog)
304
- */
305
-
306
- /**
307
- * A function that is invoked for the `drop` or input change event.
308
- * It is not invoked if the items are files (such as link, text, etc.).
309
- *
310
- * @callback dropAcceptedCb
311
- * @param {File[]} files List of accepted files that meet the given criteria
312
- * (`accept`, `multiple`, `minSize`, `maxSize`)
313
- * @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog)
314
- */
315
-
316
- /**
317
- * A function that is invoked for the `drop` or input change event.
318
- *
319
- * @callback dropRejectedCb
320
- * @param {File[]} files List of rejected files that do not meet the given criteria
321
- * (`accept`, `multiple`, `minSize`, `maxSize`)
322
- * @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog)
323
- */
324
-
325
- /**
326
- * A function that is used aggregate files,
327
- * in a asynchronous fashion, from drag or input change events.
328
- *
329
- * @callback getFilesFromEvent
330
- * @param {(DragEvent|Event|Array<FileSystemFileHandle>)} event A drag event or input change event (if files were selected via the file dialog)
331
- * @returns {(File[]|Promise<File[]>)}
332
- */
333
-
334
- /**
335
- * An object with the current dropzone state.
336
- *
337
- * @typedef {object} DropzoneState
338
- * @property {boolean} isFocused Dropzone area is in focus
339
- * @property {boolean} isFileDialogActive File dialog is opened
340
- * @property {boolean} isDragActive Active drag is in progress
341
- * @property {boolean} isDragAccept Dragged files are accepted
342
- * @property {boolean} isDragReject Some dragged files are rejected
343
- * @property {boolean} isDragGlobal Files are being dragged anywhere on the document
344
- * @property {File[]} acceptedFiles Accepted files
345
- * @property {FileRejection[]} fileRejections Rejected files and why they were rejected
346
- */
347
-
348
- /**
349
- * An object with the dropzone methods.
350
- *
351
- * @typedef {object} DropzoneMethods
352
- * @property {Function} getRootProps Returns the props you should apply to the root drop container you render
353
- * @property {Function} getInputProps Returns the props you should apply to hidden file input you render
354
- * @property {Function} open Open the native file selection dialog
355
- */
356
-
357
- var initialState = {
358
- isFocused: false,
359
- isFileDialogActive: false,
360
- isDragActive: false,
361
- isDragAccept: false,
362
- isDragReject: false,
363
- isDragGlobal: false,
364
- acceptedFiles: [],
365
- fileRejections: []
366
- };
367
- /**
368
- * A React hook that creates a drag 'n' drop area.
369
- *
370
- * ```jsx
371
- * function MyDropzone(props) {
372
- * const {getRootProps, getInputProps} = useDropzone({
373
- * onDrop: acceptedFiles => {
374
- * // do something with the File objects, e.g. upload to some server
375
- * }
376
- * });
377
- * return (
378
- * <div {...getRootProps()}>
379
- * <input {...getInputProps()} />
380
- * <p>Drag and drop some files here, or click to select files</p>
381
- * </div>
382
- * )
383
- * }
384
- * ```
385
- *
386
- * @function useDropzone
387
- *
388
- * @param {object} props
389
- * @param {import("./utils").AcceptProp} [props.accept] Set accepted file types.
390
- * Checkout https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker types option for more information.
391
- * Keep in mind that mime type determination is not reliable across platforms. CSV files,
392
- * for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
393
- * Windows. In some cases there might not be a mime type set at all (https://github.com/react-dropzone/react-dropzone/issues/276).
394
- * @param {boolean} [props.multiple=true] Allow drag 'n' drop (or selection from the file dialog) of multiple files
395
- * @param {boolean} [props.preventDropOnDocument=true] If false, allow dropped items to take over the current browser window
396
- * @param {boolean} [props.noClick=false] If true, disables click to open the native file selection dialog
397
- * @param {boolean} [props.noKeyboard=false] If true, disables SPACE/ENTER to open the native file selection dialog.
398
- * Note that it also stops tracking the focus state.
399
- * @param {boolean} [props.noDrag=false] If true, disables drag 'n' drop
400
- * @param {boolean} [props.noDragEventsBubbling=false] If true, stops drag event propagation to parents
401
- * @param {number} [props.minSize=0] Minimum file size (in bytes)
402
- * @param {number} [props.maxSize=Infinity] Maximum file size (in bytes)
403
- * @param {boolean} [props.disabled=false] Enable/disable the dropzone
404
- * @param {getFilesFromEvent} [props.getFilesFromEvent] Use this to provide a custom file aggregator
405
- * @param {Function} [props.onFileDialogCancel] Cb for when closing the file dialog with no selection
406
- * @param {boolean} [props.useFsAccessApi] Set to true to use the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API
407
- * to open the file picker instead of using an `<input type="file">` click event.
408
- * @param {boolean} autoFocus Set to true to auto focus the root element.
409
- * @param {Function} [props.onFileDialogOpen] Cb for when opening the file dialog
410
- * @param {dragCb} [props.onDragEnter] Cb for when the `dragenter` event occurs.
411
- * @param {dragCb} [props.onDragLeave] Cb for when the `dragleave` event occurs
412
- * @param {dragCb} [props.onDragOver] Cb for when the `dragover` event occurs
413
- * @param {dropCb} [props.onDrop] Cb for when the `drop` event occurs.
414
- * Note that this callback is invoked after the `getFilesFromEvent` callback is done.
415
- *
416
- * Files are accepted or rejected based on the `accept`, `multiple`, `minSize` and `maxSize` props.
417
- * `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).
418
- * If `multiple` is set to false and additional files are dropped,
419
- * all files besides the first will be rejected.
420
- * Any file which does not have a size in the [`minSize`, `maxSize`] range, will be rejected as well.
421
- *
422
- * Note that the `onDrop` callback will always be invoked regardless if the dropped files were accepted or rejected.
423
- * If you'd like to react to a specific scenario, use the `onDropAccepted`/`onDropRejected` props.
424
- *
425
- * `onDrop` will provide you with an array of [File](https://developer.mozilla.org/en-US/docs/Web/API/File) objects which you can then process and send to a server.
426
- * For example, with [SuperAgent](https://github.com/visionmedia/superagent) as a http/ajax library:
427
- *
428
- * ```js
429
- * function onDrop(acceptedFiles) {
430
- * const req = request.post('/upload')
431
- * acceptedFiles.forEach(file => {
432
- * req.attach(file.name, file)
433
- * })
434
- * req.end(callback)
435
- * }
436
- * ```
437
- * @param {dropAcceptedCb} [props.onDropAccepted]
438
- * @param {dropRejectedCb} [props.onDropRejected]
439
- * @param {(error: Error) => void} [props.onError]
440
- *
441
- * @returns {DropzoneState & DropzoneMethods}
442
- */
443
-
444
- export function useDropzone() {
445
- var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
446
-
447
- var _defaultProps$props = _objectSpread(_objectSpread({}, defaultProps), props),
448
- accept = _defaultProps$props.accept,
449
- disabled = _defaultProps$props.disabled,
450
- getFilesFromEvent = _defaultProps$props.getFilesFromEvent,
451
- maxSize = _defaultProps$props.maxSize,
452
- minSize = _defaultProps$props.minSize,
453
- multiple = _defaultProps$props.multiple,
454
- maxFiles = _defaultProps$props.maxFiles,
455
- onDragEnter = _defaultProps$props.onDragEnter,
456
- onDragLeave = _defaultProps$props.onDragLeave,
457
- onDragOver = _defaultProps$props.onDragOver,
458
- onDrop = _defaultProps$props.onDrop,
459
- onDropAccepted = _defaultProps$props.onDropAccepted,
460
- onDropRejected = _defaultProps$props.onDropRejected,
461
- onFileDialogCancel = _defaultProps$props.onFileDialogCancel,
462
- onFileDialogOpen = _defaultProps$props.onFileDialogOpen,
463
- useFsAccessApi = _defaultProps$props.useFsAccessApi,
464
- autoFocus = _defaultProps$props.autoFocus,
465
- preventDropOnDocument = _defaultProps$props.preventDropOnDocument,
466
- noClick = _defaultProps$props.noClick,
467
- noKeyboard = _defaultProps$props.noKeyboard,
468
- noDrag = _defaultProps$props.noDrag,
469
- noDragEventsBubbling = _defaultProps$props.noDragEventsBubbling,
470
- onError = _defaultProps$props.onError,
471
- validator = _defaultProps$props.validator;
472
-
473
- var acceptAttr = useMemo(function () {
474
- return acceptPropAsAcceptAttr(accept);
475
- }, [accept]);
476
- var pickerTypes = useMemo(function () {
477
- return pickerOptionsFromAccept(accept);
478
- }, [accept]);
479
- var onFileDialogOpenCb = useMemo(function () {
480
- return typeof onFileDialogOpen === "function" ? onFileDialogOpen : noop;
481
- }, [onFileDialogOpen]);
482
- var onFileDialogCancelCb = useMemo(function () {
483
- return typeof onFileDialogCancel === "function" ? onFileDialogCancel : noop;
484
- }, [onFileDialogCancel]);
485
- /**
486
- * @constant
487
- * @type {React.MutableRefObject<HTMLElement>}
488
- */
489
-
490
- var rootRef = useRef(null);
491
- var inputRef = useRef(null);
492
-
493
- var _useReducer = useReducer(reducer, initialState),
494
- _useReducer2 = _slicedToArray(_useReducer, 2),
495
- state = _useReducer2[0],
496
- dispatch = _useReducer2[1];
497
-
498
- var isFocused = state.isFocused,
499
- isFileDialogActive = state.isFileDialogActive;
500
- var fsAccessApiWorksRef = useRef(typeof window !== "undefined" && window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI()); // Update file dialog active state when the window is focused on
501
-
502
- var onWindowFocus = function onWindowFocus() {
503
- // Execute the timeout only if the file dialog is opened in the browser
504
- if (!fsAccessApiWorksRef.current && isFileDialogActive) {
505
- setTimeout(function () {
506
- if (inputRef.current) {
507
- var files = inputRef.current.files;
508
-
509
- if (!files.length) {
510
- dispatch({
511
- type: "closeDialog"
512
- });
513
- onFileDialogCancelCb();
514
- }
515
- }
516
- }, 300);
517
- }
518
- };
519
-
520
- useEffect(function () {
521
- window.addEventListener("focus", onWindowFocus, false);
522
- return function () {
523
- window.removeEventListener("focus", onWindowFocus, false);
524
- };
525
- }, [inputRef, isFileDialogActive, onFileDialogCancelCb, fsAccessApiWorksRef]);
526
- var dragTargetsRef = useRef([]);
527
- var globalDragTargetsRef = useRef([]);
528
-
529
- var onDocumentDrop = function onDocumentDrop(event) {
530
- if (rootRef.current && rootRef.current.contains(event.target)) {
531
- // If we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
532
- return;
533
- }
534
-
535
- event.preventDefault();
536
- dragTargetsRef.current = [];
537
- };
538
-
539
- useEffect(function () {
540
- if (preventDropOnDocument) {
541
- document.addEventListener("dragover", onDocumentDragOver, false);
542
- document.addEventListener("drop", onDocumentDrop, false);
543
- }
544
-
545
- return function () {
546
- if (preventDropOnDocument) {
547
- document.removeEventListener("dragover", onDocumentDragOver);
548
- document.removeEventListener("drop", onDocumentDrop);
549
- }
550
- };
551
- }, [rootRef, preventDropOnDocument]); // Track global drag state for document-level drag events
552
-
553
- useEffect(function () {
554
- var onDocumentDragEnter = function onDocumentDragEnter(event) {
555
- globalDragTargetsRef.current = [].concat(_toConsumableArray(globalDragTargetsRef.current), [event.target]);
556
-
557
- if (isEvtWithFiles(event)) {
558
- dispatch({
559
- isDragGlobal: true,
560
- type: "setDragGlobal"
561
- });
562
- }
563
- };
564
-
565
- var onDocumentDragLeave = function onDocumentDragLeave(event) {
566
- // Only deactivate once we've left all children
567
- globalDragTargetsRef.current = globalDragTargetsRef.current.filter(function (el) {
568
- return el !== event.target && el !== null;
569
- });
570
-
571
- if (globalDragTargetsRef.current.length > 0) {
572
- return;
573
- }
574
-
575
- dispatch({
576
- isDragGlobal: false,
577
- type: "setDragGlobal"
578
- });
579
- };
580
-
581
- var onDocumentDragEnd = function onDocumentDragEnd() {
582
- globalDragTargetsRef.current = [];
583
- dispatch({
584
- isDragGlobal: false,
585
- type: "setDragGlobal"
586
- });
587
- };
588
-
589
- var onDocumentDropGlobal = function onDocumentDropGlobal() {
590
- globalDragTargetsRef.current = [];
591
- dispatch({
592
- isDragGlobal: false,
593
- type: "setDragGlobal"
594
- });
595
- };
596
-
597
- document.addEventListener("dragenter", onDocumentDragEnter, false);
598
- document.addEventListener("dragleave", onDocumentDragLeave, false);
599
- document.addEventListener("dragend", onDocumentDragEnd, false);
600
- document.addEventListener("drop", onDocumentDropGlobal, false);
601
- return function () {
602
- document.removeEventListener("dragenter", onDocumentDragEnter);
603
- document.removeEventListener("dragleave", onDocumentDragLeave);
604
- document.removeEventListener("dragend", onDocumentDragEnd);
605
- document.removeEventListener("drop", onDocumentDropGlobal);
606
- };
607
- }, [rootRef]); // Auto focus the root when autoFocus is true
608
-
609
- useEffect(function () {
610
- if (!disabled && autoFocus && rootRef.current) {
611
- rootRef.current.focus();
612
- }
613
-
614
- return function () {};
615
- }, [rootRef, autoFocus, disabled]);
616
- var onErrCb = useCallback(function (e) {
617
- if (onError) {
618
- onError(e);
619
- } else {
620
- // Let the user know something's gone wrong if they haven't provided the onError cb.
621
- console.error(e);
622
- }
623
- }, [onError]);
624
- var onDragEnterCb = useCallback(function (event) {
625
- event.preventDefault(); // Persist here because we need the event later after getFilesFromEvent() is done
626
-
627
- event.persist();
628
- stopPropagation(event);
629
- dragTargetsRef.current = [].concat(_toConsumableArray(dragTargetsRef.current), [event.target]);
630
-
631
- if (isEvtWithFiles(event)) {
632
- Promise.resolve(getFilesFromEvent(event)).then(function (files) {
633
- if (isPropagationStopped(event) && !noDragEventsBubbling) {
634
- return;
635
- }
636
-
637
- var fileCount = files.length;
638
- var isDragAccept = fileCount > 0 && allFilesAccepted({
639
- files: files,
640
- accept: acceptAttr,
641
- minSize: minSize,
642
- maxSize: maxSize,
643
- multiple: multiple,
644
- maxFiles: maxFiles,
645
- validator: validator
646
- });
647
- var isDragReject = fileCount > 0 && !isDragAccept;
648
- dispatch({
649
- isDragAccept: isDragAccept,
650
- isDragReject: isDragReject,
651
- isDragActive: true,
652
- type: "setDraggedFiles"
653
- });
654
-
655
- if (onDragEnter) {
656
- onDragEnter(event);
657
- }
658
- }).catch(function (e) {
659
- return onErrCb(e);
660
- });
661
- }
662
- }, [getFilesFromEvent, onDragEnter, onErrCb, noDragEventsBubbling, acceptAttr, minSize, maxSize, multiple, maxFiles, validator]);
663
- var onDragOverCb = useCallback(function (event) {
664
- event.preventDefault();
665
- event.persist();
666
- stopPropagation(event);
667
- var hasFiles = isEvtWithFiles(event);
668
-
669
- if (hasFiles && event.dataTransfer) {
670
- try {
671
- event.dataTransfer.dropEffect = "copy";
672
- } catch (_unused) {}
673
- /* eslint-disable-line no-empty */
674
-
675
- }
676
-
677
- if (hasFiles && onDragOver) {
678
- onDragOver(event);
679
- }
680
-
681
- return false;
682
- }, [onDragOver, noDragEventsBubbling]);
683
- var onDragLeaveCb = useCallback(function (event) {
684
- event.preventDefault();
685
- event.persist();
686
- stopPropagation(event); // Only deactivate once the dropzone and all children have been left
687
-
688
- var targets = dragTargetsRef.current.filter(function (target) {
689
- return rootRef.current && rootRef.current.contains(target);
690
- }); // Make sure to remove a target present multiple times only once
691
- // (Firefox may fire dragenter/dragleave multiple times on the same element)
692
-
693
- var targetIdx = targets.indexOf(event.target);
694
-
695
- if (targetIdx !== -1) {
696
- targets.splice(targetIdx, 1);
697
- }
698
-
699
- dragTargetsRef.current = targets;
700
-
701
- if (targets.length > 0) {
702
- return;
703
- }
704
-
705
- dispatch({
706
- type: "setDraggedFiles",
707
- isDragActive: false,
708
- isDragAccept: false,
709
- isDragReject: false
710
- });
711
-
712
- if (isEvtWithFiles(event) && onDragLeave) {
713
- onDragLeave(event);
714
- }
715
- }, [rootRef, onDragLeave, noDragEventsBubbling]);
716
- var setFiles = useCallback(function (files, event) {
717
- var acceptedFiles = [];
718
- var fileRejections = [];
719
- files.forEach(function (file) {
720
- var _fileAccepted = fileAccepted(file, acceptAttr),
721
- _fileAccepted2 = _slicedToArray(_fileAccepted, 2),
722
- accepted = _fileAccepted2[0],
723
- acceptError = _fileAccepted2[1];
724
-
725
- var _fileMatchSize = fileMatchSize(file, minSize, maxSize),
726
- _fileMatchSize2 = _slicedToArray(_fileMatchSize, 2),
727
- sizeMatch = _fileMatchSize2[0],
728
- sizeError = _fileMatchSize2[1];
729
-
730
- var customErrors = validator ? validator(file) : null;
731
-
732
- if (accepted && sizeMatch && !customErrors) {
733
- acceptedFiles.push(file);
734
- } else {
735
- var errors = [acceptError, sizeError];
736
-
737
- if (customErrors) {
738
- errors = errors.concat(customErrors);
739
- }
740
-
741
- fileRejections.push({
742
- file: file,
743
- errors: errors.filter(function (e) {
744
- return e;
745
- })
746
- });
747
- }
748
- });
749
-
750
- if (!multiple && acceptedFiles.length > 1 || multiple && maxFiles >= 1 && acceptedFiles.length > maxFiles) {
751
- // Reject everything and empty accepted files
752
- acceptedFiles.forEach(function (file) {
753
- fileRejections.push({
754
- file: file,
755
- errors: [TOO_MANY_FILES_REJECTION]
756
- });
757
- });
758
- acceptedFiles.splice(0);
759
- }
760
-
761
- dispatch({
762
- acceptedFiles: acceptedFiles,
763
- fileRejections: fileRejections,
764
- isDragReject: fileRejections.length > 0,
765
- type: "setFiles"
766
- });
767
-
768
- if (onDrop) {
769
- onDrop(acceptedFiles, fileRejections, event);
770
- }
771
-
772
- if (fileRejections.length > 0 && onDropRejected) {
773
- onDropRejected(fileRejections, event);
774
- }
775
-
776
- if (acceptedFiles.length > 0 && onDropAccepted) {
777
- onDropAccepted(acceptedFiles, event);
778
- }
779
- }, [dispatch, multiple, acceptAttr, minSize, maxSize, maxFiles, onDrop, onDropAccepted, onDropRejected, validator]);
780
- var onDropCb = useCallback(function (event) {
781
- event.preventDefault(); // Persist here because we need the event later after getFilesFromEvent() is done
782
-
783
- event.persist();
784
- stopPropagation(event);
785
- dragTargetsRef.current = [];
786
-
787
- if (isEvtWithFiles(event)) {
788
- Promise.resolve(getFilesFromEvent(event)).then(function (files) {
789
- if (isPropagationStopped(event) && !noDragEventsBubbling) {
790
- return;
791
- }
792
-
793
- setFiles(files, event);
794
- }).catch(function (e) {
795
- return onErrCb(e);
796
- });
797
- }
798
-
799
- dispatch({
800
- type: "reset"
801
- });
802
- }, [getFilesFromEvent, setFiles, onErrCb, noDragEventsBubbling]); // Fn for opening the file dialog programmatically
803
-
804
- var openFileDialog = useCallback(function () {
805
- // No point to use FS access APIs if context is not secure
806
- // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection
807
- if (fsAccessApiWorksRef.current) {
808
- dispatch({
809
- type: "openDialog"
810
- });
811
- onFileDialogOpenCb(); // https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker
812
-
813
- var opts = {
814
- multiple: multiple,
815
- types: pickerTypes
816
- };
817
- window.showOpenFilePicker(opts).then(function (handles) {
818
- return getFilesFromEvent(handles);
819
- }).then(function (files) {
820
- setFiles(files, null);
821
- dispatch({
822
- type: "closeDialog"
823
- });
824
- }).catch(function (e) {
825
- // AbortError means the user canceled
826
- if (isAbort(e)) {
827
- onFileDialogCancelCb(e);
828
- dispatch({
829
- type: "closeDialog"
830
- });
831
- } else if (isSecurityError(e)) {
832
- fsAccessApiWorksRef.current = false; // CORS, so cannot use this API
833
- // Try using the input
834
-
835
- if (inputRef.current) {
836
- inputRef.current.value = null;
837
- inputRef.current.click();
838
- } else {
839
- onErrCb(new Error("Cannot open the file picker because the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API is not supported and no <input> was provided."));
840
- }
841
- } else {
842
- onErrCb(e);
843
- }
844
- });
845
- return;
846
- }
847
-
848
- if (inputRef.current) {
849
- dispatch({
850
- type: "openDialog"
851
- });
852
- onFileDialogOpenCb();
853
- inputRef.current.value = null;
854
- inputRef.current.click();
855
- }
856
- }, [dispatch, onFileDialogOpenCb, onFileDialogCancelCb, useFsAccessApi, setFiles, onErrCb, pickerTypes, multiple]); // Cb to open the file dialog when SPACE/ENTER occurs on the dropzone
857
-
858
- var onKeyDownCb = useCallback(function (event) {
859
- // Ignore keyboard events bubbling up the DOM tree
860
- if (!rootRef.current || !rootRef.current.isEqualNode(event.target)) {
861
- return;
862
- }
863
-
864
- if (event.key === " " || event.key === "Enter" || event.keyCode === 32 || event.keyCode === 13) {
865
- event.preventDefault();
866
- openFileDialog();
867
- }
868
- }, [rootRef, openFileDialog]); // Update focus state for the dropzone
869
-
870
- var onFocusCb = useCallback(function () {
871
- dispatch({
872
- type: "focus"
873
- });
874
- }, []);
875
- var onBlurCb = useCallback(function () {
876
- dispatch({
877
- type: "blur"
878
- });
879
- }, []); // Cb to open the file dialog when click occurs on the dropzone
880
-
881
- var onClickCb = useCallback(function () {
882
- if (noClick) {
883
- return;
884
- } // In IE11/Edge the file-browser dialog is blocking, therefore, use setTimeout()
885
- // to ensure React can handle state changes
886
- // See: https://github.com/react-dropzone/react-dropzone/issues/450
887
-
888
-
889
- if (isIeOrEdge()) {
890
- setTimeout(openFileDialog, 0);
891
- } else {
892
- openFileDialog();
893
- }
894
- }, [noClick, openFileDialog]);
895
-
896
- var composeHandler = function composeHandler(fn) {
897
- return disabled ? null : fn;
898
- };
899
-
900
- var composeKeyboardHandler = function composeKeyboardHandler(fn) {
901
- return noKeyboard ? null : composeHandler(fn);
902
- };
903
-
904
- var composeDragHandler = function composeDragHandler(fn) {
905
- return noDrag ? null : composeHandler(fn);
906
- };
907
-
908
- var stopPropagation = function stopPropagation(event) {
909
- if (noDragEventsBubbling) {
910
- event.stopPropagation();
911
- }
912
- };
913
-
914
- var getRootProps = useMemo(function () {
915
- return function () {
916
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
917
- _ref2$refKey = _ref2.refKey,
918
- refKey = _ref2$refKey === void 0 ? "ref" : _ref2$refKey,
919
- role = _ref2.role,
920
- onKeyDown = _ref2.onKeyDown,
921
- onFocus = _ref2.onFocus,
922
- onBlur = _ref2.onBlur,
923
- onClick = _ref2.onClick,
924
- onDragEnter = _ref2.onDragEnter,
925
- onDragOver = _ref2.onDragOver,
926
- onDragLeave = _ref2.onDragLeave,
927
- onDrop = _ref2.onDrop,
928
- rest = _objectWithoutProperties(_ref2, _excluded3);
929
-
930
- return _objectSpread(_objectSpread(_defineProperty({
931
- onKeyDown: composeKeyboardHandler(composeEventHandlers(onKeyDown, onKeyDownCb)),
932
- onFocus: composeKeyboardHandler(composeEventHandlers(onFocus, onFocusCb)),
933
- onBlur: composeKeyboardHandler(composeEventHandlers(onBlur, onBlurCb)),
934
- onClick: composeHandler(composeEventHandlers(onClick, onClickCb)),
935
- onDragEnter: composeDragHandler(composeEventHandlers(onDragEnter, onDragEnterCb)),
936
- onDragOver: composeDragHandler(composeEventHandlers(onDragOver, onDragOverCb)),
937
- onDragLeave: composeDragHandler(composeEventHandlers(onDragLeave, onDragLeaveCb)),
938
- onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),
939
- role: typeof role === "string" && role !== "" ? role : "presentation"
940
- }, refKey, rootRef), !disabled && !noKeyboard ? {
941
- tabIndex: 0
942
- } : {}), rest);
943
- };
944
- }, [rootRef, onKeyDownCb, onFocusCb, onBlurCb, onClickCb, onDragEnterCb, onDragOverCb, onDragLeaveCb, onDropCb, noKeyboard, noDrag, disabled]);
945
- var onInputElementClick = useCallback(function (event) {
946
- event.stopPropagation();
947
- }, []);
948
- var getInputProps = useMemo(function () {
949
- return function () {
950
- var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
951
- _ref3$refKey = _ref3.refKey,
952
- refKey = _ref3$refKey === void 0 ? "ref" : _ref3$refKey,
953
- onChange = _ref3.onChange,
954
- onClick = _ref3.onClick,
955
- rest = _objectWithoutProperties(_ref3, _excluded4);
956
-
957
- var inputProps = _defineProperty({
958
- accept: acceptAttr,
959
- multiple: multiple,
960
- type: "file",
961
- style: {
962
- border: 0,
963
- clip: "rect(0, 0, 0, 0)",
964
- clipPath: "inset(50%)",
965
- height: "1px",
966
- margin: "0 -1px -1px 0",
967
- overflow: "hidden",
968
- padding: 0,
969
- position: "absolute",
970
- width: "1px",
971
- whiteSpace: "nowrap"
972
- },
973
- onChange: composeHandler(composeEventHandlers(onChange, onDropCb)),
974
- onClick: composeHandler(composeEventHandlers(onClick, onInputElementClick)),
975
- tabIndex: -1
976
- }, refKey, inputRef);
977
-
978
- return _objectSpread(_objectSpread({}, inputProps), rest);
979
- };
980
- }, [inputRef, accept, multiple, onDropCb, disabled]);
981
- return _objectSpread(_objectSpread({}, state), {}, {
982
- isFocused: isFocused && !disabled,
983
- getRootProps: getRootProps,
984
- getInputProps: getInputProps,
985
- rootRef: rootRef,
986
- inputRef: inputRef,
987
- open: composeHandler(openFileDialog)
988
- });
989
- }
990
- /**
991
- * @param {DropzoneState} state
992
- * @param {{type: string} & DropzoneState} action
993
- * @returns {DropzoneState}
994
- */
995
-
996
- function reducer(state, action) {
997
- /* istanbul ignore next */
998
- switch (action.type) {
999
- case "focus":
1000
- return _objectSpread(_objectSpread({}, state), {}, {
1001
- isFocused: true
1002
- });
1003
-
1004
- case "blur":
1005
- return _objectSpread(_objectSpread({}, state), {}, {
1006
- isFocused: false
1007
- });
1008
-
1009
- case "openDialog":
1010
- return _objectSpread(_objectSpread({}, initialState), {}, {
1011
- isFileDialogActive: true
1012
- });
1013
-
1014
- case "closeDialog":
1015
- return _objectSpread(_objectSpread({}, state), {}, {
1016
- isFileDialogActive: false
1017
- });
1018
-
1019
- case "setDraggedFiles":
1020
- return _objectSpread(_objectSpread({}, state), {}, {
1021
- isDragActive: action.isDragActive,
1022
- isDragAccept: action.isDragAccept,
1023
- isDragReject: action.isDragReject
1024
- });
1025
-
1026
- case "setFiles":
1027
- return _objectSpread(_objectSpread({}, state), {}, {
1028
- acceptedFiles: action.acceptedFiles,
1029
- fileRejections: action.fileRejections,
1030
- isDragReject: action.isDragReject
1031
- });
1032
-
1033
- case "setDragGlobal":
1034
- return _objectSpread(_objectSpread({}, state), {}, {
1035
- isDragGlobal: action.isDragGlobal
1036
- });
1037
-
1038
- case "reset":
1039
- return _objectSpread({}, initialState);
1040
-
1041
- default:
1042
- return state;
1043
- }
1044
- }
1045
-
1046
- function noop() {}
1047
-
1048
- export { ErrorCode } from "./utils/index.js";