UNPKG

acud

Version:

acg react 组件库

88 lines • 3.16 kB
import _typeof from "@babel/runtime/helpers/esm/typeof"; /* eslint-disable no-param-reassign */ import * as React from 'react'; import raf from "rc-util/es/raf"; export default function useScrollTo(containerRef, data, heights, itemHeight, getKey, collectHeight, syncScrollTop, triggerFlash) { var scrollRef = React.useRef(); return function (arg) { // When not argument provided, we think dev may want to show the scrollbar if (arg === null || arg === undefined) { triggerFlash(); return; } // Normal scroll logic raf.cancel(scrollRef.current); if (typeof arg === 'number') { syncScrollTop(arg); } else if (arg && _typeof(arg) === 'object') { var index; var align = arg.align; if ('index' in arg) { index = arg.index; } else { index = data.findIndex(function (item) { return getKey(item) === arg.key; }); } var _arg$offset = arg.offset, offset = _arg$offset === void 0 ? 0 : _arg$offset; // We will retry 3 times in case dynamic height shaking var _syncScroll = function syncScroll(times, targetAlign) { if (times < 0 || !containerRef.current) return; var height = containerRef.current.clientHeight; var needCollectHeight = false; var newTargetAlign = targetAlign; // Go to next frame if height not exist if (height) { var mergedAlign = targetAlign || align; // Get top & bottom var stackTop = 0; var itemTop = 0; var itemBottom = 0; var maxLen = Math.min(data.length, index); for (var i = 0; i <= maxLen; i += 1) { var key = getKey(data[i]); itemTop = stackTop; var cacheHeight = heights.get(key); itemBottom = itemTop + (cacheHeight === undefined ? itemHeight : cacheHeight); stackTop = itemBottom; if (i === index && cacheHeight === undefined) { needCollectHeight = true; } } // Scroll to var targetTop = null; switch (mergedAlign) { case 'top': targetTop = itemTop - offset; break; case 'bottom': targetTop = itemBottom - height + offset; break; default: { var scrollTop = containerRef.current.scrollTop; var scrollBottom = scrollTop + height; if (itemTop < scrollTop) { newTargetAlign = 'top'; } else if (itemBottom > scrollBottom) { newTargetAlign = 'bottom'; } } } if (targetTop !== null && targetTop !== containerRef.current.scrollTop) { syncScrollTop(targetTop); } } // We will retry since element may not sync height as it described scrollRef.current = raf(function () { if (needCollectHeight) { collectHeight(); } _syncScroll(times - 1, newTargetAlign); }); }; _syncScroll(3); } }; }