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.
@@ -47,7 +47,7 @@ export function isDragDataWithFiles(evt) {
47
47
  }
48
48
  // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types
49
49
  // https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types#file
50
- return Array.prototype.every.call(
50
+ return Array.prototype.some.call(
51
51
  evt.dataTransfer.types,
52
52
  type => type === 'Files' || type === 'application/x-moz-file'
53
53
  )
@@ -73,3 +73,18 @@ function isEdge(userAgent) {
73
73
  export function isIeOrEdge(userAgent = window.navigator.userAgent) {
74
74
  return isIe(userAgent) || isEdge(userAgent)
75
75
  }
76
+
77
+ /**
78
+ * This is intended to be used to compose event handlers
79
+ * They are executed in order until one of them calls `event.preventDefault()`.
80
+ * Not sure this is the best way to do this, but it seems legit.
81
+ * @param {Function} fns the event hanlder functions
82
+ * @return {Function} the event handler to add to an element
83
+ */
84
+ export function composeEventHandlers(...fns) {
85
+ return (event, ...args) =>
86
+ fns.some(fn => {
87
+ fn && fn(event, ...args)
88
+ return event.defaultPrevented
89
+ })
90
+ }
@@ -1,4 +1,10 @@
1
- import { getDataTransferItems, isIeOrEdge, isKindFile, isDragDataWithFiles } from './'
1
+ import {
2
+ getDataTransferItems,
3
+ isIeOrEdge,
4
+ isKindFile,
5
+ isDragDataWithFiles,
6
+ composeEventHandlers
7
+ } from './'
2
8
 
3
9
  const files = [
4
10
  {
@@ -144,15 +150,48 @@ describe('isDragDataWithFiles()', () => {
144
150
  ).toBe(true)
145
151
  expect(isDragDataWithFiles({ dataTransfer: { types: ['text/plain'] } })).toBe(false)
146
152
  expect(isDragDataWithFiles({ dataTransfer: { types: ['text/html'] } })).toBe(false)
147
- expect(isDragDataWithFiles({ dataTransfer: { types: ['Files', 'text/html'] } })).toBe(false)
153
+ expect(isDragDataWithFiles({ dataTransfer: { types: ['Files', 'application/test'] } })).toBe(
154
+ true
155
+ )
148
156
  expect(
149
157
  isDragDataWithFiles({
150
- dataTransfer: { types: ['application/x-moz-file', 'text/html'] }
158
+ dataTransfer: { types: ['application/x-moz-file', 'application/test'] }
151
159
  })
152
- ).toBe(false)
160
+ ).toBe(true)
153
161
  })
154
162
 
155
163
  it('should return true if {dataTransfer} is not defined', () => {
156
164
  expect(isDragDataWithFiles({})).toBe(true)
157
165
  })
158
166
  })
167
+
168
+ describe('composeEventHandlers', () => {
169
+ it('returns a fn', () => {
170
+ const fn = composeEventHandlers(() => {})
171
+ expect(typeof fn).toBe('function')
172
+ })
173
+
174
+ it('runs every passed fn in order', () => {
175
+ const fn1 = jest.fn()
176
+ const fn2 = jest.fn()
177
+ const fn = composeEventHandlers(fn1, fn2)
178
+ const evt = { type: 'click' }
179
+ const data = { ping: true }
180
+ fn(evt, data)
181
+ expect(fn1).toHaveBeenCalledWith(evt, data)
182
+ expect(fn2).toHaveBeenCalledWith(evt, data)
183
+ })
184
+
185
+ it('stops after first fn that calls preventDefault()', () => {
186
+ const fn1 = jest.fn().mockImplementation(evt => {
187
+ Object.defineProperty(evt, 'defaultPrevented', { value: true })
188
+ return evt
189
+ })
190
+ const fn2 = jest.fn()
191
+ const fn = composeEventHandlers(fn1, fn2)
192
+ const evt = new MouseEvent('click')
193
+ fn(evt)
194
+ expect(fn1).toHaveBeenCalledWith(evt)
195
+ expect(fn2).not.toHaveBeenCalled()
196
+ })
197
+ })
@@ -10,6 +10,10 @@ module.exports = {
10
10
  usageMode: 'expand',
11
11
  showSidebar: false,
12
12
  serverPort: 8080,
13
+ compilerConfig: {
14
+ transforms: { dangerousTaggedTemplateString: true },
15
+ objectAssign: 'Object.assign'
16
+ },
13
17
  sections: [
14
18
  {
15
19
  name: '',
@@ -1,54 +1,68 @@
1
1
  import * as React from "react";
2
- import {func} from "prop-types";
2
+ // import {func} from "prop-types";
3
+
4
+ export default class Dropzone extends React.Component<DropzoneProps> {
5
+ open: () => void;
6
+ }
7
+
8
+ export type DropzoneProps = Pick<React.HTMLProps<HTMLElement>, PropTypes> & {
9
+ children?: DropzoneRenderFunction;
10
+ getDataTransferItems?(event: React.DragEvent<HTMLElement> | React.ChangeEvent<HTMLInputElement> | DragEvent | Event): Promise<Array<File | DataTransferItem>>;
11
+ onFileDialogCancel?(): void;
12
+ onDrop?: DropFilesEventHandler;
13
+ onDropAccepted?: DropFileEventHandler;
14
+ onDropRejected?: DropFileEventHandler;
15
+ maxSize?: number;
16
+ minSize?: number;
17
+ preventDropOnDocument?: boolean;
18
+ disableClick?: boolean;
19
+ disabled?: boolean;
20
+ };
21
+
22
+ export interface DropzoneRootProps extends React.HTMLAttributes<HTMLElement> {
23
+ refKey?: string;
24
+ [key: string]: any;
25
+ }
26
+
27
+ export interface DropzoneInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
28
+ refKey?: string;
29
+ }
30
+
31
+ export type DropzoneRenderFunction = (x: DropzoneRenderArgs) => JSX.Element;
32
+ export type GetRootPropsFn = (props?: DropzoneRootProps) => DropzoneRootProps;
33
+ export type GetInputPropsFn = (props?: DropzoneInputProps) => DropzoneInputProps;
3
34
 
4
35
  export type DropFileEventHandler = (
5
36
  acceptedOrRejected: File[],
6
- event: React.DragEvent<HTMLDivElement>
37
+ event: React.DragEvent<HTMLElement>
7
38
  ) => void;
39
+
8
40
  export type DropFilesEventHandler = (
9
41
  accepted: File[],
10
42
  rejected: File[],
11
- event: React.DragEvent<HTMLDivElement>
43
+ event: React.DragEvent<HTMLElement>
12
44
  ) => void;
13
45
 
14
- type DropzoneRenderArgs = {
46
+ export type DropzoneRenderArgs = {
15
47
  draggedFiles: File[];
16
48
  acceptedFiles: File[];
17
49
  rejectedFiles: File[];
18
50
  isDragActive: boolean;
19
51
  isDragAccept: boolean;
20
52
  isDragReject: boolean;
53
+ getRootProps: GetRootPropsFn;
54
+ getInputProps: GetInputPropsFn;
21
55
  open: () => void;
22
56
  };
23
57
 
24
- export type DropzoneRenderFunction = (x: DropzoneRenderArgs) => JSX.Element;
25
-
26
- type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
27
-
28
- export type DropzoneProps = Omit<React.HTMLProps<HTMLDivElement>, "onDrop" | "ref"> & {
29
- disableClick?: boolean;
30
- disabled?: boolean;
31
- preventDropOnDocument?: boolean;
32
- inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
33
- maxSize?: number;
34
- minSize?: number;
35
- activeClassName?: string;
36
- acceptClassName?: string;
37
- rejectClassName?: string;
38
- disabledClassName?: string;
39
- activeStyle?: React.CSSProperties;
40
- acceptStyle?: React.CSSProperties;
41
- rejectStyle?: React.CSSProperties;
42
- disabledStyle?: React.CSSProperties;
43
- onDrop?: DropFilesEventHandler;
44
- onDropAccepted?: DropFileEventHandler;
45
- onDropRejected?: DropFileEventHandler;
46
- onFileDialogCancel?(): void;
47
- getDataTransferItems?(event: React.DragEvent<HTMLDivElement> | React.ChangeEvent<HTMLInputElement> | DragEvent | Event): Promise<Array<File | DataTransferItem>>;
48
- children?: React.ReactNode | DropzoneRenderFunction;
49
- ref?: React.Ref<Dropzone>;
50
- };
51
-
52
- export default class Dropzone extends React.Component<DropzoneProps> {
53
- open: () => void;
54
- }
58
+ type PropTypes = "accept"
59
+ | "multiple"
60
+ | "name"
61
+ | "onClick"
62
+ | "onFocus"
63
+ | "onBlur"
64
+ | "onKeyDown"
65
+ | "onDragStart"
66
+ | "onDragEnter"
67
+ | "onDragOver"
68
+ | "onDragLeave";
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import Dropzone from "../../";
3
3
 
4
- class Accept extends React.Component {
4
+ export default class Accept extends React.Component {
5
5
  state = {
6
6
  accepted: [],
7
7
  rejected: []
@@ -17,10 +17,14 @@ class Accept extends React.Component {
17
17
  this.setState({ accepted, rejected });
18
18
  }}
19
19
  >
20
- <p>
21
- Try dropping some files here, or click to select files to upload.
22
- </p>
23
- <p>Only *.jpeg and *.png images will be accepted</p>
20
+ {({getRootProps}) => (
21
+ <div {...getRootProps()}>
22
+ <p>
23
+ Try dropping some files here, or click to select files to upload.
24
+ </p>
25
+ <p>Only *.jpeg and *.png images will be accepted</p>
26
+ </div>
27
+ )}
24
28
  </Dropzone>
25
29
  </div>
26
30
  <aside>
@@ -46,30 +50,26 @@ class Accept extends React.Component {
46
50
  }
47
51
  }
48
52
 
49
- const a = (
53
+ export const acceptExt = (
50
54
  <Dropzone accept=".jpeg,.png">
51
- {({ isDragActive, isDragReject }) => {
52
- if (isDragActive) {
53
- return "All files will be accepted";
54
- }
55
- if (isDragReject) {
56
- return "Some files will be rejected";
57
- }
58
- return "Dropping some files here...";
59
- }}
55
+ {({getRootProps, isDragActive, isDragAccept, isDragReject}) => (
56
+ <div {...getRootProps()}>
57
+ {isDragAccept && "All files will be accepted"}
58
+ {isDragReject && "Some files will be rejected"}
59
+ {isDragActive && "Drop some files here ..."}
60
+ </div>
61
+ )}
60
62
  </Dropzone>
61
63
  );
62
64
 
63
- const b = (
65
+ export const acceptMime = (
64
66
  <Dropzone accept="image/jpeg, image/png">
65
- {({ isDragActive, isDragReject }) => {
66
- if (isDragActive) {
67
- return "All files will be accepted";
68
- }
69
- if (isDragReject) {
70
- return "Some files will be rejected";
71
- }
72
- return "Dropping some files here...";
73
- }}
67
+ {({getRootProps, isDragActive, isDragAccept, isDragReject}) => (
68
+ <div {...getRootProps()}>
69
+ {isDragAccept && "All files will be accepted"}
70
+ {isDragReject && "Some files will be rejected"}
71
+ {isDragActive && "Drop some files here ..."}
72
+ </div>
73
+ )}
74
74
  </Dropzone>
75
75
  );
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import Dropzone from "../../";
3
3
 
4
- class Test extends React.Component {
4
+ export default class Test extends React.Component {
5
5
  dz: Dropzone;
6
6
 
7
7
  open() {
@@ -14,10 +14,6 @@ class Test extends React.Component {
14
14
  return (
15
15
  <div>
16
16
  <Dropzone
17
- ref={node => {
18
- this.dz = node;
19
- }}
20
- onClick={event => console.log(event)}
21
17
  onDrop={(acceptedFiles, rejectedFiles, event) =>
22
18
  console.log(acceptedFiles, rejectedFiles, event)}
23
19
  onDragStart={event => console.log(event)}
@@ -27,16 +23,6 @@ class Test extends React.Component {
27
23
  onDropAccepted={event => console.log(event)}
28
24
  onDropRejected={event => console.log(event)}
29
25
  onFileDialogCancel={() => console.log("abc")}
30
- style={{ borderStyle: "dashed" }}
31
- activeStyle={{ borderStyle: "dotted" }}
32
- acceptStyle={{ borderStyle: "dotted" }}
33
- rejectStyle={{ borderStyle: "dotted" }}
34
- disabledStyle={{ borderStyle: "dotted" }}
35
- className="regular"
36
- activeClassName="active"
37
- acceptClassName="accept"
38
- rejectClassName="reject"
39
- disabledClassName="disabled"
40
26
  minSize={2000}
41
27
  maxSize={Infinity}
42
28
  preventDropOnDocument
@@ -45,13 +31,14 @@ class Test extends React.Component {
45
31
  multiple={false}
46
32
  accept="*.png"
47
33
  name="dropzone"
48
- inputProps={{ id: "dropzone" }}
49
34
  >
50
- Hi
35
+ {({getRootProps, getInputProps}) => (
36
+ <div {...getRootProps()}>
37
+ <input {...getInputProps()} />
38
+ </div>
39
+ )}
51
40
  </Dropzone>
52
41
  </div>
53
42
  );
54
43
  }
55
44
  }
56
-
57
- export default Test;
@@ -1,10 +1,10 @@
1
1
  import React from "react";
2
2
  import Dropzone from "../../";
3
3
 
4
- class Basic extends React.Component {
4
+ export default class Basic extends React.Component {
5
5
  state = { files: [] };
6
6
 
7
- onDrop(files) {
7
+ onDrop = files => {
8
8
  this.setState({
9
9
  files
10
10
  });
@@ -14,10 +14,15 @@ class Basic extends React.Component {
14
14
  return (
15
15
  <section>
16
16
  <div className="dropzone">
17
- <Dropzone onDrop={this.onDrop.bind(this)}>
18
- <p>
19
- Try dropping some files here, or click to select files to upload.
20
- </p>
17
+ <Dropzone onDrop={this.onDrop}>
18
+ {({getRootProps, getInputProps}) => (
19
+ <div {...getRootProps()}>
20
+ <input {...getInputProps()} />
21
+ <p>
22
+ Try dropping some files here, or click to select files to upload.
23
+ </p>
24
+ </div>
25
+ )}
21
26
  </Dropzone>
22
27
  </div>
23
28
  <aside>
@@ -35,50 +40,12 @@ class Basic extends React.Component {
35
40
  }
36
41
  }
37
42
 
38
- class Basic2 extends React.Component {
39
- state = { disabled: true, files: [] };
40
-
41
- onDrop(files) {
42
- this.setState({
43
- files
44
- });
45
- }
46
-
47
- render() {
48
- return (
49
- <section>
50
- <aside>
51
- <button
52
- type="button"
53
- onClick={() => this.setState({ disabled: !this.state.disabled })}
54
- >
55
- Toggle disabled
56
- </button>
57
- </aside>
58
- <div className="dropzone">
59
- <Dropzone
60
- onDrop={this.onDrop.bind(this)}
61
- disabled={this.state.disabled}
62
- >
63
- <p>
64
- Try dropping some files here, or click to select files to upload.
65
- </p>
66
- </Dropzone>
67
- </div>
68
- <aside>
69
- <h2>Dropped files</h2>
70
- <ul>
71
- {this.state.files.map(f => (
72
- <li>
73
- {f.name} - {f.size} bytes
74
- </li>
75
- ))}
76
- </ul>
77
- </aside>
78
- </section>
79
- );
80
- }
81
- }
82
-
83
- // verify that all props are optional
84
- const allPropsOptional = <Dropzone/>
43
+ export const optional = (
44
+ <Dropzone>
45
+ {({getRootProps, getInputProps}) => (
46
+ <div {...getRootProps()}>
47
+ <input {...getInputProps()} />
48
+ </div>
49
+ )}
50
+ </Dropzone>
51
+ )
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import Dropzone from "../../";
3
3
 
4
- class Events extends React.Component {
4
+ export class Events extends React.Component {
5
5
  render() {
6
6
  return (
7
7
  <section>
@@ -14,9 +14,14 @@ class Events extends React.Component {
14
14
  onDragOver={event => console.log(event)}
15
15
  onDragLeave={event => console.log(event)}
16
16
  >
17
- <p>
18
- Try dropping some files here, or click to select files to upload.
19
- </p>
17
+ {({getRootProps, getInputProps}) => (
18
+ <div {...getRootProps()}>
19
+ <input {...getInputProps()} />
20
+ <p>
21
+ Try dropping some files here, or click to select files to upload.
22
+ </p>
23
+ </div>
24
+ )}
20
25
  </Dropzone>
21
26
  </div>
22
27
  </section>
@@ -1,27 +1,16 @@
1
1
  import React from "react";
2
2
  import Dropzone from "../../";
3
3
 
4
- let dropzoneRef;
5
-
6
- const x = (
7
- <div>
8
- <Dropzone
9
- ref={node => {
10
- dropzoneRef = node;
11
- }}
12
- onDrop={(accepted, rejected) => {
13
- alert(accepted);
14
- }}
15
- >
16
- <p>Drop files here.</p>
17
- </Dropzone>
18
- <button
19
- type="button"
20
- onClick={() => {
21
- dropzoneRef.open();
22
- }}
23
- >
24
- Open File Dialog
25
- </button>
26
- </div>
4
+ export const dropzone = (
5
+ <Dropzone onDrop={files => console.log(files)}>
6
+ {({getRootProps, getInputProps, open}) => (
7
+ <div {...getRootProps()}>
8
+ <input {...getInputProps()} />
9
+ <p>Drop some files here.</p>
10
+ <button type="button" onClick={open}>
11
+ Open file dialog
12
+ </button>
13
+ </div>
14
+ )}
15
+ </Dropzone>
27
16
  );
@@ -11,7 +11,9 @@ export class TestReactDragEvt extends Component {
11
11
  return (
12
12
  <div>
13
13
  <Dropzone getDataTransferItems={this.getFiles}>
14
- Hi
14
+ {({getRootProps}) => (
15
+ <div {...getRootProps()} />
16
+ )}
15
17
  </Dropzone>
16
18
  </div>
17
19
  );
@@ -28,7 +30,9 @@ export class TestDataTransferItems extends Component {
28
30
  return (
29
31
  <div>
30
32
  <Dropzone getDataTransferItems={this.getFiles}>
31
- Hi
33
+ {({getRootProps}) => (
34
+ <div {...getRootProps()} />
35
+ )}
32
36
  </Dropzone>
33
37
  </div>
34
38
  );
@@ -45,7 +49,9 @@ export class TestNativeDragEventEvt extends Component {
45
49
  return (
46
50
  <div>
47
51
  <Dropzone getDataTransferItems={this.getFiles}>
48
- Hi
52
+ {({getRootProps}) => (
53
+ <div {...getRootProps()} />
54
+ )}
49
55
  </Dropzone>
50
56
  </div>
51
57
  );
@@ -62,7 +68,9 @@ export class TestChangeEvt extends Component {
62
68
  return (
63
69
  <div>
64
70
  <Dropzone getDataTransferItems={this.getFiles}>
65
- Hi
71
+ {({getRootProps}) => (
72
+ <div {...getRootProps()} />
73
+ )}
66
74
  </Dropzone>
67
75
  </div>
68
76
  );
@@ -80,7 +88,9 @@ export class TestNativeEvt extends Component {
80
88
  return (
81
89
  <div>
82
90
  <Dropzone getDataTransferItems={this.getFiles}>
83
- Hi
91
+ {({getRootProps}) => (
92
+ <div {...getRootProps()} />
93
+ )}
84
94
  </Dropzone>
85
95
  </div>
86
96
  );
@@ -1,88 +0,0 @@
1
- import React from "react";
2
- import Dropzone from "../../";
3
-
4
- class FullScreen extends React.Component {
5
- state = {
6
- accept: "",
7
- files: [],
8
- dropzoneActive: false
9
- };
10
-
11
- onDragEnter() {
12
- this.setState({
13
- dropzoneActive: true
14
- });
15
- }
16
-
17
- onDragLeave() {
18
- this.setState({
19
- dropzoneActive: false
20
- });
21
- }
22
-
23
- onDrop(files) {
24
- this.setState({
25
- files,
26
- dropzoneActive: false
27
- });
28
- }
29
-
30
- applyMimeTypes(event) {
31
- this.setState({
32
- accept: event.target.value
33
- });
34
- }
35
-
36
- render() {
37
- const { accept, files, dropzoneActive } = this.state;
38
-
39
- return (
40
- <Dropzone
41
- disableClick
42
- style={{ position: "relative" }}
43
- accept={accept}
44
- onDrop={this.onDrop.bind(this)}
45
- onDragEnter={this.onDragEnter.bind(this)}
46
- onDragLeave={this.onDragLeave.bind(this)}
47
- >
48
- {dropzoneActive && (
49
- <div
50
- style={{
51
- position: "absolute",
52
- top: 0,
53
- right: 0,
54
- bottom: 0,
55
- left: 0,
56
- padding: "2.5em 0",
57
- background: "rgba(0,0,0,0.5)",
58
- textAlign: "center",
59
- color: "#fff"
60
- }}
61
- >
62
- Drop files...
63
- </div>
64
- )}
65
- <div>
66
- <h1>My awesome app</h1>
67
- <label htmlFor="mimetypes">
68
- Enter mime types you want to accept:{" "}
69
- </label>
70
- <input
71
- type="text"
72
- id="mimetypes"
73
- onChange={this.applyMimeTypes.bind(this)}
74
- />
75
-
76
- <h2>Dropped files</h2>
77
- <ul>
78
- {files.map(f => (
79
- <li>
80
- {f.name} - {f.size} bytes
81
- </li>
82
- ))}
83
- </ul>
84
- </div>
85
- </Dropzone>
86
- );
87
- }
88
- }
@@ -1,27 +0,0 @@
1
- import React, {
2
- Component,
3
- createRef,
4
- RefObject
5
- } from "react";
6
- import Dropzone from "../../";
7
-
8
- export default class Test extends Component {
9
- ref: RefObject<Dropzone> = createRef();
10
-
11
- open() {
12
- const dz = this.ref.current;
13
- if (dz) {
14
- dz.open();
15
- }
16
- }
17
-
18
- render() {
19
- return (
20
- <div>
21
- <Dropzone ref={this.ref}>
22
- Hi
23
- </Dropzone>
24
- </div>
25
- );
26
- }
27
- }
@@ -1,18 +0,0 @@
1
- import React from "react";
2
- import Dropzone from "../../";
3
-
4
- const x = (
5
- <Dropzone accept="image/png">
6
- {({ isDragActive, isDragReject, acceptedFiles, rejectedFiles }) => {
7
- if (isDragActive) {
8
- return "This file is authorized";
9
- }
10
- if (isDragReject) {
11
- return "This file is not authorized";
12
- }
13
- return acceptedFiles.length || rejectedFiles.length
14
- ? `Accepted ${acceptedFiles.length}, rejected ${rejectedFiles.length} files`
15
- : "Try dropping some files.";
16
- }}
17
- </Dropzone>
18
- );