@docusaurus/theme-classic 3.9.2-canary-6495 → 3.9.2-canary-6526
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/theme/DocCard/Description/index.d.ts +9 -0
- package/lib/theme/DocCard/Description/index.js +23 -0
- package/lib/theme/DocCard/Description/styles.module.css +10 -0
- package/lib/theme/DocCard/Heading/Icon/index.d.ts +9 -0
- package/lib/theme/DocCard/Heading/Icon/index.js +18 -0
- package/lib/theme/DocCard/Heading/Icon/styles.module.css +11 -0
- package/lib/theme/DocCard/Heading/Text/index.d.ts +9 -0
- package/lib/theme/DocCard/Heading/Text/index.js +22 -0
- package/lib/theme/DocCard/Heading/Text/styles.module.css +10 -0
- package/lib/theme/DocCard/Heading/index.d.ts +9 -0
- package/lib/theme/DocCard/Heading/index.js +24 -0
- package/lib/theme/DocCard/Heading/styles.module.css +11 -0
- package/lib/theme/DocCard/Layout/index.d.ts +9 -0
- package/lib/theme/DocCard/Layout/index.js +42 -0
- package/lib/theme/DocCard/{styles.module.css → Layout/styles.module.css} +0 -8
- package/lib/theme/DocCard/index.js +24 -56
- package/lib/theme/Layout/index.js +0 -2
- package/lib/theme/SiteMetadata/index.js +1 -2
- package/lib/theme/TabItem/index.d.ts +1 -1
- package/lib/theme/TabItem/index.js +15 -1
- package/lib/theme/Tabs/index.js +24 -39
- package/package.json +15 -15
- package/src/theme/DocCard/Description/index.tsx +27 -0
- package/src/theme/DocCard/Description/styles.module.css +10 -0
- package/src/theme/DocCard/Heading/Icon/index.tsx +22 -0
- package/src/theme/DocCard/Heading/Icon/styles.module.css +11 -0
- package/src/theme/DocCard/Heading/Text/index.tsx +27 -0
- package/src/theme/DocCard/Heading/Text/styles.module.css +10 -0
- package/src/theme/DocCard/Heading/index.tsx +28 -0
- package/src/theme/DocCard/Heading/styles.module.css +11 -0
- package/src/theme/DocCard/Layout/index.tsx +55 -0
- package/src/theme/DocCard/{styles.module.css → Layout/styles.module.css} +0 -8
- package/src/theme/DocCard/index.tsx +28 -79
- package/src/theme/Layout/index.tsx +0 -3
- package/src/theme/SiteMetadata/index.tsx +1 -2
- package/src/theme/TabItem/index.tsx +28 -3
- package/src/theme/Tabs/index.tsx +31 -50
- package/src/theme-classic.d.ts +65 -0
package/README.md
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import { type ReactNode } from 'react';
|
|
8
|
+
import type { Props } from '@theme/DocCard/Description';
|
|
9
|
+
export default function DocCardDescription({ description }: Props): ReactNode;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
10
|
+
import styles from './styles.module.css';
|
|
11
|
+
export default function DocCardDescription({description}) {
|
|
12
|
+
return (
|
|
13
|
+
<p
|
|
14
|
+
className={clsx(
|
|
15
|
+
'text--truncate',
|
|
16
|
+
ThemeClassNames.docs.docCard.description,
|
|
17
|
+
styles.cardDescription,
|
|
18
|
+
)}
|
|
19
|
+
title={description}>
|
|
20
|
+
{description}
|
|
21
|
+
</p>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import { type ReactNode } from 'react';
|
|
8
|
+
import type { Props } from '@theme/DocCard/Heading/Icon';
|
|
9
|
+
export default function DocCardHeadingIcon({ icon }: Props): ReactNode;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
10
|
+
import styles from './styles.module.css';
|
|
11
|
+
export default function DocCardHeadingIcon({icon}) {
|
|
12
|
+
return (
|
|
13
|
+
<span
|
|
14
|
+
className={clsx(ThemeClassNames.docs.docCard.icon, styles.cardTitleIcon)}>
|
|
15
|
+
{icon}
|
|
16
|
+
</span>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.cardTitleIcon {
|
|
9
|
+
font-size: 1.6rem;
|
|
10
|
+
margin-right: 0.6rem;
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import { type ReactNode } from 'react';
|
|
8
|
+
import type { Props } from '@theme/DocCard/Heading/Text';
|
|
9
|
+
export default function DocCardHeadingText({ title }: Props): ReactNode;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
10
|
+
import styles from './styles.module.css';
|
|
11
|
+
export default function DocCardHeadingText({title}) {
|
|
12
|
+
return (
|
|
13
|
+
<span
|
|
14
|
+
className={clsx(
|
|
15
|
+
'text--truncate',
|
|
16
|
+
ThemeClassNames.docs.docCard.title,
|
|
17
|
+
styles.cardTitleText,
|
|
18
|
+
)}>
|
|
19
|
+
{title}
|
|
20
|
+
</span>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import { type ReactNode } from 'react';
|
|
8
|
+
import type { Props } from '@theme/DocCard/Heading';
|
|
9
|
+
export default function DocCardHeading({ item, title, icon }: Props): ReactNode;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
10
|
+
import Heading from '@theme/Heading';
|
|
11
|
+
import Icon from '@theme/DocCard/Heading/Icon';
|
|
12
|
+
import Text from '@theme/DocCard/Heading/Text';
|
|
13
|
+
import styles from './styles.module.css';
|
|
14
|
+
export default function DocCardHeading({item, title, icon}) {
|
|
15
|
+
return (
|
|
16
|
+
<Heading
|
|
17
|
+
as="h2"
|
|
18
|
+
className={clsx(ThemeClassNames.docs.docCard.heading, styles.cardTitle)}
|
|
19
|
+
title={title}>
|
|
20
|
+
{icon && <Icon item={item} icon={icon} />}
|
|
21
|
+
<Text item={item} title={title} />
|
|
22
|
+
</Heading>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.cardTitle {
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import { type ReactNode } from 'react';
|
|
8
|
+
import type { Props } from '@theme/DocCard/Layout';
|
|
9
|
+
export default function DocCardLayout({ item, className, href, icon, title, description, }: Props): ReactNode;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import Link from '@docusaurus/Link';
|
|
10
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
11
|
+
import Heading from '@theme/DocCard/Heading';
|
|
12
|
+
import Description from '@theme/DocCard/Description';
|
|
13
|
+
import styles from './styles.module.css';
|
|
14
|
+
function Container({className, href, children}) {
|
|
15
|
+
return (
|
|
16
|
+
<Link
|
|
17
|
+
href={href}
|
|
18
|
+
className={clsx(
|
|
19
|
+
'card padding--lg',
|
|
20
|
+
ThemeClassNames.docs.docCard.container,
|
|
21
|
+
styles.cardContainer,
|
|
22
|
+
className,
|
|
23
|
+
)}>
|
|
24
|
+
{children}
|
|
25
|
+
</Link>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
export default function DocCardLayout({
|
|
29
|
+
item,
|
|
30
|
+
className,
|
|
31
|
+
href,
|
|
32
|
+
icon,
|
|
33
|
+
title,
|
|
34
|
+
description,
|
|
35
|
+
}) {
|
|
36
|
+
return (
|
|
37
|
+
<Container href={href} className={className}>
|
|
38
|
+
<Heading item={item} icon={icon} title={title} />
|
|
39
|
+
{description && <Description item={item} description={description} />}
|
|
40
|
+
</Container>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -5,88 +5,56 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
|
-
import clsx from 'clsx';
|
|
9
|
-
import Link from '@docusaurus/Link';
|
|
10
8
|
import {
|
|
11
9
|
useDocById,
|
|
12
10
|
findFirstSidebarItemLink,
|
|
13
11
|
} from '@docusaurus/plugin-content-docs/client';
|
|
14
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
extractLeadingEmoji,
|
|
14
|
+
useDocCardDescriptionCategoryItemsPlural,
|
|
15
|
+
} from '@docusaurus/theme-common/internal';
|
|
15
16
|
import isInternalUrl from '@docusaurus/isInternalUrl';
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
selectMessage(
|
|
23
|
-
count,
|
|
24
|
-
translate(
|
|
25
|
-
{
|
|
26
|
-
message: '1 item|{count} items',
|
|
27
|
-
id: 'theme.docs.DocCard.categoryDescription.plurals',
|
|
28
|
-
description:
|
|
29
|
-
'The default description for a category card in the generated index about how many items this category includes',
|
|
30
|
-
},
|
|
31
|
-
{count},
|
|
32
|
-
),
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
function CardContainer({className, href, children}) {
|
|
36
|
-
return (
|
|
37
|
-
<Link
|
|
38
|
-
href={href}
|
|
39
|
-
className={clsx('card padding--lg', styles.cardContainer, className)}>
|
|
40
|
-
{children}
|
|
41
|
-
</Link>
|
|
42
|
-
);
|
|
17
|
+
import Layout from '@theme/DocCard/Layout';
|
|
18
|
+
function getFallbackEmojiIcon(item) {
|
|
19
|
+
if (item.type === 'category') {
|
|
20
|
+
return '🗃';
|
|
21
|
+
}
|
|
22
|
+
return isInternalUrl(item.href) ? '📄️' : '🔗';
|
|
43
23
|
}
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{icon} {title}
|
|
52
|
-
</Heading>
|
|
53
|
-
{description && (
|
|
54
|
-
<p
|
|
55
|
-
className={clsx('text--truncate', styles.cardDescription)}
|
|
56
|
-
title={description}>
|
|
57
|
-
{description}
|
|
58
|
-
</p>
|
|
59
|
-
)}
|
|
60
|
-
</CardContainer>
|
|
61
|
-
);
|
|
24
|
+
function getIconTitleProps(item) {
|
|
25
|
+
const extracted = extractLeadingEmoji(item.label);
|
|
26
|
+
const emoji = extracted.emoji ?? getFallbackEmojiIcon(item);
|
|
27
|
+
return {
|
|
28
|
+
icon: emoji,
|
|
29
|
+
title: extracted.rest.trim(),
|
|
30
|
+
};
|
|
62
31
|
}
|
|
63
32
|
function CardCategory({item}) {
|
|
64
33
|
const href = findFirstSidebarItemLink(item);
|
|
65
|
-
const categoryItemsPlural =
|
|
34
|
+
const categoryItemsPlural = useDocCardDescriptionCategoryItemsPlural();
|
|
66
35
|
// Unexpected: categories that don't have a link have been filtered upfront
|
|
67
36
|
if (!href) {
|
|
68
37
|
return null;
|
|
69
38
|
}
|
|
70
39
|
return (
|
|
71
|
-
<
|
|
40
|
+
<Layout
|
|
41
|
+
item={item}
|
|
72
42
|
className={item.className}
|
|
73
43
|
href={href}
|
|
74
|
-
icon="🗃️"
|
|
75
|
-
title={item.label}
|
|
76
44
|
description={item.description ?? categoryItemsPlural(item.items.length)}
|
|
45
|
+
{...getIconTitleProps(item)}
|
|
77
46
|
/>
|
|
78
47
|
);
|
|
79
48
|
}
|
|
80
49
|
function CardLink({item}) {
|
|
81
|
-
const icon = isInternalUrl(item.href) ? '📄️' : '🔗';
|
|
82
50
|
const doc = useDocById(item.docId ?? undefined);
|
|
83
51
|
return (
|
|
84
|
-
<
|
|
52
|
+
<Layout
|
|
53
|
+
item={item}
|
|
85
54
|
className={item.className}
|
|
86
55
|
href={item.href}
|
|
87
|
-
icon={icon}
|
|
88
|
-
title={item.label}
|
|
89
56
|
description={item.description ?? doc?.description}
|
|
57
|
+
{...getIconTitleProps(item)}
|
|
90
58
|
/>
|
|
91
59
|
);
|
|
92
60
|
}
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
SkipToContentFallbackId,
|
|
13
13
|
ThemeClassNames,
|
|
14
14
|
} from '@docusaurus/theme-common';
|
|
15
|
-
import {useKeyboardNavigation} from '@docusaurus/theme-common/internal';
|
|
16
15
|
import SkipToContent from '@theme/SkipToContent';
|
|
17
16
|
import AnnouncementBar from '@theme/AnnouncementBar';
|
|
18
17
|
import Navbar from '@theme/Navbar';
|
|
@@ -29,7 +28,6 @@ export default function Layout(props) {
|
|
|
29
28
|
title,
|
|
30
29
|
description,
|
|
31
30
|
} = props;
|
|
32
|
-
useKeyboardNavigation();
|
|
33
31
|
return (
|
|
34
32
|
<LayoutProvider>
|
|
35
33
|
<PageMetadata title={title} description={description} />
|
|
@@ -12,7 +12,6 @@ import {PageMetadata, useThemeConfig} from '@docusaurus/theme-common';
|
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_SEARCH_TAG,
|
|
14
14
|
useAlternatePageUtils,
|
|
15
|
-
keyboardFocusedClassName,
|
|
16
15
|
} from '@docusaurus/theme-common/internal';
|
|
17
16
|
import {useLocation} from '@docusaurus/router';
|
|
18
17
|
import {applyTrailingSlash} from '@docusaurus/utils-common';
|
|
@@ -115,7 +114,7 @@ export default function SiteMetadata() {
|
|
|
115
114
|
<meta name="twitter:card" content="summary_large_image" />
|
|
116
115
|
{/* The keyboard focus class name need to be applied when SSR so links
|
|
117
116
|
are outlined when JS is disabled */}
|
|
118
|
-
<body
|
|
117
|
+
<body />
|
|
119
118
|
</Head>
|
|
120
119
|
|
|
121
120
|
{defaultImage && <PageMetadata image={defaultImage} />}
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import clsx from 'clsx';
|
|
9
|
+
import {useTabs} from '@docusaurus/theme-common/internal';
|
|
9
10
|
import styles from './styles.module.css';
|
|
10
|
-
|
|
11
|
+
function TabItemPanel({children, className, hidden}) {
|
|
11
12
|
return (
|
|
12
13
|
<div
|
|
13
14
|
role="tabpanel"
|
|
@@ -17,3 +18,16 @@ export default function TabItem({children, hidden, className}) {
|
|
|
17
18
|
</div>
|
|
18
19
|
);
|
|
19
20
|
}
|
|
21
|
+
export default function TabItem({children, className, value}) {
|
|
22
|
+
const {selectedValue, lazy} = useTabs();
|
|
23
|
+
const isSelected = value === selectedValue;
|
|
24
|
+
// TODO Docusaurus v4: use <Activity> ?
|
|
25
|
+
if (!isSelected && lazy) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return (
|
|
29
|
+
<TabItemPanel className={className} hidden={!isSelected}>
|
|
30
|
+
{children}
|
|
31
|
+
</TabItemPanel>
|
|
32
|
+
);
|
|
33
|
+
}
|
package/lib/theme/Tabs/index.js
CHANGED
|
@@ -4,17 +4,20 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import React
|
|
7
|
+
import React from 'react';
|
|
8
8
|
import clsx from 'clsx';
|
|
9
9
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
10
10
|
import {
|
|
11
11
|
useScrollPositionBlocker,
|
|
12
|
+
useTabsContextValue,
|
|
12
13
|
useTabs,
|
|
13
14
|
sanitizeTabsChildren,
|
|
15
|
+
TabsProvider,
|
|
14
16
|
} from '@docusaurus/theme-common/internal';
|
|
15
17
|
import useIsBrowser from '@docusaurus/useIsBrowser';
|
|
16
18
|
import styles from './styles.module.css';
|
|
17
|
-
function TabList({className
|
|
19
|
+
function TabList({className}) {
|
|
20
|
+
const {selectedValue, selectValue, tabValues, block} = useTabs();
|
|
18
21
|
const tabRefs = [];
|
|
19
22
|
const {blockElementScrollPositionUntilNextRender} =
|
|
20
23
|
useScrollPositionBlocker();
|
|
@@ -67,8 +70,8 @@ function TabList({className, block, selectedValue, selectValue, tabValues}) {
|
|
|
67
70
|
tabIndex={selectedValue === value ? 0 : -1}
|
|
68
71
|
aria-selected={selectedValue === value}
|
|
69
72
|
key={value}
|
|
70
|
-
ref={(
|
|
71
|
-
tabRefs.push(
|
|
73
|
+
ref={(ref) => {
|
|
74
|
+
tabRefs.push(ref);
|
|
72
75
|
}}
|
|
73
76
|
onKeyDown={handleKeydown}
|
|
74
77
|
onClick={handleTabChange}
|
|
@@ -82,35 +85,10 @@ function TabList({className, block, selectedValue, selectValue, tabValues}) {
|
|
|
82
85
|
</ul>
|
|
83
86
|
);
|
|
84
87
|
}
|
|
85
|
-
function TabContent({
|
|
86
|
-
|
|
87
|
-
Boolean,
|
|
88
|
-
);
|
|
89
|
-
if (lazy) {
|
|
90
|
-
const selectedTabItem = childTabs.find(
|
|
91
|
-
(tabItem) => tabItem.props.value === selectedValue,
|
|
92
|
-
);
|
|
93
|
-
if (!selectedTabItem) {
|
|
94
|
-
// fail-safe or fail-fast? not sure what's best here
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
return cloneElement(selectedTabItem, {
|
|
98
|
-
className: clsx('margin-top--md', selectedTabItem.props.className),
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
return (
|
|
102
|
-
<div className="margin-top--md">
|
|
103
|
-
{childTabs.map((tabItem, i) =>
|
|
104
|
-
cloneElement(tabItem, {
|
|
105
|
-
key: i,
|
|
106
|
-
hidden: tabItem.props.value !== selectedValue,
|
|
107
|
-
}),
|
|
108
|
-
)}
|
|
109
|
-
</div>
|
|
110
|
-
);
|
|
88
|
+
function TabContent({children}) {
|
|
89
|
+
return <div className="margin-top--md">{children}</div>;
|
|
111
90
|
}
|
|
112
|
-
function
|
|
113
|
-
const tabs = useTabs(props);
|
|
91
|
+
function TabsContainer({className, children}) {
|
|
114
92
|
return (
|
|
115
93
|
<div
|
|
116
94
|
className={clsx(
|
|
@@ -120,20 +98,27 @@ function TabsComponent(props) {
|
|
|
120
98
|
'tabs-container',
|
|
121
99
|
styles.tabList,
|
|
122
100
|
)}>
|
|
123
|
-
<TabList
|
|
124
|
-
|
|
101
|
+
<TabList
|
|
102
|
+
// Surprising but historical
|
|
103
|
+
// className is applied on TabList, not on TabsContainer
|
|
104
|
+
className={className}
|
|
105
|
+
/>
|
|
106
|
+
<TabContent>{children}</TabContent>
|
|
125
107
|
</div>
|
|
126
108
|
);
|
|
127
109
|
}
|
|
128
110
|
export default function Tabs(props) {
|
|
129
111
|
const isBrowser = useIsBrowser();
|
|
112
|
+
const value = useTabsContextValue(props);
|
|
130
113
|
return (
|
|
131
|
-
<
|
|
114
|
+
<TabsProvider
|
|
115
|
+
value={value}
|
|
132
116
|
// Remount tabs after hydration
|
|
133
117
|
// Temporary fix for https://github.com/facebook/docusaurus/issues/5653
|
|
134
|
-
key={String(isBrowser)}
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
118
|
+
key={String(isBrowser)}>
|
|
119
|
+
<TabsContainer className={props.className}>
|
|
120
|
+
{sanitizeTabsChildren(props.children)}
|
|
121
|
+
</TabsContainer>
|
|
122
|
+
</TabsProvider>
|
|
138
123
|
);
|
|
139
124
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/theme-classic",
|
|
3
|
-
"version": "3.9.2-canary-
|
|
3
|
+
"version": "3.9.2-canary-6526",
|
|
4
4
|
"description": "Classic theme for Docusaurus",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/theme-classic.d.ts",
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
"copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@docusaurus/core": "3.9.2-canary-
|
|
24
|
-
"@docusaurus/logger": "3.9.2-canary-
|
|
25
|
-
"@docusaurus/mdx-loader": "3.9.2-canary-
|
|
26
|
-
"@docusaurus/module-type-aliases": "3.9.2-canary-
|
|
27
|
-
"@docusaurus/plugin-content-blog": "3.9.2-canary-
|
|
28
|
-
"@docusaurus/plugin-content-docs": "3.9.2-canary-
|
|
29
|
-
"@docusaurus/plugin-content-pages": "3.9.2-canary-
|
|
30
|
-
"@docusaurus/theme-common": "3.9.2-canary-
|
|
31
|
-
"@docusaurus/theme-translations": "3.9.2-canary-
|
|
32
|
-
"@docusaurus/types": "3.9.2-canary-
|
|
33
|
-
"@docusaurus/utils": "3.9.2-canary-
|
|
34
|
-
"@docusaurus/utils-common": "3.9.2-canary-
|
|
35
|
-
"@docusaurus/utils-validation": "3.9.2-canary-
|
|
23
|
+
"@docusaurus/core": "3.9.2-canary-6526",
|
|
24
|
+
"@docusaurus/logger": "3.9.2-canary-6526",
|
|
25
|
+
"@docusaurus/mdx-loader": "3.9.2-canary-6526",
|
|
26
|
+
"@docusaurus/module-type-aliases": "3.9.2-canary-6526",
|
|
27
|
+
"@docusaurus/plugin-content-blog": "3.9.2-canary-6526",
|
|
28
|
+
"@docusaurus/plugin-content-docs": "3.9.2-canary-6526",
|
|
29
|
+
"@docusaurus/plugin-content-pages": "3.9.2-canary-6526",
|
|
30
|
+
"@docusaurus/theme-common": "3.9.2-canary-6526",
|
|
31
|
+
"@docusaurus/theme-translations": "3.9.2-canary-6526",
|
|
32
|
+
"@docusaurus/types": "3.9.2-canary-6526",
|
|
33
|
+
"@docusaurus/utils": "3.9.2-canary-6526",
|
|
34
|
+
"@docusaurus/utils-common": "3.9.2-canary-6526",
|
|
35
|
+
"@docusaurus/utils-validation": "3.9.2-canary-6526",
|
|
36
36
|
"@mdx-js/react": "^3.0.0",
|
|
37
37
|
"clsx": "^2.0.0",
|
|
38
38
|
"infima": "0.2.0-alpha.45",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"engines": {
|
|
61
61
|
"node": ">=20.0"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "a37ae138931cb80b31664f86a34f97671c00e409"
|
|
64
64
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
11
|
+
import type {Props} from '@theme/DocCard/Description';
|
|
12
|
+
|
|
13
|
+
import styles from './styles.module.css';
|
|
14
|
+
|
|
15
|
+
export default function DocCardDescription({description}: Props): ReactNode {
|
|
16
|
+
return (
|
|
17
|
+
<p
|
|
18
|
+
className={clsx(
|
|
19
|
+
'text--truncate',
|
|
20
|
+
ThemeClassNames.docs.docCard.description,
|
|
21
|
+
styles.cardDescription,
|
|
22
|
+
)}
|
|
23
|
+
title={description}>
|
|
24
|
+
{description}
|
|
25
|
+
</p>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
11
|
+
import type {Props} from '@theme/DocCard/Heading/Icon';
|
|
12
|
+
|
|
13
|
+
import styles from './styles.module.css';
|
|
14
|
+
|
|
15
|
+
export default function DocCardHeadingIcon({icon}: Props): ReactNode {
|
|
16
|
+
return (
|
|
17
|
+
<span
|
|
18
|
+
className={clsx(ThemeClassNames.docs.docCard.icon, styles.cardTitleIcon)}>
|
|
19
|
+
{icon}
|
|
20
|
+
</span>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.cardTitleIcon {
|
|
9
|
+
font-size: 1.6rem;
|
|
10
|
+
margin-right: 0.6rem;
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
11
|
+
import type {Props} from '@theme/DocCard/Heading/Text';
|
|
12
|
+
|
|
13
|
+
import styles from './styles.module.css';
|
|
14
|
+
|
|
15
|
+
export default function DocCardHeadingText({title}: Props): ReactNode {
|
|
16
|
+
return (
|
|
17
|
+
<span
|
|
18
|
+
className={clsx(
|
|
19
|
+
'text--truncate',
|
|
20
|
+
|
|
21
|
+
ThemeClassNames.docs.docCard.title,
|
|
22
|
+
styles.cardTitleText,
|
|
23
|
+
)}>
|
|
24
|
+
{title}
|
|
25
|
+
</span>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
11
|
+
import Heading from '@theme/Heading';
|
|
12
|
+
import Icon from '@theme/DocCard/Heading/Icon';
|
|
13
|
+
import Text from '@theme/DocCard/Heading/Text';
|
|
14
|
+
import type {Props} from '@theme/DocCard/Heading';
|
|
15
|
+
|
|
16
|
+
import styles from './styles.module.css';
|
|
17
|
+
|
|
18
|
+
export default function DocCardHeading({item, title, icon}: Props): ReactNode {
|
|
19
|
+
return (
|
|
20
|
+
<Heading
|
|
21
|
+
as="h2"
|
|
22
|
+
className={clsx(ThemeClassNames.docs.docCard.heading, styles.cardTitle)}
|
|
23
|
+
title={title}>
|
|
24
|
+
{icon && <Icon item={item} icon={icon} />}
|
|
25
|
+
<Text item={item} title={title} />
|
|
26
|
+
</Heading>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.cardTitle {
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import Link from '@docusaurus/Link';
|
|
11
|
+
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
12
|
+
import Heading from '@theme/DocCard/Heading';
|
|
13
|
+
import Description from '@theme/DocCard/Description';
|
|
14
|
+
import type {Props} from '@theme/DocCard/Layout';
|
|
15
|
+
|
|
16
|
+
import styles from './styles.module.css';
|
|
17
|
+
|
|
18
|
+
function Container({
|
|
19
|
+
className,
|
|
20
|
+
href,
|
|
21
|
+
children,
|
|
22
|
+
}: {
|
|
23
|
+
className?: string;
|
|
24
|
+
href: string;
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
}): ReactNode {
|
|
27
|
+
return (
|
|
28
|
+
<Link
|
|
29
|
+
href={href}
|
|
30
|
+
className={clsx(
|
|
31
|
+
'card padding--lg',
|
|
32
|
+
ThemeClassNames.docs.docCard.container,
|
|
33
|
+
styles.cardContainer,
|
|
34
|
+
className,
|
|
35
|
+
)}>
|
|
36
|
+
{children}
|
|
37
|
+
</Link>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default function DocCardLayout({
|
|
42
|
+
item,
|
|
43
|
+
className,
|
|
44
|
+
href,
|
|
45
|
+
icon,
|
|
46
|
+
title,
|
|
47
|
+
description,
|
|
48
|
+
}: Props): ReactNode {
|
|
49
|
+
return (
|
|
50
|
+
<Container href={href} className={className}>
|
|
51
|
+
<Heading item={item} icon={icon} title={title} />
|
|
52
|
+
{description && <Description item={item} description={description} />}
|
|
53
|
+
</Container>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
@@ -6,122 +6,71 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import React, {type ReactNode} from 'react';
|
|
9
|
-
import clsx from 'clsx';
|
|
10
|
-
import Link from '@docusaurus/Link';
|
|
11
9
|
import {
|
|
12
10
|
useDocById,
|
|
13
11
|
findFirstSidebarItemLink,
|
|
14
12
|
} from '@docusaurus/plugin-content-docs/client';
|
|
15
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
extractLeadingEmoji,
|
|
15
|
+
useDocCardDescriptionCategoryItemsPlural,
|
|
16
|
+
} from '@docusaurus/theme-common/internal';
|
|
16
17
|
import isInternalUrl from '@docusaurus/isInternalUrl';
|
|
17
|
-
import
|
|
18
|
+
import Layout from '@theme/DocCard/Layout';
|
|
18
19
|
|
|
19
20
|
import type {Props} from '@theme/DocCard';
|
|
20
|
-
import Heading from '@theme/Heading';
|
|
21
21
|
import type {
|
|
22
22
|
PropSidebarItemCategory,
|
|
23
23
|
PropSidebarItemLink,
|
|
24
24
|
} from '@docusaurus/plugin-content-docs';
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
translate(
|
|
34
|
-
{
|
|
35
|
-
message: '1 item|{count} items',
|
|
36
|
-
id: 'theme.docs.DocCard.categoryDescription.plurals',
|
|
37
|
-
description:
|
|
38
|
-
'The default description for a category card in the generated index about how many items this category includes',
|
|
39
|
-
},
|
|
40
|
-
{count},
|
|
41
|
-
),
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function CardContainer({
|
|
46
|
-
className,
|
|
47
|
-
href,
|
|
48
|
-
children,
|
|
49
|
-
}: {
|
|
50
|
-
className?: string;
|
|
51
|
-
href: string;
|
|
52
|
-
children: ReactNode;
|
|
53
|
-
}): ReactNode {
|
|
54
|
-
return (
|
|
55
|
-
<Link
|
|
56
|
-
href={href}
|
|
57
|
-
className={clsx('card padding--lg', styles.cardContainer, className)}>
|
|
58
|
-
{children}
|
|
59
|
-
</Link>
|
|
60
|
-
);
|
|
26
|
+
function getFallbackEmojiIcon(
|
|
27
|
+
item: PropSidebarItemLink | PropSidebarItemCategory,
|
|
28
|
+
): string {
|
|
29
|
+
if (item.type === 'category') {
|
|
30
|
+
return '🗃';
|
|
31
|
+
}
|
|
32
|
+
return isInternalUrl(item.href) ? '📄️' : '🔗';
|
|
61
33
|
}
|
|
62
34
|
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
icon: ReactNode;
|
|
73
|
-
title: string;
|
|
74
|
-
description?: string;
|
|
75
|
-
}): ReactNode {
|
|
76
|
-
return (
|
|
77
|
-
<CardContainer href={href} className={className}>
|
|
78
|
-
<Heading
|
|
79
|
-
as="h2"
|
|
80
|
-
className={clsx('text--truncate', styles.cardTitle)}
|
|
81
|
-
title={title}>
|
|
82
|
-
{icon} {title}
|
|
83
|
-
</Heading>
|
|
84
|
-
{description && (
|
|
85
|
-
<p
|
|
86
|
-
className={clsx('text--truncate', styles.cardDescription)}
|
|
87
|
-
title={description}>
|
|
88
|
-
{description}
|
|
89
|
-
</p>
|
|
90
|
-
)}
|
|
91
|
-
</CardContainer>
|
|
92
|
-
);
|
|
35
|
+
function getIconTitleProps(
|
|
36
|
+
item: PropSidebarItemLink | PropSidebarItemCategory,
|
|
37
|
+
): {icon: ReactNode; title: string} {
|
|
38
|
+
const extracted = extractLeadingEmoji(item.label);
|
|
39
|
+
const emoji = extracted.emoji ?? getFallbackEmojiIcon(item);
|
|
40
|
+
return {
|
|
41
|
+
icon: emoji,
|
|
42
|
+
title: extracted.rest.trim(),
|
|
43
|
+
};
|
|
93
44
|
}
|
|
94
45
|
|
|
95
46
|
function CardCategory({item}: {item: PropSidebarItemCategory}): ReactNode {
|
|
96
47
|
const href = findFirstSidebarItemLink(item);
|
|
97
|
-
const categoryItemsPlural =
|
|
48
|
+
const categoryItemsPlural = useDocCardDescriptionCategoryItemsPlural();
|
|
98
49
|
|
|
99
50
|
// Unexpected: categories that don't have a link have been filtered upfront
|
|
100
51
|
if (!href) {
|
|
101
52
|
return null;
|
|
102
53
|
}
|
|
103
|
-
|
|
104
54
|
return (
|
|
105
|
-
<
|
|
55
|
+
<Layout
|
|
56
|
+
item={item}
|
|
106
57
|
className={item.className}
|
|
107
58
|
href={href}
|
|
108
|
-
icon="🗃️"
|
|
109
|
-
title={item.label}
|
|
110
59
|
description={item.description ?? categoryItemsPlural(item.items.length)}
|
|
60
|
+
{...getIconTitleProps(item)}
|
|
111
61
|
/>
|
|
112
62
|
);
|
|
113
63
|
}
|
|
114
64
|
|
|
115
65
|
function CardLink({item}: {item: PropSidebarItemLink}): ReactNode {
|
|
116
|
-
const icon = isInternalUrl(item.href) ? '📄️' : '🔗';
|
|
117
66
|
const doc = useDocById(item.docId ?? undefined);
|
|
118
67
|
return (
|
|
119
|
-
<
|
|
68
|
+
<Layout
|
|
69
|
+
item={item}
|
|
120
70
|
className={item.className}
|
|
121
71
|
href={item.href}
|
|
122
|
-
icon={icon}
|
|
123
|
-
title={item.label}
|
|
124
72
|
description={item.description ?? doc?.description}
|
|
73
|
+
{...getIconTitleProps(item)}
|
|
125
74
|
/>
|
|
126
75
|
);
|
|
127
76
|
}
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
SkipToContentFallbackId,
|
|
14
14
|
ThemeClassNames,
|
|
15
15
|
} from '@docusaurus/theme-common';
|
|
16
|
-
import {useKeyboardNavigation} from '@docusaurus/theme-common/internal';
|
|
17
16
|
import SkipToContent from '@theme/SkipToContent';
|
|
18
17
|
import AnnouncementBar from '@theme/AnnouncementBar';
|
|
19
18
|
import Navbar from '@theme/Navbar';
|
|
@@ -33,8 +32,6 @@ export default function Layout(props: Props): ReactNode {
|
|
|
33
32
|
description,
|
|
34
33
|
} = props;
|
|
35
34
|
|
|
36
|
-
useKeyboardNavigation();
|
|
37
|
-
|
|
38
35
|
return (
|
|
39
36
|
<LayoutProvider>
|
|
40
37
|
<PageMetadata title={title} description={description} />
|
|
@@ -13,7 +13,6 @@ import {PageMetadata, useThemeConfig} from '@docusaurus/theme-common';
|
|
|
13
13
|
import {
|
|
14
14
|
DEFAULT_SEARCH_TAG,
|
|
15
15
|
useAlternatePageUtils,
|
|
16
|
-
keyboardFocusedClassName,
|
|
17
16
|
} from '@docusaurus/theme-common/internal';
|
|
18
17
|
import {useLocation} from '@docusaurus/router';
|
|
19
18
|
import {applyTrailingSlash} from '@docusaurus/utils-common';
|
|
@@ -130,7 +129,7 @@ export default function SiteMetadata(): ReactNode {
|
|
|
130
129
|
<meta name="twitter:card" content="summary_large_image" />
|
|
131
130
|
{/* The keyboard focus class name need to be applied when SSR so links
|
|
132
131
|
are outlined when JS is disabled */}
|
|
133
|
-
<body
|
|
132
|
+
<body />
|
|
134
133
|
</Head>
|
|
135
134
|
|
|
136
135
|
{defaultImage && <PageMetadata image={defaultImage} />}
|
|
@@ -7,15 +7,20 @@
|
|
|
7
7
|
|
|
8
8
|
import React, {type ReactNode} from 'react';
|
|
9
9
|
import clsx from 'clsx';
|
|
10
|
+
import {useTabs} from '@docusaurus/theme-common/internal';
|
|
10
11
|
import type {Props} from '@theme/TabItem';
|
|
11
12
|
|
|
12
13
|
import styles from './styles.module.css';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
function TabItemPanel({
|
|
15
16
|
children,
|
|
16
|
-
hidden,
|
|
17
17
|
className,
|
|
18
|
-
|
|
18
|
+
hidden,
|
|
19
|
+
}: {
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
className?: string;
|
|
22
|
+
hidden?: boolean;
|
|
23
|
+
}) {
|
|
19
24
|
return (
|
|
20
25
|
<div
|
|
21
26
|
role="tabpanel"
|
|
@@ -25,3 +30,23 @@ export default function TabItem({
|
|
|
25
30
|
</div>
|
|
26
31
|
);
|
|
27
32
|
}
|
|
33
|
+
|
|
34
|
+
export default function TabItem({
|
|
35
|
+
children,
|
|
36
|
+
className,
|
|
37
|
+
value,
|
|
38
|
+
}: Props): ReactNode {
|
|
39
|
+
const {selectedValue, lazy} = useTabs();
|
|
40
|
+
const isSelected = value === selectedValue;
|
|
41
|
+
|
|
42
|
+
// TODO Docusaurus v4: use <Activity> ?
|
|
43
|
+
if (!isSelected && lazy) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<TabItemPanel className={className} hidden={!isSelected}>
|
|
49
|
+
{children}
|
|
50
|
+
</TabItemPanel>
|
|
51
|
+
);
|
|
52
|
+
}
|
package/src/theme/Tabs/index.tsx
CHANGED
|
@@ -5,26 +5,23 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React, {
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
9
|
import clsx from 'clsx';
|
|
10
10
|
import {ThemeClassNames} from '@docusaurus/theme-common';
|
|
11
11
|
import {
|
|
12
12
|
useScrollPositionBlocker,
|
|
13
|
+
useTabsContextValue,
|
|
13
14
|
useTabs,
|
|
14
15
|
sanitizeTabsChildren,
|
|
15
|
-
|
|
16
|
+
TabsProvider,
|
|
16
17
|
} from '@docusaurus/theme-common/internal';
|
|
17
18
|
import useIsBrowser from '@docusaurus/useIsBrowser';
|
|
18
19
|
import type {Props} from '@theme/Tabs';
|
|
19
20
|
import styles from './styles.module.css';
|
|
20
21
|
|
|
21
|
-
function TabList({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
selectedValue,
|
|
25
|
-
selectValue,
|
|
26
|
-
tabValues,
|
|
27
|
-
}: Props & ReturnType<typeof useTabs>) {
|
|
22
|
+
function TabList({className}: {className?: string}) {
|
|
23
|
+
const {selectedValue, selectValue, tabValues, block} = useTabs();
|
|
24
|
+
|
|
28
25
|
const tabRefs: (HTMLLIElement | null)[] = [];
|
|
29
26
|
const {blockElementScrollPositionUntilNextRender} =
|
|
30
27
|
useScrollPositionBlocker();
|
|
@@ -88,8 +85,8 @@ function TabList({
|
|
|
88
85
|
tabIndex={selectedValue === value ? 0 : -1}
|
|
89
86
|
aria-selected={selectedValue === value}
|
|
90
87
|
key={value}
|
|
91
|
-
ref={(
|
|
92
|
-
tabRefs.push(
|
|
88
|
+
ref={(ref) => {
|
|
89
|
+
tabRefs.push(ref);
|
|
93
90
|
}}
|
|
94
91
|
onKeyDown={handleKeydown}
|
|
95
92
|
onClick={handleTabChange}
|
|
@@ -109,40 +106,17 @@ function TabList({
|
|
|
109
106
|
);
|
|
110
107
|
}
|
|
111
108
|
|
|
112
|
-
function TabContent({
|
|
113
|
-
|
|
114
|
-
children,
|
|
115
|
-
selectedValue,
|
|
116
|
-
}: Props & ReturnType<typeof useTabs>) {
|
|
117
|
-
const childTabs = (Array.isArray(children) ? children : [children]).filter(
|
|
118
|
-
Boolean,
|
|
119
|
-
) as ReactElement<TabItemProps>[];
|
|
120
|
-
if (lazy) {
|
|
121
|
-
const selectedTabItem = childTabs.find(
|
|
122
|
-
(tabItem) => tabItem.props.value === selectedValue,
|
|
123
|
-
);
|
|
124
|
-
if (!selectedTabItem) {
|
|
125
|
-
// fail-safe or fail-fast? not sure what's best here
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
return cloneElement(selectedTabItem, {
|
|
129
|
-
className: clsx('margin-top--md', selectedTabItem.props.className),
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
return (
|
|
133
|
-
<div className="margin-top--md">
|
|
134
|
-
{childTabs.map((tabItem, i) =>
|
|
135
|
-
cloneElement(tabItem, {
|
|
136
|
-
key: i,
|
|
137
|
-
hidden: tabItem.props.value !== selectedValue,
|
|
138
|
-
}),
|
|
139
|
-
)}
|
|
140
|
-
</div>
|
|
141
|
-
);
|
|
109
|
+
function TabContent({children}: {children: ReactNode}) {
|
|
110
|
+
return <div className="margin-top--md">{children}</div>;
|
|
142
111
|
}
|
|
143
112
|
|
|
144
|
-
function
|
|
145
|
-
|
|
113
|
+
function TabsContainer({
|
|
114
|
+
className,
|
|
115
|
+
children,
|
|
116
|
+
}: {
|
|
117
|
+
className?: string;
|
|
118
|
+
children: ReactNode;
|
|
119
|
+
}): ReactNode {
|
|
146
120
|
return (
|
|
147
121
|
<div
|
|
148
122
|
className={clsx(
|
|
@@ -152,21 +126,28 @@ function TabsComponent(props: Props): ReactNode {
|
|
|
152
126
|
'tabs-container',
|
|
153
127
|
styles.tabList,
|
|
154
128
|
)}>
|
|
155
|
-
<TabList
|
|
156
|
-
|
|
129
|
+
<TabList
|
|
130
|
+
// Surprising but historical
|
|
131
|
+
// className is applied on TabList, not on TabsContainer
|
|
132
|
+
className={className}
|
|
133
|
+
/>
|
|
134
|
+
<TabContent>{children}</TabContent>
|
|
157
135
|
</div>
|
|
158
136
|
);
|
|
159
137
|
}
|
|
160
138
|
|
|
161
139
|
export default function Tabs(props: Props): ReactNode {
|
|
162
140
|
const isBrowser = useIsBrowser();
|
|
141
|
+
const value = useTabsContextValue(props);
|
|
163
142
|
return (
|
|
164
|
-
<
|
|
143
|
+
<TabsProvider
|
|
144
|
+
value={value}
|
|
165
145
|
// Remount tabs after hydration
|
|
166
146
|
// Temporary fix for https://github.com/facebook/docusaurus/issues/5653
|
|
167
|
-
key={String(isBrowser)}
|
|
168
|
-
{
|
|
169
|
-
|
|
170
|
-
|
|
147
|
+
key={String(isBrowser)}>
|
|
148
|
+
<TabsContainer className={props.className}>
|
|
149
|
+
{sanitizeTabsChildren(props.children)}
|
|
150
|
+
</TabsContainer>
|
|
151
|
+
</TabsProvider>
|
|
171
152
|
);
|
|
172
153
|
}
|
package/src/theme-classic.d.ts
CHANGED
|
@@ -582,6 +582,71 @@ declare module '@theme/DocCard' {
|
|
|
582
582
|
export default function DocCard(props: Props): ReactNode;
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
+
declare module '@theme/DocCard/Heading' {
|
|
586
|
+
import type {ReactNode} from 'react';
|
|
587
|
+
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';
|
|
588
|
+
|
|
589
|
+
export interface Props {
|
|
590
|
+
readonly item: PropSidebarItem;
|
|
591
|
+
readonly icon: ReactNode;
|
|
592
|
+
readonly title: string;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
export default function DocCardHeading(props: Props): ReactNode;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
declare module '@theme/DocCard/Heading/Icon' {
|
|
599
|
+
import type {ReactNode} from 'react';
|
|
600
|
+
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';
|
|
601
|
+
|
|
602
|
+
export interface Props {
|
|
603
|
+
readonly item: PropSidebarItem;
|
|
604
|
+
readonly icon: ReactNode;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export default function DocCardHeadingIcon(props: Props): ReactNode;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
declare module '@theme/DocCard/Heading/Text' {
|
|
611
|
+
import type {ReactNode} from 'react';
|
|
612
|
+
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';
|
|
613
|
+
|
|
614
|
+
export interface Props {
|
|
615
|
+
readonly item: PropSidebarItem;
|
|
616
|
+
readonly title: string;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export default function DocCardHeadingText(props: Props): ReactNode;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
declare module '@theme/DocCard/Description' {
|
|
623
|
+
import type {ReactNode} from 'react';
|
|
624
|
+
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';
|
|
625
|
+
|
|
626
|
+
export interface Props {
|
|
627
|
+
readonly item: PropSidebarItem;
|
|
628
|
+
readonly description: string;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
export default function DocCardDescription(props: Props): ReactNode;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
declare module '@theme/DocCard/Layout' {
|
|
635
|
+
import type {ReactNode} from 'react';
|
|
636
|
+
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';
|
|
637
|
+
|
|
638
|
+
export interface Props {
|
|
639
|
+
readonly item: PropSidebarItem;
|
|
640
|
+
readonly className?: string;
|
|
641
|
+
readonly href: string;
|
|
642
|
+
readonly icon: ReactNode;
|
|
643
|
+
readonly title: string;
|
|
644
|
+
readonly description?: string;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
export default function DocCardLayout(props: Props): ReactNode;
|
|
648
|
+
}
|
|
649
|
+
|
|
585
650
|
declare module '@theme/DocCardList' {
|
|
586
651
|
import type {ReactNode} from 'react';
|
|
587
652
|
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';
|