UNPKG

@shoelace-style/shoelace

Version:

A forward-thinking library of web components.

193 lines (185 loc) 5.79 kB
import { menu_item_styles_default } from "./chunk.KZJNDGFO.js"; import { SubmenuController } from "./chunk.ZLIGP6HZ.js"; import { SlPopup } from "./chunk.5J7BMMD5.js"; import { SlSpinner } from "./chunk.TLKDQ5JG.js"; import { LocalizeController } from "./chunk.WLV3FVBR.js"; import { HasSlotController, getTextContent } from "./chunk.NYIIDP5N.js"; import { SlIcon } from "./chunk.E6QAPUBK.js"; import { watch } from "./chunk.CCJUT23E.js"; import { component_styles_default } from "./chunk.TUVJKY7S.js"; import { ShoelaceElement } from "./chunk.UYAO2JRR.js"; import { __decorateClass } from "./chunk.B3BW2AY6.js"; // src/components/menu-item/menu-item.component.ts import { classMap } from "lit/directives/class-map.js"; import { html } from "lit"; import { property, query } from "lit/decorators.js"; var SlMenuItem = class extends ShoelaceElement { constructor() { super(...arguments); this.localize = new LocalizeController(this); this.type = "normal"; this.checked = false; this.value = ""; this.loading = false; this.disabled = false; this.hasSlotController = new HasSlotController(this, "submenu"); this.submenuController = new SubmenuController(this, this.hasSlotController); this.handleHostClick = (event) => { if (this.disabled) { event.preventDefault(); event.stopImmediatePropagation(); } }; this.handleMouseOver = (event) => { this.focus(); event.stopPropagation(); }; } connectedCallback() { super.connectedCallback(); this.addEventListener("click", this.handleHostClick); this.addEventListener("mouseover", this.handleMouseOver); } disconnectedCallback() { super.disconnectedCallback(); this.removeEventListener("click", this.handleHostClick); this.removeEventListener("mouseover", this.handleMouseOver); } handleDefaultSlotChange() { const textLabel = this.getTextLabel(); if (typeof this.cachedTextLabel === "undefined") { this.cachedTextLabel = textLabel; return; } if (textLabel !== this.cachedTextLabel) { this.cachedTextLabel = textLabel; this.emit("slotchange", { bubbles: true, composed: false, cancelable: false }); } } handleCheckedChange() { if (this.checked && this.type !== "checkbox") { this.checked = false; console.error('The checked attribute can only be used on menu items with type="checkbox"', this); return; } if (this.type === "checkbox") { this.setAttribute("aria-checked", this.checked ? "true" : "false"); } else { this.removeAttribute("aria-checked"); } } handleDisabledChange() { this.setAttribute("aria-disabled", this.disabled ? "true" : "false"); } handleTypeChange() { if (this.type === "checkbox") { this.setAttribute("role", "menuitemcheckbox"); this.setAttribute("aria-checked", this.checked ? "true" : "false"); } else { this.setAttribute("role", "menuitem"); this.removeAttribute("aria-checked"); } } /** Returns a text label based on the contents of the menu item's default slot. */ getTextLabel() { return getTextContent(this.defaultSlot); } isSubmenu() { return this.hasSlotController.test("submenu"); } render() { const isRtl = this.localize.dir() === "rtl"; const isSubmenuExpanded = this.submenuController.isExpanded(); return html` <div id="anchor" part="base" class=${classMap({ "menu-item": true, "menu-item--rtl": isRtl, "menu-item--checked": this.checked, "menu-item--disabled": this.disabled, "menu-item--loading": this.loading, "menu-item--has-submenu": this.isSubmenu(), "menu-item--submenu-expanded": isSubmenuExpanded })} ?aria-haspopup="${this.isSubmenu()}" ?aria-expanded="${isSubmenuExpanded ? true : false}" > <span part="checked-icon" class="menu-item__check"> <sl-icon name="check" library="system" aria-hidden="true"></sl-icon> </span> <slot name="prefix" part="prefix" class="menu-item__prefix"></slot> <slot part="label" class="menu-item__label" @slotchange=${this.handleDefaultSlotChange}></slot> <slot name="suffix" part="suffix" class="menu-item__suffix"></slot> <span part="submenu-icon" class="menu-item__chevron"> <sl-icon name=${isRtl ? "chevron-left" : "chevron-right"} library="system" aria-hidden="true"></sl-icon> </span> ${this.submenuController.renderSubmenu()} ${this.loading ? html` <sl-spinner part="spinner" exportparts="base:spinner__base"></sl-spinner> ` : ""} </div> `; } }; SlMenuItem.styles = [component_styles_default, menu_item_styles_default]; SlMenuItem.dependencies = { "sl-icon": SlIcon, "sl-popup": SlPopup, "sl-spinner": SlSpinner }; __decorateClass([ query("slot:not([name])") ], SlMenuItem.prototype, "defaultSlot", 2); __decorateClass([ query(".menu-item") ], SlMenuItem.prototype, "menuItem", 2); __decorateClass([ property() ], SlMenuItem.prototype, "type", 2); __decorateClass([ property({ type: Boolean, reflect: true }) ], SlMenuItem.prototype, "checked", 2); __decorateClass([ property() ], SlMenuItem.prototype, "value", 2); __decorateClass([ property({ type: Boolean, reflect: true }) ], SlMenuItem.prototype, "loading", 2); __decorateClass([ property({ type: Boolean, reflect: true }) ], SlMenuItem.prototype, "disabled", 2); __decorateClass([ watch("checked") ], SlMenuItem.prototype, "handleCheckedChange", 1); __decorateClass([ watch("disabled") ], SlMenuItem.prototype, "handleDisabledChange", 1); __decorateClass([ watch("type") ], SlMenuItem.prototype, "handleTypeChange", 1); export { SlMenuItem };