tdesign-react
Version:
TDesign Component for React
219 lines (215 loc) • 9.76 kB
JavaScript
/**
* tdesign v1.15.1
* (c) 2025 tdesign
* @license MIT
*/
import { _ as _slicedToArray } from '../_chunks/dep-48805ab8.js';
import { useRef, useState, useMemo, useEffect } from 'react';
import { isEqual } from 'lodash-es';
import '../_chunks/dep-026a4c6b.js';
var requestAnimationFrame = (typeof window === "undefined" ? false : window.requestAnimationFrame) || function (cb) {
return setTimeout(cb, 16.6);
};
var useVirtualScroll = function useVirtualScroll(container, params) {
var data = params.data,
scroll = params.scroll;
var dataRef = useRef(data);
var _useState = useState([]),
_useState2 = _slicedToArray(_useState, 2),
visibleData = _useState2[0],
setVisibleData = _useState2[1];
var _useState3 = useState(function () {
return ((data === null || data === void 0 ? void 0 : data.length) || 0) * ((scroll === null || scroll === void 0 ? void 0 : scroll.rowHeight) || 50);
}),
_useState4 = _slicedToArray(_useState3, 2),
translateY = _useState4[0],
setTranslateY = _useState4[1];
var _useState5 = useState(0),
_useState6 = _slicedToArray(_useState5, 2),
scrollHeight = _useState6[0],
setScrollHeight = _useState6[1];
var trScrollTopHeightList = useRef([]);
var _useState7 = useState([]),
_useState8 = _slicedToArray(_useState7, 2),
trHeightList = _useState8[0],
setTrHeightList = _useState8[1];
var containerHeight = useRef(0);
var _useState9 = useState(function () {
return [0, ((scroll === null || scroll === void 0 ? void 0 : scroll.bufferSize) || 10) * 3];
}),
_useState0 = _slicedToArray(_useState9, 2),
startAndEndIndex = _useState0[0],
setStartAndEndIndex = _useState0[1];
var tScroll = useMemo(function () {
var _scroll$isFixedRowHei, _scroll$fixedRows;
if (!scroll) return {};
return {
bufferSize: scroll.bufferSize || 10,
isFixedRowHeight: (_scroll$isFixedRowHei = scroll.isFixedRowHeight) !== null && _scroll$isFixedRowHei !== void 0 ? _scroll$isFixedRowHei : false,
rowHeight: scroll.rowHeight || 47,
threshold: scroll.threshold || 100,
type: scroll.type,
fixedRows: (_scroll$fixedRows = scroll.fixedRows) !== null && _scroll$fixedRows !== void 0 ? _scroll$fixedRows : [0, 0]
};
}, [scroll]);
var isVirtualScroll = useMemo(function () {
return tScroll.type === "virtual" && tScroll.threshold < data.length;
}, [tScroll, data]);
var getTrScrollTopHeightList = function getTrScrollTopHeightList(trHeightList2) {
var list = [];
for (var i = 0, len = data.length; i < len; i++) {
list[i] = (list[i - 1] || 0) + (trHeightList2[i] || tScroll.rowHeight);
}
return list;
};
var updateVisibleData = function updateVisibleData(trScrollTopHeightList2, scrollTop) {
var currentIndex = -1;
for (var i = 0, len = trScrollTopHeightList2.length; i < len; i++) {
if (trScrollTopHeightList2[i] >= scrollTop) {
currentIndex = i;
break;
}
}
var lastIndex = trScrollTopHeightList2.length;
var containerCurrentHeight = containerHeight.current || container.current.getBoundingClientRect().height;
var scrollBottom = scrollTop + containerCurrentHeight;
for (var _i = currentIndex, _len = trScrollTopHeightList2.length; _i < _len; _i++) {
if (trScrollTopHeightList2[_i] >= scrollBottom) {
lastIndex = _i;
break;
}
}
if (currentIndex < 0) return;
var startIndex = Math.max(currentIndex - tScroll.bufferSize, 0);
var endIndex = Math.min(lastIndex + tScroll.bufferSize, trScrollTopHeightList2.length);
var fixedRows = tScroll.fixedRows;
var _fixedRows = _slicedToArray(fixedRows, 2),
fixedStart = _fixedRows[0],
fixedEnd = _fixedRows[1];
var fixedStartData = fixedStart ? data.slice(0, fixedStart) : [];
if (fixedStart && startIndex < fixedStart) {
fixedStartData = fixedStartData.slice(0, startIndex);
}
var fixedEndData = fixedEnd ? data.slice(data.length - fixedEnd) : [];
var bottomStartIndex = endIndex - data.length + 1 + (fixedEnd !== null && fixedEnd !== void 0 ? fixedEnd : 0);
if (fixedEnd && bottomStartIndex > 0) {
fixedEndData = fixedEndData.slice(bottomStartIndex);
}
if (startAndEndIndex.join() !== [startIndex, endIndex].join() && startIndex >= 0) {
var tmpVisibleData = fixedStartData.concat(data.slice(startIndex, endIndex)).concat(fixedEndData);
setVisibleData(tmpVisibleData);
var lastScrollTop = trScrollTopHeightList2[startIndex - 1];
var top = lastScrollTop > 0 ? lastScrollTop : 0;
var stickyHeight = trScrollTopHeightList2[Math.min(startIndex, fixedStart) - 1] || 0;
setTranslateY(top - stickyHeight);
setStartAndEndIndex([startIndex, endIndex]);
}
};
var handleRowMounted = function handleRowMounted(rowData) {
if (!isVirtualScroll || !rowData || tScroll.isFixedRowHeight || !(container !== null && container !== void 0 && container.current)) return;
var trHeight = rowData.ref.offsetHeight;
var rowIndex = rowData.data.__VIRTUAL_SCROLL_INDEX;
var newTrHeightList = trHeightList;
if (newTrHeightList[rowIndex] !== trHeight) {
newTrHeightList[rowIndex] = trHeight;
setTrHeightList(newTrHeightList);
var scrollTopHeightList = getTrScrollTopHeightList(newTrHeightList);
trScrollTopHeightList.current = scrollTopHeightList;
var lastIndex = scrollTopHeightList.length - 1;
setScrollHeight(scrollTopHeightList[lastIndex] - containerHeight.current);
updateVisibleData(scrollTopHeightList, container.current.scrollTop);
}
};
var handleScroll = function handleScroll() {
if (!isVirtualScroll) return;
updateVisibleData(trScrollTopHeightList.current, container.current.scrollTop);
};
var addIndexToData = function addIndexToData(data2) {
data2.forEach(function (item, index) {
Reflect.set(item, "__VIRTUAL_SCROLL_INDEX", index);
});
};
var updateScrollTop = function updateScrollTop(_ref) {
var _container$current;
var index = _ref.index,
_ref$top = _ref.top,
top = _ref$top === void 0 ? 0 : _ref$top,
behavior = _ref.behavior;
var scrollTop = trScrollTopHeightList.current[index] - top;
(_container$current = container.current) === null || _container$current === void 0 || _container$current.scrollTo({
top: scrollTop,
behavior: behavior || "auto"
});
};
var scrollToElement = function scrollToElement(p) {
updateScrollTop(p);
if (!tScroll.isFixedRowHeight) {
requestAnimationFrame(function () {
var _p$time;
var duration = (_p$time = p.time) !== null && _p$time !== void 0 ? _p$time : 60;
var timer = setTimeout(function () {
updateScrollTop(p);
clearTimeout(timer);
}, duration);
});
}
};
useEffect(function () {
if (!isVirtualScroll) {
trScrollTopHeightList.current = getTrScrollTopHeightList(trHeightList);
return;
}
addIndexToData(data);
var scrollTopHeightList = trScrollTopHeightList.current;
var dataChanged = !isEqual(dataRef.current, data);
if ((scrollTopHeightList === null || scrollTopHeightList === void 0 ? void 0 : scrollTopHeightList.length) === (data === null || data === void 0 ? void 0 : data.length) && !dataChanged) {
var lastIndex = scrollTopHeightList.length - 1;
setScrollHeight(scrollTopHeightList[lastIndex]);
updateVisibleData(scrollTopHeightList, container.current.scrollTop);
} else {
var _container$current2;
dataRef.current = data;
setScrollHeight(data.length * tScroll.rowHeight);
var currentScrollTop = ((_container$current2 = container.current) === null || _container$current2 === void 0 ? void 0 : _container$current2.scrollTop) || 0;
var currentIndex = Math.floor(currentScrollTop / tScroll.rowHeight);
var prevScrollTopHeightList = trScrollTopHeightList.current;
for (var i = 0; i < (prevScrollTopHeightList === null || prevScrollTopHeightList === void 0 ? void 0 : prevScrollTopHeightList.length); i++) {
if (prevScrollTopHeightList[i] >= currentScrollTop) {
currentIndex = i;
break;
}
}
var startIndex = Math.max(currentIndex - tScroll.bufferSize, 0);
var visibleCount = Math.min(tScroll.bufferSize * 3, data.length);
var endIndex = Math.min(startIndex + visibleCount, data.length);
var tmpData = data.slice(startIndex, endIndex);
var translateY2 = startIndex * tScroll.rowHeight;
if ((prevScrollTopHeightList === null || prevScrollTopHeightList === void 0 ? void 0 : prevScrollTopHeightList.length) > 0 && startIndex > 0) {
var prevHeight = prevScrollTopHeightList[Math.min(startIndex - 1, prevScrollTopHeightList.length - 1)] || 0;
translateY2 = Math.max(0, prevHeight);
}
setVisibleData(tmpData);
setTranslateY(translateY2);
}
var timer = setTimeout(function () {
if (container.current) {
var tmpContainerHeight = container.current.getBoundingClientRect().height;
containerHeight.current = tmpContainerHeight;
var scrollTopHeightList2 = getTrScrollTopHeightList(trHeightList);
trScrollTopHeightList.current = scrollTopHeightList2;
clearTimeout(timer);
}
}, 1);
}, [container, data, tScroll, isVirtualScroll, startAndEndIndex, trHeightList]);
return {
visibleData: visibleData,
translateY: translateY,
scrollHeight: scrollHeight,
isVirtualScroll: isVirtualScroll,
handleScroll: handleScroll,
handleRowMounted: handleRowMounted,
scrollToElement: scrollToElement
};
};
export { useVirtualScroll as default };
//# sourceMappingURL=useVirtualScroll.js.map