@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
115 lines (114 loc) • 4.75 kB
JavaScript
"use client";
import { getSpacing } from "../../core/utils/get-size/get-size.mjs";
import { createVarsResolver } from "../../core/styles-api/create-vars-resolver/create-vars-resolver.mjs";
import { useProps } from "../../core/MantineProvider/use-props/use-props.mjs";
import { useStyles } from "../../core/styles-api/use-styles/use-styles.mjs";
import { genericFactory } from "../../core/factory/factory.mjs";
import { Box } from "../../core/Box/Box.mjs";
import { getRowPositionsData } from "./get-row-position-data.mjs";
import { useDimensions } from "./use-dimensions.mjs";
import OverflowList_module_default from "./OverflowList.module.mjs";
import { cloneElement, useRef, useState } from "react";
import { useIsomorphicEffect, useMergedRef } from "@mantine/hooks";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
//#region packages/@mantine/core/src/components/OverflowList/OverflowList.tsx
const defaultProps = {
maxRows: 1,
maxVisibleItems: Infinity
};
const varsResolver = createVarsResolver((_, { gap }) => ({ root: { "--ol-gap": getSpacing(gap) } }));
const OverflowList = genericFactory((_props) => {
const props = useProps("OverflowList", defaultProps, _props);
const { classNames, className, style, styles, unstyled, vars, attributes, data, renderOverflow, renderItem, maxRows, maxVisibleItems, ref, ...others } = props;
const getStyles = useStyles({
name: "OverflowList",
classes: OverflowList_module_default,
props,
className,
style,
classNames,
styles,
unstyled,
attributes,
vars,
varsResolver
});
const [visibleCount, setVisibleCount] = useState(data.length);
const [subtractCount, setSubtractCount] = useState(0);
const [phase, setPhase] = useState("normal");
const containerRef = useRef(null);
const rootRef = useMergedRef(containerRef, ref);
const finalVisibleCount = visibleCount - subtractCount;
const overflowElement = data.length - finalVisibleCount > 0 && phase !== "measuring" ? renderOverflow?.(data.slice(finalVisibleCount)) : null;
const _overflowRef = useRef(null);
const overflowRef = useMergedRef(_overflowRef, overflowElement?.ref);
const dimensions = useDimensions(containerRef);
useIsomorphicEffect(() => {
setPhase("measuring");
setVisibleCount(data.length);
setSubtractCount(0);
}, [data.length, maxRows]);
useIsomorphicEffect(() => {
if (phase === "measuring") {
countVisibleItems();
setPhase("measuring-overflow-indicator");
}
}, [phase]);
useIsomorphicEffect(() => {
if (phase === "measuring-overflow-indicator") {
if (!updateOverflowIndicator()) setPhase("normal");
}
}, [phase, subtractCount]);
useIsomorphicEffect(() => {
if (phase === "normal") {
setPhase("measuring");
setSubtractCount(0);
}
}, [dimensions]);
const countVisibleItems = () => {
const rowData = getRowPositionsData(containerRef, _overflowRef);
if (!rowData) return;
if (data.length === 1) {
const itemRef = rowData.itemsSizesMap[rowData.rowPositions[0]].elements.values().next().value;
const containerWidth = containerRef.current?.getBoundingClientRect().width ?? 0;
if ((itemRef?.getBoundingClientRect().width ?? 0) > containerWidth) setVisibleCount(0);
else setVisibleCount(1);
return;
}
let fittingCount = rowData.rowPositions.slice(0, maxRows).reduce((acc, position) => {
return acc + rowData.itemsSizesMap[position].elements.size;
}, 0);
fittingCount = Math.min(fittingCount, maxVisibleItems);
setVisibleCount(fittingCount);
};
const updateOverflowIndicator = () => {
if (!_overflowRef.current) return false;
const rowData = getRowPositionsData(containerRef, _overflowRef);
if (!rowData) return false;
const { rowPositions, itemsSizesMap } = rowData;
const overflowRect = _overflowRef.current.getBoundingClientRect();
if (overflowRect.top + overflowRect.height / 2 > itemsSizesMap[rowPositions[rowPositions.length - 1]].bottom) {
setSubtractCount((c) => c + 1);
return true;
}
return false;
};
const clonedOverflowElement = overflowElement ? cloneElement(overflowElement, { ref: overflowRef }) : null;
let finalItems = data;
if (maxVisibleItems) finalItems = finalItems.slice(0, maxVisibleItems);
return /* @__PURE__ */ jsxs(Box, {
ref: rootRef,
...getStyles("root"),
...others,
children: [finalItems.map((item, index) => {
if (!(phase === "measuring" || index < finalVisibleCount)) return null;
return /* @__PURE__ */ jsx(Fragment$1, { children: renderItem(item, index) }, index);
}), clonedOverflowElement]
});
});
OverflowList.displayName = "@mantine/core/OverflowList";
OverflowList.classes = OverflowList_module_default;
OverflowList.varsResolver = varsResolver;
//#endregion
export { OverflowList };
//# sourceMappingURL=OverflowList.mjs.map