@coreui/react-pro
Version:
UI Components Library for React.js
81 lines (77 loc) • 4.17 kB
JavaScript
;
var tslib_es6 = require('../../node_modules/tslib/tslib.es6.js');
var React = require('react');
var PropTypes = require('prop-types');
var index = require('../../_virtual/index.js');
require('@popperjs/core');
var useForkedRef = require('../../hooks/useForkedRef.js');
const CVirtualScroller = React.forwardRef((_a, ref) => {
var { children, className, visibleItems, onScroll } = _a, rest = tslib_es6.__rest(_a, ["children", "className", "visibleItems", "onScroll"]);
const virtualScrollRef = React.useRef(null);
const virtualScrollContentRef = React.useRef(null);
const forkedRef = useForkedRef.useForkedRef(ref, virtualScrollRef);
const [buffer, setBuffer] = React.useState(Math.floor(visibleItems / 2));
const [currentItemIndex, setCurrentItemIndex] = React.useState(1);
const [itemHeight, setItemHeight] = React.useState(0);
const [itemsNumber, setItemsNumber] = React.useState(React.Children.count(children));
const [viewportPadding, setViewportPadding] = React.useState(0);
const [viewportHeight, setViewportHeight] = React.useState(visibleItems * itemHeight + 2 * viewportPadding);
const [maxHeight, setMaxHeight] = React.useState(itemsNumber * itemHeight + 2 * viewportPadding);
React.useEffect(() => {
virtualScrollRef.current && virtualScrollRef.current.scrollTop;
virtualScrollRef.current &&
setViewportPadding(Number.parseFloat(getComputedStyle(virtualScrollRef.current).paddingTop));
});
React.useEffect(() => {
setItemsNumber(React.Children.count(children));
}, [children]);
React.useEffect(() => {
setViewportHeight(Math.min(visibleItems, itemsNumber) * itemHeight + 2 * viewportPadding);
}, [itemHeight, itemsNumber, viewportPadding, visibleItems]);
React.useEffect(() => {
setMaxHeight(itemsNumber * itemHeight);
virtualScrollRef.current && virtualScrollRef.current.scrollTop;
}, [itemHeight, itemsNumber]);
React.useEffect(() => {
setBuffer(Math.floor(visibleItems / 2));
}, [visibleItems]);
const handleScroll = (scrollTop) => {
const _currentItemIndex = itemHeight && Math.max(Math.ceil(scrollTop / itemHeight), 1);
setCurrentItemIndex(_currentItemIndex);
onScroll && onScroll(_currentItemIndex);
};
return (React.createElement("div", Object.assign({ className: index.default('virtual-scroller', className), onScroll: (event) => handleScroll(event.target.scrollTop), style: {
height: viewportHeight,
overflowY: 'auto',
}, ref: forkedRef }, rest),
React.createElement("div", { className: "virtual-scroller-content", style: {
height: maxHeight,
}, ref: virtualScrollContentRef }, React.Children.map(children, (child, index$1) => {
if (React.isValidElement(child) &&
index$1 + 1 > Math.max(currentItemIndex - buffer, 0) &&
index$1 + 1 <= currentItemIndex + visibleItems + buffer) {
return React.cloneElement(child, {
className: index.default(child.props.className, {
'virtual-scroller-item-preload': index$1 + 1 > currentItemIndex + visibleItems || index$1 + 1 < currentItemIndex,
}),
key: index$1,
style: Object.assign({}, (currentItemIndex > buffer && {
transform: `translateY(${(currentItemIndex - buffer) * itemHeight}px)`,
})),
ref: (node) => node &&
node.offsetHeight &&
setItemHeight(node.offsetHeight +
Number.parseFloat(getComputedStyle(node).marginTop) +
Number.parseFloat(getComputedStyle(node).marginBottom)),
});
}
return;
}))));
});
CVirtualScroller.propTypes = {
onScroll: PropTypes.func,
visibleItems: PropTypes.number.isRequired,
};
CVirtualScroller.displayName = 'CVirtualScroller';
exports.CVirtualScroller = CVirtualScroller;
//# sourceMappingURL=CVirtualScroller.js.map