130 lines
3.1 KiB
TypeScript
130 lines
3.1 KiB
TypeScript
import { LitElement, html, css } from 'lit';
|
|
import { property, state } from 'lit/decorators.js';
|
|
|
|
export const EVENT_MENU_ITEM_SELECTED = 'menu-item-selected';
|
|
export const EVENT_MENU_ITEM_UNSELECTED = 'menu-item-unselected';
|
|
|
|
export class MenuItem extends LitElement {
|
|
@property({ attribute: 'icon-url', type: String })
|
|
iconUrl: string;
|
|
|
|
@property({ attribute: 'label', type: String })
|
|
label: string;
|
|
|
|
static styles = css`
|
|
:host {
|
|
display: inline-block;
|
|
height: 100%;
|
|
flex: 1;
|
|
cursor: pointer;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-bottom: 1px solid rgb(229,231,235);
|
|
border-top: 10px solid transparent;
|
|
transition: all 100ms ease-out;
|
|
background-color: #fff;
|
|
}
|
|
:host(:hover) {
|
|
background-color: rgb(249,250,251);
|
|
}
|
|
:host(.selected) {
|
|
border-top: 10px solid #03A9F4;
|
|
border-bottom: 1px solid transparent;
|
|
background-color: #fff;
|
|
}
|
|
:host(.unselected) {
|
|
background-color: hsl(210 20% 95% / 1);
|
|
}
|
|
.menu-item-icon {
|
|
height: 30px;
|
|
width: 30px;
|
|
overflow: hidden;
|
|
}
|
|
.menu-item-icon > img {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
.menu-item-panel {
|
|
display: none;
|
|
position: fixed;
|
|
top: 65px;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 9999;
|
|
background-color: #fff;
|
|
box-shadow: 0px 4px 5px 0px hsl(0deg 0% 0% / 10%);
|
|
max-height: 75%;
|
|
overflow-y: auto;
|
|
}
|
|
:host(.selected) .menu-item-panel {
|
|
display: block;
|
|
}
|
|
.menu-item-label {
|
|
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
|
|
color: black;
|
|
font-size: 14px;
|
|
margin: 3px 0;
|
|
}
|
|
`;
|
|
|
|
@state()
|
|
selected: boolean
|
|
|
|
constructor() {
|
|
super();
|
|
this.addEventListener('click', this._handleClick.bind(this));
|
|
}
|
|
|
|
|
|
render() {
|
|
return html`
|
|
<div class="menu-item-icon">
|
|
${
|
|
this.iconUrl ?
|
|
html`<img src="${this.iconUrl}" />` :
|
|
''
|
|
}
|
|
</div>
|
|
<div class="menu-item-label">
|
|
${this.label}
|
|
</div>
|
|
<div class="menu-item-panel">
|
|
<slot></slot>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
_handleClick() {
|
|
if (this.selected) {
|
|
this.unselect();
|
|
} else {
|
|
this.select();
|
|
}
|
|
}
|
|
|
|
select() {
|
|
this.selected = true;
|
|
const event = new CustomEvent(EVENT_MENU_ITEM_SELECTED, {
|
|
bubbles: true,
|
|
composed: true,
|
|
detail: {
|
|
element: this,
|
|
}
|
|
});
|
|
this.dispatchEvent(event);
|
|
}
|
|
|
|
unselect() {
|
|
this.selected = false;
|
|
const event = new CustomEvent(EVENT_MENU_ITEM_UNSELECTED, {
|
|
bubbles: true,
|
|
composed: true,
|
|
detail: {
|
|
element: this,
|
|
}
|
|
});
|
|
this.dispatchEvent(event);
|
|
}
|
|
} |