This repository has been archived by the owner on May 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
NavigationItem.jsx
91 lines (82 loc) · 2.59 KB
/
NavigationItem.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import ActiveMainProvider from '../main-container/private/ActiveMainProvider';
import NavigationItemContext from './NavigationItemContext';
const propTypes = {
/**
* The string uniquely identifying the navigation item within the application.
* This value must be globally unique and not shared between multiple tiers of
* navigation (primary, secondary, etc.).
*/
navigationKey: PropTypes.string.isRequired,
/**
* The string description of the NavigationItem to display to the user.
*/
label: PropTypes.string.isRequired,
/**
* A function called to generate the child content for the NavigationItem.
* A parameter indicating whether or not the NavigationItem is active is
* provided.
*
* If provided, the `children` prop will be ignored.
*
* Signature: `renderLayout({ isActive })`
*/
renderLayout: PropTypes.func,
/**
* The child components to render within the NavigationItem.
*
* If the `renderLayout` props is provided, this prop will be ignored.
*/
children: PropTypes.node,
/**
* @private
* A boolean indicating whether or not the NavigationItem is considered active
* based on the determined active navigation key of the layout consuming it.
*/
isActive: PropTypes.bool,
/**
* @private
* The HTMLElement to which the NavigationItem's content should be rendered.
*/
portalElement: PropTypes.instanceOf(HTMLElement),
};
const NavigationItem = ({
navigationKey,
children,
renderLayout,
isActive,
portalElement,
}) => {
const ancestorNavigationItemContext = React.useContext(NavigationItemContext);
const navigationItemContextValue = React.useMemo(() => ({
// If an ancestor NavigationItem is inactivated, then we must consider
// this entire branch inactivated as well.
isActive: isActive && ancestorNavigationItemContext.isActive,
navigationKeys: [
...ancestorNavigationItemContext.navigationKeys,
navigationKey,
],
}), [
isActive,
navigationKey,
ancestorNavigationItemContext.isActive,
ancestorNavigationItemContext.navigationKeys,
]);
let pageContent;
if (renderLayout) {
pageContent = renderLayout({ isActive });
} else {
pageContent = children;
}
return ReactDOM.createPortal((
<NavigationItemContext.Provider value={navigationItemContextValue}>
<ActiveMainProvider>
{pageContent}
</ActiveMainProvider>
</NavigationItemContext.Provider>
), portalElement);
};
NavigationItem.propTypes = propTypes;
export default NavigationItem;