Created
January 24, 2018 07:33
-
-
Save kavimaluskam/19b9bd5d3ae1142c01aee52059abac21 to your computer and use it in GitHub Desktop.
React-DND & Material-ui-next: List Item
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default { | |
LIST_ITEM: 'listItem', | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react'; | |
import update from 'immutability-helper'; | |
import {DragDropContext} from 'react-dnd'; | |
import HTML5Backend from 'react-dnd-html5-backend'; | |
import ReorderListItem from './ReorderListItem'; | |
import {List} from 'material-ui'; | |
class ReorderList extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
items: props.items && props.items.map(item => ({id: item, text: item})), | |
}; | |
this.handleOnClick = this.handleOnClick.bind(this); | |
this.moveListItem = this.moveListItem.bind(this); | |
} | |
handleOnClick(item) { | |
// You may pass handle on click event to props | |
console.log(item); | |
} | |
moveListItem(dragIndex, hoverIndex) { | |
const {items} = this.state; | |
const dragitem = items[dragIndex]; | |
this.setState( | |
update(this.state, { | |
items: { | |
$splice: [[dragIndex, 1], [hoverIndex, 0, dragitem]], | |
}, | |
}), | |
); | |
// You may pass the state to props | |
console.log(this.state.items); | |
} | |
render() { | |
const {items} = this.state; | |
return ( | |
<div> | |
<List> | |
{items.map((item, i) => ( | |
<ReorderListItem | |
key={item.id} | |
handleOnClick={() => this.handleOnClick(item)} | |
index={i} | |
id={item.id} | |
text={item.text} | |
moveListItem={this.moveListItem} | |
/> | |
))} | |
</List> | |
</div> | |
); | |
} | |
} | |
export default DragDropContext(HTML5Backend)(ReorderList); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react'; | |
import PropTypes from 'prop-types'; | |
import {findDOMNode} from 'react-dom'; | |
import {DragSource, DropTarget} from 'react-dnd'; | |
import ItemTypes from './ItemTypes'; | |
import {ListItem} from 'material-ui'; | |
const style = { | |
cursor: 'move', | |
}; | |
const cardSource = { | |
beginDrag(props) { | |
return { | |
id: props.id, | |
index: props.index, | |
}; | |
}, | |
}; | |
const cardTarget = { | |
hover(props, monitor, component) { | |
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.moveListItem(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 withDropTarget = DropTarget(ItemTypes.LIST_ITEM, cardTarget, connect => ({ | |
connectDropTarget: connect.dropTarget(), | |
})); | |
const withDropSource = DragSource(ItemTypes.LIST_ITEM, cardSource, (connect, monitor) => ({ | |
connectDragSource: connect.dragSource(), | |
isDragging: monitor.isDragging(), | |
})); | |
class ReorderListItem extends Component { | |
static propTypes = { | |
connectDragSource: PropTypes.func.isRequired, | |
connectDropTarget: PropTypes.func.isRequired, | |
handleOnClick: PropTypes.func.isRequired, | |
index: PropTypes.number.isRequired, | |
isDragging: PropTypes.bool.isRequired, | |
id: PropTypes.oneOfType([PropTypes.string.isRequired, PropTypes.number.isRequired]), | |
text: PropTypes.string.isRequired, | |
moveListItem: PropTypes.func.isRequired, | |
}; | |
render() { | |
const { | |
text, | |
isDragging, | |
connectDragSource, | |
connectDropTarget, | |
// props for onClick selection | |
handleOnClick | |
// | |
} = this.props; | |
const opacity = isDragging ? 0 : 1; | |
return connectDragSource( | |
connectDropTarget( | |
<div style={{...style, opacity}}> | |
<ListItem onClick={handleOnClick}>{text}</ListItem> | |
</div>) | |
); | |
} | |
} | |
export default withDropTarget(withDropSource(ReorderListItem)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment