@gravity-ui/uikit
Version:
Gravity UI base styling and components
100 lines (99 loc) • 3.77 kB
JavaScript
import * as React from 'react';
import { useCollapseChildren } from "../../../hooks/useCollapseChildren/index.js";
import { useResizeObserver } from "../../../hooks/useResizeObserver/index.js";
import { getReactNodeHash } from "../../Breadcrumbs/utils.js";
import { bTab } from "../constants.js";
import { getTabNodePropsFromReactNode } from "../utils.js";
import { useTabListGapFromContainer } from "./useTabListGapFromContainer.js";
const TAB_LIST_CHILD_SELECTOR = `.${bTab()}`;
export const useTabListCollapsedChildren = (children, tabListValue, containerRef, enabled) => {
const collapseItemRef = React.useRef(null);
const childrenHash = getReactNodeHash(children);
const listGap = useTabListGapFromContainer(containerRef, {
enabled,
childrenHash,
childSelector: TAB_LIST_CHILD_SELECTOR,
});
const { recalculate, visibleCount: visibleChildrenCount } = useCollapseChildren({
enabled,
containerRef,
preservedRefs: [collapseItemRef],
direction: 'end',
minCount: 0,
gap: listGap,
childSelector: TAB_LIST_CHILD_SELECTOR,
});
React.useEffect(() => {
recalculate();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [childrenHash, tabListValue]);
useResizeObserver({
ref: collapseItemRef,
onResize: recalculate,
});
// Don't collapse selected tab
const isReactNodeCollapsible = React.useCallback((child) => {
const tabProps = getTabNodePropsFromReactNode(child);
if (tabProps === undefined) {
return true;
}
return tabListValue !== tabProps['value'];
}, [tabListValue]);
const childrenList = [];
React.Children.forEach(children, (child, index) => {
if (!React.isValidElement(child)) {
return;
}
if (child.key === undefined || child.key === null) {
childrenList.push(React.cloneElement(child, { key: index }));
return;
}
childrenList.push(child);
});
if (!enabled) {
return {
shownChildren: childrenList,
collapsedChildren: [],
collapseItemRef,
triggerChild: null,
};
}
if (visibleChildrenCount === 0) {
const selectedChild = childrenList.find((child) => !isReactNodeCollapsible(child)) ?? childrenList[0];
const otherChildren = childrenList.filter((c) => c !== selectedChild);
// Only 1 tab is provided, so we don't need to collapse it
if (otherChildren.length === 0) {
return {
shownChildren: selectedChild ? [selectedChild] : [],
collapsedChildren: [],
collapseItemRef,
triggerChild: null,
};
}
return {
shownChildren: [],
collapsedChildren: otherChildren,
collapseItemRef,
triggerChild: selectedChild,
};
}
const notCollapsibleChildren = childrenList.filter((child) => !isReactNodeCollapsible(child));
const shownChildren = [];
const collapsedChildren = [];
let reservedToShowChildrenCount = notCollapsibleChildren.length;
childrenList.forEach((child) => {
if (!isReactNodeCollapsible(child)) {
shownChildren.push(child);
reservedToShowChildrenCount--;
return;
}
if (shownChildren.length < visibleChildrenCount - reservedToShowChildrenCount) {
shownChildren.push(child);
}
else {
collapsedChildren.push(child);
}
});
return { shownChildren, collapsedChildren, triggerChild: null, collapseItemRef };
};
//# sourceMappingURL=useTabListCollapsedChildren.js.map