@momentum-ui/react-collaboration
Version:
Cisco Momentum UI Framework for React Collaboration Applications
152 lines (135 loc) • 5.03 kB
JavaScript
/** @component menu-item */
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
import mapContextToProps from '@restart/context/mapContextToProps';
import { UIDConsumer } from 'react-uid';
import { ListItem } from '@momentum-ui/react-collaboration';
import ListContext from '../ListContext';
import SelectableContext from '../SelectableContext';
import { prefix } from '../utils/index';
/**
* @deprecated - Components in the legacy folder (/src/legacy) are deprecated. Please use a component from the components folder (/src/components) instead. Legacy components may not follow accessibility standards.
**/
class MenuItem extends React.Component {
constructor(props) {
super(props);
this.state = {
selectContext: {
parentKeyDown: !props.isHeader ? this.handleKeyDown : null,
parentOnSelect: !props.isHeader ? this.handleClick : null,
},
};
}
handleClick = (e, opts) => {
const { onClick, parentOnSelect } = this.props;
const { eventKey, label, value } = opts;
onClick && onClick(e, { value, label });
parentOnSelect && parentOnSelect(e, { eventKey, element: this });
};
handleKeyDown = (e, opts) => {
const { onClick, parentKeyDown, parentOnSelect } = this.props;
const { eventKey } = opts;
if (!e.target?.classList?.contains(`${prefix}-list-item`)) {
return;
}
if (e.which === 32 || e.which === 13 || e.charCode === 32 || e.charCode === 13) {
onClick && onClick(e);
parentOnSelect && parentOnSelect(e, { eventKey, element: this });
e.preventDefault();
} else {
parentKeyDown && parentKeyDown(e, { eventKey, element: this });
}
};
render() {
const { children, className, isHeader, isOpen, itemClassName, ...props } = this.props;
const { selectContext } = this.state;
const otherProps = omit({ ...props }, [
'keepMenuOpen',
'onClick',
'parentKeyDown',
'parentOnSelect',
]);
return (
<UIDConsumer name={(id) => `${prefix}-menu-item-${id}`}>
{(id) => (
<SelectableContext.Provider value={selectContext}>
<ListContext.Consumer>
{(listContext) => {
const cxtActive =
isOpen ||
(listContext &&
listContext.active &&
ReactDOM.findDOMNode(this.anchorRef) &&
ReactDOM.findDOMNode(this.anchorRef).attributes[`data-${prefix}-event-key`] &&
ReactDOM.findDOMNode(this.anchorRef).attributes[`data-${prefix}-event-key`]
.value &&
listContext.active.includes(
ReactDOM.findDOMNode(this.anchorRef).attributes[`data-${prefix}-event-key`]
.value
));
return (
<div
className={`${prefix}-menu-item` + `${(className && ` ${className}`) || ''}`}
aria-expanded={cxtActive}
aria-haspopup={!!children}
>
<ListItem
active={cxtActive}
className={
`${(isHeader && `md-menu-item__header`) || ''}` +
`${(itemClassName && ` ${itemClassName}`) || ''}`
}
focusOnLoad
isReadOnly={isHeader}
id={id}
ref={(ref) => (this.anchorRef = ref)}
role="menuitem"
{...otherProps}
>
{children}
</ListItem>
</div>
);
}}
</ListContext.Consumer>
</SelectableContext.Provider>
)}
</UIDConsumer>
);
}
}
MenuItem.propTypes = {
/** @prop Children nodes to render inside MenuItem | null */
children: PropTypes.node,
/** @prop Optional css class name | '' */
className: PropTypes.string,
/** @prop Determines if MenuItem is the header | false */
isHeader: PropTypes.bool,
/** @prop Determines if MenuItem is open | false */
isOpen: PropTypes.bool,
/** @prop Optional list css class name | '' */
itemClassName: PropTypes.string,
/** @prop Set to keep the MenuItem open | false */
keepMenuOpen: PropTypes.bool,
/** @prop Callback function invoked when user taps on MenutItem | null */
onClick: PropTypes.func,
// Internal Context Use Only
parentKeyDown: PropTypes.func,
// Internal Context Use Only
parentOnSelect: PropTypes.func,
};
MenuItem.defaultProps = {
children: null,
className: '',
isHeader: false,
isOpen: false,
itemClassName: '',
keepMenuOpen: false,
onClick: null,
parentKeyDown: null,
parentOnSelect: null,
};
MenuItem.displayName = 'MenuItem';
export default mapContextToProps(SelectableContext, (context) => context, MenuItem);