Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | 2x 2x 2x 1x 1x 2x 2x 2x 2x 2x 2x 1x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x | import { useState, useRef, useEffect } from "react";
import PropTypes from "prop-types";
import { setSideNavExpanded, isSideNavExpanded } from "../helpers";
import { LevelOneContent } from "../Content";
import DynamicContent from "./DynamicContent";
import { NavLinkToggle } from "../Links";
import defaultMarkup from "./default-markup";
// TODO: For an SSR version of the SideNavUI we would need to have
// the whole SideNav markup render on the server. Less reliance on
// window and document.
// We can have an API created where we send it certain parameters
// like items. All of the markup is then returned. The SideNav can
// just render the markup provided by the Frontend Server.
// The only code left behind would be triggers to respond to
// toggling the sidenav's expand state
// Things to consider when implmenting an SSR version:
// 1. any buttons will need event listeners to trigger actions.
// 2. we need a feature flag to roll this out since it will be
// a breaking change.
// 3. we may want to consider creating a web component since they
// are server friendly. https://css-tricks.com/using-web-components-with-next-or-any-ssr-framework/
// 4. If you do use web components be sure to come up with a
// strategy to register the web component before React loads
// the markup on the page. Then the web component renders
// immediately.
const SideNavUI = ({
config = {},
isAltStyle = false,
isExpanded,
items = [],
onCollapsed = () => {},
onExpanded = () => {},
}) => {
const isExpandedPropSet = isExpanded !== undefined;
const [isExpandedState, setIsExpandedState] = useState(() => {
Iif (isExpandedPropSet) {
return isExpanded;
}
return isSideNavExpanded(window.document);
});
const [sideNavContent, setSideNavContent] = useState("<nav></nav>");
const collapseRef = useRef(null);
const expand = () => {
setSideNavExpanded(window.document, "true");
setIsExpandedState(true);
if (onExpanded) {
onExpanded();
}
};
const collapse = () => {
setSideNavExpanded(window.document, "false");
setIsExpandedState(false);
if (onCollapsed) {
onCollapsed();
}
};
const toggleExpanded = () => {
isExpandedState ? collapse() : expand();
};
useEffect(() => {
// some applications use the isExpanded prop instead of reading the cookie
// this will ensure the application ignores the cookie
Iif (isExpandedPropSet) {
setIsExpandedState(isExpanded);
} else {
isSideNavExpanded(window.document);
}
}, [isExpanded, isExpandedPropSet]);
useEffect(() => {
const path = window.location.pathname;
document.cookie = `current_path=${path}; Path=/;`;
isSideNavExpanded(window.document);
let cancelRequest = false;
const { origin } = window.location;
const isRunningLocally = origin.includes("localhost");
let sideNavMenuItems;
async function getSideNavConfig() {
try {
const response = await fetch(`${origin}/config/side-navigation`);
const data = await response.json();
sideNavMenuItems = data.markup;
} catch (error) {
if (isRunningLocally) {
sideNavMenuItems = defaultMarkup;
} else E{
sideNavMenuItems = "<nav></nav>";
}
}
Eif (!cancelRequest) {
setSideNavContent(sideNavMenuItems);
}
}
getSideNavConfig();
return () => {
cancelRequest = true;
};
}, [location.pathname]);
const content = !items?.length ? (
<LevelOneContent
levelOneContent={sideNavContent}
isExpanded={isExpandedState}
config={config}
/>
) : (
<DynamicContent
contentItems={items}
className={"sidebar-content" + (isAltStyle ? " alt-style" : "")}
config={config}
isExpandedState={isExpandedState}
/>
);
return (
<aside
id="qppSidebar"
tabIndex="-1"
className={`${isExpandedState ? "sidebar" : "sidebar closed"} sidebar-${
config.navClassName
}`}
>
{content}
<NavLinkToggle
isAltStyle={isAltStyle}
collapseRef={collapseRef}
isExpanded={isExpandedState}
onClick={toggleExpanded}
/>
</aside>
);
};
SideNavUI.propTypes = {
config: PropTypes.object,
isAltStyle: PropTypes.bool,
isExpanded: PropTypes.bool,
items: PropTypes.object,
onCollapsed: PropTypes.func,
onExpanded: PropTypes.func,
};
export default SideNavUI;
|