1
1
import {
2
- type DraggableGroupContextProvider ,
2
+ DraggableGroupContextProvider ,
3
3
draggableContext ,
4
4
} from '~/draggable/DraggableGroup' ;
5
5
import {
@@ -25,29 +25,31 @@ export function useDraggableChildren({
25
25
'transition' | 'children' | 'onChange' | 'list'
26
26
> ) : ReactNode {
27
27
const forceUpdate = useForceUpdate ( ) ;
28
- const childrenRef = useFollowingRef (
28
+ const modifyChildrenRef = useFollowingRef (
29
29
outerChildren ,
30
30
( v ) => Children . map ( v , ( i ) => i ) || [ ] ,
31
31
) ;
32
- const listRef = useFollowingRef ( list , ( v ) => v . slice ( ) ) ;
33
- const { fromRef, toRef } = useContext ( draggableContext ) ;
32
+ const listRef = useFollowingRef ( list , ( v ) => ( {
33
+ origin : v . slice ( ) ,
34
+ modify : v . slice ( ) ,
35
+ } ) ) ;
36
+ const { fromRef, toRef, type } = useContext ( draggableContext ) ;
34
37
35
- const preverRef = useRef < DraggableGroupContextProvider | null > ( null ) ;
36
38
const stateRef = useRef < { readonly id : symbol ; index : number } > ( {
37
39
id : Symbol ( times ++ ) ,
38
40
index : - 1 ,
39
41
} ) ;
40
42
41
43
const [ children ] = useChildrenWithRefs (
42
- childrenRef . current ,
44
+ modifyChildrenRef . current ,
43
45
( el , props , idx ) => {
44
46
const id = stateRef . current . id ;
45
- const item = listRef . current [ idx ] ;
47
+ const item = listRef . current . modify [ idx ] ;
46
48
const emit = ( ) : void => {
47
- console . log ( 'emit' , stateRef . current . id , preverRef . current ) ;
49
+ console . log ( 'emit' , stateRef . current . id ) ;
48
50
// preverRef.current = null;
49
51
if ( isListChanged ( ) ) {
50
- const result = listRef . current . slice ( ) ;
52
+ const result = listRef . current . modify . slice ( ) ;
51
53
console . log ( 'onchange' , result ) ;
52
54
onChange ?.( result ) ;
53
55
}
@@ -63,25 +65,42 @@ export function useDraggableChildren({
63
65
// 拖动目标元素事件
64
66
function getDragSideEvents ( ) {
65
67
const left : DOMAttributes < HTMLElement > = {
68
+ onDragStart : ( e : DragEvent ) => {
69
+ const dataTransfer = e . dataTransfer as DataTransfer ;
70
+ // dataTransfer.setData('text', `draggable:${index}`);
71
+ dataTransfer . effectAllowed = 'move' ;
72
+ const from : DraggableGroupContextProvider = {
73
+ drop ( id2 ) {
74
+ if ( type === 'move' && id2 !== id ) {
75
+ removeItem ( item ) ;
76
+ }
77
+ from . cancel = undefined ;
78
+ emit ( ) ;
79
+ } ,
80
+ cancel ( _id2 ) : void {
81
+ if ( type === 'move' ) {
82
+ updateChildrenOf ( el , listRef . current . modify . indexOf ( item ) ) ;
83
+ }
84
+ } ,
85
+ children : el ,
86
+ item,
87
+ id,
88
+ } ;
89
+ fromRef . current = from ;
90
+ // const target = e.currentTarget as HTMLElement;
91
+ // target.classList.add(cls.__.ghost);
92
+ } ,
66
93
onDragEnd : ( e : DragEvent ) => {
67
- const target = e . currentTarget as HTMLElement ;
68
- target . classList . remove ( cls . __ . ghost ) ;
69
- console . log ( 'onDragEnd' , item , target ) ;
94
+ // const target = e.currentTarget as HTMLElement;
95
+ // target.classList.remove(cls.__.ghost);
70
96
toRef . current ?. cancel ?.( id ) ;
71
- emit ( ) ;
97
+ fromRef . current ?. cancel ?.( id ) ;
98
+ // emit();
72
99
fromRef . current = null ;
73
100
toRef . current = null ;
74
101
stateRef . current . index = - 1 ;
75
102
e . preventDefault ( ) ;
76
103
} ,
77
- onDragStart : ( e : DragEvent ) => {
78
- const dataTransfer = e . dataTransfer as DataTransfer ;
79
- // dataTransfer.setData('text', `draggable:${index}`);
80
- dataTransfer . effectAllowed = 'move' ;
81
- fromRef . current = { children : el , item, id } ;
82
- const target = e . currentTarget as HTMLElement ;
83
- target . classList . add ( cls . __ . ghost ) ;
84
- } ,
85
104
} ;
86
105
return left ;
87
106
}
@@ -111,12 +130,14 @@ export function useDraggableChildren({
111
130
// if (from.id !== toRef.current?.id) toRef.current?.drop?.(id);
112
131
const to = toRef . current ;
113
132
if ( to ) to . cancel = undefined ;
133
+ fromRef . current = null ;
134
+ toRef . current = null ;
114
135
emit ( ) ;
115
136
} ,
116
137
// eslint-disable-next-line perfectionist/sort-objects
117
138
onDragEnterCapture ( e : DragEvent ) : void {
118
- const index = listRef . current . indexOf ( item ) ;
119
- console . log ( 'enter' , index , stateRef . current . index ) ;
139
+ const index = listRef . current . modify . indexOf ( item ) ;
140
+ console . log ( 'enter' , id , index , stateRef . current . index ) ;
120
141
const target = e . target as HTMLElement ;
121
142
e . preventDefault ( ) ;
122
143
@@ -128,22 +149,36 @@ export function useDraggableChildren({
128
149
return ;
129
150
130
151
const from = fromRef . current ;
131
- const prever = ( preverRef . current = toRef . current || from ) ;
152
+ const prever = toRef . current || from ;
132
153
console . log ( prever ) ;
133
154
if ( ! prever || ! from ) return ;
134
155
console . log ( item , from . item ) ;
135
156
prever . enter ?.( id ) ;
136
157
137
158
console . log ( prever . id , id , prever . id === id ) ;
138
- const fromIndex = listRef . current . indexOf ( from . item ) ;
159
+ const fromIndex = listRef . current . modify . indexOf ( from . item ) ;
139
160
if ( from . item !== item ) {
140
- if ( prever . id === id || fromIndex !== - 1 ) move ( fromIndex , index ) ;
141
- else moveFromGroup ( from . item , from . children , index ) ;
161
+ if ( prever . id === id || fromIndex !== - 1 ) {
162
+ let toIndex = index ;
163
+ const modifyChildren = modifyChildrenRef . current [
164
+ fromIndex
165
+ ] as ReactElement ;
166
+ // move 返回之前隐藏的 children 位置,如果存在则 index - 1
167
+ if (
168
+ type === 'move' &&
169
+ fromIndex !== - 1 &&
170
+ fromIndex < index &&
171
+ modifyChildren . props . className . includes ( cls [ '--' ] . hidden )
172
+ ) {
173
+ toIndex -- ;
174
+ }
175
+ move ( cloneAndAddClassName ( from . children ) , fromIndex , toIndex ) ;
176
+ } else moveFromGroup ( from . item , from . children , index ) ;
142
177
} else {
143
178
console . log ( 'uuuuuuuuuuup' ) ;
144
179
updateChildrenOf (
145
- cloneAndAddGhostClassName (
146
- childrenRef . current [ fromIndex ] as ReactElement ,
180
+ cloneAndAddClassName (
181
+ modifyChildrenRef . current [ fromIndex ] as ReactElement ,
147
182
) ,
148
183
fromIndex ,
149
184
) ;
@@ -155,25 +190,29 @@ export function useDraggableChildren({
155
190
console . log ( 'id===id' , id2 === id ) ;
156
191
if ( id2 !== id ) {
157
192
stateRef . current . index = - 1 ;
158
- if ( ! list . includes ( from . item ) ) {
193
+ if ( ! listRef . current . origin . includes ( from . item ) ) {
159
194
removeItem ( from . item ) ;
160
195
}
161
- // if (item === _item && type === 'move') {
162
- // console.log('mmmmmove');
163
- // // target.classList.add(cls['--'].hidden);
164
- // removeItem(_item);
165
- // }
196
+ if ( type === 'move' ) {
197
+ console . log ( 'mmmmmmmmm' , item , from . item ) ;
198
+ updateChildrenOf (
199
+ cloneAndAddClassName ( from . children , cls [ '--' ] . hidden ) ,
200
+ listRef . current . modify . indexOf ( from . item ) ,
201
+ ) ;
202
+ }
203
+ return ;
166
204
}
205
+ stateRef . current . index = - 1 ;
167
206
} ,
168
207
cancel : ( _id2 ) : void => {
169
208
console . log ( 'oncancel' , id , _id2 , prever . id , target ) ;
170
209
stateRef . current . index = - 1 ;
171
- if ( ! list . includes ( from . item ) ) {
210
+ if ( ! listRef . current . origin . includes ( from . item ) ) {
172
211
removeItem ( from . item ) ;
173
- preverRef . current = null ;
212
+ toRef . current = null ;
174
213
} else {
175
214
console . log ( 'ccccccccccccc' ) ;
176
- const index = listRef . current . indexOf ( from . item ) ;
215
+ const index = listRef . current . modify . indexOf ( from . item ) ;
177
216
// 还原成未加工状态
178
217
updateChildrenOf ( from . children , index ) ;
179
218
}
@@ -200,50 +239,54 @@ export function useDraggableChildren({
200
239
201
240
return children ;
202
241
203
- function move ( from : number , to : number ) {
204
- if ( from === - 1 || from === to ) return ;
205
- const temp = childrenRef . current . slice ( ) ;
206
- temp [ from ] = cloneAndAddGhostClassName ( temp [ from ] as ReactElement ) ;
242
+ function move ( children : ReactElement , from : number , to : number ) {
243
+ // if (from === -1 || from === to) return;
244
+ const temp = modifyChildrenRef . current . slice ( ) ;
245
+ temp [ from ] = children ;
207
246
moveItem ( temp , from , to ) ;
208
- childrenRef . current = temp ;
209
- moveItem ( listRef . current , from , to ) ;
247
+ modifyChildrenRef . current = temp ;
248
+ moveItem ( listRef . current . modify , from , to ) ;
210
249
forceUpdate ( ) ;
211
250
}
212
251
function moveFromGroup ( item : unknown , children : ReactElement , to : number ) {
213
252
console . log ( 'moveFromGroup' , item , to , item ) ;
214
- children = cloneAndAddGhostClassName ( children ) ;
215
- const temp = childrenRef . current . slice ( ) ;
253
+ children = cloneAndAddClassName ( children ) ;
254
+ const temp = modifyChildrenRef . current . slice ( ) ;
216
255
insertToArray ( children , to , temp ) ;
217
- childrenRef . current = temp ;
218
- insertToArray ( item , to , listRef . current ) ;
256
+ modifyChildrenRef . current = temp ;
257
+ insertToArray ( item , to , listRef . current . modify ) ;
219
258
forceUpdate ( ) ;
220
259
}
221
260
function updateChildrenOf ( children : ReactElement , index : number ) : void {
222
- const temp = childrenRef . current . slice ( ) ;
261
+ const temp = modifyChildrenRef . current . slice ( ) ;
223
262
// 还原成未加工状态
224
263
temp [ index ] = children ;
225
- childrenRef . current = temp ;
264
+ modifyChildrenRef . current = temp ;
226
265
forceUpdate ( ) ;
227
266
}
228
- function cloneAndAddGhostClassName ( element : ReactElement ) : ReactElement {
267
+ function cloneAndAddClassName (
268
+ element : ReactElement ,
269
+ className = cls . __ . ghost ,
270
+ ) : ReactElement {
229
271
return cloneElement ( element , {
230
- className : getClassNames ( element . props . className , cls . __ . ghost ) ,
272
+ className : getClassNames ( element . props . className , className ) ,
231
273
} ) ;
232
274
}
233
275
function removeItem ( item : unknown ) : void {
234
- const index = listRef . current . indexOf ( item ) ;
276
+ const index = listRef . current . modify . indexOf ( item ) ;
235
277
if ( index === - 1 ) return ;
236
- listRef . current . splice ( index , 1 ) ;
278
+ listRef . current . modify . splice ( index , 1 ) ;
237
279
238
- const temp = childrenRef . current . slice ( ) ;
280
+ const temp = modifyChildrenRef . current . slice ( ) ;
239
281
temp . splice ( index , 1 ) ;
240
- childrenRef . current = temp ;
282
+ modifyChildrenRef . current = temp ;
241
283
forceUpdate ( ) ;
242
284
}
243
285
function isListChanged ( ) : boolean {
286
+ const { origin, modify } = listRef . current ;
244
287
return (
245
- list . length !== listRef . current . length ||
246
- list . some ( ( it , i ) => it !== listRef . current [ i ] )
288
+ origin . length !== modify . length ||
289
+ origin . some ( ( it , i ) => it !== modify [ i ] )
247
290
) ;
248
291
}
249
292
}
0 commit comments