import { type ReactNode, useCallback, type ForwardRefRenderFunction, forwardRef, useRef, } from 'react'; import { useOnClickOutside, type useOnClickOutsideHandler, } from '../../../../utils/hooks'; import { Checkbox, Heading, Icon, type IconShape, Label, Overlay, Flip, FlipSide, type ListItemProps, ListItem, } from '../../../atoms'; import { Modal } from '../../../molecules'; import styles from './navbar-item.module.scss'; export type NavbarItemProps = Omit< ListItemProps, 'children' | 'hideMarker' | 'id' > & { /** * The modal contents. */ children: ReactNode; /** * An icon to illustrate the nav item. */ icon: IconShape; /** * The item id. */ id: string; /** * Should the modal be visible? */ isActive: boolean; /** * An accessible name for the nav item. */ label: string; /** * The modal heading. */ modalHeading?: string; /** * Make the modal always visible from the given breakpoint. */ modalVisibleFrom?: 'sm' | 'md'; /** * A callback function to handle modal deactivation. */ onDeactivate?: () => void; /** * A callback function to handle modal toggle. */ onToggle: () => void; /** * Should we add the icon on the modal? * * @default false */ showIconOnModal?: boolean; }; const NavbarItemWithRef: ForwardRefRenderFunction< HTMLLIElement, NavbarItemProps > = ( { children, className = '', icon, id, isActive, label, modalHeading, modalVisibleFrom, onDeactivate, onToggle, showIconOnModal = false, ...props }, ref ) => { const itemClass = [ styles.item, modalVisibleFrom ? styles[`item--hidden-controller-${modalVisibleFrom}`] : '', className, ].join(' '); const labelRef = useRef(null); const checkboxRef = useRef(null); const deactivateItem: useOnClickOutsideHandler = useCallback( (e) => { const isCheckbox = e.target && checkboxRef.current?.contains(e.target as Node); const isLabel = e.target && labelRef.current?.contains(e.target as Node); if (onDeactivate && !isCheckbox && !isLabel) onDeactivate(); }, [onDeactivate] ); const modalRef = useOnClickOutside(deactivateItem); return ( {modalHeading} ) : null } icon={showIconOnModal ? : null} ref={modalRef} > {children} ); }; export const NavbarItem = forwardRef(NavbarItemWithRef);