UNPKG

@adaptabletools/adaptable-cjs

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

106 lines (105 loc) 4.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EllipsisContainer = void 0; const tslib_1 = require("tslib"); const React = tslib_1.__importStar(require("react")); const react_1 = require("react"); const rebass_1 = require("rebass"); const useLatest_1 = require("../utils/useLatest"); const usePrevious_1 = tslib_1.__importDefault(require("../utils/usePrevious")); const Container = ({ children, index, hidden, observerRef, }) => { const [mounted, setMounted] = (0, react_1.useState)(false); React.useEffect(() => { const timeoutId = setTimeout(() => { // we wait for a bit, so intersection observer // has time to kick in before we trigger a rerender // to make the element visible if needed setMounted(true); }, 50); return () => clearTimeout(timeoutId); }, []); const domRef = (0, react_1.useRef)(null); const onMount = (node) => { if (node) { if (!node.getAttribute('data-index')) { throw 'The element you render from "renderItem" should accept a "data-index" prop.'; } observerRef.current?.observe(node); } else { observerRef.current?.unobserve(domRef.current); } domRef.current = node; }; let child = React.Children.toArray(children)[0]; const cloneProps = { ref: onMount, 'data-index': index, }; if (hidden || !mounted) { cloneProps.style = { ...child.props?.style, visibility: 'hidden' }; } child = React.cloneElement(child, cloneProps); return React.createElement(React.Fragment, null, child); }; const EllipsisContainer = (props) => { const { allowWrap, count, direction, renderItem, renderEllipsis, ...boxProps } = props; const domRef = (0, react_1.useRef)(null); const observerRef = (0, react_1.useRef)(null); const [minNotVisibleIndex, setMinNotVisibleIndex] = React.useState(props.count); const [visibleSet] = (0, react_1.useState)(() => new Set()); const [invisibleSet] = (0, react_1.useState)(() => new Set()); const getCount = (0, useLatest_1.useLatest)(props.count); React.useEffect(() => { const callback = (entries) => { const count = getCount(); const isVisible = (entry) => entry.intersectionRatio === 1; entries.forEach((entry) => { const { target } = entry; const index = Number(target.getAttribute('data-index')); const visible = isVisible(entry); if (visible) { visibleSet.add(index); invisibleSet.delete(index); } else { visibleSet.delete(index); invisibleSet.add(index); } }); const minNotVisibleIndex = Math.min(count, ...invisibleSet.values()); setMinNotVisibleIndex(minNotVisibleIndex); }; if (allowWrap) { return; } const observer = new IntersectionObserver(callback, { root: domRef.current, threshold: 0.01, }); observerRef.current = observer; return () => { observer.disconnect(); }; }, []); const prevCount = (0, usePrevious_1.default)(count, count); React.useLayoutEffect(() => { if (allowWrap) { return; } if (minNotVisibleIndex === prevCount) { setMinNotVisibleIndex(count); } }, [count, minNotVisibleIndex, allowWrap]); const children = [...new Array(count)].map((_, index) => { const remaining = count - 1 - index; const hidden = allowWrap ? false : index >= minNotVisibleIndex; return (React.createElement(React.Fragment, { key: index }, React.createElement(Container, { hidden: hidden, index: index, observerRef: observerRef }, renderItem(index, count)), !allowWrap && index === minNotVisibleIndex - 1 && remaining ? renderEllipsis?.({ remaining }) ?? '...' : null)); }); return (React.createElement(rebass_1.Flex, { ref: domRef, flexWrap: allowWrap ? 'wrap' : 'nowrap', alignItems: "center", "data-name": "options-container", ...boxProps, flexDirection: direction === 'horizontal' ? 'row' : 'column' }, children)); }; exports.EllipsisContainer = EllipsisContainer;