import React, { Component } from 'react'
|
import { Tabs } from 'antd'
|
import { is, fromJS } from 'immutable'
|
import { DndProvider, DragSource, DropTarget } from 'react-dnd'
|
|
// Drag & Drop node
|
class TabNode extends Component {
|
render() {
|
const { connectDragSource, connectDropTarget, children } = this.props
|
|
return connectDragSource(connectDropTarget(children))
|
}
|
}
|
|
const cardTarget = {
|
drop(props, monitor) {
|
const dragKey = monitor.getItem().index
|
const hoverKey = props.index
|
|
if (dragKey === hoverKey) {
|
return;
|
}
|
|
props.moveTabNode(dragKey, hoverKey)
|
monitor.getItem().index = hoverKey
|
}
|
}
|
|
const cardSource = {
|
beginDrag(props) {
|
return {
|
id: props.id,
|
index: props.index,
|
}
|
}
|
}
|
|
const WrapTabNode = DropTarget('DND_NODE', cardTarget, connect => ({
|
connectDropTarget: connect.dropTarget(),
|
}))(
|
DragSource('DND_NODE', cardSource, (connect, monitor) => ({
|
connectDragSource: connect.dragSource(),
|
isDragging: monitor.isDragging(),
|
}))(TabNode)
|
)
|
|
class DraggableTabs extends Component {
|
state = {
|
order: []
|
}
|
|
moveTabNode = (dragKey, hoverKey) => {
|
const newOrder = this.state.order.slice()
|
const { children } = this.props
|
|
React.Children.forEach(children, c => {
|
if (newOrder.indexOf(c.key) === -1) {
|
newOrder.push(c.key)
|
}
|
})
|
|
const dragIndex = newOrder.indexOf(dragKey)
|
const hoverIndex = newOrder.indexOf(hoverKey)
|
|
if (dragIndex === -1) return
|
|
newOrder.splice(dragIndex, 1)
|
newOrder.splice(hoverIndex, 0, dragKey)
|
|
this.setState({
|
order: newOrder
|
})
|
this.props.tabsMove(newOrder)
|
}
|
|
renderTabBar = (props, DefaultTabBar) => (
|
<DefaultTabBar {...props}>
|
{node => (
|
<WrapTabNode key={node.key} index={node.key} moveTabNode={this.moveTabNode}>
|
{node}
|
</WrapTabNode>
|
)}
|
</DefaultTabBar>
|
)
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState)) ||
|
!is(fromJS(nextProps.children), fromJS(this.props.children)) ||
|
nextProps.tabPosition !== this.props.tabPosition ||
|
nextProps.type !== this.props.type
|
}
|
|
render() {
|
const { order } = this.state
|
const { children, ...resProps } = this.props
|
const tabs = []
|
React.Children.forEach(children, c => {
|
tabs.push(c)
|
})
|
|
const orderTabs = tabs.slice().sort((a, b) => {
|
const orderA = order.indexOf(a.key)
|
const orderB = order.indexOf(b.key)
|
|
if (orderA !== -1 && orderB !== -1) {
|
return orderA - orderB
|
}
|
if (orderA !== -1) {
|
return -1
|
}
|
if (orderB !== -1) {
|
return 1
|
}
|
|
const ia = tabs.indexOf(a)
|
const ib = tabs.indexOf(b)
|
|
return ia - ib
|
})
|
|
return (
|
<DndProvider>
|
<Tabs renderTabBar={this.renderTabBar} {...resProps}>
|
{orderTabs}
|
</Tabs>
|
</DndProvider>
|
)
|
}
|
}
|
|
export default DraggableTabs
|