544 lines
23 KiB
JavaScript
544 lines
23 KiB
JavaScript
'use client';
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "useVirtualizer_unstable", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return useVirtualizer_unstable;
|
|
}
|
|
});
|
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
|
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
const _useIntersectionObserver = require("../../hooks/useIntersectionObserver");
|
|
const _Utilities = require("../../Utilities");
|
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
const _reactdom = require("react-dom");
|
|
function useVirtualizer_unstable(props) {
|
|
'use no memo';
|
|
const { itemSize, numItems, virtualizerLength, children: renderChild, getItemSize, bufferItems = Math.round(virtualizerLength / 4.0), bufferSize = Math.floor(bufferItems / 2.0) * itemSize, axis = 'vertical', reversed = false, virtualizerContext, onRenderedFlaggedIndex, imperativeVirtualizerRef, containerSizeRef, scrollViewRef, enableScrollLoad, updateScrollPosition, gap = 0 } = props;
|
|
/* The context is optional, it's useful for injecting additional index logic, or performing uniform state updates*/ const _virtualizerContext = (0, _Utilities.useVirtualizerContextState_unstable)(virtualizerContext);
|
|
// We use this ref as a constant source to access the virtualizer's state imperatively
|
|
const actualIndexRef = _react.useRef(_virtualizerContext.contextIndex);
|
|
const flaggedIndex = _react.useRef(null);
|
|
const actualIndex = _virtualizerContext.contextIndex;
|
|
// Just in case our ref gets out of date vs the context during a re-render
|
|
if (_virtualizerContext.contextIndex !== actualIndexRef.current) {
|
|
actualIndexRef.current = _virtualizerContext.contextIndex;
|
|
}
|
|
const setActualIndex = _react.useCallback((index)=>{
|
|
actualIndexRef.current = index;
|
|
_virtualizerContext.setContextIndex(index);
|
|
}, [
|
|
_virtualizerContext
|
|
]);
|
|
// Store ref to before padding element
|
|
const beforeElementRef = _react.useRef(null);
|
|
// Store ref to before padding element
|
|
const afterElementRef = _react.useRef(null);
|
|
// We need to store an array to track dynamic sizes, we can use this to incrementally update changes
|
|
const childSizes = _react.useRef(new Array(getItemSize ? numItems : 0));
|
|
/* We keep track of the progressive sizing/placement down the list,
|
|
this helps us skip re-calculations unless children/size changes */ const childProgressiveSizes = _react.useRef(new Array(getItemSize ? numItems : 0));
|
|
if (virtualizerContext === null || virtualizerContext === void 0 ? void 0 : virtualizerContext.childProgressiveSizes) {
|
|
virtualizerContext.childProgressiveSizes.current = childProgressiveSizes.current;
|
|
}
|
|
// The internal tracking REF for child array (updates often).
|
|
const childArray = _react.useRef(new Array(virtualizerLength));
|
|
const populateSizeArrays = ()=>{
|
|
if (!getItemSize) {
|
|
// Static sizes, never mind!
|
|
return;
|
|
}
|
|
if (numItems !== childSizes.current.length) {
|
|
childSizes.current = new Array(numItems);
|
|
}
|
|
if (numItems !== childProgressiveSizes.current.length) {
|
|
childProgressiveSizes.current = new Array(numItems);
|
|
if (virtualizerContext === null || virtualizerContext === void 0 ? void 0 : virtualizerContext.childProgressiveSizes) {
|
|
virtualizerContext.childProgressiveSizes.current = childProgressiveSizes.current;
|
|
}
|
|
}
|
|
for(let index = 0; index < numItems; index++){
|
|
const _gap = index < numItems - 1 ? gap : 0;
|
|
childSizes.current[index] = getItemSize(index) + _gap;
|
|
if (index === 0) {
|
|
childProgressiveSizes.current[index] = childSizes.current[index];
|
|
} else {
|
|
childProgressiveSizes.current[index] = childProgressiveSizes.current[index - 1] + childSizes.current[index];
|
|
}
|
|
}
|
|
};
|
|
const [isScrolling, setIsScrolling] = _react.useState(false);
|
|
const [setScrollTimer, clearScrollTimer] = (0, _reactutilities.useTimeout)();
|
|
const scrollCounter = _react.useRef(0);
|
|
const initializeScrollingTimer = _react.useCallback(()=>{
|
|
if (!enableScrollLoad) {
|
|
// Disabled by default for reduction of render callbacks
|
|
setIsScrolling(false);
|
|
clearScrollTimer();
|
|
return;
|
|
}
|
|
/*
|
|
* This can be considered the 'velocity' required to start 'isScrolling'
|
|
* INIT_SCROLL_FLAG_REQ: Number of renders required to activate isScrolling
|
|
* INIT_SCROLL_FLAG_DELAY: Amount of time (ms) before current number of renders is reset
|
|
* - Maybe we should let users customize these in the future.
|
|
*/ const INIT_SCROLL_FLAG_REQ = 10;
|
|
const INIT_SCROLL_FLAG_DELAY = 100;
|
|
scrollCounter.current++;
|
|
if (scrollCounter.current >= INIT_SCROLL_FLAG_REQ) {
|
|
setIsScrolling(true);
|
|
}
|
|
clearScrollTimer();
|
|
setScrollTimer(()=>{
|
|
setIsScrolling(false);
|
|
scrollCounter.current = 0;
|
|
}, INIT_SCROLL_FLAG_DELAY);
|
|
}, [
|
|
clearScrollTimer,
|
|
setScrollTimer,
|
|
enableScrollLoad
|
|
]);
|
|
_react.useEffect(()=>{
|
|
initializeScrollingTimer();
|
|
}, [
|
|
actualIndex,
|
|
initializeScrollingTimer
|
|
]);
|
|
const updateChildRows = _react.useCallback((newIndex)=>{
|
|
if (numItems === 0) {
|
|
/* Nothing to virtualize */ return;
|
|
}
|
|
/*
|
|
We reset the array every time to ensure children are re-rendered
|
|
This function should only be called when update is nessecary
|
|
*/ childArray.current = new Array(virtualizerLength);
|
|
const _actualIndex = Math.max(newIndex, 0);
|
|
const end = Math.min(_actualIndex + virtualizerLength, numItems);
|
|
for(let i = _actualIndex; i < end; i++){
|
|
childArray.current[i - _actualIndex] = renderChild(i, isScrolling);
|
|
}
|
|
}, [
|
|
isScrolling,
|
|
numItems,
|
|
renderChild,
|
|
virtualizerLength
|
|
]);
|
|
const updateCurrentItemSizes = _react.useCallback((newIndex)=>{
|
|
if (!getItemSize) {
|
|
// Static sizes, not required.
|
|
return;
|
|
}
|
|
// We should always call our size function on index change (only for the items that will be rendered)
|
|
// This ensures we request the latest data for incoming items in case sizing has changed.
|
|
const endIndex = Math.min(newIndex + virtualizerLength, numItems);
|
|
const startIndex = Math.max(newIndex, 0);
|
|
let didUpdate = false;
|
|
for(let i = startIndex; i < endIndex; i++){
|
|
const _gap = i < numItems - 1 ? gap : 0;
|
|
const newSize = getItemSize(i) + _gap;
|
|
if (newSize !== childSizes.current[i]) {
|
|
childSizes.current[i] = newSize;
|
|
didUpdate = true;
|
|
}
|
|
}
|
|
if (didUpdate) {
|
|
// Update our progressive size array
|
|
for(let i = startIndex; i < numItems; i++){
|
|
const prevSize = i > 0 ? childProgressiveSizes.current[i - 1] : 0;
|
|
childProgressiveSizes.current[i] = prevSize + childSizes.current[i];
|
|
}
|
|
}
|
|
}, [
|
|
getItemSize,
|
|
numItems,
|
|
virtualizerLength,
|
|
gap
|
|
]);
|
|
const batchUpdateNewIndex = _react.useCallback((index)=>{
|
|
// Local updates
|
|
updateChildRows(index);
|
|
updateCurrentItemSizes(index);
|
|
// State setters
|
|
setActualIndex(index);
|
|
}, [
|
|
setActualIndex,
|
|
updateChildRows,
|
|
updateCurrentItemSizes
|
|
]);
|
|
const findIndexRecursive = _react.useCallback((scrollPos, lowIndex, highIndex)=>{
|
|
if (lowIndex > highIndex) {
|
|
// We shouldn't get here - but no-op the index if we do.
|
|
return actualIndex;
|
|
}
|
|
const midpoint = Math.floor((lowIndex + highIndex) / 2);
|
|
const iBefore = Math.max(midpoint - 1, 0);
|
|
const iAfter = Math.min(midpoint + 1, childProgressiveSizes.current.length - 1);
|
|
const indexValue = childProgressiveSizes.current[midpoint];
|
|
const afterIndexValue = childProgressiveSizes.current[iAfter];
|
|
const beforeIndexValue = childProgressiveSizes.current[iBefore];
|
|
if (scrollPos <= afterIndexValue && scrollPos >= beforeIndexValue) {
|
|
/* We've found our index - if we are exactly matching before/after index that's ok,
|
|
better to reduce checks if it's right on the boundary. */ return midpoint;
|
|
}
|
|
if (indexValue > scrollPos) {
|
|
return findIndexRecursive(scrollPos, lowIndex, midpoint - 1);
|
|
} else {
|
|
return findIndexRecursive(scrollPos, midpoint + 1, highIndex);
|
|
}
|
|
}, [
|
|
actualIndex
|
|
]);
|
|
const getIndexFromSizeArray = _react.useCallback((scrollPos)=>{
|
|
/* Quick searches our progressive height array */ if (scrollPos === 0 || childProgressiveSizes.current.length === 0 || scrollPos <= childProgressiveSizes.current[0]) {
|
|
// Check start
|
|
return 0;
|
|
}
|
|
if (scrollPos >= childProgressiveSizes.current[childProgressiveSizes.current.length - 1]) {
|
|
// Check end
|
|
return childProgressiveSizes.current.length - 1;
|
|
}
|
|
return findIndexRecursive(scrollPos, 0, childProgressiveSizes.current.length - 1);
|
|
}, [
|
|
findIndexRecursive
|
|
]);
|
|
const getIndexFromScrollPosition = _react.useCallback((scrollPos)=>{
|
|
if (!getItemSize) {
|
|
return Math.round(scrollPos / (itemSize + gap));
|
|
}
|
|
return getIndexFromSizeArray(scrollPos);
|
|
}, [
|
|
getIndexFromSizeArray,
|
|
getItemSize,
|
|
itemSize,
|
|
gap
|
|
]);
|
|
const calculateTotalSize = _react.useCallback(()=>{
|
|
if (!getItemSize) {
|
|
return (itemSize + gap) * numItems;
|
|
}
|
|
// Time for custom size calcs
|
|
return childProgressiveSizes.current[numItems - 1];
|
|
}, [
|
|
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 + gap);
|
|
}
|
|
if (currentIndex <= 0) {
|
|
return 0;
|
|
}
|
|
// Time for custom size calcs
|
|
return childProgressiveSizes.current[currentIndex - 1];
|
|
}, [
|
|
actualIndex,
|
|
getItemSize,
|
|
itemSize,
|
|
numItems,
|
|
gap
|
|
]);
|
|
const calculateAfter = _react.useCallback(()=>{
|
|
if (numItems === 0 || actualIndex + virtualizerLength >= numItems) {
|
|
return 0;
|
|
}
|
|
const lastItemIndex = Math.min(actualIndex + virtualizerLength, numItems);
|
|
if (!getItemSize) {
|
|
// The missing items from after virtualization ends height
|
|
const remainingItems = numItems - lastItemIndex;
|
|
return remainingItems * (itemSize + gap) - gap;
|
|
}
|
|
// Time for custom size calcs
|
|
return childProgressiveSizes.current[numItems - 1] - childProgressiveSizes.current[lastItemIndex - 1];
|
|
}, [
|
|
actualIndex,
|
|
getItemSize,
|
|
itemSize,
|
|
numItems,
|
|
virtualizerLength,
|
|
gap
|
|
]);
|
|
// We store the number of items since last render, we will allow an update if the number of items changes
|
|
const previousNumItems = _react.useRef(numItems);
|
|
// Observe intersections of virtualized components
|
|
const { setObserverList } = (0, _useIntersectionObserver.useIntersectionObserver)(_react.useCallback((entries, observer)=>{
|
|
/* Sanity check - do we even need virtualization? */ if (virtualizerLength > numItems) {
|
|
if (actualIndex !== 0) {
|
|
batchUpdateNewIndex(0);
|
|
}
|
|
// No-op
|
|
return;
|
|
}
|
|
if (entries.length === 0) {
|
|
// No entries found, return.
|
|
return;
|
|
}
|
|
// Find the latest entry that is intersecting
|
|
const sortedEntries = entries.sort((entry1, entry2)=>entry2.time - entry1.time);
|
|
const latestEntry = sortedEntries.find((entry)=>{
|
|
return entry.isIntersecting;
|
|
});
|
|
if (!latestEntry) {
|
|
return;
|
|
}
|
|
// We have to be sure our item sizes are up to date with current indexed ref before calculation
|
|
// Check if we still need
|
|
updateCurrentItemSizes(actualIndexRef.current);
|
|
const calculateOverBuffer = ()=>{
|
|
/**
|
|
* We avoid using the scroll ref scrollTop, it may be incorrect
|
|
* as virtualization may exist within a scroll view with other elements
|
|
* The benefit of using IO is that we can detect relative scrolls,
|
|
* so any items can be placed around the virtualizer in the scroll view
|
|
*/ let measurementPos = 0;
|
|
if (latestEntry.target === afterElementRef.current) {
|
|
// Get after buffers position
|
|
measurementPos = calculateTotalSize() - calculateAfter();
|
|
// Get exact intersection position based on overflow size (how far into IO did we scroll?)
|
|
const overflowAmount = axis === 'vertical' ? latestEntry.intersectionRect.height : latestEntry.intersectionRect.width;
|
|
// Add to original after position
|
|
measurementPos += overflowAmount;
|
|
// Ignore buffer size (IO offset)
|
|
measurementPos -= bufferSize;
|
|
var _containerSizeRef_current;
|
|
// we hit the after buffer and detected the end of view, we need to find the start index.
|
|
measurementPos -= (_containerSizeRef_current = containerSizeRef.current) !== null && _containerSizeRef_current !== void 0 ? _containerSizeRef_current : 0;
|
|
// Calculate how far past the window bounds we are (this will be zero if IO is within window)
|
|
const hOverflow = latestEntry.boundingClientRect.top - latestEntry.intersectionRect.top;
|
|
const hOverflowReversed = latestEntry.boundingClientRect.bottom - latestEntry.intersectionRect.bottom;
|
|
const wOverflow = latestEntry.boundingClientRect.left - latestEntry.intersectionRect.left;
|
|
const wOverflowReversed = latestEntry.boundingClientRect.right - latestEntry.intersectionRect.right;
|
|
const widthOverflow = reversed ? wOverflowReversed : wOverflow;
|
|
const heightOverflow = reversed ? hOverflowReversed : hOverflow;
|
|
const additionalOverflow = axis === 'vertical' ? heightOverflow : widthOverflow;
|
|
if (reversed) {
|
|
measurementPos += additionalOverflow;
|
|
} else {
|
|
measurementPos -= additionalOverflow;
|
|
}
|
|
} else if (latestEntry.target === beforeElementRef.current) {
|
|
// Get before buffers position
|
|
measurementPos = calculateBefore();
|
|
// Get exact intersection position based on overflow size (how far into window did we scroll IO?)
|
|
const overflowAmount = axis === 'vertical' ? latestEntry.intersectionRect.height : latestEntry.intersectionRect.width;
|
|
// Minus from original before position
|
|
measurementPos -= overflowAmount;
|
|
// Ignore buffer size (IO offset)
|
|
measurementPos += bufferSize;
|
|
// Calculate how far past the window bounds we are (this will be zero if IO is within window)
|
|
const hOverflow = latestEntry.boundingClientRect.bottom - latestEntry.intersectionRect.bottom;
|
|
const hOverflowReversed = latestEntry.boundingClientRect.top - latestEntry.intersectionRect.top;
|
|
const wOverflow = latestEntry.boundingClientRect.right - latestEntry.intersectionRect.right;
|
|
const wOverflowReversed = latestEntry.boundingClientRect.left - latestEntry.intersectionRect.left;
|
|
const widthOverflow = reversed ? wOverflowReversed : wOverflow;
|
|
const heightOverflow = reversed ? hOverflowReversed : hOverflow;
|
|
const additionalOverflow = axis === 'vertical' ? heightOverflow : widthOverflow;
|
|
if (reversed) {
|
|
measurementPos += additionalOverflow;
|
|
} else {
|
|
measurementPos -= additionalOverflow;
|
|
}
|
|
}
|
|
return measurementPos;
|
|
};
|
|
// Get exact relative 'scrollTop' via IO values
|
|
const measurementPos = calculateOverBuffer();
|
|
const maxIndex = Math.max(numItems - virtualizerLength, 0);
|
|
const startIndex = getIndexFromScrollPosition(measurementPos) - bufferItems;
|
|
// Safety limits
|
|
const newStartIndex = Math.min(Math.max(startIndex, 0), maxIndex);
|
|
(0, _reactdom.flushSync)(()=>{
|
|
// Callback to allow measure functions to check virtualizer length
|
|
if (previousNumItems.current === numItems && newStartIndex + virtualizerLength >= numItems && actualIndex + virtualizerLength >= numItems) {
|
|
// We've already hit the end, no need to update state.
|
|
return;
|
|
}
|
|
// We should ensure we update virtualizer calculations if the length changes
|
|
previousNumItems.current = virtualizerLength;
|
|
updateScrollPosition === null || updateScrollPosition === void 0 ? void 0 : updateScrollPosition(measurementPos);
|
|
if (actualIndex !== newStartIndex) {
|
|
batchUpdateNewIndex(newStartIndex);
|
|
}
|
|
});
|
|
}, [
|
|
actualIndex,
|
|
virtualizerLength,
|
|
axis,
|
|
reversed,
|
|
numItems,
|
|
bufferSize,
|
|
bufferItems,
|
|
containerSizeRef,
|
|
updateScrollPosition,
|
|
batchUpdateNewIndex,
|
|
calculateAfter,
|
|
calculateBefore,
|
|
calculateTotalSize,
|
|
getIndexFromScrollPosition,
|
|
updateCurrentItemSizes
|
|
]), {
|
|
root: scrollViewRef ? scrollViewRef === null || scrollViewRef === void 0 ? void 0 : scrollViewRef.current : null,
|
|
rootMargin: '0px',
|
|
threshold: 0
|
|
});
|
|
const setBeforeRef = _react.useCallback((element)=>{
|
|
if (!element || beforeElementRef.current === element) {
|
|
return;
|
|
}
|
|
beforeElementRef.current = element;
|
|
const newList = [];
|
|
newList.push(beforeElementRef.current);
|
|
if (afterElementRef.current) {
|
|
newList.push(afterElementRef.current);
|
|
}
|
|
// Ensure we update array if before element changed
|
|
setObserverList(newList);
|
|
}, [
|
|
setObserverList
|
|
]);
|
|
const setAfterRef = _react.useCallback((element)=>{
|
|
if (!element || afterElementRef.current === element) {
|
|
return;
|
|
}
|
|
afterElementRef.current = element;
|
|
const newList = [];
|
|
if (beforeElementRef.current) {
|
|
newList.push(beforeElementRef.current);
|
|
}
|
|
newList.push(afterElementRef.current);
|
|
// Ensure we update array if after element changed
|
|
setObserverList(newList);
|
|
}, [
|
|
setObserverList
|
|
]);
|
|
// Initialize the size array before first render.
|
|
const hasInitialized = _react.useRef(false);
|
|
const initializeSizeArray = ()=>{
|
|
if (hasInitialized.current === false) {
|
|
hasInitialized.current = true;
|
|
populateSizeArrays();
|
|
}
|
|
};
|
|
_react.useImperativeHandle(imperativeVirtualizerRef, ()=>{
|
|
return {
|
|
progressiveSizes: childProgressiveSizes,
|
|
nodeSizes: childSizes,
|
|
setFlaggedIndex: (index)=>flaggedIndex.current = index,
|
|
currentIndex: actualIndexRef
|
|
};
|
|
}, [
|
|
childProgressiveSizes,
|
|
childSizes
|
|
]);
|
|
// Initialization on mount - update array index to 0 (ready state).
|
|
// Only fire on mount (no deps).
|
|
_react.useEffect(()=>{
|
|
if (actualIndex < 0) {
|
|
batchUpdateNewIndex(0);
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
/*
|
|
* forceUpdate:
|
|
* We only want to trigger this when child render or scroll loading changes,
|
|
* it will force re-render all children elements
|
|
*/ const forceUpdate = _react.useReducer(()=>({}), {})[1];
|
|
// If the user passes in an updated renderChild function - update current children
|
|
_react.useEffect(()=>{
|
|
if (actualIndex >= 0) {
|
|
updateChildRows(actualIndex);
|
|
forceUpdate();
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [
|
|
renderChild,
|
|
isScrolling
|
|
]);
|
|
_react.useEffect(()=>{
|
|
// Ensure we repopulate if getItemSize callback changes
|
|
populateSizeArrays();
|
|
// We only run this effect on getItemSize change (recalc dynamic sizes)
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [
|
|
getItemSize,
|
|
gap
|
|
]);
|
|
// Effect to check flag index on updates
|
|
_react.useEffect(()=>{
|
|
if (!onRenderedFlaggedIndex || flaggedIndex.current === null) {
|
|
return;
|
|
}
|
|
if (actualIndex <= flaggedIndex.current && actualIndex + virtualizerLength >= flaggedIndex.current) {
|
|
onRenderedFlaggedIndex(flaggedIndex.current);
|
|
flaggedIndex.current = null;
|
|
}
|
|
}, [
|
|
actualIndex,
|
|
onRenderedFlaggedIndex,
|
|
virtualizerLength
|
|
]);
|
|
// Ensure we have run through and updated the whole size list array at least once.
|
|
initializeSizeArray();
|
|
if (getItemSize && (numItems !== childSizes.current.length || numItems !== childProgressiveSizes.current.length)) {
|
|
// Child length mismatch, repopulate size arrays.
|
|
populateSizeArrays();
|
|
}
|
|
// Ensure we recalc if virtualizer length changes
|
|
const maxCompare = Math.min(virtualizerLength, numItems);
|
|
if (childArray.current.length !== maxCompare && actualIndex + childArray.current.length < numItems) {
|
|
updateChildRows(actualIndex);
|
|
}
|
|
const isFullyInitialized = hasInitialized.current && actualIndex >= 0;
|
|
return {
|
|
components: {
|
|
before: 'div',
|
|
after: 'div',
|
|
beforeContainer: 'div',
|
|
afterContainer: 'div'
|
|
},
|
|
virtualizedChildren: childArray.current,
|
|
before: _reactutilities.slot.always(props.before, {
|
|
defaultProps: {
|
|
ref: setBeforeRef,
|
|
role: 'none'
|
|
},
|
|
elementType: 'div'
|
|
}),
|
|
after: _reactutilities.slot.always(props.after, {
|
|
defaultProps: {
|
|
ref: setAfterRef,
|
|
role: 'none'
|
|
},
|
|
elementType: 'div'
|
|
}),
|
|
beforeContainer: _reactutilities.slot.always(props.beforeContainer, {
|
|
defaultProps: {
|
|
role: 'none'
|
|
},
|
|
elementType: 'div'
|
|
}),
|
|
afterContainer: _reactutilities.slot.always(props.afterContainer, {
|
|
defaultProps: {
|
|
role: 'none'
|
|
},
|
|
elementType: 'div'
|
|
}),
|
|
beforeBufferHeight: isFullyInitialized ? calculateBefore() : 0,
|
|
afterBufferHeight: isFullyInitialized ? calculateAfter() : 0,
|
|
totalVirtualizerHeight: isFullyInitialized ? calculateTotalSize() : virtualizerLength * itemSize,
|
|
virtualizerStartIndex: actualIndex,
|
|
axis,
|
|
bufferSize,
|
|
reversed,
|
|
childSizes,
|
|
childProgressiveSizes
|
|
};
|
|
}
|