UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

166 lines (165 loc) 7.38 kB
'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 };