lucid-ui
Version:
A UI component library from Xandr.
189 lines • 6.51 kB
JavaScript
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