@@ -146,7 +146,7 @@ export class DropListRef<T = any> {
146
146
private _parentPositions : ParentPositionTracker ;
147
147
148
148
/** Cached `ClientRect` of the drop list. */
149
- private _clientRect : ClientRect ;
149
+ private _clientRect : ClientRect | undefined ;
150
150
151
151
/**
152
152
* Draggable items that are currently active inside the container. Includes the items
@@ -163,7 +163,7 @@ export class DropListRef<T = any> {
163
163
private _previousSwap = { drag : null as DragRef | null , delta : 0 , overlaps : false } ;
164
164
165
165
/** Draggable items in the container. */
166
- private _draggables : ReadonlyArray < DragRef > ;
166
+ private _draggables : ReadonlyArray < DragRef > = [ ] ;
167
167
168
168
/** Drop lists that are connected to the current one. */
169
169
private _siblings : ReadonlyArray < DropListRef > = [ ] ;
@@ -240,19 +240,8 @@ export class DropListRef<T = any> {
240
240
241
241
/** Starts dragging an item. */
242
242
start ( ) : void {
243
- const styles = coerceElement ( this . element ) . style as DragCSSStyleDeclaration ;
244
- this . beforeStarted . next ( ) ;
245
- this . _isDragging = true ;
246
-
247
- // We need to disable scroll snapping while the user is dragging, because it breaks automatic
248
- // scrolling. The browser seems to round the value based on the snapping points which means
249
- // that we can't increment/decrement the scroll position.
250
- this . _initialScrollSnap = styles . msScrollSnapType || styles . scrollSnapType || '' ;
251
- styles . scrollSnapType = styles . msScrollSnapType = 'none' ;
252
- this . _cacheItems ( ) ;
253
- this . _siblings . forEach ( sibling => sibling . _startReceiving ( this ) ) ;
254
- this . _viewportScrollSubscription . unsubscribe ( ) ;
255
- this . _listenToScrollEvents ( ) ;
243
+ this . _draggingStarted ( ) ;
244
+ this . _notifyReceivingSiblings ( ) ;
256
245
}
257
246
258
247
/**
@@ -264,7 +253,7 @@ export class DropListRef<T = any> {
264
253
* out automatically.
265
254
*/
266
255
enter ( item : DragRef , pointerX : number , pointerY : number , index ?: number ) : void {
267
- this . start ( ) ;
256
+ this . _draggingStarted ( ) ;
268
257
269
258
// If sorting is disabled, we want the item to return to its starting
270
259
// position if the user is returning it to its initial container.
@@ -323,6 +312,8 @@ export class DropListRef<T = any> {
323
312
this . _cacheItemPositions ( ) ;
324
313
this . _cacheParentPositions ( ) ;
325
314
315
+ // Notify siblings at the end so that the item has been inserted into the `activeDraggables`.
316
+ this . _notifyReceivingSiblings ( ) ;
326
317
this . entered . next ( { item, container : this , currentIndex : this . getItemIndex ( item ) } ) ;
327
318
}
328
319
@@ -463,7 +454,7 @@ export class DropListRef<T = any> {
463
454
_sortItem ( item : DragRef , pointerX : number , pointerY : number ,
464
455
pointerDelta : { x : number , y : number } ) : void {
465
456
// Don't sort the item if sorting is disabled or it's out of range.
466
- if ( this . sortingDisabled ||
457
+ if ( this . sortingDisabled || ! this . _clientRect ||
467
458
! isPointerNearClientRect ( this . _clientRect , DROP_PROXIMITY_THRESHOLD , pointerX , pointerY ) ) {
468
459
return ;
469
460
}
@@ -600,6 +591,22 @@ export class DropListRef<T = any> {
600
591
this . _stopScrollTimers . next ( ) ;
601
592
}
602
593
594
+ /** Starts the dragging sequence within the list. */
595
+ private _draggingStarted ( ) {
596
+ const styles = coerceElement ( this . element ) . style as DragCSSStyleDeclaration ;
597
+ this . beforeStarted . next ( ) ;
598
+ this . _isDragging = true ;
599
+
600
+ // We need to disable scroll snapping while the user is dragging, because it breaks automatic
601
+ // scrolling. The browser seems to round the value based on the snapping points which means
602
+ // that we can't increment/decrement the scroll position.
603
+ this . _initialScrollSnap = styles . msScrollSnapType || styles . scrollSnapType || '' ;
604
+ styles . scrollSnapType = styles . msScrollSnapType = 'none' ;
605
+ this . _cacheItems ( ) ;
606
+ this . _viewportScrollSubscription . unsubscribe ( ) ;
607
+ this . _listenToScrollEvents ( ) ;
608
+ }
609
+
603
610
/** Caches the positions of the configured scrollable parents. */
604
611
private _cacheParentPositions ( ) {
605
612
const element = coerceElement ( this . element ) ;
@@ -802,7 +809,7 @@ export class DropListRef<T = any> {
802
809
* @param y Pointer position along the Y axis.
803
810
*/
804
811
_isOverContainer ( x : number , y : number ) : boolean {
805
- return isInsideClientRect ( this . _clientRect , x , y ) ;
812
+ return this . _clientRect != null && isInsideClientRect ( this . _clientRect , x , y ) ;
806
813
}
807
814
808
815
/**
@@ -823,7 +830,8 @@ export class DropListRef<T = any> {
823
830
* @param y Position of the item along the Y axis.
824
831
*/
825
832
_canReceive ( item : DragRef , x : number , y : number ) : boolean {
826
- if ( ! isInsideClientRect ( this . _clientRect , x , y ) || ! this . enterPredicate ( item , this ) ) {
833
+ if ( ! this . _clientRect || ! isInsideClientRect ( this . _clientRect , x , y ) ||
834
+ ! this . enterPredicate ( item , this ) ) {
827
835
return false ;
828
836
}
829
837
@@ -850,10 +858,16 @@ export class DropListRef<T = any> {
850
858
* Called by one of the connected drop lists when a dragging sequence has started.
851
859
* @param sibling Sibling in which dragging has started.
852
860
*/
853
- _startReceiving ( sibling : DropListRef ) {
861
+ _startReceiving ( sibling : DropListRef , items : DragRef [ ] ) {
854
862
const activeSiblings = this . _activeSiblings ;
855
863
856
- if ( ! activeSiblings . has ( sibling ) ) {
864
+ if ( ! activeSiblings . has ( sibling ) && items . every ( item => {
865
+ // Note that we have to add an exception to the `enterPredicate` for items that started off
866
+ // in this drop list. The drag ref has logic that allows an item to return to its initial
867
+ // container, if it has left the initial container and none of the connected containers
868
+ // allow it to enter. See `DragRef._updateActiveDropContainer` for more context.
869
+ return this . enterPredicate ( item , this ) || this . _draggables . indexOf ( item ) > - 1 ;
870
+ } ) ) {
857
871
activeSiblings . add ( sibling ) ;
858
872
this . _cacheParentPositions ( ) ;
859
873
this . _listenToScrollEvents ( ) ;
@@ -917,6 +931,12 @@ export class DropListRef<T = any> {
917
931
918
932
return this . _cachedShadowRoot ;
919
933
}
934
+
935
+ /** Notifies any siblings that may potentially receive the item. */
936
+ private _notifyReceivingSiblings ( ) {
937
+ const draggedItems = this . _activeDraggables . filter ( item => item . isDragging ( ) ) ;
938
+ this . _siblings . forEach ( sibling => sibling . _startReceiving ( this , draggedItems ) ) ;
939
+ }
920
940
}
921
941
922
942
0 commit comments