UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

154 lines (153 loc) 7.13 kB
'use client'; import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime"; import * as React from 'react'; import _throttle from "lodash/throttle.js"; import { block } from "../../utils/cn.js"; import { BreadcrumbsItem as Item } from "./BreadcrumbsItem.js"; import { BreadcrumbsMore } from "./BreadcrumbsMore.js"; import { BreadcrumbsSeparator } from "./BreadcrumbsSeparator.js"; import "./Breadcrumbs.css"; const RESIZE_THROTTLE = 200; const MORE_ITEM_WIDTH = 34; const DEFAULT_POPUP_PLACEMENT = ['bottom', 'top']; const GAP_WIDTH = 4; const b = block('breadcrumbs-legacy'); export var LastDisplayedItemsCount; (function (LastDisplayedItemsCount) { LastDisplayedItemsCount[LastDisplayedItemsCount["One"] = 1] = "One"; LastDisplayedItemsCount[LastDisplayedItemsCount["Two"] = 2] = "Two"; })(LastDisplayedItemsCount || (LastDisplayedItemsCount = {})); export var FirstDisplayedItemsCount; (function (FirstDisplayedItemsCount) { FirstDisplayedItemsCount[FirstDisplayedItemsCount["Zero"] = 0] = "Zero"; FirstDisplayedItemsCount[FirstDisplayedItemsCount["One"] = 1] = "One"; })(FirstDisplayedItemsCount || (FirstDisplayedItemsCount = {})); /** * @deprecated */ export class Breadcrumbs extends React.Component { static defaultProps = { popupPlacement: DEFAULT_POPUP_PLACEMENT, }; static prepareInitialState(props) { const { firstDisplayedItemsCount } = props; return { calculated: false, rootItem: firstDisplayedItemsCount ? props.items[0] : undefined, visibleItems: props.items.slice(firstDisplayedItemsCount), hiddenItems: [], allItems: props.items, }; } static getDerivedStateFromProps(props, state) { if (state.allItems !== props.items) { return Breadcrumbs.prepareInitialState(props); } return null; } container; resizeObserver; constructor(props) { super(props); this.handleResize = _throttle(this.handleResize, RESIZE_THROTTLE); if (typeof window !== 'undefined') { this.resizeObserver = new ResizeObserver(this.handleResize); } this.container = React.createRef(); this.state = Breadcrumbs.prepareInitialState(props); } componentDidMount() { this.recalculate(); this.resizeObserver?.observe(this.container.current); } componentDidUpdate(prevProps) { if (prevProps.items !== this.state.allItems) { this.recalculate(); } } componentWillUnmount() { this.resizeObserver?.disconnect(); } render() { const { className, qa } = this.props; const { calculated } = this.state; return (_jsx("div", { className: b({ calculated: calculated ? 'yes' : 'no' }, className), "data-qa": qa, children: _jsxs("div", { className: b('inner'), ref: this.container, children: [this.renderRootItem(), this.renderMoreItem(), this.renderVisibleItems()] }) })); } renderItem(item, isCurrent, isPrevCurrent, renderItemContent) { return (_jsx(Item, { item: item, isCurrent: isCurrent, isPrevCurrent: isPrevCurrent, renderItemContent: renderItemContent || this.props.renderItemContent, renderItem: this.props.renderItem })); } renderItemDivider() { const { renderItemDivider } = this.props; return _jsx(BreadcrumbsSeparator, { renderItemDivider: renderItemDivider }); } renderRootItem() { const { renderRootContent } = this.props; const { rootItem, visibleItems } = this.state; const isCurrent = visibleItems.length === 0; if (!rootItem) { return null; } return this.renderItem(rootItem, isCurrent, false, renderRootContent); } renderVisibleItems() { const { visibleItems } = this.state; return visibleItems.map((item, index, items) => { const isCurrent = index === items.length - 1; const isPrevCurrent = index === items.length - 2; return (_jsxs(React.Fragment, { children: [this.renderItemDivider(), this.renderItem(item, isCurrent, isPrevCurrent)] }, index)); }); } renderMoreItem() { const { hiddenItems } = this.state; if (hiddenItems.length === 0) { return null; } const { popupStyle, popupPlacement, renderItemDivider } = this.props; return (_jsxs(React.Fragment, { children: [_jsx(BreadcrumbsSeparator, { renderItemDivider: renderItemDivider }), _jsx(BreadcrumbsMore, { items: hiddenItems, popupPlacement: popupPlacement, popupStyle: popupStyle })] })); } recalculate() { const { items: allItems, lastDisplayedItemsCount, firstDisplayedItemsCount } = this.props; let availableWidth = this.container.current?.offsetWidth || 0; if (this.container.current && availableWidth > 0) { availableWidth += GAP_WIDTH; const dividers = Array.from(this.container.current.querySelectorAll(`.${b('divider')}`)); const items = [ ...Array.from(this.container.current.querySelectorAll(`.${b('switcher')}`)), ...Array.from(this.container.current.querySelectorAll(`.${b('item')}`)), ]; const itemsWidths = items.map((elem, i) => elem.scrollWidth + (i === items.length - 1 ? GAP_WIDTH : GAP_WIDTH * 2)); const dividersWidths = dividers.map((elem) => elem.offsetWidth); const buttonsWidth = itemsWidths.reduce((total, width, index, widths) => { const isLastItem = widths.length - 1 === index; const isItemBeforeLast = lastDisplayedItemsCount === LastDisplayedItemsCount.Two && widths.length - 2 === index; if (isLastItem || isItemBeforeLast) { return total + Math.min(width, 200); } return total + width; }, 0); const dividersWidth = dividersWidths.reduce((total, width) => total + width, 0); let totalWidth = buttonsWidth + dividersWidth; let visibleItemsStartIndex = 1; while (totalWidth > availableWidth && visibleItemsStartIndex < items.length - lastDisplayedItemsCount) { if (visibleItemsStartIndex === 1) { totalWidth += MORE_ITEM_WIDTH + dividersWidths[visibleItemsStartIndex]; } totalWidth -= itemsWidths[visibleItemsStartIndex] + dividersWidths[visibleItemsStartIndex]; visibleItemsStartIndex++; } this.setState({ calculated: true, visibleItems: allItems.slice(visibleItemsStartIndex - (1 - firstDisplayedItemsCount)), hiddenItems: allItems.slice(firstDisplayedItemsCount, visibleItemsStartIndex - (1 - firstDisplayedItemsCount)), }); } } handleResize = () => { const state = Breadcrumbs.prepareInitialState(this.props); this.setState(state, this.recalculate); }; } //# sourceMappingURL=Breadcrumbs.js.map