@docusaurus/theme-classic 3.7.0 → 3.8.0-canary-6324

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.
Files changed (136) hide show
  1. package/lib/getSwizzleConfig.js +1 -1
  2. package/lib/index.js +9 -0
  3. package/lib/inlineScripts.js +6 -27
  4. package/lib/inlineSvgSprites.d.ts +7 -0
  5. package/lib/inlineSvgSprites.js +14 -0
  6. package/lib/options.js +5 -0
  7. package/lib/theme/AnnouncementBar/index.js +6 -2
  8. package/lib/theme/CodeBlock/{WordWrapButton → Buttons/Button}/index.d.ts +2 -2
  9. package/lib/theme/CodeBlock/Buttons/Button/index.js +13 -0
  10. package/lib/theme/CodeBlock/Buttons/CopyButton/index.d.ts +9 -0
  11. package/lib/theme/CodeBlock/{CopyButton → Buttons/CopyButton}/index.js +36 -25
  12. package/lib/theme/CodeBlock/Buttons/WordWrapButton/index.d.ts +9 -0
  13. package/lib/theme/CodeBlock/{WordWrapButton → Buttons/WordWrapButton}/index.js +12 -7
  14. package/lib/theme/CodeBlock/{CopyButton → Buttons}/index.d.ts +2 -2
  15. package/lib/theme/CodeBlock/Buttons/index.js +27 -0
  16. package/lib/theme/CodeBlock/Buttons/styles.module.css +37 -0
  17. package/lib/theme/CodeBlock/Content/Element.js +4 -2
  18. package/lib/theme/CodeBlock/Content/String.d.ts +1 -1
  19. package/lib/theme/CodeBlock/Content/String.js +22 -92
  20. package/lib/theme/CodeBlock/Content/index.d.ts +9 -0
  21. package/lib/theme/CodeBlock/Content/index.js +74 -0
  22. package/lib/theme/CodeBlock/Content/styles.module.css +0 -52
  23. package/lib/theme/CodeBlock/Layout/index.d.ts +9 -0
  24. package/lib/theme/CodeBlock/Layout/index.js +30 -0
  25. package/lib/theme/CodeBlock/Layout/styles.module.css +27 -0
  26. package/lib/theme/CodeBlock/Line/Token/index.d.ts +9 -0
  27. package/lib/theme/CodeBlock/Line/Token/index.js +11 -0
  28. package/lib/theme/CodeBlock/Line/index.d.ts +1 -1
  29. package/lib/theme/CodeBlock/Line/index.js +21 -7
  30. package/lib/theme/CodeBlock/Title/index.d.ts +9 -0
  31. package/lib/theme/CodeBlock/Title/index.js +10 -0
  32. package/lib/theme/ColorModeToggle/index.d.ts +1 -1
  33. package/lib/theme/ColorModeToggle/index.js +85 -27
  34. package/lib/theme/ColorModeToggle/styles.module.css +7 -2
  35. package/lib/theme/DocBreadcrumbs/StructuredData/index.d.ts +9 -0
  36. package/lib/theme/DocBreadcrumbs/StructuredData/index.js +21 -0
  37. package/lib/theme/DocBreadcrumbs/index.js +36 -54
  38. package/lib/theme/DocCard/index.js +6 -4
  39. package/lib/theme/DocCardList/index.js +12 -6
  40. package/lib/theme/DocCardList/styles.module.css +14 -0
  41. package/lib/theme/DocCategoryGeneratedIndexPage/index.js +1 -1
  42. package/lib/theme/DocCategoryGeneratedIndexPage/styles.module.css +0 -8
  43. package/lib/theme/DocItem/Paginator/index.js +7 -1
  44. package/lib/theme/DocPaginator/index.js +3 -2
  45. package/lib/theme/DocSidebarItem/Category/index.js +8 -1
  46. package/lib/theme/Footer/Layout/index.js +2 -1
  47. package/lib/theme/Footer/Links/MultiColumn/index.js +7 -1
  48. package/lib/theme/Icon/ExternalLink/index.js +4 -5
  49. package/lib/theme/Icon/SystemColorMode/index.d.ts +9 -0
  50. package/lib/theme/Icon/SystemColorMode/index.js +16 -0
  51. package/lib/theme/Layout/index.js +1 -0
  52. package/lib/theme/Navbar/ColorModeToggle/index.js +5 -4
  53. package/lib/theme/Navbar/Content/index.js +20 -3
  54. package/lib/theme/Navbar/Content/styles.module.css +8 -0
  55. package/lib/theme/Navbar/Layout/index.js +2 -1
  56. package/lib/theme/Navbar/MobileSidebar/Layout/index.js +35 -4
  57. package/lib/theme/NavbarItem/DefaultNavbarItem/Desktop/index.d.ts +9 -0
  58. package/lib/theme/NavbarItem/DefaultNavbarItem/Desktop/index.js +29 -0
  59. package/lib/theme/NavbarItem/DefaultNavbarItem/Mobile/index.d.ts +9 -0
  60. package/lib/theme/NavbarItem/DefaultNavbarItem/Mobile/index.js +20 -0
  61. package/lib/theme/NavbarItem/DefaultNavbarItem/index.js +25 -0
  62. package/lib/theme/NavbarItem/DocsVersionDropdownNavbarItem.d.ts +1 -1
  63. package/lib/theme/NavbarItem/DocsVersionDropdownNavbarItem.js +50 -7
  64. package/lib/theme/NavbarItem/DropdownNavbarItem/Desktop/index.d.ts +9 -0
  65. package/lib/theme/NavbarItem/DropdownNavbarItem/Desktop/index.js +74 -0
  66. package/lib/theme/NavbarItem/DropdownNavbarItem/Mobile/index.d.ts +10 -0
  67. package/lib/theme/NavbarItem/DropdownNavbarItem/Mobile/index.js +142 -0
  68. package/lib/theme/NavbarItem/DropdownNavbarItem/index.js +3 -142
  69. package/lib/theme/Tag/index.js +1 -0
  70. package/lib/theme/ThemeProvider/TitleFormatter/index.d.ts +9 -0
  71. package/lib/theme/ThemeProvider/TitleFormatter/index.js +19 -0
  72. package/lib/theme/ThemeProvider/index.d.ts +9 -0
  73. package/lib/theme/ThemeProvider/index.js +11 -0
  74. package/package.json +15 -15
  75. package/src/getSwizzleConfig.ts +1 -1
  76. package/src/index.ts +9 -0
  77. package/src/inlineScripts.ts +6 -27
  78. package/src/inlineSvgSprites.ts +12 -0
  79. package/src/options.ts +15 -0
  80. package/src/theme/AnnouncementBar/index.tsx +6 -2
  81. package/src/theme/CodeBlock/Buttons/Button/index.tsx +19 -0
  82. package/src/theme/CodeBlock/{CopyButton → Buttons/CopyButton}/index.tsx +42 -26
  83. package/src/theme/CodeBlock/{WordWrapButton → Buttons/WordWrapButton}/index.tsx +15 -12
  84. package/src/theme/CodeBlock/Buttons/index.tsx +32 -0
  85. package/src/theme/CodeBlock/Buttons/styles.module.css +37 -0
  86. package/src/theme/CodeBlock/Content/Element.tsx +4 -2
  87. package/src/theme/CodeBlock/Content/String.tsx +24 -101
  88. package/src/theme/CodeBlock/Content/index.tsx +84 -0
  89. package/src/theme/CodeBlock/Content/styles.module.css +0 -52
  90. package/src/theme/CodeBlock/Layout/index.tsx +34 -0
  91. package/src/theme/CodeBlock/Layout/styles.module.css +27 -0
  92. package/src/theme/CodeBlock/Line/Token/index.tsx +18 -0
  93. package/src/theme/CodeBlock/Line/index.tsx +26 -7
  94. package/src/theme/CodeBlock/Title/index.tsx +15 -0
  95. package/src/theme/ColorModeToggle/index.tsx +102 -32
  96. package/src/theme/ColorModeToggle/styles.module.css +7 -2
  97. package/src/theme/DocBreadcrumbs/StructuredData/index.tsx +24 -0
  98. package/src/theme/DocBreadcrumbs/index.tsx +35 -57
  99. package/src/theme/DocCard/index.tsx +8 -2
  100. package/src/theme/DocCardList/index.tsx +18 -7
  101. package/src/theme/DocCardList/styles.module.css +14 -0
  102. package/src/theme/DocCategoryGeneratedIndexPage/index.tsx +1 -1
  103. package/src/theme/DocCategoryGeneratedIndexPage/styles.module.css +0 -8
  104. package/src/theme/DocItem/Paginator/index.tsx +7 -1
  105. package/src/theme/DocPaginator/index.tsx +3 -2
  106. package/src/theme/DocSidebarItem/Category/index.tsx +8 -1
  107. package/src/theme/Footer/Layout/index.tsx +2 -1
  108. package/src/theme/Footer/Links/MultiColumn/index.tsx +7 -1
  109. package/src/theme/Icon/ExternalLink/index.tsx +5 -5
  110. package/src/theme/Icon/SystemColorMode/index.tsx +20 -0
  111. package/src/theme/Layout/index.tsx +1 -0
  112. package/src/theme/Navbar/ColorModeToggle/index.tsx +5 -4
  113. package/src/theme/Navbar/Content/index.tsx +20 -3
  114. package/src/theme/Navbar/Content/styles.module.css +8 -0
  115. package/src/theme/Navbar/Layout/index.tsx +2 -1
  116. package/src/theme/Navbar/MobileSidebar/Layout/index.tsx +43 -4
  117. package/src/theme/NavbarItem/DefaultNavbarItem/Desktop/index.tsx +34 -0
  118. package/src/theme/NavbarItem/DefaultNavbarItem/Mobile/index.tsx +23 -0
  119. package/src/theme/NavbarItem/DefaultNavbarItem/index.tsx +28 -0
  120. package/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx +87 -9
  121. package/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.tsx +86 -0
  122. package/src/theme/NavbarItem/DropdownNavbarItem/Mobile/index.tsx +166 -0
  123. package/src/theme/NavbarItem/DropdownNavbarItem/index.tsx +4 -168
  124. package/src/theme/Tag/index.tsx +1 -0
  125. package/src/theme/ThemeProvider/TitleFormatter/index.tsx +27 -0
  126. package/src/theme/ThemeProvider/index.tsx +14 -0
  127. package/src/theme-classic.d.ts +175 -20
  128. package/lib/theme/NavbarItem/DefaultNavbarItem.js +0 -52
  129. package/src/theme/NavbarItem/DefaultNavbarItem.tsx +0 -66
  130. /package/lib/theme/CodeBlock/{CopyButton → Buttons/CopyButton}/styles.module.css +0 -0
  131. /package/lib/theme/CodeBlock/{WordWrapButton → Buttons/WordWrapButton}/styles.module.css +0 -0
  132. /package/lib/theme/NavbarItem/{DefaultNavbarItem.d.ts → DefaultNavbarItem/index.d.ts} +0 -0
  133. /package/lib/theme/NavbarItem/DropdownNavbarItem/{styles.module.css → Mobile/styles.module.css} +0 -0
  134. /package/src/theme/CodeBlock/{CopyButton → Buttons/CopyButton}/styles.module.css +0 -0
  135. /package/src/theme/CodeBlock/{WordWrapButton → Buttons/WordWrapButton}/styles.module.css +0 -0
  136. /package/src/theme/NavbarItem/DropdownNavbarItem/{styles.module.css → Mobile/styles.module.css} +0 -0
@@ -9,10 +9,6 @@
9
9
  .generatedIndexPage {
10
10
  max-width: 75% !important;
11
11
  }
12
-
13
- .list article:nth-last-child(-n + 2) {
14
- margin-bottom: 0 !important;
15
- }
16
12
  }
17
13
 
18
14
  /* Duplicated from .markdown h1 */
@@ -20,7 +16,3 @@
20
16
  --ifm-h1-font-size: 3rem;
21
17
  margin-bottom: calc(1.25 * var(--ifm-leading));
22
18
  }
23
-
24
- .list article:last-child {
25
- margin-bottom: 0 !important;
26
- }
@@ -13,5 +13,11 @@ import DocPaginator from '@theme/DocPaginator';
13
13
  */
14
14
  export default function DocItemPaginator() {
15
15
  const {metadata} = useDoc();
16
- return <DocPaginator previous={metadata.previous} next={metadata.next} />;
16
+ return (
17
+ <DocPaginator
18
+ className="docusaurus-mt-lg"
19
+ previous={metadata.previous}
20
+ next={metadata.next}
21
+ />
22
+ );
17
23
  }
@@ -5,13 +5,14 @@
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';
8
9
  import Translate, {translate} from '@docusaurus/Translate';
9
10
  import PaginatorNavLink from '@theme/PaginatorNavLink';
10
11
  export default function DocPaginator(props) {
11
- const {previous, next} = props;
12
+ const {className, previous, next} = props;
12
13
  return (
13
14
  <nav
14
- className="pagination-nav docusaurus-mt-lg"
15
+ className={clsx(className, 'pagination-nav')}
15
16
  aria-label={translate({
16
17
  id: 'theme.docs.paginator.navAriaLabel',
17
18
  message: 'Docs pages',
@@ -155,7 +155,14 @@ export default function DocSidebarItemCategory({
155
155
  ? (e) => {
156
156
  onItemClick?.(item);
157
157
  if (href) {
158
- updateCollapsed(false);
158
+ if (isActive) {
159
+ e.preventDefault();
160
+ updateCollapsed();
161
+ } else {
162
+ // When navigating to a new category, we always expand
163
+ // see https://github.com/facebook/docusaurus/issues/10854#issuecomment-2609616182
164
+ updateCollapsed(false);
165
+ }
159
166
  } else {
160
167
  e.preventDefault();
161
168
  updateCollapsed();
@@ -6,10 +6,11 @@
6
6
  */
7
7
  import React from 'react';
8
8
  import clsx from 'clsx';
9
+ import {ThemeClassNames} from '@docusaurus/theme-common';
9
10
  export default function FooterLayout({style, links, logo, copyright}) {
10
11
  return (
11
12
  <footer
12
- className={clsx('footer', {
13
+ className={clsx(ThemeClassNames.layout.footer.container, 'footer', {
13
14
  'footer--dark': style === 'dark',
14
15
  })}>
15
16
  <div className="container container-fluid">
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import React from 'react';
8
8
  import clsx from 'clsx';
9
+ import {ThemeClassNames} from '@docusaurus/theme-common';
9
10
  import LinkItem from '@theme/Footer/LinkItem';
10
11
  function ColumnLinkItem({item}) {
11
12
  return item.html ? (
@@ -23,7 +24,12 @@ function ColumnLinkItem({item}) {
23
24
  }
24
25
  function Column({column}) {
25
26
  return (
26
- <div className={clsx('col footer__col', column.className)}>
27
+ <div
28
+ className={clsx(
29
+ ThemeClassNames.layout.footer.column,
30
+ 'col footer__col',
31
+ column.className,
32
+ )}>
27
33
  <div className="footer__title">{column.title}</div>
28
34
  <ul className="footer__items clean-list">
29
35
  {column.items.map((item, i) => (
@@ -6,18 +6,17 @@
6
6
  */
7
7
  import React from 'react';
8
8
  import styles from './styles.module.css';
9
+ // References symbol in docusaurus-theme-classic/src/inlineSvgSprites.ts
10
+ // See why: https://github.com/facebook/docusaurus/issues/5865
11
+ const svgSprite = '#theme-svg-external-link';
9
12
  export default function IconExternalLink({width = 13.5, height = 13.5}) {
10
13
  return (
11
14
  <svg
12
15
  width={width}
13
16
  height={height}
14
17
  aria-hidden="true"
15
- viewBox="0 0 24 24"
16
18
  className={styles.iconExternalLink}>
17
- <path
18
- fill="currentColor"
19
- d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
20
- />
19
+ <use href={svgSprite} />
21
20
  </svg>
22
21
  );
23
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/Icon/SystemColorMode';
9
+ export default function IconSystemColorMode(props: Props): ReactNode;
@@ -0,0 +1,16 @@
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
+ export default function IconSystemColorMode(props) {
8
+ return (
9
+ <svg viewBox="0 0 24 24" width={24} height={24} {...props}>
10
+ <path
11
+ fill="currentColor"
12
+ d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"
13
+ />
14
+ </svg>
15
+ );
16
+ }
@@ -43,6 +43,7 @@ export default function Layout(props) {
43
43
  <div
44
44
  id={SkipToContentFallbackId}
45
45
  className={clsx(
46
+ ThemeClassNames.layout.main.container,
46
47
  ThemeClassNames.wrapper.main,
47
48
  styles.mainWrapper,
48
49
  wrapperClassName,
@@ -10,9 +10,9 @@ import ColorModeToggle from '@theme/ColorModeToggle';
10
10
  import styles from './styles.module.css';
11
11
  export default function NavbarColorModeToggle({className}) {
12
12
  const navbarStyle = useThemeConfig().navbar.style;
13
- const disabled = useThemeConfig().colorMode.disableSwitch;
14
- const {colorMode, setColorMode} = useColorMode();
15
- if (disabled) {
13
+ const {disableSwitch, respectPrefersColorScheme} = useThemeConfig().colorMode;
14
+ const {colorModeChoice, setColorMode} = useColorMode();
15
+ if (disableSwitch) {
16
16
  return null;
17
17
  }
18
18
  return (
@@ -21,7 +21,8 @@ export default function NavbarColorModeToggle({className}) {
21
21
  buttonClassName={
22
22
  navbarStyle === 'dark' ? styles.darkNavbarColorModeToggle : undefined
23
23
  }
24
- value={colorMode}
24
+ respectPrefersColorScheme={respectPrefersColorScheme}
25
+ value={colorModeChoice}
25
26
  onChange={setColorMode}
26
27
  />
27
28
  );
@@ -5,7 +5,12 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React from 'react';
8
- import {useThemeConfig, ErrorCauseBoundary} from '@docusaurus/theme-common';
8
+ import clsx from 'clsx';
9
+ import {
10
+ useThemeConfig,
11
+ ErrorCauseBoundary,
12
+ ThemeClassNames,
13
+ } from '@docusaurus/theme-common';
9
14
  import {
10
15
  splitNavbarItems,
11
16
  useNavbarMobileSidebar,
@@ -44,8 +49,20 @@ ${JSON.stringify(item, null, 2)}`,
44
49
  function NavbarContentLayout({left, right}) {
45
50
  return (
46
51
  <div className="navbar__inner">
47
- <div className="navbar__items">{left}</div>
48
- <div className="navbar__items navbar__items--right">{right}</div>
52
+ <div
53
+ className={clsx(
54
+ ThemeClassNames.layout.navbar.containerLeft,
55
+ 'navbar__items',
56
+ )}>
57
+ {left}
58
+ </div>
59
+ <div
60
+ className={clsx(
61
+ ThemeClassNames.layout.navbar.containerRight,
62
+ 'navbar__items navbar__items--right',
63
+ )}>
64
+ {right}
65
+ </div>
49
66
  </div>
50
67
  );
51
68
  }
@@ -13,3 +13,11 @@ Hide color mode toggle in small viewports
13
13
  display: none;
14
14
  }
15
15
  }
16
+
17
+ /*
18
+ Restore some Infima style that broke with CSS Cascade Layers
19
+ See https://github.com/facebook/docusaurus/pull/11142
20
+ */
21
+ :global(.navbar__items--right) > :last-child {
22
+ padding-right: 0;
23
+ }
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import React from 'react';
8
8
  import clsx from 'clsx';
9
- import {useThemeConfig} from '@docusaurus/theme-common';
9
+ import {ThemeClassNames, useThemeConfig} from '@docusaurus/theme-common';
10
10
  import {
11
11
  useHideableNavbar,
12
12
  useNavbarMobileSidebar,
@@ -38,6 +38,7 @@ export default function NavbarLayout({children}) {
38
38
  description: 'The ARIA label for the main navigation',
39
39
  })}
40
40
  className={clsx(
41
+ ThemeClassNames.layout.navbar.container,
41
42
  'navbar',
42
43
  'navbar--fixed-top',
43
44
  hideOnScroll && [
@@ -4,9 +4,32 @@
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 from 'react';
7
+ import React, {version} from 'react';
8
8
  import clsx from 'clsx';
9
9
  import {useNavbarSecondaryMenu} from '@docusaurus/theme-common/internal';
10
+ import {ThemeClassNames} from '@docusaurus/theme-common';
11
+ // TODO Docusaurus v4: remove temporary inert workaround
12
+ // See https://github.com/facebook/react/issues/17157
13
+ // See https://github.com/radix-ui/themes/pull/509
14
+ function inertProps(inert) {
15
+ const isBeforeReact19 = parseInt(version.split('.')[0], 10) < 19;
16
+ if (isBeforeReact19) {
17
+ return {inert: inert ? '' : undefined};
18
+ }
19
+ return {inert};
20
+ }
21
+ function NavbarMobileSidebarPanel({children, inert}) {
22
+ return (
23
+ <div
24
+ className={clsx(
25
+ ThemeClassNames.layout.navbar.mobileSidebar.panel,
26
+ 'navbar-sidebar__item menu',
27
+ )}
28
+ {...inertProps(inert)}>
29
+ {children}
30
+ </div>
31
+ );
32
+ }
10
33
  export default function NavbarMobileSidebarLayout({
11
34
  header,
12
35
  primaryMenu,
@@ -14,14 +37,22 @@ export default function NavbarMobileSidebarLayout({
14
37
  }) {
15
38
  const {shown: secondaryMenuShown} = useNavbarSecondaryMenu();
16
39
  return (
17
- <div className="navbar-sidebar">
40
+ <div
41
+ className={clsx(
42
+ ThemeClassNames.layout.navbar.mobileSidebar.container,
43
+ 'navbar-sidebar',
44
+ )}>
18
45
  {header}
19
46
  <div
20
47
  className={clsx('navbar-sidebar__items', {
21
48
  'navbar-sidebar__items--show-secondary': secondaryMenuShown,
22
49
  })}>
23
- <div className="navbar-sidebar__item menu">{primaryMenu}</div>
24
- <div className="navbar-sidebar__item menu">{secondaryMenu}</div>
50
+ <NavbarMobileSidebarPanel inert={secondaryMenuShown}>
51
+ {primaryMenu}
52
+ </NavbarMobileSidebarPanel>
53
+ <NavbarMobileSidebarPanel inert={!secondaryMenuShown}>
54
+ {secondaryMenu}
55
+ </NavbarMobileSidebarPanel>
25
56
  </div>
26
57
  </div>
27
58
  );
@@ -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/NavbarItem/DefaultNavbarItem/Desktop';
9
+ export default function DefaultNavbarItemDesktop({ className, isDropdownItem, ...props }: Props): ReactNode;
@@ -0,0 +1,29 @@
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 NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
10
+ export default function DefaultNavbarItemDesktop({
11
+ className,
12
+ isDropdownItem = false,
13
+ ...props
14
+ }) {
15
+ const element = (
16
+ <NavbarNavLink
17
+ className={clsx(
18
+ isDropdownItem ? 'dropdown__link' : 'navbar__item navbar__link',
19
+ className,
20
+ )}
21
+ isDropdownLink={isDropdownItem}
22
+ {...props}
23
+ />
24
+ );
25
+ if (isDropdownItem) {
26
+ return <li>{element}</li>;
27
+ }
28
+ return element;
29
+ }
@@ -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/NavbarItem/DefaultNavbarItem/Mobile';
9
+ export default function DefaultNavbarItemMobile({ className, isDropdownItem, ...props }: Props): ReactNode;
@@ -0,0 +1,20 @@
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 NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
10
+ export default function DefaultNavbarItemMobile({
11
+ className,
12
+ isDropdownItem,
13
+ ...props
14
+ }) {
15
+ return (
16
+ <li className="menu__list-item">
17
+ <NavbarNavLink className={clsx('menu__link', className)} {...props} />
18
+ </li>
19
+ );
20
+ }
@@ -0,0 +1,25 @@
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 DefaultNavbarItemMobile from '@theme/NavbarItem/DefaultNavbarItem/Mobile';
9
+ import DefaultNavbarItemDesktop from '@theme/NavbarItem/DefaultNavbarItem/Desktop';
10
+ export default function DefaultNavbarItem({
11
+ mobile = false,
12
+ position, // Need to destructure position from props so that it doesn't get passed on.
13
+ ...props
14
+ }) {
15
+ const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop;
16
+ return (
17
+ <Comp
18
+ {...props}
19
+ activeClassName={
20
+ props.activeClassName ??
21
+ (mobile ? 'menu__link--active' : 'navbar__link--active')
22
+ }
23
+ />
24
+ );
25
+ }
@@ -6,4 +6,4 @@
6
6
  */
7
7
  import { type ReactNode } from 'react';
8
8
  import type { Props } from '@theme/NavbarItem/DocsVersionDropdownNavbarItem';
9
- export default function DocsVersionDropdownNavbarItem({ mobile, docsPluginId, dropdownActiveClassDisabled, dropdownItemsBefore, dropdownItemsAfter, ...props }: Props): ReactNode;
9
+ export default function DocsVersionDropdownNavbarItem({ mobile, docsPluginId, dropdownActiveClassDisabled, dropdownItemsBefore, dropdownItemsAfter, versions: configs, ...props }: Props): ReactNode;
@@ -15,6 +15,35 @@ import {translate} from '@docusaurus/Translate';
15
15
  import {useLocation} from '@docusaurus/router';
16
16
  import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
17
17
  import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
18
+ function getVersionItems(versions, configs) {
19
+ if (configs) {
20
+ // Collect all the versions we have
21
+ const versionMap = new Map(
22
+ versions.map((version) => [version.name, version]),
23
+ );
24
+ const toVersionItem = (name, config) => {
25
+ const version = versionMap.get(name);
26
+ if (!version) {
27
+ throw new Error(`No docs version exist for name '${name}', please verify your 'docsVersionDropdown' navbar item versions config.
28
+ Available version names:\n- ${versions.map((v) => `${v.name}`).join('\n- ')}`);
29
+ }
30
+ return {version, label: config?.label ?? version.label};
31
+ };
32
+ if (Array.isArray(configs)) {
33
+ return configs.map((name) => toVersionItem(name, undefined));
34
+ } else {
35
+ return Object.entries(configs).map(([name, config]) =>
36
+ toVersionItem(name, config),
37
+ );
38
+ }
39
+ } else {
40
+ return versions.map((version) => ({version, label: version.label}));
41
+ }
42
+ }
43
+ function useVersionItems({docsPluginId, configs}) {
44
+ const versions = useVersions(docsPluginId);
45
+ return getVersionItems(versions, configs);
46
+ }
18
47
  function getVersionMainDoc(version) {
19
48
  return version.docs.find((doc) => doc.id === version.mainDocId);
20
49
  }
@@ -26,22 +55,36 @@ function getVersionTargetDoc(version, activeDocContext) {
26
55
  getVersionMainDoc(version)
27
56
  );
28
57
  }
58
+ // The version item to use for the "dropdown button"
59
+ function useDisplayedVersionItem({docsPluginId, versionItems}) {
60
+ // The order of the candidates matters!
61
+ const candidates = useDocsVersionCandidates(docsPluginId);
62
+ const candidateItems = candidates
63
+ .map((candidate) => versionItems.find((vi) => vi.version === candidate))
64
+ .filter((vi) => vi !== undefined);
65
+ return candidateItems[0] ?? versionItems[0];
66
+ }
29
67
  export default function DocsVersionDropdownNavbarItem({
30
68
  mobile,
31
69
  docsPluginId,
32
70
  dropdownActiveClassDisabled,
33
71
  dropdownItemsBefore,
34
72
  dropdownItemsAfter,
73
+ versions: configs,
35
74
  ...props
36
75
  }) {
37
76
  const {search, hash} = useLocation();
38
77
  const activeDocContext = useActiveDocContext(docsPluginId);
39
- const versions = useVersions(docsPluginId);
40
78
  const {savePreferredVersionName} = useDocsPreferredVersion(docsPluginId);
41
- function versionToLink(version) {
79
+ const versionItems = useVersionItems({docsPluginId, configs});
80
+ const displayedVersionItem = useDisplayedVersionItem({
81
+ docsPluginId,
82
+ versionItems,
83
+ });
84
+ function versionItemToLink({version, label}) {
42
85
  const targetDoc = getVersionTargetDoc(version, activeDocContext);
43
86
  return {
44
- label: version.label,
87
+ label,
45
88
  // preserve ?search#hash suffix on version switches
46
89
  to: `${targetDoc.path}${search}${hash}`,
47
90
  isActive: () => version === activeDocContext.activeVersion,
@@ -50,10 +93,9 @@ export default function DocsVersionDropdownNavbarItem({
50
93
  }
51
94
  const items = [
52
95
  ...dropdownItemsBefore,
53
- ...versions.map(versionToLink),
96
+ ...versionItems.map(versionItemToLink),
54
97
  ...dropdownItemsAfter,
55
98
  ];
56
- const dropdownVersion = useDocsVersionCandidates(docsPluginId)[0];
57
99
  // Mobile dropdown is handled a bit differently
58
100
  const dropdownLabel =
59
101
  mobile && items.length > 1
@@ -63,11 +105,12 @@ export default function DocsVersionDropdownNavbarItem({
63
105
  description:
64
106
  'The label for the navbar versions dropdown on mobile view',
65
107
  })
66
- : dropdownVersion.label;
108
+ : displayedVersionItem.label;
67
109
  const dropdownTo =
68
110
  mobile && items.length > 1
69
111
  ? undefined
70
- : getVersionTargetDoc(dropdownVersion, activeDocContext).path;
112
+ : getVersionTargetDoc(displayedVersionItem.version, activeDocContext)
113
+ .path;
71
114
  // We don't want to render a version dropdown with 0 or 1 item. If we build
72
115
  // the site with a single docs version (onlyIncludeVersions: ['1.0.0']),
73
116
  // We'd rather render a button instead of a dropdown
@@ -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/NavbarItem/DropdownNavbarItem/Desktop';
9
+ export default function DropdownNavbarItemDesktop({ items, position, className, onClick, ...props }: Props): ReactNode;
@@ -0,0 +1,74 @@
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, {useState, useRef, useEffect} from 'react';
8
+ import clsx from 'clsx';
9
+ import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
10
+ import NavbarItem from '@theme/NavbarItem';
11
+ export default function DropdownNavbarItemDesktop({
12
+ items,
13
+ position,
14
+ className,
15
+ onClick,
16
+ ...props
17
+ }) {
18
+ const dropdownRef = useRef(null);
19
+ const [showDropdown, setShowDropdown] = useState(false);
20
+ useEffect(() => {
21
+ const handleClickOutside = (event) => {
22
+ if (!dropdownRef.current || dropdownRef.current.contains(event.target)) {
23
+ return;
24
+ }
25
+ setShowDropdown(false);
26
+ };
27
+ document.addEventListener('mousedown', handleClickOutside);
28
+ document.addEventListener('touchstart', handleClickOutside);
29
+ document.addEventListener('focusin', handleClickOutside);
30
+ return () => {
31
+ document.removeEventListener('mousedown', handleClickOutside);
32
+ document.removeEventListener('touchstart', handleClickOutside);
33
+ document.removeEventListener('focusin', handleClickOutside);
34
+ };
35
+ }, [dropdownRef]);
36
+ return (
37
+ <div
38
+ ref={dropdownRef}
39
+ className={clsx('navbar__item', 'dropdown', 'dropdown--hoverable', {
40
+ 'dropdown--right': position === 'right',
41
+ 'dropdown--show': showDropdown,
42
+ })}>
43
+ <NavbarNavLink
44
+ aria-haspopup="true"
45
+ aria-expanded={showDropdown}
46
+ role="button"
47
+ // # hash permits to make the <a> tag focusable in case no link target
48
+ // See https://github.com/facebook/docusaurus/pull/6003
49
+ // There's probably a better solution though...
50
+ href={props.to ? undefined : '#'}
51
+ className={clsx('navbar__link', className)}
52
+ {...props}
53
+ onClick={props.to ? undefined : (e) => e.preventDefault()}
54
+ onKeyDown={(e) => {
55
+ if (e.key === 'Enter') {
56
+ e.preventDefault();
57
+ setShowDropdown(!showDropdown);
58
+ }
59
+ }}>
60
+ {props.children ?? props.label}
61
+ </NavbarNavLink>
62
+ <ul className="dropdown__menu">
63
+ {items.map((childItemProps, i) => (
64
+ <NavbarItem
65
+ isDropdownItem
66
+ activeClassName="dropdown__link--active"
67
+ {...childItemProps}
68
+ key={i}
69
+ />
70
+ ))}
71
+ </ul>
72
+ </div>
73
+ );
74
+ }
@@ -0,0 +1,10 @@
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/NavbarItem/DropdownNavbarItem/Mobile';
9
+ export default function DropdownNavbarItemMobile({ items, className, position, // Need to destructure position from props so that it doesn't get passed on.
10
+ onClick, ...props }: Props): ReactNode;