react-dropzone 15.0.0 → 17.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 +129 -114
- package/dist/index.cjs +685 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +117 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.js +656 -2
- package/dist/index.js.map +1 -0
- package/package.json +76 -177
- package/src/index.tsx +774 -0
- package/src/utils/index.ts +305 -0
- package/.babelrc.js +0 -28
- package/.codeclimate.yml +0 -15
- package/.editorconfig +0 -13
- package/.eslintignore +0 -3
- package/.eslintrc +0 -37
- package/.gitpod.yml +0 -6
- package/.husky/commit-msg +0 -5
- package/.husky/pre-commit +0 -5
- package/.nvmrc +0 -1
- package/.releaserc.json +0 -27
- package/CHANGELOG.md +0 -9
- package/commitlint.config.js +0 -1
- package/dist/es/index.js +0 -1051
- package/dist/es/package.json +0 -1
- package/dist/es/utils/index.js +0 -366
- package/examples/.eslintrc +0 -5
- package/examples/accept/README.md +0 -144
- package/examples/basic/README.md +0 -70
- package/examples/class-component/README.md +0 -45
- package/examples/drag-overlay/README.md +0 -132
- package/examples/events/README.md +0 -164
- package/examples/file-dialog/README.md +0 -90
- package/examples/forms/README.md +0 -69
- package/examples/maxFiles/README.md +0 -58
- package/examples/no-jsx/README.md +0 -32
- package/examples/pintura/README.md +0 -146
- package/examples/plugins/README.md +0 -55
- package/examples/previews/README.md +0 -86
- package/examples/styling/README.md +0 -126
- package/examples/theme.css +0 -37
- package/examples/validator/README.md +0 -68
- package/rollup.config.js +0 -33
- package/src/.eslintrc +0 -37
- package/src/__snapshots__/index.spec.js.snap +0 -3
- package/src/index.js +0 -1103
- package/src/index.spec.js +0 -3838
- package/src/utils/index.js +0 -362
- package/src/utils/index.spec.js +0 -625
- package/styleguide.config.js +0 -107
- package/testSetup.js +0 -8
- package/typings/.eslintrc +0 -28
- package/typings/react-dropzone.d.ts +0 -102
- package/typings/tests/accept.tsx +0 -54
- package/typings/tests/all.tsx +0 -46
- package/typings/tests/basic.tsx +0 -53
- package/typings/tests/events.tsx +0 -31
- package/typings/tests/file-dialog.tsx +0 -20
- package/typings/tests/hook.tsx +0 -15
- package/typings/tests/plugin.tsx +0 -87
- package/typings/tests/refs.tsx +0 -18
- package/typings/tests/tsconfig.json +0 -22
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
3
|
# react-dropzone
|
|
4
|
+
|
|
4
5
|
[](https://www.npmjs.com/package/react-dropzone)
|
|
5
6
|

|
|
6
7
|
[](https://codecov.io/gh/react-dropzone/react-dropzone)
|
|
@@ -13,49 +14,48 @@ Simple React hook to create a HTML5-compliant drag'n'drop zone for files.
|
|
|
13
14
|
|
|
14
15
|
Documentation and examples at https://react-dropzone.js.org. Source code at https://github.com/react-dropzone/react-dropzone/.
|
|
15
16
|
|
|
16
|
-
|
|
17
17
|
## Installation
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
Install it from npm. `react-dropzone` ships as ESM and CommonJS with TypeScript types included, and works with any modern bundler ([Vite](https://vite.dev/), [webpack](https://webpack.js.org/), [Rspack](https://rspack.rs/), etc.).
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
|
-
npm install
|
|
22
|
+
npm install react-dropzone
|
|
22
23
|
```
|
|
24
|
+
|
|
23
25
|
or:
|
|
26
|
+
|
|
24
27
|
```bash
|
|
25
28
|
yarn add react-dropzone
|
|
26
29
|
```
|
|
27
30
|
|
|
28
|
-
|
|
29
31
|
## Usage
|
|
32
|
+
|
|
30
33
|
You can either use the hook:
|
|
31
34
|
|
|
32
35
|
```jsx static
|
|
33
|
-
import React, {useCallback} from
|
|
34
|
-
import {useDropzone} from
|
|
36
|
+
import React, {useCallback} from "react";
|
|
37
|
+
import {useDropzone} from "react-dropzone";
|
|
35
38
|
|
|
36
39
|
function MyDropzone() {
|
|
37
40
|
const onDrop = useCallback(acceptedFiles => {
|
|
38
41
|
// Do something with the files
|
|
39
|
-
}, [])
|
|
40
|
-
const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop})
|
|
42
|
+
}, []);
|
|
43
|
+
const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop});
|
|
41
44
|
|
|
42
45
|
return (
|
|
43
46
|
<div {...getRootProps()}>
|
|
44
47
|
<input {...getInputProps()} />
|
|
45
|
-
{
|
|
46
|
-
isDragActive ?
|
|
47
|
-
<p>Drop the files here ...</p> :
|
|
48
|
-
<p>Drag 'n' drop some files here, or click to select files</p>
|
|
49
|
-
}
|
|
48
|
+
{isDragActive ? <p>Drop the files here ...</p> : <p>Drag 'n' drop some files here, or click to select files</p>}
|
|
50
49
|
</div>
|
|
51
|
-
)
|
|
50
|
+
);
|
|
52
51
|
}
|
|
53
52
|
```
|
|
54
53
|
|
|
55
54
|
Or the wrapper component for the hook:
|
|
55
|
+
|
|
56
56
|
```jsx static
|
|
57
|
-
import React from
|
|
58
|
-
import Dropzone from
|
|
57
|
+
import React from "react";
|
|
58
|
+
import Dropzone from "react-dropzone";
|
|
59
59
|
|
|
60
60
|
<Dropzone onDrop={acceptedFiles => console.log(acceptedFiles)}>
|
|
61
61
|
{({getRootProps, getInputProps}) => (
|
|
@@ -66,71 +66,72 @@ import Dropzone from 'react-dropzone'
|
|
|
66
66
|
</div>
|
|
67
67
|
</section>
|
|
68
68
|
)}
|
|
69
|
-
</Dropzone
|
|
69
|
+
</Dropzone>;
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
If you want to access file contents you have to use the [FileReader API](https://developer.mozilla.org/en-US/docs/Web/API/FileReader):
|
|
73
73
|
|
|
74
74
|
```jsx static
|
|
75
|
-
import React, {useCallback} from
|
|
76
|
-
import {useDropzone} from
|
|
75
|
+
import React, {useCallback} from "react";
|
|
76
|
+
import {useDropzone} from "react-dropzone";
|
|
77
77
|
|
|
78
78
|
function MyDropzone() {
|
|
79
|
-
const onDrop = useCallback(
|
|
80
|
-
acceptedFiles.forEach(
|
|
81
|
-
const reader = new FileReader()
|
|
79
|
+
const onDrop = useCallback(acceptedFiles => {
|
|
80
|
+
acceptedFiles.forEach(file => {
|
|
81
|
+
const reader = new FileReader();
|
|
82
82
|
|
|
83
|
-
reader.onabort = () => console.log(
|
|
84
|
-
reader.onerror = () => console.log(
|
|
83
|
+
reader.onabort = () => console.log("file reading was aborted");
|
|
84
|
+
reader.onerror = () => console.log("file reading has failed");
|
|
85
85
|
reader.onload = () => {
|
|
86
|
-
|
|
87
|
-
const binaryStr = reader.result
|
|
88
|
-
console.log(binaryStr)
|
|
89
|
-
}
|
|
90
|
-
reader.readAsArrayBuffer(file)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const {getRootProps, getInputProps} = useDropzone({onDrop})
|
|
86
|
+
// Do whatever you want with the file contents
|
|
87
|
+
const binaryStr = reader.result;
|
|
88
|
+
console.log(binaryStr);
|
|
89
|
+
};
|
|
90
|
+
reader.readAsArrayBuffer(file);
|
|
91
|
+
});
|
|
92
|
+
}, []);
|
|
93
|
+
const {getRootProps, getInputProps} = useDropzone({onDrop});
|
|
95
94
|
|
|
96
95
|
return (
|
|
97
96
|
<div {...getRootProps()}>
|
|
98
97
|
<input {...getInputProps()} />
|
|
99
98
|
<p>Drag 'n' drop some files here, or click to select files</p>
|
|
100
99
|
</div>
|
|
101
|
-
)
|
|
100
|
+
);
|
|
102
101
|
}
|
|
103
102
|
```
|
|
104
103
|
|
|
105
|
-
|
|
106
104
|
## Dropzone Props Getters
|
|
105
|
+
|
|
107
106
|
The dropzone property getters are just two functions that return objects with properties which you need to use to create the drag 'n' drop zone.
|
|
108
107
|
The root properties can be applied to whatever element you want, whereas the input properties must be applied to an `<input>`:
|
|
108
|
+
|
|
109
109
|
```jsx static
|
|
110
|
-
import React from
|
|
111
|
-
import {useDropzone} from
|
|
110
|
+
import React from "react";
|
|
111
|
+
import {useDropzone} from "react-dropzone";
|
|
112
112
|
|
|
113
113
|
function MyDropzone() {
|
|
114
|
-
const {getRootProps, getInputProps} = useDropzone()
|
|
114
|
+
const {getRootProps, getInputProps} = useDropzone();
|
|
115
115
|
|
|
116
116
|
return (
|
|
117
117
|
<div {...getRootProps()}>
|
|
118
118
|
<input {...getInputProps()} />
|
|
119
119
|
<p>Drag 'n' drop some files here, or click to select files</p>
|
|
120
120
|
</div>
|
|
121
|
-
)
|
|
121
|
+
);
|
|
122
122
|
}
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
Note that whatever other props you want to add to the element where the props from `getRootProps()` are set, you should always pass them through that function rather than applying them on the element itself.
|
|
126
126
|
This is in order to avoid your props being overridden (or overriding the props returned by `getRootProps()`):
|
|
127
|
+
|
|
127
128
|
```jsx static
|
|
128
129
|
<div
|
|
129
130
|
{...getRootProps({
|
|
130
131
|
onClick: event => console.log(event),
|
|
131
|
-
role:
|
|
132
|
-
|
|
133
|
-
...
|
|
132
|
+
role: "button",
|
|
133
|
+
"aria-label": "drag and drop area"
|
|
134
|
+
// ...and any other props
|
|
134
135
|
})}
|
|
135
136
|
/>
|
|
136
137
|
```
|
|
@@ -138,57 +139,62 @@ This is in order to avoid your props being overridden (or overriding the props r
|
|
|
138
139
|
In the example above, the provided `{onClick}` handler will be invoked before the internal one, therefore, internal callbacks can be prevented by simply using [stopPropagation](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation).
|
|
139
140
|
See [Events](https://react-dropzone.js.org#events) for more examples.
|
|
140
141
|
|
|
141
|
-
|
|
142
|
+
_Important_: if you omit rendering an `<input>` and/or binding the props from `getInputProps()`, opening a file dialog will not be possible.
|
|
142
143
|
|
|
143
144
|
## Refs
|
|
145
|
+
|
|
144
146
|
Both `getRootProps` and `getInputProps` accept a custom `refKey` (defaults to `ref`) as one of the attributes passed down in the parameter.
|
|
145
147
|
|
|
146
148
|
This can be useful when the element you're trying to apply the props from either one of those fns does not expose a reference to the element, e.g:
|
|
147
149
|
|
|
148
150
|
```jsx static
|
|
149
|
-
import React from
|
|
150
|
-
import {useDropzone} from
|
|
151
|
+
import React from "react";
|
|
152
|
+
import {useDropzone} from "react-dropzone";
|
|
151
153
|
// NOTE: After v4.0.0, styled components exposes a ref using forwardRef,
|
|
152
154
|
// therefore, no need for using innerRef as refKey
|
|
153
|
-
import styled from
|
|
155
|
+
import styled from "styled-components";
|
|
154
156
|
|
|
155
157
|
const StyledDiv = styled.div`
|
|
156
158
|
// Some styling here
|
|
157
|
-
|
|
159
|
+
`;
|
|
158
160
|
function Example() {
|
|
159
|
-
const {getRootProps, getInputProps} = useDropzone()
|
|
160
|
-
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
const {getRootProps, getInputProps} = useDropzone();
|
|
162
|
+
return (
|
|
163
|
+
<StyledDiv {...getRootProps({refKey: "innerRef"})}>
|
|
164
|
+
<input {...getInputProps()} />
|
|
165
|
+
<p>Drag 'n' drop some files here, or click to select files</p>
|
|
166
|
+
</StyledDiv>
|
|
167
|
+
);
|
|
164
168
|
}
|
|
165
169
|
```
|
|
166
170
|
|
|
167
171
|
If you're working with [Material UI v4](https://v4.mui.com/) and would like to apply the root props on some component that does not expose a ref, use [RootRef](https://v4.mui.com/api/root-ref/):
|
|
168
172
|
|
|
169
173
|
```jsx static
|
|
170
|
-
import React from
|
|
171
|
-
import {useDropzone} from
|
|
172
|
-
import RootRef from
|
|
174
|
+
import React from "react";
|
|
175
|
+
import {useDropzone} from "react-dropzone";
|
|
176
|
+
import RootRef from "@material-ui/core/RootRef";
|
|
173
177
|
|
|
174
178
|
function PaperDropzone() {
|
|
175
|
-
const {getRootProps, getInputProps} = useDropzone()
|
|
176
|
-
const {ref, ...rootProps} = getRootProps()
|
|
179
|
+
const {getRootProps, getInputProps} = useDropzone();
|
|
180
|
+
const {ref, ...rootProps} = getRootProps();
|
|
177
181
|
|
|
178
|
-
|
|
179
|
-
<
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
return (
|
|
183
|
+
<RootRef rootRef={ref}>
|
|
184
|
+
<Paper {...rootProps}>
|
|
185
|
+
<input {...getInputProps()} />
|
|
186
|
+
<p>Drag 'n' drop some files here, or click to select files</p>
|
|
187
|
+
</Paper>
|
|
188
|
+
</RootRef>
|
|
189
|
+
);
|
|
184
190
|
}
|
|
185
191
|
```
|
|
186
192
|
|
|
187
193
|
**IMPORTANT**: do not set the `ref` prop on the elements where `getRootProps()`/`getInputProps()` props are set, instead, get the refs from the hook itself:
|
|
188
194
|
|
|
189
195
|
```jsx static
|
|
190
|
-
import React from
|
|
191
|
-
import {useDropzone} from
|
|
196
|
+
import React from "react";
|
|
197
|
+
import {useDropzone} from "react-dropzone";
|
|
192
198
|
|
|
193
199
|
function Refs() {
|
|
194
200
|
const {
|
|
@@ -196,21 +202,23 @@ function Refs() {
|
|
|
196
202
|
getInputProps,
|
|
197
203
|
rootRef, // Ref to the `<div>`
|
|
198
204
|
inputRef // Ref to the `<input>`
|
|
199
|
-
} = useDropzone()
|
|
200
|
-
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
205
|
+
} = useDropzone();
|
|
206
|
+
return (
|
|
207
|
+
<div {...getRootProps()}>
|
|
208
|
+
<input {...getInputProps()} />
|
|
209
|
+
<p>Drag 'n' drop some files here, or click to select files</p>
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
204
212
|
}
|
|
205
213
|
```
|
|
206
214
|
|
|
207
215
|
If you're using the `<Dropzone>` component, though, you can set the `ref` prop on the component itself which will expose the `{open}` prop that can be used to open the file dialog programmatically:
|
|
208
216
|
|
|
209
217
|
```jsx static
|
|
210
|
-
import React, {createRef} from
|
|
211
|
-
import Dropzone from
|
|
218
|
+
import React, {createRef} from "react";
|
|
219
|
+
import Dropzone from "react-dropzone";
|
|
212
220
|
|
|
213
|
-
const dropzoneRef = createRef()
|
|
221
|
+
const dropzoneRef = createRef();
|
|
214
222
|
|
|
215
223
|
<Dropzone ref={dropzoneRef}>
|
|
216
224
|
{({getRootProps, getInputProps}) => (
|
|
@@ -219,101 +227,103 @@ const dropzoneRef = createRef()
|
|
|
219
227
|
<p>Drag 'n' drop some files here, or click to select files</p>
|
|
220
228
|
</div>
|
|
221
229
|
)}
|
|
222
|
-
</Dropzone
|
|
230
|
+
</Dropzone>;
|
|
223
231
|
|
|
224
|
-
dropzoneRef.open()
|
|
232
|
+
dropzoneRef.open();
|
|
225
233
|
```
|
|
226
234
|
|
|
227
|
-
|
|
228
235
|
## Testing
|
|
236
|
+
|
|
229
237
|
`react-dropzone` makes some of its drag 'n' drop callbacks asynchronous to enable promise based `getFilesFromEvent()` functions. In order to test components that use this library, you need to use the [react-testing-library](https://github.com/testing-library/react-testing-library):
|
|
238
|
+
|
|
230
239
|
```js static
|
|
231
|
-
import React from
|
|
232
|
-
import Dropzone from
|
|
233
|
-
import {act, fireEvent, render} from
|
|
240
|
+
import React from "react";
|
|
241
|
+
import Dropzone from "react-dropzone";
|
|
242
|
+
import {act, fireEvent, render} from "@testing-library/react";
|
|
234
243
|
|
|
235
|
-
test(
|
|
236
|
-
const file = new File([
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const data = mockData([file])
|
|
240
|
-
const onDragEnter = jest.fn()
|
|
244
|
+
test("invoke onDragEnter when dragenter event occurs", async () => {
|
|
245
|
+
const file = new File([JSON.stringify({ping: true})], "ping.json", {type: "application/json"});
|
|
246
|
+
const data = mockData([file]);
|
|
247
|
+
const onDragEnter = jest.fn();
|
|
241
248
|
|
|
242
249
|
const ui = (
|
|
243
250
|
<Dropzone onDragEnter={onDragEnter}>
|
|
244
|
-
{({
|
|
251
|
+
{({getRootProps, getInputProps}) => (
|
|
245
252
|
<div {...getRootProps()}>
|
|
246
253
|
<input {...getInputProps()} />
|
|
247
254
|
</div>
|
|
248
255
|
)}
|
|
249
256
|
</Dropzone>
|
|
250
|
-
)
|
|
251
|
-
const { container } = render(ui)
|
|
252
|
-
|
|
253
|
-
await act(
|
|
254
|
-
() => fireEvent.dragEnter(
|
|
255
|
-
container.querySelector('div'),
|
|
256
|
-
data,
|
|
257
|
-
)
|
|
258
257
|
);
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
const {container} = render(ui);
|
|
259
|
+
|
|
260
|
+
await act(() => fireEvent.dragEnter(container.querySelector("div"), data));
|
|
261
|
+
expect(onDragEnter).toHaveBeenCalled();
|
|
262
|
+
});
|
|
261
263
|
|
|
262
264
|
function mockData(files) {
|
|
263
265
|
return {
|
|
264
266
|
dataTransfer: {
|
|
265
267
|
files,
|
|
266
268
|
items: files.map(file => ({
|
|
267
|
-
kind:
|
|
269
|
+
kind: "file",
|
|
268
270
|
type: file.type,
|
|
269
271
|
getAsFile: () => file
|
|
270
272
|
})),
|
|
271
|
-
types: [
|
|
273
|
+
types: ["Files"]
|
|
272
274
|
}
|
|
273
|
-
}
|
|
275
|
+
};
|
|
274
276
|
}
|
|
275
277
|
```
|
|
276
278
|
|
|
277
279
|
**NOTE**: using [Enzyme](https://airbnb.io/enzyme) for testing is not supported at the moment, see [#2011](https://github.com/airbnb/enzyme/issues/2011).
|
|
278
280
|
|
|
279
|
-
More examples for this can be found in `react-dropzone`'s own [test suites](https://github.com/react-dropzone/react-dropzone/blob/master/src/index.spec.
|
|
281
|
+
More examples for this can be found in `react-dropzone`'s own [test suites](https://github.com/react-dropzone/react-dropzone/blob/master/src/index.spec.tsx).
|
|
280
282
|
|
|
281
283
|
## Caveats
|
|
284
|
+
|
|
282
285
|
### Required React Version
|
|
283
|
-
|
|
286
|
+
|
|
287
|
+
React [18](https://react.dev/blog/2022/03/29/react-v18) or above is required because we use [hooks](https://react.dev/reference/react/hooks) (the lib itself is a hook).
|
|
284
288
|
|
|
285
289
|
### File Paths
|
|
290
|
+
|
|
286
291
|
Files returned by the hook or passed as arg to the `onDrop` cb won't have the properties `path` or `fullPath`.
|
|
287
292
|
For more inf check [this SO question](https://stackoverflow.com/a/23005925/2275818) and [this issue](https://github.com/react-dropzone/react-dropzone/issues/477).
|
|
288
293
|
|
|
289
294
|
### Not a File Uploader
|
|
295
|
+
|
|
290
296
|
This lib is not a file uploader; as such, it does not process files or provide any way to make HTTP requests to some server; if you're looking for that, checkout [filepond](https://pqina.nl/filepond) or [uppy.io](https://uppy.io/).
|
|
291
297
|
|
|
292
298
|
### Using \<label\> as Root
|
|
299
|
+
|
|
293
300
|
If you use [\<label\>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) as the root element, the file dialog will be opened twice; see [#1107](https://github.com/react-dropzone/react-dropzone/issues/1107) why. To avoid this, use `noClick`:
|
|
301
|
+
|
|
294
302
|
```jsx static
|
|
295
|
-
import React, {useCallback} from
|
|
296
|
-
import {useDropzone} from
|
|
303
|
+
import React, {useCallback} from "react";
|
|
304
|
+
import {useDropzone} from "react-dropzone";
|
|
297
305
|
|
|
298
306
|
function MyDropzone() {
|
|
299
|
-
const {getRootProps, getInputProps} = useDropzone({noClick: true})
|
|
307
|
+
const {getRootProps, getInputProps} = useDropzone({noClick: true});
|
|
300
308
|
|
|
301
309
|
return (
|
|
302
310
|
<label {...getRootProps()}>
|
|
303
311
|
<input {...getInputProps()} />
|
|
304
312
|
</label>
|
|
305
|
-
)
|
|
313
|
+
);
|
|
306
314
|
}
|
|
307
315
|
```
|
|
308
316
|
|
|
309
317
|
### Using open() on Click
|
|
318
|
+
|
|
310
319
|
If you bind a click event on an inner element and use `open()`, it will trigger a click on the root element too, resulting in the file dialog opening twice. To prevent this, use the `noClick` on the root:
|
|
320
|
+
|
|
311
321
|
```jsx static
|
|
312
|
-
import React, {useCallback} from
|
|
313
|
-
import {useDropzone} from
|
|
322
|
+
import React, {useCallback} from "react";
|
|
323
|
+
import {useDropzone} from "react-dropzone";
|
|
314
324
|
|
|
315
325
|
function MyDropzone() {
|
|
316
|
-
const {getRootProps, getInputProps, open} = useDropzone({noClick: true})
|
|
326
|
+
const {getRootProps, getInputProps, open} = useDropzone({noClick: true});
|
|
317
327
|
|
|
318
328
|
return (
|
|
319
329
|
<div {...getRootProps()}>
|
|
@@ -322,18 +332,19 @@ function MyDropzone() {
|
|
|
322
332
|
Open
|
|
323
333
|
</button>
|
|
324
334
|
</div>
|
|
325
|
-
)
|
|
335
|
+
);
|
|
326
336
|
}
|
|
327
337
|
```
|
|
328
338
|
|
|
329
339
|
### File Dialog Cancel Callback
|
|
340
|
+
|
|
330
341
|
The `onFileDialogCancel()` cb is unstable in most browsers, meaning, there's a good chance of it being triggered even though you have selected files.
|
|
331
342
|
|
|
332
343
|
We rely on using a timeout of `300ms` after the window is focused (the window `onfocus` event is triggered when the file select dialog is closed) to check if any files were selected and trigger `onFileDialogCancel` if none were selected.
|
|
333
344
|
|
|
334
345
|
As one can imagine, this doesn't really work if there's a lot of files or large files as by the time we trigger the check, the browser is still processing the files and no `onchange` events are triggered yet on the input. Check [#1031](https://github.com/react-dropzone/react-dropzone/issues/1031) for more info.
|
|
335
346
|
|
|
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.
|
|
347
|
+
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.
|
|
337
348
|
|
|
338
349
|
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).
|
|
339
350
|
|
|
@@ -348,23 +359,25 @@ What this essentially does is that it will use the [showOpenFilePicker](https://
|
|
|
348
359
|
In contrast, the traditional way (when the `useFsAccessApi` is not set to `true` or not specified) uses an `<input type="file">` (see [docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file)) on which a click event is triggered.
|
|
349
360
|
|
|
350
361
|
With the use of the file system access API enabled, there's a couple of caveats to keep in mind:
|
|
362
|
+
|
|
351
363
|
1. The users will not be able to select directories
|
|
352
364
|
2. It requires the app to run in a [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)
|
|
353
365
|
3. In [Electron](https://www.electronjs.org/), the path may not be set (see [#1249](https://github.com/react-dropzone/react-dropzone/issues/1249))
|
|
354
366
|
|
|
355
367
|
## Supported Browsers
|
|
356
|
-
We use [browserslist](https://github.com/browserslist/browserslist) config to state the browser support for this lib, so check it out on [browserslist.dev](https://browserslist.dev/?q=ZGVmYXVsdHM%3D).
|
|
357
368
|
|
|
369
|
+
We use [browserslist](https://github.com/browserslist/browserslist) config to state the browser support for this lib, so check it out on [browserslist.dev](https://browserslist.dev/?q=ZGVmYXVsdHM%3D).
|
|
358
370
|
|
|
359
371
|
## Need image editing?
|
|
372
|
+
|
|
360
373
|
React Dropzone integrates perfectly with [Pintura Image Editor](https://pqina.nl/pintura/?ref=react-dropzone), creating a modern image editing experience. Pintura supports crop aspect ratios, resizing, rotating, cropping, annotating, filtering, and much more.
|
|
361
374
|
|
|
362
375
|
Checkout the [Pintura integration example](https://codesandbox.io/s/react-dropzone-pintura-40xh4?file=/src/App.js).
|
|
363
376
|
|
|
364
|
-
|
|
365
377
|
## Support
|
|
366
378
|
|
|
367
379
|
### Backers
|
|
380
|
+
|
|
368
381
|
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/react-dropzone#backer)]
|
|
369
382
|
|
|
370
383
|
<a href="https://opencollective.com/react-dropzone/backer/0/website" target="_blank"><img src="https://opencollective.com/react-dropzone/backer/0/avatar.svg"></a>
|
|
@@ -398,8 +411,8 @@ Support us with a monthly donation and help us continue our activities. [[Become
|
|
|
398
411
|
<a href="https://opencollective.com/react-dropzone/backer/28/website" target="_blank"><img src="https://opencollective.com/react-dropzone/backer/28/avatar.svg"></a>
|
|
399
412
|
<a href="https://opencollective.com/react-dropzone/backer/29/website" target="_blank"><img src="https://opencollective.com/react-dropzone/backer/29/avatar.svg"></a>
|
|
400
413
|
|
|
401
|
-
|
|
402
414
|
### Sponsors
|
|
415
|
+
|
|
403
416
|
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/react-dropzone#sponsor)]
|
|
404
417
|
|
|
405
418
|
<a href="https://opencollective.com/react-dropzone/sponsor/0/website" target="_blank"><img src="https://opencollective.com/react-dropzone/sponsor/0/avatar.svg"></a>
|
|
@@ -433,12 +446,14 @@ Become a sponsor and get your logo on our README on Github with a link to your s
|
|
|
433
446
|
<a href="https://opencollective.com/react-dropzone/sponsor/28/website" target="_blank"><img src="https://opencollective.com/react-dropzone/sponsor/28/avatar.svg"></a>
|
|
434
447
|
<a href="https://opencollective.com/react-dropzone/sponsor/29/website" target="_blank"><img src="https://opencollective.com/react-dropzone/sponsor/29/avatar.svg"></a>
|
|
435
448
|
|
|
436
|
-
|
|
437
449
|
### Hosting
|
|
450
|
+
|
|
438
451
|
[react-dropzone.js.org](https://react-dropzone.js.org/) hosting provided by [netlify](https://www.netlify.com/).
|
|
439
452
|
|
|
440
453
|
## Contribute
|
|
454
|
+
|
|
441
455
|
Checkout the organization [CONTRIBUTING.md](https://github.com/react-dropzone/.github/blob/main/CONTRIBUTING.md).
|
|
442
456
|
|
|
443
457
|
## License
|
|
458
|
+
|
|
444
459
|
MIT
|