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 | import {
FunctionComponent,
useCallback,
useEffect,
useRef,
useState,
} from "react";
import { useLocation } from "react-router-dom";
import { PACKAGE_ANALYTICS } from "./constants";
import { normalizeId, useIntersectingHeader } from "./useIntersectingHeader";
import { useSectionItems } from "./useSectionItems";
import { GetIsActiveItemFunction, NavTree } from "../../components/NavTree";
export const SecondaryDocNavigation: FunctionComponent = () => {
const intersectingHeader = useIntersectingHeader();
const sectionItems = useSectionItems();
const { hash } = useLocation();
// This ref is used to direct control over highlight state between
// recentlyClickedItem and intersectingHeader
const allowIntersectTakeover = useRef(false);
// Tracks the link which was clicked, is set to undefined when the intersectingHeader state takes over
const [recentlyClickedItem, setRecentlyClickedItem] = useState<
string | undefined
>(hash);
// When a user clicks a link, we give control of highlights to the recentlyClickedItem state for 500ms
// Afterwards, intersectingHeader state via intersection observer takes control of state
useEffect(() => {
setRecentlyClickedItem(hash);
allowIntersectTakeover.current = false;
setTimeout(() => {
allowIntersectTakeover.current = true;
}, 500);
}, [hash]);
// When intersectingHeader changes from scroll and allowIntersectTakeover is true,
// we set the recentlyClickedItem state to undefined so link highlight state will be dictated
// by the intersectingHeader state
useEffect(() => {
if (recentlyClickedItem && allowIntersectTakeover.current) {
setRecentlyClickedItem(undefined);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [intersectingHeader]);
// If recentlyClickedItem is defined, use it to compare for highlight state
// Otherwise compare item id against intersectingHeader
const getIsLinkActive: GetIsActiveItemFunction = useCallback(
({ path, id }) => {
if (recentlyClickedItem) {
return new URL(path ?? "", window.origin).hash === recentlyClickedItem;
}
return normalizeId(id) === intersectingHeader;
},
[intersectingHeader, recentlyClickedItem]
);
return (
<NavTree
data-event={PACKAGE_ANALYTICS.SCOPE}
getIsActiveItem={getIsLinkActive}
items={sectionItems}
variant="sm"
/>
);
};
|