import React, { useCallback, useEffect, useLayoutEffect, useRef, useState, } from 'react' import Button from '../../Button/Button' import { envColorMap, envName } from '../../../services/EnvironmentHelper' import PatternLogo from '../../PatternLogo/PatternLogo' import Tag from '../../Tag/Tag' import { useTouchDeviceDetection } from '../../../hooks/useTouchDeviceDetection/useTouchDeviceDetection' import { useWindowSize } from '../../../hooks/useWindowSize/useWindowSize' import { type LeftNavProps } from '../LeftNav' import styles from './_left-nav-desktop.module.scss' import LeftNavFooter from '../Common/LeftNavFooter/LeftNavFooter' import LeftNavLinkContainer from '../Common/LeftNavLinkContainer/LeftNavLinkContainer' import { useHoverAndTouchSidebar } from '../Common/useHoverAndTouchSidebar' import { type TagProps } from '../../Tag/Tag' import { c } from '../../../translations/LibraryTranslationService' const LeftNavDesktop = ({ logo, footer, leftNavLinks, breadcrumbs, accountPopoverProps, navigate, heightOffset, environment = 'production', routerComponent, routerProp, languageConfig, hideLogo = false, hideCopyright = false, qaTestId = 'left-nav-desktop', linkSegmentIndexToMatch, }: Omit): React.JSX.Element => { const [linkContainerHeight, setLinkContainerHeight] = useState< string | number >('auto') const sidebarRef = useRef(null) const logoRef = useRef(null) const headerRef = useRef(null) const linkContainerRef = useRef(null) const footerRef = useRef(null) const logoWidth = logoRef.current?.clientWidth const pageDimensions = useWindowSize() const isTouchDevice = useTouchDeviceDetection() const [hovered, isUseable, closeSidebar, setHovered] = useHoverAndTouchSidebar(sidebarRef) const logoCallout = () => { navigate() closeSidebar() } useLayoutEffect(() => { const headerHeight = headerRef.current?.clientHeight ?? 0 const footerHeight = footerRef.current?.clientHeight ?? 0 const heightToSubtract = headerHeight + footerHeight + (heightOffset ?? 0) const height = window.innerHeight - heightToSubtract setLinkContainerHeight(height) }, [pageDimensions, heightOffset]) const calculateHeight = useCallback(() => { const headerHeight = headerRef.current?.clientHeight ?? 0 const footerHeight = footerRef.current?.clientHeight ?? 0 const heightToSubtract = headerHeight + footerHeight + (heightOffset ?? 0) const height = window.innerHeight - heightToSubtract setLinkContainerHeight(height) }, [heightOffset]) useEffect(() => { const handleResize = () => { calculateHeight() } window.addEventListener('resize', handleResize) // Create observer to watch for size changes const resizeObserver = new ResizeObserver(calculateHeight) if (headerRef.current) { resizeObserver.observe(headerRef.current) if (footerRef.current) { resizeObserver.observe(footerRef.current) } } return () => { window.removeEventListener('resize', handleResize) resizeObserver.disconnect() } }, [calculateHeight]) const envColor = envColorMap[environment] const logoMaxHeight = logo.maxHeight ? { maxHeight: logo.maxHeight } : {} const Logo = () => { const logoStyles = hovered ? { height: 24, marginLeft: 24, ...logoMaxHeight, } : { width: 50, ...logoMaxHeight } const logoSrc = hovered ? logo.url : logo.abbreviatedUrl return (
{hovered || (!hideLogo ? : null)} {c('logo')}
) } const EnvironmentTag = () => { const logoSrc = hovered ? logo.isolatedUrl : logo.abbreviatedUrl return (
{envName[environment]} {c('logo')}
) } return (
{/* This is needed to prevent Sidebar elements from being clickable while Sidebar is closed. This experience should only be present for touch screen devices (except Mobile since this component is only rendered on larger devices). */} {isTouchDevice && !isUseable ? (
) : null}
{/* logo.abbreviatedUrl && logo.isolatedUrl are added here so that only apps with the new logos are updated. Shelf is the only application that will not receive this update for now. */} {logo.abbreviatedUrl && logo.isolatedUrl ? (
) : (
{/********************************* LOGO *********************************/} {/*************************** ENVIRONMENT TAG ***************************/} {environment !== 'production' ? (
{/* Casting here is necessary so Tag understands that these envColor options are allowed. All colors fall under TagProps['color'] so we will not have any strange behavior. */} {envName[environment]}
) : null}
)} {/**************************** NAVIGATION LINKS ****************************/}
{/********************************** FOOTER **********************************/} setHovered(true)} languageConfig={languageConfig} hideCopyright={hideCopyright} />
) } export default LeftNavDesktop