Skip to content

Commit

Permalink
fix: stuck to bottom on filter clear (#1579)
Browse files Browse the repository at this point in the history
Closes #1477 

Previous comments are in #1571 PR. 

Note: Once this PR is merged #1571 can go in as well
  • Loading branch information
ethanalvizo authored Oct 27, 2023
1 parent b065f1c commit ef52749
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 21 deletions.
77 changes: 64 additions & 13 deletions packages/grid/src/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ type LegacyCanvasRenderingContext2D = CanvasRenderingContext2D & {
backingStorePixelRatio?: number;
};

export type StickyOptions = {
shouldStickBottom?: boolean;
shouldStickRight?: boolean;
};

export type GridProps = typeof Grid.defaultProps & {
// Options to set on the canvas
canvasOptions?: CanvasRenderingContext2DSettings;
Expand Down Expand Up @@ -1181,26 +1186,42 @@ class Grid extends PureComponent<GridProps, GridState> {
* @param deltaColumn Number of columns to move the cursor
* @param deltaRow Number of rows to move the cursor
* @param extendSelection True if the current selection should be extended, false to start a new selection
* @param stickyOptions Options for sticky behavior
*/
moveCursor(
deltaColumn: number,
deltaRow: number,
extendSelection: boolean
extendSelection: boolean,
stickyOptions?: StickyOptions
): void {
const { cursorRow, cursorColumn, selectionEndColumn, selectionEndRow } =
this.state;
const column = extendSelection ? selectionEndColumn : cursorColumn;
const row = extendSelection ? selectionEndRow : cursorRow;
if (row === null || column === null) {
const { left, top } = this.state;
this.moveCursorToPosition(left, top, extendSelection);
this.moveCursorToPosition(
left,
top,
extendSelection,
true,
false,
stickyOptions
);
} else {
const { model } = this.props;
const { columnCount, rowCount } = model;

const left = clamp(column + deltaColumn, 0, columnCount - 1);
const top = clamp(row + deltaRow, 0, rowCount - 1);
this.moveCursorToPosition(left, top, extendSelection);
this.moveCursorToPosition(
left,
top,
extendSelection,
true,
false,
stickyOptions
);
}
}

Expand Down Expand Up @@ -1260,13 +1281,15 @@ class Grid extends PureComponent<GridProps, GridState> {
* @param extendSelection Whether to extend the current selection (eg. holding Shift)
* @param keepCursorInView Whether to move the viewport so that the cursor is in view
* @param maximizePreviousRange With this and `extendSelection` true, it will maximize/add to the previous range only, ignoring where the selection was started
* @param stickyOptions Options for sticky behavior
*/
moveCursorToPosition(
column: GridRangeIndex,
row: GridRangeIndex,
extendSelection = false,
keepCursorInView = true,
maximizePreviousRange = false
maximizePreviousRange = false,
stickyOptions?: StickyOptions
): void {
if (!extendSelection) {
this.beginSelection(column, row);
Expand All @@ -1275,7 +1298,7 @@ class Grid extends PureComponent<GridProps, GridState> {
this.moveSelection(column, row, extendSelection, maximizePreviousRange);

if (keepCursorInView) {
this.moveViewToCell(column, row);
this.moveViewToCell(column, row, stickyOptions);
}
}

Expand All @@ -1284,8 +1307,13 @@ class Grid extends PureComponent<GridProps, GridState> {
*
* @param column The column index to bring into view
* @param row The row index to bring into view
* @param stickyOptions Options for sticky behavior
*/
moveViewToCell(column: GridRangeIndex, row: GridRangeIndex): void {
moveViewToCell(
column: GridRangeIndex,
row: GridRangeIndex,
stickyOptions?: StickyOptions
): void {
if (!this.metrics) throw new Error('metrics not set');

const { metricCalculator } = this;
Expand Down Expand Up @@ -1314,26 +1342,41 @@ class Grid extends PureComponent<GridProps, GridState> {
}
}

this.setViewState({ top, left, topOffset, leftOffset });
this.setViewState(
{ top, left, topOffset, leftOffset },
false,
stickyOptions
);
}

/**
* Checks the `top` and `left` properties that are set and updates the isStuckToBottom/Right properties
* Should be called when user interaction occurs
* @param viewState New state properties to set.
* @param forceUpdate Whether to force an update.
* @param stickyOptions Options for sticky behavior
*/
setViewState(viewState: Partial<GridState>, forceUpdate = false): void {

setViewState(
viewState: Partial<GridState>,
forceUpdate = false,
stickyOptions?: StickyOptions
): void {
if (!this.metrics) throw new Error('metrics not set');

const { isStickyBottom, isStickyRight } = this.props;
const { top, left } = viewState;
const { lastTop, lastLeft } = this.metrics;
if (top != null) {
this.setState({ isStuckToBottom: isStickyBottom && top >= lastTop });

if (top != null && (stickyOptions?.shouldStickBottom ?? false)) {
this.setState({
isStuckToBottom: isStickyBottom && top >= lastTop,
});
}
if (left != null) {
this.setState({ isStuckToRight: isStickyRight && left >= lastLeft });
if (left != null && (stickyOptions?.shouldStickRight ?? false)) {
this.setState({
isStuckToRight: isStickyRight && left >= lastLeft,
});
}

this.setState(viewState as GridState);
Expand Down Expand Up @@ -1978,7 +2021,15 @@ class Grid extends PureComponent<GridProps, GridState> {
}
}

this.setViewState({ top, left, leftOffset, topOffset });
const stickyOptions: StickyOptions = {
shouldStickBottom: event.deltaY > 0,
shouldStickRight: event.deltaX > 0,
};
this.setViewState(
{ top, left, leftOffset, topOffset },
false,
stickyOptions
);

event.stopPropagation();
event.preventDefault();
Expand Down
28 changes: 20 additions & 8 deletions packages/grid/src/key-handlers/SelectionKeyHandler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint class-methods-use-this: "off" */
import clamp from 'lodash.clamp';
import { EventHandlerResult } from '../EventHandlerResult';
import Grid from '../Grid';
import Grid, { StickyOptions } from '../Grid';
import GridRange from '../GridRange';
import GridUtils from '../GridUtils';
import KeyHandler, { GridKeyboardEvent } from '../KeyHandler';
Expand Down Expand Up @@ -144,6 +144,11 @@ class SelectionKeyHandler extends KeyHandler {
grid.state;
const column = isShiftKey ? selectionEndColumn : cursorColumn;
const row = isShiftKey ? selectionEndRow : cursorRow;
const stickyOptions: StickyOptions = {
shouldStickBottom: deltaRow > 0,
shouldStickRight: deltaColumn > 0,
};

if (isModifierKey) {
const { model } = grid.props;
const { columnCount, rowCount } = model;
Expand All @@ -169,14 +174,16 @@ class SelectionKeyHandler extends KeyHandler {
moveToRow,
isShiftKey,
true,
maximizePreviousRange
maximizePreviousRange,
stickyOptions
);
}
} else {
if (!grid.metrics) throw new Error('grid.metrics are not set');

const { theme } = grid.props;
const { autoSelectRow = false, autoSelectColumn = false } = theme;

if (autoSelectRow && deltaColumn !== 0) {
const { lastLeft } = grid.metrics;
let { left } = grid.state;
Expand All @@ -185,7 +192,7 @@ class SelectionKeyHandler extends KeyHandler {

grid.moveCursorToPosition(left, cursorRow, isShiftKey, false);

grid.setViewState({ left });
grid.setViewState({ left }, false, stickyOptions);
} else if (autoSelectColumn && deltaRow !== 0) {
const { lastTop } = grid.metrics;
let { top } = grid.state;
Expand All @@ -194,9 +201,9 @@ class SelectionKeyHandler extends KeyHandler {

grid.moveCursorToPosition(top, cursorColumn, isShiftKey, false);

grid.setViewState({ top });
grid.setViewState({ top }, false, stickyOptions);
} else {
grid.moveCursor(deltaColumn, deltaRow, isShiftKey);
grid.moveCursor(deltaColumn, deltaRow, isShiftKey, stickyOptions);
}
}
return true;
Expand Down Expand Up @@ -242,8 +249,8 @@ class SelectionKeyHandler extends KeyHandler {
return true;
}

handlePageDown(e: GridKeyboardEvent, grid: Grid): boolean {
const isShiftKey = e.shiftKey;
handlePageDown(event: GridKeyboardEvent, grid: Grid): boolean {
const isShiftKey = event.shiftKey;

if (isShiftKey) {
grid.trimSelectedRanges();
Expand Down Expand Up @@ -279,7 +286,12 @@ class SelectionKeyHandler extends KeyHandler {
isShiftKey,
false
);
grid.setViewState({ top: viewportPosition });

const stickyOptions: StickyOptions = {
shouldStickBottom: true,
shouldStickRight: false,
};
grid.setViewState({ top: viewportPosition }, false, stickyOptions);

return true;
}
Expand Down

0 comments on commit ef52749

Please sign in to comment.