import { jsx as C } from "react/jsx-runtime"; import S from "react"; import { o as P } from "./create-component-CVXl33PD.mjs"; import { _ as o, n as u, r as $, x as O, c as L, E as h, a as N, b as z } from "./class-map-CwiboTfb.mjs"; import "./divider-Diu_1O5h.mjs"; import { E as b, r as g, a as l } from "./animation-DjClVFum.mjs"; import { m as H } from "./delegate-BXi1gVeU.mjs"; import { r as _ } from "./redispatch-event-taWUbWUt.mjs"; /** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ const M = { dialog: [ [ // Dialog slide down [{ transform: "translateY(-50px)" }, { transform: "translateY(0)" }], { duration: 500, easing: b.EMPHASIZED } ] ], scrim: [ [ // Scrim fade in [{ opacity: 0 }, { opacity: 0.32 }], { duration: 500, easing: "linear" } ] ], container: [ [ // Container fade in [{ opacity: 0 }, { opacity: 1 }], { duration: 50, easing: "linear", pseudoElement: "::before" } ], [ // Container grow // Note: current spec says to grow from 0dp->100% and shrink from // 100%->35%. We change this to 35%->100% to simplify the animation that // is supposed to clip content as it grows. From 0dp it's possible to see // text/actions appear before the container has fully grown. [{ height: "35%" }, { height: "100%" }], { duration: 500, easing: b.EMPHASIZED, pseudoElement: "::before" } ] ], headline: [ [ // Headline fade in [{ opacity: 0 }, { opacity: 0, offset: 0.2 }, { opacity: 1 }], { duration: 250, easing: "linear", fill: "forwards" } ] ], content: [ [ // Content fade in [{ opacity: 0 }, { opacity: 0, offset: 0.2 }, { opacity: 1 }], { duration: 250, easing: "linear", fill: "forwards" } ] ], actions: [ [ // Actions fade in [{ opacity: 0 }, { opacity: 0, offset: 0.5 }, { opacity: 1 }], { duration: 300, easing: "linear", fill: "forwards" } ] ] }, V = { dialog: [ [ // Dialog slide up [{ transform: "translateY(0)" }, { transform: "translateY(-50px)" }], { duration: 150, easing: b.EMPHASIZED_ACCELERATE } ] ], scrim: [ [ // Scrim fade out [{ opacity: 0.32 }, { opacity: 0 }], { duration: 150, easing: "linear" } ] ], container: [ [ // Container shrink [{ height: "100%" }, { height: "35%" }], { duration: 150, easing: b.EMPHASIZED_ACCELERATE, pseudoElement: "::before" } ], [ // Container fade out [{ opacity: "1" }, { opacity: "0" }], { delay: 100, duration: 50, easing: "linear", pseudoElement: "::before" } ] ], headline: [ [ // Headline fade out [{ opacity: 1 }, { opacity: 0 }], { duration: 100, easing: "linear", fill: "forwards" } ] ], content: [ [ // Content fade out [{ opacity: 1 }, { opacity: 0 }], { duration: 100, easing: "linear", fill: "forwards" } ] ], actions: [ [ // Actions fade out [{ opacity: 1 }, { opacity: 0 }], { duration: 100, easing: "linear", fill: "forwards" } ] ] }; /** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ const W = H($); let s = class extends W { // We do not use `delegatesFocus: true` due to a Chromium bug with // selecting text. // See https://bugs.chromium.org/p/chromium/issues/detail?id=950357 /** * Opens the dialog when set to `true` and closes it when set to `false`. */ get open() { return this.isOpen; } set open(e) { e !== this.isOpen && (this.isOpen = e, e ? (this.setAttribute("open", ""), this.show()) : (this.removeAttribute("open"), this.close())); } constructor() { super(), this.quick = !1, this.returnValue = "", this.noFocusTrap = !1, this.getOpenAnimation = () => M, this.getCloseAnimation = () => V, this.isOpen = !1, this.isOpening = !1, this.isConnectedPromise = this.getIsConnectedPromise(), this.isAtScrollTop = !1, this.isAtScrollBottom = !1, this.nextClickIsFromContent = !1, this.hasHeadline = !1, this.hasActions = !1, this.hasIcon = !1, this.escapePressedWithoutCancel = !1, this.treewalker = document.createTreeWalker(this, NodeFilter.SHOW_ELEMENT), this.addEventListener("submit", this.handleSubmit); } /** * Opens the dialog and fires a cancelable `open` event. After a dialog's * animation, an `opened` event is fired. * * Add an `autofocus` attribute to a child of the dialog that should * receive focus after opening. * * @return A Promise that resolves after the animation is finished and the * `opened` event was fired. */ async show() { var i; this.isOpening = !0, await this.isConnectedPromise, await this.updateComplete; const e = this.dialog; if (e.open || !this.isOpening) { this.isOpening = !1; return; } if (!this.dispatchEvent(new Event("open", { cancelable: !0 }))) { this.open = !1, this.isOpening = !1; return; } e.showModal(), this.open = !0, this.scroller && (this.scroller.scrollTop = 0), (i = this.querySelector("[autofocus]")) == null || i.focus(), await this.animateDialog(this.getOpenAnimation()), this.dispatchEvent(new Event("opened")), this.isOpening = !1; } /** * Closes the dialog and fires a cancelable `close` event. After a dialog's * animation, a `closed` event is fired. * * @param returnValue A return value usually indicating which button was used * to close a dialog. If a dialog is canceled by clicking the scrim or * pressing Escape, it will not change the return value after closing. * @return A Promise that resolves after the animation is finished and the * `closed` event was fired. */ async close(e = this.returnValue) { if (this.isOpening = !1, !this.isConnected) { this.open = !1; return; } await this.updateComplete; const t = this.dialog; if (!t.open || this.isOpening) { this.open = !1; return; } const i = this.returnValue; if (this.returnValue = e, !this.dispatchEvent(new Event("close", { cancelable: !0 }))) { this.returnValue = i; return; } await this.animateDialog(this.getCloseAnimation()), t.close(e), this.open = !1, this.dispatchEvent(new Event("closed")); } connectedCallback() { super.connectedCallback(), this.isConnectedPromiseResolve(); } disconnectedCallback() { super.disconnectedCallback(), this.isConnectedPromise = this.getIsConnectedPromise(); } render() { const e = this.open && !(this.isAtScrollTop && this.isAtScrollBottom), t = { "has-headline": this.hasHeadline, "has-actions": this.hasActions, "has-icon": this.hasIcon, scrollable: e, "show-top-divider": e && !this.isAtScrollTop, "show-bottom-divider": e && !this.isAtScrollBottom }, i = this.open && !this.noFocusTrap, a = O`
`, { ariaLabel: r } = this; return O` `; } firstUpdated() { this.intersectionObserver = new IntersectionObserver((e) => { for (const t of e) this.handleAnchorIntersection(t); }, { root: this.scroller }), this.intersectionObserver.observe(this.topAnchor), this.intersectionObserver.observe(this.bottomAnchor); } handleDialogClick() { if (this.nextClickIsFromContent) { this.nextClickIsFromContent = !1; return; } this.dispatchEvent(new Event("cancel", { cancelable: !0 })) && this.close(); } handleContentClick() { this.nextClickIsFromContent = !0; } handleSubmit(e) { const t = e.target, { submitter: i } = e; t.method !== "dialog" || !i || this.close(i.getAttribute("value") ?? this.returnValue); } handleCancel(e) { if (e.target !== this.dialog) return; this.escapePressedWithoutCancel = !1; const t = !_(this, e); e.preventDefault(), !t && this.close(); } handleClose() { var e; this.escapePressedWithoutCancel && (this.escapePressedWithoutCancel = !1, (e = this.dialog) == null || e.dispatchEvent(new Event("cancel", { cancelable: !0 }))); } handleKeydown(e) { e.key === "Escape" && (this.escapePressedWithoutCancel = !0, setTimeout(() => { this.escapePressedWithoutCancel = !1; })); } async animateDialog(e) { var k; if ((k = this.cancelAnimations) == null || k.abort(), this.cancelAnimations = new AbortController(), this.quick) return; const { dialog: t, scrim: i, container: a, headline: r, content: d, actions: c } = this; if (!t || !i || !a || !r || !d || !c) return; const { container: p, dialog: f, scrim: v, headline: m, content: w, actions: A } = e, E = [ [t, f ?? []], [i, v ?? []], [a, p ?? []], [r, m ?? []], [d, w ?? []], [c, A ?? []] ], y = []; for (const [F, I] of E) for (const D of I) { const T = F.animate(...D); this.cancelAnimations.signal.addEventListener("abort", () => { T.cancel(); }), y.push(T); } await Promise.all(y.map((F) => F.finished.catch(() => { }))); } handleHeadlineChange(e) { const t = e.target; this.hasHeadline = t.assignedElements().length > 0; } handleActionsChange(e) { const t = e.target; this.hasActions = t.assignedElements().length > 0; } handleIconChange(e) { const t = e.target; this.hasIcon = t.assignedElements().length > 0; } handleAnchorIntersection(e) { const { target: t, isIntersecting: i } = e; t === this.topAnchor && (this.isAtScrollTop = i), t === this.bottomAnchor && (this.isAtScrollBottom = i); } getIsConnectedPromise() { return new Promise((e) => { this.isConnectedPromiseResolve = e; }); } handleFocusTrapFocus(e) { var m; const [t, i] = this.getFirstAndLastFocusableChildren(); if (!t || !i) { (m = this.dialog) == null || m.focus(); return; } const a = e.target === this.firstFocusTrap, r = !a, d = e.relatedTarget === t, c = e.relatedTarget === i, p = !d && !c; if (r && c || a && p) { t.focus(); return; } if (a && d || r && p) { i.focus(); return; } } getFirstAndLastFocusableChildren() { if (!this.treewalker) return [null, null]; let e = null, t = null; for (this.treewalker.currentNode = this.treewalker.root; this.treewalker.nextNode(); ) { const i = this.treewalker.currentNode; B(i) && (e || (e = i), t = i); } return [e, t]; } }; o([ u({ type: Boolean }) ], s.prototype, "open", null); o([ u({ type: Boolean }) ], s.prototype, "quick", void 0); o([ u({ attribute: !1 }) ], s.prototype, "returnValue", void 0); o([ u() ], s.prototype, "type", void 0); o([ u({ type: Boolean, attribute: "no-focus-trap" }) ], s.prototype, "noFocusTrap", void 0); o([ l("dialog") ], s.prototype, "dialog", void 0); o([ l(".scrim") ], s.prototype, "scrim", void 0); o([ l(".container") ], s.prototype, "container", void 0); o([ l(".headline") ], s.prototype, "headline", void 0); o([ l(".content") ], s.prototype, "content", void 0); o([ l(".actions") ], s.prototype, "actions", void 0); o([ g() ], s.prototype, "isAtScrollTop", void 0); o([ g() ], s.prototype, "isAtScrollBottom", void 0); o([ l(".scroller") ], s.prototype, "scroller", void 0); o([ l(".top.anchor") ], s.prototype, "topAnchor", void 0); o([ l(".bottom.anchor") ], s.prototype, "bottomAnchor", void 0); o([ l(".focus-trap") ], s.prototype, "firstFocusTrap", void 0); o([ g() ], s.prototype, "hasHeadline", void 0); o([ g() ], s.prototype, "hasActions", void 0); o([ g() ], s.prototype, "hasIcon", void 0); function B(n) { var r; const e = ":is(button,input,select,textarea,object,:is(a,area)[href],[tabindex],[contenteditable=true])", t = ":not(:disabled,[disabled])"; return n.matches(e + t + ':not([tabindex^="-"])') ? !0 : !n.localName.includes("-") || !n.matches(t) ? !1 : ((r = n.shadowRoot) == null ? void 0 : r.delegatesFocus) ?? !1; } /** * @license * Copyright 2024 Google LLC * SPDX-License-Identifier: Apache-2.0 */ const R = N`:host{border-start-start-radius:var(--md-dialog-container-shape-start-start, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));border-start-end-radius:var(--md-dialog-container-shape-start-end, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));border-end-end-radius:var(--md-dialog-container-shape-end-end, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));border-end-start-radius:var(--md-dialog-container-shape-end-start, var(--md-dialog-container-shape, var(--md-sys-shape-corner-extra-large, 28px)));display:contents;margin:auto;max-height:min(560px,100% - 48px);max-width:min(560px,100% - 48px);min-height:140px;min-width:280px;position:fixed;height:fit-content;width:fit-content}dialog{background:rgba(0,0,0,0);border:none;border-radius:inherit;flex-direction:column;height:inherit;margin:inherit;max-height:inherit;max-width:inherit;min-height:inherit;min-width:inherit;outline:none;overflow:visible;padding:0;width:inherit}dialog[open]{display:flex}::backdrop{background:none}.scrim{background:var(--md-sys-color-scrim, #000);display:none;inset:0;opacity:32%;pointer-events:none;position:fixed;z-index:1}:host([open]) .scrim{display:flex}h2{all:unset;align-self:stretch}.headline{align-items:center;color:var(--md-dialog-headline-color, var(--md-sys-color-on-surface, #1d1b20));display:flex;flex-direction:column;font-family:var(--md-dialog-headline-font, var(--md-sys-typescale-headline-small-font, var(--md-ref-typeface-brand, Roboto)));font-size:var(--md-dialog-headline-size, var(--md-sys-typescale-headline-small-size, 1.5rem));line-height:var(--md-dialog-headline-line-height, var(--md-sys-typescale-headline-small-line-height, 2rem));font-weight:var(--md-dialog-headline-weight, var(--md-sys-typescale-headline-small-weight, var(--md-ref-typeface-weight-regular, 400)));position:relative}slot[name=headline]::slotted(*){align-items:center;align-self:stretch;box-sizing:border-box;display:flex;gap:8px;padding:24px 24px 0}.icon{display:flex}slot[name=icon]::slotted(*){color:var(--md-dialog-icon-color, var(--md-sys-color-secondary, #625b71));fill:currentColor;font-size:var(--md-dialog-icon-size, 24px);margin-top:24px;height:var(--md-dialog-icon-size, 24px);width:var(--md-dialog-icon-size, 24px)}.has-icon slot[name=headline]::slotted(*){justify-content:center;padding-top:16px}.scrollable slot[name=headline]::slotted(*){padding-bottom:16px}.scrollable.has-headline slot[name=content]::slotted(*){padding-top:8px}.container{border-radius:inherit;display:flex;flex-direction:column;flex-grow:1;overflow:hidden;position:relative;transform-origin:top}.container::before{background:var(--md-dialog-container-color, var(--md-sys-color-surface-container-high, #ece6f0));border-radius:inherit;content:"";inset:0;position:absolute}.scroller{display:flex;flex:1;flex-direction:column;overflow:hidden;z-index:1}.scrollable .scroller{overflow-y:scroll}.content{color:var(--md-dialog-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));font-family:var(--md-dialog-supporting-text-font, var(--md-sys-typescale-body-medium-font, var(--md-ref-typeface-plain, Roboto)));font-size:var(--md-dialog-supporting-text-size, var(--md-sys-typescale-body-medium-size, 0.875rem));line-height:var(--md-dialog-supporting-text-line-height, var(--md-sys-typescale-body-medium-line-height, 1.25rem));flex:1;font-weight:var(--md-dialog-supporting-text-weight, var(--md-sys-typescale-body-medium-weight, var(--md-ref-typeface-weight-regular, 400)));height:min-content;position:relative}slot[name=content]::slotted(*){box-sizing:border-box;padding:24px}.anchor{position:absolute}.top.anchor{top:0}.bottom.anchor{bottom:0}.actions{position:relative}slot[name=actions]::slotted(*){box-sizing:border-box;display:flex;gap:8px;justify-content:flex-end;padding:16px 24px 24px}.has-actions slot[name=content]::slotted(*){padding-bottom:8px}md-divider{display:none;position:absolute}.has-headline.show-top-divider .headline md-divider,.has-actions.show-bottom-divider .actions md-divider{display:flex}.headline md-divider{bottom:0}.actions md-divider{top:0}@media(forced-colors: active){dialog{outline:2px solid WindowText}} `; /** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ let x = class extends s { }; x.styles = [R]; x = o([ z("md-dialog") ], x); const q = P({ react: S, tagName: "md-dialog", elementClass: x, events: { onClose: "close", onShow: "show", onOpen: "open", onOpened: "opened", onClosed: "closed", onCancel: "cancel" } }), te = (n) => { const { children: e, quick: t, returnValue: i, noFocusTrap: a, open: r, fullScreen: d, style: c, className: p, id: f, onClose: v, onShow: m, onOpen: w, onOpened: A, onClosed: E, onCancel: y } = n; return /* @__PURE__ */ C( q, { quick: t, returnValue: i, noFocusTrap: a, open: r, style: { ...c, ...d ? { width: "100vw", height: "100vh", maxWidth: "100vw", maxHeight: "100vh" } : {} }, className: p, id: f, onClose: v, onShow: m, onOpen: w, onOpened: A, onClosed: E, onCancel: y, children: e } ); }, ie = (n) => /* @__PURE__ */ C("div", { slot: "headline", ...n, children: n.children }), oe = (n) => /* @__PURE__ */ C("div", { slot: "content", ...n, children: n.children }), se = (n) => /* @__PURE__ */ C("div", { slot: "actions", ...n, children: n.children }); export { te as Dialog, se as DialogActions, oe as DialogContent, ie as DialogTitle };