import React, { useEffect, useRef, useState } from 'react' import Icon from '../../Icons/Icon' import { type BreadcrumbType } from '../../Breadcrumbs/Common/BreadcrumbTypes' import { useIsMobileView } from '../../../hooks/useIsMobileView/useIsMobileView' import styles from './_left-nav-link.module.scss' import { type LeftNavLinkObj, type LeftNavProps } from '../LeftNav' export type LeftNavLinkProps = { /** The content to be displayed on the SidebarLink */ content: LeftNavLinkObj /** We need the first index of the breadcrumbs array to help us determine with SidebarLink is the active link */ firstBreadcrumb: BreadcrumbType /** The index is used to determine the active SidebarLink and also help create the animation effects */ index: number /** This boolean is necessary to help with styling the SidebarLink when in an expanded state */ isExpanded: boolean /** This boolean is necessary to help with improving the interaction on touch devices */ isUseable: boolean /** This callout function is needed to update the current active index */ setActiveBarPosition: React.Dispatch> /** The top position of the link container */ topOfLinkContainer: number /** Component to use for routing. We need this to be defined in each application using the LeftNav. */ routerComponent: LeftNavProps['routerComponent'] /** Prop to use for routing within the routerComponent. We need this to be defined in each application using the LeftNav. */ routerProp: LeftNavProps['routerProp'] /** Function to close the LeftNav */ close: () => void /** The index of the link segment to match */ linkSegmentIndexToMatch?: number } const LeftNavLink = ({ content, firstBreadcrumb, index, isExpanded, setActiveBarPosition, topOfLinkContainer, routerComponent: RouterComponent, routerProp, close, linkSegmentIndexToMatch, }: LeftNavLinkProps): React.JSX.Element => { const [active, setActive] = useState(false) const elRef = useRef(null) const isMobile = useIsMobileView() const headerHeight = isMobile ? 49 : 73 const linkPosition = elRef.current ? elRef.current.getBoundingClientRect().top - topOfLinkContainer : 0 const linkCallout = () => { elRef.current && setActiveBarPosition(linkPosition) close() } useEffect(() => { const checkLinkMatch = () => { if (content.exactLinkMatch) return firstBreadcrumb?.link === content.link if (linkSegmentIndexToMatch) { // Strip any search params from URLs before comparing const firstBreadcrumbPath = firstBreadcrumb?.link.split('?')[0] const contentPath = content.link.split('?')[0] const firstBreadcrumbSegments = firstBreadcrumbPath?.split('/') const contentSegments = contentPath.split('/') return ( firstBreadcrumbSegments?.[linkSegmentIndexToMatch] === contentSegments?.[linkSegmentIndexToMatch] ) } const firstBreadcrumbSegments = firstBreadcrumb?.link.split('/') const contentSegments = content.link.split('/') for (let i = 0; i < contentSegments?.length; i++) { if (firstBreadcrumbSegments?.[i] !== contentSegments?.[i]) { return false } } return true } if (checkLinkMatch()) { setActive(true) elRef.current && setActiveBarPosition(linkPosition) } else { setActive(false) } }, [ setActiveBarPosition, content.link, firstBreadcrumb?.link, index, content, linkPosition, headerHeight, linkSegmentIndexToMatch, ]) const getRouterComponentProps = () => { const link = content.link const genericProps = { className: `${styles.link} ${active ? styles.active : ''}`, onClick: linkCallout, [routerProp]: link, } return { ...genericProps, } } return (
{content.name}
) } export default LeftNavLink