diff --git a/src/primitives/types.ts b/src/primitives/types.ts index dd683a6..188e481 100644 --- a/src/primitives/types.ts +++ b/src/primitives/types.ts @@ -25,6 +25,12 @@ export interface NavigableProps extends NodeProps { /** When auto scrolling, item index at which scrolling begins */ scrollIndex?: number; + /** + * When true and scroll is 'edge' or 'auto', the last item keeps the same + * position as the second-to-last instead of scrolling to remove trailing space. + */ + scrollStopLast?: boolean; + /** The initial index */ selected?: number; diff --git a/src/primitives/utils/withScrolling.ts b/src/primitives/utils/withScrolling.ts index db01780..1ed41ae 100644 --- a/src/primitives/utils/withScrolling.ts +++ b/src/primitives/utils/withScrolling.ts @@ -28,6 +28,7 @@ export interface ScrollableElement extends ElementNode { _targetPosition?: number; _screenOffset?: number; _initialPosition?: number; + scrollStopLast?: boolean; } // From the renderer, not exported @@ -185,7 +186,11 @@ export function withScrolling(isRow: boolean): Scroller { nextPosition = Math.min(Math.max(centerPosition, maxOffset), offset); } else if (!nextElement) { // If at the last element, align to end - nextPosition = isIncrementing ? maxOffset : offset; + if (componentRef.scrollStopLast && isIncrementing) { + nextPosition = rootPosition - selectedSize - gap; + } else { + nextPosition = isIncrementing ? maxOffset : offset; + } } else if (scroll === 'auto') { if (componentRef.scrollIndex && componentRef.scrollIndex > 0) { // Prevent scrolling if the selected item is within the last scrollIndex items @@ -213,8 +218,13 @@ export function withScrolling(isRow: boolean): Scroller { } // Prevent container from moving beyond bounds + const isScrollStopLastCase = + componentRef.scrollStopLast && !nextElement && isIncrementing; nextPosition = - isIncrementing && scroll !== 'always' && scroll !== 'bounded' + isIncrementing && + scroll !== 'always' && + scroll !== 'bounded' && + !isScrollStopLastCase ? Math.max(nextPosition, maxOffset) : Math.min(nextPosition, offset);