const {ReactDraggable: Draggable, React, ReactDOM} = window;
class App extends React.Component {
state = {
activeDrags: 0,
deltaPosition: {
x: 0, y: 0
},
controlledPosition: {
x: -400, y: 200
}
};
handleDrag = (e, ui) => {
const {x, y} = this.state.deltaPosition;
this.setState({
deltaPosition: {
x: x + ui.deltaX,
y: y + ui.deltaY,
}
});
};
onStart = () => {
this.setState({activeDrags: ++this.state.activeDrags});
};
onStop = () => {
this.setState({activeDrags: --this.state.activeDrags});
};
onDrop = (e) => {
this.setState({activeDrags: --this.state.activeDrags});
if (e.target.classList.contains("drop-target")) {
alert("Dropped!");
e.target.classList.remove('hovered');
}
};
onDropAreaMouseEnter = (e) => {
if (this.state.activeDrags) {
e.target.classList.add('hovered');
}
}
onDropAreaMouseLeave = (e) => {
e.target.classList.remove('hovered');
}
// For controlled component
adjustXPos = (e) => {
e.preventDefault();
e.stopPropagation();
const {x, y} = this.state.controlledPosition;
this.setState({controlledPosition: {x: x - 10, y}});
};
adjustYPos = (e) => {
e.preventDefault();
e.stopPropagation();
const {controlledPosition} = this.state;
const {x, y} = controlledPosition;
this.setState({controlledPosition: {x, y: y - 10}});
};
onControlledDrag = (e, position) => {
const {x, y} = position;
this.setState({controlledPosition: {x, y}});
};
onControlledDragStop = (e, position) => {
this.onControlledDrag(e, position);
this.onStop();
};
render() {
const dragHandlers = {onStart: this.onStart, onStop: this.onStop};
const {deltaPosition, controlledPosition} = this.state;
return (
React Draggable
Active DragHandlers: {this.state.activeDrags}
Demo Source
I can be dragged anywhere
I can only be dragged horizonally (x axis)
I can only be dragged vertically (y axis)
false}>
I don't want to be dragged
I track my deltas
x: {deltaPosition.x.toFixed(0)}, y: {deltaPosition.y.toFixed(0)}
Drag here
You must click my handle to drag me
Drag here
I have long scrollable content with a handle
{'\n' + Array(40).fill('x').join('\n')}
Can't drag here
Dragging here works
I snap to a 25 x 25 grid
I snap to a 50 x 50 grid
I can only be moved 100px in any direction.
I can detect drops from the next box.
I can be dropped onto another box.
I can only be moved within my offsetParent.
Both parent padding and child margin work properly.
I also can only be moved within my offsetParent.
Both parent padding and child margin work properly.
I can only be moved within the confines of the body element.
I already have an absolute position.
I use rem instead of px for my transforms. I also have absolute positioning.
I depend on a CSS hack to avoid double absolute positioning.
{"I have a default position of {x: 25, y: 25}, so I'm slightly offset."}
{'I have a default position based on percents {x: \'-10%\', y: \'-10%\'}, so I\'m slightly offset.'}
My position can be changed programmatically.
I have a drag handler to sync state.
My position can be changed programmatically.
I have a dragStop handler to sync state.
);
}
}
class RemWrapper extends React.Component {
// PropTypes is not available in this environment, but here they are.
// static propTypes = {
// style: PropTypes.shape({
// transform: PropTypes.string.isRequired
// }),
// children: PropTypes.node.isRequired,
// remBaseline: PropTypes.number,
// }
translateTransformToRem(transform, remBaseline = 16) {
const convertedValues = transform.replace('translate(', '').replace(')', '')
.split(',')
.map(px => px.replace('px', ''))
.map(px => parseInt(px, 10) / remBaseline)
.map(x => `${x}rem`)
const [x, y] = convertedValues
return `translate(${x}, ${y})`
}
render() {
const { children, remBaseline = 16, style } = this.props
const child = React.Children.only(children)
const editedStyle = {
...child.props.style,
...style,
transform: this.translateTransformToRem(style.transform, remBaseline),
}
return React.cloneElement(child, {
...child.props,
...this.props,
style: editedStyle
})
}
}
ReactDOM.render(, document.getElementById('container'));