import { useRouter } from 'next/router' import cx from 'classnames' import { useState, useEffect, SyntheticEvent, ReactElement } from 'react' import { ChevronDownIcon } from '@primer/octicons-react' import { ActionList } from '@primer/react' import { Link } from 'components/Link' import { ProductTreeNode } from 'components/context/MainContext' import { EventType, sendEvent } from 'components/lib/events' import { MiniTocItem, useRestContext } from 'components/context/RestContext' import styles from './SidebarProduct.module.scss' type SectionProps = { routePath: string page: ProductTreeNode title: string defaultOpen: boolean isStandaloneCategory: boolean } type ConditionalLinkTypes = { condition: boolean wrapper: Function children: ReactElement } export const RestCollapsibleSection = (props: SectionProps) => { const router = useRouter() const { routePath, defaultOpen, title, page, isStandaloneCategory } = props const [isOpen, setIsOpen] = useState(defaultOpen) const [currentAnchor, setCurrentAnchor] = useState('') const [visibleAnchor, setVisibleAnchor] = useState('') const onToggle = (e: SyntheticEvent) => { const newIsOpen = (e.target as HTMLDetailsElement).open setIsOpen(newIsOpen) sendEvent({ type: EventType.navigate, navigate_label: `details ${newIsOpen ? 'open' : 'close'}: ${title}`, }) } const miniTocItems = router.query.productId === 'rest' || // These pages need the Article Page mini tocs instead of the Rest Pages router.asPath.includes('/rest/guides') || router.asPath.includes('/rest/overview') ? [] : useRestContext().miniTocItems useEffect(() => { if (!currentAnchor) { setCurrentAnchor(window.location.hash) } const hashChangeHandler = () => { setCurrentAnchor(window.location.hash) } window.addEventListener('hashchange', hashChangeHandler) return () => { window.removeEventListener('hashchange', hashChangeHandler) } }, []) useEffect(() => { if (!router.asPath.includes('guides') && !router.asPath.includes('overview')) { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.target.id) { const anchor = '#' + entry.target.id.split('--')[0] if (entry.isIntersecting === true) setVisibleAnchor(anchor) } else if (router.asPath.includes('#')) { setVisibleAnchor('#' + router.asPath.split('#')[1]) } else { setVisibleAnchor('') } }) }, { rootMargin: '0px 0px -85% 0px' } ) // TODO: When we add the ## About the {title} API to each operation // we can remove the h2 here const headingsList = Array.from(document.querySelectorAll('h2, h3')) headingsList.forEach((heading) => { observer.observe(heading) }) return () => { observer.disconnect() } } }, [miniTocItems]) // This wrapper solves the issue of having standalone categories not // link to the new page. We want standalone categories to have links // just like maptopics/subcategories. const ConditionalLinkWrapper = ({ condition, wrapper, children }: ConditionalLinkTypes) => condition ? wrapper(children) : children const renderRestAnchorLink = (miniTocItem: MiniTocItem) => { const miniTocAnchor = miniTocItem.contents.href const title = miniTocItem.contents.title const isCurrent = visibleAnchor === miniTocAnchor return { text: title, renderItem: () => ( setVisibleAnchor(miniTocAnchor)} href={miniTocAnchor} > {title} ), } } return (
( {children} )} >
{title}
{ <> {/* */} }
) }