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.
Files changed (61) hide show
  1. package/README.md +129 -114
  2. package/dist/index.cjs +685 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +117 -0
  5. package/dist/index.d.ts +117 -0
  6. package/dist/index.js +656 -2
  7. package/dist/index.js.map +1 -0
  8. package/package.json +76 -177
  9. package/src/index.tsx +774 -0
  10. package/src/utils/index.ts +305 -0
  11. package/.babelrc.js +0 -28
  12. package/.codeclimate.yml +0 -15
  13. package/.editorconfig +0 -13
  14. package/.eslintignore +0 -3
  15. package/.eslintrc +0 -37
  16. package/.gitpod.yml +0 -6
  17. package/.husky/commit-msg +0 -5
  18. package/.husky/pre-commit +0 -5
  19. package/.nvmrc +0 -1
  20. package/.releaserc.json +0 -27
  21. package/CHANGELOG.md +0 -9
  22. package/commitlint.config.js +0 -1
  23. package/dist/es/index.js +0 -1051
  24. package/dist/es/package.json +0 -1
  25. package/dist/es/utils/index.js +0 -366
  26. package/examples/.eslintrc +0 -5
  27. package/examples/accept/README.md +0 -144
  28. package/examples/basic/README.md +0 -70
  29. package/examples/class-component/README.md +0 -45
  30. package/examples/drag-overlay/README.md +0 -132
  31. package/examples/events/README.md +0 -164
  32. package/examples/file-dialog/README.md +0 -90
  33. package/examples/forms/README.md +0 -69
  34. package/examples/maxFiles/README.md +0 -58
  35. package/examples/no-jsx/README.md +0 -32
  36. package/examples/pintura/README.md +0 -146
  37. package/examples/plugins/README.md +0 -55
  38. package/examples/previews/README.md +0 -86
  39. package/examples/styling/README.md +0 -126
  40. package/examples/theme.css +0 -37
  41. package/examples/validator/README.md +0 -68
  42. package/rollup.config.js +0 -33
  43. package/src/.eslintrc +0 -37
  44. package/src/__snapshots__/index.spec.js.snap +0 -3
  45. package/src/index.js +0 -1103
  46. package/src/index.spec.js +0 -3838
  47. package/src/utils/index.js +0 -362
  48. package/src/utils/index.spec.js +0 -625
  49. package/styleguide.config.js +0 -107
  50. package/testSetup.js +0 -8
  51. package/typings/.eslintrc +0 -28
  52. package/typings/react-dropzone.d.ts +0 -102
  53. package/typings/tests/accept.tsx +0 -54
  54. package/typings/tests/all.tsx +0 -46
  55. package/typings/tests/basic.tsx +0 -53
  56. package/typings/tests/events.tsx +0 -31
  57. package/typings/tests/file-dialog.tsx +0 -20
  58. package/typings/tests/hook.tsx +0 -15
  59. package/typings/tests/plugin.tsx +0 -87
  60. package/typings/tests/refs.tsx +0 -18
  61. package/typings/tests/tsconfig.json +0 -22
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ![react-dropzone logo](https://raw.githubusercontent.com/react-dropzone/react-dropzone/master/logo/logo.png)
2
2
 
3
3
  # react-dropzone
4
+
4
5
  [![npm](https://img.shields.io/npm/v/react-dropzone.svg?style=flat-square)](https://www.npmjs.com/package/react-dropzone)
5
6
  ![Tests](https://img.shields.io/github/actions/workflow/status/react-dropzone/react-dropzone/test.yml?branch=master&style=flat-square&label=tests)
6
7
  [![codecov](https://img.shields.io/codecov/c/gh/react-dropzone/react-dropzone/master.svg?style=flat-square)](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
- Install it from npm and include it in your React build process (using [Webpack](http://webpack.github.io/), [Browserify](http://browserify.org/), etc).
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 --save react-dropzone
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 'react'
34
- import {useDropzone} from 'react-dropzone'
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 'react'
58
- import Dropzone from 'react-dropzone'
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 'react'
76
- import {useDropzone} from 'react-dropzone'
75
+ import React, {useCallback} from "react";
76
+ import {useDropzone} from "react-dropzone";
77
77
 
78
78
  function MyDropzone() {
79
- const onDrop = useCallback((acceptedFiles) => {
80
- acceptedFiles.forEach((file) => {
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('file reading was aborted')
84
- reader.onerror = () => console.log('file reading has failed')
83
+ reader.onabort = () => console.log("file reading was aborted");
84
+ reader.onerror = () => console.log("file reading has failed");
85
85
  reader.onload = () => {
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
- }, [])
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 'react'
111
- import {useDropzone} from 'react-dropzone'
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: 'button',
132
- 'aria-label': 'drag and drop area',
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
- *Important*: if you omit rendering an `<input>` and/or binding the props from `getInputProps()`, opening a file dialog will not be possible.
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 'react'
150
- import {useDropzone} from 'react-dropzone'
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 'styled-components'
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
- <StyledDiv {...getRootProps({ refKey: 'innerRef' })}>
161
- <input {...getInputProps()} />
162
- <p>Drag 'n' drop some files here, or click to select files</p>
163
- </StyledDiv>
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 'react'
171
- import {useDropzone} from 'react-dropzone'
172
- import RootRef from '@material-ui/core/RootRef'
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
- <RootRef rootRef={ref}>
179
- <Paper {...rootProps}>
180
- <input {...getInputProps()} />
181
- <p>Drag 'n' drop some files here, or click to select files</p>
182
- </Paper>
183
- </RootRef>
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 'react'
191
- import {useDropzone} from 'react-dropzone'
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
- <div {...getRootProps()}>
201
- <input {...getInputProps()} />
202
- <p>Drag 'n' drop some files here, or click to select files</p>
203
- </div>
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 'react'
211
- import Dropzone from 'react-dropzone'
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 'react'
232
- import Dropzone from 'react-dropzone'
233
- import {act, fireEvent, render} from '@testing-library/react'
240
+ import React from "react";
241
+ import Dropzone from "react-dropzone";
242
+ import {act, fireEvent, render} from "@testing-library/react";
234
243
 
235
- test('invoke onDragEnter when dragenter event occurs', async () => {
236
- const file = new File([
237
- JSON.stringify({ping: true})
238
- ], 'ping.json', { type: 'application/json' })
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
- {({ getRootProps, getInputProps }) => (
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
- expect(onDragEnter).toHaveBeenCalled()
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: 'file',
269
+ kind: "file",
268
270
  type: file.type,
269
271
  getAsFile: () => file
270
272
  })),
271
- types: ['Files']
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.js).
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
- React [16.8](https://reactjs.org/blog/2019/02/06/react-v16.8.0.html) or above is required because we use [hooks](https://reactjs.org/docs/hooks-intro.html) (the lib itself is a hook).
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 'react'
296
- import {useDropzone} from 'react-dropzone'
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 'react'
313
- import {useDropzone} from 'react-dropzone'
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