@docusaurus/theme-classic 2.0.0-beta.8bda3b2db → 2.0.0-beta.9

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 (310) hide show
  1. package/README.md +1 -1
  2. package/codeTranslations/ar.json +12 -7
  3. package/codeTranslations/base.json +17 -7
  4. package/codeTranslations/bn.json +11 -5
  5. package/codeTranslations/cs.json +62 -0
  6. package/codeTranslations/da.json +8 -3
  7. package/codeTranslations/de.json +8 -3
  8. package/codeTranslations/es.json +15 -10
  9. package/codeTranslations/fa.json +31 -26
  10. package/codeTranslations/fil.json +8 -3
  11. package/codeTranslations/fr.json +8 -3
  12. package/codeTranslations/he.json +9 -4
  13. package/codeTranslations/hi.json +9 -4
  14. package/codeTranslations/ja.json +8 -3
  15. package/codeTranslations/ko.json +8 -3
  16. package/codeTranslations/pl.json +8 -3
  17. package/codeTranslations/pt-BR.json +16 -11
  18. package/codeTranslations/pt-PT.json +8 -3
  19. package/codeTranslations/ru.json +10 -5
  20. package/codeTranslations/sr.json +62 -0
  21. package/codeTranslations/tr.json +9 -4
  22. package/codeTranslations/vi.json +10 -5
  23. package/codeTranslations/zh-Hans.json +9 -4
  24. package/codeTranslations/zh-Hant.json +9 -4
  25. package/lib/__tests__/validateThemeConfig.test.js +277 -3
  26. package/lib/admonitions.css +35 -0
  27. package/lib/index.js +31 -8
  28. package/lib/prism-include-languages.js +9 -5
  29. package/lib/theme/AnnouncementBar/index.js +10 -16
  30. package/lib/theme/AnnouncementBar/styles.module.css +25 -30
  31. package/lib/theme/BackToTopButton/index.js +140 -0
  32. package/lib/theme/BackToTopButton/styles.module.css +42 -0
  33. package/lib/theme/BlogArchivePage/index.js +89 -0
  34. package/lib/theme/BlogLayout/index.js +51 -0
  35. package/lib/theme/BlogListPage/index.js +10 -21
  36. package/lib/theme/BlogPostAuthor/index.js +51 -0
  37. package/lib/theme/BlogPostAuthor/styles.module.css +12 -0
  38. package/lib/theme/BlogPostAuthors/index.js +47 -0
  39. package/lib/theme/BlogPostAuthors/styles.module.css +11 -0
  40. package/lib/theme/BlogPostItem/index.js +58 -67
  41. package/lib/theme/BlogPostPage/index.js +37 -24
  42. package/lib/theme/BlogSidebar/styles.module.css +2 -2
  43. package/lib/theme/BlogTagsListPage/index.js +8 -44
  44. package/lib/theme/BlogTagsPostsPage/index.js +24 -38
  45. package/lib/theme/CodeBlock/index.js +45 -41
  46. package/lib/theme/CodeBlock/styles.module.css +6 -9
  47. package/lib/theme/Details/index.js +30 -0
  48. package/lib/theme/Details/styles.module.css +13 -0
  49. package/lib/theme/DocItem/index.js +29 -45
  50. package/lib/theme/DocItem/styles.module.css +5 -9
  51. package/lib/theme/DocItemFooter/index.js +79 -0
  52. package/lib/theme/DocItemFooter/styles.module.css +18 -0
  53. package/lib/theme/DocPage/index.js +25 -49
  54. package/lib/theme/DocPage/styles.module.css +8 -23
  55. package/lib/theme/DocSidebar/index.js +45 -227
  56. package/lib/theme/DocSidebar/styles.module.css +0 -18
  57. package/lib/theme/DocSidebarItem/index.js +177 -0
  58. package/lib/theme/DocSidebarItem/styles.module.css +15 -0
  59. package/lib/theme/DocTagDocListPage/index.js +89 -0
  60. package/lib/theme/DocTagsListPage/index.js +44 -0
  61. package/lib/theme/{DocVersionSuggestions → DocVersionBanner}/index.js +37 -18
  62. package/lib/theme/EditThisPage/index.js +3 -1
  63. package/lib/theme/Footer/index.js +13 -4
  64. package/lib/theme/Heading/index.js +7 -9
  65. package/lib/theme/Heading/styles.css +4 -6
  66. package/lib/theme/Heading/styles.module.css +9 -5
  67. package/lib/theme/IconClose/index.js +31 -0
  68. package/lib/theme/LastUpdated/index.js +4 -2
  69. package/lib/theme/LayoutHead/index.js +13 -11
  70. package/lib/theme/LayoutProviders/index.js +11 -5
  71. package/lib/theme/Logo/index.js +14 -12
  72. package/lib/theme/MDXComponents/index.js +45 -4
  73. package/lib/theme/MDXComponents/styles.css +11 -0
  74. package/lib/theme/MDXPage/index.js +2 -1
  75. package/lib/theme/Navbar/index.js +164 -42
  76. package/lib/theme/Navbar/styles.module.css +10 -3
  77. package/lib/theme/NavbarItem/DefaultNavbarItem.js +27 -123
  78. package/lib/theme/NavbarItem/DocNavbarItem.js +6 -5
  79. package/lib/theme/NavbarItem/DocsVersionDropdownNavbarItem.js +19 -12
  80. package/lib/theme/NavbarItem/DropdownNavbarItem.js +155 -0
  81. package/lib/theme/NavbarItem/{LocaleDropdownNavbarItem.js → LocaleDropdownNavbarItem/index.js} +5 -6
  82. package/lib/theme/NavbarItem/LocaleDropdownNavbarItem/styles.module.css +11 -0
  83. package/lib/theme/NavbarItem/index.js +31 -11
  84. package/lib/theme/Seo/index.js +10 -7
  85. package/lib/theme/SkipToContent/index.js +9 -3
  86. package/lib/theme/SkipToContent/styles.module.css +1 -0
  87. package/lib/theme/TOC/index.js +9 -29
  88. package/lib/theme/TOC/styles.module.css +1 -1
  89. package/lib/theme/TOCCollapsible/index.js +53 -0
  90. package/lib/theme/TOCCollapsible/styles.module.css +50 -0
  91. package/lib/theme/TOCInline/index.js +7 -27
  92. package/lib/theme/TOCItems/index.js +78 -0
  93. package/lib/theme/Tabs/__tests__/index.test.js +123 -0
  94. package/lib/theme/Tabs/index.js +73 -50
  95. package/lib/theme/Tabs/styles.module.css +0 -13
  96. package/lib/theme/Tag/index.js +40 -0
  97. package/lib/theme/Tag/styles.module.css +70 -0
  98. package/lib/theme/TagsListByLetter/index.js +48 -0
  99. package/lib/theme/TagsListByLetter/styles.module.css +11 -0
  100. package/lib/theme/TagsListInline/index.js +44 -0
  101. package/lib/theme/TagsListInline/styles.module.css +15 -0
  102. package/lib/theme/ThemedImage/index.js +4 -5
  103. package/lib/theme/Toggle/index.js +23 -18
  104. package/lib/theme/Toggle/styles.module.css +91 -0
  105. package/lib/theme/UserPreferencesProvider/index.js +1 -9
  106. package/lib/theme/hooks/useHideableNavbar.js +14 -32
  107. package/lib/theme/hooks/useTabGroupChoice.js +2 -4
  108. package/lib/theme/hooks/useTheme.js +2 -2
  109. package/lib/theme/hooks/useWindowSize.js +33 -20
  110. package/lib/theme/prism-include-languages.js +4 -3
  111. package/lib/translations.js +4 -4
  112. package/lib/types.d.ts +338 -138
  113. package/lib/validateThemeConfig.js +226 -245
  114. package/lib-next/__tests__/validateThemeConfig.test.js +277 -3
  115. package/lib-next/admonitions.css +35 -0
  116. package/lib-next/index.js +33 -7
  117. package/lib-next/prism-include-languages.js +0 -2
  118. package/lib-next/theme/AnnouncementBar/index.js +9 -18
  119. package/lib-next/theme/AnnouncementBar/styles.module.css +25 -30
  120. package/lib-next/theme/BackToTopButton/index.js +131 -0
  121. package/lib-next/theme/BackToTopButton/styles.module.css +42 -0
  122. package/lib-next/theme/BlogArchivePage/index.js +80 -0
  123. package/lib-next/theme/BlogLayout/index.js +40 -0
  124. package/lib-next/theme/BlogListPage/index.js +16 -24
  125. package/lib-next/theme/BlogPostAuthor/index.js +46 -0
  126. package/lib-next/theme/BlogPostAuthor/styles.module.css +12 -0
  127. package/lib-next/theme/BlogPostAuthors/index.js +34 -0
  128. package/lib-next/theme/BlogPostAuthors/styles.module.css +11 -0
  129. package/lib-next/theme/BlogPostItem/index.js +79 -86
  130. package/lib-next/theme/BlogPostPage/index.js +70 -35
  131. package/lib-next/theme/BlogSidebar/styles.module.css +2 -2
  132. package/lib-next/theme/BlogTagsListPage/index.js +13 -54
  133. package/lib-next/theme/BlogTagsPostsPage/index.js +28 -38
  134. package/lib-next/theme/CodeBlock/index.js +54 -53
  135. package/lib-next/theme/CodeBlock/styles.module.css +6 -9
  136. package/lib-next/theme/Details/index.js +20 -0
  137. package/lib-next/theme/Details/styles.module.css +13 -0
  138. package/lib-next/theme/DocItem/index.js +46 -55
  139. package/lib-next/theme/DocItem/styles.module.css +5 -9
  140. package/lib-next/theme/DocItemFooter/index.js +79 -0
  141. package/lib-next/theme/DocItemFooter/styles.module.css +18 -0
  142. package/lib-next/theme/DocPage/index.js +25 -43
  143. package/lib-next/theme/DocPage/styles.module.css +8 -23
  144. package/lib-next/theme/DocSidebar/index.js +59 -288
  145. package/lib-next/theme/DocSidebar/styles.module.css +0 -18
  146. package/lib-next/theme/DocSidebarItem/index.js +181 -0
  147. package/lib-next/theme/DocSidebarItem/styles.module.css +15 -0
  148. package/lib-next/theme/DocTagDocListPage/index.js +89 -0
  149. package/lib-next/theme/DocTagsListPage/index.js +38 -0
  150. package/lib-next/theme/{DocVersionSuggestions → DocVersionBanner}/index.js +44 -36
  151. package/lib-next/theme/EditThisPage/index.js +6 -1
  152. package/lib-next/theme/Footer/index.js +24 -4
  153. package/lib-next/theme/Heading/index.js +10 -13
  154. package/lib-next/theme/Heading/styles.css +4 -6
  155. package/lib-next/theme/Heading/styles.module.css +9 -5
  156. package/lib-next/theme/IconClose/index.js +23 -0
  157. package/lib-next/theme/LastUpdated/index.js +3 -2
  158. package/lib-next/theme/LayoutHead/index.js +9 -15
  159. package/lib-next/theme/LayoutProviders/index.js +17 -6
  160. package/lib-next/theme/Logo/index.js +23 -19
  161. package/lib-next/theme/MDXComponents/index.js +34 -7
  162. package/lib-next/theme/MDXComponents/styles.css +11 -0
  163. package/lib-next/theme/MDXPage/index.js +10 -2
  164. package/lib-next/theme/Navbar/index.js +192 -56
  165. package/lib-next/theme/Navbar/styles.module.css +10 -3
  166. package/lib-next/theme/NavbarItem/DefaultNavbarItem.js +45 -147
  167. package/lib-next/theme/NavbarItem/DocNavbarItem.js +6 -5
  168. package/lib-next/theme/NavbarItem/DocsVersionDropdownNavbarItem.js +31 -19
  169. package/lib-next/theme/NavbarItem/DropdownNavbarItem.js +158 -0
  170. package/lib-next/theme/NavbarItem/{LocaleDropdownNavbarItem.js → LocaleDropdownNavbarItem/index.js} +4 -8
  171. package/lib-next/theme/NavbarItem/LocaleDropdownNavbarItem/styles.module.css +11 -0
  172. package/lib-next/theme/NavbarItem/index.js +25 -12
  173. package/lib-next/theme/Seo/index.js +11 -7
  174. package/lib-next/theme/SkipToContent/index.js +5 -6
  175. package/lib-next/theme/SkipToContent/styles.module.css +1 -0
  176. package/lib-next/theme/TOC/index.js +12 -36
  177. package/lib-next/theme/TOC/styles.module.css +1 -1
  178. package/lib-next/theme/TOCCollapsible/index.js +54 -0
  179. package/lib-next/theme/TOCCollapsible/styles.module.css +50 -0
  180. package/lib-next/theme/TOCInline/index.js +10 -28
  181. package/lib-next/theme/TOCItems/index.js +85 -0
  182. package/lib-next/theme/Tabs/__tests__/index.test.js +142 -0
  183. package/lib-next/theme/Tabs/index.js +91 -43
  184. package/lib-next/theme/Tabs/styles.module.css +0 -13
  185. package/lib-next/theme/Tag/index.js +27 -0
  186. package/lib-next/theme/Tag/styles.module.css +70 -0
  187. package/lib-next/theme/TagsListByLetter/index.js +42 -0
  188. package/lib-next/theme/TagsListByLetter/styles.module.css +11 -0
  189. package/lib-next/theme/TagsListInline/index.js +31 -0
  190. package/lib-next/theme/TagsListInline/styles.module.css +15 -0
  191. package/lib-next/theme/ThemedImage/index.js +5 -6
  192. package/lib-next/theme/Toggle/index.js +20 -15
  193. package/lib-next/theme/Toggle/styles.module.css +91 -0
  194. package/lib-next/theme/UserPreferencesProvider/index.js +0 -4
  195. package/lib-next/theme/hooks/useHideableNavbar.js +31 -44
  196. package/lib-next/theme/hooks/useTabGroupChoice.js +2 -4
  197. package/lib-next/theme/hooks/useTheme.js +2 -2
  198. package/lib-next/theme/hooks/useWindowSize.js +34 -20
  199. package/lib-next/theme/prism-include-languages.js +2 -1
  200. package/lib-next/translations.js +6 -10
  201. package/lib-next/types.d.ts +338 -138
  202. package/lib-next/validateThemeConfig.js +134 -110
  203. package/package.json +24 -19
  204. package/src/__tests__/validateThemeConfig.test.js +277 -3
  205. package/src/admonitions.css +35 -0
  206. package/src/index.ts +44 -14
  207. package/src/{prism-include-languages.js → prism-include-languages.ts} +0 -0
  208. package/src/theme/AnnouncementBar/index.tsx +10 -17
  209. package/src/theme/AnnouncementBar/styles.module.css +25 -30
  210. package/src/theme/BackToTopButton/index.tsx +142 -0
  211. package/src/theme/BackToTopButton/styles.module.css +42 -0
  212. package/src/theme/BlogArchivePage/index.tsx +91 -0
  213. package/src/theme/BlogLayout/index.tsx +44 -0
  214. package/src/theme/BlogListPage/index.tsx +17 -24
  215. package/src/theme/BlogPostAuthor/index.tsx +49 -0
  216. package/src/theme/BlogPostAuthor/styles.module.css +12 -0
  217. package/src/theme/BlogPostAuthors/index.tsx +36 -0
  218. package/src/theme/BlogPostAuthors/styles.module.css +11 -0
  219. package/src/theme/BlogPostItem/index.tsx +70 -80
  220. package/src/theme/BlogPostPage/index.tsx +72 -35
  221. package/src/theme/BlogSidebar/styles.module.css +2 -2
  222. package/src/theme/BlogTagsListPage/index.tsx +13 -56
  223. package/src/theme/BlogTagsPostsPage/index.tsx +28 -38
  224. package/src/theme/CodeBlock/index.tsx +70 -55
  225. package/src/theme/CodeBlock/styles.module.css +6 -9
  226. package/src/theme/Details/index.tsx +24 -0
  227. package/src/theme/Details/styles.module.css +13 -0
  228. package/src/theme/DocItem/index.tsx +49 -55
  229. package/src/theme/DocItem/styles.module.css +5 -9
  230. package/src/theme/DocItemFooter/index.tsx +91 -0
  231. package/src/theme/DocItemFooter/styles.module.css +18 -0
  232. package/src/theme/DocPage/index.tsx +24 -38
  233. package/src/theme/DocPage/styles.module.css +8 -23
  234. package/src/theme/DocSidebar/index.tsx +70 -300
  235. package/src/theme/DocSidebar/styles.module.css +0 -18
  236. package/src/theme/DocSidebarItem/index.tsx +206 -0
  237. package/src/theme/DocSidebarItem/styles.module.css +15 -0
  238. package/src/theme/DocTagDocListPage/index.tsx +89 -0
  239. package/src/theme/DocTagsListPage/index.tsx +41 -0
  240. package/src/theme/{DocVersionSuggestions → DocVersionBanner}/index.tsx +58 -44
  241. package/src/theme/EditThisPage/index.tsx +6 -1
  242. package/src/theme/Footer/index.tsx +26 -4
  243. package/src/theme/Heading/index.tsx +10 -13
  244. package/src/theme/Heading/styles.css +4 -6
  245. package/src/theme/Heading/styles.module.css +9 -5
  246. package/src/theme/IconClose/index.tsx +26 -0
  247. package/src/theme/LastUpdated/index.tsx +3 -2
  248. package/src/theme/LayoutHead/index.tsx +9 -9
  249. package/src/theme/LayoutProviders/index.tsx +17 -6
  250. package/src/theme/Logo/index.tsx +19 -15
  251. package/src/theme/MDXComponents/index.tsx +39 -5
  252. package/src/theme/MDXComponents/styles.css +11 -0
  253. package/src/theme/MDXPage/index.tsx +10 -2
  254. package/src/theme/Navbar/index.tsx +202 -61
  255. package/src/theme/Navbar/styles.module.css +10 -3
  256. package/src/theme/NavbarItem/DefaultNavbarItem.tsx +42 -154
  257. package/src/theme/NavbarItem/DocNavbarItem.tsx +11 -14
  258. package/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx +33 -21
  259. package/src/theme/NavbarItem/DocsVersionNavbarItem.tsx +7 -3
  260. package/src/theme/NavbarItem/DropdownNavbarItem.tsx +180 -0
  261. package/src/theme/NavbarItem/{LocaleDropdownNavbarItem.tsx → LocaleDropdownNavbarItem/index.tsx} +8 -7
  262. package/src/theme/NavbarItem/LocaleDropdownNavbarItem/styles.module.css +11 -0
  263. package/src/theme/NavbarItem/index.tsx +41 -16
  264. package/src/theme/Seo/index.tsx +7 -4
  265. package/src/theme/SkipToContent/index.tsx +5 -6
  266. package/src/theme/SkipToContent/styles.module.css +1 -0
  267. package/src/theme/TOC/index.tsx +12 -41
  268. package/src/theme/TOC/styles.module.css +1 -1
  269. package/src/theme/TOCCollapsible/index.tsx +58 -0
  270. package/src/theme/TOCCollapsible/styles.module.css +50 -0
  271. package/src/theme/TOCInline/index.tsx +13 -32
  272. package/src/theme/TOCItems/index.tsx +96 -0
  273. package/src/theme/Tabs/__tests__/index.test.tsx +129 -0
  274. package/src/theme/Tabs/index.tsx +93 -49
  275. package/src/theme/Tabs/styles.module.css +0 -13
  276. package/src/theme/Tag/index.tsx +31 -0
  277. package/src/theme/Tag/styles.module.css +70 -0
  278. package/src/theme/TagsListByLetter/index.tsx +45 -0
  279. package/src/theme/TagsListByLetter/styles.module.css +11 -0
  280. package/src/theme/TagsListInline/index.tsx +35 -0
  281. package/src/theme/TagsListInline/styles.module.css +15 -0
  282. package/src/theme/ThemedImage/index.tsx +6 -6
  283. package/src/theme/Toggle/index.tsx +20 -15
  284. package/src/theme/Toggle/styles.module.css +91 -0
  285. package/src/theme/UserPreferencesProvider/index.tsx +0 -5
  286. package/src/theme/hooks/useContextualSearchFilters.ts +1 -1
  287. package/src/theme/hooks/useHideableNavbar.ts +32 -45
  288. package/src/theme/hooks/useTabGroupChoice.ts +4 -4
  289. package/src/theme/hooks/useTheme.ts +2 -2
  290. package/src/theme/hooks/useWindowSize.ts +38 -20
  291. package/src/theme/prism-include-languages.ts +3 -2
  292. package/src/translations.ts +6 -10
  293. package/src/types.d.ts +338 -138
  294. package/src/{validateThemeConfig.js → validateThemeConfig.ts} +144 -90
  295. package/tsconfig.json +1 -2
  296. package/update-code-translations.js +10 -6
  297. package/update-code-translations.test.js +1 -1
  298. package/update.js +151 -0
  299. package/lib/theme/Toggle/styles.css +0 -103
  300. package/lib/theme/hooks/useAnnouncementBar.js +0 -63
  301. package/lib/theme/hooks/useScrollPosition.js +0 -49
  302. package/lib/theme/hooks/useTOCHighlight.js +0 -87
  303. package/lib-next/theme/Toggle/styles.css +0 -103
  304. package/lib-next/theme/hooks/useAnnouncementBar.js +0 -49
  305. package/lib-next/theme/hooks/useScrollPosition.js +0 -38
  306. package/lib-next/theme/hooks/useTOCHighlight.js +0 -84
  307. package/src/theme/Toggle/styles.css +0 -103
  308. package/src/theme/hooks/useAnnouncementBar.ts +0 -58
  309. package/src/theme/hooks/useScrollPosition.ts +0 -45
  310. package/src/theme/hooks/useTOCHighlight.ts +0 -98
@@ -6,19 +6,32 @@
6
6
  */
7
7
  import React, {useCallback, useState, useEffect} from 'react';
8
8
  import clsx from 'clsx';
9
+ import Translate from '@docusaurus/Translate';
9
10
  import SearchBar from '@theme/SearchBar';
10
11
  import Toggle from '@theme/Toggle';
11
12
  import useThemeContext from '@theme/hooks/useThemeContext';
12
- import {useThemeConfig} from '@docusaurus/theme-common';
13
+ import {
14
+ useThemeConfig,
15
+ useMobileSecondaryMenuRenderer,
16
+ usePrevious,
17
+ useHistoryPopHandler,
18
+ } from '@docusaurus/theme-common';
13
19
  import useHideableNavbar from '@theme/hooks/useHideableNavbar';
14
20
  import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
15
- import useWindowSize, {windowSizes} from '@theme/hooks/useWindowSize';
21
+ import useWindowSize from '@theme/hooks/useWindowSize';
22
+ import {useActivePlugin} from '@theme/hooks/useDocs';
16
23
  import NavbarItem from '@theme/NavbarItem';
17
24
  import Logo from '@theme/Logo';
18
25
  import IconMenu from '@theme/IconMenu';
26
+ import IconClose from '@theme/IconClose';
19
27
  import styles from './styles.module.css'; // retrocompatible with v1
20
28
 
21
- const DefaultNavItemPosition = 'right'; // If split links by left/right
29
+ const DefaultNavItemPosition = 'right';
30
+
31
+ function useNavbarItems() {
32
+ // TODO temporary casting until ThemeConfig type is improved
33
+ return useThemeConfig().navbar.items;
34
+ } // If split links by left/right
22
35
  // if position is unspecified, fallback to right (as v1)
23
36
 
24
37
  function splitNavItemsByPosition(items) {
@@ -34,31 +47,173 @@ function splitNavItemsByPosition(items) {
34
47
  };
35
48
  }
36
49
 
37
- function Navbar() {
50
+ function useMobileSidebar() {
51
+ const windowSize = useWindowSize(); // Mobile sidebar not visible on hydration: can avoid SSR rendering
52
+
53
+ const shouldRender = windowSize === 'mobile'; // || windowSize === 'ssr';
54
+
55
+ const [shown, setShown] = useState(false); // Close mobile sidebar on navigation pop
56
+ // Most likely firing when using the Android back button (but not only)
57
+
58
+ useHistoryPopHandler(() => {
59
+ if (shown) {
60
+ setShown(false); // Should we prevent the navigation here?
61
+ // See https://github.com/facebook/docusaurus/pull/5462#issuecomment-911699846
62
+
63
+ return false; // prevent pop navigation
64
+ }
65
+
66
+ return undefined;
67
+ });
68
+ const toggle = useCallback(() => {
69
+ setShown((s) => !s);
70
+ }, []);
71
+ useEffect(() => {
72
+ if (windowSize === 'desktop') {
73
+ setShown(false);
74
+ }
75
+ }, [windowSize]);
76
+ return {
77
+ shouldRender,
78
+ toggle,
79
+ shown,
80
+ };
81
+ }
82
+
83
+ function useColorModeToggle() {
38
84
  const {
39
- navbar: {items, hideOnScroll, style},
40
- colorMode: {disableSwitch: disableColorModeSwitch},
85
+ colorMode: {disableSwitch},
41
86
  } = useThemeConfig();
42
- const [sidebarShown, setSidebarShown] = useState(false);
43
87
  const {isDarkTheme, setLightTheme, setDarkTheme} = useThemeContext();
44
- const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll);
45
- useLockBodyScroll(sidebarShown);
46
- const showSidebar = useCallback(() => {
47
- setSidebarShown(true);
48
- }, [setSidebarShown]);
49
- const hideSidebar = useCallback(() => {
50
- setSidebarShown(false);
51
- }, [setSidebarShown]);
52
- const onToggleChange = useCallback(
88
+ const toggle = useCallback(
53
89
  (e) => (e.target.checked ? setDarkTheme() : setLightTheme()),
54
90
  [setLightTheme, setDarkTheme],
55
91
  );
56
- const windowSize = useWindowSize();
92
+ return {
93
+ isDarkTheme,
94
+ toggle,
95
+ disabled: disableSwitch,
96
+ };
97
+ }
98
+
99
+ function useSecondaryMenu({sidebarShown, toggleSidebar}) {
100
+ const content = useMobileSecondaryMenuRenderer()?.({
101
+ toggleSidebar,
102
+ });
103
+ const previousContent = usePrevious(content);
104
+ const [shown, setShown] = useState(() => {
105
+ // /!\ content is set with useEffect,
106
+ // so it's not available on mount anyway
107
+ // "return !!content" => always returns false
108
+ return false;
109
+ }); // When content is become available for the first time (set in useEffect)
110
+ // we set this content to be shown!
111
+
57
112
  useEffect(() => {
58
- if (windowSize === windowSizes.desktop) {
59
- setSidebarShown(false);
113
+ const contentBecameAvailable = content && !previousContent;
114
+
115
+ if (contentBecameAvailable) {
116
+ setShown(true);
60
117
  }
61
- }, [windowSize]);
118
+ }, [content, previousContent]);
119
+ const hasContent = !!content; // On sidebar close, secondary menu is set to be shown on next re-opening
120
+ // (if any secondary menu content available)
121
+
122
+ useEffect(() => {
123
+ if (!hasContent) {
124
+ setShown(false);
125
+ return;
126
+ }
127
+
128
+ if (!sidebarShown) {
129
+ setShown(true);
130
+ }
131
+ }, [sidebarShown, hasContent]);
132
+ const hide = useCallback(() => {
133
+ setShown(false);
134
+ }, []);
135
+ return {
136
+ shown,
137
+ hide,
138
+ content,
139
+ };
140
+ }
141
+
142
+ function NavbarMobileSidebar({sidebarShown, toggleSidebar}) {
143
+ useLockBodyScroll(sidebarShown);
144
+ const items = useNavbarItems();
145
+ const colorModeToggle = useColorModeToggle();
146
+ const secondaryMenu = useSecondaryMenu({
147
+ sidebarShown,
148
+ toggleSidebar,
149
+ });
150
+ return (
151
+ <div className="navbar-sidebar">
152
+ <div className="navbar-sidebar__brand">
153
+ <Logo
154
+ className="navbar__brand"
155
+ imageClassName="navbar__logo"
156
+ titleClassName="navbar__title"
157
+ />
158
+ {!colorModeToggle.disabled && (
159
+ <Toggle
160
+ className={styles.navbarSidebarToggle}
161
+ checked={colorModeToggle.isDarkTheme}
162
+ onChange={colorModeToggle.toggle}
163
+ />
164
+ )}
165
+ <button
166
+ type="button"
167
+ className="clean-btn navbar-sidebar__close"
168
+ onClick={toggleSidebar}>
169
+ <IconClose
170
+ color="var(--ifm-color-emphasis-600)"
171
+ className={styles.navbarSidebarCloseSvg}
172
+ />
173
+ </button>
174
+ </div>
175
+
176
+ <div
177
+ className={clsx('navbar-sidebar__items', {
178
+ 'navbar-sidebar__items--show-secondary': secondaryMenu.shown,
179
+ })}>
180
+ <div className="navbar-sidebar__item menu">
181
+ <ul className="menu__list">
182
+ {items.map((item, i) => (
183
+ <NavbarItem mobile {...item} onClick={toggleSidebar} key={i} />
184
+ ))}
185
+ </ul>
186
+ </div>
187
+
188
+ <div className="navbar-sidebar__item menu">
189
+ {items.length > 0 && (
190
+ <button
191
+ type="button"
192
+ className="clean-btn navbar-sidebar__back"
193
+ onClick={secondaryMenu.hide}>
194
+ <Translate
195
+ id="theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel"
196
+ description="The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)">
197
+ ← Back to main menu
198
+ </Translate>
199
+ </button>
200
+ )}
201
+ {secondaryMenu.content}
202
+ </div>
203
+ </div>
204
+ </div>
205
+ );
206
+ }
207
+
208
+ function Navbar() {
209
+ const {
210
+ navbar: {hideOnScroll, style},
211
+ } = useThemeConfig();
212
+ const mobileSidebar = useMobileSidebar();
213
+ const colorModeToggle = useColorModeToggle();
214
+ const activeDocPlugin = useActivePlugin();
215
+ const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll);
216
+ const items = useNavbarItems();
62
217
  const hasSearchNavbarItem = items.some((item) => item.type === 'search');
63
218
  const {leftItems, rightItems} = splitNavItemsByPosition(items);
64
219
  return (
@@ -67,20 +222,20 @@ function Navbar() {
67
222
  className={clsx('navbar', 'navbar--fixed-top', {
68
223
  'navbar--dark': style === 'dark',
69
224
  'navbar--primary': style === 'primary',
70
- 'navbar-sidebar--show': sidebarShown,
225
+ 'navbar-sidebar--show': mobileSidebar.shown,
71
226
  [styles.navbarHideable]: hideOnScroll,
72
227
  [styles.navbarHidden]: hideOnScroll && !isNavbarVisible,
73
228
  })}>
74
229
  <div className="navbar__inner">
75
230
  <div className="navbar__items">
76
- {items != null && items.length !== 0 && (
231
+ {(items?.length > 0 || activeDocPlugin) && (
77
232
  <button
78
233
  aria-label="Navigation bar toggle"
79
234
  className="navbar__toggle clean-btn"
80
235
  type="button"
81
236
  tabIndex={0}
82
- onClick={showSidebar}
83
- onKeyDown={showSidebar}>
237
+ onClick={mobileSidebar.toggle}
238
+ onKeyDown={mobileSidebar.toggle}>
84
239
  <IconMenu />
85
240
  </button>
86
241
  )}
@@ -97,48 +252,29 @@ function Navbar() {
97
252
  {rightItems.map((item, i) => (
98
253
  <NavbarItem {...item} key={i} />
99
254
  ))}
100
- {!disableColorModeSwitch && (
255
+ {!colorModeToggle.disabled && (
101
256
  <Toggle
102
- className={styles.displayOnlyInLargeViewport}
103
- checked={isDarkTheme}
104
- onChange={onToggleChange}
257
+ className={styles.toggle}
258
+ checked={colorModeToggle.isDarkTheme}
259
+ onChange={colorModeToggle.toggle}
105
260
  />
106
261
  )}
107
262
  {!hasSearchNavbarItem && <SearchBar />}
108
263
  </div>
109
264
  </div>
265
+
110
266
  <div
111
267
  role="presentation"
112
268
  className="navbar-sidebar__backdrop"
113
- onClick={hideSidebar}
269
+ onClick={mobileSidebar.toggle}
114
270
  />
115
- <div className="navbar-sidebar">
116
- <div className="navbar-sidebar__brand">
117
- <Logo
118
- className="navbar__brand"
119
- imageClassName="navbar__logo"
120
- titleClassName="navbar__title"
121
- onClick={hideSidebar}
122
- />
123
- {!disableColorModeSwitch && sidebarShown && (
124
- <Toggle checked={isDarkTheme} onChange={onToggleChange} />
125
- )}
126
- </div>
127
- <div className="navbar-sidebar__items">
128
- <div className="menu">
129
- <ul className="menu__list">
130
- {items.map((item, i) => (
131
- <NavbarItem
132
- mobile
133
- {...item} // TODO fix typing
134
- onClick={hideSidebar}
135
- key={i}
136
- />
137
- ))}
138
- </ul>
139
- </div>
140
- </div>
141
- </div>
271
+
272
+ {mobileSidebar.shouldRender && (
273
+ <NavbarMobileSidebar
274
+ sidebarShown={mobileSidebar.shown}
275
+ toggleSidebar={mobileSidebar.toggle}
276
+ />
277
+ )}
142
278
  </nav>
143
279
  );
144
280
  }
@@ -5,9 +5,12 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- @media screen and (max-width: 997px) {
9
- .displayOnlyInLargeViewport {
10
- display: none !important;
8
+ /*
9
+ Hide toggle in small viewports
10
+ */
11
+ @media (max-width: 996px) {
12
+ .toggle {
13
+ display: none;
11
14
  }
12
15
  }
13
16
 
@@ -18,3 +21,7 @@
18
21
  .navbarHidden {
19
22
  transform: translate3d(0, calc(-100% - 2px), 0);
20
23
  }
24
+
25
+ .navbarSidebarToggle {
26
+ margin-right: 1rem;
27
+ }
@@ -4,23 +4,22 @@
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, {useState, useRef, useEffect} from 'react';
7
+ import React from 'react';
8
8
  import clsx from 'clsx';
9
9
  import Link from '@docusaurus/Link';
10
10
  import useBaseUrl from '@docusaurus/useBaseUrl';
11
- import {useLocation} from '@docusaurus/router';
12
- import {isSamePath} from '@docusaurus/theme-common';
13
11
  import IconExternalLink from '@theme/IconExternalLink';
14
12
  import isInternalUrl from '@docusaurus/isInternalUrl';
13
+ import {isRegexpStringMatch} from '@docusaurus/theme-common';
14
+ import {getInfimaActiveClassName} from './index';
15
15
  const dropdownLinkActiveClass = 'dropdown__link--active';
16
-
17
- function NavLink({
16
+ export function NavLink({
18
17
  activeBasePath,
19
18
  activeBaseRegex,
20
19
  to,
21
20
  href,
22
21
  label,
23
- activeClassName = 'navbar__link--active',
22
+ activeClassName = '',
24
23
  prependBaseUrlToHref,
25
24
  ...props
26
25
  }) {
@@ -41,13 +40,15 @@ function NavLink({
41
40
  }
42
41
  : {
43
42
  isNavLink: true,
44
- activeClassName,
43
+ activeClassName: !props.className?.includes(activeClassName)
44
+ ? activeClassName
45
+ : '',
45
46
  to: toUrl,
46
47
  ...(activeBasePath || activeBaseRegex
47
48
  ? {
48
49
  isActive: (_match, location) =>
49
50
  activeBaseRegex
50
- ? new RegExp(activeBaseRegex).test(location.pathname)
51
+ ? isRegexpStringMatch(activeBaseRegex, location.pathname)
51
52
  : location.pathname.startsWith(activeBaseUrl),
52
53
  }
53
54
  : null),
@@ -70,158 +71,55 @@ function NavLink({
70
71
  );
71
72
  }
72
73
 
73
- function NavItemDesktop({items, position, className, ...props}) {
74
- const dropdownRef = useRef(null);
75
- const dropdownMenuRef = useRef(null);
76
- const [showDropdown, setShowDropdown] = useState(false);
77
- useEffect(() => {
78
- const handleClickOutside = (event) => {
79
- if (!dropdownRef.current || dropdownRef.current.contains(event.target)) {
80
- return;
81
- }
82
-
83
- setShowDropdown(false);
84
- };
85
-
86
- document.addEventListener('mousedown', handleClickOutside);
87
- document.addEventListener('touchstart', handleClickOutside);
88
- return () => {
89
- document.removeEventListener('mousedown', handleClickOutside);
90
- document.removeEventListener('touchstart', handleClickOutside);
91
- };
92
- }, [dropdownRef]);
93
-
94
- const navLinkClassNames = (extraClassName, isDropdownItem = false) =>
95
- clsx(
96
- {
97
- 'navbar__item navbar__link': !isDropdownItem,
98
- dropdown__link: isDropdownItem,
99
- },
100
- extraClassName,
101
- );
74
+ function DefaultNavbarItemDesktop({
75
+ className,
76
+ isDropdownItem = false,
77
+ ...props
78
+ }) {
79
+ const element = (
80
+ <NavLink
81
+ className={clsx(
82
+ isDropdownItem ? 'dropdown__link' : 'navbar__item navbar__link',
83
+ className,
84
+ )}
85
+ {...props}
86
+ />
87
+ );
102
88
 
103
- if (!items) {
104
- return <NavLink className={navLinkClassNames(className)} {...props} />;
89
+ if (isDropdownItem) {
90
+ return <li>{element}</li>;
105
91
  }
106
92
 
107
- return (
108
- <div
109
- ref={dropdownRef}
110
- className={clsx('navbar__item', 'dropdown', 'dropdown--hoverable', {
111
- 'dropdown--left': position === 'left',
112
- 'dropdown--right': position === 'right',
113
- 'dropdown--show': showDropdown,
114
- })}>
115
- <NavLink
116
- className={navLinkClassNames(className)}
117
- {...props}
118
- onClick={props.to ? undefined : (e) => e.preventDefault()}
119
- onKeyDown={(e) => {
120
- if (e.key === 'Enter') {
121
- e.preventDefault();
122
- setShowDropdown(!showDropdown);
123
- }
124
- }}>
125
- {props.children ?? props.label}
126
- </NavLink>
127
- <ul ref={dropdownMenuRef} className="dropdown__menu">
128
- {items.map(({className: childItemClassName, ...childItemProps}, i) => (
129
- <li key={i}>
130
- <NavLink
131
- onKeyDown={(e) => {
132
- if (i === items.length - 1 && e.key === 'Tab') {
133
- e.preventDefault();
134
- setShowDropdown(false);
135
- const nextNavbarItem = dropdownRef.current.nextElementSibling;
136
-
137
- if (nextNavbarItem) {
138
- nextNavbarItem.focus();
139
- }
140
- }
141
- }}
142
- activeClassName={dropdownLinkActiveClass}
143
- className={navLinkClassNames(childItemClassName, true)}
144
- {...childItemProps}
145
- />
146
- </li>
147
- ))}
148
- </ul>
149
- </div>
150
- );
93
+ return element;
151
94
  }
152
95
 
153
- function NavItemMobile({
154
- items,
96
+ function DefaultNavbarItemMobile({
155
97
  className,
156
- position: _position,
157
- // Need to destructure position from props so that it doesn't get passed on.
98
+ isDropdownItem: _isDropdownItem,
158
99
  ...props
159
100
  }) {
160
- const menuListRef = useRef(null);
161
- const {pathname} = useLocation();
162
- const [collapsed, setCollapsed] = useState(
163
- () => !items?.some((item) => isSamePath(item.to, pathname)) ?? true,
164
- );
165
-
166
- const navLinkClassNames = (extraClassName, isSubList = false) =>
167
- clsx(
168
- 'menu__link',
169
- {
170
- 'menu__link--sublist': isSubList,
171
- },
172
- extraClassName,
173
- );
174
-
175
- if (!items) {
176
- return (
177
- <li className="menu__list-item">
178
- <NavLink className={navLinkClassNames(className)} {...props} />
179
- </li>
180
- );
181
- }
182
-
183
- const menuListHeight = menuListRef.current?.scrollHeight
184
- ? `${menuListRef.current?.scrollHeight}px`
185
- : undefined;
186
101
  return (
187
- <li
188
- className={clsx('menu__list-item', {
189
- 'menu__list-item--collapsed': collapsed,
190
- })}>
191
- <NavLink
192
- role="button"
193
- className={navLinkClassNames(className, true)}
194
- {...props}
195
- onClick={(e) => {
196
- e.preventDefault();
197
- setCollapsed((state) => !state);
198
- }}>
199
- {props.children ?? props.label}
200
- </NavLink>
201
- <ul
202
- className="menu__list"
203
- ref={menuListRef}
204
- style={{
205
- height: !collapsed ? menuListHeight : undefined,
206
- }}>
207
- {items.map(({className: childItemClassName, ...childItemProps}, i) => (
208
- <li className="menu__list-item" key={i}>
209
- <NavLink
210
- activeClassName="menu__link--active"
211
- className={navLinkClassNames(childItemClassName)}
212
- {...childItemProps}
213
- onClick={props.onClick}
214
- />
215
- </li>
216
- ))}
217
- </ul>
102
+ <li className="menu__list-item">
103
+ <NavLink className={clsx('menu__link', className)} {...props} />
218
104
  </li>
219
105
  );
220
106
  }
221
107
 
222
- function DefaultNavbarItem({mobile = false, ...props}) {
223
- const Comp = mobile ? NavItemMobile : NavItemDesktop;
224
- return <Comp {...props} />;
108
+ function DefaultNavbarItem({
109
+ mobile = false,
110
+ position: _position,
111
+ // Need to destructure position from props so that it doesn't get passed on.
112
+ ...props
113
+ }) {
114
+ const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop;
115
+ return (
116
+ <Comp
117
+ {...props}
118
+ activeClassName={
119
+ props.activeClassName ?? getInfimaActiveClassName(mobile)
120
+ }
121
+ />
122
+ );
225
123
  }
226
124
 
227
125
  export default DefaultNavbarItem;
@@ -8,12 +8,12 @@ import React from 'react';
8
8
  import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
9
9
  import {useLatestVersion, useActiveDocContext} from '@theme/hooks/useDocs';
10
10
  import clsx from 'clsx';
11
+ import {getInfimaActiveClassName} from './index';
11
12
  import {useDocsPreferredVersion} from '@docusaurus/theme-common';
12
13
  import {uniq} from '@docusaurus/utils-common';
13
14
 
14
15
  function getDocInVersions(versions, docId) {
15
- // vanilla-js flatten, TODO replace soon by ES flat() / flatMap()
16
- const allDocs = [].concat(...versions.map((version) => version.docs));
16
+ const allDocs = versions.flatMap((version) => version.docs);
17
17
  const doc = allDocs.find((versionDoc) => versionDoc.id === docId);
18
18
 
19
19
  if (!doc) {
@@ -29,7 +29,6 @@ Available doc ids are:\n- ${docIds}`);
29
29
 
30
30
  export default function DocNavbarItem({
31
31
  docId,
32
- activeSidebarClassName,
33
32
  label: staticLabel,
34
33
  docsPluginId,
35
34
  ...props
@@ -42,14 +41,16 @@ export default function DocNavbarItem({
42
41
  [activeVersion, preferredVersion, latestVersion].filter(Boolean),
43
42
  );
44
43
  const doc = getDocInVersions(versions, docId);
44
+ const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile);
45
45
  return (
46
46
  <DefaultNavbarItem
47
47
  exact
48
48
  {...props}
49
49
  className={clsx(props.className, {
50
- [activeSidebarClassName]:
51
- activeDoc && activeDoc.sidebar === doc.sidebar,
50
+ [activeDocInfimaClassName]:
51
+ activeDoc?.sidebar && activeDoc.sidebar === doc.sidebar,
52
52
  })}
53
+ activeClassName={activeDocInfimaClassName}
53
54
  label={staticLabel ?? doc.id}
54
55
  to={doc.path}
55
56
  />