@docusaurus/theme-common 2.0.0-beta.18 → 2.0.0-beta.19

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 (128) hide show
  1. package/Details.d.ts +14 -0
  2. package/lib/components/Collapsible/index.js +2 -2
  3. package/lib/components/Collapsible/index.js.map +1 -1
  4. package/lib/components/Details/index.d.ts.map +1 -1
  5. package/lib/components/Details/index.js +3 -2
  6. package/lib/components/Details/index.js.map +1 -1
  7. package/lib/components/Details/styles.module.css +4 -0
  8. package/lib/contexts/announcementBar.js +1 -1
  9. package/lib/contexts/colorMode.d.ts.map +1 -1
  10. package/lib/contexts/colorMode.js +34 -16
  11. package/lib/contexts/colorMode.js.map +1 -1
  12. package/lib/contexts/docsPreferredVersion.d.ts +5 -2
  13. package/lib/contexts/docsPreferredVersion.d.ts.map +1 -1
  14. package/lib/contexts/docsPreferredVersion.js +5 -2
  15. package/lib/contexts/docsPreferredVersion.js.map +1 -1
  16. package/lib/contexts/docsSidebar.d.ts +9 -3
  17. package/lib/contexts/docsSidebar.d.ts.map +1 -1
  18. package/lib/contexts/docsSidebar.js +7 -6
  19. package/lib/contexts/docsSidebar.js.map +1 -1
  20. package/lib/contexts/navbarMobileSidebar.js +5 -5
  21. package/lib/contexts/navbarMobileSidebar.js.map +1 -1
  22. package/lib/contexts/{navbarSecondaryMenu.d.ts → navbarSecondaryMenu/content.d.ts} +13 -14
  23. package/lib/contexts/navbarSecondaryMenu/content.d.ts.map +1 -0
  24. package/lib/contexts/navbarSecondaryMenu/content.js +56 -0
  25. package/lib/contexts/navbarSecondaryMenu/content.js.map +1 -0
  26. package/lib/contexts/navbarSecondaryMenu/display.d.ts +24 -0
  27. package/lib/contexts/navbarSecondaryMenu/display.d.ts.map +1 -0
  28. package/lib/contexts/navbarSecondaryMenu/display.js +62 -0
  29. package/lib/contexts/navbarSecondaryMenu/display.js.map +1 -0
  30. package/lib/contexts/tabGroupChoice.d.ts.map +1 -1
  31. package/lib/contexts/tabGroupChoice.js.map +1 -1
  32. package/lib/hooks/useBackToTopButton.d.ts +27 -0
  33. package/lib/hooks/useBackToTopButton.d.ts.map +1 -0
  34. package/lib/hooks/useBackToTopButton.js +50 -0
  35. package/lib/hooks/useBackToTopButton.js.map +1 -0
  36. package/lib/hooks/useCodeWordWrap.d.ts +14 -0
  37. package/lib/hooks/useCodeWordWrap.d.ts.map +1 -0
  38. package/lib/hooks/useCodeWordWrap.js +41 -0
  39. package/lib/hooks/useCodeWordWrap.js.map +1 -0
  40. package/lib/hooks/useHideableNavbar.d.ts.map +1 -1
  41. package/lib/hooks/useHideableNavbar.js +1 -2
  42. package/lib/hooks/useHideableNavbar.js.map +1 -1
  43. package/lib/hooks/usePrismTheme.d.ts +2 -2
  44. package/lib/hooks/usePrismTheme.d.ts.map +1 -1
  45. package/lib/hooks/usePrismTheme.js +1 -2
  46. package/lib/hooks/usePrismTheme.js.map +1 -1
  47. package/lib/hooks/useSkipToContent.d.ts +25 -0
  48. package/lib/hooks/useSkipToContent.d.ts.map +1 -0
  49. package/lib/hooks/useSkipToContent.js +35 -0
  50. package/lib/hooks/useSkipToContent.js.map +1 -0
  51. package/lib/hooks/useTOCHighlight.js +3 -3
  52. package/lib/hooks/useTOCHighlight.js.map +1 -1
  53. package/lib/index.d.ts +9 -6
  54. package/lib/index.d.ts.map +1 -1
  55. package/lib/index.js +8 -5
  56. package/lib/index.js.map +1 -1
  57. package/lib/utils/codeBlockUtils.d.ts +42 -12
  58. package/lib/utils/codeBlockUtils.d.ts.map +1 -1
  59. package/lib/utils/codeBlockUtils.js +89 -58
  60. package/lib/utils/codeBlockUtils.js.map +1 -1
  61. package/lib/utils/docsUtils.d.ts +58 -0
  62. package/lib/utils/docsUtils.d.ts.map +1 -1
  63. package/lib/utils/docsUtils.js +109 -10
  64. package/lib/utils/docsUtils.js.map +1 -1
  65. package/lib/utils/metadataUtils.d.ts +2 -2
  66. package/lib/utils/metadataUtils.d.ts.map +1 -1
  67. package/lib/utils/navbarUtils.d.ts +2 -2
  68. package/lib/utils/navbarUtils.d.ts.map +1 -1
  69. package/lib/utils/navbarUtils.js +7 -5
  70. package/lib/utils/navbarUtils.js.map +1 -1
  71. package/lib/utils/routesUtils.d.ts +4 -4
  72. package/lib/utils/routesUtils.d.ts.map +1 -1
  73. package/lib/utils/routesUtils.js.map +1 -1
  74. package/lib/utils/scrollUtils.d.ts +24 -0
  75. package/lib/utils/scrollUtils.d.ts.map +1 -1
  76. package/lib/utils/scrollUtils.js +52 -0
  77. package/lib/utils/scrollUtils.js.map +1 -1
  78. package/lib/utils/searchUtils.d.ts.map +1 -1
  79. package/lib/utils/searchUtils.js +2 -0
  80. package/lib/utils/searchUtils.js.map +1 -1
  81. package/lib/utils/storageUtils.d.ts +2 -2
  82. package/lib/utils/storageUtils.d.ts.map +1 -1
  83. package/lib/utils/tagsUtils.d.ts +3 -7
  84. package/lib/utils/tagsUtils.d.ts.map +1 -1
  85. package/lib/utils/tagsUtils.js +2 -2
  86. package/lib/utils/tagsUtils.js.map +1 -1
  87. package/lib/utils/tocUtils.d.ts +2 -2
  88. package/lib/utils/tocUtils.d.ts.map +1 -1
  89. package/lib/utils/tocUtils.js +4 -4
  90. package/lib/utils/tocUtils.js.map +1 -1
  91. package/lib/utils/useThemeConfig.d.ts +7 -4
  92. package/lib/utils/useThemeConfig.d.ts.map +1 -1
  93. package/lib/utils/useThemeConfig.js.map +1 -1
  94. package/package.json +18 -10
  95. package/src/components/Collapsible/index.tsx +2 -2
  96. package/src/components/Details/index.tsx +4 -2
  97. package/src/components/Details/styles.module.css +4 -0
  98. package/src/contexts/announcementBar.tsx +1 -1
  99. package/src/contexts/colorMode.tsx +38 -15
  100. package/src/contexts/docsPreferredVersion.tsx +5 -2
  101. package/src/contexts/docsSidebar.tsx +17 -9
  102. package/src/contexts/navbarMobileSidebar.tsx +5 -5
  103. package/src/contexts/navbarSecondaryMenu/content.tsx +110 -0
  104. package/src/contexts/navbarSecondaryMenu/display.tsx +102 -0
  105. package/src/contexts/tabGroupChoice.tsx +6 -3
  106. package/src/hooks/useBackToTopButton.ts +73 -0
  107. package/src/hooks/useCodeWordWrap.ts +56 -0
  108. package/src/hooks/useHideableNavbar.ts +1 -3
  109. package/src/hooks/usePrismTheme.ts +3 -3
  110. package/src/hooks/useSkipToContent.ts +58 -0
  111. package/src/hooks/useTOCHighlight.ts +3 -3
  112. package/src/index.ts +12 -5
  113. package/src/utils/codeBlockUtils.ts +150 -66
  114. package/src/utils/docsUtils.tsx +163 -9
  115. package/src/utils/metadataUtils.tsx +2 -2
  116. package/src/utils/navbarUtils.tsx +11 -6
  117. package/src/utils/routesUtils.ts +7 -7
  118. package/src/utils/scrollUtils.tsx +74 -0
  119. package/src/utils/searchUtils.ts +2 -0
  120. package/src/utils/storageUtils.ts +2 -2
  121. package/src/utils/tagsUtils.ts +4 -9
  122. package/src/utils/tocUtils.ts +5 -5
  123. package/src/utils/useThemeConfig.ts +7 -4
  124. package/yarn-error.log +20199 -0
  125. package/lib/contexts/navbarSecondaryMenu.d.ts.map +0 -1
  126. package/lib/contexts/navbarSecondaryMenu.js +0 -93
  127. package/lib/contexts/navbarSecondaryMenu.js.map +0 -1
  128. package/src/contexts/navbarSecondaryMenu.tsx +0 -170
@@ -12,9 +12,9 @@ import React, {
12
12
  useMemo,
13
13
  type ReactNode,
14
14
  } from 'react';
15
+ import {useNavbarSecondaryMenuContent} from './navbarSecondaryMenu/content';
15
16
  import {useWindowSize} from '../hooks/useWindowSize';
16
17
  import {useHistoryPopHandler} from '../utils/historyUtils';
17
- import {useActivePlugin} from '@docusaurus/plugin-content-docs/client';
18
18
  import {useThemeConfig} from '../utils/useThemeConfig';
19
19
  import {ReactContextError} from '../utils/reactUtils';
20
20
 
@@ -40,9 +40,9 @@ type ContextValue = {
40
40
  const Context = React.createContext<ContextValue | undefined>(undefined);
41
41
 
42
42
  function useIsNavbarMobileSidebarDisabled() {
43
- const activeDocPlugin = useActivePlugin();
43
+ const secondaryMenuContent = useNavbarSecondaryMenuContent();
44
44
  const {items} = useThemeConfig().navbar;
45
- return items.length === 0 && !activeDocPlugin;
45
+ return items.length === 0 && !secondaryMenuContent.component;
46
46
  }
47
47
 
48
48
  function useContextValue(): ContextValue {
@@ -58,9 +58,9 @@ function useContextValue(): ContextValue {
58
58
  useHistoryPopHandler(() => {
59
59
  if (shown) {
60
60
  setShown(false);
61
- // Should we prevent the navigation here?
61
+ // Prevent pop navigation; seems desirable enough
62
62
  // See https://github.com/facebook/docusaurus/pull/5462#issuecomment-911699846
63
- return false; // prevent pop navigation
63
+ return false;
64
64
  }
65
65
  return undefined;
66
66
  });
@@ -0,0 +1,110 @@
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, {
9
+ useState,
10
+ useContext,
11
+ useEffect,
12
+ useMemo,
13
+ type ReactNode,
14
+ type ComponentType,
15
+ } from 'react';
16
+ import {ReactContextError} from '../../utils/reactUtils';
17
+
18
+ // This context represents a "global layout store". A component (usually a
19
+ // layout component) can request filling this store through
20
+ // `NavbarSecondaryMenuFiller`. It doesn't actually control rendering by itself,
21
+ // and this context should be considered internal implementation. The user-
22
+ // facing value comes from `display.tsx`, which takes the `component` and
23
+ // `props` stored here and renders the actual element.
24
+
25
+ export type NavbarSecondaryMenuComponent<Props> = ComponentType<Props>;
26
+
27
+ /** @internal */
28
+ export type Content =
29
+ | {
30
+ component: NavbarSecondaryMenuComponent<object>;
31
+ props: object;
32
+ }
33
+ | {component: null; props: null};
34
+
35
+ type ContextValue = [
36
+ content: Content,
37
+ setContent: React.Dispatch<React.SetStateAction<Content>>,
38
+ ];
39
+
40
+ const Context = React.createContext<ContextValue | null>(null);
41
+
42
+ /** @internal */
43
+ export function NavbarSecondaryMenuContentProvider({
44
+ children,
45
+ }: {
46
+ children: ReactNode;
47
+ }): JSX.Element {
48
+ const value = useState({component: null, props: null});
49
+ return (
50
+ // @ts-expect-error: this context is hard to type
51
+ <Context.Provider value={value}>{children}</Context.Provider>
52
+ );
53
+ }
54
+
55
+ /** @internal */
56
+ export function useNavbarSecondaryMenuContent(): Content {
57
+ const value = useContext(Context);
58
+ if (!value) {
59
+ throw new ReactContextError('NavbarSecondaryMenuContentProvider');
60
+ }
61
+ return value[0];
62
+ }
63
+
64
+ function useShallowMemoizedObject<O>(obj: O) {
65
+ return useMemo(
66
+ () => obj,
67
+ // Is this safe?
68
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
+ [...Object.keys(obj), ...Object.values(obj)],
70
+ );
71
+ }
72
+
73
+ /**
74
+ * This component renders nothing by itself, but it fills the placeholder in the
75
+ * generic secondary menu layout. This reduces coupling between the main layout
76
+ * and the specific page.
77
+ *
78
+ * This kind of feature is often called portal/teleport/gateway/outlet...
79
+ * Various unmaintained React libs exist. Most up-to-date one:
80
+ * https://github.com/gregberge/react-teleporter
81
+ * Not sure any of those is safe regarding concurrent mode.
82
+ */
83
+ export function NavbarSecondaryMenuFiller<P extends object>({
84
+ component,
85
+ props,
86
+ }: {
87
+ component: NavbarSecondaryMenuComponent<P>;
88
+ props: P;
89
+ }): JSX.Element | null {
90
+ const context = useContext(Context);
91
+ if (!context) {
92
+ throw new ReactContextError('NavbarSecondaryMenuContentProvider');
93
+ }
94
+ const [, setContent] = context;
95
+
96
+ // To avoid useless context re-renders, props are memoized shallowly
97
+ const memoizedProps = useShallowMemoizedObject(props);
98
+
99
+ useEffect(() => {
100
+ // @ts-expect-error: this context is hard to type
101
+ setContent({component, props: memoizedProps});
102
+ }, [setContent, component, memoizedProps]);
103
+
104
+ useEffect(
105
+ () => () => setContent({component: null, props: null}),
106
+ [setContent],
107
+ );
108
+
109
+ return null;
110
+ }
@@ -0,0 +1,102 @@
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, {
9
+ useState,
10
+ useContext,
11
+ useEffect,
12
+ useMemo,
13
+ useCallback,
14
+ type ReactNode,
15
+ } from 'react';
16
+ import {ReactContextError, usePrevious} from '../../utils/reactUtils';
17
+ import {useNavbarMobileSidebar} from '../navbarMobileSidebar';
18
+ import {useNavbarSecondaryMenuContent, type Content} from './content';
19
+
20
+ type ContextValue = [
21
+ shown: boolean,
22
+ setShown: React.Dispatch<React.SetStateAction<boolean>>,
23
+ ];
24
+
25
+ const Context = React.createContext<ContextValue | null>(null);
26
+
27
+ function useContextValue(): ContextValue {
28
+ const mobileSidebar = useNavbarMobileSidebar();
29
+ const content = useNavbarSecondaryMenuContent();
30
+
31
+ const [shown, setShown] = useState(false);
32
+
33
+ const hasContent = content.component !== null;
34
+ const previousHasContent = usePrevious(hasContent);
35
+
36
+ // When content is become available for the first time (set in useEffect)
37
+ // we set this content to be shown!
38
+ useEffect(() => {
39
+ const contentBecameAvailable = hasContent && !previousHasContent;
40
+ if (contentBecameAvailable) {
41
+ setShown(true);
42
+ }
43
+ }, [hasContent, previousHasContent]);
44
+
45
+ // On sidebar close, secondary menu is set to be shown on next re-opening
46
+ // (if any secondary menu content available)
47
+ useEffect(() => {
48
+ if (!hasContent) {
49
+ setShown(false);
50
+ return;
51
+ }
52
+ if (!mobileSidebar.shown) {
53
+ setShown(true);
54
+ }
55
+ }, [mobileSidebar.shown, hasContent]);
56
+
57
+ return useMemo(() => [shown, setShown], [shown]);
58
+ }
59
+
60
+ /** @internal */
61
+ export function NavbarSecondaryMenuDisplayProvider({
62
+ children,
63
+ }: {
64
+ children: ReactNode;
65
+ }): JSX.Element {
66
+ const value = useContextValue();
67
+ return <Context.Provider value={value}>{children}</Context.Provider>;
68
+ }
69
+
70
+ function renderElement(content: Content): JSX.Element | undefined {
71
+ if (content.component) {
72
+ const Comp = content.component;
73
+ return <Comp {...content.props} />;
74
+ }
75
+ return undefined;
76
+ }
77
+
78
+ /** Wires the logic for rendering the mobile navbar secondary menu. */
79
+ export function useNavbarSecondaryMenu(): {
80
+ /** Whether secondary menu is displayed. */
81
+ shown: boolean;
82
+ /**
83
+ * Hide the secondary menu; fired either when hiding the entire sidebar, or
84
+ * when going back to the primary menu.
85
+ */
86
+ hide: () => void;
87
+ /** The content returned from the current secondary menu filler. */
88
+ content: JSX.Element | undefined;
89
+ } {
90
+ const value = useContext(Context);
91
+ if (!value) {
92
+ throw new ReactContextError('NavbarSecondaryMenuDisplayProvider');
93
+ }
94
+ const [shown, setShown] = value;
95
+ const hide = useCallback(() => setShown(false), [setShown]);
96
+ const content = useNavbarSecondaryMenuContent();
97
+
98
+ return useMemo(
99
+ () => ({shown, hide, content: renderElement(content)}),
100
+ [hide, content, shown],
101
+ );
102
+ }
@@ -31,9 +31,12 @@ function useContextValue(): ContextValue {
31
31
  const [tabGroupChoices, setChoices] = useState<{
32
32
  readonly [groupId: string]: string;
33
33
  }>({});
34
- const setChoiceSyncWithLocalStorage = useCallback((groupId, newChoice) => {
35
- createStorageSlot(`${TAB_CHOICE_PREFIX}${groupId}`).set(newChoice);
36
- }, []);
34
+ const setChoiceSyncWithLocalStorage = useCallback(
35
+ (groupId: string, newChoice: string) => {
36
+ createStorageSlot(`${TAB_CHOICE_PREFIX}${groupId}`).set(newChoice);
37
+ },
38
+ [],
39
+ );
37
40
 
38
41
  useEffect(() => {
39
42
  try {
@@ -0,0 +1,73 @@
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 {useRef, useState} from 'react';
9
+ import {useScrollPosition, useSmoothScrollTo} from '../utils/scrollUtils';
10
+ import {useLocationChange} from '../utils/useLocationChange';
11
+
12
+ /** Wires the logic for the back to top button. */
13
+ export function useBackToTopButton({
14
+ threshold,
15
+ }: {
16
+ /**
17
+ * The minimum vertical scroll position, above which a scroll-up would not
18
+ * cause `shown` to become `true`. This is because BTT is only useful if the
19
+ * user is far down the page.
20
+ */
21
+ threshold: number;
22
+ }): {
23
+ /**
24
+ * Whether the button should be displayed. We only show if the user has
25
+ * scrolled up and is on a vertical position greater than `threshold`.
26
+ */
27
+ shown: boolean;
28
+ /**
29
+ * A (memoized) handle for starting the scroll, which you can directly plug
30
+ * into the props.
31
+ */
32
+ scrollToTop: () => void;
33
+ } {
34
+ const [shown, setShown] = useState(false);
35
+ const isFocusedAnchor = useRef(false);
36
+ const {startScroll, cancelScroll} = useSmoothScrollTo();
37
+
38
+ useScrollPosition(({scrollY: scrollTop}, lastPosition) => {
39
+ const lastScrollTop = lastPosition?.scrollY;
40
+ // Component is just being mounted. Not really a scroll event from the user.
41
+ // Ignore it.
42
+ if (!lastScrollTop) {
43
+ return;
44
+ }
45
+ if (isFocusedAnchor.current) {
46
+ // This scroll position change is triggered by navigating to an anchor.
47
+ // Ignore it.
48
+ isFocusedAnchor.current = false;
49
+ } else if (scrollTop >= lastScrollTop) {
50
+ // The user has scrolled down to "fight against" the animation. Cancel any
51
+ // animation under progress.
52
+ cancelScroll();
53
+ setShown(false);
54
+ } else if (scrollTop < threshold) {
55
+ // Scrolled to the minimum position; hide the button.
56
+ setShown(false);
57
+ } else if (
58
+ scrollTop + window.innerHeight <
59
+ document.documentElement.scrollHeight
60
+ ) {
61
+ setShown(true);
62
+ }
63
+ });
64
+
65
+ useLocationChange((locationChangeEvent) => {
66
+ if (locationChangeEvent.location.hash) {
67
+ isFocusedAnchor.current = true;
68
+ setShown(false);
69
+ }
70
+ });
71
+
72
+ return {shown, scrollToTop: () => startScroll(0)};
73
+ }
@@ -0,0 +1,56 @@
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 type {RefObject} from 'react';
9
+ import {useState, useCallback, useEffect, useRef} from 'react';
10
+
11
+ export function useCodeWordWrap(): {
12
+ readonly codeBlockRef: RefObject<HTMLPreElement>;
13
+ readonly isEnabled: boolean;
14
+ readonly isCodeScrollable: boolean;
15
+ readonly toggle: () => void;
16
+ } {
17
+ const [isEnabled, setIsEnabled] = useState(false);
18
+ const [isCodeScrollable, setIsCodeScrollable] = useState<boolean>(false);
19
+ const codeBlockRef = useRef<HTMLPreElement>(null);
20
+
21
+ const toggle = useCallback(() => {
22
+ const codeElement = codeBlockRef.current!.querySelector('code')!;
23
+
24
+ if (isEnabled) {
25
+ codeElement.removeAttribute('style');
26
+ } else {
27
+ codeElement.style.whiteSpace = 'pre-wrap';
28
+ }
29
+
30
+ setIsEnabled((value) => !value);
31
+ }, [codeBlockRef, isEnabled]);
32
+
33
+ const updateCodeIsScrollable = useCallback(() => {
34
+ const {scrollWidth, clientWidth} = codeBlockRef.current!;
35
+ const isScrollable =
36
+ scrollWidth > clientWidth ||
37
+ codeBlockRef.current!.querySelector('code')!.hasAttribute('style');
38
+ setIsCodeScrollable(isScrollable);
39
+ }, [codeBlockRef]);
40
+
41
+ useEffect(() => {
42
+ updateCodeIsScrollable();
43
+ }, [isEnabled, updateCodeIsScrollable]);
44
+
45
+ useEffect(() => {
46
+ window.addEventListener('resize', updateCodeIsScrollable, {
47
+ passive: true,
48
+ });
49
+
50
+ return () => {
51
+ window.removeEventListener('resize', updateCodeIsScrollable);
52
+ };
53
+ }, [updateCodeIsScrollable]);
54
+
55
+ return {codeBlockRef, isEnabled, isCodeScrollable, toggle};
56
+ }
@@ -28,13 +28,11 @@ export function useHideableNavbar(hideOnScroll: boolean): {
28
28
  }
29
29
  }, []);
30
30
 
31
- useScrollPosition((currentPosition, lastPosition) => {
31
+ useScrollPosition(({scrollY: scrollTop}, lastPosition) => {
32
32
  if (!hideOnScroll) {
33
33
  return;
34
34
  }
35
35
 
36
- const scrollTop = currentPosition.scrollY;
37
-
38
36
  // Needed mostly for handling rubber band scrolling.
39
37
  // See https://github.com/facebook/docusaurus/pull/5721
40
38
  if (scrollTop < navbarHeight.current) {
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import defaultTheme from 'prism-react-renderer/themes/palenight';
8
+ import type {PrismTheme} from 'prism-react-renderer';
9
9
  import {useColorMode} from '../contexts/colorMode';
10
10
  import {useThemeConfig} from '../utils/useThemeConfig';
11
11
 
@@ -13,10 +13,10 @@ import {useThemeConfig} from '../utils/useThemeConfig';
13
13
  * Returns a color-mode-dependent Prism theme: whatever the user specified in
14
14
  * the config. Falls back to `palenight`.
15
15
  */
16
- export function usePrismTheme(): typeof defaultTheme {
16
+ export function usePrismTheme(): PrismTheme {
17
17
  const {prism} = useThemeConfig();
18
18
  const {colorMode} = useColorMode();
19
- const lightModeTheme = prism.theme || defaultTheme;
19
+ const lightModeTheme = prism.theme;
20
20
  const darkModeTheme = prism.darkTheme || lightModeTheme;
21
21
  const prismTheme = colorMode === 'dark' ? darkModeTheme : lightModeTheme;
22
22
 
@@ -0,0 +1,58 @@
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 type React from 'react';
9
+ import {useCallback, useRef} from 'react';
10
+ import {useHistory} from '@docusaurus/router';
11
+ import {useLocationChange} from '../utils/useLocationChange';
12
+ import {ThemeClassNames} from '../utils/ThemeClassNames';
13
+
14
+ function programmaticFocus(el: HTMLElement) {
15
+ el.setAttribute('tabindex', '-1');
16
+ el.focus();
17
+ el.removeAttribute('tabindex');
18
+ }
19
+
20
+ /** This hook wires the logic for a skip-to-content link. */
21
+ export function useSkipToContent(): {
22
+ /**
23
+ * The ref to the container. On page transition, the container will be focused
24
+ * so that keyboard navigators can instantly interact with the link and jump
25
+ * to content. **Note:** the type is `RefObject<HTMLDivElement>` only because
26
+ * the typing for refs don't reflect that the `ref` prop is contravariant, so
27
+ * using `HTMLElement` causes type-checking to fail. You can plug the ref into
28
+ * any HTML element, as long as it can be focused.
29
+ */
30
+ containerRef: React.RefObject<HTMLDivElement>;
31
+ /**
32
+ * Callback fired when the skip to content link has been interacted with. It
33
+ * will programmatically focus the main content.
34
+ */
35
+ handleSkip: (e: React.MouseEvent<HTMLAnchorElement>) => void;
36
+ } {
37
+ const containerRef = useRef<HTMLDivElement>(null);
38
+ const {action} = useHistory();
39
+ const handleSkip = useCallback((e: React.MouseEvent<HTMLAnchorElement>) => {
40
+ e.preventDefault();
41
+
42
+ const targetElement: HTMLElement | null =
43
+ document.querySelector('main:first-of-type') ||
44
+ document.querySelector(`.${ThemeClassNames.wrapper.main}`);
45
+
46
+ if (targetElement) {
47
+ programmaticFocus(targetElement);
48
+ }
49
+ }, []);
50
+
51
+ useLocationChange(({location}) => {
52
+ if (containerRef.current && !location.hash && action === 'PUSH') {
53
+ programmaticFocus(containerRef.current);
54
+ }
55
+ });
56
+
57
+ return {containerRef, handleSkip};
58
+ }
@@ -81,8 +81,8 @@ function getActiveAnchor(
81
81
  // https://github.com/facebook/docusaurus/issues/5318
82
82
  return anchors[anchors.indexOf(nextVisibleAnchor) - 1] ?? null;
83
83
  }
84
- // no anchor under viewport top? (ie we are at the bottom of the page)
85
- // => highlight the last anchor found
84
+ // No anchor under viewport top (i.e. we are at the bottom of the page),
85
+ // highlight the last anchor found
86
86
  return anchors[anchors.length - 1] ?? null;
87
87
  }
88
88
 
@@ -140,7 +140,7 @@ export function useTOCHighlight(config: TOCHighlightConfig | undefined): void {
140
140
 
141
141
  useEffect(() => {
142
142
  if (!config) {
143
- // no-op, highlighting is disabled
143
+ // No-op, highlighting is disabled
144
144
  return () => {};
145
145
  }
146
146
 
package/src/index.ts CHANGED
@@ -34,6 +34,8 @@ export {
34
34
  parseCodeBlockTitle,
35
35
  parseLanguage,
36
36
  parseLines,
37
+ containsLineNumbers,
38
+ getPrismCssVariables,
37
39
  } from './utils/codeBlockUtils';
38
40
 
39
41
  export {
@@ -50,6 +52,10 @@ export {
50
52
  useCurrentSidebarCategory,
51
53
  isActiveSidebarItem,
52
54
  useSidebarBreadcrumbs,
55
+ useDocsVersionCandidates,
56
+ useLayoutDoc,
57
+ useLayoutDocsSidebar,
58
+ useDocRouteMetadata,
53
59
  } from './utils/docsUtils';
54
60
 
55
61
  export {useTitleFormatter} from './utils/generalUtils';
@@ -60,8 +66,6 @@ export {useLocationChange} from './utils/useLocationChange';
60
66
 
61
67
  export {useCollapsible, Collapsible} from './components/Collapsible';
62
68
 
63
- export {Details, type DetailsProps} from './components/Details';
64
-
65
69
  export {
66
70
  useDocsPreferredVersion,
67
71
  useDocsPreferredVersionByPluginId,
@@ -83,7 +87,6 @@ export {
83
87
  translateTagsPageTitle,
84
88
  listTagsByLetters,
85
89
  type TagLetterEntry,
86
- type TagsListItem,
87
90
  } from './utils/tagsUtils';
88
91
 
89
92
  export {useHistoryPopHandler} from './utils/historyUtils';
@@ -106,6 +109,7 @@ export {
106
109
  useScrollController,
107
110
  useScrollPosition,
108
111
  useScrollPositionBlocker,
112
+ useSmoothScrollTo,
109
113
  } from './utils/scrollUtils';
110
114
 
111
115
  export {
@@ -140,11 +144,12 @@ export {
140
144
 
141
145
  export {useNavbarMobileSidebar} from './contexts/navbarMobileSidebar';
142
146
  export {
143
- useNavbarSecondaryMenu,
144
147
  NavbarSecondaryMenuFiller,
145
148
  type NavbarSecondaryMenuComponent,
146
- } from './contexts/navbarSecondaryMenu';
149
+ } from './contexts/navbarSecondaryMenu/content';
150
+ export {useNavbarSecondaryMenu} from './contexts/navbarSecondaryMenu/display';
147
151
 
152
+ export {useBackToTopButton} from './hooks/useBackToTopButton';
148
153
  export {useHideableNavbar} from './hooks/useHideableNavbar';
149
154
  export {
150
155
  useKeyboardNavigation,
@@ -154,3 +159,5 @@ export {usePrismTheme} from './hooks/usePrismTheme';
154
159
  export {useLockBodyScroll} from './hooks/useLockBodyScroll';
155
160
  export {useWindowSize} from './hooks/useWindowSize';
156
161
  export {useSearchPage} from './hooks/useSearchPage';
162
+ export {useCodeWordWrap} from './hooks/useCodeWordWrap';
163
+ export {useSkipToContent} from './hooks/useSkipToContent';