import * as plugins from './plugins.js'; import { customElement, html, DeesElement, property, type TemplateResult, cssManager, css, type CSSResult, unsafeCSS, } from '@design.estate/dees-element'; import * as domtools from '@design.estate/dees-domtools'; import { DeesWindowLayer } from './dees-windowlayer.js'; declare global { interface HTMLElementTagNameMap { 'dees-contextmenu': DeesContextmenu; } } @customElement('dees-contextmenu') export class DeesContextmenu extends DeesElement { // DEMO public static demo = () => html` { DeesContextmenu.openContextMenuWithOptions(eventArg, [ { name: 'copy', iconName: 'copySolid', action: async () => { return null; }, }, { name: 'edit', iconName: 'penToSquare', action: async () => { return null; }, },{ name: 'paste', iconName: 'pasteSolid', action: async () => { return null; }, }, ]); }}>Hello {}, }, { name: 'edit', iconName: 'penToSquare', action: async () => {}, },{ name: 'paste', iconName: 'pasteSolid', action: async () => {}, }, ] as plugins.tsclass.website.IMenuItem[]} > `; // STATIC public static async openContextMenuWithOptions(eventArg: MouseEvent, menuItemsArg: plugins.tsclass.website.IMenuItem[]) { eventArg.preventDefault(); const contextMenu = new DeesContextmenu(); contextMenu.style.position = 'absolute'; contextMenu.style.zIndex = '2000'; contextMenu.style.top = `${eventArg.clientY.toString()}px`; contextMenu.style.left = `${eventArg.clientX.toString()}px`; contextMenu.style.opacity = '0'; contextMenu.style.transform = 'scale(0.95,0.95)'; contextMenu.style.transformOrigin = 'top left'; contextMenu.menuItems = menuItemsArg; contextMenu.windowLayer = await DeesWindowLayer.createAndShow(); contextMenu.windowLayer.addEventListener('click', async () => { await contextMenu.destroy(); }) document.body.append(contextMenu); await domtools.plugins.smartdelay.delayFor(0); contextMenu.style.opacity = '1'; contextMenu.style.transform = 'scale(1,1)'; } @property({ type: Array, }) public menuItems: plugins.tsclass.website.IMenuItem[] = []; windowLayer: DeesWindowLayer; constructor() { super(); } public static styles = [ cssManager.defaultStyles, css` :host { display: block; transition: all 0.1s; } .mainbox { color: ${cssManager.bdTheme('#222', '#ccc')}; font-size: 14px; width: 200px; border: 1px solid #444; min-height: 40px; border-radius: 3px; background: #222; box-shadow: 0px 1px 4px #000; user-select: none; } .mainbox .menuitem { padding: 8px; } .mainbox .menuitem dees-icon { display: inline-block; margin-right: 8px; width: 14px; transform: translateY(2px); } .mainbox .menuitem:hover { cursor: pointer; background: #ffffff10; } .mainbox .menuitem:active { cursor: pointer; background: #ffffff05; } `, ]; public render(): TemplateResult { return html`
${this.menuItems.map((menuItemArg) => { return html` `; })}
`; } public async firstUpdated() { if (!this.menuItems || this.menuItems.length === 0) { const mainbox = this.shadowRoot.querySelector('.mainbox'); mainbox.textContent = 'no menu items present'; } } public async handleClick(menuItem: plugins.tsclass.website.IMenuItem) { menuItem.action(); await this.destroy(); } public async destroy() { if (this.windowLayer) { this.windowLayer.destroy(); } this.style.opacity = '0'; this.style.transform = 'scale(0.95,0,95)'; await domtools.plugins.smartdelay.delayFor(100); this.parentElement.removeChild(this); } }