Private
Public Access
1
0
Files
power-apps-codeapps-blog-part2/node_modules/@fluentui/react-virtualizer/lib/hooks/useDynamicVirtualizerMeasure.js

130 lines
6.6 KiB
JavaScript

'use client';
import { useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities';
import * as React from 'react';
import { useResizeObserverRef_unstable } from './useResizeObserverRef';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
/**
* React hook that measures virtualized space dynamically to ensure optimized virtualization length.
* @deprecated migrated to \@fluentui\-contrib/react\-virtualizer for stable release.
*/ export const useDynamicVirtualizerMeasure = (virtualizerProps)=>{
const { defaultItemSize, direction = 'vertical', numItems, getItemSize, bufferItems, bufferSize, virtualizerContext } = virtualizerProps;
const [state, setState] = React.useState({
virtualizerLength: 0,
virtualizerBufferItems: 0,
virtualizerBufferSize: 0
});
const containerSizeRef = React.useRef(0);
const scrollPosition = React.useRef(0);
const { virtualizerLength, virtualizerBufferItems, virtualizerBufferSize } = state;
const { targetDocument } = useFluent();
const container = React.useRef(null);
const handleScrollResize = React.useCallback(// eslint-disable-next-line @typescript-eslint/no-deprecated
(scrollRef)=>{
if (!(scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current)) {
// Error? ignore?
return;
}
if (scrollRef.current !== (targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.body)) {
// We have a local scroll container
containerSizeRef.current = direction === 'vertical' ? scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current.getBoundingClientRect().height : scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current.getBoundingClientRect().width;
} else if (targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) {
var _targetDocument_defaultView, _targetDocument_defaultView1;
// If our scroll ref is the document body, we should check window height
containerSizeRef.current = direction === 'vertical' ? targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.innerHeight : targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView1 = targetDocument.defaultView) === null || _targetDocument_defaultView1 === void 0 ? void 0 : _targetDocument_defaultView1.innerWidth;
}
let indexSizer = 0;
let i = 0;
let length = 0;
const startIndex = virtualizerContext.contextIndex;
const sizeToBeat = containerSizeRef.current + virtualizerBufferSize * 2;
while(indexSizer <= sizeToBeat && i + startIndex < numItems){
const iItemSize = getItemSize(startIndex + i);
if (virtualizerContext.childProgressiveSizes.current.length < numItems) {
/* We are in unknown territory, either an initial render or an update
in virtualizer item length has occurred.
We need to let the new items render first then we can accurately assess.*/ return virtualizerLength - virtualizerBufferSize * 2;
}
const currentScrollPos = scrollPosition.current;
const currentItemPos = virtualizerContext.childProgressiveSizes.current[startIndex + i] - iItemSize;
if (currentScrollPos > currentItemPos + iItemSize) {
// The item isn't in view, ignore for now.
i++;
continue;
} else if (currentScrollPos > currentItemPos) {
// The item is partially out of view, ignore the out of bounds portion
const variance = currentItemPos + iItemSize - currentScrollPos;
indexSizer += variance;
} else {
// Item is in view
indexSizer += iItemSize;
}
// Increment
i++;
length++;
}
/*
* Number of items to append at each end, i.e. 'preload' each side before entering view.
* Minimum: 2 - we give slightly more buffer for dynamic version.
*/ const newBufferItems = bufferItems !== null && bufferItems !== void 0 ? bufferItems : Math.max(Math.ceil(length / 3), 1);
/*
* This is how far we deviate into the bufferItems to detect a redraw.
*/ const newBufferSize = bufferSize !== null && bufferSize !== void 0 ? bufferSize : Math.max(defaultItemSize / 2, 1);
const totalLength = length + newBufferItems * 2;
setState({
virtualizerLength: totalLength,
virtualizerBufferSize: newBufferSize,
virtualizerBufferItems: newBufferItems
});
}, [
bufferItems,
bufferSize,
defaultItemSize,
direction,
getItemSize,
numItems,
targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.body,
targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView,
virtualizerBufferSize,
virtualizerContext.childProgressiveSizes,
virtualizerContext.contextIndex,
virtualizerLength
]);
const resizeCallback = React.useCallback((_entries, // TODO: exclude types from this lint rule: https://github.com/microsoft/fluentui/issues/31286
_observer, // eslint-disable-next-line @typescript-eslint/no-deprecated
scrollRef)=>{
if (scrollRef) {
handleScrollResize(scrollRef);
}
}, [
handleScrollResize
]);
const scrollRef = useMergedRefs(container, useResizeObserverRef_unstable(resizeCallback));
useIsomorphicLayoutEffect(()=>{
if (virtualizerContext.contextIndex + virtualizerLength < numItems) {
// Avoid re-rendering/re-calculating when the end index has already been reached
handleScrollResize(container);
}
}, [
handleScrollResize,
numItems,
virtualizerContext.contextIndex,
virtualizerLength
]);
const updateScrollPosition = React.useCallback((_scrollPosition)=>{
scrollPosition.current = _scrollPosition;
// Check if our vLength's need recalculating
handleScrollResize(scrollRef);
}, [
handleScrollResize,
scrollRef
]);
return {
virtualizerLength,
bufferItems: virtualizerBufferItems,
bufferSize: virtualizerBufferSize,
scrollRef,
containerSizeRef,
updateScrollPosition
};
};