All files / Components/NavElements NavDropdown.js

100% Statements 26/26
90.47% Branches 19/21
100% Functions 4/4
100% Lines 26/26

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                          1x   1x                     54x       54x   54x   54x 54x             54x   54x 54x 22x     54x 3x   3x 3x 3x   3x     54x 54x 54x           54x 22x     54x                                             54x             54x         54x                                              
import React, {
    useState,
    useEffect,
    createRef,
    useContext,
    createContext,
} from 'react';
import classNames from 'classnames';
 
import Badge from '../Badge';
import Icon from '../Icon';
import { WebAppsUXContext } from '../../Context';
 
export const DropdownContext = createContext({});
 
const NavDropdown = props => {
    const {
        children,
        className,
        innerRef,
        color,
        icon,
        name,
        badge,
        show,
        route,
    } = props;
 
    const {
        useNavigation,
    } = useContext(WebAppsUXContext);
 
    const { navigation, setNavigation } = useNavigation;
 
    const ref = createRef();
    innerRef && innerRef(ref);
 
    /* istanbul ignore next */
    if (navigation === undefined) {
        return null;
    }
 
    const { dropdownMode } = navigation;
 
    const [isOpen, setIsOpen] = useState(show)
    useEffect(() => {
        setIsOpen(show);
    }, [show]);
 
    const toggle = (e) => {
        e.preventDefault();
        /* istanbul ignore else */
        if (!dropdownMode && navigation !== undefined) {
            navigation.openDropdown = isOpen ? null : ref.current;
            setNavigation({ ...navigation });
        }
        setIsOpen(!isOpen);
    }
 
    let path = '';
    try {
        path = window.location.pathname;
    } catch (e) {
        /* istanbul ignore next */
        console.warn(e);
    }
 
    useEffect(() => {
        setIsOpen(path.includes(route));
    }, [path]);
 
    const linkClasses = classNames(
        'relative',
        'flex',
        'items-center',
        'justify-start',
        'px-4',
        'py-2.5',
        'text-sm',
        'font-medium',
        'leading-5',
        'transition-colors',
        'duration-200',
        'focus:outline-none',
        color
            ? `text-${color}-600 hover:bg-black/10 dark:hover:bg-white/10`
            : 'text-black/60 hover:text-black/100 dark:text-white/60 dark:hover:text-white/100 hover:bg-black/10 dark:hover:bg-white/10',
        isOpen
            ? color
                ? `rounded-t-md text-${color}-600 bg-black/10 dark:bg-white/10`
                : 'rounded-t-md text-black/100 dark:text-white/100 bg-black/10 dark:bg-white/10'
            : 'rounded-md'
    );
 
    const childWrapper = classNames(
        isOpen
            ? `block p-1 bg-black/10 dark:bg-white/10 rounded-b-md`
            : 'hidden'
    );
 
    const dropIcon = (
        isOpen
            ? '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" /></svg>'
            : '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" /></svg>'
    );
 
    return (
        <div className={classNames(className, 'mb-1')} ref={ref}>
            <a
                href="#"
                className={linkClasses}
                tabIndex="0"
                onClick={toggle}
            >
                {icon && <Icon icon={icon} className="h-6 w-6 mr-4" />}
                <span className="font-medium text-sm">{name}</span>
                {badge && <Badge {...{ ...badge, text: null }}>{badge.text}</Badge>}
                <Icon icon={dropIcon} className="ml-auto h-6 w-6" />
            </a>
            <div className={childWrapper}>
                <DropdownContext.Provider value={{ isOpen }}>
                    {children}
                </DropdownContext.Provider>
            </div>
        </div>
    )
}
 
export default NavDropdown;