UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

182 lines (181 loc) 7.74 kB
'use client'; "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Breadcrumbs = void 0; const tslib_1 = require("tslib"); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const React = tslib_1.__importStar(require("react")); const hooks_1 = require("../../hooks/index.js"); const filterDOMProps_1 = require("../utils/filterDOMProps.js"); const BreadcrumbsDropdownMenu_1 = require("./BreadcrumbsDropdownMenu.js"); const BreadcrumbsItem_1 = require("./BreadcrumbsItem.js"); const BreadcrumbsSeparator_1 = require("./BreadcrumbsSeparator.js"); const utils_1 = require("./utils.js"); require("./Breadcrumbs.css"); exports.Breadcrumbs = React.forwardRef(function Breadcrumbs(props, ref) { const listRef = React.useRef(null); const containerRef = (0, hooks_1.useForkRef)(ref, listRef); 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 [visibleItemsCount, setVisibleItemsCount] = React.useState(items.length); const [calculated, setCalculated] = React.useState(false); const recalculate = (visibleItems) => { const list = listRef.current; if (!list) { return; } const listItems = Array.from(list.children); const endElement = endContentRef.current; if (endElement) { listItems.pop(); } if (listItems.length === 0) { setCalculated(true); return; } const containerWidth = list.offsetWidth - (endElement?.offsetWidth ?? 0); let newVisibleItemsCount = 0; let calculatedWidth = 0; let maxItems = props.maxItems || Infinity; let rootWidth = 0; if (props.showRoot) { const item = listItems.shift(); if (item) { rootWidth = item.scrollWidth; calculatedWidth += rootWidth; } newVisibleItemsCount++; } const hasMenu = items.length > visibleItems; if (hasMenu) { const item = listItems.shift(); if (item) { calculatedWidth += item.offsetWidth; } maxItems--; } if (props.showRoot && calculatedWidth >= containerWidth) { calculatedWidth -= rootWidth; newVisibleItemsCount--; } const lastItem = listItems.pop(); if (lastItem) { calculatedWidth += Math.min(lastItem.offsetWidth, 200); if (calculatedWidth < containerWidth) { newVisibleItemsCount++; } } for (let i = listItems.length - 1; i >= 0; i--) { const item = listItems[i]; calculatedWidth += item.offsetWidth; if (calculatedWidth >= containerWidth) { break; } newVisibleItemsCount++; } newVisibleItemsCount = Math.max(Math.min(maxItems, newVisibleItemsCount), 1); if (newVisibleItemsCount === visibleItemsCount) { setCalculated(true); } else { setVisibleItemsCount(newVisibleItemsCount); } }; const handleResize = React.useCallback(() => { setCalculated(false); setVisibleItemsCount(items.length); }, [items.length]); (0, hooks_1.useResizeObserver)({ ref: listRef, onResize: handleResize, }); (0, hooks_1.useResizeObserver)({ ref: props.endContent ? endContentRef : undefined, onResize: handleResize, }); const lastChildren = React.useRef(null); React.useLayoutEffect(() => { if (calculated && props.children !== lastChildren.current) { lastChildren.current = props.children; setCalculated(false); setVisibleItemsCount(items.length); } }, [calculated, items.length, props.children]); React.useLayoutEffect(() => { if (!calculated) { recalculate(visibleItemsCount); } }); 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 = ((0, jsx_runtime_1.jsx)(BreadcrumbsDropdownMenu_1.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_1.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 ((0, react_1.createElement)(Component, { ...child.props, key: key, ...innerProps }, child.props.children)); }) })); contents.push(menuItem); contents.push(...breadcrumbs.slice(-endItems)); } const lastIndex = contents.length - 1; const breadcrumbsItems = contents.map((child, index) => { const isCurrent = index === lastIndex; const key = child.key ?? index; const { 'data-breadcrumbs-menu-item': isMenu, ...childProps } = child.props; let item; if (isMenu) { item = child; } else { const Component = props.itemComponent ?? BreadcrumbsItem_1.BreadcrumbsItem; const handleAction = () => { if (typeof props.onAction === 'function') { props.onAction(key); } }; const innerProps = { __current: isCurrent, __disabled: props.disabled || childProps.disabled, __onAction: handleAction, }; item = ((0, react_1.createElement)(Component, { ...childProps, key: key, ...innerProps }, childProps.children)); } return ((0, jsx_runtime_1.jsxs)("li", { className: (0, utils_1.b)('item', { calculating: isCurrent && !calculated, current: isCurrent }), children: [item, isCurrent ? null : (0, jsx_runtime_1.jsx)(BreadcrumbsSeparator_1.BreadcrumbsSeparator, { separator: props.separator })] }, isMenu ? 'menu' : `item-${key}`)); }); if (props.endContent) { breadcrumbsItems.push((0, jsx_runtime_1.jsx)("li", { ref: endContentRef, className: (0, utils_1.b)('item'), children: props.endContent }, "end-content")); } return ((0, jsx_runtime_1.jsx)("ol", { ref: containerRef, ...(0, filterDOMProps_1.filterDOMProps)(props, { labelable: true }), "data-qa": props.qa, className: (0, utils_1.b)(null, props.className), style: props.style, children: breadcrumbsItems })); }); exports.Breadcrumbs.Item = BreadcrumbsItem_1.BreadcrumbsItem; exports.Breadcrumbs.displayName = 'Breadcrumbs'; //# sourceMappingURL=Breadcrumbs.js.map