UNPKG

@coreui/react-pro

Version:

UI Components Library for React.js

84 lines (80 loc) 4.35 kB
'use strict'; 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