import { useFrontmatter, useI18n, useLocation } from '@rspress/core/runtime'; import { IconArrowRight, IconMenu, ReadPercent, renderInlineMarkdown, SvgWrapper, useActiveAnchor, useDynamicToc, } from '@rspress/core/theme'; import { forwardRef, type ReactNode, useEffect, useRef } from 'react'; import { createPortal } from 'react-dom'; import './index.scss'; /* Top Menu, only displayed on <1280px screen width */ export const SidebarMenu = forwardRef( ( { isSidebarOpen, onIsSidebarOpenChange, isOutlineOpen, onIsOutlineOpenChange, beforeOutline, afterOutline, }: { isSidebarOpen: boolean; onIsSidebarOpenChange: (isOpen: boolean) => void; isOutlineOpen: boolean; onIsOutlineOpenChange: (isOpen: boolean) => void; beforeOutline?: ReactNode; afterOutline?: ReactNode; }, forwardedRef, ) => { const sidebarMenuRef = useRef(null); const t = useI18n(); const { pathname, hash } = useLocation(); const headers = useDynamicToc(); const { scrolledHeader } = useActiveAnchor(headers); const outlineDisabled = !beforeOutline && !afterOutline && headers.length === 0; const { frontmatter: { sidebar: sidebarConfig = true, outline: showOutline = true, }, } = useFrontmatter(); const showSidebar = sidebarConfig === true; function openSidebar() { onIsSidebarOpenChange(true); } function closeSidebar() { onIsSidebarOpenChange(false); } function openOutline() { onIsOutlineOpenChange(!isOutlineOpen); } function closeOutline() { onIsOutlineOpenChange(false); } useEffect(() => { closeSidebar(); }, [pathname]); useEffect(() => { if (hash) { closeOutline(); } }, [hash]); return ( <>
{ sidebarMenuRef.current = ref; if (typeof forwardedRef === 'function') { forwardedRef(sidebarMenuRef.current); } else if (forwardedRef) { forwardedRef.current = sidebarMenuRef.current; } }} > {showSidebar ? ( ) : (
)} {showOutline ? ( ) : (
)}
{(isSidebarOpen || isOutlineOpen) && createPortal(
, document.getElementById('__rspress_modal_container')!, )} ); }, );