lbry-desktop/ui/js/component/menu.js

114 lines
2.7 KiB
JavaScript
Raw Normal View History

2017-06-06 23:19:12 +02:00
import React from "react";
import { Icon } from "./common.js";
import Link from "component/link";
2016-11-22 21:19:08 +01:00
2017-06-08 06:42:19 +02:00
export class DropDownMenuItem extends React.PureComponent {
2017-05-17 10:10:25 +02:00
static propTypes = {
href: React.PropTypes.string,
label: React.PropTypes.string,
icon: React.PropTypes.string,
onClick: React.PropTypes.func,
2017-06-06 23:19:12 +02:00
};
2017-05-17 10:10:25 +02:00
static defaultProps = {
2017-06-06 23:19:12 +02:00
iconPosition: "left",
};
2017-05-17 10:10:25 +02:00
render() {
2017-06-06 23:19:12 +02:00
var icon = this.props.icon ? <Icon icon={this.props.icon} fixed /> : null;
return (
2017-06-06 23:19:12 +02:00
<a
className="menu__menu-item"
onClick={this.props.onClick}
href={this.props.href || "javascript:"}
label={this.props.label}
>
{this.props.iconPosition == "left" ? icon : null}
{this.props.label}
2017-06-06 23:19:12 +02:00
{this.props.iconPosition == "left" ? null : icon}
</a>
);
}
2017-05-17 10:10:25 +02:00
}
2017-06-08 06:42:19 +02:00
export class DropDownMenu extends React.PureComponent {
2017-05-17 10:10:25 +02:00
constructor(props) {
super(props);
2017-05-17 10:10:25 +02:00
this._isWindowClickBound = false;
this._menuDiv = null;
2017-05-17 10:10:25 +02:00
this.state = {
menuOpen: false,
};
2017-05-17 10:10:25 +02:00
}
componentWillUnmount() {
if (this._isWindowClickBound) {
2017-06-06 23:19:12 +02:00
window.removeEventListener("click", this.handleWindowClick, false);
}
2017-05-17 10:10:25 +02:00
}
handleMenuIconClick(e) {
this.setState({
menuOpen: !this.state.menuOpen,
});
if (!this.state.menuOpen && !this._isWindowClickBound) {
this._isWindowClickBound = true;
2017-06-06 23:19:12 +02:00
window.addEventListener("click", this.handleWindowClick, false);
e.stopPropagation();
}
return false;
2017-05-17 10:10:25 +02:00
}
handleMenuClick(e) {
// Event bubbles up to the menu after a link is clicked
this.setState({
menuOpen: false,
});
2017-05-17 10:10:25 +02:00
}
2017-08-28 19:56:55 +02:00
/*this will force "this" to always be the class, even when passed to an event listener*/
handleWindowClick = e => {
2017-06-06 23:19:12 +02:00
if (
this.state.menuOpen &&
(!this._menuDiv || !this._menuDiv.contains(e.target))
) {
this.setState({
2017-06-06 23:19:12 +02:00
menuOpen: false,
});
}
2017-08-28 19:56:55 +02:00
};
2017-05-17 10:10:25 +02:00
render() {
if (!this.state.menuOpen && this._isWindowClickBound) {
this._isWindowClickBound = false;
2017-06-06 23:19:12 +02:00
window.removeEventListener("click", this.handleWindowClick, false);
}
return (
<div className="menu-container">
2017-06-06 23:19:12 +02:00
<Link
ref={span => (this._menuButton = span)}
button="text"
icon="icon-ellipsis-v"
onClick={event => {
this.handleMenuIconClick(event);
}}
/>
{this.state.menuOpen
2017-06-06 23:19:12 +02:00
? <div
ref={div => (this._menuDiv = div)}
className="menu"
onClick={event => {
this.handleMenuClick(event);
}}
>
{this.props.children}
</div>
: null}
</div>
);
}
2017-06-06 06:21:55 +02:00
}