import React, { useContext, useMemo } from 'react'; import isUndefined from 'lodash/isUndefined'; import { css, cx } from '@leafygreen-ui/emotion'; import { useAvailableSpace, useForwardedRef } from '@leafygreen-ui/hooks'; import { Icon } from '@leafygreen-ui/icon'; import { useDarkMode } from '@leafygreen-ui/leafygreen-provider'; import { palette } from '@leafygreen-ui/palette'; import { Popover } from '@leafygreen-ui/popover'; import { Error } from '@leafygreen-ui/typography'; import { ComboboxProps } from '../Combobox'; import { ComboboxContext } from '../ComboboxContext'; import { DropdownWidthBasis } from '../types'; import { autoWidthStyles, getMenuThemeStyles, loadingIconStyle, menuBaseStyle, menuList, menuMessageBaseStyle, menuMessageSizeStyle, menuMessageThemeStyle, popoverStyle, popoverThemeStyle, } from './Menu.styles'; type ComboboxMenuProps = { children?: React.ReactNode; refEl: React.RefObject; id: string; labelId: string; menuWidth: number; dropdownWidthBasis?: DropdownWidthBasis; } & Pick< ComboboxProps, 'searchLoadingMessage' | 'searchErrorMessage' | 'searchEmptyMessage' >; export const ComboboxMenu = React.forwardRef( ( { children, id, refEl, labelId, menuWidth, searchLoadingMessage, searchErrorMessage, searchEmptyMessage, dropdownWidthBasis = DropdownWidthBasis.Trigger, }: ComboboxMenuProps, forwardedRef, ) => { const { darkMode, theme } = useDarkMode(); const { disabled, size, isOpen, searchState } = useContext(ComboboxContext); const ref = useForwardedRef(forwardedRef, null); /** The max height of the menu element */ const availableSpace = useAvailableSpace(refEl); const maxHeightValue = !isUndefined(availableSpace) ? `${Math.min(availableSpace, 256)}px` : 'unset'; /** * The rendered menu JSX contents * Includes error, empty, search and default states */ const renderedMenuContents = useMemo((): JSX.Element => { const messageStyles = cx( menuMessageBaseStyle, menuMessageThemeStyle[theme], menuMessageSizeStyle(size), ); const errorMessageStyles = cx( menuMessageBaseStyle, menuMessageSizeStyle(size), ); switch (searchState) { case 'loading': { return ( {searchLoadingMessage} ); } case 'error': { return ( {searchErrorMessage} ); } case 'unset': default: { if ( children && typeof children === 'object' && 'length' in children && (children as Array).length > 0 ) { return
    {children}
; } return {searchEmptyMessage}; } } }, [ theme, size, searchState, darkMode, searchLoadingMessage, searchErrorMessage, children, searchEmptyMessage, ]); return (
e.preventDefault()} > {renderedMenuContents}
); }, ); ComboboxMenu.displayName = 'ComboboxMenu';