@@ -2,48 +2,18 @@ import React from 'react';
2
2
import ReactDOM from 'react-dom' ;
3
3
import Sortable from 'sortablejs' ;
4
4
5
- const defaultOptions = {
6
- ref : 'list'
7
- } ;
8
-
9
- const store = {
5
+ const store = {
10
6
nextSibling : null ,
11
7
activeComponent : null
12
8
} ;
13
9
14
- const refName = 'sortableComponent' ;
15
-
16
- const extend = ( target , ...sources ) => {
17
- if ( target === undefined || target === null ) {
18
- throw new TypeError ( 'Cannot convert undefined or null to object' ) ;
19
- }
20
-
21
- const output = Object ( target ) ;
22
- for ( let index = 0 ; index < sources . length ; index ++ ) {
23
- const source = sources [ index ] ;
24
- if ( source !== undefined && source !== null ) {
25
- for ( let key in source ) {
26
- if ( source . hasOwnProperty ( key ) ) {
27
- output [ key ] = source [ key ] ;
28
- }
29
- }
30
- }
31
- }
32
- return output ;
33
- } ;
34
-
35
- const SortableMixin = ( options = defaultOptions ) => ( Component ) => class extends React . Component {
36
- static propTypes = {
37
- items : React . PropTypes . array . isRequired ,
38
- onChange : React . PropTypes . func . isRequired
39
- } ;
40
- state = {
41
- sortableInstance : null
42
- } ;
43
- sortableOptions = extend ( { } , defaultOptions , options ) ;
10
+ export default class extends React . Component {
11
+ sortable = null ;
44
12
45
13
componentDidMount ( ) {
46
- [ // Bind callbacks
14
+ const { children, className, ...options } = this . props ;
15
+
16
+ [
47
17
'onStart' ,
48
18
'onEnd' ,
49
19
'onAdd' ,
@@ -52,76 +22,43 @@ const SortableMixin = (options = defaultOptions) => (Component) => class extends
52
22
'onRemove' ,
53
23
'onFilter' ,
54
24
'onMove'
55
- ] . forEach ( name => {
56
- const eventHandler = this . sortableOptions [ name ] ;
25
+ ] . forEach ( ( name ) => {
26
+ const eventHandler = options [ name ] ;
57
27
58
- this . sortableOptions [ name ] = ( evt ) => {
28
+ options [ name ] = ( evt ) => {
59
29
if ( name === 'onStart' ) {
60
30
store . nextSibling = evt . item . nextElementSibling ;
61
31
store . activeComponent = this ;
62
- } else if ( name === 'onAdd' || name === 'onUpdate' ) {
63
- evt . from . insertBefore ( evt . item , store . nextSibling ) ;
32
+ } else if ( ( name === 'onAdd' || name === 'onUpdate' ) && this . props . onChange ) {
33
+ const items = this . sortable . toArray ( ) ;
34
+ const remote = store . activeComponent ;
35
+ const remoteItems = remote . sortable . toArray ( ) ;
64
36
65
- const oldIndex = evt . oldIndex ;
66
- const newIndex = evt . newIndex ;
67
- let items = this . props . items ;
68
- let remoteItems = [ ] ;
69
-
70
- if ( name === 'onAdd' ) {
71
- remoteItems = store . activeComponent . props . items ;
72
- items . splice ( newIndex , 0 , remoteItems . splice ( oldIndex , 1 ) [ 0 ] ) ;
73
- } else {
74
- items . splice ( newIndex , 0 , items . splice ( oldIndex , 1 ) [ 0 ] ) ;
37
+ evt . from . insertBefore ( evt . item , store . nextSibling ) ;
38
+
39
+ if ( remote !== this && remote . props . group && remote . props . group . pull === 'clone' ) {
40
+ // Remove the node with the same data-reactid
41
+ evt . item . parentNode . removeChild ( evt . item ) ;
75
42
}
76
43
77
- // Called by any change to the list (add / update / remove)
78
- this . props . onChange ( items , this . state . sortableInstance ) ;
44
+ this . props . onChange && this . props . onChange ( items , this . sortable ) ;
79
45
80
- if ( store . activeComponent !== this ) {
81
- const sortableInstance = store . activeComponent . state . sortableInstance ;
82
- store . activeComponent . props . onChange ( remoteItems , sortableInstance ) ;
46
+ if ( remote !== this ) {
47
+ remote . props . onChange && remote . props . onChange ( remoteItems , remote . sortable ) ;
83
48
}
84
49
}
85
50
86
51
setTimeout ( ( ) => {
87
- // Event handler props
88
- this . props [ name ] && this . props [ name ] ( evt , this . state . sortableInstance ) ;
89
-
90
- // Event handler options
91
- eventHandler && eventHandler ( evt , this . state . sortableInstance ) ;
52
+ eventHandler && eventHandler ( evt ) ;
92
53
} , 0 ) ;
93
- } ;
54
+ }
94
55
} ) ;
95
56
96
- const sortableComponent = this . refs [ refName ] ;
97
- this . initSortable ( sortableComponent ) ;
98
- }
99
- componentDidUpdate ( prevProps , prevState ) {
100
- if ( this . props . items !== prevProps . items ) {
101
- this . initSortable ( this . refs [ refName ] ) ;
102
- }
103
- }
104
- componentWillUnmount ( ) {
105
- this . destroySortable ( ) ;
57
+ this . sortable = Sortable . create ( ReactDOM . findDOMNode ( this ) , options ) ;
106
58
}
107
- initSortable ( sortableComponent ) {
108
- this . destroySortable ( ) ;
109
- const domNode = ReactDOM . findDOMNode ( sortableComponent . refs [ this . sortableOptions . ref ] || sortableComponent ) ;
110
- const sortableInstance = Sortable . create ( domNode , this . sortableOptions ) ;
111
- this . setState ( { sortableInstance : sortableInstance } ) ;
112
- }
113
- destroySortable ( ) {
114
- if ( this . state . sortableInstance ) {
115
- this . state . sortableInstance . destroy ( ) ;
116
- this . setState ( { sortableInstance : null } ) ;
117
- }
118
- }
119
-
120
59
render ( ) {
121
60
return (
122
- < Component ref = { refName } { ... this . props } { ... this . state } / >
61
+ < div className = { this . props . className } > { this . props . children } </ div >
123
62
) ;
124
63
}
125
- } ;
126
-
127
- export default SortableMixin ;
64
+ }
0 commit comments