feat(v2): Provide typing to most of the theme-classic components (#3348)

* feat(v2): Provide typing to most of the theme-classic components

* Expose type to the end users and dogfood it in v2 website
This commit is contained in:
Sam Zhou 2020-08-28 06:06:37 -04:00 committed by GitHub
parent 658dac7d42
commit bd9b6618c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 440 additions and 125 deletions

View file

@ -44,7 +44,7 @@ declare module '@theme/BlogPostPage' {
export type Content = { export type Content = {
readonly frontMatter: FrontMatter; readonly frontMatter: FrontMatter;
readonly metadata: Metadata; readonly metadata: Metadata;
readonly rightToc: MarkdownRightTableOfContents; readonly rightToc: readonly MarkdownRightTableOfContents[];
(): JSX.Element; (): JSX.Element;
}; };
@ -64,8 +64,7 @@ declare module '@theme/BlogListPage' {
readonly content: () => JSX.Element; readonly content: () => JSX.Element;
}; };
export type Props = { export type Metadata = {
readonly metadata: {
readonly blogDescription: string; readonly blogDescription: string;
readonly nextPage?: string; readonly nextPage?: string;
readonly page: number; readonly page: number;
@ -75,6 +74,9 @@ declare module '@theme/BlogListPage' {
readonly totalCount: number; readonly totalCount: number;
readonly totalPages: number; readonly totalPages: number;
}; };
export type Props = {
readonly metadata: Metadata;
readonly items: readonly {readonly content: Content}[]; readonly items: readonly {readonly content: Content}[];
}; };

View file

@ -66,6 +66,8 @@ declare module '@theme/DocItem' {
readonly lastUpdatedAt?: number; readonly lastUpdatedAt?: number;
readonly lastUpdatedBy?: string; readonly lastUpdatedBy?: string;
readonly version?: string; readonly version?: string;
readonly previous?: {readonly permalink: string; readonly title: string};
readonly next?: {readonly permalink: string; readonly title: string};
}; };
export type Props = { export type Props = {
@ -73,7 +75,7 @@ declare module '@theme/DocItem' {
readonly content: { readonly content: {
readonly frontMatter: FrontMatter; readonly frontMatter: FrontMatter;
readonly metadata: Metadata; readonly metadata: Metadata;
readonly rightToc: MarkdownRightTableOfContents; readonly rightToc: readonly MarkdownRightTableOfContents[];
(): JSX.Element; (): JSX.Element;
}; };
}; };

View file

@ -3,6 +3,7 @@
"version": "2.0.0-alpha.61", "version": "2.0.0-alpha.61",
"description": "Classic theme for Docusaurus", "description": "Classic theme for Docusaurus",
"main": "src/index.js", "main": "src/index.js",
"types": "src/types.d.ts",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@ -10,13 +11,14 @@
"scripts": { "scripts": {
"build": "tsc --noEmit && yarn babel && yarn prettier", "build": "tsc --noEmit && yarn babel && yarn prettier",
"watch": "yarn babel --watch", "watch": "yarn babel --watch",
"babel": "babel src -d lib --extensions \".tsx,.ts\" --copy-files", "babel": "babel src -d lib --extensions \".tsx,.ts\" --ignore \"**/*.d.ts\" --copy-files",
"prettier": "prettier --config ../../.prettierrc --write \"**/*.{js,ts}\"" "prettier": "prettier --config ../../.prettierrc --write \"**/*.{js,ts}\""
}, },
"dependencies": { "dependencies": {
"@hapi/joi": "^17.1.1", "@hapi/joi": "^17.1.1",
"@mdx-js/mdx": "^1.5.8", "@mdx-js/mdx": "^1.5.8",
"@mdx-js/react": "^1.5.8", "@mdx-js/react": "^1.5.8",
"@types/react-toggle": "^4.0.2",
"clsx": "^1.1.1", "clsx": "^1.1.1",
"copy-text-to-clipboard": "^2.2.0", "copy-text-to-clipboard": "^2.2.0",
"infima": "0.2.0-alpha.12", "infima": "0.2.0-alpha.12",

View file

@ -7,8 +7,9 @@
import React from 'react'; import React from 'react';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import type {Metadata} from '@theme/BlogListPage';
function BlogListPaginator(props): JSX.Element { function BlogListPaginator(props: {readonly metadata: Metadata}): JSX.Element {
const {metadata} = props; const {metadata} = props;
const {previousPage, nextPage} = metadata; const {previousPage, nextPage} = metadata;

View file

@ -12,7 +12,7 @@ import {MDXProvider} from '@mdx-js/react';
import Head from '@docusaurus/Head'; import Head from '@docusaurus/Head';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import MDXComponents from '@theme/MDXComponents'; import MDXComponents from '@theme/MDXComponents';
import type {FrontMatter, Metadata} from '@theme/BlogPostPage'; import type {Props} from '@theme/BlogPostItem';
import useBaseUrl from '@docusaurus/useBaseUrl'; import useBaseUrl from '@docusaurus/useBaseUrl';
import styles from './styles.module.css'; import styles from './styles.module.css';
@ -32,14 +32,6 @@ const MONTHS = [
'December', 'December',
]; ];
type Props = {
readonly frontMatter: FrontMatter;
readonly metadata: Metadata;
readonly truncated?: boolean;
readonly isBlogPostPage?: boolean;
readonly children: JSX.Element;
};
function BlogPostItem(props: Props): JSX.Element { function BlogPostItem(props: Props): JSX.Element {
const { const {
children, children,

View file

@ -7,8 +7,9 @@
import React from 'react'; import React from 'react';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import type {Props} from '@theme/BlogPostPaginator';
function BlogPostPaginator(props): JSX.Element { function BlogPostPaginator(props: Props): JSX.Element {
const {nextItem, prevItem} = props; const {nextItem, prevItem} = props;
return ( return (

View file

@ -14,6 +14,7 @@ import copy from 'copy-text-to-clipboard';
import rangeParser from 'parse-numeric-range'; import rangeParser from 'parse-numeric-range';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import usePrismTheme from '@theme/hooks/usePrismTheme'; import usePrismTheme from '@theme/hooks/usePrismTheme';
import type {Props} from '@theme/CodeBlock';
import styles from './styles.module.css'; import styles from './styles.module.css';
@ -91,11 +92,7 @@ export default ({
children, children,
className: languageClassName, className: languageClassName,
metastring, metastring,
}: { }: Props): JSX.Element => {
children: string;
className: string;
metastring: string;
}): JSX.Element => {
const { const {
siteConfig: { siteConfig: {
themeConfig: {prism = {}}, themeConfig: {prism = {}},

View file

@ -7,12 +7,7 @@
import React from 'react'; import React from 'react';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import type {Props} from '@theme/DocPaginator';
type PageInfo = {permalink: string; title: string};
type Props = {
metadata: {previous: PageInfo; next: PageInfo};
};
function DocPaginator(props: Props): JSX.Element { function DocPaginator(props: Props): JSX.Element {
const {metadata} = props; const {metadata} = props;

View file

@ -15,6 +15,7 @@ import useLogo from '@theme/hooks/useLogo';
import useScrollPosition from '@theme/hooks/useScrollPosition'; import useScrollPosition from '@theme/hooks/useScrollPosition';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import isInternalUrl from '@docusaurus/isInternalUrl'; import isInternalUrl from '@docusaurus/isInternalUrl';
import type {Props} from '@theme/DocSidebar';
import styles from './styles.module.css'; import styles from './styles.module.css';
@ -167,7 +168,7 @@ function DocSidebar({
path, path,
sidebar, sidebar,
sidebarCollapsible = true, sidebarCollapsible = true,
}): JSX.Element | null { }: Props): JSX.Element | null {
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false); const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
const { const {
siteConfig: { siteConfig: {
@ -195,7 +196,7 @@ function DocSidebar({
})}> })}>
{hideOnScroll && ( {hideOnScroll && (
<Link <Link
tabIndex="-1" tabIndex={-1}
className={styles.sidebarLogo} className={styles.sidebarLogo}
to={logoLink} to={logoLink}
{...logoLinkProps}> {...logoLinkProps}>

View file

@ -7,14 +7,15 @@
/* eslint-disable jsx-a11y/anchor-has-content, jsx-a11y/anchor-is-valid */ /* eslint-disable jsx-a11y/anchor-has-content, jsx-a11y/anchor-is-valid */
import React, {ComponentType} from 'react'; import React from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import type {HeadingType, Props} from '@theme/Heading';
import './styles.css'; import './styles.css';
import styles from './styles.module.css'; import styles from './styles.module.css';
const Heading = (Tag: ComponentType): ((props) => JSX.Element) => const Heading = (Tag: HeadingType): ((props: Props) => JSX.Element) =>
function TargetComponent({id, ...props}) { function TargetComponent({id, ...props}) {
const { const {
siteConfig: { siteConfig: {

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React, {ReactNode} from 'react'; import React from 'react';
import Head from '@docusaurus/Head'; import Head from '@docusaurus/Head';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl'; import useBaseUrl from '@docusaurus/useBaseUrl';
@ -15,6 +15,7 @@ import UserPreferencesProvider from '@theme/UserPreferencesProvider';
import AnnouncementBar from '@theme/AnnouncementBar'; import AnnouncementBar from '@theme/AnnouncementBar';
import Navbar from '@theme/Navbar'; import Navbar from '@theme/Navbar';
import Footer from '@theme/Footer'; import Footer from '@theme/Footer';
import type {Props} from '@theme/Layout';
import './styles.css'; import './styles.css';
@ -26,17 +27,6 @@ function Providers({children}) {
); );
} }
type Props = {
children: ReactNode;
title?: string;
noFooter?: boolean;
description?: string;
image?: string;
keywords?: string[];
permalink?: string;
version?: string;
};
function Layout(props: Props): JSX.Element { function Layout(props: Props): JSX.Element {
const {siteConfig = {}} = useDocusaurusContext(); const {siteConfig = {}} = useDocusaurusContext();
const { const {

View file

@ -5,15 +5,16 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React, {ComponentProps} from 'react'; import React from 'react';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import CodeBlock from '@theme/CodeBlock'; import CodeBlock from '@theme/CodeBlock';
import Heading from '@theme/Heading'; import Heading from '@theme/Heading';
import type {MDXComponentsObject} from '@theme/MDXComponents';
import styles from './styles.module.css'; import styles from './styles.module.css';
export default { const MDXComponents: MDXComponentsObject = {
code: (props: ComponentProps<typeof CodeBlock>): JSX.Element => { code: (props) => {
const {children} = props; const {children} = props;
if (typeof children === 'string') { if (typeof children === 'string') {
if (!children.includes('\n')) { if (!children.includes('\n')) {
@ -23,12 +24,8 @@ export default {
} }
return children; return children;
}, },
a: (props: ComponentProps<'a'>): JSX.Element => { a: (props) => <Link {...props} />,
return <Link {...props} />; pre: (props) => <div className={styles.mdxCodeBlock} {...props} />,
},
pre: (props: ComponentProps<'div'>): JSX.Element => (
<div className={styles.mdxCodeBlock} {...props} />
),
h1: Heading('h1'), h1: Heading('h1'),
h2: Heading('h2'), h2: Heading('h2'),
h3: Heading('h3'), h3: Heading('h3'),
@ -36,3 +33,5 @@ export default {
h5: Heading('h5'), h5: Heading('h5'),
h6: Heading('h6'), h6: Heading('h6'),
}; };
export default MDXComponents;

View file

@ -8,15 +8,13 @@
import React from 'react'; import React from 'react';
import useTOCHighlight from '@theme/hooks/useTOCHighlight'; import useTOCHighlight from '@theme/hooks/useTOCHighlight';
import type {MarkdownRightTableOfContents} from '@docusaurus/types'; import type {TOCProps} from '@theme/TOC';
import styles from './styles.module.css'; import styles from './styles.module.css';
const LINK_CLASS_NAME = 'table-of-contents__link'; const LINK_CLASS_NAME = 'table-of-contents__link';
const ACTIVE_LINK_CLASS_NAME = 'table-of-contents__link--active'; const ACTIVE_LINK_CLASS_NAME = 'table-of-contents__link--active';
const TOP_OFFSET = 100; const TOP_OFFSET = 100;
type TOCProps = {readonly headings: MarkdownRightTableOfContents[]};
/* eslint-disable jsx-a11y/control-has-associated-label */ /* eslint-disable jsx-a11y/control-has-associated-label */
function Headings({headings, isChild}: TOCProps & {isChild?: boolean}) { function Headings({headings, isChild}: TOCProps & {isChild?: boolean}) {
if (!headings.length) { if (!headings.length) {

View file

@ -5,9 +5,10 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React, {ReactNode} from 'react'; import React from 'react';
import type {Props} from '@theme/TabItem';
function TabItem(props: {readonly children: ReactNode}): JSX.Element { function TabItem(props: Props): JSX.Element {
return <div>{props.children}</div>; return <div>{props.children}</div>;
} }

View file

@ -7,6 +7,7 @@
import React, {useState, Children, ReactElement, useEffect} from 'react'; import React, {useState, Children, ReactElement, useEffect} from 'react';
import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext'; import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext';
import type {Props} from '@theme/Tabs';
import clsx from 'clsx'; import clsx from 'clsx';
@ -18,14 +19,6 @@ const keys = {
tab: 9, tab: 9,
}; };
type Props = {
block?: boolean;
children: ReactElement<{value: string}>[];
defaultValue?: string;
values: {value: string; label: string}[];
groupId?: string;
};
function Tabs(props: Props): JSX.Element { function Tabs(props: Props): JSX.Element {
const {block, children, defaultValue, values, groupId} = props; const {block, children, defaultValue, values, groupId} = props;
const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext(); const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();

View file

@ -6,7 +6,10 @@
*/ */
import React from 'react'; import React from 'react';
import type {ThemeContextProps} from '@theme/hooks/useThemeContext';
const ThemeContext = React.createContext(undefined); const ThemeContext = React.createContext<ThemeContextProps | undefined>(
undefined,
);
export default ThemeContext; export default ThemeContext;

View file

@ -5,12 +5,13 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React, {ReactNode} from 'react'; import React from 'react';
import useTheme from '@theme/hooks/useTheme'; import useTheme from '@theme/hooks/useTheme';
import ThemeContext from '@theme/ThemeContext'; import ThemeContext from '@theme/ThemeContext';
import type {Props} from '@theme/ThemeProvider';
function ThemeProvider(props: {readonly children: ReactNode}): JSX.Element { function ThemeProvider(props: Props): JSX.Element {
const {isDarkTheme, setLightTheme, setDarkTheme} = useTheme(); const {isDarkTheme, setLightTheme, setDarkTheme} = useTheme();
return ( return (

View file

@ -5,13 +5,14 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React, {ReactNode} from 'react'; import React from 'react';
import useTabGroupChoice from '@theme/hooks/useTabGroupChoice'; import useTabGroupChoice from '@theme/hooks/useTabGroupChoice';
import useAnnouncementBar from '@theme/hooks/useAnnouncementBar'; import useAnnouncementBar from '@theme/hooks/useAnnouncementBar';
import UserPreferencesContext from '@theme/UserPreferencesContext'; import UserPreferencesContext from '@theme/UserPreferencesContext';
import type {Props} from '@theme/UserPreferencesProvider';
function UserPreferencesProvider(props: {children: ReactNode}): JSX.Element { function UserPreferencesProvider(props: Props): JSX.Element {
const {tabGroupChoices, setTabGroupChoices} = useTabGroupChoice(); const {tabGroupChoices, setTabGroupChoices} = useTabGroupChoice();
const {isAnnouncementBarClosed, closeAnnouncementBar} = useAnnouncementBar(); const {isAnnouncementBarClosed, closeAnnouncementBar} = useAnnouncementBar();

View file

@ -7,14 +7,12 @@
import {useState, useEffect, useCallback} from 'react'; import {useState, useEffect, useCallback} from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import type {useAnnouncementBarReturns} from '@theme/hooks/useAnnoucementBar';
const STORAGE_DISMISS_KEY = 'docusaurus.announcement.dismiss'; const STORAGE_DISMISS_KEY = 'docusaurus.announcement.dismiss';
const STORAGE_ID_KEY = 'docusaurus.announcement.id'; const STORAGE_ID_KEY = 'docusaurus.announcement.id';
const useAnnouncementBar = (): { const useAnnouncementBar = (): useAnnouncementBarReturns => {
isAnnouncementBarClosed: boolean;
closeAnnouncementBar: () => void;
} => {
const {announcementBar} = useDocusaurusContext().siteConfig.themeConfig; const {announcementBar} = useDocusaurusContext().siteConfig.themeConfig;
const [isClosed, setClosed] = useState(true); const [isClosed, setClosed] = useState(true);

View file

@ -9,13 +9,14 @@ import {useState, useCallback, useEffect} from 'react';
import {useLocation} from '@docusaurus/router'; import {useLocation} from '@docusaurus/router';
import useLocationHash from '@theme/hooks/useLocationHash'; import useLocationHash from '@theme/hooks/useLocationHash';
import useScrollPosition from '@theme/hooks/useScrollPosition'; import useScrollPosition from '@theme/hooks/useScrollPosition';
import type {useHideableNavbarReturns} from '@theme/hooks/useHideableNavbar';
const useHideableNavbar = (hideOnScroll: boolean) => { const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => {
const [isNavbarVisible, setIsNavbarVisible] = useState(true); const [isNavbarVisible, setIsNavbarVisible] = useState(true);
const [isFocusedAnchor, setIsFocusedAnchor] = useState(false); const [isFocusedAnchor, setIsFocusedAnchor] = useState(false);
const [lastScrollTop, setLastScrollTop] = useState(0); const [lastScrollTop, setLastScrollTop] = useState(0);
const [navbarHeight, setNavbarHeight] = useState(0); const [navbarHeight, setNavbarHeight] = useState(0);
const navbarRef = useCallback((node) => { const navbarRef = useCallback((node: HTMLElement | null) => {
if (node !== null) { if (node !== null) {
setNavbarHeight(node.getBoundingClientRect().height); setNavbarHeight(node.getBoundingClientRect().height);
} }

View file

@ -5,11 +5,10 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import {useState, useEffect, Dispatch, SetStateAction} from 'react'; import {useState, useEffect} from 'react';
import type {useLocationHashReturns} from '@theme/hooks/useLocationHash';
function useLocationHash( function useLocationHash(initialHash: string): useLocationHashReturns {
initialHash: string,
): [string, Dispatch<SetStateAction<string>>] {
const [hash, setHash] = useState(initialHash); const [hash, setHash] = useState(initialHash);
useEffect(() => { useEffect(() => {

View file

@ -9,15 +9,9 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useThemeContext from '@theme/hooks/useThemeContext'; import useThemeContext from '@theme/hooks/useThemeContext';
import useBaseUrl from '@docusaurus/useBaseUrl'; import useBaseUrl from '@docusaurus/useBaseUrl';
import isInternalUrl from '@docusaurus/isInternalUrl'; import isInternalUrl from '@docusaurus/isInternalUrl';
import type {LogoLinkProps, useLogoReturns} from '@theme/hooks/useLogo';
type LogoLinkProps = {target?: string; rel?: string}; const useLogo = (): useLogoReturns => {
const useLogo = (): {
logoLink: string;
logoLinkProps: LogoLinkProps;
logoImageUrl: string;
logoAlt: string;
} => {
const { const {
siteConfig: {themeConfig: {navbar: {logo = {}} = {}} = {}} = {}, siteConfig: {themeConfig: {navbar: {logo = {}} = {}} = {}} = {},
} = useDocusaurusContext(); } = useDocusaurusContext();

View file

@ -7,8 +7,7 @@
import {useState, useEffect} from 'react'; import {useState, useEffect} from 'react';
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
import type {ScrollPosition} from '@theme/hooks/useScrollPosition';
type ScrollPosition = {scrollX: number; scrollY: number};
const getScrollPosition = (): ScrollPosition => ({ const getScrollPosition = (): ScrollPosition => ({
scrollX: ExecutionEnvironment.canUseDOM ? window.pageXOffset : 0, scrollX: ExecutionEnvironment.canUseDOM ? window.pageXOffset : 0,
@ -16,7 +15,7 @@ const getScrollPosition = (): ScrollPosition => ({
}); });
const useScrollPosition = ( const useScrollPosition = (
effect: (position: ScrollPosition) => void, effect?: (position: ScrollPosition) => void,
deps = [], deps = [],
): ScrollPosition => { ): ScrollPosition => {
const [scrollPosition, setScrollPosition] = useState(getScrollPosition()); const [scrollPosition, setScrollPosition] = useState(getScrollPosition());

View file

@ -6,13 +6,11 @@
*/ */
import {useState, useCallback, useEffect} from 'react'; import {useState, useCallback, useEffect} from 'react';
import type {useTabGroupChoiceReturns} from '@theme/hooks/useTabGroupChoice';
const TAB_CHOICE_PREFIX = 'docusaurus.tab.'; const TAB_CHOICE_PREFIX = 'docusaurus.tab.';
const useTabGroupChoice = (): { const useTabGroupChoice = (): useTabGroupChoiceReturns => {
tabGroupChoices: {readonly [groupId: string]: string};
setTabGroupChoices: (groupId: string, newChoice: string) => void;
} => {
const [tabGroupChoices, setChoices] = useState<{ const [tabGroupChoices, setChoices] = useState<{
readonly [groupId: string]: string; readonly [groupId: string]: string;
}>({}); }>({});

View file

@ -9,6 +9,7 @@ import {useState, useCallback, useEffect} from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
import type {useThemeReturns} from '@theme/hooks/useTheme';
const themes = { const themes = {
light: 'light', light: 'light',
@ -35,11 +36,7 @@ const storeTheme = (newTheme) => {
} }
}; };
const useTheme = (): { const useTheme = (): useThemeReturns => {
isDarkTheme: boolean;
setLightTheme: () => void;
setDarkTheme: () => void;
} => {
const { const {
siteConfig: { siteConfig: {
themeConfig: {colorMode: {disableSwitch = false} = {}} = {}, themeConfig: {colorMode: {disableSwitch = false} = {}} = {},

View file

@ -8,15 +8,10 @@
import {useContext} from 'react'; import {useContext} from 'react';
import ThemeContext from '@theme/ThemeContext'; import ThemeContext from '@theme/ThemeContext';
import type {ThemeContextProps} from '@theme/hooks/useThemeContext';
type ThemeContextProps = {
isDarkTheme: boolean;
setLightTheme: () => void;
setDarkTheme: () => void;
};
function useThemeContext(): ThemeContextProps { function useThemeContext(): ThemeContextProps {
const context = useContext<ThemeContextProps>(ThemeContext); const context = useContext<ThemeContextProps | undefined>(ThemeContext);
if (context == null) { if (context == null) {
throw new Error( throw new Error(
'`useThemeContext` is used outside of `Layout` Component. See https://v2.docusaurus.io/docs/theme-classic#usethemecontext.', '`useThemeContext` is used outside of `Layout` Component. See https://v2.docusaurus.io/docs/theme-classic#usethemecontext.',

View file

@ -8,16 +8,10 @@
import {useContext} from 'react'; import {useContext} from 'react';
import UserPreferencesContext from '@theme/UserPreferencesContext'; import UserPreferencesContext from '@theme/UserPreferencesContext';
import type {UserPreferencesContextProps} from '@theme/hooks/useUserPreferencesContext';
type UserPreferencesContextProps = {
tabGroupChoices: {readonly [groupId: string]: string};
setTabGroupChoices: (groupId: string, newChoice: string) => void;
isAnnouncementBarClosed: boolean;
closeAnnouncementBar: () => void;
};
function useUserPreferencesContext(): UserPreferencesContextProps { function useUserPreferencesContext(): UserPreferencesContextProps {
const context = useContext<UserPreferencesContextProps>( const context = useContext<UserPreferencesContextProps | undefined>(
UserPreferencesContext, UserPreferencesContext,
); );
if (context == null) { if (context == null) {

View file

@ -7,6 +7,8 @@
import {useEffect, useState} from 'react'; import {useEffect, useState} from 'react';
import type {WindowSize} from '@theme/hooks/useWindowSize';
const desktopThresholdWidth = 996; const desktopThresholdWidth = 996;
const windowSizes = { const windowSizes = {
@ -14,8 +16,6 @@ const windowSizes = {
mobile: 'mobile', mobile: 'mobile',
} as const; } as const;
type WindowSize = keyof typeof windowSizes;
function useWindowSize(): WindowSize | undefined { function useWindowSize(): WindowSize | undefined {
const isClient = typeof window !== 'undefined'; const isClient = typeof window !== 'undefined';

View file

@ -5,7 +5,359 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
/* eslint-disable import/no-duplicates */
/* eslint-disable spaced-comment */ /* eslint-disable spaced-comment */
/// <reference types="@docusaurus/module-type-aliases" /> /// <reference types="@docusaurus/module-type-aliases" />
/// <reference types="@docusaurus/plugin-content-blog" /> /// <reference types="@docusaurus/plugin-content-blog" />
/// <reference types="@docusaurus/plugin-content-docs" /> /// <reference types="@docusaurus/plugin-content-docs" />
declare module '@theme/AnnouncementBar' {
const AnnouncementBar: () => JSX.Element | null;
export default AnnouncementBar;
}
declare module '@theme/BlogListPaginator' {
import type {Metadata} from '@theme/BlogListPage';
export type Props = {readonly metadata: Metadata};
const BlogListPaginator: (props: Props) => JSX.Element;
export default BlogListPaginator;
}
declare module '@theme/BlogPostItem' {
import type {FrontMatter, Metadata} from '@theme/BlogPostPage';
export type Props = {
readonly frontMatter: FrontMatter;
readonly metadata: Metadata;
readonly truncated?: string | boolean;
readonly isBlogPostPage?: boolean;
readonly children: JSX.Element;
};
const BlogPostItem: (props: Props) => JSX.Element;
export default BlogPostItem;
}
declare module '@theme/BlogPostPaginator' {
type Item = {readonly title: string; readonly permalink: string};
export type Props = {readonly nextItem?: Item; readonly prevItem?: Item};
const BlogPostPaginator: (props: Props) => JSX.Element;
export default BlogPostPaginator;
}
declare module '@theme/CodeBlock' {
export type Props = {
readonly children: string;
readonly className?: string;
readonly metastring?: string;
};
const CodeBlock: (props: Props) => JSX.Element;
export default CodeBlock;
}
declare module '@theme/DocPaginator' {
type PageInfo = {readonly permalink: string; readonly title: string};
export type Props = {
readonly metadata: {readonly previous?: PageInfo; readonly next?: PageInfo};
};
const DocPaginator: (props: Props) => JSX.Element;
export default DocPaginator;
}
declare module '@theme/DocSidebar' {
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs-types';
export type Props = {
readonly path: string;
readonly sidebar: readonly PropSidebarItem[];
readonly sidebarCollapsible?: boolean;
};
const DocSidebar: (props: Props) => JSX.Element;
export default DocSidebar;
}
declare module '@theme/DocVersionSuggestions' {
const DocVersionSuggestions: () => JSX.Element;
export default DocVersionSuggestions;
}
declare module '@theme/Footer' {
const Footer: () => JSX.Element | null;
export default Footer;
}
declare module '@theme/Heading' {
import type {ComponentProps} from 'react';
export type HeadingType = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
export type Props = ComponentProps<HeadingType>;
const Heading: (Tag: HeadingType) => (props: Props) => JSX.Element;
export default Heading;
}
declare module '@theme/hooks/useAnnoucementBar' {
export type useAnnouncementBarReturns = {
readonly isAnnouncementBarClosed: boolean;
readonly closeAnnouncementBar: () => void;
};
const useAnnouncementBar: () => useAnnouncementBarReturns;
export default useAnnouncementBar;
}
declare module '@theme/hooks/useHideableNavbar' {
export type useHideableNavbarReturns = {
readonly navbarRef: (node: HTMLElement | null) => void;
readonly isNavbarVisible: boolean;
};
const useHideableNavbar: (hideOnScroll: boolean) => useHideableNavbarReturns;
export default useHideableNavbar;
}
declare module '@theme/hooks/useLocationHash' {
import type {Dispatch, SetStateAction} from 'react';
export type useLocationHashReturns = readonly [
string,
Dispatch<SetStateAction<string>>,
];
const useLocationHash: (initialHash: string) => useLocationHashReturns;
export default useLocationHash;
}
declare module '@theme/hooks/useLockBodyScroll' {
const useLockBodyScroll: (lock?: boolean) => void;
export default useLockBodyScroll;
}
declare module '@theme/hooks/useLogo' {
export type LogoLinkProps = {target?: string; rel?: string};
export type useLogoReturns = {
readonly logoLink: string;
readonly logoLinkProps: LogoLinkProps;
readonly logoImageUrl: string;
readonly logoAlt: string;
};
const useLogo: () => useLogoReturns;
export default useLogo;
}
declare module '@theme/hooks/usePrismTheme' {
import defaultTheme from 'prism-react-renderer/themes/palenight';
const usePrismTheme: () => typeof defaultTheme;
export default usePrismTheme;
}
declare module '@theme/hooks/useScrollPosition' {
export type ScrollPosition = {scrollX: number; scrollY: number};
const useScrollPosition: (
effect?: (position: ScrollPosition) => void,
deps?: unknown[],
) => ScrollPosition;
export default useScrollPosition;
}
declare module '@theme/hooks/useTabGroupChoice' {
export type useTabGroupChoiceReturns = {
readonly tabGroupChoices: {readonly [groupId: string]: string};
readonly setTabGroupChoices: (groupId: string, newChoice: string) => void;
};
const useTabGroupChoice: () => useTabGroupChoiceReturns;
export default useTabGroupChoice;
}
declare module '@theme/hooks/useTheme' {
export type useThemeReturns = {
readonly isDarkTheme: boolean;
readonly setLightTheme: () => void;
readonly setDarkTheme: () => void;
};
const useTheme: () => useThemeReturns;
export default useTheme;
}
declare module '@theme/hooks/useThemeContext' {
export type ThemeContextProps = {
isDarkTheme: boolean;
setLightTheme: () => void;
setDarkTheme: () => void;
};
export default function useThemeContext(): ThemeContextProps;
}
declare module '@theme/hooks/useTOCHighlight' {
export default function useTOCHighlight(
linkClassName: string,
linkActiveClassName: string,
topOffset: number,
): void;
}
declare module '@theme/hooks/useUserPreferencesContext' {
export type UserPreferencesContextProps = {
tabGroupChoices: {readonly [groupId: string]: string};
setTabGroupChoices: (groupId: string, newChoice: string) => void;
isAnnouncementBarClosed: boolean;
closeAnnouncementBar: () => void;
};
export default function useUserPreferencesContext(): UserPreferencesContextProps;
}
declare module '@theme/hooks/useWindowSize' {
export const windowSizes: {
desktop: 'desktop';
mobile: 'mobile';
};
export type WindowSize = keyof typeof windowSizes;
export default function useWindowSize(): WindowSize | undefined;
}
declare module '@theme/Layout' {
import type {ReactNode} from 'react';
export type Props = {
children: ReactNode;
title?: string;
noFooter?: boolean;
description?: string;
image?: string;
keywords?: string[];
permalink?: string;
version?: string;
};
const Layout: (props: Props) => JSX.Element;
export default Layout;
}
declare module '@theme/MDXComponents' {
import {ComponentProps} from 'react';
import CodeBlock from '@theme/CodeBlock';
export type MDXComponentsObject = {
readonly code: typeof CodeBlock;
readonly a: (props: ComponentProps<'a'>) => JSX.Element;
readonly pre: (props: ComponentProps<'div'>) => JSX.Element;
readonly h1: (props: ComponentProps<'h1'>) => JSX.Element;
readonly h2: (props: ComponentProps<'h2'>) => JSX.Element;
readonly h3: (props: ComponentProps<'h3'>) => JSX.Element;
readonly h4: (props: ComponentProps<'h4'>) => JSX.Element;
readonly h5: (props: ComponentProps<'h5'>) => JSX.Element;
readonly h6: (props: ComponentProps<'h6'>) => JSX.Element;
};
const MDXComponents: MDXComponentsObject;
export default MDXComponents;
}
// TODO @theme/MDXPage
declare module '@theme/Navbar' {
const Navbar: () => JSX.Element;
export default Navbar;
}
// TODO @theme/NavbarItem/DefaultNavbarItem
// TODO @theme/NavbarItem/DocsVersionDropdownNavbarItem
// TODO @theme/NavbarItem/DocsVersionNavbarItem
// TODO @theme/NavbarItem
declare module '@theme/TabItem' {
import type {ReactNode} from 'react';
export type Props = {readonly children: ReactNode};
const TabItem: () => JSX.Element;
export default TabItem;
}
declare module '@theme/Tabs' {
import type {ReactElement} from 'react';
export type Props = {
readonly block?: boolean;
readonly children: readonly ReactElement<{value: string}>[];
readonly defaultValue?: string;
readonly values: readonly {value: string; label: string}[];
readonly groupId?: string;
};
const Tabs: () => JSX.Element;
export default Tabs;
}
declare module '@theme/ThemeProvider' {
import type {ReactNode} from 'react';
export type Props = {readonly children: ReactNode};
const ThemeProvider: (props: Props) => JSX.Element;
export default ThemeProvider;
}
declare module '@theme/TOC' {
import type {MarkdownRightTableOfContents} from '@docusaurus/types';
export type TOCProps = {
readonly headings: readonly MarkdownRightTableOfContents[];
};
const TOC: (props: TOCProps) => JSX.Element;
export default TOC;
}
declare module '@theme/Toggle' {
import {ComponentProps} from 'react';
import ReactToggle from 'react-toggle';
const Toggle: (props: ComponentProps<typeof ReactToggle>) => JSX.Element;
export default Toggle;
}
declare module '@theme/UserPreferencesProvider' {
import type {ReactNode} from 'react';
export type Props = {readonly children: ReactNode};
const UserPreferencesProvider: (props: Props) => JSX.Element;
export default UserPreferencesProvider;
}
declare module '@theme/ThemeContext' {
import type {Context} from 'react';
import type {ThemeContextProps} from '@theme/hooks/useThemeContext';
const ThemeContext: Context<ThemeContextProps | undefined>;
export default ThemeContext;
}
declare module '@theme/UserPreferencesContext' {
import type {Context} from 'react';
import type {UserPreferencesContextProps} from '@theme/hooks/useUserPreferencesContext';
const UserPreferencesContext: Context<
UserPreferencesContextProps | undefined
>;
export default UserPreferencesContext;
}

View file

@ -7,3 +7,4 @@
// eslint-disable-next-line spaced-comment // eslint-disable-next-line spaced-comment
/// <reference types="@docusaurus/module-type-aliases" /> /// <reference types="@docusaurus/module-type-aliases" />
/// <reference types="@docusaurus/theme-classic" />

View file

@ -4168,6 +4168,13 @@
"@types/history" "*" "@types/history" "*"
"@types/react" "*" "@types/react" "*"
"@types/react-toggle@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/react-toggle/-/react-toggle-4.0.2.tgz#46ffa5af1a55de5f25d0aa78ef0b557b5c8bf276"
integrity sha512-sHqfoKFnL0YU2+OC4meNEC8Ptx9FE8/+nFeFvNcdBa6ANA8KpAzj3R9JN8GtrvlLgjKDoYgI7iILgXYcTPo2IA==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^16.9.38": "@types/react@*", "@types/react@^16.9.38":
version "16.9.38" version "16.9.38"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.38.tgz#868405dace93a4095d3e054f4c4a1de7a1ac0680" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.38.tgz#868405dace93a4095d3e054f4c4a1de7a1ac0680"