UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

82 lines (81 loc) 4.33 kB
import { __rest } from "tslib"; import { jsx as _jsx } from "react/jsx-runtime"; import { useEffect, useMemo, useRef } from 'react'; import { CacheStrategies, LRUCache } from '@selfcommunity/utils'; import VirtualScroller from 'virtual-scroller/react'; /** * VirtualizedScroller * A component for efficiently rendering large lists of variable height items. * VirtualScroller works by measuring each list item's height as it's being rendered, and then, as the user scrolls, * it hides the items that are no longer visible, and shows the now-visible items as they're scrolled to. * The hidden items at the top are compensated by setting padding-top on the list element, and the hidden items * at the bottom are compensated by setting padding-bottom on the list element. * The component listens to scroll / resize events and re-renders the currently visible items as the user * scrolls (or if the browser window is resized). * Set window['VirtualScrollerDebug'] = true; to output debug messages to console. */ export default function VirtualizedScroller(props) { const { items = [], ItemComponent, getItemId, initialScrollerState, onScrollerStateChange, onScrollerMount, onScrollerPositionChange, onScrollerSaveState, cacheStrategy = CacheStrategies.CACHE_FIRST, cacheScrollStateKey = 'virtual_scroller_st', cacheScrollerPositionKey = 'virtual_scroller_sp' } = props, rest = __rest(props, ["items", "ItemComponent", "getItemId", "initialScrollerState", "onScrollerStateChange", "onScrollerMount", "onScrollerPositionChange", "onScrollerSaveState", "cacheStrategy", "cacheScrollStateKey", "cacheScrollerPositionKey"]); // REF const virtualScrollerMountState = useRef(false); // HELPERS /** * Callback on mount the virtual scroller */ const onVirtualScrollerMount = useMemo(() => () => { virtualScrollerMountState.current = true; onScrollerMount && onScrollerMount(); }, []); /** * Get initial scroll position by cacheScrollerPositionKey * Recovered only if cacheStrategy = CACHE_FIRST */ const getInitialScrollPosition = useMemo(() => () => cacheStrategy === CacheStrategies.CACHE_FIRST && cacheScrollerPositionKey ? LRUCache.get(cacheScrollerPositionKey) : 0, [cacheStrategy, cacheScrollerPositionKey]); /** * Callback on virtual scroller position change */ const onScrollPositionChange = useMemo(() => (y) => { if (cacheScrollerPositionKey) { LRUCache.set(cacheScrollerPositionKey, y); } onScrollerPositionChange && onScrollerPositionChange(y); }, [cacheScrollerPositionKey]); /** * Callback on virtual scroller state change */ const onStateScrollChange = useMemo(() => (state) => { virtualScrollerState.current = state; onScrollerStateChange && onScrollerStateChange(state); }, []); /** * Save virtual scroller state */ const saveVirtualScrollerState = useMemo(() => (state) => { if (cacheScrollerPositionKey) { LRUCache.set(cacheScrollStateKey, state); } onScrollerSaveState && onScrollerSaveState(state); }, [cacheScrollStateKey]); /** * Read virtual scroller state */ const readVirtualScrollerState = useMemo(() => () => { if (cacheStrategy === CacheStrategies.CACHE_FIRST && cacheScrollStateKey && LRUCache.hasKey(cacheScrollStateKey)) { const _state = LRUCache.get(cacheScrollStateKey); if (_state.items && _state.items.length) { return _state; } } return null; }, [cacheScrollStateKey, cacheStrategy]); // REF const virtualScrollerState = useRef(readVirtualScrollerState()); // EFFECTS useEffect(() => { return () => { // Save state before the component unmounts. saveVirtualScrollerState(virtualScrollerState.current); }; }); return (_jsx(VirtualScroller, Object.assign({ items: items, itemComponent: ItemComponent, onMount: onVirtualScrollerMount }, (getItemId && { getItemId }), { initialState: initialScrollerState ? initialScrollerState : readVirtualScrollerState(), onStateChange: onStateScrollChange, initialScrollPosition: getInitialScrollPosition(), onScrollPositionChange: onScrollPositionChange }, rest))); }