import {css, html, LitElement, nothing} from "lit"; import {SlMenu, SlMenuItem} from "@shoelace-style/shoelace"; import {egwMenuItem} from "./egw_menu"; import {customElement} from "lit/decorators/custom-element.js"; import {repeat} from "lit/directives/repeat.js"; import {classMap} from "lit/directives/class-map.js"; @customElement("egw-menu-shoelace") export class EgwMenuShoelace extends LitElement { static get styles() { return [ css` :host { display: block; /* Fit in popup, scroll if not enough height */ max-height: var(--auto-size-available-height, auto); overflow-y: auto; } .default-item::part(label) { font-weight: var(--sl-font-weight-bold, bold); } et2-image { width: 1.5em; } ` ] } private structure = []; private popup = null; private removeCallback = null; private get menu() : SlMenu { return this.shadowRoot?.querySelector("sl-menu");} constructor(_structure : egwMenuItem[]) { super(); this.structure = _structure; } connectedCallback() { super.connectedCallback(); } disconnectedCallback() { super.disconnectedCallback(); if(this.popup) { this.popup.remove(); this.popup = null; } if(this.removeCallback) { this.removeCallback.call(); } } public showAt(_x, _y, _onHide) { this.removeCallback = _onHide; if(this.popup == null) { this.popup = document.createElement("sl-popup"); this.popup.placement = "bottom"; this.popup.autoSize = "vertical"; this.popup.flip = true; this.popup.shift = true; this.popup.classList.add("egw_menu") document.body.append(this.popup); this.popup.append(this); } this.popup.anchor = { getBoundingClientRect() { return { x: _x, y: _y, width: 0, height: 0, top: _y, left: _x, right: _x, bottom: _y } } }; this.popup.active = true; Promise.all([this.updateComplete, this.popup.updateComplete]).then(() => { // Causes scroll issues if we don't position this.popup.popup.style = "top: 0px"; (this.menu.querySelector('sl-menu-item')).focus(); }); } public hide() { this.popup.active = false; // egw_menu always creates a new menu this.remove(); } handleSelect(event) { if(!this.popup) { return; } if(event.detail.item.value) { const item = event.detail.item.value; if(item.checkbox) { item.checked = event.detail.item.checked; return; } if(typeof item.onClick == "function") { this.hide(); item.onClick.call(event.detail.item, item, event); } } } private itemTemplate(item : egwMenuItem) { if(item.caption == "-") { return html` `; } return html` ${item.iconUrl ? html` ` : nothing} ${item.caption} ${item.shortcutCaption ? html` ${item.shortcutCaption} ` : nothing} ${item.children.length == 0 ? nothing : html` ${repeat(item.children, i => this.itemTemplate(i))} `} `; } render() { return html` ${repeat(this.structure, i => this.itemTemplate(i))} `; } }