package.src.components.Menu.MenuContent.tsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of react-core Show documentation
Show all versions of react-core Show documentation
This library provides a set of common React components for use with the PatternFly reference implementation.
The newest version!
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';