'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' }) }; }