/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import React, {useState, useRef, useEffect} from 'react'; import clsx from 'clsx'; import { isRegexpStringMatch, useCollapsible, Collapsible, } from '@docusaurus/theme-common'; import {isSamePath, useLocalPathname} from '@docusaurus/theme-common/internal'; import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; import NavbarItem from '@theme/NavbarItem'; import styles from './styles.module.css'; function isItemActive(item, localPathname) { if (isSamePath(item.to, localPathname)) { return true; } if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) { return true; } if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) { return true; } return false; } function containsActiveItems(items, localPathname) { return items.some((item) => isItemActive(item, localPathname)); } function DropdownNavbarItemDesktop({ items, position, className, onClick, ...props }) { const dropdownRef = useRef(null); const [showDropdown, setShowDropdown] = useState(false); useEffect(() => { const handleClickOutside = (event) => { if (!dropdownRef.current || dropdownRef.current.contains(event.target)) { return; } setShowDropdown(false); }; document.addEventListener('mousedown', handleClickOutside); document.addEventListener('touchstart', handleClickOutside); document.addEventListener('focusin', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); document.removeEventListener('touchstart', handleClickOutside); document.removeEventListener('focusin', handleClickOutside); }; }, [dropdownRef]); return (
tag focusable in case no link target // See https://github.com/facebook/docusaurus/pull/6003 // There's probably a better solution though... href={props.to ? undefined : '#'} className={clsx('navbar__link', className)} {...props} onClick={props.to ? undefined : (e) => e.preventDefault()} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); setShowDropdown(!showDropdown); } }}> {props.children ?? props.label}
); } function DropdownNavbarItemMobile({ items, className, position, // Need to destructure position from props so that it doesn't get passed on. onClick, ...props }) { const localPathname = useLocalPathname(); const containsActive = containsActiveItems(items, localPathname); const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({ initialState: () => !containsActive, }); // Expand/collapse if any item active after a navigation useEffect(() => { if (containsActive) { setCollapsed(!containsActive); } }, [localPathname, containsActive, setCollapsed]); return (
  • { e.preventDefault(); toggleCollapsed(); }}> {props.children ?? props.label} {items.map((childItemProps, i) => ( ))}
  • ); } export default function DropdownNavbarItem({mobile = false, ...props}) { const Comp = mobile ? DropdownNavbarItemMobile : DropdownNavbarItemDesktop; return ; }