import React, { Component } from 'react' import ReactDOM from 'react-dom'; import './context-menu-modal.less' import classnames from 'classnames'; const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, } interface IProps { left?: number top?: number bottom?: number right?: number width?: number visible?: boolean mask?: boolean wrapperClassname?: string children?: React.ReactNode forceRender?: boolean onCancel?: () => void onEscape?: () => void onRightClick?: () => void } interface IState { container: HTMLElement } export default class ContextMenuModal extends Component { ref = React.createRef(); static defaultProps = { mask: true, forceRender: false, } state = { container: null } visible: boolean componentDidMount() { document.addEventListener('keydown', this.onKeyup); if (this.props.forceRender) { let container = document.createElement('div'); this.setState({ container: container }) document.body.appendChild(container); } } componentDidUpdate() { if (this.props.forceRender) return; if (this.props.visible !== this.visible && !!this.props.visible) { this.visible = this.props.visible; let container = document.createElement('div'); // container.classList.add('context-menu-container') // container.addEventListener('click', this.onCancel) this.setState({ container: container }) document.body.appendChild(container); // ReactDOM.createPortal(this.props.children, this.container); } else if (!this.props.visible && this.state.container) { this.visible = this.props.visible; this.state.container.parentElement.removeChild(this.state.container); // this.state.container.removeEventListener('click', this.onCancel); this.setState({ container: null, }) } } componentWillUnmount() { if (this.state.container) { this.state.container.parentElement.removeChild(this.state.container); // this.state.container.removeEventListener('click', this.onCancel); } document.removeEventListener('keyup', this.onKeyup); } onClick = (event) => { if (event.button === MOUSE.LEFT) { if (this.checkClickInBound(event)) return; if (this.props.onCancel) { this.props.onCancel(); } } } onRightClick = (event) => { event.preventDefault(); if (this.props.onRightClick) { this.props.onRightClick(); } } checkClickInBound = (event) => { let bound = this.ref?.current?.getBoundingClientRect(); if (!bound) return false; let x = event.clientX; let y = event.clientY; return x>bound.left && xbound.top && y { let keyCode = event.keyCode; if (keyCode === 27) { //escape if (this.props.onEscape) { this.props.onEscape(); } } } render() { if (this.props.forceRender) { return ( this.state.container && ( ReactDOM.createPortal(
{this.props.children}
, this.state.container) ) ) } return ( this.props.visible && this.state.container && (ReactDOM.createPortal(
{this.props.children}
, this.state.container)) ); } }