@@ -93,6 +93,33 @@ export function filterSelectionMenuItems(items, options) {
9393 } ) ;
9494}
9595
96+ /**
97+ * Detect which edge(s) should trigger drag auto-scroll.
98+ * @param {{
99+ * x:number,
100+ * y:number,
101+ * rect:{left:number,right:number,top:number,bottom:number},
102+ * allowHorizontal?:boolean,
103+ * gap?:number,
104+ * }} options
105+ * @returns {{horizontal:number, vertical:number} }
106+ */
107+ export function getEdgeScrollDirections ( options ) {
108+ const { x, y, rect, allowHorizontal = true , gap = EDGE_SCROLL_GAP } = options ;
109+ let horizontal = 0 ;
110+ let vertical = 0 ;
111+
112+ if ( allowHorizontal ) {
113+ if ( x < rect . left + gap ) horizontal = - 1 ;
114+ else if ( x > rect . right - gap ) horizontal = 1 ;
115+ }
116+
117+ if ( y < rect . top + gap ) vertical = - 1 ;
118+ else if ( y > rect . bottom - gap ) vertical = 1 ;
119+
120+ return { horizontal, vertical } ;
121+ }
122+
96123function clamp ( value , min , max ) {
97124 return Math . max ( min , Math . min ( max , value ) ) ;
98125}
@@ -1014,7 +1041,8 @@ class TouchSelectionMenuController {
10141041 startX : x ,
10151042 startY : y ,
10161043 moved : false ,
1017- direction : 0 ,
1044+ scrollX : 0 ,
1045+ scrollY : 0 ,
10181046 fixedPos :
10191047 type === "start" ? range . to : type === "end" ? range . from : null ,
10201048 } ;
@@ -1098,28 +1126,73 @@ class TouchSelectionMenuController {
10981126 this . #view. focus ( ) ;
10991127 }
11001128
1129+ #getAutoScrollDelta( x , y ) {
1130+ const scroller = this . #view. scrollDOM ;
1131+ const rect = scroller . getBoundingClientRect ( ) ;
1132+ const { horizontal, vertical } = getEdgeScrollDirections ( {
1133+ x,
1134+ y,
1135+ rect,
1136+ allowHorizontal : ! this . #view. lineWrapping ,
1137+ } ) ;
1138+ const maxScrollLeft = Math . max (
1139+ 0 ,
1140+ scroller . scrollWidth - scroller . clientWidth ,
1141+ ) ;
1142+ const maxScrollTop = Math . max (
1143+ 0 ,
1144+ scroller . scrollHeight - scroller . clientHeight ,
1145+ ) ;
1146+ let scrollX = horizontal * EDGE_SCROLL_STEP ;
1147+ let scrollY = vertical * EDGE_SCROLL_STEP ;
1148+
1149+ if (
1150+ ( scrollX < 0 && scroller . scrollLeft <= 0 ) ||
1151+ ( scrollX > 0 && scroller . scrollLeft >= maxScrollLeft )
1152+ ) {
1153+ scrollX = 0 ;
1154+ }
1155+
1156+ if (
1157+ ( scrollY < 0 && scroller . scrollTop <= 0 ) ||
1158+ ( scrollY > 0 && scroller . scrollTop >= maxScrollTop )
1159+ ) {
1160+ scrollY = 0 ;
1161+ }
1162+
1163+ return { scrollX, scrollY } ;
1164+ }
1165+
11011166 #startAutoScrollIfNeeded( x , y ) {
1102- const rect = this . #view. scrollDOM . getBoundingClientRect ( ) ;
1103- let direction = 0 ;
1104- if ( y < rect . top + EDGE_SCROLL_GAP ) direction = - 1 ;
1105- if ( y > rect . bottom - EDGE_SCROLL_GAP ) direction = 1 ;
1167+ const { scrollX, scrollY } = this . #getAutoScrollDelta( x , y ) ;
1168+ if ( this . #dragState) {
1169+ this . #dragState. scrollX = scrollX ;
1170+ this . #dragState. scrollY = scrollY ;
1171+ }
11061172
1107- if ( ! direction ) {
1173+ if ( ! scrollX && ! scrollY ) {
11081174 this . #stopAutoScroll( ) ;
11091175 return ;
11101176 }
11111177
1112- this . #dragState. direction = direction ;
11131178 if ( this . #autoScrollRaf) return ;
11141179
11151180 const tick = ( ) => {
1116- if ( ! this . #dragState?. direction ) {
1181+ if ( ! this . #dragState) {
1182+ this . #autoScrollRaf = 0 ;
1183+ return ;
1184+ }
1185+
1186+ const delta = this . #getAutoScrollDelta( this . #pointer. x , this . #pointer. y ) ;
1187+ this . #dragState. scrollX = delta . scrollX ;
1188+ this . #dragState. scrollY = delta . scrollY ;
1189+ if ( ! delta . scrollX && ! delta . scrollY ) {
11171190 this . #autoScrollRaf = 0 ;
11181191 return ;
11191192 }
11201193
1121- this . #view. scrollDOM . scrollTop +=
1122- this . #dragState . direction * EDGE_SCROLL_STEP ;
1194+ this . #view. scrollDOM . scrollLeft += delta . scrollX ;
1195+ this . #view . scrollDOM . scrollTop += delta . scrollY ;
11231196 this . #dragTo( this . #pointer. x , this . #pointer. y ) ;
11241197 this . #autoScrollRaf = requestAnimationFrame ( tick ) ;
11251198 } ;
@@ -1131,7 +1204,8 @@ class TouchSelectionMenuController {
11311204 cancelAnimationFrame ( this . #autoScrollRaf) ;
11321205 this . #autoScrollRaf = 0 ;
11331206 if ( this . #dragState) {
1134- this . #dragState. direction = 0 ;
1207+ this . #dragState. scrollX = 0 ;
1208+ this . #dragState. scrollY = 0 ;
11351209 }
11361210 }
11371211
0 commit comments