@coreui/react-pro
Version:
UI Components Library for React.js
84 lines (80 loc) • 4.35 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(() => {
if (virtualScrollRef.current) {
void virtualScrollRef.current.scrollTop; // force reflow
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(() => {
var _a;
setMaxHeight(itemsNumber * itemHeight);
void ((_a = virtualScrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollTop); // force reflow
}, [itemHeight, itemsNumber]);
React.useEffect(() => {
setBuffer(Math.floor(visibleItems / 2));
}, [visibleItems]);
const handleScroll = (scrollTop) => {
const _currentItemIndex = itemHeight ? Math.max(Math.ceil(scrollTop / itemHeight), 1) : 0;
setCurrentItemIndex(_currentItemIndex);
onScroll === null || onScroll === void 0 ? void 0 : onScroll(_currentItemIndex);
};
return (React.createElement("div", Object.assign({ className: index.default('virtual-scroller', className), onScroll: (event) => handleScroll(event.currentTarget.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) {
const childElement = child;
return React.cloneElement(childElement, {
className: index.default(childElement.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