UNPKG

lucid-ui

Version:

A UI component library from Xandr.

189 lines 6.51 kB
import _, { omit } from 'lodash'; import React from 'react'; import PropTypes from 'prop-types'; import { lucidClassNames } from '../../util/style-helpers'; const cx = lucidClassNames.bind('&-DragCaptureZone'); const { func, string } = PropTypes; /** TODO: Remove the nonPassThroughs when the component is converted to a functional component */ const nonPassThroughs = [ 'className', 'onDrag', 'onDragEnd', 'onDragStart', 'onDragCancel', 'initialState', 'callbackId', ]; class DragCaptureZone extends React.Component { constructor() { super(...arguments); this.elementRef = React.createRef(); this.state = { pageX: 0, pageY: 0, }; this.handleDrag = (event) => { let pageX; let pageY; /* istanbul ignore next */ if ('touches' in event) { pageX = event.touches[0].pageX; pageY = event.touches[0].pageY; } else { pageX = event.pageX; pageY = event.pageY; } event.preventDefault(); this.props.onDrag({ dX: pageX - this.state.pageX, dY: pageY - this.state.pageY, pageX, pageY, }, { event, props: this.props, }); }; this.handleMouseDragStart = (event) => { const pageX = event.pageX; const pageY = event.pageY; window.document.addEventListener('mousemove', this.handleDrag); window.document.addEventListener('mouseup', this.handleDragEnd); event.preventDefault(); this.props.onDragStart({ dX: 0, dY: 0, pageX, pageY, }, { event, props: this.props, }); this.setState({ pageX, pageY, }); }; this.handleTouchDragStart = (event) => { const pageX = event.touches[0].pageX; const pageY = event.touches[0].pageY; event.preventDefault(); this.props.onDragStart({ dX: 0, dY: 0, pageX, pageY, }, { event, props: this.props, }); this.setState({ pageX, pageY, }); }; this.handleDragEnd = (event) => { let pageX; let pageY; /* istanbul ignore next */ if ('changedTouches' in event) { pageX = event.changedTouches[0].pageX; pageY = event.changedTouches[0].pageY; } else { pageX = event.pageX; pageY = event.pageY; } window.document.removeEventListener('mousemove', this.handleDrag); window.document.removeEventListener('mouseup', this.handleDragEnd); event.preventDefault(); this.props.onDragEnd({ dX: pageX - this.state.pageX, dY: pageY - this.state.pageY, pageX, pageY, }, { event, props: this.props, }); this.setState({ pageX: 0, pageY: 0, }); }; this.handleDragCancel = (event) => { this.props.onDragCancel({ event, props: this.props, }); this.setState({ pageX: 0, pageY: 0, }); }; } componentDidMount() { //add event listeners directly on the DOM element to allow preventDefault //calls which are not honored due to react's event delegation //reference: https://github.com/facebook/react/issues/8968 if (this.elementRef.current) { this.elementRef.current.addEventListener('touchmove', this.handleDrag); this.elementRef.current.addEventListener('touchend', this.handleDragEnd); this.elementRef.current.addEventListener('touchcancel', this.handleDragCancel); } } componentWillUnmount() { if (this.elementRef.current) { this.elementRef.current.removeEventListener('touchmove', this.handleDrag); this.elementRef.current.removeEventListener('touchend', this.handleDragEnd); this.elementRef.current.removeEventListener('touchcancel', this.handleDragCancel); } window.document.removeEventListener('mousemove', this.handleDrag); window.document.removeEventListener('mouseup', this.handleDragEnd); } render() { return (React.createElement("div", { ...omit(this.props, nonPassThroughs), className: cx('&', this.props.className), key: 'DragCaptureZone', onMouseDown: this.handleMouseDragStart, onTouchStart: this.handleTouchDragStart, ref: this.elementRef })); } } DragCaptureZone.displayName = 'DragCaptureZone'; DragCaptureZone.peek = { description: `This is a helper component used to capture mouse events to determine when the user starts, is and stops dragging.`, categories: ['utility'], }; DragCaptureZone.propTypes = { /** Appended to the component-specific class names set on the root element. */ className: string, /** Called as the user drags the mouse. Signature: \`({ dx, dy, pageX, pageY }, { event, props }) => {}\` */ onDrag: func, /** Called when the user releases the mouse button after having dragged. Signature: \`({ dx, dy, pageX, pageY }, { event, props }) => {}\` */ onDragEnd: func, /** Called when the user presses the mouse button down while over the component. Signature: \`({ dx, dy, pageX, pageY }, { event, props }) => {}\` */ onDragStart: func, /** Called when the drag event is canceled due to user interaction. For example: if a system alert pops up during a touch event. Signature: \`({ event, props }) => {}\` */ onDragCancel: func, }; DragCaptureZone.defaultProps = { onDrag: _.noop, onDragEnd: _.noop, onDragStart: _.noop, onDragCancel: _.noop, }; export default DragCaptureZone; //# sourceMappingURL=DragCaptureZone.js.map