@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
166 lines (165 loc) • 7.38 kB
JavaScript
'use client';
import { debounce, Device, useStylesheet, useSyncRef } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import { cloneElement, forwardRef, isValidElement, useEffect, useRef, useState } from 'react';
import { FlexBoxAlignItems, FlexBoxDirection, FlexBoxJustifyContent } from '../../enums/index.js';
import { stopPropagation } from '../../internal/stopPropagation.js';
import { FlexBox } from '../FlexBox/index.js';
import { classNames, styleData } from './ObjectPageTitle.module.css.js';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
* The `ObjectPageTitle` component is used to serve as title of the `ObjectPage`.
* It can contain Breadcrumbs, Title, Subtitle, Content, KPIs and Actions.
*
* __Note:__ When used inside a custom component, it's essential to pass through all props, as otherwise the component won't function as intended!
*/
const ObjectPageTitle = /*#__PURE__*/forwardRef((props, ref) => {
const {
actionsBar,
breadcrumbs,
children,
header,
subHeader,
navigationBar,
className,
onToggleHeaderContentVisibility,
expandedContent,
snappedContent,
...rest
} = props;
useStylesheet(styleData, ObjectPageTitle.displayName);
const [componentRef, dynamicPageTitleRef] = useSyncRef(ref);
const [showNavigationInTopArea, setShowNavigationInTopArea] = useState(undefined);
const isMounted = useRef(false);
const [isPhone, setIsPhone] = useState(Device.getCurrentRange(dynamicPageTitleRef.current?.getBoundingClientRect().width)?.name === 'Phone');
const containerClasses = clsx(classNames.container, isPhone && classNames.phone, className);
const toolbarContainerRef = useRef(null);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, [isMounted]);
const onHeaderClick = e => {
if (typeof onToggleHeaderContentVisibility === 'function') {
onToggleHeaderContentVisibility(e);
}
};
useEffect(() => {
const debouncedObserverFn = debounce(([titleContainer]) => {
// Firefox implements `borderBoxSize` as a single content rect, rather than an array
const borderBoxSize = Array.isArray(titleContainer.borderBoxSize) ? titleContainer.borderBoxSize[0] : titleContainer.borderBoxSize;
// Safari doesn't implement `borderBoxSize`
const titleContainerWidth = borderBoxSize?.inlineSize ?? titleContainer.target.getBoundingClientRect().width;
setIsPhone(Device.getCurrentRange(titleContainerWidth)?.name === 'Phone');
if (titleContainerWidth < 1280 && !showNavigationInTopArea === true && isMounted.current) {
setShowNavigationInTopArea(true);
} else if (titleContainerWidth >= 1280 && !showNavigationInTopArea === false && isMounted.current) {
setShowNavigationInTopArea(false);
}
}, 150);
const observer = new ResizeObserver(debouncedObserverFn);
if (dynamicPageTitleRef.current) {
observer.observe(dynamicPageTitleRef.current);
}
return () => {
debouncedObserverFn.cancel();
observer.disconnect();
};
}, [dynamicPageTitleRef.current, showNavigationInTopArea, isMounted]);
const [wcrNavToolbar, setWcrNavToolbar] = useState(null);
useEffect(() => {
//@ts-expect-error: private identifier
if ( /*#__PURE__*/isValidElement(navigationBar) && navigationBar?.type?._displayName === 'UI5WCRToolbar') {
setWcrNavToolbar( /*#__PURE__*/cloneElement(navigationBar, {
numberOfAlwaysVisibleItems: Infinity
}));
}
}, [navigationBar]);
useEffect(() => {
const toolbarContainer = toolbarContainerRef.current;
const observer = new MutationObserver(([toolbarContainerMutation]) => {
if (toolbarContainerMutation.type === 'childList') {
const navigationToolbar = toolbarContainerMutation.target.querySelector(':has(> :nth-last-child(n + 2)) > [ui5-toolbar]:last-child');
if (navigationToolbar?.children) {
Array.from(navigationToolbar.children).forEach(item => {
item.setAttribute('overflow-priority', 'NeverOverflow');
});
}
}
});
const config = {
childList: true,
subtree: true
};
if (toolbarContainer) {
const navigationToolbar = toolbarContainer.querySelector(':has(> :nth-last-child(n + 2)) > [ui5-toolbar]:last-child');
if (navigationToolbar?.children) {
Array.from(navigationToolbar.children).forEach(item => {
item.setAttribute('overflow-priority', 'NeverOverflow');
});
}
observer.observe(toolbarContainer, config);
}
return () => {
observer.disconnect();
};
}, []);
return /*#__PURE__*/_jsxs(FlexBox, {
className: containerClasses,
ref: componentRef,
"data-component-name": "ObjectPageTitle",
direction: FlexBoxDirection.Column,
justifyContent: FlexBoxJustifyContent.SpaceBetween,
...rest,
children: [/*#__PURE__*/_jsx("span", {
className: classNames.clickArea,
onClick: onHeaderClick,
"data-component-name": "ObjectPageTitleClickElement"
}), (breadcrumbs || navigationBar && showNavigationInTopArea) && /*#__PURE__*/_jsxs(FlexBox, {
justifyContent: FlexBoxJustifyContent.SpaceBetween,
"data-component-name": "ObjectPageTitleBreadcrumbs",
children: [breadcrumbs && /*#__PURE__*/_jsx("div", {
className: classNames.breadcrumbs,
onClick: stopPropagation,
children: breadcrumbs
}), showNavigationInTopArea && navigationBar && /*#__PURE__*/_jsx("div", {
className: classNames.toolbar,
children: navigationBar
})]
}), /*#__PURE__*/_jsxs(FlexBox, {
alignItems: FlexBoxAlignItems.Center,
className: classNames.middleSection,
"data-component-name": "ObjectPageTitleMiddleSection",
children: [/*#__PURE__*/_jsxs(FlexBox, {
className: classNames.titleMainSection,
onClick: onHeaderClick,
children: [header && /*#__PURE__*/_jsx("div", {
className: classNames.title,
"data-component-name": "ObjectPageTitleHeader" /*onClick={onHeaderClick}*/,
children: header
}), children && /*#__PURE__*/_jsx("div", {
className: classNames.content,
"data-component-name": "ObjectPageTitleContent",
children: children
})]
}), (actionsBar || !showNavigationInTopArea && navigationBar) && /*#__PURE__*/_jsxs("div", {
className: classNames.toolbar,
ref: toolbarContainerRef,
children: [actionsBar, !showNavigationInTopArea && actionsBar && navigationBar && /*#__PURE__*/_jsx("div", {
className: classNames.actionsSpacer,
"data-component-name": "ObjectPageTitleActionsSeparator",
"aria-hidden": true
}), !showNavigationInTopArea && (wcrNavToolbar ? wcrNavToolbar : navigationBar)]
})]
}), subHeader && /*#__PURE__*/_jsx(FlexBox, {
children: /*#__PURE__*/_jsx("div", {
className: clsx(classNames.subTitle, classNames.subTitleBottom),
"data-component-name": "ObjectPageTitleSubHeader",
children: subHeader
})
}), props?.['data-header-content-visible'] ? expandedContent : props['data-is-snapped-rendered-outside'] ? undefined : snappedContent]
});
});
ObjectPageTitle.displayName = 'ObjectPageTitle';
export { ObjectPageTitle };