import * as React from 'react'; import styles from '@patternfly/react-styles/css/components/Menu/menu'; import { css } from '@patternfly/react-styles'; import { MenuContext } from './MenuContext'; import cssHeight from '@patternfly/react-tokens/dist/esm/c_menu__content_Height'; import cssMaxHeight from '@patternfly/react-tokens/dist/esm/c_menu__content_MaxHeight'; export interface MenuContentProps extends React.HTMLProps { /** Items within group */ children?: React.ReactNode; /** @hide Forwarded ref */ innerRef?: React.Ref; /** Height of the menu content */ menuHeight?: string; /** Maximum height of menu content */ maxMenuHeight?: string; /** Callback to return the height of the menu content */ getHeight?: (height: string) => void; } export const MenuContent = React.forwardRef((props: MenuContentProps, ref: React.Ref) => { const { getHeight, children, menuHeight, maxMenuHeight, ...rest } = props; const menuContentRef = React.createRef(); const refCallback = (el: HTMLElement, menuId: string, onGetMenuHeight: (menuId: string, height: number) => void) => { if (el) { let clientHeight = el.clientHeight; // if this menu is a submenu, we need to account for the root menu list's padding and root menu content's border. let rootMenuList = null; let parentEl = el.closest(`.${styles.menuList}`); while (parentEl !== null && parentEl.nodeType === 1) { if (parentEl.classList.contains(styles.menuList)) { rootMenuList = parentEl; } parentEl = parentEl.parentElement; } if (rootMenuList) { const rootMenuListStyles = getComputedStyle(rootMenuList); const rootMenuListPaddingOffset = parseFloat(rootMenuListStyles.getPropertyValue('padding-top').replace(/px/g, '')) + parseFloat(rootMenuListStyles.getPropertyValue('padding-bottom').replace(/px/g, '')) + parseFloat( getComputedStyle(rootMenuList.parentElement).getPropertyValue('border-bottom-width').replace(/px/g, '') ); clientHeight = clientHeight + rootMenuListPaddingOffset; } onGetMenuHeight && onGetMenuHeight(menuId, clientHeight); getHeight && getHeight(clientHeight.toString()); } return ref || menuContentRef; }; return ( {({ menuId, onGetMenuHeight }) => (
refCallback(el, menuId, onGetMenuHeight)} style={ { ...(menuHeight && { [cssHeight.name]: menuHeight }), ...(maxMenuHeight && { [cssMaxHeight.name]: maxMenuHeight }) } as React.CSSProperties } > {children}
)} ); }); MenuContent.displayName = 'MenuContent';