2020-11-26 14:57:22 +01:00

144 lines
3.9 KiB
TypeScript
Executable File

import verbosity from 'core/libs/verbosity'
import styles from './index.less'
import ReactDOM from 'react-dom'
import React from 'react'
let onRend = false
const renderDiv = document.createElement('div')
export interface ContextMenuComponent_props {
renderList: any;
yPos: number;
xPos: number;
app: any;
dispatch: any;
}
export class ContextMenuComponent extends React.PureComponent<ContextMenuComponent_props>{
listening: boolean
wrapperRef: any
eventListener: () => void
renderDiv: HTMLDivElement
state: any
constructor(props:any){
super(props)
this.state = {
renderList: null,
loading: true
}
this.renderDiv = renderDiv
this.listening = false
this.setWrapperRef = this.setWrapperRef.bind(this)
this.handleClickOutside = this.handleClickOutside.bind(this)
this.eventListener = () => {
document.addEventListener('click', this.handleClickOutside, false)
this.listening = true
}
}
setWrapperRef(node){
this.wrapperRef = node
}
handleClickOutside(event) {
if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
this.listening = false
DestroyContextMenu()
document.removeEventListener('click', this.eventListener, false)
}
}
filterArray(data: any[]) {
let tmp: any = []
return new Promise(resolve => {
data.forEach(async (element: { require: string; }) => {
if (typeof(element.require) !== 'undefined') {
const validRequire = await window.requireQuery(element.require)
validRequire? tmp.push(element) : null
}else{
tmp.push(element)
}
})
resolve(tmp)
})
}
async queryMenu(data){
this.setState({ renderList: await this.filterArray(data), loading: false })
}
handle(e:any, props:any){
if(!e || typeof(e) == 'undefined') {
return false
}
typeof(e.onClick) !== 'undefined' && e.onClick ? e.onClick(props) : null
typeof(e.keepOnClick) !== 'undefined' && e.keepOnClick ? null : DestroyContextMenu()
}
renderElements(){
if (!Array.isArray(this.state.renderList)) {
return null
}
return this.state.renderList.map((e:any) => {
return(
<div {...e.params.itemProps} onClick={() => this.handle(e.params, this.props)} key={e.key}>
{e.icon}{e.title}
</div>
)
})
}
componentDidMount(){
if (this.props.renderList) {
this.queryMenu(this.props.renderList)
}
}
componentDidUpdate(){
!this.listening ? this.eventListener() : null
}
render(){
if (this.state.loading) {
return null
}
return (
<div
id="contextualMenu"
ref={this.setWrapperRef}
className={styles.contextualMenu}
style={{
top: this.props.yPos,
left: this.props.xPos,
}}>
{this.renderElements()}
</div>
)
}
}
export function DestroyContextMenu(){
verbosity('destroying')
const unmountResult = ReactDOM.unmountComponentAtNode(renderDiv)
if (unmountResult && renderDiv.parentNode) {
renderDiv.parentNode.removeChild(renderDiv)
onRend = false
}
}
export function OpenContextMenu(props){
verbosity([props])
const renderComponent = React.createElement(ContextMenuComponent, props)
if (onRend) {
DestroyContextMenu()
}
document.body.appendChild(renderDiv).setAttribute('id', 'contextMenu')
ReactDOM.render(renderComponent, renderDiv)
onRend = true
}
export default OpenContextMenu