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