d5d0e1036b
* docs: add docs * ignore dumi theme test * fix: error TS2717: Subsequent property declarations must have the same type. * update docs * deploy gh-pages * plugins docs * hash & cname * exportStatic * ssr * vercel * vercel * fix: deploy vercel * Delete vercel.json * docs * fix APP_DIST * on master branch
140 lines
4.5 KiB
TypeScript
Executable File
140 lines
4.5 KiB
TypeScript
Executable File
import type { FC} from 'react';
|
|
import React, { useContext } from 'react';
|
|
import { context, Link, NavLink } from 'dumi/theme';
|
|
import LocaleSelect from './LocaleSelect';
|
|
import SlugList from './SlugList';
|
|
import './SideMenu.less';
|
|
|
|
interface INavbarProps {
|
|
mobileMenuCollapsed: boolean;
|
|
location: any;
|
|
}
|
|
|
|
const SideMenu: FC<INavbarProps> = ({ mobileMenuCollapsed, location }) => {
|
|
const {
|
|
config: {
|
|
logo,
|
|
title,
|
|
description,
|
|
mode,
|
|
repository: { url: repoUrl },
|
|
},
|
|
menu,
|
|
nav: navItems,
|
|
base,
|
|
meta,
|
|
} = useContext(context);
|
|
const isHiddenMenus =
|
|
Boolean((meta.hero || meta.features || meta.gapless) && mode === 'site') ||
|
|
meta.sidemenu === false ||
|
|
undefined;
|
|
|
|
return (
|
|
<div
|
|
className="__dumi-default-menu"
|
|
data-mode={mode}
|
|
data-hidden={isHiddenMenus}
|
|
data-mobile-show={!mobileMenuCollapsed || undefined}
|
|
>
|
|
<div className="__dumi-default-menu-inner">
|
|
<div className="__dumi-default-menu-header">
|
|
<Link
|
|
to={base}
|
|
className="__dumi-default-menu-logo"
|
|
style={{
|
|
backgroundImage: logo && `url('${logo}')`,
|
|
}}
|
|
/>
|
|
<h1>{title}</h1>
|
|
<p>{description}</p>
|
|
{/* github star badge */}
|
|
{/github\.com/.test(repoUrl) && mode === 'doc' && (
|
|
<p>
|
|
<object
|
|
type="image/svg+xml"
|
|
data={`https://img.shields.io/github/stars${
|
|
repoUrl.match(/((\/[^\/]+){2})$/)[1]
|
|
}?style=social`}
|
|
/>
|
|
</p>
|
|
)}
|
|
</div>
|
|
{/* mobile nav list */}
|
|
{navItems.length ? (
|
|
<div className="__dumi-default-menu-mobile-area">
|
|
<ul className="__dumi-default-menu-nav-list">
|
|
{navItems.map(nav => {
|
|
const child = Boolean(nav.children?.length) && (
|
|
<ul>
|
|
{nav.children.map(item => (
|
|
<li key={item.path || item.title}>
|
|
<NavLink to={item.path}>{item.title}</NavLink>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
);
|
|
|
|
return (
|
|
<li key={nav.path || nav.title}>
|
|
{nav.path ? <NavLink to={nav.path}>{nav.title}</NavLink> : nav.title}
|
|
{child}
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
{/* site mode locale select */}
|
|
<LocaleSelect location={location} />
|
|
</div>
|
|
) : (
|
|
<div className="__dumi-default-menu-doc-locale">
|
|
{/* doc mode locale select */}
|
|
<LocaleSelect location={location} />
|
|
</div>
|
|
)}
|
|
{/* menu list */}
|
|
<ul className="__dumi-default-menu-list">
|
|
{!isHiddenMenus &&
|
|
menu.map(item => {
|
|
// always use meta from routes to reduce menu data size
|
|
const hasSlugs = Boolean(meta.slugs?.length);
|
|
const hasChildren = item.children && Boolean(item.children.length);
|
|
const show1LevelSlugs =
|
|
meta.toc === 'menu' && !hasChildren && hasSlugs && item.path === location.pathname.replace(/([^^])\/$/, '$1');
|
|
|
|
return (
|
|
<li key={item.path || item.title}>
|
|
<NavLink to={item.path} exact={!(item.children && item.children.length)}>
|
|
{item.title}
|
|
</NavLink>
|
|
{/* group children */}
|
|
{Boolean(item.children && item.children.length) && (
|
|
<ul>
|
|
{item.children.map(child => (
|
|
<li key={child.path}>
|
|
<NavLink to={child.path} exact>
|
|
<span>{child.title}</span>
|
|
</NavLink>
|
|
{/* group children slugs */}
|
|
{Boolean(
|
|
meta.toc === 'menu' &&
|
|
typeof window !== 'undefined' &&
|
|
child.path === location.pathname &&
|
|
hasSlugs,
|
|
) && <SlugList slugs={meta.slugs} />}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
{/* group slugs */}
|
|
{show1LevelSlugs && <SlugList slugs={meta.slugs} />}
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SideMenu;
|