wix-style-react
Version:
wix-style-react
84 lines • 3.92 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import { buildChildrenObject } from '../common/utils/buildChildrenObject';
import { dataHooks } from './constants';
import { st, classes } from './Dropzone.st.css';
/** Defines a region in the page where files can be dropped */
class Dropzone extends React.PureComponent {
constructor() {
super(...arguments);
this.state = {
isDragActive: false,
};
/** https://spin.atomicobject.com/2018/09/13/file-uploader-react-typescript/ */
this._dragEventCounter = 0;
this._eventHasFiles = event => {
/** DataTransfer object is defined here: https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer */
return event.dataTransfer
? Array.from(event.dataTransfer.items).some(item => {
return item.kind === 'file';
})
: !!(event.target && event.target.files);
};
this._onDragEnter = event => {
Dropzone._overrideEventDefaults(event);
this._dragEventCounter++;
/** We only want to show the overlay when files are dragged over the dropzone */
return this._eventHasFiles(event) && this.setState({ isDragActive: true });
};
this._onDragLeave = event => {
Dropzone._overrideEventDefaults(event);
this._dragEventCounter--;
return (this._dragEventCounter === 0 && this.setState({ isDragActive: false }));
};
this._onDrop = event => {
Dropzone._overrideEventDefaults(event);
this._dragEventCounter = 0;
if (this._eventHasFiles(event)) {
const files = event.dataTransfer
? Array.from(event.dataTransfer.items).map(item => item.getAsFile())
: event.target.files;
this.setState({ isDragActive: false });
return this.props.onDrop(files);
}
};
}
render() {
const { children, dataHook, className } = this.props;
const { isDragActive } = this.state;
const childrenObj = buildChildrenObject(children, {
Content: null,
Overlay: null,
});
return (React.createElement("div", { "data-hook": dataHook, className: st(classes.root, className), onDrop: this._onDrop, onDragEnter: this._onDragEnter, onDragLeave: this._onDragLeave, onDragOver: Dropzone._overrideEventDefaults },
isDragActive && childrenObj.Overlay,
childrenObj.Content));
}
}
Dropzone.displayName = 'Dropzone';
Dropzone.propTypes = {
/** Applies a data-hook HTML attribute that can be used in the tests. */
dataHook: PropTypes.string,
/** Specifies a CSS class name to be appended to the component’s root element. */
className: PropTypes.string,
/** Defines an event handler which is called when files are dropped over the dropzone. Dropped files are supplied as an argument to the function. */
onDrop: PropTypes.func.isRequired,
/** Accepts `<Dropzone.Overlay />` or `<Dropzone.Content />`. Both of them can contain any required content. */
children: PropTypes.node,
};
/**
* An overlay element to be displayed during a drag over the content
*/
Dropzone.Overlay = ({ children }) => (React.createElement("div", { "data-hook": dataHooks.dropzoneOverlay, className: classes.dropzoneOverlay }, children));
/**
* An content element on which a file can be dragged over
*/
Dropzone.Content = ({ children }) => (React.createElement("div", { "data-hook": dataHooks.dropzoneContent }, children));
Dropzone._overrideEventDefaults = event => {
event.preventDefault();
event.stopPropagation();
};
Dropzone.Content.displayName = 'Dropzone.Content';
Dropzone.Overlay.displayName = 'Dropzone.Overlay';
export default Dropzone;
//# sourceMappingURL=Dropzone.js.map