1
1
import Component from '@glimmer/component' ;
2
2
import Sortable from 'sortablejs' ;
3
- import { bind , scheduleOnce } from '@ember/runloop' ;
3
+ import { bind , next } from '@ember/runloop' ;
4
4
import { action } from '@ember/object' ;
5
- import { next } from '@ember/runloop' ;
6
5
import { tracked } from '@glimmer/tracking' ;
7
6
import { move , insertAt , removeFrom } from 'ember-sortablejs/utils/array-utils' ;
8
7
import { inject as service } from '@ember/service' ;
@@ -12,9 +11,11 @@ export default class SortableJsComponent extends Component {
12
11
13
12
@tracked list = [ ] ;
14
13
14
+ cachedList = null ;
15
+ hasUpdatedList = false ; // Used to prevent unwanted renders. Probably there's a better way to do this.
15
16
#sortableContainer = null ;
16
- # sortableInstance = null ;
17
- # internalEvents = [
17
+ sortableInstance = null ;
18
+ internalEvents = [
18
19
'onStart' ,
19
20
'onAdd' ,
20
21
'onUpdate' ,
@@ -66,7 +67,7 @@ export default class SortableJsComponent extends Component {
66
67
this . #sortableContainer = element ;
67
68
68
69
next ( this , ( ) => {
69
- this . # sortableInstance = Sortable . create ( element , options ) ;
70
+ this . sortableInstance = Sortable . create ( element , options ) ;
70
71
this . setupEventHandlers ( ) ;
71
72
this . setupInternalEventHandlers ( ) ;
72
73
this . setList ( ) ;
@@ -78,8 +79,19 @@ export default class SortableJsComponent extends Component {
78
79
this . list = [ ...( this . args . items || [ ] ) ] ;
79
80
}
80
81
82
+ @action
83
+ cancelDnD ( ) {
84
+ if ( this . cachedList ) {
85
+ this . list = [ ...this . cachedList ] ;
86
+ this . cachedList = null ;
87
+ this . dragStore . dragAddInstance ?. cancelDnD ( ) ;
88
+ }
89
+ this . dragStore . reset ( ) ;
90
+ }
91
+
81
92
willDestroy ( ) {
82
- this . #sortableInstance. destroy ( ) ;
93
+ this . sortableInstance . destroy ( ) ;
94
+ this . dragStore . reset ( ) ;
83
95
}
84
96
85
97
onUpdate ( evt ) {
@@ -88,7 +100,8 @@ export default class SortableJsComponent extends Component {
88
100
oldDraggableIndex,
89
101
} = evt ;
90
102
91
- this . list = move ( this . list , oldDraggableIndex , newDraggableIndex ) ;
103
+ this . sync ( evt . item , move ( this . list , oldDraggableIndex , newDraggableIndex ) ) ;
104
+ this . hasUpdatedList = true ;
92
105
this . args ?. onUpdate ?. ( evt ) ;
93
106
}
94
107
@@ -98,57 +111,66 @@ export default class SortableJsComponent extends Component {
98
111
} = evt ;
99
112
100
113
if ( evt . pullMode !== 'clone' ) {
101
- this . list = removeFrom ( this . list , oldDraggableIndex ) ;
114
+ this . sync ( evt . item , removeFrom ( this . list , oldDraggableIndex ) ) ;
115
+ this . hasUpdatedList = true ;
102
116
}
103
117
104
118
this . args ?. onRemove ?. ( evt ) ;
105
119
}
106
120
107
121
onAdd ( evt ) {
108
- evt . item . remove ( ) ; // without this DOM is wrong
122
+ this . cachedList = [ ...this . list ] ;
123
+ this . dragStore . dragAddInstance = this ;
109
124
const {
110
125
oldDraggableIndex,
111
126
newDraggableIndex,
112
127
} = evt ;
113
- const oldItem = this . dragStore . dragging . list [ oldDraggableIndex ] ;
114
- this . list = insertAt ( this . list , newDraggableIndex , oldItem )
128
+ const oldItem = this . dragStore . dragStartInstance . list [ oldDraggableIndex ] ;
129
+
130
+ this . sync ( evt . item , insertAt ( this . list , newDraggableIndex , oldItem ) ) ;
115
131
this . args ?. onAdd ?. ( evt ) ;
116
132
}
117
133
118
134
onStart ( evt ) {
119
- this . dragStore . dragging = this ;
135
+ this . cachedList = [ ...this . list ] ;
136
+ this . dragStore . dragStartInstance = this ;
120
137
this . args ?. onStart ?. ( evt ) ;
121
138
}
122
139
123
- onEnd ( evt ) {
124
- this . args ?. onEnd ?. ( evt ) ;
125
- this . dragStore . dragging = null ;
140
+ onEnd ( evt , ) {
141
+ if ( ! this . hasUpdatedList ) {
142
+ this . sync ( evt . item , this . list ) ;
143
+ }
144
+
145
+ this . args ?. onEnd ?. ( evt , this . cancelDnD ) ;
146
+ this . hasUpdatedList = false ;
147
+ }
148
+
149
+ sync ( element , changedArray ) {
150
+ element . remove ( ) ;
151
+ this . list = [ ...changedArray ] ;
126
152
}
127
153
128
154
setupEventHandlers ( ) {
129
155
this . #events. forEach ( eventName => {
130
156
const action = this . args [ eventName ] ;
131
157
if ( typeof action === 'function' ) {
132
- this . # sortableInstance. option ( eventName , bind ( this , 'performExternalAction' , eventName ) ) ;
158
+ this . sortableInstance . option ( eventName , bind ( this , 'performExternalAction' , eventName ) ) ;
133
159
}
134
160
} ) ;
135
161
}
136
162
137
163
setupInternalEventHandlers ( ) {
138
- this . # internalEvents. forEach ( eventName => {
139
- this . # sortableInstance. option ( eventName , bind ( this , this [ eventName ] ) ) ;
164
+ this . internalEvents . forEach ( eventName => {
165
+ this . sortableInstance . option ( eventName , bind ( this , this [ eventName ] ) ) ;
140
166
} ) ;
141
167
}
142
168
143
169
performExternalAction ( actionName , ...args ) {
144
- let action = this . args [ actionName ] ;
145
-
146
- if ( typeof action === 'function' ) {
147
- action ( ...args , this . sortable ) ;
148
- }
170
+ this . args [ actionName ] ?. ( ...args )
149
171
}
150
172
151
173
setOption ( option , value ) {
152
- this . # sortableInstance. option ( option , value ) ;
174
+ this . sortableInstance . option ( option , value ) ;
153
175
}
154
176
}
0 commit comments