@@ -517,31 +517,28 @@ export class DropListRef<T = any> {
517
517
let verticalScrollDirection = AutoScrollVerticalDirection . NONE ;
518
518
let horizontalScrollDirection = AutoScrollHorizontalDirection . NONE ;
519
519
520
+ // Check whether we should start scrolling the container.
521
+ if ( this . _isPointerNearDropContainer ( pointerX , pointerY ) ) {
522
+ const element = coerceElement ( this . element ) ;
523
+
524
+ [ verticalScrollDirection , horizontalScrollDirection ] =
525
+ getElementScrollDirections ( element , this . _clientRect , pointerX , pointerY ) ;
526
+
527
+ if ( verticalScrollDirection || horizontalScrollDirection ) {
528
+ scrollNode = element ;
529
+ }
530
+ }
531
+
520
532
// @breaking -change 9.0.0 Remove null check for _viewportRuler once it's a required parameter.
521
- // Check whether we're in range to scroll the viewport.
522
- if ( this . _viewportRuler ) {
533
+ // Otherwise check if we can start scrolling the viewport.
534
+ if ( this . _viewportRuler && ! verticalScrollDirection && ! horizontalScrollDirection ) {
523
535
const { width, height} = this . _viewportRuler . getViewportSize ( ) ;
524
536
const clientRect = { width, height, top : 0 , right : width , bottom : height , left : 0 } ;
525
537
verticalScrollDirection = getVerticalScrollDirection ( clientRect , pointerY ) ;
526
538
horizontalScrollDirection = getHorizontalScrollDirection ( clientRect , pointerX ) ;
527
539
scrollNode = window ;
528
540
}
529
541
530
- // If we couldn't find a scroll direction based on the
531
- // window, try with the container, if the pointer is close by.
532
- if ( ! verticalScrollDirection && ! horizontalScrollDirection &&
533
- this . _isPointerNearDropContainer ( pointerX , pointerY ) ) {
534
- verticalScrollDirection = getVerticalScrollDirection ( this . _clientRect , pointerY ) ;
535
- horizontalScrollDirection = getHorizontalScrollDirection ( this . _clientRect , pointerX ) ;
536
- scrollNode = coerceElement ( this . element ) ;
537
- }
538
-
539
- // TODO(crisbeto): we also need to account for whether the view or element are scrollable in
540
- // the first place. With the current approach we'll still try to scroll them, but it just
541
- // won't do anything. The only case where this is relevant is that if we have a scrollable
542
- // list close to the viewport edge where the viewport isn't scrollable. In this case the
543
- // we'll be trying to scroll the viewport rather than the list.
544
-
545
542
if ( scrollNode && ( verticalScrollDirection !== this . _verticalScrollDirection ||
546
543
horizontalScrollDirection !== this . _horizontalScrollDirection ||
547
544
scrollNode !== this . _scrollNode ) ) {
@@ -994,3 +991,49 @@ function getHorizontalScrollDirection(clientRect: ClientRect, pointerX: number)
994
991
995
992
return AutoScrollHorizontalDirection . NONE ;
996
993
}
994
+
995
+ /**
996
+ * Gets the directions in which an element node should be scrolled,
997
+ * assuming that the user's pointer is already within it scrollable region.
998
+ * @param element Element for which we should calculate the scroll direction.
999
+ * @param clientRect Bounding client rectangle of the element.
1000
+ * @param pointerX Position of the user's pointer along the x axis.
1001
+ * @param pointerY Position of the user's pointer along the y axis.
1002
+ */
1003
+ function getElementScrollDirections ( element : HTMLElement , clientRect : ClientRect , pointerX : number ,
1004
+ pointerY : number ) : [ AutoScrollVerticalDirection , AutoScrollHorizontalDirection ] {
1005
+ const computedVertical = getVerticalScrollDirection ( clientRect , pointerY ) ;
1006
+ const computedHorizontal = getHorizontalScrollDirection ( clientRect , pointerX ) ;
1007
+ let verticalScrollDirection = AutoScrollVerticalDirection . NONE ;
1008
+ let horizontalScrollDirection = AutoScrollHorizontalDirection . NONE ;
1009
+
1010
+ // Note that we here we do some extra checks for whether the element is actually scrollable in
1011
+ // a certain direction and we only assign the scroll direction if it is. We do this so that we
1012
+ // can allow other elements to be scrolled, if the current element can't be scrolled anymore.
1013
+ // This allows us to handle cases where the scroll regions of two scrollable elements overlap.
1014
+ if ( computedVertical ) {
1015
+ const scrollTop = element . scrollTop ;
1016
+
1017
+ if ( computedVertical === AutoScrollVerticalDirection . UP ) {
1018
+ if ( scrollTop > 0 ) {
1019
+ verticalScrollDirection = AutoScrollVerticalDirection . UP ;
1020
+ }
1021
+ } else if ( element . scrollHeight - scrollTop > element . clientHeight ) {
1022
+ verticalScrollDirection = AutoScrollVerticalDirection . DOWN ;
1023
+ }
1024
+ }
1025
+
1026
+ if ( computedHorizontal ) {
1027
+ const scrollLeft = element . scrollLeft ;
1028
+
1029
+ if ( computedHorizontal === AutoScrollHorizontalDirection . LEFT ) {
1030
+ if ( scrollLeft > 0 ) {
1031
+ horizontalScrollDirection = AutoScrollHorizontalDirection . LEFT ;
1032
+ }
1033
+ } else if ( element . scrollWidth - scrollLeft > element . clientWidth ) {
1034
+ horizontalScrollDirection = AutoScrollHorizontalDirection . RIGHT ;
1035
+ }
1036
+ }
1037
+
1038
+ return [ verticalScrollDirection , horizontalScrollDirection ] ;
1039
+ }
0 commit comments