Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-dropzone

Package Overview
Dependencies
Maintainers
2
Versions
189
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-dropzone - npm Package Compare versions

Comparing version 3.6.0 to 3.7.0

6

CHANGELOG.md

@@ -0,1 +1,7 @@

# 3.7.0
- [feature] Added onCancel callback. Closes #199 <Anurag Sharma (CES)>
- [feature] onDrop will be called with 2 arguments: acceptedFiles and rejectedFiles <Christian Kaps>
- [docs] Update README examples to use ref callbacks <Kye Hohenberger>
# 3.6.0

@@ -2,0 +8,0 @@

94

dist/index.js

@@ -93,3 +93,3 @@ (function webpackUniversalModuleDefinition(root, factory) {

var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Dropzone).call(this, props, context));
var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this, props, context));

@@ -102,2 +102,5 @@ _this.onClick = _this.onClick.bind(_this);

_this.onDrop = _this.onDrop.bind(_this);
_this.onFileDialogCancel = _this.onFileDialogCancel.bind(_this);
_this.fileAccepted = _this.fileAccepted.bind(_this);
_this.isFileDialogActive = false;

@@ -114,4 +117,12 @@ _this.state = {

this.enterCounter = 0;
// Tried implementing addEventListener, but didn't work out
document.body.onfocus = this.onFileDialogCancel;
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
// Can be replaced with removeEventListener, if addEventListener works
document.body.onfocus = null;
}
}, {
key: 'onDragStart',

@@ -189,3 +200,4 @@ value: function onDragStart(e) {

var max = this.props.multiple ? droppedFiles.length : Math.min(droppedFiles.length, 1);
var files = [];
var acceptedFiles = [];
var rejectedFiles = [];

@@ -198,18 +210,24 @@ for (var i = 0; i < max; i++) {

}
files.push(file);
if (this.fileAccepted(file) && this.fileMatchSize(file)) {
acceptedFiles.push(file);
} else {
rejectedFiles.push(file);
}
}
if (this.allFilesAccepted(files) && this.allFilesMatchSize(files)) {
if (this.props.onDrop) {
this.props.onDrop.call(this, files, e);
if (this.props.onDrop) {
this.props.onDrop.call(this, acceptedFiles, rejectedFiles, e);
}
if (rejectedFiles.length > 0) {
if (this.props.onDropRejected) {
this.props.onDropRejected.call(this, rejectedFiles, e);
}
} else if (acceptedFiles.length > 0) {
if (this.props.onDropAccepted) {
this.props.onDropAccepted.call(this, files, e);
this.props.onDropAccepted.call(this, acceptedFiles, e);
}
} else {
if (this.props.onDropRejected) {
this.props.onDropRejected.call(this, files, e);
}
}
this.isFileDialogActive = false;
}

@@ -224,22 +242,41 @@ }, {

}, {
key: 'allFilesAccepted',
value: function allFilesAccepted(files) {
var _this2 = this;
key: 'onFileDialogCancel',
value: function onFileDialogCancel() {
// timeout will not recognize context of this method
var onFileDialogCancel = this.props.onFileDialogCancel;
var fileInputEl = this.fileInputEl;
var isFileDialogActive = this.isFileDialogActive;
// execute the timeout only if the onFileDialogCancel is defined and FileDialog
// is opened in the browser
return files.every(function (file) {
return (0, _attrAccept2.default)(file, _this2.props.accept);
});
if (onFileDialogCancel && isFileDialogActive) {
setTimeout(function () {
// Returns an object as FileList
var FileList = fileInputEl.files;
if (!FileList.length) {
isFileDialogActive = false;
onFileDialogCancel();
}
}, 300);
}
}
}, {
key: 'allFilesMatchSize',
value: function allFilesMatchSize(files) {
var _this3 = this;
return files.every(function (file) {
return file.size <= _this3.props.maxSize && file.size >= _this3.props.minSize;
});
key: 'fileAccepted',
value: function fileAccepted(file) {
return (0, _attrAccept2.default)(file, this.props.accept);
}
}, {
key: 'fileMatchSize',
value: function fileMatchSize(file) {
return file.size <= this.props.maxSize && file.size >= this.props.minSize;
}
}, {
key: 'allFilesAccepted',
value: function allFilesAccepted(files) {
return files.every(this.fileAccepted);
}
}, {
key: 'open',
value: function open() {
this.isFileDialogActive = true;
this.fileInputEl.value = null;

@@ -251,3 +288,3 @@ this.fileInputEl.click();

value: function render() {
var _this4 = this;
var _this2 = this;

@@ -319,3 +356,3 @@ var _props = this.props;

ref: function ref(el) {
return _this4.fileInputEl = el;
return _this2.fileInputEl = el;
}, // eslint-disable-line

@@ -330,3 +367,3 @@ onChange: this.onDrop

// Remove custom properties before passing them to the wrapper div element
var customProps = ['disablePreview', 'disableClick', 'onDropAccepted', 'onDropRejected', 'maxSize', 'minSize'];
var customProps = ['disablePreview', 'disableClick', 'onDropAccepted', 'onDropRejected', 'maxSize', 'minSize', 'onFileDialogCancel'];
var divProps = _extends({}, props);

@@ -388,2 +425,3 @@ customProps.forEach(function (prop) {

disableClick: _react2.default.PropTypes.bool, // Disallow clicking on the dropzone container to open file dialog
onFileDialogCancel: _react2.default.PropTypes.func, // Provide a callback on clicking the cancel button of the file dialog

@@ -390,0 +428,0 @@ inputProps: _react2.default.PropTypes.object, // Pass additional attributes to the <input type="file"/> tag

{
"name": "react-dropzone",
"version": "3.6.0",
"version": "3.7.0",
"description": "Simple HTML5 drag-drop zone with React.js",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -35,4 +35,6 @@ react-dropzone [![Build Status](https://travis-ci.org/okonet/react-dropzone.svg)](https://travis-ci.org/okonet/react-dropzone)

Simply `require('react-dropzone')` and specify an `onDrop` method that accepts an array of dropped files.
Simply `require('react-dropzone')` and specify an `onDrop` method which accepts two arguments. The first argument represents the accepted files and the second argument the rejected files.
The `onDrop` method gets always called if a file was uploaded, regardless if it was accepted or rejected. The library provides two additional methods named `onDropAccepted` and `onDropRejected`. The `onDropAccepted` method will be called if all dropped files were accepted and the `onDropRejected` method will be called if any of the dropped files was rejected.
By default, the component picks up some default styling to get you started. You can customize `<Dropzone>` by specifying a `style` and `activeStyle` which is applied when a file is dragged over the zone. You can also specify `className` and `activeClassName` if you would rather style using CSS.

@@ -50,4 +52,5 @@

var DropzoneDemo = React.createClass({
onDrop: function (files) {
console.log('Received files: ', files);
onDrop: function (acceptedFiles, rejectedFiles) {
console.log('Accepted files: ', acceptedFiles);
console.log('Rejected files: ', rejectedFiles);
},

@@ -97,5 +100,5 @@

onDrop: function (files) {
onDrop: function (acceptedFiles) {
this.setState({
files: files
files: acceptedFiles
});

@@ -105,3 +108,3 @@ },

onOpenClick: function () {
this.refs.dropzone.open();
this.dropzone.open();
},

@@ -112,3 +115,3 @@

<div>
<Dropzone ref="dropzone" onDrop={this.onDrop}>
<Dropzone ref={(node) => { this.dropzone = node; }} onDrop={this.onDrop}>
<div>Try dropping some files here, or click to select files to upload.</div>

@@ -139,5 +142,5 @@ </Dropzone>

```javascript
onDrop: function(files){
onDrop: function(acceptedFiles){
var req = request.post('/upload');
files.forEach((file)=> {
acceptedFiles.forEach((file)=> {
req.attach(file.name, file);

@@ -144,0 +147,0 @@ });

@@ -19,2 +19,5 @@ /* eslint prefer-template: 0 */

this.onDrop = this.onDrop.bind(this);
this.onFileDialogCancel = this.onFileDialogCancel.bind(this);
this.fileAccepted = this.fileAccepted.bind(this);
this.isFileDialogActive = false;

@@ -28,4 +31,11 @@ this.state = {

this.enterCounter = 0;
// Tried implementing addEventListener, but didn't work out
document.body.onfocus = this.onFileDialogCancel;
}
componentWillUnmount() {
// Can be replaced with removeEventListener, if addEventListener works
document.body.onfocus = null;
}
onDragStart(e) {

@@ -98,3 +108,4 @@ if (this.props.onDragStart) {

const max = this.props.multiple ? droppedFiles.length : Math.min(droppedFiles.length, 1);
const files = [];
const acceptedFiles = [];
const rejectedFiles = [];

@@ -107,18 +118,24 @@ for (let i = 0; i < max; i++) {

}
files.push(file);
if (this.fileAccepted(file) && this.fileMatchSize(file)) {
acceptedFiles.push(file);
} else {
rejectedFiles.push(file);
}
}
if (this.allFilesAccepted(files) && this.allFilesMatchSize(files)) {
if (this.props.onDrop) {
this.props.onDrop.call(this, files, e);
if (this.props.onDrop) {
this.props.onDrop.call(this, acceptedFiles, rejectedFiles, e);
}
if (rejectedFiles.length > 0) {
if (this.props.onDropRejected) {
this.props.onDropRejected.call(this, rejectedFiles, e);
}
} else if (acceptedFiles.length > 0) {
if (this.props.onDropAccepted) {
this.props.onDropAccepted.call(this, files, e);
this.props.onDropAccepted.call(this, acceptedFiles, e);
}
} else {
if (this.props.onDropRejected) {
this.props.onDropRejected.call(this, files, e);
}
}
this.isFileDialogActive = false;
}

@@ -132,11 +149,35 @@

allFilesAccepted(files) {
return files.every(file => accepts(file, this.props.accept));
onFileDialogCancel() {
// timeout will not recognize context of this method
const { onFileDialogCancel } = this.props;
const { fileInputEl } = this;
let { isFileDialogActive } = this;
// execute the timeout only if the onFileDialogCancel is defined and FileDialog
// is opened in the browser
if (onFileDialogCancel && isFileDialogActive) {
setTimeout(() => {
// Returns an object as FileList
const FileList = fileInputEl.files;
if (!FileList.length) {
isFileDialogActive = false;
onFileDialogCancel();
}
}, 300);
}
}
allFilesMatchSize(files) {
return files.every(file => (file.size <= this.props.maxSize && file.size >= this.props.minSize));
fileAccepted(file) {
return accepts(file, this.props.accept);
}
fileMatchSize(file) {
return file.size <= this.props.maxSize && file.size >= this.props.minSize;
}
allFilesAccepted(files) {
return files.every(this.fileAccepted);
}
open() {
this.isFileDialogActive = true;
this.fileInputEl.value = null;

@@ -226,3 +267,5 @@ this.fileInputEl.click();

// Remove custom properties before passing them to the wrapper div element
const customProps = ['disablePreview', 'disableClick', 'onDropAccepted', 'onDropRejected', 'maxSize', 'minSize'];
const customProps = [
'disablePreview', 'disableClick', 'onDropAccepted', 'onDropRejected', 'maxSize', 'minSize', 'onFileDialogCancel'
];
const divProps = { ...props };

@@ -282,2 +325,3 @@ customProps.forEach(prop => delete divProps[prop]);

disableClick: React.PropTypes.bool, // Disallow clicking on the dropzone container to open file dialog
onFileDialogCancel: React.PropTypes.func, // Provide a callback on clicking the cancel button of the file dialog

@@ -284,0 +328,0 @@ inputProps: React.PropTypes.object, // Pass additional attributes to the <input type="file"/> tag

@@ -14,2 +14,3 @@ /* eslint no-unused-expressions: 0 */

let files = [];
let images = [];

@@ -22,2 +23,11 @@ beforeEach(() => {

}];
images = [{
name: 'cats.gif',
size: 1234,
type: 'image/gif'
}, {
name: 'dogs.jpg',
size: 2345,
type: 'image/jpeg'
}];
});

@@ -149,14 +159,7 @@

it('applies the accept prop to the dropped files', () => {
const images = [{
name: 'cats.gif',
size: 1234,
type: 'image/gif'
}, {
name: 'dogs.jpg',
size: 2345,
type: 'image/jpeg'
}];
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy} accept="image/*">
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy} accept="image/*">
<div className="dropzone-content">some content</div>

@@ -168,21 +171,40 @@ </Dropzone>

TestUtils.Simulate.drop(content, { dataTransfer: { files } });
expect(dropSpy.callCount).to.equal(0);
expect(dropSpy.callCount).to.equal(1);
expect(dropSpy.firstCall.args[0]).to.have.length(0);
expect(dropSpy.firstCall.args[1]).to.have.length(1);
expect(dropAcceptedSpy.callCount).to.equal(0);
expect(dropRejectedSpy.callCount).to.equal(1);
expect(dropRejectedSpy.firstCall.args[0]).to.have.length(1);
});
it('applies the accept prop to the dropped images', () => {
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy} accept="image/*">
<div className="dropzone-content">some content</div>
</Dropzone>
);
const content = TestUtils.findRenderedDOMComponentWithClass(dropzone, 'dropzone-content');
TestUtils.Simulate.drop(content, { dataTransfer: { files: images } });
expect(dropSpy.callCount).to.equal(1);
expect(dropSpy.firstCall.args[0]).to.have.length(2);
expect(dropSpy.firstCall.args[1]).to.have.length(0);
expect(dropAcceptedSpy.callCount).to.equal(1);
expect(dropAcceptedSpy.firstCall.args[0]).to.have.length(2);
expect(dropRejectedSpy.callCount).to.equal(0);
});
it('accepts all dropped files when no accept prop is specified', () => {
const images = [{
name: 'cats.gif',
size: 1234,
type: 'image/gif'
}, {
name: 'dogs.jpg',
size: 2345,
type: 'image/jpeg'
}];
it('accepts all dropped files and images when no accept prop is specified', () => {
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy}>
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy}>
<div className="dropzone-content">some content</div>

@@ -193,22 +215,19 @@ </Dropzone>

TestUtils.Simulate.drop(content, { dataTransfer: { files } });
TestUtils.Simulate.drop(content, { dataTransfer: { files: files.concat(images) } });
expect(dropSpy.callCount).to.equal(1);
TestUtils.Simulate.drop(content, { dataTransfer: { files: images } });
expect(dropSpy.callCount).to.equal(2);
expect(dropSpy.secondCall.args[0]).to.have.length(2);
expect(dropSpy.firstCall.args[0]).to.have.length(3);
expect(dropSpy.firstCall.args[1]).to.have.length(0);
expect(dropAcceptedSpy.callCount).to.equal(1);
expect(dropAcceptedSpy.firstCall.args[0]).to.have.length(3);
expect(dropRejectedSpy.callCount).to.equal(0);
});
it('applies the maxSize prop to the dropped files', () => {
const images = [{
name: 'cats.gif',
size: 1234,
type: 'image/gif'
}, {
name: 'dogs.jpg',
size: 2345,
type: 'image/jpeg'
}];
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy} maxSize={1111}>
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy} maxSize={1111}>
<div className="dropzone-content">some content</div>

@@ -221,20 +240,39 @@ </Dropzone>

expect(dropSpy.callCount).to.equal(1);
expect(dropSpy.firstCall.args[0]).to.have.length(1);
expect(dropSpy.firstCall.args[1]).to.have.length(0);
expect(dropAcceptedSpy.callCount).to.equal(1);
expect(dropAcceptedSpy.firstCall.args[0]).to.have.length(1);
expect(dropRejectedSpy.callCount).to.equal(0);
});
it('applies the maxSize prop to the dropped images', () => {
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy} maxSize={1111}>
<div className="dropzone-content">some content</div>
</Dropzone>
);
const content = TestUtils.findRenderedDOMComponentWithClass(dropzone, 'dropzone-content');
TestUtils.Simulate.drop(content, { dataTransfer: { files: images } });
expect(dropSpy.callCount).to.equal(1);
expect(dropSpy.firstCall.args[0]).to.have.length(1);
expect(dropSpy.firstCall.args[0]).to.have.length(0);
expect(dropSpy.firstCall.args[1]).to.have.length(2);
expect(dropAcceptedSpy.callCount).to.equal(0);
expect(dropRejectedSpy.callCount).to.equal(1);
expect(dropRejectedSpy.firstCall.args[0]).to.have.length(2);
});
it('applies the minSize prop to the dropped files', () => {
const images = [{
name: 'cats.gif',
size: 1234,
type: 'image/gif'
}, {
name: 'dogs.jpg',
size: 2345,
type: 'image/jpeg'
}];
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy} minSize={1112}>
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy} minSize={1112}>
<div className="dropzone-content">some content</div>

@@ -246,21 +284,40 @@ </Dropzone>

TestUtils.Simulate.drop(content, { dataTransfer: { files } });
expect(dropSpy.callCount).to.equal(0);
expect(dropSpy.callCount).to.equal(1);
expect(dropSpy.firstCall.args[0]).to.have.length(0);
expect(dropSpy.firstCall.args[1]).to.have.length(1);
expect(dropAcceptedSpy.callCount).to.equal(0);
expect(dropRejectedSpy.callCount).to.equal(1);
expect(dropRejectedSpy.firstCall.args[0]).to.have.length(1);
});
it('applies the minSize prop to the dropped images', () => {
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy} minSize={1112}>
<div className="dropzone-content">some content</div>
</Dropzone>
);
const content = TestUtils.findRenderedDOMComponentWithClass(dropzone, 'dropzone-content');
TestUtils.Simulate.drop(content, { dataTransfer: { files: images } });
expect(dropSpy.callCount).to.equal(1);
expect(dropSpy.firstCall.args[0]).to.have.length(2);
expect(dropSpy.firstCall.args[1]).to.have.length(0);
expect(dropAcceptedSpy.callCount).to.equal(1);
expect(dropAcceptedSpy.firstCall.args[0]).to.have.length(2);
expect(dropRejectedSpy.callCount).to.equal(0);
});
it('accepts all dropped files when no size prop is specified', () => {
const images = [{
name: 'cats.gif',
size: 1234,
type: 'image/gif'
}, {
name: 'dogs.jpg',
size: 2345,
type: 'image/jpeg'
}];
it('accepts all dropped files and images when no size prop is specified', () => {
const dropSpy = spy();
const dropAcceptedSpy = spy();
const dropRejectedSpy = spy();
const dropzone = TestUtils.renderIntoDocument(
<Dropzone onDrop={dropSpy}>
<Dropzone onDrop={dropSpy} onDropAccepted={dropAcceptedSpy} onDropRejected={dropRejectedSpy}>
<div className="dropzone-content">some content</div>

@@ -271,7 +328,11 @@ </Dropzone>

TestUtils.Simulate.drop(content, { dataTransfer: { files } });
TestUtils.Simulate.drop(content, { dataTransfer: { files: files.concat(images) } });
expect(dropSpy.callCount).to.equal(1);
TestUtils.Simulate.drop(content, { dataTransfer: { files: images } });
expect(dropSpy.callCount).to.equal(2);
expect(dropSpy.secondCall.args[0]).to.have.length(2);
expect(dropSpy.firstCall.args[0]).to.have.length(3);
expect(dropSpy.firstCall.args[1]).to.have.length(0);
expect(dropAcceptedSpy.callCount).to.equal(1);
expect(dropAcceptedSpy.firstCall.args[0]).to.have.length(3);
expect(dropRejectedSpy.callCount).to.equal(0);
});

@@ -318,4 +379,58 @@

it('overrides onDragEnter', () => {
const dragEnterSpy = spy();
const component = TestUtils.renderIntoDocument(
<Dropzone id="drag-example" onDragEnter={dragEnterSpy} />
);
const content = TestUtils.find(component, '#drag-example')[0];
TestUtils.Simulate.dragEnter(content, { dataTransfer: { items: files } });
expect(dragEnterSpy.callCount).to.equal(1);
});
it('do not invoke onCancel prop everytime document body receives focus', (done) => {
const onCancelSpy = spy();
TestUtils.renderIntoDocument(
<Dropzone id="on-cancel-example" onFileDialogCancel={onCancelSpy} />
);
// Simulated DOM event - onfocus
document.body.addEventListener('focus', () => {});
const evt = document.createEvent('HTMLEvents');
evt.initEvent('focus', false, true);
document.body.dispatchEvent(evt);
// setTimeout to match the event callback from actual Component
setTimeout(() => {
expect(onCancelSpy.callCount).to.equal(0);
done();
}, 300);
});
it('invoke onFileDialogCancel prop when document body receives focus via cancel button', (done) => {
const onCancelSpy = spy();
const component = TestUtils.renderIntoDocument(
<Dropzone className="dropzone-content" onFileDialogCancel={onCancelSpy} />
);
// Test / invoke the click event
spy(component, 'open');
const content = TestUtils.findRenderedDOMComponentWithClass(component, 'dropzone-content');
TestUtils.Simulate.click(content);
expect(component.open.callCount).to.equal(1);
// Simulated DOM event - onfocus
document.body.addEventListener('focus', () => {});
const evt = document.createEvent('HTMLEvents');
evt.initEvent('focus', false, true);
document.body.dispatchEvent(evt);
// setTimeout to match the event callback from actual Component
setTimeout(() => {
expect(onCancelSpy.callCount).to.equal(1);
done();
}, 300);
});
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc