import React = require("react"); import { observable, action } from "mobx"; import { observer } from "mobx-react"; import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { UndoManager } from "../util/UndoManager"; library.add(faAngleRight); export interface OriginalMenuProps { description: string; event: (stuff?: any) => void; undoable?: boolean; icon: IconProp; //maybe should be optional (icon?) closeMenu?: () => void; } export interface SubmenuProps { description: string; subitems: ContextMenuProps[]; icon: IconProp; //maybe should be optional (icon?) closeMenu?: () => void; } export type ContextMenuProps = OriginalMenuProps | SubmenuProps; @observer export class ContextMenuItem extends React.Component { @observable private _items: Array = []; @observable private overItem = false; constructor(props: ContextMenuProps | SubmenuProps) { super(props); if ("subitems" in this.props) { this.props.subitems.forEach(i => this._items.push(i)); } } handleEvent = async (e: React.MouseEvent) => { if ("event" in this.props) { this.props.closeMenu && this.props.closeMenu(); let batch: UndoManager.Batch | undefined; if (this.props.undoable !== false) { batch = UndoManager.StartBatch(`Context menu event: ${this.props.description}`); } await this.props.event({ x: e.clientX, y: e.clientY }); batch && batch.end(); } } currentTimeout?: any; static readonly timeout = 300; onPointerEnter = () => { if (this.currentTimeout) { clearTimeout(this.currentTimeout); this.currentTimeout = undefined; } if (this.overItem) { return; } this.currentTimeout = setTimeout(action(() => this.overItem = true), ContextMenuItem.timeout); } onPointerLeave = () => { if (this.currentTimeout) { clearTimeout(this.currentTimeout); this.currentTimeout = undefined; } if (!this.overItem) { return; } this.currentTimeout = setTimeout(action(() => this.overItem = false), ContextMenuItem.timeout); } render() { if ("event" in this.props) { return (
{this.props.icon ? ( ) : null}
{this.props.description}
); } else if ("subitems" in this.props) { let submenu = !this.overItem ? (null) :
{this._items.map(prop => )}
; return (
{this.props.icon ? ( ) : null}
{this.props.description}
{submenu}
); } } }