@@ -30,6 +30,12 @@ import {moveItemInArray} from './drag-utils';
30
30
/** Counter used to generate unique ids for drop zones. */
31
31
let _uniqueIdCounter = 0 ;
32
32
33
+ /**
34
+ * Proximity, as a ratio to width/height, at which a
35
+ * dragged item will affect the drop container.
36
+ */
37
+ const DROP_PROXIMITY_THRESHOLD = 0.05 ;
38
+
33
39
/** Container that wraps a set of draggable items. */
34
40
@Component ( {
35
41
moduleId : module . id ,
@@ -112,7 +118,8 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
112
118
/** Cache of the dimensions of all the items and the sibling containers. */
113
119
private _positionCache = {
114
120
items : [ ] as { drag : CdkDrag , clientRect : ClientRect , offset : number } [ ] ,
115
- siblings : [ ] as { drop : CdkDrop , clientRect : ClientRect } [ ]
121
+ siblings : [ ] as { drop : CdkDrop , clientRect : ClientRect } [ ] ,
122
+ self : { } as ClientRect
116
123
} ;
117
124
118
125
/**
@@ -150,16 +157,16 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
150
157
/**
151
158
* Emits an event to indicate that the user moved an item into the container.
152
159
* @param item Item that was moved into the container.
153
- * @param xOffset Position of the item along the X axis.
154
- * @param yOffset Position of the item along the Y axis.
160
+ * @param pointerX Position of the item along the X axis.
161
+ * @param pointerY Position of the item along the Y axis.
155
162
*/
156
- enter ( item : CdkDrag , xOffset : number , yOffset : number ) : void {
163
+ enter ( item : CdkDrag , pointerX : number , pointerY : number ) : void {
157
164
this . entered . emit ( { item, container : this } ) ;
158
165
this . start ( ) ;
159
166
160
167
// We use the coordinates of where the item entered the drop
161
168
// zone to figure out at which index it should be inserted.
162
- const newIndex = this . _getItemIndexFromPointerPosition ( item , xOffset , yOffset ) ;
169
+ const newIndex = this . _getItemIndexFromPointerPosition ( item , pointerX , pointerY ) ;
163
170
const currentIndex = this . _activeDraggables . indexOf ( item ) ;
164
171
const newPositionReference = this . _activeDraggables [ newIndex ] ;
165
172
const placeholder = item . getPlaceholderElement ( ) ;
@@ -211,12 +218,17 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
211
218
/**
212
219
* Sorts an item inside the container based on its position.
213
220
* @param item Item to be sorted.
214
- * @param xOffset Position of the item along the X axis.
215
- * @param yOffset Position of the item along the Y axis.
221
+ * @param pointerX Position of the item along the X axis.
222
+ * @param pointerY Position of the item along the Y axis.
216
223
*/
217
- _sortItem ( item : CdkDrag , xOffset : number , yOffset : number ) : void {
224
+ _sortItem ( item : CdkDrag , pointerX : number , pointerY : number ) : void {
225
+ // Don't sort the item if it's out of range.
226
+ if ( ! this . _isPointerNearDropContainer ( pointerX , pointerY ) ) {
227
+ return ;
228
+ }
229
+
218
230
const siblings = this . _positionCache . items ;
219
- const newIndex = this . _getItemIndexFromPointerPosition ( item , xOffset , yOffset ) ;
231
+ const newIndex = this . _getItemIndexFromPointerPosition ( item , pointerX , pointerY ) ;
220
232
221
233
if ( newIndex === - 1 && siblings . length > 0 ) {
222
234
return ;
@@ -321,6 +333,8 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
321
333
. map ( drop => typeof drop === 'string' ? this . _dragDropRegistry . getDropContainer ( drop ) ! : drop )
322
334
. filter ( drop => drop && drop !== this )
323
335
. map ( drop => ( { drop, clientRect : drop . element . nativeElement . getBoundingClientRect ( ) } ) ) ;
336
+
337
+ this . _positionCache . self = this . element . nativeElement . getBoundingClientRect ( ) ;
324
338
}
325
339
326
340
/** Resets the container to its initial state. */
@@ -351,10 +365,10 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
351
365
/**
352
366
* Gets the index of an item in the drop container, based on the position of the user's pointer.
353
367
* @param item Item that is being sorted.
354
- * @param xOffset Position of the user's pointer along the X axis.
355
- * @param yOffset Position of the user's pointer along the Y axis.
368
+ * @param pointerX Position of the user's pointer along the X axis.
369
+ * @param pointerY Position of the user's pointer along the Y axis.
356
370
*/
357
- private _getItemIndexFromPointerPosition ( item : CdkDrag , xOffset : number , yOffset : number ) {
371
+ private _getItemIndexFromPointerPosition ( item : CdkDrag , pointerX : number , pointerY : number ) {
358
372
return this . _positionCache . items . findIndex ( ( { drag, clientRect} , _ , array ) => {
359
373
if ( drag === item ) {
360
374
// If there's only one item left in the container, it must be
@@ -365,8 +379,22 @@ export class CdkDrop<T = any> implements OnInit, OnDestroy {
365
379
return this . orientation === 'horizontal' ?
366
380
// Round these down since most browsers report client rects with
367
381
// sub-pixel precision, whereas the mouse coordinates are rounded to pixels.
368
- xOffset >= Math . floor ( clientRect . left ) && xOffset <= Math . floor ( clientRect . right ) :
369
- yOffset >= Math . floor ( clientRect . top ) && yOffset <= Math . floor ( clientRect . bottom ) ;
382
+ pointerX >= Math . floor ( clientRect . left ) && pointerX <= Math . floor ( clientRect . right ) :
383
+ pointerY >= Math . floor ( clientRect . top ) && pointerY <= Math . floor ( clientRect . bottom ) ;
370
384
} ) ;
371
385
}
386
+
387
+ /**
388
+ * Checks whether the pointer coordinates are close to the drop container.
389
+ * @param pointerX Coordinates along the X axis.
390
+ * @param pointerY Coordinates along the Y axis.
391
+ */
392
+ private _isPointerNearDropContainer ( pointerX : number , pointerY : number ) : boolean {
393
+ const { top, right, bottom, left, width, height} = this . _positionCache . self ;
394
+ const xThreshold = width * DROP_PROXIMITY_THRESHOLD ;
395
+ const yThreshold = height * DROP_PROXIMITY_THRESHOLD ;
396
+
397
+ return pointerY > top - yThreshold && pointerY < bottom + yThreshold &&
398
+ pointerX > left - xThreshold && pointerX < right + xThreshold ;
399
+ }
372
400
}
0 commit comments