react-dropzone 7.0.1 → 8.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,36 +1,53 @@
1
- **Please note**, that for security reasons most browsers require popups and dialogues to originate from a direct user interaction (i.e. click). If you are calling `dropzoneRef.open()` asynchronously, there’s a good chance it’s going to be blocked by the browser. So if you are calling `dropzoneRef.open()` asynchronously, be sure there is no more than *1000ms* delay between user interaction and `dropzoneRef.open()` call. Due to the lack of official docs on this (at least we haven’t found any. If you know one, feel free to open PR), there is no guarantee that **allowed delay duration** will not be changed in later browser versions. Since implementations may differ between different browsers, avoid calling open asynchronously if possible.
1
+ You can programmatically invoke the default OS file prompt; there are two ways to do that:
2
2
 
3
- You can programmatically invoke default OS file prompt. There are two ways to do that. The first is to provide a function as the child for `Dropzone` to access the `open` method as a parameter. The second way is to set the ref on your `Dropzone` instance and call the instance `open` method.
3
+ - Provide a function as the child for `Dropzone` to access the `open` method as a parameter
4
+ - Set the ref on your `Dropzone` instance and call the instance `open` method
4
5
 
5
- ##### Open programmatically by Child Function
6
+ **Note** that for security reasons most browsers require popups and dialogues to originate from a direct user interaction (i.e. click).
6
7
 
7
- ```
8
- <Dropzone onDrop={files => alert(JSON.stringify(files))} disableClick>
9
- {({ open }) => (
10
- <React.Fragment>
11
- <button type="button" onClick={() => open()}>
12
- Open File Dialog
13
- </button>
14
-
15
- <p>Drop files here.</p>
16
- </React.Fragment>
8
+ If you are calling `dropzoneRef.open()` asynchronously, there’s a good chance it’s going to be blocked by the browser. So if you are calling `dropzoneRef.open()` asynchronously, be sure there is no more than *1000ms* delay between user interaction and `dropzoneRef.open()` call.
9
+
10
+ Due to the lack of official docs on this (at least we haven’t found any. If you know one, feel free to open PR), there is no guarantee that **allowed delay duration** will not be changed in later browser versions. Since implementations may differ between different browsers, avoid calling open asynchronously if possible.
11
+
12
+ #### Open programmatically using the children function param
13
+
14
+ ```jsx harmony
15
+ <Dropzone
16
+ onDrop={files => alert(JSON.stringify(files.map(f => f.name)))}
17
+ disableClick
18
+ >
19
+ {({getRootProps, getInputProps, open}) => (
20
+ <div {...getRootProps()}>
21
+ <input {...getInputProps()} />
22
+ <p>Drop files here</p>
23
+
24
+ <button type="button" onClick={() => open()}>
25
+ Open File Dialog
26
+ </button>
27
+ </div>
17
28
  )}
18
29
  </Dropzone>
19
30
  ```
20
31
 
21
- ##### Open programmatically by Ref
32
+ #### Open programmatically using the Dropzone ref
22
33
 
23
- ```
34
+ ```jsx harmony
24
35
  const dropzoneRef = React.createRef();
25
36
 
26
- <div>
27
- <Dropzone ref={dropzoneRef} onDrop={(accepted, rejected) => { alert(JSON.stringify(accepted)) }}>
28
- <p>Drop files here.</p>
29
- </Dropzone>
30
- <button type="button" onClick={() => { dropzoneRef.current.open() }}>
31
- Open File Dialog
32
- </button>
33
- </div>
37
+ <Dropzone
38
+ ref={dropzoneRef}
39
+ onDrop={files => { alert(JSON.stringify(files.map(f => f.name))) }}
40
+ disableClick
41
+ >
42
+ {({getRootProps, getInputProps}) => (
43
+ <div {...getRootProps()}>
44
+ <input {...getInputProps()} />
45
+ <p>Drop files here</p>
46
+
47
+ <button type="button" onClick={() => dropzoneRef.current.open()}>
48
+ Open File Dialog
49
+ </button>
50
+ </div>
51
+ )}
52
+ </Dropzone>
34
53
  ```
35
-
36
- The completion handler for the `open` function is also the `onDrop` function.
@@ -1,45 +1,49 @@
1
1
  Dropzone that accepts folders as drag-and-drop. Supports multiple folders and subfolders.
2
2
 
3
3
  ```jsx harmony
4
- const { fromEvent } = require('file-selector')
4
+ const {fromEvent} = require('file-selector')
5
5
 
6
- class FolderDropzone extends React.Component {
6
+ class Folders extends React.Component {
7
7
  constructor() {
8
8
  super()
9
- this.state = { files: [] }
9
+ this.state = {
10
+ files: []
11
+ }
10
12
  }
11
13
 
12
14
  onDrop(files) {
13
- this.setState({
14
- files
15
- })
15
+ this.setState({files})
16
16
  }
17
17
 
18
18
  render() {
19
+ const files = this.state.files.map(f => (
20
+ <li key={f.name}>
21
+ {f.path} - {f.size} bytes
22
+ </li>
23
+ ))
19
24
  return (
20
25
  <section>
21
- <div className="dropzone">
26
+ <div>
22
27
  <Dropzone
23
28
  getDataTransferItems={evt => fromEvent(evt)}
24
29
  onDrop={this.onDrop.bind(this)}
25
30
  >
26
- <p>Drop a folder with files here.</p>
31
+ {({getRootProps, getInputProps}) => (
32
+ <div {...getRootProps()}>
33
+ <input {...getInputProps()} />
34
+ <p>Drop a folder with files here</p>
35
+ </div>
36
+ )}
27
37
  </Dropzone>
28
38
  </div>
29
39
  <aside>
30
- <h2>Dropped files and folders</h2>
31
- <ul>
32
- {this.state.files.map(f => (
33
- <li key={f.name}>
34
- {f.path} - {f.size} bytes
35
- </li>
36
- ))}
37
- </ul>
40
+ <h4>Files</h4>
41
+ <ul>{files}</ul>
38
42
  </aside>
39
43
  </section>
40
44
  )
41
45
  }
42
46
  }
43
47
 
44
- <FolderDropzone />
48
+ <Folders />
45
49
  ```
@@ -1,33 +1,29 @@
1
1
  You can wrap the whole app into the dropzone. This will make the whole app a Dropzone target.
2
2
 
3
3
  ```jsx harmony
4
+ const overlayStyle = {
5
+ position: 'absolute',
6
+ top: 0,
7
+ right: 0,
8
+ bottom: 0,
9
+ left: 0,
10
+ padding: '2.5em 0',
11
+ background: 'rgba(0,0,0,0.5)',
12
+ textAlign: 'center',
13
+ color: '#fff'
14
+ };
15
+
4
16
  class FullScreen extends React.Component {
5
17
  constructor() {
6
18
  super()
7
19
  this.state = {
8
20
  accept: '',
9
- files: [],
10
- dropzoneActive: false
21
+ files: []
11
22
  }
12
23
  }
13
24
 
14
- onDragEnter() {
15
- this.setState({
16
- dropzoneActive: true
17
- });
18
- }
19
-
20
- onDragLeave() {
21
- this.setState({
22
- dropzoneActive: false
23
- });
24
- }
25
-
26
25
  onDrop(files) {
27
- this.setState({
28
- files,
29
- dropzoneActive: false
30
- });
26
+ this.setState({files});
31
27
  }
32
28
 
33
29
  applyMimeTypes(event) {
@@ -37,45 +33,36 @@ class FullScreen extends React.Component {
37
33
  }
38
34
 
39
35
  render() {
40
- const { accept, files, dropzoneActive } = this.state;
41
- const overlayStyle = {
42
- position: 'absolute',
43
- top: 0,
44
- right: 0,
45
- bottom: 0,
46
- left: 0,
47
- padding: '2.5em 0',
48
- background: 'rgba(0,0,0,0.5)',
49
- textAlign: 'center',
50
- color: '#fff'
51
- };
36
+ const { accept } = this.state;
37
+
38
+ const files = this.state.files.map((file, index) => (
39
+ <li key={file.name}>
40
+ {file.name} - {file.size} bytes
41
+ </li>
42
+ ))
43
+
52
44
  return (
53
45
  <Dropzone
54
- disableClick
55
- style={{position: "relative"}}
56
46
  accept={accept}
57
47
  onDrop={this.onDrop.bind(this)}
58
- onDragEnter={this.onDragEnter.bind(this)}
59
- onDragLeave={this.onDragLeave.bind(this)}
48
+ disableClick
60
49
  >
61
- { dropzoneActive && <div style={overlayStyle}>Drop files...</div> }
62
- <div>
63
- <h1>My awesome app</h1>
64
- <label htmlFor="mimetypes">Enter mime types you want to accept: </label>
65
- <input
66
- type="text"
67
- id="mimetypes"
68
- onChange={this.applyMimeTypes.bind(this)}
69
- />
70
-
71
- <h2>Dropped files</h2>
72
- <ul>
73
- {
74
- files.map((file, index) => <li key={index}>{file.name} - {file.size} bytes</li>)
75
- }
76
- </ul>
50
+ {({getRootProps, getInputProps, isDragActive}) => (
51
+ <div {...getRootProps()} style={{position: "relative"}}>
52
+ <input {...getInputProps()} />
53
+ { isDragActive && <div style={overlayStyle}>Drop files here</div> }
54
+ <h4>My awesome app</h4>
55
+ <label htmlFor="mimetypes">Enter mime types you want to accept: </label>
56
+ <input
57
+ type="text"
58
+ id="mimetypes"
59
+ onChange={this.applyMimeTypes.bind(this)}
60
+ />
77
61
 
78
- </div>
62
+ <h4>Files</h4>
63
+ <ul>{files}</ul>
64
+ </div>
65
+ )}
79
66
  </Dropzone>
80
67
  );
81
68
  }
@@ -68,16 +68,23 @@ class NestedDropzone extends React.Component {
68
68
  onDragOver={this.createDragHandler('dragover', 'parent')}
69
69
  onDragLeave={this.createDragHandler('dragleave', 'parent')}
70
70
  onDrop={this.createDropHandler('parent')}
71
- style={parentStyle}
72
71
  >
73
- <Dropzone
74
- onDragStart={this.createDragHandler('dragstart', 'child')}
75
- onDragEnter={this.createDragHandler('dragenter', 'child')}
76
- onDragOver={this.createDragHandler('dragover', 'child')}
77
- onDragLeave={this.createDragHandler('dragleave', 'child')}
78
- onDrop={this.createDropHandler('child')}
79
- style={childStyle}
80
- />
72
+ {({getRootProps, getInputProps}) => (
73
+ <div {...getRootProps()} style={parentStyle}>
74
+ <Dropzone
75
+ onDragStart={this.createDragHandler('dragstart', 'child')}
76
+ onDragEnter={this.createDragHandler('dragenter', 'child')}
77
+ onDragOver={this.createDragHandler('dragover', 'child')}
78
+ onDragLeave={this.createDragHandler('dragleave', 'child')}
79
+ onDrop={this.createDropHandler('child')}
80
+ style={childStyle}
81
+ >
82
+ {({getRootProps, getInputProps}) => (
83
+ <div {...getRootProps()} style={childStyle} />
84
+ )}
85
+ </Dropzone>
86
+ </div>
87
+ )}
81
88
  </Dropzone>
82
89
  </div>
83
90
  <aside>
@@ -18,10 +18,12 @@ async function myCustomFileGetter(evt) {
18
18
  return files;
19
19
  }
20
20
 
21
- class PulginExample extends React.Component {
21
+ class Plugin extends React.Component {
22
22
  constructor() {
23
23
  super()
24
- this.state = { files: [] }
24
+ this.state = {
25
+ files: []
26
+ }
25
27
  }
26
28
 
27
29
  onDrop(files) {
@@ -31,30 +33,34 @@ class PulginExample extends React.Component {
31
33
  }
32
34
 
33
35
  render() {
36
+ const files = this.state.files.map(f => (
37
+ <li key={f.name}>
38
+ {f.name} has <strong>myProps</strong>: {f.myProp === true ? 'YES' : ''}
39
+ </li>
40
+ ))
34
41
  return (
35
42
  <section>
36
- <div className="dropzone">
43
+ <div>
37
44
  <Dropzone
38
45
  getDataTransferItems={evt => myCustomFileGetter(evt)}
39
46
  onDrop={this.onDrop.bind(this)}
40
47
  >
41
- <p>Drop some files here ...</p>
48
+ {({getRootProps, getInputProps}) => (
49
+ <div {...getRootProps()}>
50
+ <input {...getInputProps()} />
51
+ <p>Drop files here</p>
52
+ </div>
53
+ )}
42
54
  </Dropzone>
43
55
  </div>
44
56
  <aside>
45
- <h2>Dropped files</h2>
46
- <ul>
47
- {this.state.files.map(f => (
48
- <li key={f.name}>
49
- {f.name} has <strong>myProps</strong>: {f.myProp === true ? 'YES' : ''}
50
- </li>
51
- ))}
52
- </ul>
57
+ <h4>Files</h4>
58
+ <ul>{files}</ul>
53
59
  </aside>
54
60
  </section>
55
61
  )
56
62
  }
57
63
  }
58
64
 
59
- <PulginExample />
65
+ <Plugin />
60
66
  ```
@@ -44,8 +44,7 @@ class DropzoneWithPreview extends React.Component {
44
44
 
45
45
  onDrop(files) {
46
46
  this.setState({
47
- files: files.map(file => ({
48
- ...file,
47
+ files: files.map(file => Object.assign(file, {
49
48
  preview: URL.createObjectURL(file)
50
49
  }))
51
50
  });
@@ -53,18 +52,14 @@ class DropzoneWithPreview extends React.Component {
53
52
 
54
53
  componentWillUnmount() {
55
54
  // Make sure to revoke the data uris to avoid memory leaks
56
- const {files} = this.state;
57
- for (let i = files.length; i >= 0; i--) {
58
- const file = files[0];
59
- URL.revokeObjectURL(file.preview);
60
- }
55
+ this.state.files.forEach(file => URL.revokeObjectURL(file.preview))
61
56
  }
62
57
 
63
58
  render() {
64
59
  const {files} = this.state;
65
60
 
66
61
  const thumbs = files.map(file => (
67
- <div style={thumb}>
62
+ <div style={thumb} key={file.name}>
68
63
  <div style={thumbInner}>
69
64
  <img
70
65
  src={file.preview}
@@ -76,12 +71,17 @@ class DropzoneWithPreview extends React.Component {
76
71
 
77
72
  return (
78
73
  <section>
79
- <div className="dropzone">
80
- <Dropzone
81
- accept="image/*"
82
- onDrop={this.onDrop.bind(this)}
83
- />
84
- </div>
74
+ <Dropzone
75
+ accept="image/*"
76
+ onDrop={this.onDrop.bind(this)}
77
+ >
78
+ {({getRootProps, getInputProps}) => (
79
+ <div {...getRootProps()}>
80
+ <input {...getInputProps()} />
81
+ <p>Drop files here</p>
82
+ </div>
83
+ )}
84
+ </Dropzone>
85
85
  <aside style={thumbsContainer}>
86
86
  {thumbs}
87
87
  </aside>
@@ -1,24 +1,88 @@
1
- By default, the Dropzone component picks up some default styling to get you started. You can customize `<Dropzone>` by specifying a `style`, `activeStyle` or `rejectStyle` which is applied when a file is dragged over the zone. You can also specify `className`, `activeClassName` or `rejectClassName` if you would rather style using CSS.
1
+ By default, the Dropzone component doesn't render any styles.
2
+ By providing a function that returns the component's children you can not only style Dropzone appropriately but also render appropriate content.
2
3
 
3
- ## Updating styles and contents based on user input
4
+ ### Using inline styles
4
5
 
5
6
  By providing a function that returns the component's children you can not only style Dropzone appropriately but also render appropriate content.
6
7
 
7
- ```jsx
8
- <Dropzone
9
- accept="image/png"
10
- >
11
- {({ isDragAccept, isDragReject, acceptedFiles, rejectedFiles }) => {
12
- if (acceptedFiles.length || rejectedFiles.length) {
13
- return `Accepted ${acceptedFiles.length}, rejected ${rejectedFiles.length} files`;
14
- }
15
- if (isDragAccept) {
16
- return "This file is authorized";
17
- }
18
- if (isDragReject) {
19
- return "This file is not authorized";
20
- }
21
- return "Try dropping some files.";
8
+ ```jsx harmony
9
+ const baseStyle = {
10
+ width: 200,
11
+ height: 200,
12
+ borderWidth: 2,
13
+ borderColor: '#666',
14
+ borderStyle: 'dashed',
15
+ borderRadius: 5
16
+ };
17
+ const activeStyle = {
18
+ borderStyle: 'solid',
19
+ borderColor: '#6c6',
20
+ backgroundColor: '#eee'
21
+ };
22
+ const rejectStyle = {
23
+ borderStyle: 'solid',
24
+ borderColor: '#c66',
25
+ backgroundColor: '#eee'
26
+ };
27
+
28
+ <Dropzone accept="image/*">
29
+ {({ getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject, acceptedFiles, rejectedFiles }) => {
30
+ let styles = {...baseStyle}
31
+ styles = isDragActive ? {...styles, ...activeStyle} : styles
32
+ styles = isDragReject ? {...styles, ...rejectStyle} : styles
33
+
34
+ return (
35
+ <div
36
+ {...getRootProps()}
37
+ style={styles}
38
+ >
39
+ <input {...getInputProps()} />
40
+ <div>
41
+ {isDragAccept ? 'Drop' : 'Drag'} files here...
42
+ </div>
43
+ {isDragReject && <div>Unsupported file type...</div>}
44
+ </div>
45
+ )
46
+ }}
47
+ </Dropzone>
48
+ ```
49
+
50
+ ### Using styled-components
51
+
52
+ ```jsx harmony
53
+ const styled = require('styled-components').default;
54
+
55
+ const getColor = (props) => {
56
+ if (props.isDragReject) {
57
+ return '#c66';
58
+ }
59
+ if (props.isDragActive) {
60
+ return '#6c6';
61
+ }
62
+ return '#666';
63
+ };
64
+
65
+ const Container = styled.div`
66
+ width: 200px;
67
+ height: 200px;
68
+ border-width: 2px;
69
+ border-radius: 5px;
70
+ border-color: ${props => getColor(props)};
71
+ border-style: ${props => props.isDragReject || props.isDragActive ? 'solid' : 'dashed'};
72
+ background-color: ${props => props.isDragReject || props.isDragActive ? '#eee' : ''};
73
+ `;
74
+
75
+ <Dropzone accept="image/*">
76
+ {({ getRootProps, isDragActive, isDragAccept, isDragReject, acceptedFiles }) => {
77
+ return (
78
+ <Container
79
+ isDragActive={isDragActive}
80
+ isDragReject={isDragReject}
81
+ {...getRootProps()}
82
+ >
83
+ {isDragAccept ? 'Drop' : 'Drag'} files here...
84
+ </Container>
85
+ )
22
86
  }}
23
87
  </Dropzone>
24
88
  ```
package/package.json CHANGED
@@ -134,6 +134,7 @@
134
134
  "rollup-plugin-node-resolve": "^3.3.0",
135
135
  "rollup-plugin-uglify": "^3.0.0",
136
136
  "size-limit": "^0.19.2",
137
+ "styled-components": "^4.1.2",
137
138
  "webpack-blocks": "^1.0.0",
138
139
  "sinon": "^3.2.1",
139
140
  "style-loader": "^0.18.2",
@@ -147,7 +148,7 @@
147
148
  "path": "@commitlint/prompt"
148
149
  }
149
150
  },
150
- "version": "7.0.1",
151
+ "version": "8.0.3",
151
152
  "engines": {
152
153
  "node": ">= 6"
153
154
  }
@@ -1,7 +1,7 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`Dropzone basics should render children 1`] = `"<div class=\\"\\" style=\\"position: relative; width: 200px; height: 200px; border-width: 2px; border-color: #666; border-style: dashed; border-radius: 5px;\\" aria-disabled=\\"false\\"><p>some content</p><input type=\\"file\\" style=\\"position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; opacity: 0.00001; pointer-events: none;\\" multiple=\\"\\" autocomplete=\\"off\\"></div>"`;
3
+ exports[`Dropzone basics should render children 1`] = `"<div tabindex=\\"0\\"><input type=\\"file\\" style=\\"display: none;\\" multiple=\\"\\" autocomplete=\\"off\\" tabindex=\\"-1\\"></div>"`;
4
4
 
5
- exports[`Dropzone document drop protection does not prevent stray drops when preventDropOnDocument is false 1`] = `"<div class=\\"\\" style=\\"position: relative; width: 200px; height: 200px; border-width: 2px; border-color: #666; border-style: dashed; border-radius: 5px;\\" aria-disabled=\\"false\\"><input type=\\"file\\" style=\\"position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; opacity: 0.00001; pointer-events: none;\\" multiple=\\"\\" autocomplete=\\"off\\"></div>"`;
5
+ exports[`Dropzone document drop protection does not prevent stray drops when preventDropOnDocument is false 1`] = `"<div tabindex=\\"0\\"><input type=\\"file\\" style=\\"display: none;\\" multiple=\\"\\" autocomplete=\\"off\\" tabindex=\\"-1\\"></div>"`;
6
6
 
7
- exports[`Dropzone document drop protection installs hooks to prevent stray drops from taking over the browser window 1`] = `"<div class=\\"\\" style=\\"position: relative; width: 200px; height: 200px; border-width: 2px; border-color: #666; border-style: dashed; border-radius: 5px;\\" aria-disabled=\\"false\\"><p>Content</p><input type=\\"file\\" style=\\"position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; opacity: 0.00001; pointer-events: none;\\" multiple=\\"\\" autocomplete=\\"off\\"></div>"`;
7
+ exports[`Dropzone document drop protection installs hooks to prevent stray drops from taking over the browser window 1`] = `"<div tabindex=\\"0\\"><input type=\\"file\\" style=\\"display: none;\\" multiple=\\"\\" autocomplete=\\"off\\" tabindex=\\"-1\\"><p>Content</p></div>"`;