import { _ as r, n as u, r as J, x as z, c as ee, E as te, a as V, b as ie } from "./class-map-CwiboTfb.mjs"; import "./elevation-Dg8ssDJC.mjs"; import "./ripple-pQcEjR05.mjs"; import { r as ne, a as j, c as se, E as _ } from "./animation-DjClVFum.mjs"; import { o as oe } from "./query-assigned-elements-DUhez03i.mjs"; import { o as ae } from "./style-map-CdUj7GnE.mjs"; import { N as S, L as re, b as le, e as ce, g as de } from "./item-CpL4zUlE.mjs"; /** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ function he(g, e) { return new CustomEvent("close-menu", { bubbles: !0, composed: !0, detail: { initiator: g, reason: e, itemPath: [g] } }); } const Y = he; function Ae() { return new Event("deactivate-typeahead", { bubbles: !0, composed: !0 }); } function Oe() { return new Event("activate-typeahead", { bubbles: !0, composed: !0 }); } const Re = { UP: "ArrowUp", DOWN: "ArrowDown", RIGHT: "ArrowRight", LEFT: "ArrowLeft" }, W = { SPACE: "Space", ENTER: "Enter" }, q = { CLICK_SELECTION: "click-selection", KEYDOWN: "keydown" }, pe = { ESCAPE: "Escape", SPACE: W.SPACE, ENTER: W.ENTER }; function Z(g) { return Object.values(pe).some((e) => e === g); } function ke(g) { return Object.values(W).some((e) => e === g); } function G(g, e) { const t = new Event("md-contains", { bubbles: !0, composed: !0 }); let i = []; const s = (p) => { i = p.composedPath(); }; return e.addEventListener("md-contains", s), g.dispatchEvent(t), e.removeEventListener("md-contains", s), i.length > 0; } const B = { NONE: "none", LIST_ROOT: "list-root", FIRST_ITEM: "first-item", LAST_ITEM: "last-item" }; /** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ const X = { END_START: "end-start", END_END: "end-end", START_START: "start-start", START_END: "start-end" }; class ue { /** * @param host The host to connect the controller to. * @param getProperties A function that returns the properties for the * controller. */ constructor(e, t) { this.host = e, this.getProperties = t, this.surfaceStylesInternal = { display: "none" }, this.lastValues = { isOpen: !1 }, this.host.addController(this); } /** * The StyleInfo map to apply to the surface via Lit's stylemap */ get surfaceStyles() { return this.surfaceStylesInternal; } /** * Calculates the surface's new position required so that the surface's * `surfaceCorner` aligns to the anchor's `anchorCorner` while keeping the * surface inside the window viewport. This positioning also respects RTL by * checking `getComputedStyle()` on the surface element. */ async position() { const { surfaceEl: e, anchorEl: t, anchorCorner: i, surfaceCorner: s, positioning: n, xOffset: p, yOffset: a, disableBlockFlip: o, disableInlineFlip: m, repositionStrategy: v } = this.getProperties(), I = i.toLowerCase().trim(), w = s.toLowerCase().trim(); if (!e || !t) return; const b = window.innerWidth, C = window.innerHeight, c = document.createElement("div"); c.style.opacity = "0", c.style.position = "fixed", c.style.display = "block", c.style.inset = "0", document.body.appendChild(c); const f = c.getBoundingClientRect(); c.remove(); const x = window.innerHeight - f.bottom, d = window.innerWidth - f.right; this.surfaceStylesInternal = { display: "block", opacity: "0" }, this.host.requestUpdate(), await this.host.updateComplete, e.popover && e.isConnected && e.showPopover(); const E = e.getSurfacePositionClientRect ? e.getSurfacePositionClientRect() : e.getBoundingClientRect(), y = t.getSurfacePositionClientRect ? t.getSurfacePositionClientRect() : t.getBoundingClientRect(), [h, R] = w.split("-"), [k, L] = I.split("-"), N = getComputedStyle(e).direction === "ltr"; let { blockInset: P, blockOutOfBoundsCorrection: A, surfaceBlockProperty: $ } = this.calculateBlock({ surfaceRect: E, anchorRect: y, anchorBlock: k, surfaceBlock: h, yOffset: a, positioning: n, windowInnerHeight: C, blockScrollbarHeight: x }); if (A && !o) { const M = h === "start" ? "end" : "start", U = k === "start" ? "end" : "start", O = this.calculateBlock({ surfaceRect: E, anchorRect: y, anchorBlock: U, surfaceBlock: M, yOffset: a, positioning: n, windowInnerHeight: C, blockScrollbarHeight: x }); A > O.blockOutOfBoundsCorrection && (P = O.blockInset, A = O.blockOutOfBoundsCorrection, $ = O.surfaceBlockProperty); } let { inlineInset: F, inlineOutOfBoundsCorrection: D, surfaceInlineProperty: K } = this.calculateInline({ surfaceRect: E, anchorRect: y, anchorInline: L, surfaceInline: R, xOffset: p, positioning: n, isLTR: N, windowInnerWidth: b, inlineScrollbarWidth: d }); if (D && !m) { const M = R === "start" ? "end" : "start", U = L === "start" ? "end" : "start", O = this.calculateInline({ surfaceRect: E, anchorRect: y, anchorInline: U, surfaceInline: M, xOffset: p, positioning: n, isLTR: N, windowInnerWidth: b, inlineScrollbarWidth: d }); Math.abs(D) > Math.abs(O.inlineOutOfBoundsCorrection) && (F = O.inlineInset, D = O.inlineOutOfBoundsCorrection, K = O.surfaceInlineProperty); } v === "move" && (P = P - A, F = F - D), this.surfaceStylesInternal = { display: "block", opacity: "1", [$]: `${P}px`, [K]: `${F}px` }, v === "resize" && (A && (this.surfaceStylesInternal.height = `${E.height - A}px`), D && (this.surfaceStylesInternal.width = `${E.width - D}px`)), this.host.requestUpdate(); } /** * Calculates the css property, the inset, and the out of bounds correction * for the surface in the block direction. */ calculateBlock(e) { const { surfaceRect: t, anchorRect: i, anchorBlock: s, surfaceBlock: n, yOffset: p, positioning: a, windowInnerHeight: o, blockScrollbarHeight: m } = e, v = a === "fixed" || a === "document" ? 1 : 0, I = a === "document" ? 1 : 0, w = n === "start" ? 1 : 0, b = n === "end" ? 1 : 0, c = (s !== n ? 1 : 0) * i.height + p, f = w * i.top + b * (o - i.bottom - m), x = w * window.scrollY - b * window.scrollY, d = Math.abs(Math.min(0, o - f - c - t.height)); return { blockInset: v * f + I * x + c, blockOutOfBoundsCorrection: d, surfaceBlockProperty: n === "start" ? "inset-block-start" : "inset-block-end" }; } /** * Calculates the css property, the inset, and the out of bounds correction * for the surface in the inline direction. */ calculateInline(e) { const { isLTR: t, surfaceInline: i, anchorInline: s, anchorRect: n, surfaceRect: p, xOffset: a, positioning: o, windowInnerWidth: m, inlineScrollbarWidth: v } = e, I = o === "fixed" || o === "document" ? 1 : 0, w = o === "document" ? 1 : 0, b = t ? 1 : 0, C = t ? 0 : 1, c = i === "start" ? 1 : 0, f = i === "end" ? 1 : 0, d = (s !== i ? 1 : 0) * n.width + a, E = c * n.left + f * (m - n.right - v), y = c * (m - n.right - v) + f * n.left, h = b * E + C * y, R = c * window.scrollX - f * window.scrollX, k = f * window.scrollX - c * window.scrollX, L = b * R + C * k, N = Math.abs(Math.min(0, m - h - d - p.width)), P = I * h + d + w * L; let A = i === "start" ? "inset-inline-start" : "inset-inline-end"; return (o === "document" || o === "fixed") && (i === "start" && t || i === "end" && !t ? A = "left" : A = "right"), { inlineInset: P, inlineOutOfBoundsCorrection: N, surfaceInlineProperty: A }; } hostUpdate() { this.onUpdate(); } hostUpdated() { this.onUpdate(); } /** * Checks whether the properties passed into the controller have changed since * the last positioning. If so, it will reposition if the surface is open or * close it if the surface should close. */ async onUpdate() { const e = this.getProperties(); let t = !1; for (const [p, a] of Object.entries(e)) if (t = t || a !== this.lastValues[p], t) break; const i = this.lastValues.isOpen !== e.isOpen, s = !!e.anchorEl, n = !!e.surfaceEl; t && s && n && (this.lastValues.isOpen = e.isOpen, e.isOpen ? (this.lastValues = e, await this.position(), e.onOpen()) : i && (await e.beforeClose(), this.close(), e.onClose())); } /** * Hides the surface. */ close() { this.surfaceStylesInternal = { display: "none" }, this.host.requestUpdate(); const e = this.getProperties().surfaceEl; e != null && e.popover && (e != null && e.isConnected) && e.hidePopover(); } } /** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ const T = { INDEX: 0, ITEM: 1, TEXT: 2 }; class me { /** * @param getProperties A function that returns the options of the typeahead * controller: * * { * getItems: A function that returns an array of menu items to be searched. * typeaheadBufferTime: The maximum time between each keystroke to keep the * current type buffer alive. * } */ constructor(e) { this.getProperties = e, this.typeaheadRecords = [], this.typaheadBuffer = "", this.cancelTypeaheadTimeout = 0, this.isTypingAhead = !1, this.lastActiveRecord = null, this.onKeydown = (t) => { this.isTypingAhead ? this.typeahead(t) : this.beginTypeahead(t); }, this.endTypeahead = () => { this.isTypingAhead = !1, this.typaheadBuffer = "", this.typeaheadRecords = []; }; } get items() { return this.getProperties().getItems(); } get active() { return this.getProperties().active; } /** * Sets up typingahead */ beginTypeahead(e) { this.active && (e.code === "Space" || e.code === "Enter" || e.code.startsWith("Arrow") || e.code === "Escape" || (this.isTypingAhead = !0, this.typeaheadRecords = this.items.map((t, i) => [ i, t, t.typeaheadText.trim().toLowerCase() ]), this.lastActiveRecord = this.typeaheadRecords.find((t) => t[T.ITEM].tabIndex === 0) ?? null, this.lastActiveRecord && (this.lastActiveRecord[T.ITEM].tabIndex = -1), this.typeahead(e))); } /** * Performs the typeahead. Based on the normalized items and the current text * buffer, finds the _next_ item with matching text and activates it. * * @example * * items: Apple, Banana, Olive, Orange, Cucumber * buffer: '' * user types: o * * activates Olive * * @example * * items: Apple, Banana, Olive (active), Orange, Cucumber * buffer: 'o' * user types: l * * activates Olive * * @example * * items: Apple, Banana, Olive (active), Orange, Cucumber * buffer: '' * user types: o * * activates Orange * * @example * * items: Apple, Banana, Olive, Orange (active), Cucumber * buffer: '' * user types: o * * activates Olive */ typeahead(e) { if (e.defaultPrevented) return; if (clearTimeout(this.cancelTypeaheadTimeout), e.code === "Enter" || e.code.startsWith("Arrow") || e.code === "Escape") { this.endTypeahead(), this.lastActiveRecord && (this.lastActiveRecord[T.ITEM].tabIndex = -1); return; } e.code === "Space" && e.preventDefault(), this.cancelTypeaheadTimeout = setTimeout(this.endTypeahead, this.getProperties().typeaheadBufferTime), this.typaheadBuffer += e.key.toLowerCase(); const t = this.lastActiveRecord ? this.lastActiveRecord[T.INDEX] : -1, i = this.typeaheadRecords.length, s = (o) => (o[T.INDEX] + i - t) % i, n = this.typeaheadRecords.filter((o) => !o[T.ITEM].disabled && o[T.TEXT].startsWith(this.typaheadBuffer)).sort((o, m) => s(o) - s(m)); if (n.length === 0) { clearTimeout(this.cancelTypeaheadTimeout), this.lastActiveRecord && (this.lastActiveRecord[T.ITEM].tabIndex = -1), this.endTypeahead(); return; } const p = this.typaheadBuffer.length === 1; let a; this.lastActiveRecord === n[0] && p ? a = n[1] ?? n[0] : a = n[0], this.lastActiveRecord && (this.lastActiveRecord[T.ITEM].tabIndex = -1), this.lastActiveRecord = a, a[T.ITEM].tabIndex = 0, a[T.ITEM].focus(); } } /** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ const fe = 200, Q = /* @__PURE__ */ new Set([ S.ArrowDown, S.ArrowUp, S.Home, S.End ]), ye = /* @__PURE__ */ new Set([ S.ArrowLeft, S.ArrowRight, ...Q ]); function ge(g = document) { var t; let e = g.activeElement; for (; e && ((t = e == null ? void 0 : e.shadowRoot) != null && t.activeElement); ) e = e.shadowRoot.activeElement; return e; } class l extends J { /** * Whether the menu is animating upwards or downwards when opening. This is * helpful for calculating some animation calculations. */ get openDirection() { return this.menuCorner.split("-")[0] === "start" ? "DOWN" : "UP"; } /** * The element which the menu should align to. If `anchor` is set to a * non-empty idref string, then `anchorEl` will resolve to the element with * the given id in the same root node. Otherwise, `null`. */ get anchorElement() { return this.anchor ? this.getRootNode().querySelector(`#${this.anchor}`) : this.currentAnchorElement; } set anchorElement(e) { this.currentAnchorElement = e, this.requestUpdate("anchorElement"); } constructor() { super(), this.anchor = "", this.positioning = "absolute", this.quick = !1, this.hasOverflow = !1, this.open = !1, this.xOffset = 0, this.yOffset = 0, this.noHorizontalFlip = !1, this.noVerticalFlip = !1, this.typeaheadDelay = fe, this.anchorCorner = X.END_START, this.menuCorner = X.START_START, this.stayOpenOnOutsideClick = !1, this.stayOpenOnFocusout = !1, this.skipRestoreFocus = !1, this.defaultFocus = B.FIRST_ITEM, this.noNavigationWrap = !1, this.typeaheadActive = !0, this.isSubmenu = !1, this.pointerPath = [], this.isRepositioning = !1, this.openCloseAnimationSignal = se(), this.listController = new re({ isItem: (e) => e.hasAttribute("md-menu-item"), getPossibleItems: () => this.slotItems, isRtl: () => getComputedStyle(this).direction === "rtl", deactivateItem: (e) => { e.selected = !1, e.tabIndex = -1; }, activateItem: (e) => { e.selected = !0, e.tabIndex = 0; }, isNavigableKey: (e) => { if (!this.isSubmenu) return ye.has(e); const i = getComputedStyle(this).direction === "rtl" ? S.ArrowLeft : S.ArrowRight; return e === i ? !0 : Q.has(e); }, wrapNavigation: () => !this.noNavigationWrap }), this.lastFocusedElement = null, this.typeaheadController = new me(() => ({ getItems: () => this.items, typeaheadBufferTime: this.typeaheadDelay, active: this.typeaheadActive })), this.currentAnchorElement = null, this.internals = // Cast needed for closure this.attachInternals(), this.menuPositionController = new ue(this, () => ({ anchorCorner: this.anchorCorner, surfaceCorner: this.menuCorner, surfaceEl: this.surfaceEl, anchorEl: this.anchorElement, positioning: this.positioning === "popover" ? "document" : this.positioning, isOpen: this.open, xOffset: this.xOffset, yOffset: this.yOffset, disableBlockFlip: this.noVerticalFlip, disableInlineFlip: this.noHorizontalFlip, onOpen: this.onOpened, beforeClose: this.beforeClose, onClose: this.onClosed, // We can't resize components that have overflow like menus with // submenus because the overflow-y will show menu items / content // outside the bounds of the menu. Popover API fixes this because each // submenu is hoisted to the top-layer and are not considered overflow // content. repositionStrategy: this.hasOverflow && this.positioning !== "popover" ? "move" : "resize" })), this.onWindowResize = () => { this.isRepositioning || this.positioning !== "document" && this.positioning !== "fixed" && this.positioning !== "popover" || (this.isRepositioning = !0, this.reposition(), this.isRepositioning = !1); }, this.handleFocusout = async (e) => { const t = this.anchorElement; if (this.stayOpenOnFocusout || !this.open || this.pointerPath.includes(t)) return; if (e.relatedTarget) { if (G(e.relatedTarget, this) || this.pointerPath.length !== 0 && G(e.relatedTarget, t)) return; } else if (this.pointerPath.includes(this)) return; const i = this.skipRestoreFocus; this.skipRestoreFocus = !0, this.close(), await this.updateComplete, this.skipRestoreFocus = i; }, this.onOpened = async () => { this.lastFocusedElement = ge(); const e = this.items, t = le(e); t && this.defaultFocus !== B.NONE && (t.item.tabIndex = -1); let i = !this.quick; switch (this.quick ? this.dispatchEvent(new Event("opening")) : i = !!await this.animateOpen(), this.defaultFocus) { case B.FIRST_ITEM: const s = de(e); s && (s.tabIndex = 0, s.focus(), await s.updateComplete); break; case B.LAST_ITEM: const n = ce(e); n && (n.tabIndex = 0, n.focus(), await n.updateComplete); break; case B.LIST_ROOT: this.focus(); break; default: case B.NONE: break; } i || this.dispatchEvent(new Event("opened")); }, this.beforeClose = async () => { var e, t; this.open = !1, this.skipRestoreFocus || (t = (e = this.lastFocusedElement) == null ? void 0 : e.focus) == null || t.call(e), this.quick || await this.animateClose(); }, this.onClosed = () => { this.quick && (this.dispatchEvent(new Event("closing")), this.dispatchEvent(new Event("closed"))); }, this.onWindowPointerdown = (e) => { this.pointerPath = e.composedPath(); }, this.onDocumentClick = (e) => { if (!this.open) return; const t = e.composedPath(); !this.stayOpenOnOutsideClick && !t.includes(this) && !t.includes(this.anchorElement) && (this.open = !1); }, this.internals.role = "menu", this.addEventListener("keydown", this.handleKeydown), this.addEventListener("keydown", this.captureKeydown, { capture: !0 }), this.addEventListener("focusout", this.handleFocusout); } /** * The menu items associated with this menu. The items must be `MenuItem`s and * have both the `md-menu-item` and `md-list-item` attributes. */ get items() { return this.listController.items; } willUpdate(e) { if (e.has("open")) { if (this.open) { this.removeAttribute("aria-hidden"); return; } this.setAttribute("aria-hidden", "true"); } } update(e) { e.has("open") && (this.open ? this.setUpGlobalEventListeners() : this.cleanUpGlobalEventListeners()), e.has("positioning") && this.positioning === "popover" && // type required for Google JS conformance !this.showPopover && (this.positioning = "fixed"), super.update(e); } connectedCallback() { super.connectedCallback(), this.open && this.setUpGlobalEventListeners(); } disconnectedCallback() { super.disconnectedCallback(), this.cleanUpGlobalEventListeners(); } getBoundingClientRect() { return this.surfaceEl ? this.surfaceEl.getBoundingClientRect() : super.getBoundingClientRect(); } getClientRects() { return this.surfaceEl ? this.surfaceEl.getClientRects() : super.getClientRects(); } render() { return this.renderSurface(); } /** * Renders the positionable surface element and its contents. */ renderSurface() { return z`
`; } /** * Renders the menu items' slot */ renderMenuItems() { return z`