UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

185 lines (184 loc) 8.03 kB
'use client'; import { debounce, Device, useStylesheet, useSyncRef } from '@ui5/webcomponents-react-base'; import { clsx } from 'clsx'; import { cloneElement, forwardRef, isValidElement, useEffect, useMemo, useRef, useState } from 'react'; import { FlexBoxAlignItems } from '../../enums/FlexBoxAlignItems.js'; import { FlexBoxDirection } from '../../enums/FlexBoxDirection.js'; import { FlexBoxJustifyContent } from '../../enums/FlexBoxJustifyContent.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, snappedHeader, snappedSubHeader, _snappedAvatar, ...rest } = props; useStylesheet(styleData, ObjectPageTitle.displayName); const [componentRef, dynamicPageTitleRef] = useSyncRef(ref); const [showNavigationInTopArea, setShowNavigationInTopArea] = useState(undefined); const isMounted = useRef(false); const [isPhone, setIsPhone] = useState(false); const containerClasses = clsx(classNames.container, isPhone && classNames.phone, className); const toolbarContainerRef = useRef(null); const _header = !props?.['data-header-content-visible'] && snappedHeader ? snappedHeader : header; const _subHeader = !props?.['data-header-content-visible'] && snappedSubHeader ? snappedSubHeader : subHeader; 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, showNavigationInTopArea, isMounted]); const wcrNavToolbar = useMemo(() => { //@ts-expect-error: private identifier if (/*#__PURE__*/isValidElement(navigationBar) && navigationBar?.type?._displayName === 'UI5WCRToolbar') { return /*#__PURE__*/cloneElement(navigationBar, { numberOfAlwaysVisibleItems: Infinity }); } return null; }, [navigationBar]); useEffect(() => { const toolbarContainer = toolbarContainerRef.current; const updateNavigationToolbar = container => { if (container.children.length >= 2) { const lastChild = container.lastElementChild; if (lastChild && lastChild.matches('[ui5-toolbar]')) { Array.from(lastChild.children).forEach(item => { item.setAttribute('overflow-priority', 'NeverOverflow'); }); } } }; const observer = new MutationObserver(([toolbarContainerMutation]) => { if (toolbarContainerMutation.type === 'childList') { updateNavigationToolbar(toolbarContainerMutation.target); } }); const config = { childList: true, subtree: true }; if (toolbarContainer) { updateNavigationToolbar(toolbarContainer); 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.End, children: [/*#__PURE__*/_jsx("div", { className: classNames.snappedAvatarContainer, children: _snappedAvatar }), /*#__PURE__*/_jsx(FlexBox, { direction: FlexBoxDirection.Column, className: classNames.contentContainer, children: /*#__PURE__*/_jsxs(FlexBox, { alignItems: FlexBoxAlignItems.Center, className: classNames.middleSection, "data-component-name": "ObjectPageTitleMiddleSection", children: [/*#__PURE__*/_jsxs(FlexBox, { direction: FlexBoxDirection.Column, className: classNames.titleAndSubHeader, children: [/*#__PURE__*/_jsxs(FlexBox, { className: classNames.titleMainSection, onClick: onHeaderClick, children: [_header && /*#__PURE__*/_jsx("div", { className: classNames.title, "data-component-name": "ObjectPageTitleHeader", children: _header }), children && /*#__PURE__*/_jsx("div", { className: classNames.content, "data-component-name": "ObjectPageTitleContent", children: children })] }), _subHeader && /*#__PURE__*/_jsx("div", { className: clsx(classNames.subTitle, classNames.subTitleBottom), "data-component-name": "ObjectPageTitleSubHeader", children: _subHeader })] }), (actionsBar || !showNavigationInTopArea && navigationBar) && /*#__PURE__*/_jsxs("div", { className: classNames.toolbar, ref: toolbarContainerRef, children: [actionsBar, !showNavigationInTopArea && actionsBar && navigationBar && /*#__PURE__*/_jsx("div", { className: classNames.actionsSeparator, "data-component-name": "ObjectPageTitleActionsSeparator", "aria-hidden": "true" }), !showNavigationInTopArea && (wcrNavToolbar ? wcrNavToolbar : navigationBar)] })] }) })] }), props?.['data-header-content-visible'] ? expandedContent : snappedContent] }); }); ObjectPageTitle.displayName = 'ObjectPageTitle'; export { ObjectPageTitle };