@docusaurus/theme-classic 3.7.0-canary-6272 → 3.7.0-canary-6274
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/theme/NavbarItem/DefaultNavbarItem/Desktop/index.d.ts +9 -0
- package/lib/theme/NavbarItem/DefaultNavbarItem/Desktop/index.js +29 -0
- package/lib/theme/NavbarItem/DefaultNavbarItem/Mobile/index.d.ts +9 -0
- package/lib/theme/NavbarItem/DefaultNavbarItem/Mobile/index.js +20 -0
- package/lib/theme/NavbarItem/DefaultNavbarItem/index.js +25 -0
- package/lib/theme/NavbarItem/DropdownNavbarItem/Desktop/index.d.ts +9 -0
- package/lib/theme/NavbarItem/DropdownNavbarItem/Desktop/index.js +74 -0
- package/lib/theme/NavbarItem/DropdownNavbarItem/Mobile/index.d.ts +10 -0
- package/lib/theme/NavbarItem/DropdownNavbarItem/Mobile/index.js +142 -0
- package/lib/theme/NavbarItem/DropdownNavbarItem/index.js +3 -146
- package/package.json +15 -15
- package/src/theme/NavbarItem/DefaultNavbarItem/Desktop/index.tsx +34 -0
- package/src/theme/NavbarItem/DefaultNavbarItem/Mobile/index.tsx +23 -0
- package/src/theme/NavbarItem/DefaultNavbarItem/index.tsx +28 -0
- package/src/theme/NavbarItem/DropdownNavbarItem/Desktop/index.tsx +86 -0
- package/src/theme/NavbarItem/DropdownNavbarItem/Mobile/index.tsx +166 -0
- package/src/theme/NavbarItem/DropdownNavbarItem/index.tsx +4 -172
- package/src/theme-classic.d.ts +46 -4
- package/lib/theme/NavbarItem/DefaultNavbarItem.js +0 -52
- package/src/theme/NavbarItem/DefaultNavbarItem.tsx +0 -66
- /package/lib/theme/NavbarItem/{DefaultNavbarItem.d.ts → DefaultNavbarItem/index.d.ts} +0 -0
- /package/lib/theme/NavbarItem/DropdownNavbarItem/{styles.module.css → Mobile/styles.module.css} +0 -0
- /package/src/theme/NavbarItem/DropdownNavbarItem/{styles.module.css → Mobile/styles.module.css} +0 -0
|
@@ -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
|
+
}
|
|
@@ -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;
|
|
@@ -0,0 +1,142 @@
|
|
|
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, {useEffect} from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import {
|
|
10
|
+
isRegexpStringMatch,
|
|
11
|
+
useCollapsible,
|
|
12
|
+
Collapsible,
|
|
13
|
+
} from '@docusaurus/theme-common';
|
|
14
|
+
import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal';
|
|
15
|
+
import {translate} from '@docusaurus/Translate';
|
|
16
|
+
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
17
|
+
import NavbarItem from '@theme/NavbarItem';
|
|
18
|
+
import styles from './styles.module.css';
|
|
19
|
+
function isItemActive(item, localPathname) {
|
|
20
|
+
if (isSamePath(item.to, localPathname)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
function containsActiveItems(items, localPathname) {
|
|
32
|
+
return items.some((item) => isItemActive(item, localPathname));
|
|
33
|
+
}
|
|
34
|
+
function CollapseButton({collapsed, onClick}) {
|
|
35
|
+
return (
|
|
36
|
+
<button
|
|
37
|
+
aria-label={
|
|
38
|
+
collapsed
|
|
39
|
+
? translate({
|
|
40
|
+
id: 'theme.navbar.mobileDropdown.collapseButton.expandAriaLabel',
|
|
41
|
+
message: 'Expand the dropdown',
|
|
42
|
+
description:
|
|
43
|
+
'The ARIA label of the button to expand the mobile dropdown navbar item',
|
|
44
|
+
})
|
|
45
|
+
: translate({
|
|
46
|
+
id: 'theme.navbar.mobileDropdown.collapseButton.collapseAriaLabel',
|
|
47
|
+
message: 'Collapse the dropdown',
|
|
48
|
+
description:
|
|
49
|
+
'The ARIA label of the button to collapse the mobile dropdown navbar item',
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
aria-expanded={!collapsed}
|
|
53
|
+
type="button"
|
|
54
|
+
className="clean-btn menu__caret"
|
|
55
|
+
onClick={onClick}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
function useItemCollapsible({active}) {
|
|
60
|
+
const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({
|
|
61
|
+
initialState: () => !active,
|
|
62
|
+
});
|
|
63
|
+
// Expand if any item active after a navigation
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (active) {
|
|
66
|
+
setCollapsed(false);
|
|
67
|
+
}
|
|
68
|
+
}, [active, setCollapsed]);
|
|
69
|
+
return {
|
|
70
|
+
collapsed,
|
|
71
|
+
toggleCollapsed,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export default function DropdownNavbarItemMobile({
|
|
75
|
+
items,
|
|
76
|
+
className,
|
|
77
|
+
position, // Need to destructure position from props so that it doesn't get passed on.
|
|
78
|
+
onClick,
|
|
79
|
+
...props
|
|
80
|
+
}) {
|
|
81
|
+
const localPathname = useLocalPathname();
|
|
82
|
+
const isActive = isSamePath(props.to, localPathname);
|
|
83
|
+
const containsActive = containsActiveItems(items, localPathname);
|
|
84
|
+
const {collapsed, toggleCollapsed} = useItemCollapsible({
|
|
85
|
+
active: isActive || containsActive,
|
|
86
|
+
});
|
|
87
|
+
// # hash permits to make the <a> tag focusable in case no link target
|
|
88
|
+
// See https://github.com/facebook/docusaurus/pull/6003
|
|
89
|
+
// There's probably a better solution though...
|
|
90
|
+
const href = props.to ? undefined : '#';
|
|
91
|
+
return (
|
|
92
|
+
<li
|
|
93
|
+
className={clsx('menu__list-item', {
|
|
94
|
+
'menu__list-item--collapsed': collapsed,
|
|
95
|
+
})}>
|
|
96
|
+
<div
|
|
97
|
+
className={clsx('menu__list-item-collapsible', {
|
|
98
|
+
'menu__list-item-collapsible--active': isActive,
|
|
99
|
+
})}>
|
|
100
|
+
<NavbarNavLink
|
|
101
|
+
role="button"
|
|
102
|
+
className={clsx(
|
|
103
|
+
styles.dropdownNavbarItemMobile,
|
|
104
|
+
'menu__link menu__link--sublist',
|
|
105
|
+
className,
|
|
106
|
+
)}
|
|
107
|
+
href={href}
|
|
108
|
+
{...props}
|
|
109
|
+
onClick={(e) => {
|
|
110
|
+
// Prevent navigation when link is "#"
|
|
111
|
+
if (href === '#') {
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
}
|
|
114
|
+
// Otherwise we let navigation eventually happen, and/or collapse
|
|
115
|
+
toggleCollapsed();
|
|
116
|
+
}}>
|
|
117
|
+
{props.children ?? props.label}
|
|
118
|
+
</NavbarNavLink>
|
|
119
|
+
<CollapseButton
|
|
120
|
+
collapsed={collapsed}
|
|
121
|
+
onClick={(e) => {
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
toggleCollapsed();
|
|
124
|
+
}}
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<Collapsible lazy as="ul" className="menu__list" collapsed={collapsed}>
|
|
129
|
+
{items.map((childItemProps, i) => (
|
|
130
|
+
<NavbarItem
|
|
131
|
+
mobile
|
|
132
|
+
isDropdownItem
|
|
133
|
+
onClick={onClick}
|
|
134
|
+
activeClassName="menu__link--active"
|
|
135
|
+
{...childItemProps}
|
|
136
|
+
key={i}
|
|
137
|
+
/>
|
|
138
|
+
))}
|
|
139
|
+
</Collapsible>
|
|
140
|
+
</li>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
@@ -4,152 +4,9 @@
|
|
|
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
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
isRegexpStringMatch,
|
|
11
|
-
useCollapsible,
|
|
12
|
-
Collapsible,
|
|
13
|
-
} from '@docusaurus/theme-common';
|
|
14
|
-
import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal';
|
|
15
|
-
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
16
|
-
import NavbarItem from '@theme/NavbarItem';
|
|
17
|
-
import styles from './styles.module.css';
|
|
18
|
-
function isItemActive(item, localPathname) {
|
|
19
|
-
if (isSamePath(item.to, localPathname)) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) {
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
function containsActiveItems(items, localPathname) {
|
|
31
|
-
return items.some((item) => isItemActive(item, localPathname));
|
|
32
|
-
}
|
|
33
|
-
function DropdownNavbarItemDesktop({
|
|
34
|
-
items,
|
|
35
|
-
position,
|
|
36
|
-
className,
|
|
37
|
-
onClick,
|
|
38
|
-
...props
|
|
39
|
-
}) {
|
|
40
|
-
const dropdownRef = useRef(null);
|
|
41
|
-
const [showDropdown, setShowDropdown] = useState(false);
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
const handleClickOutside = (event) => {
|
|
44
|
-
if (!dropdownRef.current || dropdownRef.current.contains(event.target)) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
setShowDropdown(false);
|
|
48
|
-
};
|
|
49
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
50
|
-
document.addEventListener('touchstart', handleClickOutside);
|
|
51
|
-
document.addEventListener('focusin', handleClickOutside);
|
|
52
|
-
return () => {
|
|
53
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
54
|
-
document.removeEventListener('touchstart', handleClickOutside);
|
|
55
|
-
document.removeEventListener('focusin', handleClickOutside);
|
|
56
|
-
};
|
|
57
|
-
}, [dropdownRef]);
|
|
58
|
-
return (
|
|
59
|
-
<div
|
|
60
|
-
ref={dropdownRef}
|
|
61
|
-
className={clsx('navbar__item', 'dropdown', 'dropdown--hoverable', {
|
|
62
|
-
'dropdown--right': position === 'right',
|
|
63
|
-
'dropdown--show': showDropdown,
|
|
64
|
-
})}>
|
|
65
|
-
<NavbarNavLink
|
|
66
|
-
aria-haspopup="true"
|
|
67
|
-
aria-expanded={showDropdown}
|
|
68
|
-
role="button"
|
|
69
|
-
// # hash permits to make the <a> tag focusable in case no link target
|
|
70
|
-
// See https://github.com/facebook/docusaurus/pull/6003
|
|
71
|
-
// There's probably a better solution though...
|
|
72
|
-
href={props.to ? undefined : '#'}
|
|
73
|
-
className={clsx('navbar__link', className)}
|
|
74
|
-
{...props}
|
|
75
|
-
onClick={props.to ? undefined : (e) => e.preventDefault()}
|
|
76
|
-
onKeyDown={(e) => {
|
|
77
|
-
if (e.key === 'Enter') {
|
|
78
|
-
e.preventDefault();
|
|
79
|
-
setShowDropdown(!showDropdown);
|
|
80
|
-
}
|
|
81
|
-
}}>
|
|
82
|
-
{props.children ?? props.label}
|
|
83
|
-
</NavbarNavLink>
|
|
84
|
-
<ul className="dropdown__menu">
|
|
85
|
-
{items.map((childItemProps, i) => (
|
|
86
|
-
<NavbarItem
|
|
87
|
-
isDropdownItem
|
|
88
|
-
activeClassName="dropdown__link--active"
|
|
89
|
-
{...childItemProps}
|
|
90
|
-
key={i}
|
|
91
|
-
/>
|
|
92
|
-
))}
|
|
93
|
-
</ul>
|
|
94
|
-
</div>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
function DropdownNavbarItemMobile({
|
|
98
|
-
items,
|
|
99
|
-
className,
|
|
100
|
-
position, // Need to destructure position from props so that it doesn't get passed on.
|
|
101
|
-
onClick,
|
|
102
|
-
...props
|
|
103
|
-
}) {
|
|
104
|
-
const localPathname = useLocalPathname();
|
|
105
|
-
const containsActive = containsActiveItems(items, localPathname);
|
|
106
|
-
const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({
|
|
107
|
-
initialState: () => !containsActive,
|
|
108
|
-
});
|
|
109
|
-
// Expand/collapse if any item active after a navigation
|
|
110
|
-
useEffect(() => {
|
|
111
|
-
if (containsActive) {
|
|
112
|
-
setCollapsed(!containsActive);
|
|
113
|
-
}
|
|
114
|
-
}, [localPathname, containsActive, setCollapsed]);
|
|
115
|
-
return (
|
|
116
|
-
<li
|
|
117
|
-
className={clsx('menu__list-item', {
|
|
118
|
-
'menu__list-item--collapsed': collapsed,
|
|
119
|
-
})}>
|
|
120
|
-
<NavbarNavLink
|
|
121
|
-
role="button"
|
|
122
|
-
className={clsx(
|
|
123
|
-
styles.dropdownNavbarItemMobile,
|
|
124
|
-
'menu__link menu__link--sublist menu__link--sublist-caret',
|
|
125
|
-
className,
|
|
126
|
-
)}
|
|
127
|
-
// # hash permits to make the <a> tag focusable in case no link target
|
|
128
|
-
// See https://github.com/facebook/docusaurus/pull/6003
|
|
129
|
-
// There's probably a better solution though...
|
|
130
|
-
href={props.to ? undefined : '#'}
|
|
131
|
-
{...props}
|
|
132
|
-
onClick={(e) => {
|
|
133
|
-
e.preventDefault();
|
|
134
|
-
toggleCollapsed();
|
|
135
|
-
}}>
|
|
136
|
-
{props.children ?? props.label}
|
|
137
|
-
</NavbarNavLink>
|
|
138
|
-
<Collapsible lazy as="ul" className="menu__list" collapsed={collapsed}>
|
|
139
|
-
{items.map((childItemProps, i) => (
|
|
140
|
-
<NavbarItem
|
|
141
|
-
mobile
|
|
142
|
-
isDropdownItem
|
|
143
|
-
onClick={onClick}
|
|
144
|
-
activeClassName="menu__link--active"
|
|
145
|
-
{...childItemProps}
|
|
146
|
-
key={i}
|
|
147
|
-
/>
|
|
148
|
-
))}
|
|
149
|
-
</Collapsible>
|
|
150
|
-
</li>
|
|
151
|
-
);
|
|
152
|
-
}
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import DropdownNavbarItemMobile from '@theme/NavbarItem/DropdownNavbarItem/Mobile';
|
|
9
|
+
import DropdownNavbarItemDesktop from '@theme/NavbarItem/DropdownNavbarItem/Desktop';
|
|
153
10
|
export default function DropdownNavbarItem({mobile = false, ...props}) {
|
|
154
11
|
const Comp = mobile ? DropdownNavbarItemMobile : DropdownNavbarItemDesktop;
|
|
155
12
|
return <Comp {...props} />;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/theme-classic",
|
|
3
|
-
"version": "3.7.0-canary-
|
|
3
|
+
"version": "3.7.0-canary-6274",
|
|
4
4
|
"description": "Classic theme for Docusaurus",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/theme-classic.d.ts",
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
"copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@docusaurus/core": "3.7.0-canary-
|
|
24
|
-
"@docusaurus/logger": "3.7.0-canary-
|
|
25
|
-
"@docusaurus/mdx-loader": "3.7.0-canary-
|
|
26
|
-
"@docusaurus/module-type-aliases": "3.7.0-canary-
|
|
27
|
-
"@docusaurus/plugin-content-blog": "3.7.0-canary-
|
|
28
|
-
"@docusaurus/plugin-content-docs": "3.7.0-canary-
|
|
29
|
-
"@docusaurus/plugin-content-pages": "3.7.0-canary-
|
|
30
|
-
"@docusaurus/theme-common": "3.7.0-canary-
|
|
31
|
-
"@docusaurus/theme-translations": "3.7.0-canary-
|
|
32
|
-
"@docusaurus/types": "3.7.0-canary-
|
|
33
|
-
"@docusaurus/utils": "3.7.0-canary-
|
|
34
|
-
"@docusaurus/utils-common": "3.7.0-canary-
|
|
35
|
-
"@docusaurus/utils-validation": "3.7.0-canary-
|
|
23
|
+
"@docusaurus/core": "3.7.0-canary-6274",
|
|
24
|
+
"@docusaurus/logger": "3.7.0-canary-6274",
|
|
25
|
+
"@docusaurus/mdx-loader": "3.7.0-canary-6274",
|
|
26
|
+
"@docusaurus/module-type-aliases": "3.7.0-canary-6274",
|
|
27
|
+
"@docusaurus/plugin-content-blog": "3.7.0-canary-6274",
|
|
28
|
+
"@docusaurus/plugin-content-docs": "3.7.0-canary-6274",
|
|
29
|
+
"@docusaurus/plugin-content-pages": "3.7.0-canary-6274",
|
|
30
|
+
"@docusaurus/theme-common": "3.7.0-canary-6274",
|
|
31
|
+
"@docusaurus/theme-translations": "3.7.0-canary-6274",
|
|
32
|
+
"@docusaurus/types": "3.7.0-canary-6274",
|
|
33
|
+
"@docusaurus/utils": "3.7.0-canary-6274",
|
|
34
|
+
"@docusaurus/utils-common": "3.7.0-canary-6274",
|
|
35
|
+
"@docusaurus/utils-validation": "3.7.0-canary-6274",
|
|
36
36
|
"@mdx-js/react": "^3.0.0",
|
|
37
37
|
"clsx": "^2.0.0",
|
|
38
38
|
"copy-text-to-clipboard": "^3.2.0",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"engines": {
|
|
63
63
|
"node": ">=18.0"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "c46c12c65ae718bb6352556f7e34e5adfd629856"
|
|
66
66
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
11
|
+
import type {Props} from '@theme/NavbarItem/DefaultNavbarItem/Desktop';
|
|
12
|
+
|
|
13
|
+
export default function DefaultNavbarItemDesktop({
|
|
14
|
+
className,
|
|
15
|
+
isDropdownItem = false,
|
|
16
|
+
...props
|
|
17
|
+
}: Props): ReactNode {
|
|
18
|
+
const element = (
|
|
19
|
+
<NavbarNavLink
|
|
20
|
+
className={clsx(
|
|
21
|
+
isDropdownItem ? 'dropdown__link' : 'navbar__item navbar__link',
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
isDropdownLink={isDropdownItem}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
if (isDropdownItem) {
|
|
30
|
+
return <li>{element}</li>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return element;
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
11
|
+
import type {Props} from '@theme/NavbarItem/DefaultNavbarItem/Mobile';
|
|
12
|
+
|
|
13
|
+
export default function DefaultNavbarItemMobile({
|
|
14
|
+
className,
|
|
15
|
+
isDropdownItem,
|
|
16
|
+
...props
|
|
17
|
+
}: Props): ReactNode {
|
|
18
|
+
return (
|
|
19
|
+
<li className="menu__list-item">
|
|
20
|
+
<NavbarNavLink className={clsx('menu__link', className)} {...props} />
|
|
21
|
+
</li>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import DefaultNavbarItemMobile from '@theme/NavbarItem/DefaultNavbarItem/Mobile';
|
|
10
|
+
import DefaultNavbarItemDesktop from '@theme/NavbarItem/DefaultNavbarItem/Desktop';
|
|
11
|
+
import type {Props} from '@theme/NavbarItem/DefaultNavbarItem';
|
|
12
|
+
|
|
13
|
+
export default function DefaultNavbarItem({
|
|
14
|
+
mobile = false,
|
|
15
|
+
position, // Need to destructure position from props so that it doesn't get passed on.
|
|
16
|
+
...props
|
|
17
|
+
}: Props): ReactNode {
|
|
18
|
+
const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop;
|
|
19
|
+
return (
|
|
20
|
+
<Comp
|
|
21
|
+
{...props}
|
|
22
|
+
activeClassName={
|
|
23
|
+
props.activeClassName ??
|
|
24
|
+
(mobile ? 'menu__link--active' : 'navbar__link--active')
|
|
25
|
+
}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
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, {useState, useRef, useEffect, type ReactNode} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
11
|
+
import NavbarItem from '@theme/NavbarItem';
|
|
12
|
+
import type {Props} from '@theme/NavbarItem/DropdownNavbarItem/Desktop';
|
|
13
|
+
|
|
14
|
+
export default function DropdownNavbarItemDesktop({
|
|
15
|
+
items,
|
|
16
|
+
position,
|
|
17
|
+
className,
|
|
18
|
+
onClick,
|
|
19
|
+
...props
|
|
20
|
+
}: Props): ReactNode {
|
|
21
|
+
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
22
|
+
const [showDropdown, setShowDropdown] = useState(false);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const handleClickOutside = (
|
|
26
|
+
event: MouseEvent | TouchEvent | FocusEvent,
|
|
27
|
+
) => {
|
|
28
|
+
if (
|
|
29
|
+
!dropdownRef.current ||
|
|
30
|
+
dropdownRef.current.contains(event.target as Node)
|
|
31
|
+
) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
setShowDropdown(false);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
38
|
+
document.addEventListener('touchstart', handleClickOutside);
|
|
39
|
+
document.addEventListener('focusin', handleClickOutside);
|
|
40
|
+
|
|
41
|
+
return () => {
|
|
42
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
43
|
+
document.removeEventListener('touchstart', handleClickOutside);
|
|
44
|
+
document.removeEventListener('focusin', handleClickOutside);
|
|
45
|
+
};
|
|
46
|
+
}, [dropdownRef]);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
ref={dropdownRef}
|
|
51
|
+
className={clsx('navbar__item', 'dropdown', 'dropdown--hoverable', {
|
|
52
|
+
'dropdown--right': position === 'right',
|
|
53
|
+
'dropdown--show': showDropdown,
|
|
54
|
+
})}>
|
|
55
|
+
<NavbarNavLink
|
|
56
|
+
aria-haspopup="true"
|
|
57
|
+
aria-expanded={showDropdown}
|
|
58
|
+
role="button"
|
|
59
|
+
// # hash permits to make the <a> tag focusable in case no link target
|
|
60
|
+
// See https://github.com/facebook/docusaurus/pull/6003
|
|
61
|
+
// There's probably a better solution though...
|
|
62
|
+
href={props.to ? undefined : '#'}
|
|
63
|
+
className={clsx('navbar__link', className)}
|
|
64
|
+
{...props}
|
|
65
|
+
onClick={props.to ? undefined : (e) => e.preventDefault()}
|
|
66
|
+
onKeyDown={(e) => {
|
|
67
|
+
if (e.key === 'Enter') {
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
setShowDropdown(!showDropdown);
|
|
70
|
+
}
|
|
71
|
+
}}>
|
|
72
|
+
{props.children ?? props.label}
|
|
73
|
+
</NavbarNavLink>
|
|
74
|
+
<ul className="dropdown__menu">
|
|
75
|
+
{items.map((childItemProps, i) => (
|
|
76
|
+
<NavbarItem
|
|
77
|
+
isDropdownItem
|
|
78
|
+
activeClassName="dropdown__link--active"
|
|
79
|
+
{...childItemProps}
|
|
80
|
+
key={i}
|
|
81
|
+
/>
|
|
82
|
+
))}
|
|
83
|
+
</ul>
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
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, {useEffect, type ReactNode, type ComponentProps} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import {
|
|
11
|
+
isRegexpStringMatch,
|
|
12
|
+
useCollapsible,
|
|
13
|
+
Collapsible,
|
|
14
|
+
} from '@docusaurus/theme-common';
|
|
15
|
+
import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal';
|
|
16
|
+
import {translate} from '@docusaurus/Translate';
|
|
17
|
+
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
18
|
+
import NavbarItem, {type LinkLikeNavbarItemProps} from '@theme/NavbarItem';
|
|
19
|
+
import type {Props} from '@theme/NavbarItem/DropdownNavbarItem/Mobile';
|
|
20
|
+
import styles from './styles.module.css';
|
|
21
|
+
|
|
22
|
+
function isItemActive(
|
|
23
|
+
item: LinkLikeNavbarItemProps,
|
|
24
|
+
localPathname: string,
|
|
25
|
+
): boolean {
|
|
26
|
+
if (isSamePath(item.to, localPathname)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function containsActiveItems(
|
|
39
|
+
items: readonly LinkLikeNavbarItemProps[],
|
|
40
|
+
localPathname: string,
|
|
41
|
+
): boolean {
|
|
42
|
+
return items.some((item) => isItemActive(item, localPathname));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function CollapseButton({
|
|
46
|
+
collapsed,
|
|
47
|
+
onClick,
|
|
48
|
+
}: {
|
|
49
|
+
collapsed: boolean;
|
|
50
|
+
onClick: ComponentProps<'button'>['onClick'];
|
|
51
|
+
}) {
|
|
52
|
+
return (
|
|
53
|
+
<button
|
|
54
|
+
aria-label={
|
|
55
|
+
collapsed
|
|
56
|
+
? translate({
|
|
57
|
+
id: 'theme.navbar.mobileDropdown.collapseButton.expandAriaLabel',
|
|
58
|
+
message: 'Expand the dropdown',
|
|
59
|
+
description:
|
|
60
|
+
'The ARIA label of the button to expand the mobile dropdown navbar item',
|
|
61
|
+
})
|
|
62
|
+
: translate({
|
|
63
|
+
id: 'theme.navbar.mobileDropdown.collapseButton.collapseAriaLabel',
|
|
64
|
+
message: 'Collapse the dropdown',
|
|
65
|
+
description:
|
|
66
|
+
'The ARIA label of the button to collapse the mobile dropdown navbar item',
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
aria-expanded={!collapsed}
|
|
70
|
+
type="button"
|
|
71
|
+
className="clean-btn menu__caret"
|
|
72
|
+
onClick={onClick}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function useItemCollapsible({active}: {active: boolean}) {
|
|
78
|
+
const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({
|
|
79
|
+
initialState: () => !active,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Expand if any item active after a navigation
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (active) {
|
|
85
|
+
setCollapsed(false);
|
|
86
|
+
}
|
|
87
|
+
}, [active, setCollapsed]);
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
collapsed,
|
|
91
|
+
toggleCollapsed,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export default function DropdownNavbarItemMobile({
|
|
96
|
+
items,
|
|
97
|
+
className,
|
|
98
|
+
position, // Need to destructure position from props so that it doesn't get passed on.
|
|
99
|
+
onClick,
|
|
100
|
+
...props
|
|
101
|
+
}: Props): ReactNode {
|
|
102
|
+
const localPathname = useLocalPathname();
|
|
103
|
+
const isActive = isSamePath(props.to, localPathname);
|
|
104
|
+
const containsActive = containsActiveItems(items, localPathname);
|
|
105
|
+
|
|
106
|
+
const {collapsed, toggleCollapsed} = useItemCollapsible({
|
|
107
|
+
active: isActive || containsActive,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// # hash permits to make the <a> tag focusable in case no link target
|
|
111
|
+
// See https://github.com/facebook/docusaurus/pull/6003
|
|
112
|
+
// There's probably a better solution though...
|
|
113
|
+
const href = props.to ? undefined : '#';
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<li
|
|
117
|
+
className={clsx('menu__list-item', {
|
|
118
|
+
'menu__list-item--collapsed': collapsed,
|
|
119
|
+
})}>
|
|
120
|
+
<div
|
|
121
|
+
className={clsx('menu__list-item-collapsible', {
|
|
122
|
+
'menu__list-item-collapsible--active': isActive,
|
|
123
|
+
})}>
|
|
124
|
+
<NavbarNavLink
|
|
125
|
+
role="button"
|
|
126
|
+
className={clsx(
|
|
127
|
+
styles.dropdownNavbarItemMobile,
|
|
128
|
+
'menu__link menu__link--sublist',
|
|
129
|
+
className,
|
|
130
|
+
)}
|
|
131
|
+
href={href}
|
|
132
|
+
{...props}
|
|
133
|
+
onClick={(e) => {
|
|
134
|
+
// Prevent navigation when link is "#"
|
|
135
|
+
if (href === '#') {
|
|
136
|
+
e.preventDefault();
|
|
137
|
+
}
|
|
138
|
+
// Otherwise we let navigation eventually happen, and/or collapse
|
|
139
|
+
toggleCollapsed();
|
|
140
|
+
}}>
|
|
141
|
+
{props.children ?? props.label}
|
|
142
|
+
</NavbarNavLink>
|
|
143
|
+
<CollapseButton
|
|
144
|
+
collapsed={collapsed}
|
|
145
|
+
onClick={(e) => {
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
toggleCollapsed();
|
|
148
|
+
}}
|
|
149
|
+
/>
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
<Collapsible lazy as="ul" className="menu__list" collapsed={collapsed}>
|
|
153
|
+
{items.map((childItemProps, i) => (
|
|
154
|
+
<NavbarItem
|
|
155
|
+
mobile
|
|
156
|
+
isDropdownItem
|
|
157
|
+
onClick={onClick}
|
|
158
|
+
activeClassName="menu__link--active"
|
|
159
|
+
{...childItemProps}
|
|
160
|
+
key={i}
|
|
161
|
+
/>
|
|
162
|
+
))}
|
|
163
|
+
</Collapsible>
|
|
164
|
+
</li>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
@@ -5,178 +5,10 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React, {
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
useCollapsible,
|
|
13
|
-
Collapsible,
|
|
14
|
-
} from '@docusaurus/theme-common';
|
|
15
|
-
import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal';
|
|
16
|
-
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
17
|
-
import NavbarItem, {type LinkLikeNavbarItemProps} from '@theme/NavbarItem';
|
|
18
|
-
import type {
|
|
19
|
-
DesktopOrMobileNavBarItemProps,
|
|
20
|
-
Props,
|
|
21
|
-
} from '@theme/NavbarItem/DropdownNavbarItem';
|
|
22
|
-
import styles from './styles.module.css';
|
|
23
|
-
|
|
24
|
-
function isItemActive(
|
|
25
|
-
item: LinkLikeNavbarItemProps,
|
|
26
|
-
localPathname: string,
|
|
27
|
-
): boolean {
|
|
28
|
-
if (isSamePath(item.to, localPathname)) {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) {
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) {
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function containsActiveItems(
|
|
41
|
-
items: readonly LinkLikeNavbarItemProps[],
|
|
42
|
-
localPathname: string,
|
|
43
|
-
): boolean {
|
|
44
|
-
return items.some((item) => isItemActive(item, localPathname));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function DropdownNavbarItemDesktop({
|
|
48
|
-
items,
|
|
49
|
-
position,
|
|
50
|
-
className,
|
|
51
|
-
onClick,
|
|
52
|
-
...props
|
|
53
|
-
}: DesktopOrMobileNavBarItemProps) {
|
|
54
|
-
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
55
|
-
const [showDropdown, setShowDropdown] = useState(false);
|
|
56
|
-
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
const handleClickOutside = (
|
|
59
|
-
event: MouseEvent | TouchEvent | FocusEvent,
|
|
60
|
-
) => {
|
|
61
|
-
if (
|
|
62
|
-
!dropdownRef.current ||
|
|
63
|
-
dropdownRef.current.contains(event.target as Node)
|
|
64
|
-
) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
setShowDropdown(false);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
71
|
-
document.addEventListener('touchstart', handleClickOutside);
|
|
72
|
-
document.addEventListener('focusin', handleClickOutside);
|
|
73
|
-
|
|
74
|
-
return () => {
|
|
75
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
76
|
-
document.removeEventListener('touchstart', handleClickOutside);
|
|
77
|
-
document.removeEventListener('focusin', handleClickOutside);
|
|
78
|
-
};
|
|
79
|
-
}, [dropdownRef]);
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<div
|
|
83
|
-
ref={dropdownRef}
|
|
84
|
-
className={clsx('navbar__item', 'dropdown', 'dropdown--hoverable', {
|
|
85
|
-
'dropdown--right': position === 'right',
|
|
86
|
-
'dropdown--show': showDropdown,
|
|
87
|
-
})}>
|
|
88
|
-
<NavbarNavLink
|
|
89
|
-
aria-haspopup="true"
|
|
90
|
-
aria-expanded={showDropdown}
|
|
91
|
-
role="button"
|
|
92
|
-
// # hash permits to make the <a> tag focusable in case no link target
|
|
93
|
-
// See https://github.com/facebook/docusaurus/pull/6003
|
|
94
|
-
// There's probably a better solution though...
|
|
95
|
-
href={props.to ? undefined : '#'}
|
|
96
|
-
className={clsx('navbar__link', className)}
|
|
97
|
-
{...props}
|
|
98
|
-
onClick={props.to ? undefined : (e) => e.preventDefault()}
|
|
99
|
-
onKeyDown={(e) => {
|
|
100
|
-
if (e.key === 'Enter') {
|
|
101
|
-
e.preventDefault();
|
|
102
|
-
setShowDropdown(!showDropdown);
|
|
103
|
-
}
|
|
104
|
-
}}>
|
|
105
|
-
{props.children ?? props.label}
|
|
106
|
-
</NavbarNavLink>
|
|
107
|
-
<ul className="dropdown__menu">
|
|
108
|
-
{items.map((childItemProps, i) => (
|
|
109
|
-
<NavbarItem
|
|
110
|
-
isDropdownItem
|
|
111
|
-
activeClassName="dropdown__link--active"
|
|
112
|
-
{...childItemProps}
|
|
113
|
-
key={i}
|
|
114
|
-
/>
|
|
115
|
-
))}
|
|
116
|
-
</ul>
|
|
117
|
-
</div>
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function DropdownNavbarItemMobile({
|
|
122
|
-
items,
|
|
123
|
-
className,
|
|
124
|
-
position, // Need to destructure position from props so that it doesn't get passed on.
|
|
125
|
-
onClick,
|
|
126
|
-
...props
|
|
127
|
-
}: DesktopOrMobileNavBarItemProps) {
|
|
128
|
-
const localPathname = useLocalPathname();
|
|
129
|
-
const containsActive = containsActiveItems(items, localPathname);
|
|
130
|
-
|
|
131
|
-
const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({
|
|
132
|
-
initialState: () => !containsActive,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Expand/collapse if any item active after a navigation
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
if (containsActive) {
|
|
138
|
-
setCollapsed(!containsActive);
|
|
139
|
-
}
|
|
140
|
-
}, [localPathname, containsActive, setCollapsed]);
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<li
|
|
144
|
-
className={clsx('menu__list-item', {
|
|
145
|
-
'menu__list-item--collapsed': collapsed,
|
|
146
|
-
})}>
|
|
147
|
-
<NavbarNavLink
|
|
148
|
-
role="button"
|
|
149
|
-
className={clsx(
|
|
150
|
-
styles.dropdownNavbarItemMobile,
|
|
151
|
-
'menu__link menu__link--sublist menu__link--sublist-caret',
|
|
152
|
-
className,
|
|
153
|
-
)}
|
|
154
|
-
// # hash permits to make the <a> tag focusable in case no link target
|
|
155
|
-
// See https://github.com/facebook/docusaurus/pull/6003
|
|
156
|
-
// There's probably a better solution though...
|
|
157
|
-
href={props.to ? undefined : '#'}
|
|
158
|
-
{...props}
|
|
159
|
-
onClick={(e) => {
|
|
160
|
-
e.preventDefault();
|
|
161
|
-
toggleCollapsed();
|
|
162
|
-
}}>
|
|
163
|
-
{props.children ?? props.label}
|
|
164
|
-
</NavbarNavLink>
|
|
165
|
-
<Collapsible lazy as="ul" className="menu__list" collapsed={collapsed}>
|
|
166
|
-
{items.map((childItemProps, i) => (
|
|
167
|
-
<NavbarItem
|
|
168
|
-
mobile
|
|
169
|
-
isDropdownItem
|
|
170
|
-
onClick={onClick}
|
|
171
|
-
activeClassName="menu__link--active"
|
|
172
|
-
{...childItemProps}
|
|
173
|
-
key={i}
|
|
174
|
-
/>
|
|
175
|
-
))}
|
|
176
|
-
</Collapsible>
|
|
177
|
-
</li>
|
|
178
|
-
);
|
|
179
|
-
}
|
|
8
|
+
import React, {type ReactNode} from 'react';
|
|
9
|
+
import DropdownNavbarItemMobile from '@theme/NavbarItem/DropdownNavbarItem/Mobile';
|
|
10
|
+
import DropdownNavbarItemDesktop from '@theme/NavbarItem/DropdownNavbarItem/Desktop';
|
|
11
|
+
import type {Props} from '@theme/NavbarItem/DropdownNavbarItem';
|
|
180
12
|
|
|
181
13
|
export default function DropdownNavbarItem({
|
|
182
14
|
mobile = false,
|
package/src/theme-classic.d.ts
CHANGED
|
@@ -1181,19 +1181,40 @@ declare module '@theme/NavbarItem/DefaultNavbarItem' {
|
|
|
1181
1181
|
import type {ReactNode} from 'react';
|
|
1182
1182
|
import type {Props as NavbarNavLinkProps} from '@theme/NavbarItem/NavbarNavLink';
|
|
1183
1183
|
|
|
1184
|
-
export type
|
|
1184
|
+
export type DefaultNavbarItemProps = NavbarNavLinkProps & {
|
|
1185
1185
|
readonly isDropdownItem?: boolean;
|
|
1186
1186
|
readonly className?: string;
|
|
1187
1187
|
readonly position?: 'left' | 'right';
|
|
1188
1188
|
};
|
|
1189
1189
|
|
|
1190
|
-
|
|
1190
|
+
// TODO Docusaurus v4, remove old type name
|
|
1191
|
+
export type DesktopOrMobileNavBarItemProps = DefaultNavbarItemProps;
|
|
1192
|
+
|
|
1193
|
+
export interface Props extends DefaultNavbarItemProps {
|
|
1191
1194
|
readonly mobile?: boolean;
|
|
1192
1195
|
}
|
|
1193
1196
|
|
|
1194
1197
|
export default function DefaultNavbarItem(props: Props): ReactNode;
|
|
1195
1198
|
}
|
|
1196
1199
|
|
|
1200
|
+
declare module '@theme/NavbarItem/DefaultNavbarItem/Mobile' {
|
|
1201
|
+
import type {ReactNode} from 'react';
|
|
1202
|
+
import type {DefaultNavbarItemProps} from '@theme/NavbarItem/DefaultNavbarItem';
|
|
1203
|
+
|
|
1204
|
+
export interface Props extends DefaultNavbarItemProps {}
|
|
1205
|
+
|
|
1206
|
+
export default function DefaultNavbarItemMobile(props: Props): ReactNode;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
declare module '@theme/NavbarItem/DefaultNavbarItem/Desktop' {
|
|
1210
|
+
import type {ReactNode} from 'react';
|
|
1211
|
+
import type {DefaultNavbarItemProps} from '@theme/NavbarItem/DefaultNavbarItem';
|
|
1212
|
+
|
|
1213
|
+
export interface Props extends DefaultNavbarItemProps {}
|
|
1214
|
+
|
|
1215
|
+
export default function DefaultNavbarItemDesktop(props: Props): ReactNode;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1197
1218
|
declare module '@theme/NavbarItem/NavbarNavLink' {
|
|
1198
1219
|
import type {ReactNode} from 'react';
|
|
1199
1220
|
import type {Props as LinkProps} from '@docusaurus/Link';
|
|
@@ -1216,19 +1237,40 @@ declare module '@theme/NavbarItem/DropdownNavbarItem' {
|
|
|
1216
1237
|
import type {Props as NavbarNavLinkProps} from '@theme/NavbarItem/NavbarNavLink';
|
|
1217
1238
|
import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem';
|
|
1218
1239
|
|
|
1219
|
-
export type
|
|
1240
|
+
export type DropdownNavbarItemProps = NavbarNavLinkProps & {
|
|
1220
1241
|
readonly position?: 'left' | 'right';
|
|
1221
1242
|
readonly items: readonly LinkLikeNavbarItemProps[];
|
|
1222
1243
|
readonly className?: string;
|
|
1223
1244
|
};
|
|
1224
1245
|
|
|
1225
|
-
|
|
1246
|
+
// TODO Docusaurus v4, remove old type name
|
|
1247
|
+
export type DesktopOrMobileNavBarItemProps = DropdownNavbarItemProps;
|
|
1248
|
+
|
|
1249
|
+
export interface Props extends DropdownNavbarItemProps {
|
|
1226
1250
|
readonly mobile?: boolean;
|
|
1227
1251
|
}
|
|
1228
1252
|
|
|
1229
1253
|
export default function DropdownNavbarItem(props: Props): ReactNode;
|
|
1230
1254
|
}
|
|
1231
1255
|
|
|
1256
|
+
declare module '@theme/NavbarItem/DropdownNavbarItem/Mobile' {
|
|
1257
|
+
import type {ReactNode} from 'react';
|
|
1258
|
+
import type {DropdownNavbarItemProps} from '@theme/NavbarItem/DropdownNavbarItem';
|
|
1259
|
+
|
|
1260
|
+
export interface Props extends DropdownNavbarItemProps {}
|
|
1261
|
+
|
|
1262
|
+
export default function DropdownNavbarItemMobile(props: Props): ReactNode;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
declare module '@theme/NavbarItem/DropdownNavbarItem/Desktop' {
|
|
1266
|
+
import type {ReactNode} from 'react';
|
|
1267
|
+
import type {DropdownNavbarItemProps} from '@theme/NavbarItem/DropdownNavbarItem';
|
|
1268
|
+
|
|
1269
|
+
export interface Props extends DropdownNavbarItemProps {}
|
|
1270
|
+
|
|
1271
|
+
export default function DropdownNavbarItemDesktop(props: Props): ReactNode;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1232
1274
|
declare module '@theme/NavbarItem/SearchNavbarItem' {
|
|
1233
1275
|
import type {ReactNode} from 'react';
|
|
1234
1276
|
|
|
@@ -1,52 +0,0 @@
|
|
|
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
|
-
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
|
-
}
|
|
30
|
-
function DefaultNavbarItemMobile({className, isDropdownItem, ...props}) {
|
|
31
|
-
return (
|
|
32
|
-
<li className="menu__list-item">
|
|
33
|
-
<NavbarNavLink className={clsx('menu__link', className)} {...props} />
|
|
34
|
-
</li>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
export default function DefaultNavbarItem({
|
|
38
|
-
mobile = false,
|
|
39
|
-
position, // Need to destructure position from props so that it doesn't get passed on.
|
|
40
|
-
...props
|
|
41
|
-
}) {
|
|
42
|
-
const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop;
|
|
43
|
-
return (
|
|
44
|
-
<Comp
|
|
45
|
-
{...props}
|
|
46
|
-
activeClassName={
|
|
47
|
-
props.activeClassName ??
|
|
48
|
-
(mobile ? 'menu__link--active' : 'navbar__link--active')
|
|
49
|
-
}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import React, {type ReactNode} from 'react';
|
|
9
|
-
import clsx from 'clsx';
|
|
10
|
-
import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
|
|
11
|
-
import type {
|
|
12
|
-
DesktopOrMobileNavBarItemProps,
|
|
13
|
-
Props,
|
|
14
|
-
} from '@theme/NavbarItem/DefaultNavbarItem';
|
|
15
|
-
|
|
16
|
-
function DefaultNavbarItemDesktop({
|
|
17
|
-
className,
|
|
18
|
-
isDropdownItem = false,
|
|
19
|
-
...props
|
|
20
|
-
}: DesktopOrMobileNavBarItemProps) {
|
|
21
|
-
const element = (
|
|
22
|
-
<NavbarNavLink
|
|
23
|
-
className={clsx(
|
|
24
|
-
isDropdownItem ? 'dropdown__link' : 'navbar__item navbar__link',
|
|
25
|
-
className,
|
|
26
|
-
)}
|
|
27
|
-
isDropdownLink={isDropdownItem}
|
|
28
|
-
{...props}
|
|
29
|
-
/>
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
if (isDropdownItem) {
|
|
33
|
-
return <li>{element}</li>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return element;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function DefaultNavbarItemMobile({
|
|
40
|
-
className,
|
|
41
|
-
isDropdownItem,
|
|
42
|
-
...props
|
|
43
|
-
}: DesktopOrMobileNavBarItemProps) {
|
|
44
|
-
return (
|
|
45
|
-
<li className="menu__list-item">
|
|
46
|
-
<NavbarNavLink className={clsx('menu__link', className)} {...props} />
|
|
47
|
-
</li>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export default function DefaultNavbarItem({
|
|
52
|
-
mobile = false,
|
|
53
|
-
position, // Need to destructure position from props so that it doesn't get passed on.
|
|
54
|
-
...props
|
|
55
|
-
}: Props): ReactNode {
|
|
56
|
-
const Comp = mobile ? DefaultNavbarItemMobile : DefaultNavbarItemDesktop;
|
|
57
|
-
return (
|
|
58
|
-
<Comp
|
|
59
|
-
{...props}
|
|
60
|
-
activeClassName={
|
|
61
|
-
props.activeClassName ??
|
|
62
|
-
(mobile ? 'menu__link--active' : 'navbar__link--active')
|
|
63
|
-
}
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
File without changes
|
/package/lib/theme/NavbarItem/DropdownNavbarItem/{styles.module.css → Mobile/styles.module.css}
RENAMED
|
File without changes
|
/package/src/theme/NavbarItem/DropdownNavbarItem/{styles.module.css → Mobile/styles.module.css}
RENAMED
|
File without changes
|