@momentum-ui/react-collaboration
Version:
Cisco Momentum UI Framework for React Collaboration Applications
117 lines (98 loc) • 3.61 kB
JavaScript
/** @component menu */
import React from 'react';
import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
import { UIDReset } from 'react-uid';
import EventOverlay from '../EventOverlay';
import MenuContext from '../MenuContext';
import { isMRv2Button } from '../../helpers/verifyTypes';
/**
* @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 MenuOverlay extends React.Component {
state = {
isOpen: this.props.isOpen || false,
};
componentDidMount() {
this.props.isOpen && this.forceUpdate();
}
componentDidUpdate(prevProps, prevState) {
const { focusFirstQuery } = this.props;
const { isOpen } = this.state;
if (!prevState.isOpen && prevState !== isOpen && focusFirstQuery) {
const overlay = findDOMNode(this.menuOverlay);
const focusElement = overlay && overlay.querySelector(focusFirstQuery);
focusElement && focusElement.focus();
}
}
onSelect = (e, opts) => {
const { onSelect } = this.props;
const { eventKey, element } = opts;
const { keepMenuOpen } = element.props;
onSelect && onSelect(e, { eventKey, element });
element.constructor.displayName !== 'SubMenu' && !keepMenuOpen && this.handleClose();
};
handleClose = () => {
this.setState({ isOpen: false });
};
render() {
const { children, className, menuTrigger, showArrow, ...props } = this.props;
const { isOpen } = this.state;
const otherProps = omit({ ...props }, ['isOpen', 'focusFirstQuery', 'onSelect']);
const setMenuTrigger = () => {
return React.cloneElement(menuTrigger, {
[isMRv2Button(menuTrigger) ? 'onPress' : 'onClick']: () =>
this.setState({ isOpen: !isOpen }),
ref: (ref) => (this.anchorNode = ref),
});
};
return (
<div className={'md-menu-overlay-wrapper' + `${(className && ` ${className}`) || ''}`}>
{setMenuTrigger()}
{isOpen && (
<EventOverlay
allowClickAway
anchorNode={this.anchorNode}
className="md-menu-overlay"
close={this.handleClose}
isOpen={isOpen}
ref={(ref) => (this.menuOverlay = ref)}
showArrow={showArrow}
{...otherProps}
>
<MenuContext.Provider value={{ parentOnSelect: this.onSelect }}>
<UIDReset>{children}</UIDReset>
</MenuContext.Provider>
</EventOverlay>
)}
</div>
);
}
}
MenuOverlay.propTypes = {
/** @prop Children nodes to render inside MenuOverlay | null */
children: PropTypes.node,
/** @prop Optional css class name | '' */
className: PropTypes.string,
/** @prop Queries children to find matching item to have focus | '' */
focusFirstQuery: PropTypes.string,
/** @prop Prop to initalize state as open | false */
isOpen: PropTypes.bool,
/** @prop HTML element that provides control to MenuOverlay user */
menuTrigger: PropTypes.element.isRequired,
/** @prop Callback function invoked when user selects MenuOverlay | null */
onSelect: PropTypes.func,
/** @prop Determines if the MenuOverlay should show the open/close arrow | true */
showArrow: PropTypes.bool,
};
MenuOverlay.defaultProps = {
children: null,
className: '',
focusFirstQuery: '',
isOpen: false,
onSelect: null,
showArrow: true,
};
MenuOverlay.displayName = 'MenuOverlay';
export default MenuOverlay;