Skip to content

Commit d798073

Browse files
committed
fix: add wider range for stick to center boundaries
1 parent a50c225 commit d798073

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed

packages/lib/src/spatial-navigation/components/virtualizedList/SpatialNavigationVirtualizedList.test.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -335,15 +335,17 @@ describe('SpatialNavigationVirtualizedList', () => {
335335
renderItem={renderItem}
336336
data={data}
337337
itemSize={100}
338-
numberOfRenderedItems={5}
339-
numberOfItemsVisibleOnScreen={3}
340338
scrollBehavior="stick-to-center"
339+
additionalItemsRendered={0}
341340
/>
342341
</DefaultFocus>
343342
</SpatialNavigationRoot>,
344343
);
345344
act(() => jest.runAllTimers());
346345

346+
// Given this layout size, this item size, and the additional items rendered parameter:
347+
// - number of visible items on screen = 3
348+
// - total amount of items rendered = 5
347349
setComponentLayoutSize(listTestId, component, { width: 300, height: 300 });
348350

349351
const listElement = await component.findByTestId(listTestId);
@@ -410,9 +412,8 @@ describe('SpatialNavigationVirtualizedList', () => {
410412
renderItem={renderItem}
411413
data={data.slice(0, 3)}
412414
itemSize={100}
413-
numberOfRenderedItems={5}
414-
numberOfItemsVisibleOnScreen={3}
415415
scrollBehavior="stick-to-center"
416+
additionalItemsRendered={0}
416417
/>
417418
</DefaultFocus>
418419
</SpatialNavigationRoot>,

packages/lib/src/spatial-navigation/components/virtualizedList/VirtualizedList.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import { computeAllScrollOffsets } from './helpers/createScrollOffsetArray';
1212
import { getNumberOfItemsVisibleOnScreen } from './helpers/getNumberOfItemsVisibleOnScreen';
1313
import { getAdditionalNumberOfItemsRendered } from './helpers/getAdditionalNumberOfItemsRendered';
1414

15-
export type ScrollBehavior = 'stick-to-start' | 'stick-to-center' | 'stick-to-end' | 'jump-on-scroll';
15+
export type ScrollBehavior =
16+
| 'stick-to-start'
17+
| 'stick-to-center'
18+
| 'stick-to-end'
19+
| 'jump-on-scroll';
1620
export interface VirtualizedListProps<T> {
1721
data: T[];
1822
renderItem: (args: { item: T; index: number }) => JSX.Element;

packages/lib/src/spatial-navigation/components/virtualizedList/helpers/getRange.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,39 @@ describe('getRange for custom virtualized list', () => {
5858
expect(expectedResult).toEqual(result);
5959
expect(console.error).toHaveBeenCalledTimes(1);
6060
});
61+
62+
describe('stick-to-center', () => {
63+
it.each`
64+
description | arraySize | focusIndex | result
65+
${'empty array'} | ${0} | ${0} | ${{ start: 0, end: 0 }}
66+
${'empty array and out of bounds focus'} | ${0} | ${3} | ${{ start: 0, end: 0 }}
67+
${'one element focused'} | ${1} | ${0} | ${{ start: 0, end: 0 }}
68+
${'one element and out of bounds focus'} | ${1} | ${12} | ${{ start: 0, end: 0 }}
69+
${'small array with focus in the middle'} | ${5} | ${3} | ${{ start: 0, end: 4 }}
70+
${'bigger number of rendered items than data with range out of bound'} | ${5} | ${12} | ${{ start: 0, end: 4 }}
71+
${'focus at the beginning of big array focus 0'} | ${30} | ${0} | ${{ start: 0, end: 7 }}
72+
${'focus at the beginning of big array focus 1'} | ${30} | ${1} | ${{ start: 0, end: 7 }}
73+
${'focus at the beginning of big array focus 2'} | ${30} | ${2} | ${{ start: 0, end: 7 }}
74+
${'focus at the beginning of big array focus 3'} | ${30} | ${3} | ${{ start: 0, end: 7 }}
75+
${'focus at the beginning of big array focus 4, starts scrolling'} | ${30} | ${4} | ${{ start: 1, end: 8 }}
76+
${'focus at the beginning of big array focus 5, scrolls'} | ${30} | ${5} | ${{ start: 2, end: 9 }}
77+
${'focus in the middle of big array, must scroll'} | ${30} | ${12} | ${{ start: 9, end: 16 }}
78+
${'focus at the end of big array'} | ${30} | ${29} | ${{ start: 22, end: 29 }}
79+
${'big array and focus out of bounds'} | ${30} | ${31} | ${{ start: 22, end: 29 }}
80+
`(
81+
'should return proper range for array size $arraySize at index $focusIndex (case description: "$description")',
82+
({ arraySize, focusIndex, result }) => {
83+
const input = new Array(arraySize).fill(1);
84+
const expectedResult = getRange({
85+
data: input,
86+
currentlyFocusedItemIndex: focusIndex,
87+
numberOfRenderedItems: 8,
88+
numberOfItemsVisibleOnScreen: 4,
89+
scrollBehavior: 'stick-to-center',
90+
});
91+
92+
expect(expectedResult).toEqual(result);
93+
},
94+
);
95+
});
6196
});

packages/lib/src/spatial-navigation/components/virtualizedList/helpers/getRange.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ const getRawStartAndEndIndexes = ({
7979
scrollBehavior: ScrollBehavior;
8080
}) => {
8181
const halfNumberOfItemsNotVisible = numberOfItemsNotVisible / 2;
82+
const stickToCenterBoundaries = (numberOfItemsVisibleOnScreen + numberOfItemsNotVisible - 1) / 2;
8283

8384
switch (scrollBehavior) {
8485
case 'stick-to-start':
@@ -92,8 +93,8 @@ const getRawStartAndEndIndexes = ({
9293
};
9394
case 'stick-to-center':
9495
return {
95-
rawStartIndex: currentlyFocusedItemIndex - (halfNumberOfItemsNotVisible + 1),
96-
rawEndIndex: currentlyFocusedItemIndex + (halfNumberOfItemsNotVisible + 1),
96+
rawStartIndex: currentlyFocusedItemIndex - stickToCenterBoundaries,
97+
rawEndIndex: currentlyFocusedItemIndex + stickToCenterBoundaries,
9798
};
9899
case 'stick-to-end':
99100
return {

0 commit comments

Comments
 (0)