blob: 07b75b03cfadaa9b6a4eab95959379c3e5b9672f [file] [log] [blame]
import React, { useEffect, createContext, useState, useRef, JSX } from 'react';
import { useLocation } from '@docusaurus/router';
import clsx from 'clsx';
import ErrorBoundary from '@docusaurus/ErrorBoundary';
import { PageMetadata, SkipToContentFallbackId, ThemeClassNames } from '@docusaurus/theme-common';
import { useKeyboardNavigation } from '@docusaurus/theme-common/internal';
import SkipToContent from '@theme/SkipToContent';
import AnnouncementBar from '@theme/AnnouncementBar';
import Navbar from '@theme/Navbar';
import Footer from '@theme/Footer';
import LayoutProvider from '@theme/Layout/Provider';
import ErrorPageContent from '@theme/ErrorPageContent';
import NavbarSearch from '../Navbar/Search';
import SearchBar from '@theme/SearchBar';
import type { Props } from '@theme/Layout';
import styles from './styles.module.css';
import { useHistory } from '@docusaurus/router';
interface DataType {
showSearchPageMobile: boolean;
setShowSearchPageMobile: React.Dispatch<React.SetStateAction<boolean>>;
}
export const DataContext = createContext<DataType>(null);
export default function Layout(props: Props): JSX.Element {
const {
children,
noFooter,
wrapperClassName,
// Not really layout-related, but kept for convenience/retro-compatibility
title,
description,
} = props;
const history = useHistory();
const [showSearchPageMobile, setShowSearchPageMobile] = useState(false);
const searchPageDom = useRef<HTMLDivElement>(null);
const { hash } = useLocation();
useKeyboardNavigation();
useEffect(() => {
if (
history.location.pathname?.length > 1 &&
history.location.pathname[history.location.pathname.length - 1] === '/'
) {
const params = location.href.split(history.location.pathname)[1];
history.replace(history.location.pathname.slice(0, -1) + params);
}
}, [history.location]);
useEffect(() => {
if (showSearchPageMobile) {
window.scroll(0, 0);
document.body.style.overflow = 'hidden';
searchPageDom.current.style.height = '100vh';
} else {
window.scroll(0, 0);
document.body.style.overflow = 'auto';
}
}, [showSearchPageMobile]);
useEffect(() => {
if (hash) {
try {
const decodeHash = decodeURIComponent(hash);
const targetElement = document.querySelector(decodeHash);
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth' });
}
} catch (err) {
console.error(err);
}
}
}, [hash]);
return (
<DataContext.Provider value={{ showSearchPageMobile, setShowSearchPageMobile }}>
<LayoutProvider>
<PageMetadata title={title} description={description} />
<SkipToContent />
<AnnouncementBar />
<Navbar />
{showSearchPageMobile ? (
<div ref={searchPageDom}>
<NavbarSearch>
<SearchBar />
</NavbarSearch>
</div>
) : null}
<div
id={SkipToContentFallbackId}
className={clsx(ThemeClassNames.wrapper.main, styles.mainWrapper, wrapperClassName)}
>
<ErrorBoundary fallback={params => <ErrorPageContent {...params} />}>{children}</ErrorBoundary>
</div>
{!noFooter && <Footer />}
</LayoutProvider>
</DataContext.Provider>
);
}