Skip to content

Commit

Permalink
Virtualizer: Add gap property for calculation (#33275)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mitch-At-Work authored Dec 5, 2024
1 parent df2eb61 commit 9a01d45
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat: Add gap property to simplify gap css virtualization",
"packageName": "@fluentui/react-virtualizer",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ export type VirtualizerConfigProps = {
* this should be passed in from useDynamicVirtualizerMeasure
*/
updateScrollPosition?: (position: number) => void;

/**
* Spacing between rendered children for calculation, should match the container's gap CSS value.
*/
gap?: number;
};

export type VirtualizerProps = ComponentProps<Partial<VirtualizerSlots>> & VirtualizerConfigProps;
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta
scrollViewRef,
enableScrollLoad,
updateScrollPosition,
gap = 0,
} = props;

/* The context is optional, it's useful for injecting additional index logic, or performing uniform state updates*/
Expand Down Expand Up @@ -86,7 +87,8 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta
}

for (let index = 0; index < numItems; index++) {
childSizes.current[index] = getItemSize(index);
const _gap = index < numItems - 1 ? gap : 0;
childSizes.current[index] = getItemSize(index) + _gap;
if (index === 0) {
childProgressiveSizes.current[index] = childSizes.current[index];
} else {
Expand Down Expand Up @@ -162,7 +164,8 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta

let didUpdate = false;
for (let i = startIndex; i < endIndex; i++) {
const newSize = getItemSize(i);
const _gap = i < numItems - 1 ? gap : 0;
const newSize = getItemSize(i) + _gap;
if (newSize !== childSizes.current[i]) {
childSizes.current[i] = newSize;
didUpdate = true;
Expand All @@ -177,7 +180,7 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta
}
}
},
[getItemSize, numItems, virtualizerLength],
[getItemSize, numItems, virtualizerLength, gap],
);

const batchUpdateNewIndex = React.useCallback(
Expand Down Expand Up @@ -243,29 +246,29 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta
const getIndexFromScrollPosition = React.useCallback(
(scrollPos: number) => {
if (!getItemSize) {
return Math.round(scrollPos / itemSize);
return Math.round(scrollPos / (itemSize + gap));
}

return getIndexFromSizeArray(scrollPos);
},
[getIndexFromSizeArray, getItemSize, itemSize],
[getIndexFromSizeArray, getItemSize, itemSize, gap],
);

const calculateTotalSize = React.useCallback(() => {
if (!getItemSize) {
return itemSize * numItems;
return (itemSize + gap) * numItems;
}

// Time for custom size calcs
return childProgressiveSizes.current[numItems - 1];
}, [getItemSize, itemSize, numItems]);
}, [getItemSize, itemSize, numItems, gap]);

const calculateBefore = React.useCallback(() => {
const currentIndex = Math.min(actualIndex, numItems - 1);

if (!getItemSize) {
// The missing items from before virtualization starts height
return currentIndex * itemSize;
return currentIndex * (itemSize + gap);
}

if (currentIndex <= 0) {
Expand All @@ -274,7 +277,7 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta

// Time for custom size calcs
return childProgressiveSizes.current[currentIndex - 1];
}, [actualIndex, getItemSize, itemSize, numItems]);
}, [actualIndex, getItemSize, itemSize, numItems, gap]);

const calculateAfter = React.useCallback(() => {
if (numItems === 0 || actualIndex + virtualizerLength >= numItems) {
Expand All @@ -285,12 +288,12 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta
if (!getItemSize) {
// The missing items from after virtualization ends height
const remainingItems = numItems - lastItemIndex;
return remainingItems * itemSize;
return remainingItems * (itemSize + gap) - gap;
}

// Time for custom size calcs
return childProgressiveSizes.current[numItems - 1] - childProgressiveSizes.current[lastItemIndex - 1];
}, [actualIndex, getItemSize, itemSize, numItems, virtualizerLength]);
}, [actualIndex, getItemSize, itemSize, numItems, virtualizerLength, gap]);

// Observe intersections of virtualized components
const { setObserverList } = useIntersectionObserver(
Expand Down Expand Up @@ -532,7 +535,7 @@ export function useVirtualizer_unstable(props: VirtualizerProps): VirtualizerSta

// We only run this effect on getItemSize change (recalc dynamic sizes)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [getItemSize]);
}, [getItemSize, gap]);

// Effect to check flag index on updates
React.useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const useStyles = makeStyles({
width: '100%',
height: '100%',
maxHeight: '750px',
gap: '20px',
},
child: {
height: `${smallSize}px`,
Expand Down Expand Up @@ -87,6 +88,7 @@ export const Dynamic = () => {
containerSizeRef={containerSizeRef}
virtualizerContext={contextState}
updateScrollPosition={updateScrollPosition}
gap={20}
>
{React.useCallback(
(index: number) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ export const AutoMeasure = () => {
numItems={childLength}
// We can use itemSize to set average height and reduce unknown whitespace
itemSize={minHeight + maxHeightIncrease / 2.0 + 100}
container={{ role: 'list', style: { maxHeight: '80vh' } }}
container={{ role: 'list', style: { maxHeight: '80vh', gap: '20px' } }}
bufferItems={1}
bufferSize={minHeight / 2.0}
gap={20}
>
{(index: number) => {
const backgroundColor = index % 2 ? '#CCCCCC' : '#ABABAB';
Expand Down

0 comments on commit 9a01d45

Please sign in to comment.