You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2022/04/12 07:43:45 UTC
[apisix-website] branch master updated: refactor(hooks, theme): to ts (#1014)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
The following commit(s) were added to refs/heads/master by this push:
new de1b36ad0be refactor(hooks, theme): to ts (#1014)
de1b36ad0be is described below
commit de1b36ad0be8fea5fbecc42ff9897e5cbf049b5d
Author: SkyeYoung <is...@outlook.com>
AuthorDate: Tue Apr 12 15:43:37 2022 +0800
refactor(hooks, theme): to ts (#1014)
Co-authored-by: 琚致远 <ju...@apache.org>
---
package.json | 4 +-
website/src/hooks/useOutsideClick.js | 19 ---
website/src/hooks/useOutsideClick.ts | 20 +++
website/src/theme/DocPage/index.tsx | 239 +++++++++++++++++----------------
website/src/theme/DocSidebar/index.tsx | 176 ++++++++++++------------
5 files changed, 234 insertions(+), 224 deletions(-)
diff --git a/package.json b/package.json
index dd7ffa2ef85..13e5ba0a2cf 100644
--- a/package.json
+++ b/package.json
@@ -32,8 +32,8 @@
"stylelint-config-standard": "^25.0.0"
},
"lint-staged": {
- "*.{js, jsx, ts, tsx}": "eslint --cache --fix",
- "*.{yml, yaml}": "eslint --cache --fix",
+ "*.{js,jsx,ts,tsx}": "eslint --cache --fix",
+ "*.{yml,yaml}": "eslint --cache --fix",
"*.css": "stylelint --cache --fix"
}
}
diff --git a/website/src/hooks/useOutsideClick.js b/website/src/hooks/useOutsideClick.js
deleted file mode 100644
index 690f8ebf8c7..00000000000
--- a/website/src/hooks/useOutsideClick.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { useEffect } from "react";
-
-const useOutsideClick = (ref, callback) => {
- const handleClick = (e) => {
- if (ref.current && !ref.current.contains(e.target)) {
- callback();
- }
- };
-
- useEffect(() => {
- document.addEventListener("click", handleClick);
-
- return () => {
- document.removeEventListener("click", handleClick);
- };
- });
-};
-
-export default useOutsideClick;
diff --git a/website/src/hooks/useOutsideClick.ts b/website/src/hooks/useOutsideClick.ts
new file mode 100644
index 00000000000..c11566aa578
--- /dev/null
+++ b/website/src/hooks/useOutsideClick.ts
@@ -0,0 +1,20 @@
+import type { MutableRefObject } from 'react';
+import { useEffect } from 'react';
+
+const useOutsideClick = (ref: MutableRefObject<HTMLDivElement>, callback: () => void): void => {
+ const handleClick = (e: MouseEvent & { target: HTMLDivElement }) => {
+ if (ref.current && !ref.current.contains(e.target)) {
+ callback();
+ }
+ };
+
+ useEffect(() => {
+ document.addEventListener('click', handleClick);
+
+ return () => {
+ document.removeEventListener('click', handleClick);
+ };
+ });
+};
+
+export default useOutsideClick;
diff --git a/website/src/theme/DocPage/index.tsx b/website/src/theme/DocPage/index.tsx
index 9c895afdb60..ff90ceec8ed 100644
--- a/website/src/theme/DocPage/index.tsx
+++ b/website/src/theme/DocPage/index.tsx
@@ -5,40 +5,53 @@
* LICENSE file in the root directory of this source tree.
*/
-import React, {ReactNode, useState, useCallback, useEffect} from 'react';
-import {MDXProvider} from '@mdx-js/react';
+import type { ReactNode } from 'react';
+import React, { useState, useCallback, useEffect } from 'react';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { MDXProvider } from '@mdx-js/react';
import renderRoutes from '@docusaurus/renderRoutes';
-import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types';
+import type { PropVersionMetadata } from '@docusaurus/plugin-content-docs-types';
import Layout from '@theme/Layout';
import DocSidebar from '@theme/DocSidebar';
import MDXComponents from '@theme/MDXComponents';
import NotFound from '@theme/NotFound';
-import type {DocumentRoute} from '@theme/DocItem';
-import type {Props} from '@theme/DocPage';
+import type { DocumentRoute } from '@theme/DocItem';
+import type { Props } from '@theme/DocPage';
import IconArrow from '@theme/IconArrow';
import BackToTopButton from '@theme/BackToTopButton';
-import {matchPath} from '@docusaurus/router';
-import {translate} from '@docusaurus/Translate';
-
+import { matchPath } from '@docusaurus/router';
+import { translate } from '@docusaurus/Translate';
import clsx from 'clsx';
-import styles from './styles.module.css';
-import {ThemeClassNames, docVersionSearchTag} from '@docusaurus/theme-common';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { ThemeClassNames, docVersionSearchTag } from '@docusaurus/theme-common';
import Head from '@docusaurus/Head';
-import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
-type DocPageContentProps = {
- readonly currentDocRoute: DocumentRoute;
- readonly versionMetadata: PropVersionMetadata;
- readonly children: ReactNode;
+import styles from './styles.module.css';
+
+ type DocPageContentProps = {
+ readonly currentDocRoute: DocumentRoute;
+ readonly versionMetadata: PropVersionMetadata;
+ readonly children: ReactNode;
+ };
+
+const navbarLinkMap = {
+ general: 'General',
+ apisix: 'Apache APISIX®',
+ dashboard: 'Apache APISIX® Dashboard',
+ 'ingress-controller': 'Apache APISIX® Ingress Controller',
+ 'helm-chart': 'Apache APISIX® Helm Chart',
+ docker: 'Apache APISIX® Docker',
+ 'java-plugin-runner': 'Apache APISIX® Java Plugin Runner',
+ 'go-plugin-runner': 'Apache APISIX® Go Plugin Runner',
};
-function DocPageContent({
+const DocPageContent = ({
currentDocRoute,
versionMetadata,
children,
-}: DocPageContentProps): JSX.Element {
- const {pluginId, version} = versionMetadata;
+}: DocPageContentProps): JSX.Element => {
+ const { pluginId, version } = versionMetadata;
const sidebarName = currentDocRoute.sidebar;
const sidebar = sidebarName
? versionMetadata.docsSidebars[sidebarName]
@@ -46,45 +59,23 @@ function DocPageContent({
const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false);
const [hiddenSidebar, setHiddenSidebar] = useState(false);
-
+
useEffect(() => {
- const children = document.querySelector(".navbar__items--right").childElementCount;
- if(window.innerWidth > 745) {
- document.querySelector(".navbar__items--right").childNodes[children-2].style.display = "block";
- }
- else {
- document.querySelector(".navbar__items--right").childNodes[children-2].style.display = "none";
- }
- const currentPage = currentDocRoute.path.split("/")[2] || "";
- switch (currentPage) {
- case "general":
- document.querySelectorAll(".navbar__link")[0].innerText = "General";
- break;
- case "apisix":
- document.querySelectorAll(".navbar__link")[0].innerText = "Apache APISIX®";
- break;
- case "dashboard":
- document.querySelectorAll(".navbar__link")[0].innerText = "Apache APISIX® Dashboard";
- break;
- case "ingress-controller":
- document.querySelectorAll(".navbar__link")[0].innerText = "Apache APISIX® Ingress Controller";
- break;
- case "helm-chart":
- document.querySelectorAll(".navbar__link")[0].innerText = "Apache APISIX® Helm Chart";
- break;
- case "docker":
- document.querySelectorAll(".navbar__link")[0].innerText = "Apache APISIX® Docker";
- break;
- case "java-plugin-runner":
- document.querySelectorAll(".navbar__link")[0].innerText = "Apache APISIX® Java Plugin Runner";
- break;
- case "go-plugin-runner":
- document.querySelectorAll(".navbar__link")[0].innerText = "Apache APISIX® Go Plugin Runner";
- break;
+ const childrenCount = document.querySelector('.navbar__items--right').childElementCount;
+ const el = document.querySelector('.navbar__items--right').childNodes[childrenCount - 2] as HTMLDivElement;
+ if (window.innerWidth > 745) {
+ el.style.display = 'block';
+ } else {
+ el.style.display = 'none';
}
+
+ const currentPage = currentDocRoute.path.split('/')[2] || '';
+ const navbarLink = document.querySelectorAll('.navbar__link')[0] as HTMLAnchorElement;
+ navbarLink.innerText = navbarLinkMap[currentPage];
+
return () => {
- document.querySelector(".navbar__items--right").childNodes[children-2].style.display = "none"
- }
+ el.style.display = 'none';
+ };
}, []);
const toggleSidebar = useCallback(() => {
@@ -94,77 +85,84 @@ function DocPageContent({
setHiddenSidebarContainer(!hiddenSidebarContainer);
}, [hiddenSidebar]);
-
+
return (
<Layout
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
wrapperClassName={ThemeClassNames.wrapper.docsPages}
pageClassName={ThemeClassNames.page.docsDocPage}
searchMetadatas={{
version,
tag: docVersionSearchTag(pluginId, version),
- }}>
+ }}
+ >
<div className={styles.docPage}>
<BackToTopButton />
{sidebar && (
- <aside
- className={clsx(styles.docSidebarContainer, {
- [styles.docSidebarContainerHidden]: hiddenSidebarContainer,
+ <aside
+ className={clsx(styles.docSidebarContainer, {
+ [styles.docSidebarContainerHidden]: hiddenSidebarContainer,
+ })}
+ onTransitionEnd={(e) => {
+ if (
+ !e.currentTarget.classList.contains(styles.docSidebarContainer)
+ ) {
+ return;
+ }
+
+ if (hiddenSidebarContainer) {
+ setHiddenSidebar(true);
+ }
+ }}
+ >
+ <DocSidebar
+ key={
+ // Reset sidebar state on sidebar changes
+ // See https://github.com/facebook/docusaurus/issues/3414
+ sidebarName
+ }
+ sidebar={sidebar}
+ path={currentDocRoute.path}
+ onCollapse={toggleSidebar}
+ isHidden={hiddenSidebar}
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ docsPluginId={pluginId}
+ />
+
+ {hiddenSidebar && (
+ <div
+ className={styles.collapsedDocSidebar}
+ title={translate({
+ id: 'theme.docs.sidebar.expandButtonTitle',
+ message: 'Expand sidebar',
+ description:
+ 'The ARIA label and title attribute for expand button of doc sidebar',
})}
- onTransitionEnd={(e) => {
- if (
- !e.currentTarget.classList.contains(styles.docSidebarContainer)
- ) {
- return;
- }
-
- if (hiddenSidebarContainer) {
- setHiddenSidebar(true);
- }
- }}>
- <DocSidebar
- key={
- // Reset sidebar state on sidebar changes
- // See https://github.com/facebook/docusaurus/issues/3414
- sidebarName
- }
- sidebar={sidebar}
- path={currentDocRoute.path}
- onCollapse={toggleSidebar}
- isHidden={hiddenSidebar}
- // @ts-ignore
- docsPluginId={pluginId}
- />
-
- {hiddenSidebar && (
- <div
- className={styles.collapsedDocSidebar}
- title={translate({
- id: 'theme.docs.sidebar.expandButtonTitle',
- message: 'Expand sidebar',
- description:
- 'The ARIA label and title attribute for expand button of doc sidebar',
- })}
- aria-label={translate({
- id: 'theme.docs.sidebar.expandButtonAriaLabel',
- message: 'Expand sidebar',
- description:
- 'The ARIA label and title attribute for expand button of doc sidebar',
- })}
- tabIndex={0}
- role="button"
- onKeyDown={toggleSidebar}
- onClick={toggleSidebar}>
- <IconArrow className={styles.expandSidebarButtonIcon} />
- </div>
- )}
- </aside>
+ aria-label={translate({
+ id: 'theme.docs.sidebar.expandButtonAriaLabel',
+ message: 'Expand sidebar',
+ description:
+ 'The ARIA label and title attribute for expand button of doc sidebar',
+ })}
+ tabIndex={0}
+ role="button"
+ onKeyDown={toggleSidebar}
+ onClick={toggleSidebar}
+ >
+ <IconArrow className={styles.expandSidebarButtonIcon} />
+ </div>
+ )}
+ </aside>
)}
<main
className={clsx(styles.docMainContainer, {
[styles.docMainContainerEnhanced]:
- hiddenSidebarContainer || !sidebar,
- })}>
+ hiddenSidebarContainer || !sidebar,
+ })}
+ >
<div
className={clsx(
'container padding-top--md padding-bottom--lg',
@@ -172,40 +170,43 @@ function DocPageContent({
{
[styles.docItemWrapperEnhanced]: hiddenSidebarContainer,
},
- )}>
+ )}
+ >
<MDXProvider components={MDXComponents}>{children}</MDXProvider>
</div>
</main>
</div>
</Layout>
);
-}
+};
-function DocPage(props: Props): JSX.Element {
+const DocPage = (props: Props): JSX.Element => {
const {
- route: {routes: docRoutes},
+ route: { routes: docRoutes },
versionMetadata,
location,
} = props;
- const currentDocRoute = docRoutes.find((docRoute) =>
- matchPath(location.pathname, docRoute),
- );
+ const currentDocRoute = docRoutes.find((docRoute) => matchPath(location.pathname, docRoute));
if (!currentDocRoute) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
return <NotFound {...props} />;
}
return (
<>
<Head>
{/* TODO we should add a core addRoute({htmlClassName}) generic plugin option */}
+ {/* eslint-disable-next-line jsx-a11y/html-has-lang */}
<html className={versionMetadata.className} />
</Head>
<DocPageContent
currentDocRoute={currentDocRoute}
- versionMetadata={versionMetadata}>
- {renderRoutes(docRoutes, {versionMetadata})}
+ versionMetadata={versionMetadata}
+ >
+ {renderRoutes(docRoutes, { versionMetadata })}
</DocPageContent>
</>
);
-}
+};
export default DocPage;
diff --git a/website/src/theme/DocSidebar/index.tsx b/website/src/theme/DocSidebar/index.tsx
index 37318f57335..127ce92528f 100644
--- a/website/src/theme/DocSidebar/index.tsx
+++ b/website/src/theme/DocSidebar/index.tsx
@@ -5,30 +5,31 @@
* LICENSE file in the root directory of this source tree.
*/
-import React, {useState} from 'react';
+import type { FC } from 'react';
+import React, { useState } from 'react';
import clsx from 'clsx';
+// eslint-disable-next-line import/no-extraneous-dependencies
import {
useThemeConfig,
useAnnouncementBar,
MobileSecondaryMenuFiller,
- MobileSecondaryMenuComponent,
ThemeClassNames,
} from '@docusaurus/theme-common';
import useWindowSize from '@theme/hooks/useWindowSize';
import useScrollPosition from '@theme/hooks/useScrollPosition';
import Logo from '@theme/Logo';
import IconArrow from '@theme/IconArrow';
-import {translate} from '@docusaurus/Translate';
-import {DocSidebarItems} from '@theme/DocSidebarItem';
-import DocsVersionDropdownNavbarItem from "@theme/NavbarItem/DocsVersionDropdownNavbarItem";
-import type {Props} from '@theme/DocSidebar';
+import { translate } from '@docusaurus/Translate';
+import { DocSidebarItems } from '@theme/DocSidebarItem';
+import DocsVersionDropdownNavbarItem from '@theme/NavbarItem/DocsVersionDropdownNavbarItem';
+import type { Props } from '@theme/DocSidebar';
import styles from './styles.module.css';
function useShowAnnouncementBar() {
- const {isClosed} = useAnnouncementBar();
+ const { isClosed } = useAnnouncementBar();
const [showAnnouncementBar, setShowAnnouncementBar] = useState(!isClosed);
- useScrollPosition(({scrollY}) => {
+ useScrollPosition(({ scrollY }) => {
if (!isClosed) {
setShowAnnouncementBar(scrollY === 0);
}
@@ -36,51 +37,101 @@ function useShowAnnouncementBar() {
return showAnnouncementBar;
}
-function HideableSidebarButton({onClick}: {onClick: React.MouseEventHandler}) {
+const HideableSidebarButton = ({ onClick }: {onClick: React.MouseEventHandler}) => (
+ <button
+ type="button"
+ title={translate({
+ id: 'theme.docs.sidebar.collapseButtonTitle',
+ message: 'Collapse sidebar',
+ description: 'The title attribute for collapse button of doc sidebar',
+ })}
+ aria-label={translate({
+ id: 'theme.docs.sidebar.collapseButtonAriaLabel',
+ message: 'Collapse sidebar',
+ description: 'The title attribute for collapse button of doc sidebar',
+ })}
+ className={clsx(
+ 'button button--secondary button--outline',
+ styles.collapseSidebarButton,
+ )}
+ onClick={onClick}
+ >
+ <IconArrow className={styles.collapseSidebarButtonIcon} />
+ </button>
+);
+
+const DocsVersionWrapper = (props: {docsPluginId: string}) => {
+ const { docsPluginId } = props;
return (
- <button
- type="button"
- title={translate({
- id: 'theme.docs.sidebar.collapseButtonTitle',
- message: 'Collapse sidebar',
- description: 'The title attribute for collapse button of doc sidebar',
- })}
- aria-label={translate({
- id: 'theme.docs.sidebar.collapseButtonAriaLabel',
- message: 'Collapse sidebar',
- description: 'The title attribute for collapse button of doc sidebar',
- })}
- className={clsx(
- 'button button--secondary button--outline',
- styles.collapseSidebarButton,
- )}
- onClick={onClick}>
- <IconArrow className={styles.collapseSidebarButtonIcon} />
- </button>
+ <div className={styles.sidebarVersionSwitch}>
+ Version:
+ <DocsVersionDropdownNavbarItem
+ docsPluginId={docsPluginId}
+ dropdownItemsBefore={[]}
+ dropdownItemsAfter={[]}
+ items={[]}
+ />
+ </div>
);
-}
+};
+
+const DocsVersionWrapperMemo = React.memo(DocsVersionWrapper);
+
+ interface DocSidebarMobileSecondaryMenuProps extends Props {
+ docsPluginId: string,
+ toggleSidebar: () => void
+ }
-function DocSidebarDesktop({path, sidebar, onCollapse, isHidden, docsPluginId}: Props & {docsPluginId: string}) {
+const DocSidebarMobileSecondaryMenu: FC<DocSidebarMobileSecondaryMenuProps> = ({
+ toggleSidebar,
+ sidebar,
+ path,
+ docsPluginId,
+}) => (
+ <>
+ <DocsVersionWrapperMemo docsPluginId={docsPluginId} />
+ <ul className={clsx(ThemeClassNames.docs.docSidebarMenu, 'menu__list')}>
+ <DocSidebarItems
+ items={sidebar}
+ activePath={path}
+ onItemClick={() => toggleSidebar()}
+ />
+ </ul>
+ </>
+);
+
+const DocSidebarMobile = (props: Props) => (
+ <MobileSecondaryMenuFiller
+ component={DocSidebarMobileSecondaryMenu}
+ props={props}
+ />
+);
+
+const DocSidebarDesktop = ({
+ path, sidebar, onCollapse, isHidden, docsPluginId,
+}: Props & {docsPluginId: string}) => {
const showAnnouncementBar = useShowAnnouncementBar();
const {
- navbar: {hideOnScroll},
+ navbar: { hideOnScroll },
hideableSidebar,
} = useThemeConfig();
- const {isClosed: isAnnouncementBarClosed} = useAnnouncementBar();
+ const { isClosed: isAnnouncementBarClosed } = useAnnouncementBar();
return (
<div
className={clsx(styles.sidebar, {
[styles.sidebarWithHideableNavbar]: hideOnScroll,
[styles.sidebarHidden]: isHidden,
- })}>
+ })}
+ >
{hideOnScroll && <Logo tabIndex={-1} className={styles.sidebarLogo} />}
<DocsVersionWrapperMemo docsPluginId={docsPluginId} />
<nav
className={clsx('menu thin-scrollbar', styles.menu, {
[styles.menuWithAnnouncementBar]:
- !isAnnouncementBarClosed && showAnnouncementBar,
- })}>
+ !isAnnouncementBarClosed && showAnnouncementBar,
+ })}
+ >
<ul className={clsx(ThemeClassNames.docs.docSidebarMenu, 'menu__list')}>
<DocSidebarItems items={sidebar} activePath={path} />
</ul>
@@ -88,61 +139,16 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden, docsPluginId}:
{hideableSidebar && <HideableSidebarButton onClick={onCollapse} />}
</div>
);
-}
-
-const DocSidebarMobileSecondaryMenu: MobileSecondaryMenuComponent<Props & {docsPluginId: string}> = ({
- toggleSidebar,
- sidebar,
- path,
- docsPluginId
-}) => {
- return (
- <>
- <DocsVersionWrapperMemo docsPluginId={docsPluginId} />
- <ul className={clsx(ThemeClassNames.docs.docSidebarMenu, 'menu__list')}>
- <DocSidebarItems
- items={sidebar}
- activePath={path}
- onItemClick={() => toggleSidebar()}
- />
- </ul>
- </>
- );
};
-function DocSidebarMobile(props: Props) {
- return (
- <MobileSecondaryMenuFiller
- component={DocSidebarMobileSecondaryMenu}
- props={props}
- />
- );
-}
-
-function DocsVersionWrapper(props: {docsPluginId: string}) {
- return (
- <div className={styles.sidebarVersionSwitch}>
- Version:
- <DocsVersionDropdownNavbarItem
- docsPluginId={props.docsPluginId}
- dropdownItemsBefore={[]}
- dropdownItemsAfter={[]}
- items={[]}
- />
- </div>
- );
-}
-
-const DocSidebarDesktopMemo = React.memo(DocSidebarDesktop);
const DocSidebarMobileMemo = React.memo(DocSidebarMobile);
-const DocsVersionWrapperMemo = React.memo(DocsVersionWrapper);
+const DocSidebarDesktopMemo = React.memo(DocSidebarDesktop);
-export default function DocSidebar(props: Props & {docsPluginId: string}): JSX.Element {
+const DocSidebar: FC<Props & {docsPluginId: string}> = (props) => {
const windowSize = useWindowSize();
// Desktop sidebar visible on hydration: need SSR rendering
- const shouldRenderSidebarDesktop =
- windowSize === 'desktop' || windowSize === 'ssr';
+ const shouldRenderSidebarDesktop = windowSize === 'desktop' || windowSize === 'ssr';
// Mobile sidebar not visible on hydration: can avoid SSR rendering
const shouldRenderSidebarMobile = windowSize === 'mobile';
@@ -153,4 +159,6 @@ export default function DocSidebar(props: Props & {docsPluginId: string}): JSX.E
{shouldRenderSidebarMobile && <DocSidebarMobileMemo {...props} />}
</>
);
-}
+};
+
+export default DocSidebar;