import React from "react"; import { createPortal } from "react-dom"; import PropTypes from "prop-types"; import classnames from "classnames"; import "../../css/context-menu.css"; class Portal extends React.Component { constructor(props) { super(props); this._node = document.createElement("div"); document.body.appendChild(this._node); } componentWillUnmount() { document.body.removeChild(this._node); } render() { const style = { position: "absolute", top: this.props.top, left: this.props.left }; return createPortal(
{this.props.children}
, this._node ); } } export const Hr = () => (

  • ); // TODO: Add down-arrow export const Parent = ({ children, label }) => (
  • {label}
  • ); export const LinkNode = props => (
  • {props.label}
  • ); LinkNode.propTypes = { label: PropTypes.string.isRequired, href: PropTypes.string.isRequired }; export const Node = props =>
  • {props.label}
  • ; Node.propTypes = { label: PropTypes.string.isRequired }; export class ContextMenu extends React.Component { constructor(props) { super(props); this.state = { selected: false }; this._handleHandleClick = this._handleHandleClick.bind(this); this._handleGlobalClick = this._handleGlobalClick.bind(this); } componentDidMount() { document.addEventListener("click", this._handleGlobalClick); } componentWillUnmount() { document.removeEventListener("click", this._handleGlobalClick); } _handleHandleClick() { this.setState({ selected: !this.state.selected }); } _handleGlobalClick(e) { if ( this.state.selected && // Not sure how, but it's possible for this to get called when handleNode is null/undefined. // https://sentry.io/share/issue/2066cd79f21e4f279791319f4d2ea35d/ this.handleNode && !this.handleNode.contains(e.target) ) { this.setState({ selected: false }); } } render() { const { handle, children, top, bottom, ...passThroughProps } = this.props; const rect = this.handleNode ? this.handleNode.getBoundingClientRect() : { top: 0, left: 0 }; return (
    (this.handleNode = node)} onClick={this._handleHandleClick} > {handle}
    {this.state.selected && ( )}
    ); } } ContextMenu.propTypes = { children: PropTypes.any.isRequired, handle: PropTypes.any.isRequired, top: PropTypes.bool, bottom: PropTypes.bool };