@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
JavaScript
;
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;