import { ForwardedRef, forwardRef, useCallback, useRef } from 'react'; import { RtListVirtualProps } from '../types/rt-list-virtual.types'; import { useRtBaseProps } from '@dpa/react-hoc'; import { useVirtualizer } from '@tanstack/react-virtual'; import { RtFrame } from '@dpa/react-frame-intro'; import classNames from 'classnames/bind'; import styles from '../styles/rt-list-virtual.module.css'; import { RtGrid } from '@dpa/react-grid'; import mergeRefs from 'merge-refs'; import { getDefaultRenderItem } from '../utils/default-render-item'; const cn = classNames.bind(styles); const getEstimateSize = () => 40; export const RtInternalListVirtual = ( props: RtListVirtualProps, ref: ForwardedRef ) => { const { items, getId, renderItem, containerRef, useGrid, ariaLabel, use, paddingBottom, paddingTop, ...otherProps } = props; const baseProps = useRtBaseProps(props, '0.2.2'); const localContainerRef = useRef(null); const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => containerRef?.current || localContainerRef.current, estimateSize: getEstimateSize, overscan: 5, }); const virtualItems = virtualizer.getVirtualItems(); const renderItemFn = renderItem || getDefaultRenderItem(use); const renderVirtualItems = useCallback(() => { return virtualItems.map((virtualItem) => { const item = items[virtualItem.index]; return (
  • {renderItemFn(item)}
  • ); }); }, [ items, renderItemFn, virtualItems, virtualizer.measureElement, paddingBottom, paddingTop, ]); return ( {useGrid ? (
    {renderVirtualItems()}
    ) : (
      {renderVirtualItems()}
    )}
    ); }; /** * Компонент для отображения виртуализированного списка. * Может использовать RtGrid. В качестве единицы списка может использовать RtItem или кастомный компонент в slot * {@link RtListVirtualProps} */ export const RtListVirtual = forwardRef(RtInternalListVirtual); RtListVirtual.displayName = 'RtListVirtual';