Skip to content

Instantly share code, notes, and snippets.

@kaleem-elahi
Created January 31, 2020 09:34
Show Gist options
  • Save kaleem-elahi/c9d0527bab459cac1a89844e3510182f to your computer and use it in GitHub Desktop.
Save kaleem-elahi/c9d0527bab459cac1a89844e3510182f to your computer and use it in GitHub Desktop.
Draggable Wrapper HOC react
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import './DraggableWrapperHOC.css';
const DraggableWrapperHOC = (WrappedComponent) => {
return class DraggableWrapperHOC extends Component {
constructor(props) {
super(props);
this.state = {
pos: { x: 0, y: 0 },
dragging: false,
rel: null // position relative to the cursor
}
this.onMouseDown = this.onMouseDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.onMouseMove = this.onMouseMove.bind(this);
}
// we could get away with not having this (and just having the listeners on
// our div), but then the experience would be possibly be janky. If there's
// anything w/ a higher z-index that gets in the way, then you're toast,
// etc.
componentDidUpdate(nextProps, state) {
console.log("WrappedComponent:", WrappedComponent);
if (this.state.dragging && !state.dragging) {
document.addEventListener('mousemove', this.onMouseMove)
document.addEventListener('mouseup', this.onMouseUp)
} else if (!this.state.dragging && state.dragging) {
document.removeEventListener('mousemove', this.onMouseMove)
document.removeEventListener('mouseup', this.onMouseUp)
}
}
// calculate relative position to the mouse and set dragging=true
onMouseDown(e) {
let bodyRect = document.body.getBoundingClientRect(),
elemRect = ReactDOM.findDOMNode(this).getBoundingClientRect(),
pos = elemRect.top - bodyRect.top;
// only left mouse button
if (e.button !== 0) return
// let pos = ReactDOM.findDOMNode(this);
console.log("pos", elemRect, pos);
this.setState({
dragging: true,
rel: {
x: e.pageX - elemRect.left,
y: e.pageY - elemRect.top
}
})
e.stopPropagation()
e.preventDefault()
}
onMouseUp(e) {
this.setState({ dragging: false })
e.stopPropagation()
e.preventDefault()
}
onMouseMove(e) {
if (!this.state.dragging) return
this.setState({
pos: {
x: e.pageX - this.state.rel.x,
y: e.pageY - this.state.rel.y
}
})
e.stopPropagation()
e.preventDefault()
}
render() {
console.log("WrappedComponent.prototype: ", WrappedComponent.prototype);
return (<div
onMouseDown={this.onMouseDown}
style={{
position: 'absolute',
left: this.state.pos.x + 'px',
top: this.state.pos.y + 'px'
}}
>
<WrappedComponent {...this.props} />
</div>
)
}
}
}
DraggableWrapperHOC.propTypes = {
initialPos: PropTypes.objectOf(PropTypes.any)
}
DraggableWrapperHOC.DefaultProps = {
// allow the initial position to be passed in as a prop
// initialPos:
}
export default DraggableWrapperHOC;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment