156 lines
8.0 KiB
JavaScript
156 lines
8.0 KiB
JavaScript
'use client';
|
|
import * as React from 'react';
|
|
import { slot, useMergedRefs } from '@fluentui/react-utilities';
|
|
import { useVirtualizer_unstable } from '../Virtualizer/useVirtualizer';
|
|
import { useDynamicVirtualizerMeasure } from '../../Hooks';
|
|
import { useVirtualizerContextState_unstable, scrollToItemDynamic } from '../../Utilities';
|
|
import { useMeasureList } from '../../hooks/useMeasureList';
|
|
import { useDynamicVirtualizerPagination } from '../../hooks/useDynamicPagination';
|
|
/**
|
|
* @deprecated migrated to \@fluentui\-contrib/react\-virtualizer for stable release.
|
|
*/ export function useVirtualizerScrollViewDynamic_unstable(props) {
|
|
'use no memo';
|
|
var _imperativeVirtualizerRef_current;
|
|
const contextState = useVirtualizerContextState_unstable(props.virtualizerContext);
|
|
const { imperativeRef, axis = 'vertical', reversed, imperativeVirtualizerRef, enablePagination = false, bufferItems: _bufferItems, bufferSize: _bufferSize } = props;
|
|
let sizeTrackingArray = React.useRef(new Array(props.numItems).fill(props.itemSize));
|
|
// This lets us trigger updates when a size change occurs.
|
|
const [sizeUpdateCount, setSizeUpdateCount] = React.useState(0);
|
|
const getChildSizeAuto = React.useCallback((index)=>{
|
|
if (sizeTrackingArray.current.length <= index || sizeTrackingArray.current[index] <= 0) {
|
|
// Default size for initial state or untracked
|
|
return props.itemSize;
|
|
}
|
|
/* Required to be defined prior to our measure function
|
|
* we use a sizing array ref that we will update post-render
|
|
*/ return sizeTrackingArray.current[index];
|
|
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
[
|
|
sizeTrackingArray,
|
|
props.itemSize,
|
|
sizeUpdateCount
|
|
]);
|
|
var _props_axis, _props_getItemSize;
|
|
const { virtualizerLength, bufferItems, bufferSize, scrollRef, containerSizeRef, updateScrollPosition } = useDynamicVirtualizerMeasure({
|
|
defaultItemSize: props.itemSize,
|
|
direction: (_props_axis = props.axis) !== null && _props_axis !== void 0 ? _props_axis : 'vertical',
|
|
getItemSize: (_props_getItemSize = props.getItemSize) !== null && _props_getItemSize !== void 0 ? _props_getItemSize : getChildSizeAuto,
|
|
virtualizerContext: contextState,
|
|
numItems: props.numItems,
|
|
bufferItems: _bufferItems,
|
|
bufferSize: _bufferSize
|
|
});
|
|
const _imperativeVirtualizerRef = useMergedRefs(React.useRef(null), imperativeVirtualizerRef);
|
|
var _contextState_contextIndex;
|
|
const paginationRef = useDynamicVirtualizerPagination({
|
|
axis,
|
|
progressiveItemSizes: (_imperativeVirtualizerRef_current = _imperativeVirtualizerRef.current) === null || _imperativeVirtualizerRef_current === void 0 ? void 0 : _imperativeVirtualizerRef_current.progressiveSizes,
|
|
virtualizerLength,
|
|
currentIndex: (_contextState_contextIndex = contextState === null || contextState === void 0 ? void 0 : contextState.contextIndex) !== null && _contextState_contextIndex !== void 0 ? _contextState_contextIndex : 0
|
|
}, enablePagination);
|
|
// Store the virtualizer length as a ref for imperative ref access
|
|
const virtualizerLengthRef = React.useRef(virtualizerLength);
|
|
if (virtualizerLengthRef.current !== virtualizerLength) {
|
|
virtualizerLengthRef.current = virtualizerLength;
|
|
}
|
|
const scrollViewRef = useMergedRefs(props.scrollViewRef, scrollRef, paginationRef);
|
|
const scrollCallbackRef = React.useRef(null);
|
|
React.useImperativeHandle(imperativeRef, ()=>{
|
|
var _imperativeVirtualizerRef_current;
|
|
return {
|
|
scrollTo (index, behavior = 'auto', callback) {
|
|
scrollCallbackRef.current = callback !== null && callback !== void 0 ? callback : null;
|
|
if (_imperativeVirtualizerRef.current) {
|
|
var _imperativeVirtualizerRef_current;
|
|
const progressiveSizes = _imperativeVirtualizerRef.current.progressiveSizes.current;
|
|
const totalSize = progressiveSizes && (progressiveSizes === null || progressiveSizes === void 0 ? void 0 : progressiveSizes.length) > 0 ? progressiveSizes[Math.max(progressiveSizes.length - 1, 0)] : 0;
|
|
_imperativeVirtualizerRef.current.setFlaggedIndex(index);
|
|
scrollToItemDynamic({
|
|
index,
|
|
itemSizes: (_imperativeVirtualizerRef_current = _imperativeVirtualizerRef.current) === null || _imperativeVirtualizerRef_current === void 0 ? void 0 : _imperativeVirtualizerRef_current.nodeSizes,
|
|
totalSize,
|
|
scrollViewRef: scrollViewRef,
|
|
axis,
|
|
reversed,
|
|
behavior
|
|
});
|
|
}
|
|
},
|
|
currentIndex: (_imperativeVirtualizerRef_current = _imperativeVirtualizerRef.current) === null || _imperativeVirtualizerRef_current === void 0 ? void 0 : _imperativeVirtualizerRef_current.currentIndex,
|
|
virtualizerLength: virtualizerLengthRef
|
|
};
|
|
}, [
|
|
axis,
|
|
scrollViewRef,
|
|
reversed,
|
|
_imperativeVirtualizerRef
|
|
]);
|
|
const handleRenderedIndex = (index)=>{
|
|
if (scrollCallbackRef.current) {
|
|
scrollCallbackRef.current(index);
|
|
}
|
|
};
|
|
var _props_getItemSize1;
|
|
const virtualizerState = useVirtualizer_unstable({
|
|
...props,
|
|
getItemSize: (_props_getItemSize1 = props.getItemSize) !== null && _props_getItemSize1 !== void 0 ? _props_getItemSize1 : getChildSizeAuto,
|
|
virtualizerLength,
|
|
bufferItems,
|
|
bufferSize,
|
|
virtualizerContext: contextState,
|
|
imperativeVirtualizerRef: _imperativeVirtualizerRef,
|
|
onRenderedFlaggedIndex: handleRenderedIndex,
|
|
containerSizeRef,
|
|
scrollViewRef,
|
|
updateScrollPosition
|
|
});
|
|
const measureObject = useMeasureList(virtualizerState.virtualizerStartIndex, virtualizerLength, props.numItems, props.itemSize);
|
|
if (enablePagination && measureObject.sizeUpdateCount !== sizeUpdateCount) {
|
|
/* This enables us to let callback know that the sizes have been updated
|
|
triggers a re-render but is only required on pagination (else index change handles) */ setSizeUpdateCount(measureObject.sizeUpdateCount);
|
|
}
|
|
if (axis === 'horizontal') {
|
|
sizeTrackingArray = measureObject.widthArray;
|
|
} else {
|
|
sizeTrackingArray = measureObject.heightArray;
|
|
}
|
|
if (!props.getItemSize) {
|
|
// Auto-measuring is required
|
|
React.Children.map(virtualizerState.virtualizedChildren, (child, index)=>{
|
|
if (/*#__PURE__*/ React.isValidElement(child)) {
|
|
virtualizerState.virtualizedChildren[index] = /*#__PURE__*/ React.createElement(child.type, {
|
|
...child.props,
|
|
key: child.key,
|
|
ref: (element)=>{
|
|
if (child.hasOwnProperty('ref')) {
|
|
// We must access this from the child directly, not props (forward ref).
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const localRef = child === null || child === void 0 ? void 0 : child.ref;
|
|
if (typeof localRef === 'function') {
|
|
localRef(element);
|
|
} else if (localRef) {
|
|
localRef.current = element;
|
|
}
|
|
}
|
|
// Call the auto-measure ref attachment.
|
|
measureObject.createIndexedRef(index)(element);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
return {
|
|
...virtualizerState,
|
|
components: {
|
|
...virtualizerState.components,
|
|
container: 'div'
|
|
},
|
|
container: slot.always(props.container, {
|
|
defaultProps: {
|
|
ref: scrollViewRef
|
|
},
|
|
elementType: 'div'
|
|
})
|
|
};
|
|
}
|