@@ -68,6 +68,11 @@ type LegacyCanvasRenderingContext2D = CanvasRenderingContext2D & {
6868 backingStorePixelRatio ?: number ;
6969} ;
7070
71+ export type StickyOptions = {
72+ shouldStickBottom ?: boolean ;
73+ shouldStickRight ?: boolean ;
74+ } ;
75+
7176export type GridProps = typeof Grid . defaultProps & {
7277 // Options to set on the canvas
7378 canvasOptions ?: CanvasRenderingContext2DSettings ;
@@ -1181,26 +1186,42 @@ class Grid extends PureComponent<GridProps, GridState> {
11811186 * @param deltaColumn Number of columns to move the cursor
11821187 * @param deltaRow Number of rows to move the cursor
11831188 * @param extendSelection True if the current selection should be extended, false to start a new selection
1189+ * @param stickyOptions Options for sticky behavior
11841190 */
11851191 moveCursor (
11861192 deltaColumn : number ,
11871193 deltaRow : number ,
1188- extendSelection : boolean
1194+ extendSelection : boolean ,
1195+ stickyOptions ?: StickyOptions
11891196 ) : void {
11901197 const { cursorRow, cursorColumn, selectionEndColumn, selectionEndRow } =
11911198 this . state ;
11921199 const column = extendSelection ? selectionEndColumn : cursorColumn ;
11931200 const row = extendSelection ? selectionEndRow : cursorRow ;
11941201 if ( row === null || column === null ) {
11951202 const { left, top } = this . state ;
1196- this . moveCursorToPosition ( left , top , extendSelection ) ;
1203+ this . moveCursorToPosition (
1204+ left ,
1205+ top ,
1206+ extendSelection ,
1207+ true ,
1208+ false ,
1209+ stickyOptions
1210+ ) ;
11971211 } else {
11981212 const { model } = this . props ;
11991213 const { columnCount, rowCount } = model ;
12001214
12011215 const left = clamp ( column + deltaColumn , 0 , columnCount - 1 ) ;
12021216 const top = clamp ( row + deltaRow , 0 , rowCount - 1 ) ;
1203- this . moveCursorToPosition ( left , top , extendSelection ) ;
1217+ this . moveCursorToPosition (
1218+ left ,
1219+ top ,
1220+ extendSelection ,
1221+ true ,
1222+ false ,
1223+ stickyOptions
1224+ ) ;
12041225 }
12051226 }
12061227
@@ -1260,13 +1281,15 @@ class Grid extends PureComponent<GridProps, GridState> {
12601281 * @param extendSelection Whether to extend the current selection (eg. holding Shift)
12611282 * @param keepCursorInView Whether to move the viewport so that the cursor is in view
12621283 * @param maximizePreviousRange With this and `extendSelection` true, it will maximize/add to the previous range only, ignoring where the selection was started
1284+ * @param stickyOptions Options for sticky behavior
12631285 */
12641286 moveCursorToPosition (
12651287 column : GridRangeIndex ,
12661288 row : GridRangeIndex ,
12671289 extendSelection = false ,
12681290 keepCursorInView = true ,
1269- maximizePreviousRange = false
1291+ maximizePreviousRange = false ,
1292+ stickyOptions ?: StickyOptions
12701293 ) : void {
12711294 if ( ! extendSelection ) {
12721295 this . beginSelection ( column , row ) ;
@@ -1275,7 +1298,7 @@ class Grid extends PureComponent<GridProps, GridState> {
12751298 this . moveSelection ( column , row , extendSelection , maximizePreviousRange ) ;
12761299
12771300 if ( keepCursorInView ) {
1278- this . moveViewToCell ( column , row ) ;
1301+ this . moveViewToCell ( column , row , stickyOptions ) ;
12791302 }
12801303 }
12811304
@@ -1284,8 +1307,13 @@ class Grid extends PureComponent<GridProps, GridState> {
12841307 *
12851308 * @param column The column index to bring into view
12861309 * @param row The row index to bring into view
1310+ * @param stickyOptions Options for sticky behavior
12871311 */
1288- moveViewToCell ( column : GridRangeIndex , row : GridRangeIndex ) : void {
1312+ moveViewToCell (
1313+ column : GridRangeIndex ,
1314+ row : GridRangeIndex ,
1315+ stickyOptions ?: StickyOptions
1316+ ) : void {
12891317 if ( ! this . metrics ) throw new Error ( 'metrics not set' ) ;
12901318
12911319 const { metricCalculator } = this ;
@@ -1314,26 +1342,41 @@ class Grid extends PureComponent<GridProps, GridState> {
13141342 }
13151343 }
13161344
1317- this . setViewState ( { top, left, topOffset, leftOffset } ) ;
1345+ this . setViewState (
1346+ { top, left, topOffset, leftOffset } ,
1347+ false ,
1348+ stickyOptions
1349+ ) ;
13181350 }
13191351
13201352 /**
13211353 * Checks the `top` and `left` properties that are set and updates the isStuckToBottom/Right properties
13221354 * Should be called when user interaction occurs
13231355 * @param viewState New state properties to set.
13241356 * @param forceUpdate Whether to force an update.
1357+ * @param stickyOptions Options for sticky behavior
13251358 */
1326- setViewState ( viewState : Partial < GridState > , forceUpdate = false ) : void {
1359+
1360+ setViewState (
1361+ viewState : Partial < GridState > ,
1362+ forceUpdate = false ,
1363+ stickyOptions ?: StickyOptions
1364+ ) : void {
13271365 if ( ! this . metrics ) throw new Error ( 'metrics not set' ) ;
13281366
13291367 const { isStickyBottom, isStickyRight } = this . props ;
13301368 const { top, left } = viewState ;
13311369 const { lastTop, lastLeft } = this . metrics ;
1332- if ( top != null ) {
1333- this . setState ( { isStuckToBottom : isStickyBottom && top >= lastTop } ) ;
1370+
1371+ if ( top != null && ( stickyOptions ?. shouldStickBottom ?? false ) ) {
1372+ this . setState ( {
1373+ isStuckToBottom : isStickyBottom && top >= lastTop ,
1374+ } ) ;
13341375 }
1335- if ( left != null ) {
1336- this . setState ( { isStuckToRight : isStickyRight && left >= lastLeft } ) ;
1376+ if ( left != null && ( stickyOptions ?. shouldStickRight ?? false ) ) {
1377+ this . setState ( {
1378+ isStuckToRight : isStickyRight && left >= lastLeft ,
1379+ } ) ;
13371380 }
13381381
13391382 this . setState ( viewState as GridState ) ;
@@ -1978,7 +2021,15 @@ class Grid extends PureComponent<GridProps, GridState> {
19782021 }
19792022 }
19802023
1981- this . setViewState ( { top, left, leftOffset, topOffset } ) ;
2024+ const stickyOptions : StickyOptions = {
2025+ shouldStickBottom : event . deltaY > 0 ,
2026+ shouldStickRight : event . deltaX > 0 ,
2027+ } ;
2028+ this . setViewState (
2029+ { top, left, leftOffset, topOffset } ,
2030+ false ,
2031+ stickyOptions
2032+ ) ;
19822033
19832034 event . stopPropagation ( ) ;
19842035 event . preventDefault ( ) ;
0 commit comments