import React from 'react';
import PropTypes from 'prop-types';
import { Icon } from '@procore/core-react';
import { findDOMNode } from 'react-dom';
import baseStyles from './OverflowMenu.scss';
import composeStyles from '../../shared/stylesheetComposer';
import InlinePortal from './InlinePortal';
import DropdownContent from './DropdownContent';
export default class OverflowMenu extends React.Component {
static propTypes = {
stylesheets: PropTypes.arrayOf(PropTypes.shape()),
placement: PropTypes.oneOf(['left', 'right'])
};
static defaultProps = {
stylesheets: [],
placement: 'right'
};
constructor(props) {
super(props);
this.styles = composeStyles(baseStyles, props.stylesheets);
this.state = { expanded: false };
}
componentDidMount() {
window.addEventListener('click', this.closeDropdown);
}
componentWillUnmount() {
window.removeEventListener('click', this.closeDropdown);
}
closeDropdown = () => {
this.setState({ expanded: false });
};
onExpand = (evt) => {
evt.stopPropagation();
this.setState({ expanded: !this.state.expanded });
};
itemClickHandler = handler => (e) => {
this.closeDropdown();
if (handler && typeof handler === 'function') {
handler(e);
}
};
setLeft = (dropdownLeft) => {
this.dropdown.style.left = `${Math.ceil(dropdownLeft)}px`;
};
setTop = (dropdownTop) => {
const top = dropdownTop + window.pageYOffset;
this.dropdown.style.top = `${Math.ceil(top)}px`;
};
position = () => {
const {
left: dropdownLeft,
bottom: dropdownTop,
width: ellipsisWidth
} = this.ellipsis.getBoundingClientRect();
const leftPosition = this.props.placement === 'left' ?
dropdownLeft + (ellipsisWidth - this.dropdown.clientWidth) :
dropdownLeft;
this.setLeft(leftPosition);
this.setTop(dropdownTop);
};
render() {
const styles = this.styles;
const { expanded } = this.state;
return (
<div>
<div
className={styles.iconContainer}
ref={elem => this.ellipsis = elem}
onClick={this.onExpand}
>
<Icon icon={'ellipsis-v'} />
</div>
<InlinePortal show={expanded}>
<DropdownContent
styles={styles}
onItemClick={this.itemClickHandler}
ref={(el) => {
if (el) {
this.dropdown = findDOMNode(el);
this.position();
}
}}
>
{this.props.children}
</DropdownContent>
</InlinePortal>
</div>
);
}
}
|