king
2021-01-06 b6ccd63b80fc7017bfabc446787732a98c7cbab7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import React, { Component } from 'react'
import { Tabs } from 'antd'
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
 
    if (dragKey === 'tool' || hoverKey === 'tool') return
 
    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)
 
    newOrder.splice(dragIndex, 1)
    newOrder.splice(hoverIndex, 0, dragKey)
    let _order = newOrder.filter(item => item !== 'tool')
    
    this.setState({
      order: [..._order, 'tool']
    })
    this.props.tabsMove(_order)
  }
 
  renderTabBar = (props, DefaultTabBar) => (
    <DefaultTabBar {...props}>
      {node => (
        <WrapTabNode key={node.key} index={node.key} moveTabNode={this.moveTabNode}>
          {node}
        </WrapTabNode>
      )}
    </DefaultTabBar>
  )
 
  render() {
    const { order } = this.state
    const { children } = 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} {...this.props}>
          {orderTabs}
        </Tabs>
      </DndProvider>
    )
  }
}
 
export default DraggableTabs