import React from 'react'; import styled from '@emotion/styled'; import omit from 'lodash/omit'; import Link from 'app/components/links/link'; import space from 'app/styles/space'; import {callIfFunction} from 'app/utils/callIfFunction'; import {Theme} from 'app/utils/theme'; type MenuItemProps = { /** * Should this item act as a header */ header?: boolean; /** * Should this item act as a divider */ divider?: boolean; /** * The title/tooltipe of the item */ title?: string; /** * Is the item disabled? */ disabled?: boolean; /** * Triggered when the item is clicked */ onSelect?: (eventKey: any) => void; /** * Provided to the onSelect callback when this item is selected */ eventKey?: any; /** * Is the item actively seleted? */ isActive?: boolean; /** * Enable to provide custom button/contents via children */ noAnchor?: boolean; /** * A router target destination */ to?: React.ComponentProps['to']; /** * A server rendered URL. */ href?: string; className?: string; }; type Props = MenuItemProps & Omit, keyof MenuItemProps>; class MenuItem extends React.Component { handleClick = (e: React.MouseEvent): void => { const {onSelect, disabled, eventKey} = this.props; if (disabled) { return; } if (onSelect) { e.preventDefault(); callIfFunction(onSelect, eventKey); } }; renderAnchor = (): React.ReactNode => { const {to, href, title, disabled, isActive, children} = this.props; if (to) { return ( {children} ); } if (href) { return ( {children} ); } return ( {this.props.children} ); }; render() { const { header, divider, isActive, noAnchor, className, children, ...props } = this.props; let renderChildren: React.ReactNode | null = null; if (noAnchor) { renderChildren = children; } else if (header) { renderChildren = children; } else if (!divider) { renderChildren = this.renderAnchor(); } return ( {renderChildren} ); } } type MenuListItemProps = { header?: boolean; noAnchor?: boolean; isActive?: boolean; disabled?: boolean; divider?: boolean; } & React.HTMLProps; function getListItemStyles(props: MenuListItemProps & {theme: Theme}) { const common = ` display: block; padding: ${space(0.5)} ${space(2)}; &:focus { outline: none; } `; if (props.disabled) { return ` ${common} color: ${props.theme.disabled}; background: transparent; cursor: not-allowed; `; } if (props.isActive) { return ` ${common} color: ${props.theme.white}; background: ${props.theme.active}; &:hover { color: ${props.theme.black}; } `; } return ` ${common} &:hover { background: ${props.theme.focus}; } `; } function getChildStyles(props: MenuListItemProps & {theme: Theme}) { if (!props.noAnchor) { return ''; } return ` & a { ${getListItemStyles(props)} } `; } const MenuAnchor = styled('a', { shouldForwardProp: p => ['isActive', 'disabled'].includes(p) === false, })` ${getListItemStyles} `; const MenuListItem = styled('li')` display: block; ${p => p.divider && ` height: 1px; margin: ${space(0.5)} 0; overflow: hidden; background-color: ${p.theme.innerBorder}; `} ${p => p.header && ` padding: ${space(0.25)} ${space(1)}; font-size: ${p.theme.fontSizeSmall}; line-height: 1.4; color: ${p.theme.gray300}; `} ${getChildStyles} `; const MenuTarget = styled('span')` ${getListItemStyles} display: flex; `; const MenuLink = styled(Link, { shouldForwardProp: p => ['isActive', 'disabled'].includes(p) === false, })` ${getListItemStyles} `; export default MenuItem;