412 lines
12 KiB
JavaScript
412 lines
12 KiB
JavaScript
import { jsx as E } from "react/jsx-runtime";
|
|
import T from "react";
|
|
import { o as S } from "./create-component-CVXl33PD.mjs";
|
|
import { M as I, s as R, C as M, c as b, a as k, N as l, S as g, b as O, K as x, d as A } from "./menuItemController-CeB921ip.mjs";
|
|
import { r as $, _ as s, n as r, x as d, E as m, c as K, b as w, a as D } from "./class-map-CwiboTfb.mjs";
|
|
import "./ripple-pQcEjR05.mjs";
|
|
import { c as p, g as P, a as L, d as N } from "./item-CpL4zUlE.mjs";
|
|
import { a as F } from "./animation-DjClVFum.mjs";
|
|
import { o as f } from "./query-assigned-elements-DUhez03i.mjs";
|
|
import { n as H } from "./query-assigned-nodes-MKI2zKDb.mjs";
|
|
import { i as C, u as B } from "./static-DdXEOlS4.mjs";
|
|
import { m as _ } from "./delegate-BXi1gVeU.mjs";
|
|
/**
|
|
* @license
|
|
* Copyright 2022 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
const G = _($);
|
|
class i extends G {
|
|
constructor() {
|
|
super(...arguments), this.disabled = !1, this.type = "menuitem", this.href = "", this.target = "", this.keepOpen = !1, this.selected = !1, this.menuItemController = new I(this, {
|
|
getHeadlineElements: () => this.headlineElements,
|
|
getSupportingTextElements: () => this.supportingTextElements,
|
|
getDefaultElements: () => this.defaultElements,
|
|
getInteractiveElement: () => this.listItemRoot
|
|
});
|
|
}
|
|
/**
|
|
* The text that is selectable via typeahead. If not set, defaults to the
|
|
* innerText of the item slotted into the `"headline"` slot.
|
|
*/
|
|
get typeaheadText() {
|
|
return this.menuItemController.typeaheadText;
|
|
}
|
|
set typeaheadText(e) {
|
|
this.menuItemController.setTypeaheadText(e);
|
|
}
|
|
render() {
|
|
return this.renderListItem(d`
|
|
<md-item>
|
|
<div slot="container">
|
|
${this.renderRipple()} ${this.renderFocusRing()}
|
|
</div>
|
|
<slot name="start" slot="start"></slot>
|
|
<slot name="end" slot="end"></slot>
|
|
${this.renderBody()}
|
|
</md-item>
|
|
`);
|
|
}
|
|
/**
|
|
* Renders the root list item.
|
|
*
|
|
* @param content the child content of the list item.
|
|
*/
|
|
renderListItem(e) {
|
|
const o = this.type === "link";
|
|
let t;
|
|
switch (this.menuItemController.tagName) {
|
|
case "a":
|
|
t = C`a`;
|
|
break;
|
|
case "button":
|
|
t = C`button`;
|
|
break;
|
|
default:
|
|
case "li":
|
|
t = C`li`;
|
|
break;
|
|
}
|
|
const n = o && this.target ? this.target : m;
|
|
return B`
|
|
<${t}
|
|
id="item"
|
|
tabindex=${this.disabled && !o ? -1 : 0}
|
|
role=${this.menuItemController.role}
|
|
aria-label=${this.ariaLabel || m}
|
|
aria-selected=${this.ariaSelected || m}
|
|
aria-checked=${this.ariaChecked || m}
|
|
aria-expanded=${this.ariaExpanded || m}
|
|
aria-haspopup=${this.ariaHasPopup || m}
|
|
class="list-item ${K(this.getRenderClasses())}"
|
|
href=${this.href || m}
|
|
target=${n}
|
|
@click=${this.menuItemController.onClick}
|
|
@keydown=${this.menuItemController.onKeydown}
|
|
>${e}</${t}>
|
|
`;
|
|
}
|
|
/**
|
|
* Handles rendering of the ripple element.
|
|
*/
|
|
renderRipple() {
|
|
return d` <md-ripple
|
|
part="ripple"
|
|
for="item"
|
|
?disabled=${this.disabled}></md-ripple>`;
|
|
}
|
|
/**
|
|
* Handles rendering of the focus ring.
|
|
*/
|
|
renderFocusRing() {
|
|
return d` <md-focus-ring
|
|
part="focus-ring"
|
|
for="item"
|
|
inward></md-focus-ring>`;
|
|
}
|
|
/**
|
|
* Classes applied to the list item root.
|
|
*/
|
|
getRenderClasses() {
|
|
return {
|
|
disabled: this.disabled,
|
|
selected: this.selected
|
|
};
|
|
}
|
|
/**
|
|
* Handles rendering the headline and supporting text.
|
|
*/
|
|
renderBody() {
|
|
return d`
|
|
<slot></slot>
|
|
<slot name="overline" slot="overline"></slot>
|
|
<slot name="headline" slot="headline"></slot>
|
|
<slot name="supporting-text" slot="supporting-text"></slot>
|
|
<slot
|
|
name="trailing-supporting-text"
|
|
slot="trailing-supporting-text"></slot>
|
|
`;
|
|
}
|
|
focus() {
|
|
var e;
|
|
(e = this.listItemRoot) == null || e.focus();
|
|
}
|
|
}
|
|
i.shadowRootOptions = {
|
|
...$.shadowRootOptions,
|
|
delegatesFocus: !0
|
|
};
|
|
s([
|
|
r({ type: Boolean, reflect: !0 })
|
|
], i.prototype, "disabled", void 0);
|
|
s([
|
|
r()
|
|
], i.prototype, "type", void 0);
|
|
s([
|
|
r()
|
|
], i.prototype, "href", void 0);
|
|
s([
|
|
r()
|
|
], i.prototype, "target", void 0);
|
|
s([
|
|
r({ type: Boolean, attribute: "keep-open" })
|
|
], i.prototype, "keepOpen", void 0);
|
|
s([
|
|
r({ type: Boolean })
|
|
], i.prototype, "selected", void 0);
|
|
s([
|
|
F(".list-item")
|
|
], i.prototype, "listItemRoot", void 0);
|
|
s([
|
|
f({ slot: "headline" })
|
|
], i.prototype, "headlineElements", void 0);
|
|
s([
|
|
f({ slot: "supporting-text" })
|
|
], i.prototype, "supportingTextElements", void 0);
|
|
s([
|
|
H({ slot: "" })
|
|
], i.prototype, "defaultElements", void 0);
|
|
s([
|
|
r({ attribute: "typeahead-text" })
|
|
], i.prototype, "typeaheadText", null);
|
|
/**
|
|
* @license
|
|
* Copyright 2022 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
let c = class extends i {
|
|
};
|
|
c.styles = [R];
|
|
c = s([
|
|
w("md-menu-item")
|
|
], c);
|
|
/**
|
|
* @license
|
|
* Copyright 2023 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
let u = class extends $ {
|
|
get item() {
|
|
return this.items[0] ?? null;
|
|
}
|
|
get menu() {
|
|
return this.menus[0] ?? null;
|
|
}
|
|
constructor() {
|
|
super(), this.anchorCorner = M.START_END, this.menuCorner = M.START_START, this.hoverOpenDelay = 400, this.hoverCloseDelay = 400, this.isSubMenu = !0, this.previousOpenTimeout = 0, this.previousCloseTimeout = 0, this.onMouseenter = () => {
|
|
var e;
|
|
clearTimeout(this.previousOpenTimeout), clearTimeout(this.previousCloseTimeout), !((e = this.menu) != null && e.open) && (this.hoverOpenDelay ? this.previousOpenTimeout = setTimeout(() => {
|
|
this.show();
|
|
}, this.hoverOpenDelay) : this.show());
|
|
}, this.onMouseleave = () => {
|
|
clearTimeout(this.previousCloseTimeout), clearTimeout(this.previousOpenTimeout), this.hoverCloseDelay ? this.previousCloseTimeout = setTimeout(() => {
|
|
this.close();
|
|
}, this.hoverCloseDelay) : this.close();
|
|
}, this.addEventListener("mouseenter", this.onMouseenter), this.addEventListener("mouseleave", this.onMouseleave);
|
|
}
|
|
render() {
|
|
return d`
|
|
<slot
|
|
name="item"
|
|
@click=${this.onClick}
|
|
@keydown=${this.onKeydown}
|
|
@slotchange=${this.onSlotchange}>
|
|
</slot>
|
|
<slot
|
|
name="menu"
|
|
@keydown=${this.onSubMenuKeydown}
|
|
@close-menu=${this.onCloseSubmenu}
|
|
@slotchange=${this.onSlotchange}>
|
|
</slot>
|
|
`;
|
|
}
|
|
firstUpdated() {
|
|
this.onSlotchange();
|
|
}
|
|
/**
|
|
* Shows the submenu.
|
|
*/
|
|
async show() {
|
|
const e = this.menu;
|
|
if (!e || e.open)
|
|
return;
|
|
e.addEventListener("closed", () => {
|
|
this.item.ariaExpanded = "false", this.dispatchEvent(b()), this.dispatchEvent(p()), e.ariaHidden = "true";
|
|
}, { once: !0 }), e.positioning === "document" && (e.positioning = "absolute"), e.quick = !0, e.hasOverflow = !0, e.anchorCorner = this.anchorCorner, e.menuCorner = this.menuCorner, e.anchorElement = this.item, e.defaultFocus = "first-item", e.removeAttribute("aria-hidden"), e.skipRestoreFocus = !1;
|
|
const o = e.open;
|
|
if (e.show(), this.item.ariaExpanded = "true", this.item.ariaHasPopup = "menu", e.id && this.item.setAttribute("aria-controls", e.id), this.dispatchEvent(p()), this.dispatchEvent(k()), this.item.selected = !0, !o) {
|
|
let t = (h) => {
|
|
};
|
|
const n = new Promise((h) => {
|
|
t = h;
|
|
});
|
|
e.addEventListener("opened", t, { once: !0 }), await n;
|
|
}
|
|
}
|
|
/**
|
|
* Closes the submenu.
|
|
*/
|
|
async close() {
|
|
const e = this.menu;
|
|
if (!e || !e.open)
|
|
return;
|
|
this.dispatchEvent(b()), e.quick = !0, e.close(), this.dispatchEvent(p());
|
|
let o = (n) => {
|
|
};
|
|
const t = new Promise((n) => {
|
|
o = n;
|
|
});
|
|
e.addEventListener("closed", o, { once: !0 }), await t;
|
|
}
|
|
onSlotchange() {
|
|
var o;
|
|
if (!this.item)
|
|
return;
|
|
this.item.ariaExpanded = "false", this.item.ariaHasPopup = "menu", (o = this.menu) != null && o.id && this.item.setAttribute("aria-controls", this.menu.id), this.item.keepOpen = !0;
|
|
const e = this.menu;
|
|
e && (e.isSubmenu = !0, e.ariaHidden = "true");
|
|
}
|
|
onClick() {
|
|
this.show();
|
|
}
|
|
/**
|
|
* On item keydown handles opening the submenu.
|
|
*/
|
|
async onKeydown(e) {
|
|
const o = this.isSubmenuOpenKey(e.code);
|
|
if (e.defaultPrevented)
|
|
return;
|
|
const t = o && (l.LEFT === e.code || l.RIGHT === e.code);
|
|
if ((e.code === g.SPACE || t) && (e.preventDefault(), t && e.stopPropagation()), !o)
|
|
return;
|
|
const n = this.menu;
|
|
if (!n)
|
|
return;
|
|
const h = n.items, v = P(h);
|
|
if (v) {
|
|
await this.show(), v.tabIndex = 0, v.focus();
|
|
return;
|
|
}
|
|
}
|
|
onCloseSubmenu(e) {
|
|
const { itemPath: o, reason: t } = e.detail;
|
|
if (o.push(this.item), this.dispatchEvent(b()), t.kind === O.KEYDOWN && t.key === x.ESCAPE) {
|
|
e.stopPropagation(), this.item.dispatchEvent(L());
|
|
return;
|
|
}
|
|
this.dispatchEvent(p());
|
|
}
|
|
async onSubMenuKeydown(e) {
|
|
var n;
|
|
if (e.defaultPrevented)
|
|
return;
|
|
const { close: o, keyCode: t } = this.isSubmenuCloseKey(e.code);
|
|
o && (e.preventDefault(), (t === l.LEFT || t === l.RIGHT) && e.stopPropagation(), await this.close(), N(this.menu.items), (n = this.item) == null || n.focus(), this.item.tabIndex = 0, this.item.focus());
|
|
}
|
|
/**
|
|
* Determines whether the given KeyboardEvent code is one that should open
|
|
* the submenu. This is RTL-aware. By default, left, right, space, or enter.
|
|
*
|
|
* @param code The native KeyboardEvent code.
|
|
* @return Whether or not the key code should open the submenu.
|
|
*/
|
|
isSubmenuOpenKey(e) {
|
|
const t = getComputedStyle(this).direction === "rtl" ? l.LEFT : l.RIGHT;
|
|
switch (e) {
|
|
case t:
|
|
case g.SPACE:
|
|
case g.ENTER:
|
|
return !0;
|
|
default:
|
|
return !1;
|
|
}
|
|
}
|
|
/**
|
|
* Determines whether the given KeyboardEvent code is one that should close
|
|
* the submenu. This is RTL-aware. By default right, left, or escape.
|
|
*
|
|
* @param code The native KeyboardEvent code.
|
|
* @return Whether or not the key code should close the submenu.
|
|
*/
|
|
isSubmenuCloseKey(e) {
|
|
const t = getComputedStyle(this).direction === "rtl" ? l.RIGHT : l.LEFT;
|
|
switch (e) {
|
|
case t:
|
|
case x.ESCAPE:
|
|
return { close: !0, keyCode: e };
|
|
default:
|
|
return { close: !1 };
|
|
}
|
|
}
|
|
};
|
|
s([
|
|
r({ attribute: "anchor-corner" })
|
|
], u.prototype, "anchorCorner", void 0);
|
|
s([
|
|
r({ attribute: "menu-corner" })
|
|
], u.prototype, "menuCorner", void 0);
|
|
s([
|
|
r({ type: Number, attribute: "hover-open-delay" })
|
|
], u.prototype, "hoverOpenDelay", void 0);
|
|
s([
|
|
r({ type: Number, attribute: "hover-close-delay" })
|
|
], u.prototype, "hoverCloseDelay", void 0);
|
|
s([
|
|
r({ type: Boolean, reflect: !0, attribute: "md-sub-menu" })
|
|
], u.prototype, "isSubMenu", void 0);
|
|
s([
|
|
f({ slot: "item", flatten: !0 })
|
|
], u.prototype, "items", void 0);
|
|
s([
|
|
f({ slot: "menu", flatten: !0 })
|
|
], u.prototype, "menus", void 0);
|
|
/**
|
|
* @license
|
|
* Copyright 2024 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
const q = D`:host{position:relative;display:flex;flex-direction:column}
|
|
`;
|
|
/**
|
|
* @license
|
|
* Copyright 2023 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
let y = class extends u {
|
|
};
|
|
y.styles = [q];
|
|
y = s([
|
|
w("md-sub-menu")
|
|
], y);
|
|
const W = S({
|
|
react: T,
|
|
tagName: "md-menu",
|
|
elementClass: A
|
|
}), j = S({
|
|
react: T,
|
|
tagName: "md-menu-item",
|
|
elementClass: c,
|
|
events: {
|
|
"close-menu": "onCloseMenu"
|
|
}
|
|
}), U = S({
|
|
react: T,
|
|
tagName: "md-sub-menu",
|
|
elementClass: y
|
|
}), le = (a) => /* @__PURE__ */ E(
|
|
W,
|
|
{
|
|
...a
|
|
}
|
|
), ue = (a) => /* @__PURE__ */ E(
|
|
U,
|
|
{
|
|
...a
|
|
}
|
|
), me = (a) => /* @__PURE__ */ E(j, { ...a });
|
|
export {
|
|
le as Menu,
|
|
me as MenuItem,
|
|
ue as SubMenu
|
|
};
|