import { css } from '@emotion/react'; import { theme } from '@expo/styleguide'; import { breakpoints } from '@expo/styleguide-base'; import { useRouter } from 'next/compat/router'; import { useEffect, useState, createRef } from 'react'; import * as RoutesUtils from '~/common/routes'; import * as Utilities from '~/common/utilities'; import * as WindowUtils from '~/common/window'; import DocumentationNestedScrollLayout from '~/components/DocumentationNestedScrollLayout'; import DocumentationSidebarRight, { SidebarRightComponentType, } from '~/components/DocumentationSidebarRight'; import Head from '~/components/Head'; import { usePageApiVersion } from '~/providers/page-api-version'; import { Footer } from '~/ui/components/Footer'; import { Header } from '~/ui/components/Header'; import { PageTitle } from '~/ui/components/PageTitle'; import { Separator } from '~/ui/components/Separator'; import { Sidebar } from '~/ui/components/Sidebar'; import { P } from '~/ui/components/Text'; const STYLES_DOCUMENT = css` background: ${theme.background.default}; margin: 0 auto; padding: 40px 56px; @media screen and (max-width: ${breakpoints.medium + 124}px) { padding: 20px 16px 48px 16px; } `; type Props = React.PropsWithChildren<{ title?: string; description?: string; sourceCodeUrl?: string; tocVisible: boolean; packageName?: string; iconUrl?: string; /** If the page should not show up in the Algolia Docsearch results */ hideFromSearch?: boolean; }>; const getCanonicalUrl = (path: string) => { if (RoutesUtils.isReferencePath(path)) { return `https://docs.expo.dev${Utilities.replaceVersionInUrl(path, 'latest')}`; } else { return `https://docs.expo.dev${path}`; } }; export default function DocumentationPage(props: Props) { const { version } = usePageApiVersion(); const router = useRouter(); const pathname = router?.pathname ?? '/'; const layoutRef = createRef(); const sidebarRightRef = createRef(); const [isMobileMenuVisible, setMobileMenuVisible] = useState(false); const routes = RoutesUtils.getRoutes(pathname, version); const sidebarActiveGroup = RoutesUtils.getPageSection(pathname); const sidebarScrollPosition = process.browser ? window.__sidebarScroll : 0; useEffect(() => { router?.events.on('routeChangeStart', url => { if (layoutRef.current) { if ( RoutesUtils.getPageSection(pathname) !== RoutesUtils.getPageSection(url) || pathname === '/' ) { window.__sidebarScroll = 0; } else { window.__sidebarScroll = layoutRef.current.getSidebarScrollTop(); } } }); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }); const handleResize = () => { if (WindowUtils.getViewportSize().width >= breakpoints.medium + 124) { setMobileMenuVisible(false); window.scrollTo(0, 0); } }; const handleContentScroll = (contentScrollPosition: number) => { window.requestAnimationFrame(() => { if (sidebarRightRef && sidebarRightRef.current) { sidebarRightRef.current.handleContentScroll(contentScrollPosition); } }); }; const sidebarElement = ; const sidebarRightElement = ; const headerElement = (
setMobileMenuVisible(newState)} /> ); return ( {props.hideFromSearch !== true && ( )} {(version === 'unversioned' || RoutesUtils.isPreviewPath(pathname) || RoutesUtils.isArchivePath(pathname)) && } {version !== 'latest' && version !== 'unversioned' && ( )}
{props.title && ( )} {props.description && (

{props.description}

)} {props.title && } {props.children} {props.title && (
); }