完善 docs

This commit is contained in:
SmallMain
2022-06-01 14:40:10 +08:00
parent 113677baf9
commit 69fba27b50
40 changed files with 911 additions and 206 deletions

View File

@@ -15,6 +15,7 @@
--ifm-color-primary-lightest: #7b59c3;
--ifm-code-font-size: 90%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
--ifm-h1-font-size: 2.5rem;
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
@@ -31,12 +32,46 @@
@media screen and (max-width: 996px) {
:root {
--ifm-font-size-base: 15px;
--ifm-font-size-base: 16px;
}
}
@media screen and (min-width: 997px) {
:root {
--ifm-font-size-base: 15px;
--ifm-font-size-base: 18px;
}
}
html[data-theme=light] .navbar__item.header-github-link {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMy42MDEgMGExMy41OTcgMTMuNTk3IDAgMCAwLTQuMjk4IDI2LjQ5OGMuNjc2LjEyNi45MjgtLjI5NS45MjgtLjY1NSAwLS4zMjUtLjAxMS0xLjM5NC0uMDE4LTIuNTMxLTMuNzgzLjgyMi00LjU4LTEuNjAzLTQuNTgtMS42MDMtLjYxOS0xLjU3Ni0xLjUxLTEuOTktMS41MS0xLjk5LTEuMjM0LS44NDUuMDkyLS44MjcuMDkyLS44MjcgMS4zNjYuMDk3IDIuMDg1IDEuNCAyLjA4NSAxLjQgMS4yMTMgMi4wNzkgMy4xODEgMS40OCAzLjk1NiAxLjEyNi4xMjMtLjg3OC40NzUtMS40NzcuODY0LTEuODE3LTMuMDEtLjM0LTYuMTk2LTEuNTA2LTYuMTk2LTYuNzE2YTUuMjU3IDUuMjU3IDAgMCAxIDEuNDAzLTMuNjU0Yy0uMTQyLS4zNDItLjYwOC0xLjcyNS4xMy0zLjYwMiAwIDAgMS4xNDItLjM2NSAzLjc0IDEuMzkzYTEyLjkyIDEyLjkyIDAgMCAxIDYuODEgMGMyLjU4NS0xLjc0OSAzLjczNi0xLjM5MyAzLjczNi0xLjM5My43MzkgMS44NzMuMjc1IDMuMjU1LjEzMyAzLjYwMmE1LjI1NSA1LjI1NSAwIDAgMSAxLjM5OCAzLjY1YzAgNS4yMjMtMy4xOCA2LjM3MS02LjIwNyA2LjcxLjQ4Ni40Mi45MiAxLjI0OS45MiAyLjUxNiAwIDEuODItLjAxMyAzLjI4NS0uMDEzIDMuNzMxIDAgLjM2My4yNDMuNzg2LjkzMi42NTNBMTMuNTk2IDEzLjU5NiAwIDAgMCAxMy42MDEgMHoiIGZpbGw9IiMyMTIyMkMiLz48cGF0aCBkPSJNNS4xNTQgMTkuNTJjLS4wMy4wNjgtLjEzNS4wODgtLjIyNS4wNDNzLS4xNTYtLjEzNy0uMTI0LS4yMDVjLjAzMS0uMDY3LjEzNy0uMDg3LjIyNS0uMDQyLjA4OC4wNDUuMTU1LjEzNy4xMjIuMjA0aC4wMDJ6bS41NTEuNjE1Yy0uMDY1LjA2LS4xOTEuMDMyLS4yNzktLjA2M2EuMjA3LjIwNyAwIDAgMS0uMDM4LS4yODFjLjA2Ny0uMDYxLjE4OS0uMDMyLjI3OS4wNjMuMDkuMDk0LjEwNi4yMjUuMDM4LjI4MXptLjUzNi43ODNjLS4wODMuMDU5LS4yMjUgMC0uMzA0LS4xMTctLjA3OS0uMTE3LS4wODMtLjI2NSAwLS4zMjQuMDg0LS4wNTguMjI1IDAgLjMwNC4xMTUuMDc5LjExNS4wODQuMjY4IDAgLjMyNnptLjc0My43NTdhLjI1NS4yNTUgMCAwIDEtLjM1OC0uMDZjLS4xMi0uMTExLS4xNTMtLjI2Ni0uMDc2LS4zNDguMDc2LS4wOC4yMjUtLjA2LjM1LjA1Mi4xMjcuMTEzLjE1NC4yNjYuMDc1LjM0N2wuMDEuMDA5em0xLjAwNC40MzljLS4wMzMuMTA2LS4xODQuMTU1LS4zNC4xMS0uMTU1LS4wNDUtLjI1NC0uMTctLjIyNS0uMjc5LjAzLS4xMDguMTg1LS4xNTcuMzQtLjExLjE1Ni4wNDcuMjU1LjE3LjIyNS4yNzl6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTkuMSAyMi4xOTVjMCAuMTEzLS4xMjYuMjA1LS4yODguMjA3LS4xNjIuMDAyLS4yOTItLjA4NS0uMjk1LS4xOTgtLjAwMi0uMTEzLjEyNi0uMjA1LjI5LS4yMDcuMTY1LS4wMDIuMjkzLjA4OC4yOTMuMTk4em0xLjAzNi0uMTc1Yy4wMi4xMS0uMDkyLjIyNS0uMjUyLjI1Mi0uMTYuMDI3LS4zMDQtLjAzOS0uMzI0LS4xNDktLjAyLS4xMS4wOTQtLjIyNS4yNTItLjI1Mi4xNTgtLjAyNy4zMDQuMDM4LjMyNC4xNDh6IiBmaWxsPSIjMUUxRjI3Ii8+PC9zdmc+) 0/20px 20px no-repeat;
}
.navbar__item.header-github-link {
padding-left: 1.6rem;
padding-bottom: 0.2rem;
margin-left: 0.6rem;
margin-right: -1rem;
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMy42MDEgMGExMy41OTcgMTMuNTk3IDAgMCAwLTQuMjk4IDI2LjQ5OGMuNjc2LjEyNi45MjgtLjI5NS45MjgtLjY1NSAwLS4zMjUtLjAxMS0xLjM5NC0uMDE4LTIuNTMxLTMuNzgzLjgyMi00LjU4LTEuNjAzLTQuNTgtMS42MDMtLjYxOS0xLjU3Ni0xLjUxLTEuOTktMS41MS0xLjk5LTEuMjM0LS44NDUuMDkyLS44MjcuMDkyLS44MjcgMS4zNjYuMDk3IDIuMDg1IDEuNCAyLjA4NSAxLjQgMS4yMTMgMi4wNzkgMy4xODEgMS40OCAzLjk1NiAxLjEyNi4xMjMtLjg3OC40NzUtMS40NzcuODY0LTEuODE3LTMuMDEtLjM0LTYuMTk2LTEuNTA2LTYuMTk2LTYuNzE2YTUuMjU3IDUuMjU3IDAgMCAxIDEuNDAzLTMuNjU0Yy0uMTQyLS4zNDItLjYwOC0xLjcyNS4xMy0zLjYwMiAwIDAgMS4xNDItLjM2NSAzLjc0IDEuMzkzYTEyLjkyIDEyLjkyIDAgMCAxIDYuODEgMGMyLjU4NS0xLjc0OSAzLjczNi0xLjM5MyAzLjczNi0xLjM5My43MzkgMS44NzMuMjc1IDMuMjU1LjEzMyAzLjYwMmE1LjI1NSA1LjI1NSAwIDAgMSAxLjM5OCAzLjY1YzAgNS4yMjMtMy4xOCA2LjM3MS02LjIwNyA2LjcxLjQ4Ni40Mi45MiAxLjI0OS45MiAyLjUxNiAwIDEuODItLjAxMyAzLjI4NS0uMDEzIDMuNzMxIDAgLjM2My4yNDMuNzg2LjkzMi42NTNBMTMuNTk2IDEzLjU5NiAwIDAgMCAxMy42MDEgMHoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJNNS4xNTQgMTkuNTJjLS4wMy4wNjgtLjEzNS4wODgtLjIyNS4wNDNzLS4xNTYtLjEzNy0uMTI0LS4yMDVjLjAzMS0uMDY3LjEzNy0uMDg3LjIyNS0uMDQyLjA4OC4wNDUuMTU1LjEzNy4xMjIuMjA0aC4wMDJ6bS41NTEuNjE1Yy0uMDY1LjA2LS4xOTEuMDMyLS4yNzktLjA2M2EuMjA3LjIwNyAwIDAgMS0uMDM4LS4yODFjLjA2Ny0uMDYxLjE4OS0uMDMyLjI3OS4wNjMuMDkuMDk0LjEwNi4yMjUuMDM4LjI4MXptLjUzNi43ODNjLS4wODMuMDU5LS4yMjUgMC0uMzA0LS4xMTctLjA3OS0uMTE3LS4wODMtLjI2NSAwLS4zMjQuMDg0LS4wNTguMjI1IDAgLjMwNC4xMTUuMDc5LjExNS4wODQuMjY4IDAgLjMyNnptLjc0My43NTdhLjI1NS4yNTUgMCAwIDEtLjM1OC0uMDZjLS4xMi0uMTExLS4xNTMtLjI2Ni0uMDc2LS4zNDguMDc2LS4wOC4yMjUtLjA2LjM1LjA1Mi4xMjcuMTEzLjE1NC4yNjYuMDc1LjM0N2wuMDEuMDA5em0xLjAwNC40MzljLS4wMzMuMTA2LS4xODQuMTU1LS4zNC4xMS0uMTU1LS4wNDUtLjI1NC0uMTctLjIyNS0uMjc5LjAzLS4xMDguMTg1LS4xNTcuMzQtLjExLjE1Ni4wNDcuMjU1LjE3LjIyNS4yNzl6bTEuMTEyLjA4MWMwIC4xMTMtLjEyNi4yMDUtLjI4OC4yMDctLjE2Mi4wMDItLjI5Mi0uMDg1LS4yOTUtLjE5OC0uMDAyLS4xMTMuMTI2LS4yMDUuMjktLjIwNy4xNjUtLjAwMi4yOTMuMDg4LjI5My4xOTh6bTEuMDM2LS4xNzVjLjAyLjExLS4wOTIuMjI1LS4yNTIuMjUyLS4xNi4wMjctLjMwNC0uMDM5LS4zMjQtLjE0OS0uMDItLjExLjA5NC0uMjI1LjI1Mi0uMjUyLjE1OC0uMDI3LjMwNC4wMzguMzI0LjE0OHoiIGZpbGw9IiNmZmYiLz48L3N2Zz4=) 0/20px 20px no-repeat;
}
.hero__subtitle {
margin-top: 2rem;
}
.hero__title {
font-size: 4rem;
}
@media screen and (max-width: 996px) {
.banner-img {
display: none;
}
}
.markdown h1:first-child {
--ifm-h1-font-size: 2.5rem;
}
.title_node_modules-\@docusaurus-theme-classic-lib-next-theme-DocCategoryGeneratedIndexPage-styles-module {
--ifm-h1-font-size: 2.5rem !important;
}

View File

@@ -5,7 +5,7 @@
.heroBanner {
padding: 4rem 0;
text-align: center;
/* text-align: center; */
position: relative;
overflow: hidden;
}
@@ -19,5 +19,6 @@
.buttons {
display: flex;
align-items: center;
justify-content: center;
margin-top: 60px;
/* justify-content: center; */
}

View File

@@ -5,20 +5,59 @@ import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './index.module.css';
import HomepageFeatures from '@site/src/components/HomepageFeatures';
import Rocket from '../../static/img/rocket.svg';
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
const { siteConfig } = useDocusaurusContext();
return (
<header className={clsx('hero', styles.heroBanner)}>
//
<header className={clsx('hero', styles.heroBanner)} style={{ height: window.innerHeight - 100 }}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/intro">
Docusaurus Tutorial - 5min
</Link>
<div className="row">
<div className="col col--8">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline + ""}</p>
<div>
<p style={{ color: 'var(--ifm-color-primary)', fontWeight: 'bold', marginBottom: 2 }}>
<span className="badge badge--primary" style={{ marginRight: 8 }}>2D </span>
</p>
<p style={{ color: 'var(--ifm-color-primary)', fontWeight: 'bold', marginBottom: 2 }}>
<span className="badge badge--primary" style={{ marginRight: 8 }}></span>
</p>
<p style={{ color: 'var(--ifm-color-primary)', fontWeight: 'bold', marginBottom: 2 }}>
<span className="badge badge--primary" style={{ marginRight: 8 }}>Label </span>
DPI BITMAP CHAR
</p>
<p style={{ color: 'var(--ifm-color-primary)', fontWeight: 'bold', marginBottom: 2 }}>
<span className="badge badge--primary" style={{ marginRight: 8 }}>RichText </span>
使
</p>
<p style={{ color: 'var(--ifm-color-primary)', fontWeight: 'bold', marginBottom: 2 }}>
<span className="badge badge--primary" style={{ marginRight: 8 }}>Spine </span>
Region
</p>
</div>
<div className={styles.buttons}>
<Link
className="button button--primary button--lg"
to="/docs/intro"
style={{ marginRight: 20 }}
>
使
</Link>
<Link
className="button button--secondary button--lg"
href='https://github.com/smallmain/cocos-service-pack'>
<svg style={{ marginRight: 8, marginBottom: -4 }} stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 496 512" className="GithubIcon_3htU" height="1.2em" width="1.2em" xmlns="http://www.w3.org/2000/svg"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg>
GitHub
</Link>
</div>
</div>
<div className="col col--4">
<Rocket width={'30rem'} height={'26rem'} className='banner-img' />
</div>
</div>
</div>
</header>
@@ -26,7 +65,7 @@ function HomepageHeader() {
}
export default function Home(): JSX.Element {
const {siteConfig} = useDocusaurusContext();
const { siteConfig } = useDocusaurusContext();
return (
<Layout
// title={`${siteConfig.title}`}

View File

@@ -0,0 +1,27 @@
import React from 'react';
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import isInternalUrl from '@docusaurus/isInternalUrl';
import IconExternalLink from '@theme/IconExternalLink';
export default function FooterLinkItem({item}) {
const {to, href, label, prependBaseUrlToHref, ...props} = item;
const toUrl = useBaseUrl(to);
const normalizedHref = useBaseUrl(href, {
forcePrependBaseUrl: true,
});
return (
<Link
className="footer__link-item"
{...(href
? {
href: prependBaseUrlToHref ? normalizedHref : href,
}
: {
to: toUrl,
})}
{...props}>
{label}
{/* {href && !isInternalUrl(href) && <IconExternalLink />} */}
</Link>
);
}

View File

@@ -0,0 +1,26 @@
import React from 'react';
import {useThemeConfig} from '@docusaurus/theme-common';
import FooterLinks from '@theme/Footer/Links';
import FooterLogo from '@theme/Footer/Logo';
import FooterCopyright from '@theme/Footer/Copyright';
import FooterLayout from '@theme/Footer/Layout';
function Footer() {
const {footer} = useThemeConfig();
if (!footer) {
return null;
}
const {copyright, links, logo, style} = footer;
return (
<FooterLayout
style={style}
links={links && links.length > 0 && <FooterLinks links={links} />}
logo={logo && <FooterLogo logo={logo} />}
copyright={copyright && <FooterCopyright copyright={copyright} />}
/>
);
}
export default React.memo(Footer);

View File

@@ -0,0 +1,21 @@
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
import LocaleDropdownNavbarItem from '@theme/NavbarItem/LocaleDropdownNavbarItem';
import SearchNavbarItem from '@theme/NavbarItem/SearchNavbarItem';
import HtmlNavbarItem from '@theme/NavbarItem/HtmlNavbarItem';
import DocNavbarItem from '@theme/NavbarItem/DocNavbarItem';
import DocSidebarNavbarItem from '@theme/NavbarItem/DocSidebarNavbarItem';
import DocsVersionNavbarItem from '@theme/NavbarItem/DocsVersionNavbarItem';
import DocsVersionDropdownNavbarItem from '@theme/NavbarItem/DocsVersionDropdownNavbarItem';
const ComponentTypes = {
default: DefaultNavbarItem,
localeDropdown: LocaleDropdownNavbarItem,
search: SearchNavbarItem,
dropdown: DropdownNavbarItem,
html: HtmlNavbarItem,
doc: DocNavbarItem,
docSidebar: DocSidebarNavbarItem,
docsVersion: DocsVersionNavbarItem,
docsVersionDropdown: DocsVersionDropdownNavbarItem,
};
export default ComponentTypes;

View File

@@ -0,0 +1,51 @@
import React from 'react';
import clsx from 'clsx';
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
import {getInfimaActiveClassName} from '@theme/NavbarItem/utils';
function DefaultNavbarItemDesktop({
className,
isDropdownItem = false,
...props
}) {
const element = (
<NavbarNavLink
className={clsx(
isDropdownItem ? 'dropdown__link' : 'navbar__item navbar__link',
className,
)}
{...props}
/>
);
if (isDropdownItem) {
return <li>{element}</li>;
}
return element;
}
function DefaultNavbarItemMobile({className, isDropdownItem, ...props}) {
return (
<li className="menu__list-item">
<NavbarNavLink className={clsx('menu__link', className)} {...props} />
</li>
);
}
export default function DefaultNavbarItem({
mobile = false,
position,
// Need to destructure position from props so that it doesn't get passed on.
...props
}) {
const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop;
return (
<Comp
{...props}
activeClassName={
props.activeClassName ?? getInfimaActiveClassName(mobile)
}
/>
);
}

View File

@@ -0,0 +1,37 @@
import React from 'react';
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
import {useActiveDocContext} from '@docusaurus/plugin-content-docs/client';
import clsx from 'clsx';
import {getInfimaActiveClassName} from '@theme/NavbarItem/utils';
import {useLayoutDoc} from '@docusaurus/theme-common';
export default function DocNavbarItem({
docId,
label: staticLabel,
docsPluginId,
...props
}) {
const {activeDoc} = useActiveDocContext(docsPluginId);
const doc = useLayoutDoc(docId, docsPluginId); // Draft items are not displayed in the navbar.
if (doc === null) {
return null;
}
const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile);
return (
<DefaultNavbarItem
exact
{...props}
className={clsx(props.className, {
// Do not make the item active if the active doc doesn't have sidebar.
[activeDocInfimaClassName]:
// If `activeDoc === doc` react-router will make it active anyways,
// regardless of the existence of a sidebar
activeDoc?.sidebar && activeDoc.sidebar === doc.sidebar,
})}
activeClassName={activeDocInfimaClassName}
label={staticLabel ?? doc.id}
to={doc.path}
/>
);
}

View File

@@ -0,0 +1,35 @@
import React from 'react';
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
import {useActiveDocContext} from '@docusaurus/plugin-content-docs/client';
import clsx from 'clsx';
import {getInfimaActiveClassName} from '@theme/NavbarItem/utils';
import {useLayoutDocsSidebar} from '@docusaurus/theme-common';
export default function DocSidebarNavbarItem({
sidebarId,
label,
docsPluginId,
...props
}) {
const {activeDoc} = useActiveDocContext(docsPluginId);
const sidebarLink = useLayoutDocsSidebar(sidebarId, docsPluginId).link;
if (!sidebarLink) {
throw new Error(
`DocSidebarNavbarItem: Sidebar with ID "${sidebarId}" doesn't have anything to be linked to.`,
);
}
const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile);
return (
<DefaultNavbarItem
exact
{...props}
className={clsx(props.className, {
[activeDocInfimaClassName]: activeDoc?.sidebar === sidebarId,
})}
activeClassName={activeDocInfimaClassName}
label={label ?? sidebarLink.label}
to={sidebarLink.path}
/>
);
}

View File

@@ -0,0 +1,87 @@
import React from 'react';
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
import {
useVersions,
useActiveDocContext,
} from '@docusaurus/plugin-content-docs/client';
import {
useDocsPreferredVersion,
useDocsVersionCandidates,
} from '@docusaurus/theme-common';
import {translate} from '@docusaurus/Translate';
const getVersionMainDoc = (version) =>
version.docs.find((doc) => doc.id === version.mainDocId);
export default function DocsVersionDropdownNavbarItem({
mobile,
docsPluginId,
dropdownActiveClassDisabled,
dropdownItemsBefore,
dropdownItemsAfter,
...props
}) {
const activeDocContext = useActiveDocContext(docsPluginId);
const versions = useVersions(docsPluginId);
const {savePreferredVersionName} = useDocsPreferredVersion(docsPluginId);
const versionLinks = versions.map((version) => {
// We try to link to the same doc, in another version
// When not possible, fallback to the "main doc" of the version
const versionDoc =
activeDocContext?.alternateDocVersions[version.name] ??
getVersionMainDoc(version);
return {
isNavLink: true,
label: version.label,
to: versionDoc.path,
isActive: () => version === activeDocContext?.activeVersion,
onClick: () => savePreferredVersionName(version.name),
};
});
const items = [
...dropdownItemsBefore,
...versionLinks,
...dropdownItemsAfter,
];
const dropdownVersion = useDocsVersionCandidates(docsPluginId)[0]; // Mobile dropdown is handled a bit differently
const dropdownLabel =
mobile && items.length > 1
? translate({
id: 'theme.navbar.mobileVersionsDropdown.label',
message: 'Versions',
description:
'The label for the navbar versions dropdown on mobile view',
})
: dropdownVersion.label;
const dropdownTo =
mobile && items.length > 1
? undefined
: getVersionMainDoc(dropdownVersion).path; // We don't want to render a version dropdown with 0 or 1 item. If we build
// the site with a single docs version (onlyIncludeVersions: ['1.0.0']),
// We'd rather render a button instead of a dropdown
if (items.length <= 1) {
return (
<DefaultNavbarItem
{...props}
mobile={mobile}
label={dropdownLabel}
to={dropdownTo}
isActive={dropdownActiveClassDisabled ? () => false : undefined}
/>
);
}
return (
<DropdownNavbarItem
{...props}
mobile={mobile}
label={dropdownLabel}
to={dropdownTo}
items={items}
isActive={dropdownActiveClassDisabled ? () => false : undefined}
/>
);
}

View File

@@ -0,0 +1,18 @@
import React from 'react';
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
import {useDocsVersionCandidates} from '@docusaurus/theme-common';
const getVersionMainDoc = (version) =>
version.docs.find((doc) => doc.id === version.mainDocId);
export default function DocsVersionNavbarItem({
label: staticLabel,
to: staticTo,
docsPluginId,
...props
}) {
const version = useDocsVersionCandidates(docsPluginId)[0];
const label = staticLabel ?? version.label;
const path = staticTo ?? getVersionMainDoc(version).path;
return <DefaultNavbarItem {...props} label={label} to={path} />;
}

View File

@@ -0,0 +1,161 @@
import React, {useState, useRef, useEffect} from 'react';
import clsx from 'clsx';
import {
isSamePath,
useCollapsible,
Collapsible,
isRegexpStringMatch,
useLocalPathname,
} from '@docusaurus/theme-common';
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
import NavbarItem from '@theme/NavbarItem';
const dropdownLinkActiveClass = 'dropdown__link--active';
function isItemActive(item, localPathname) {
if (isSamePath(item.to, localPathname)) {
return true;
}
if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) {
return true;
}
if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) {
return true;
}
return false;
}
function containsActiveItems(items, localPathname) {
return items.some((item) => isItemActive(item, localPathname));
}
function DropdownNavbarItemDesktop({items, position, className, ...props}) {
const dropdownRef = useRef(null);
const [showDropdown, setShowDropdown] = useState(false);
useEffect(() => {
const handleClickOutside = (event) => {
if (!dropdownRef.current || dropdownRef.current.contains(event.target)) {
return;
}
setShowDropdown(false);
};
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('touchstart', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('touchstart', handleClickOutside);
};
}, [dropdownRef]);
return (
<div
ref={dropdownRef}
className={clsx('navbar__item', 'dropdown', 'dropdown--hoverable', {
'dropdown--right': position === 'right',
'dropdown--show': showDropdown,
})}>
<NavbarNavLink
aria-haspopup="true"
aria-expanded={showDropdown}
role="button"
href={props.to ? undefined : '#'}
className={clsx('navbar__link', className)}
{...props}
onClick={props.to ? undefined : (e) => e.preventDefault()}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
setShowDropdown(!showDropdown);
}
}}>
{props.children ?? props.label}
</NavbarNavLink>
<ul className="dropdown__menu">
{items.map((childItemProps, i) => (
<NavbarItem
isDropdownItem
onKeyDown={(e) => {
if (i === items.length - 1 && e.key === 'Tab') {
e.preventDefault();
setShowDropdown(false);
const nextNavbarItem = dropdownRef.current.nextElementSibling;
if (nextNavbarItem) {
const targetItem =
nextNavbarItem instanceof HTMLAnchorElement
? nextNavbarItem // Next item is another dropdown; focus on the inner
: // anchor element instead so there's outline
nextNavbarItem.querySelector('a');
targetItem.focus();
}
}
}}
activeClassName={dropdownLinkActiveClass}
{...childItemProps}
key={i}
/>
))}
</ul>
</div>
);
}
function DropdownNavbarItemMobile({
items,
className,
position,
// Need to destructure position from props so that it doesn't get passed on.
...props
}) {
const localPathname = useLocalPathname();
const containsActive = containsActiveItems(items, localPathname);
const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({
initialState: () => !containsActive,
}); // Expand/collapse if any item active after a navigation
useEffect(() => {
if (containsActive) {
setCollapsed(!containsActive);
}
}, [localPathname, containsActive, setCollapsed]);
return (
<li
className={clsx('menu__list-item', {
'menu__list-item--collapsed': collapsed,
})}>
<NavbarNavLink
role="button"
className={clsx(
'menu__link menu__link--sublist menu__link--sublist-caret',
className,
)}
{...props}
onClick={(e) => {
e.preventDefault();
toggleCollapsed();
}}>
{props.children ?? props.label}
</NavbarNavLink>
<Collapsible lazy as="ul" className="menu__list" collapsed={collapsed}>
{items.map((childItemProps, i) => (
<NavbarItem
mobile
isDropdownItem
onClick={props.onClick}
activeClassName="menu__link--active"
{...childItemProps}
key={i}
/>
))}
</Collapsible>
</li>
);
}
export default function DropdownNavbarItem({mobile = false, ...props}) {
const Comp = mobile ? DropdownNavbarItemMobile : DropdownNavbarItemDesktop;
return <Comp {...props} />;
}

View File

@@ -0,0 +1,24 @@
import React from 'react';
import clsx from 'clsx';
export default function HtmlNavbarItem({
value,
className,
mobile = false,
isDropdownItem = false,
}) {
const Comp = isDropdownItem ? 'li' : 'div';
return (
<Comp
className={clsx(
{
navbar__item: !mobile && !isDropdownItem,
'menu__list-item': mobile,
},
className,
)}
dangerouslySetInnerHTML={{
__html: value,
}}
/>
);
}

View File

@@ -0,0 +1,69 @@
import React from 'react';
import Link from '@docusaurus/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';
import isInternalUrl from '@docusaurus/isInternalUrl';
import {isRegexpStringMatch} from '@docusaurus/theme-common';
const dropdownLinkActiveClass = 'dropdown__link--active';
export default function NavbarNavLink({
activeBasePath,
activeBaseRegex,
to,
href,
label,
html,
activeClassName = '',
prependBaseUrlToHref,
...props
}) {
// TODO all this seems hacky
// {to: 'version'} should probably be forbidden, in favor of {to: '/version'}
const toUrl = useBaseUrl(to);
const activeBaseUrl = useBaseUrl(activeBasePath);
const normalizedHref = useBaseUrl(href, {
forcePrependBaseUrl: true,
});
const isExternalLink = label && href && !isInternalUrl(href);
const isDropdownLink = activeClassName === dropdownLinkActiveClass; // Link content is set through html XOR label
const linkContentProps = html
? {
dangerouslySetInnerHTML: {
__html: html,
},
}
: {
children: (
<>
{label}
</>
),
};
if (href) {
return (
<Link
href={prependBaseUrlToHref ? normalizedHref : href}
{...props}
{...linkContentProps}
/>
);
}
return (
<Link
to={toUrl}
isNavLink
activeClassName={
!props.className?.includes(activeClassName) ? activeClassName : ''
}
{...((activeBasePath || activeBaseRegex) && {
isActive: (_match, location) =>
activeBaseRegex
? isRegexpStringMatch(activeBaseRegex, location.pathname)
: location.pathname.startsWith(activeBaseUrl),
})}
{...props}
{...linkContentProps}
/>
);
}

View File

@@ -0,0 +1,14 @@
import React from 'react';
import SearchBar from '@theme/SearchBar';
import NavbarSearch from '@theme/Navbar/Search';
export default function SearchNavbarItem({mobile}) {
if (mobile) {
return null;
}
return (
<NavbarSearch>
<SearchBar />
</NavbarSearch>
);
}

View File

@@ -0,0 +1,28 @@
import React from 'react';
import ComponentTypes from '@theme/NavbarItem/ComponentTypes';
const getNavbarItemComponent = (type) => {
const component = ComponentTypes[type];
if (!component) {
throw new Error(`No NavbarItem component found for type "${type}".`);
}
return component;
};
function getComponentType(type, isDropdown) {
// Backward compatibility: navbar item with no type set
// but containing dropdown items should use the type "dropdown"
if (!type || type === 'default') {
return isDropdown ? 'dropdown' : 'default';
}
return type;
}
export default function NavbarItem({type, ...props}) {
const componentType = getComponentType(type, props.items !== undefined);
const NavbarItemComponent = getNavbarItemComponent(componentType);
return <NavbarItemComponent {...props} />;
}

View File

@@ -0,0 +1,3 @@
/* eslint-disable import/no-named-export */
export const getInfimaActiveClassName = (mobile) =>
mobile ? 'menu__link--active' : 'navbar__link--active';