import Thorium , {Components , Controller, UserInterface , Mouse , Events , useState} from "thoriumjs"; import {LineControl} from "../../elements/linecontrols/linecontrols"; import {IconInitOptions} from "../../elements/icon/icon"; import style from '../../../styles/contextualmenu.module.css'; const { Div, } = Components; type ContextualMenuElementType = "label"|"separator"; interface ContextualMenuInit{ title?:string; type?:ContextualMenuElementType; action?:(contoller:Controller) => void; children?:ContextualMenuOptionsInit; icon?:IconInitOptions; controls?:[]; prop?:Thorium.ElementInterface['prop']; } type ContextualMenuOptionsInit = ContextualMenuInit[]; export class ContextualMenu extends Div{ constructor(options:ContextualMenuOptionsInit , position:typeof Mouse.position){ const [cursorIsOnMenu,updateCursor] = useState(false); const [eventId,updateEvent] = useState(null); super({ prop : { name : 'ContextualMenu', class : `${style.ContextualMenu} context`, style: `top:${position.y}px;left:${position.x}px;`, }, childrens : Array.from(options , (option,iterator) => { option = {type : 'label' , ...option}; if(option.type == 'label')return new LineControl({ text : option.title, ...(option.icon ? {icon : option.icon} : {}), ...(option.action ? {onLineMouseDown : (function(event:Event){ const element = event.target as Controller; option.action(element); element.context(null).remove(); })} : {}), ...(option.controls ? {controls : option.controls} : {}), ...(option.prop ? {prop : option.prop} : {}) }) if(option.type == 'separator')return { type : 'hr' }; }), proto : { onMouseEnter(){ updateCursor(true); if(eventId.value == null)updateEvent(Events.Add('mousedown' , () => { if(cursorIsOnMenu.value == false){ this.remove(); Events.Remove(eventId.value); } })); }, onMouseLeave(){ updateCursor(false); } } }) } } export default function Menu(options:ContextualMenuOptionsInit){ new UserInterface.NodeUI([ new ContextualMenu(options , Mouse.position) ]).BuildIn(document.body) .then((node) => {node.Initialise()}) }