Skip to content

Instantly share code, notes, and snippets.

@shlomitc
Created August 13, 2018 14:50
Show Gist options
  • Save shlomitc/7c1bc3ab760de7b127388d0ef63fff4b to your computer and use it in GitHub Desktop.
Save shlomitc/7c1bc3ab760de7b127388d0ef63fff4b to your computer and use it in GitHub Desktop.
import React from 'react';
import {findDOMNode} from 'react-dom';
import css from './App.scss';
import HTML5Backend from 'react-dnd-html5-backend';
import {DragDropContext, DragSource, DropTarget} from 'react-dnd';
//PHASE
class Phase extends React.Component {
constructor() {
super();
this.state = {
cards: [{id: 'A', content: 'Card A'}, {id: 'B', content: 'Card B'}]
};
this.moveCard = this.moveCard.bind(this);
}
moveCard(dragIndex, hoverIndex) {
const {cards} = this.state;
const dragCard = cards[dragIndex];
const moshe = cards.filter(c => c.id !== dragCard.id);
const mashu = [...moshe.splice(0, hoverIndex), dragCard, ...moshe.splice(hoverIndex)];
this.setState({cards: mashu});
}
render() {
return (
<div className={css.phase}>
{
this.state.cards.map(
(cardData, index) =>
<Card key={cardData.id}
id={cardData.id}
index={index}
moveCard={this.moveCard}
>
{cardData.content}
</Card>
)
}
</div>
);
}
}
//CARD
class CardRaw extends React.Component {
render() {
const {isDragging, connectDragSource, connectDropTarget} = this.props;
return connectDropTarget(connectDragSource(
<div className={css.card}>
{this.props.children}
</div>
));
}
}
const cardSource = {
canDrag: () => {
return true;
},
isDragging: (props, monitor) => {
return monitor.getItem().id === props.id;
},
beginDrag: props => {
return {
id: props.id,
index: props.index
};
},
endDrag: () => null
};
const cardSourceCollect = (connect, monitor) => {
return {
isDragging: monitor.isDragging(),
connectDragSource: connect.dragSource()
};
};
const cardTarget = {
hover(props, monitor, component) {
if (!component) {
return null;
}
const dragIndex = monitor.getItem().index;
const hoverIndex = props.index;
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return;
}
// Determine rectangle on screen
const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
// Determine mouse position
const clientOffset = monitor.getClientOffset();
// Get pixels to the top
const hoverClientY = (clientOffset).y - hoverBoundingRect.top;
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
// Time to actually perform the action
props.moveCard(dragIndex, hoverIndex);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
monitor.getItem().index = hoverIndex
},
};
const cardTargetCollect = (connect) => ({
connectDropTarget: connect.dropTarget()
});
const Card = DropTarget('card', cardTarget, cardTargetCollect)(DragSource('card', cardSource, cardSourceCollect)(CardRaw));
//APP
class App extends React.Component {
state = {disabled: false};
render() {
return (
<div className={css.wrapper}>
<Phase/>
</div>
);
}
}
export default DragDropContext(HTML5Backend)(App);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment