UNPKG

wix-style-react

Version:
84 lines 3.92 kB
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