@gravity-ui/uikit
Version:
Gravity UI base styling and components
115 lines (114 loc) • 5.66 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createElement as _createElement } from "react";
import * as React from 'react';
import { useCollapseChildren, useForkRef, useResizeObserver } from "../../hooks/index.js";
import { useDefaultProps } from "../theme/useDefaultProps.js";
import { filterDOMProps } from "../utils/filterDOMProps.js";
import { BreadcrumbsDropdownMenu } from "./BreadcrumbsDropdownMenu.js";
import { BreadcrumbsItem } from "./BreadcrumbsItem.js";
import { BreadcrumbsSeparator } from "./BreadcrumbsSeparator.js";
import { b, getReactNodeHash } from "./utils.js";
import "./Breadcrumbs.css";
export const Breadcrumbs = React.forwardRef(function Breadcrumbs(rawProps, ref) {
const props = useDefaultProps('Breadcrumbs', rawProps);
const listRef = React.useRef(null);
const containerRef = useForkRef(ref, listRef);
const menuRef = React.useRef(null);
const endContentRef = React.useRef(null);
const items = [];
React.Children.forEach(props.children, (child, index) => {
if (React.isValidElement(child)) {
if (child.key === undefined || child.key === null) {
child = React.cloneElement(child, { key: index });
}
items.push(child);
}
});
const { calculated, recalculate, visibleCount: visibleItemsCount, } = useCollapseChildren({
containerRef: listRef,
preservedRefs: [menuRef, endContentRef],
direction: 'start',
minCount: 1,
maxCount: typeof props.maxItems === 'number' && props.maxItems < items.length
? props.maxItems - 1
: undefined,
childSelector: `.${b('item')}`,
getChildWidth: (child) => {
const width = child.getBoundingClientRect().width;
const maxWidth = child.dataset.current ? 200 : Infinity;
return Math.min(maxWidth, width);
},
});
useResizeObserver({
ref: endContentRef,
onResize: recalculate,
});
const childrenHash = getReactNodeHash(props.children);
const separatorHash = getReactNodeHash(props.separator);
React.useEffect(() => {
recalculate();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [childrenHash, separatorHash, props.itemComponent]);
let contents = items;
if (items.length > visibleItemsCount) {
contents = [];
const breadcrumbs = [...items];
let endItems = visibleItemsCount;
if (props.showRoot && visibleItemsCount > 1) {
const rootItem = breadcrumbs.shift();
if (rootItem) {
contents.push(rootItem);
}
endItems--;
}
const hiddenItems = breadcrumbs.slice(0, -endItems);
const menuItem = (_jsx(BreadcrumbsDropdownMenu, { disabled: props.disabled, popupPlacement: props.popupPlacement, popupStyle: props.popupStyle, "data-breadcrumbs-menu-item": true, children: hiddenItems.map((child, index) => {
const Component = props.itemComponent ?? BreadcrumbsItem;
const key = child.key ?? index;
const handleAction = () => {
if (typeof props.onAction === 'function') {
props.onAction(key);
}
};
const innerProps = {
__index: index,
__disabled: props.disabled || child.props.disabled,
__onAction: handleAction,
};
return (_createElement(Component, { ...child.props, key: key, ...innerProps }, child.props.children));
}) }));
contents.push(menuItem);
contents.push(...breadcrumbs.slice(-endItems));
}
return (_jsxs("ol", { ref: containerRef, ...filterDOMProps(props, { labelable: true }), "data-qa": props.qa, className: b(null, props.className), style: props.style, children: [contents.map((child, index) => {
const key = child.key ?? index;
const isCurrent = index === contents.length - 1;
const { 'data-breadcrumbs-menu-item': isMenu, ...childProps } = child.props;
let item;
if (isMenu) {
item = child;
}
else {
const Component = props.itemComponent ?? BreadcrumbsItem;
const handleAction = () => {
if (typeof props.onAction === 'function') {
props.onAction(key);
}
};
const innerProps = {
__current: isCurrent,
__disabled: props.disabled || childProps.disabled,
__onAction: handleAction,
};
item = (_createElement(Component, { ...childProps, key: key, ...innerProps }, childProps.children));
}
return (_jsxs("li", { ref: isMenu ? menuRef : undefined, className: b('item', {
calculating: isCurrent && !calculated,
current: isCurrent,
}), "data-current": isCurrent ? isCurrent : undefined, children: [item, isCurrent ? null : _jsx(BreadcrumbsSeparator, { separator: props.separator })] }, isMenu ? 'menu' : `item-${key}`));
}), props.endContent && (_jsx("li", { ref: endContentRef, className: b('item'), children: props.endContent }))] }));
});
Breadcrumbs.Item = BreadcrumbsItem;
Breadcrumbs.displayName = 'Breadcrumbs';
//# sourceMappingURL=Breadcrumbs.js.map