UNPKG

wj-elements

Version:

WebJET Elements is a modern set of user interface tools harnessing the power of web components designed to simplify web application development.

714 lines (713 loc) 28.2 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import WJElement from "./wje-element.js"; import { WjElementUtils } from "./element-utils.js"; import { event } from "./event.js"; const styles = "/*\n[ WJ Toast ]\n*/\n\n:host {\n --wje-toast-stack-z: 9999;\n --wje-toast-stack-host-margin-top: 0.5rem;\n --wje-toast-stack-host-margin-bottom: 0.5rem;\n --wje-toast-stack-layout-duration: 0.2s;\n --wje-toast-stack-visual-duration: 0.2s;\n --wje-toast-stack-opacity: 1;\n --wje-toast-stack-shift: 0px;\n --wje-toast-enter-offset: 0px;\n --wje-toast-stack-scale: 1;\n --wje-toast-stack-origin: center top;\n position: relative;\n z-index: var(--wje-toast-stack-z);\n width: 300px;\n max-width: min(100%, calc(100vw - 1rem));\n margin: var(--wje-toast-stack-host-margin-top) 0 var(--wje-toast-stack-host-margin-bottom);\n display: none;\n transition:\n margin-top var(--wje-toast-stack-layout-duration) ease,\n margin-bottom var(--wje-toast-stack-layout-duration) ease;\n}\n\n:host([open]) {\n display: block;\n}\n\n.native-toast {\n display: flex;\n align-items: center;\n padding: 1rem;\n overflow: hidden;\n margin: 0;\n border-width: 1px;\n border-style: solid;\n border-radius: var(--wje-border-radius-large);\n position: relative;\n opacity: var(--wje-toast-stack-opacity);\n transform: translateY(calc(var(--wje-toast-stack-shift) + var(--wje-toast-enter-offset))) scale(var(--wje-toast-stack-scale));\n transform-origin: var(--wje-toast-stack-origin);\n transition:\n transform var(--wje-toast-stack-visual-duration) ease,\n opacity var(--wje-toast-stack-visual-duration) ease;\n\n &.has-media slot[name='media'] {\n flex: 0 0 1.5rem;\n width: 1.5rem;\n display: flex;\n margin-right: 0.5rem;\n justify-content: center;\n }\n\n .content {\n font-size: var(--wje-font-size-small);\n .headline {\n font-size: var(--wje-font-size);\n font-weight: var(--wje-font-weight-bold);\n }\n }\n\n wje-button {\n --wje-button-margin-inline: auto 0;\n margin-left: auto !important;\n }\n\n .countdown {\n position: absolute;\n left: 0;\n bottom: 0;\n width: 100%;\n height: 4px;\n .countdown-bar {\n height: 100%;\n }\n }\n}\n\n:host([position='top']) {\n animation: slideDown 0.3s ease-out forwards;\n top: 1rem;\n left: auto;\n right: auto;\n}\n\n:host::part(icon) {\n margin-right: 0.5rem;\n}\n\n@keyframes slideDown {\n 0% {\n transform: translateY(-100%);\n }\n 100% {\n transform: translateY(0);\n }\n}\n\n/*PRIMARY*/\n:host([color='primary']) .native-toast {\n background-color: var(--wje-color-primary-1);\n color: var(--wje-color-primary-9);\n border-color: var(--wje-color-primary-3);\n}\n\n/*COMPLETE*/\n:host([color='complete']) .native-toast {\n background-color: var(--wje-color-complete-1);\n color: var(--wje-color-complete-9);\n border-color: var(--wje-color-complete-3);\n}\n\n/*SUCCESS*/\n:host([color='success']) .native-toast {\n background-color: var(--wje-color-success-1);\n color: var(--wje-color-success-9);\n border-color: var(--wje-color-success-3);\n}\n\n/*WARNING*/\n:host([color='warning']) .native-toast {\n background-color: var(--wje-color-warning-1);\n color: var(--wje-color-warning-11);\n border-color: var(--wje-color-warning-3);\n}\n\n/*DANGER*/\n:host([color='danger']) .native-toast {\n background-color: var(--wje-color-danger-1);\n color: var(--wje-color-danger-9);\n border-color: var(--wje-color-danger-3);\n}\n\n/*INFO*/\n:host([color='info']) .native-toast {\n background-color: var(--wje-color-info-1);\n color: var(--wje-color-info-11);\n border-color: var(--wje-color-info-4);\n}\n\n/*CONTRAST*/\n:host([color='contrast']) .native-toast {\n background-color: var(--wje-color-contrast-2);\n color: var(--wje-color-contrast-9);\n border-color: var(--wje-color-contrast-3);\n}\n\n/*PRIMARY*/\n:host([color='primary']) .countdown-bar {\n background-color: var(--wje-color-primary-9);\n}\n\n/*COMPLETE*/\n:host([color='complete']) .countdown-bar {\n background-color: var(--wje-color-complete-9);\n}\n\n/*SUCCESS*/\n:host([color='success']) .countdown-bar {\n background-color: var(--wje-color-success-9);\n}\n\n/*WARNING*/\n:host([color='warning']) .countdown-bar {\n background-color: var(--wje-color-warning-9);\n}\n\n/*DANGER*/\n:host([color='danger']) .countdown-bar {\n background-color: var(--wje-color-danger-9);\n}\n\n/*INFO*/\n:host([color='info']) .countdown-bar {\n background-color: var(--wje-color-info-9);\n}\n\n/*CONTRAST*/\n:host([color='contrast']) .countdown-bar {\n background-color: var(--wje-color-contrast-9);\n}\n"; const DEFAULT_STACK_POSITION = "top-end"; const DEFAULT_STACK_DEPTH = 3; const VALID_STACK_POSITIONS = /* @__PURE__ */ new Set([ "top-start", "top-center", "top-end", "bottom-start", "bottom-center", "bottom-end" ]); const STACKED_SCALE_STEP = 0.04; const STACKED_MIN_SCALE = 0.88; const STACKED_MIN_OPACITY = 0.72; const STACKED_VISIBLE_SLICE = 16; const STACKED_EXPANDED_MARGIN = "0.5rem"; const STACKED_PADDING = "1rem"; const STACKED_ENTER_OFFSET = 24; const toggleStackExpanded = (stack, expanded) => { if (expanded) { stack.dataset.expanded = "true"; return; } delete stack.dataset.expanded; }; const syncExpandedStackToasts = (stack, expanded) => { Array.from(stack.children).filter((child) => child.tagName === "WJE-TOAST").forEach((toast) => { var _a, _b; if (expanded) { (_a = toast.pause) == null ? void 0 : _a.call(toast); return; } (_b = toast.resume) == null ? void 0 : _b.call(toast); }); }; const setStackExpandedState = (stack, expanded) => { var _a; let shouldExpand = stack.dataset.stacked === "true" && expanded; let isExpanded = stack.dataset.expanded === "true"; if (shouldExpand === isExpanded) { return; } toggleStackExpanded(stack, shouldExpand); syncExpandedStackToasts(stack, shouldExpand); (_a = stack.updateToastLayout) == null ? void 0 : _a.call(stack); }; const syncStackExpandedState = (stack) => { setStackExpandedState(stack, stack.matches(":hover") || stack.matches(":focus-within")); }; class Toast extends WJElement { /** * Creates an instance of Toast. */ constructor() { super(); /** * The class name for the component. * @type {string} */ __publicField(this, "className", "Toast"); /** * Asynchronously shows the toast notification. * This method sets the `open` property to `true` and dispatches the * `wje-toast:after-show` custom event. If the toast is already open, * the method returns `undefined`. */ __publicField(this, "show", () => { if (this.open) { return; } this.open = true; event.dispatchCustomEvent(this, "wje-toast:after-show"); }); /** * Asynchronously hides the toast notification. * This method sets the `open` property to `false` and dispatches the * `wje-toast:after-hide` custom event. If the toast is already hidden, * the method returns `undefined`. */ __publicField(this, "hide", () => { if (!this.open) { return; } this.open = false; event.dispatchCustomEvent(this, "wje-toast:after-hide"); }); /** * Pauses the countdown animation and stops the timer. */ __publicField(this, "pause", () => { var _a; (_a = this.countdownAnimation) == null ? void 0 : _a.pause(); this.stopTimer(); }); /** * Resumes the countdown animation and resumes the timer. */ __publicField(this, "resume", () => { var _a, _b; if (((_a = this.toastStack) == null ? void 0 : _a.dataset.expanded) === "true") { return; } (_b = this.countdownAnimation) == null ? void 0 : _b.play(); this.resumeTimer(); }); /** * Asynchronously starts the toast notification. * This method appends the toast notification to the document body and * shows the toast notification. The method returns a promise that * resolves when the toast notification is shown. * @returns {Promise<unknown>} */ __publicField(this, "start", () => { return new Promise((resolve) => { var _a; let stack = document.body.querySelector(`.wje-toast-stack[data-stack-key="${this.getToastStackKey()}"]`); if (stack) { this.toastStack = stack; } else { this.toastStack = this.createToastStack(); } this.syncToastStack(this.toastStack); if (this.toastStack.parentElement === null) { document.body.append(this.toastStack); } this.toastStack.append(this); if (this.stacked) { this.toastStack.style.setProperty("--wje-toast-stack-layout-duration", "0s"); this.toastStack.style.setProperty("--wje-toast-stack-visual-duration", "0s"); this.style.setProperty( "--wje-toast-enter-offset", this.stackPosition.startsWith("bottom") ? `${STACKED_ENTER_OFFSET}px` : `-${STACKED_ENTER_OFFSET}px` ); this.style.visibility = "hidden"; this.show(); this.updateToastStack(this.toastStack); } else { this.updateToastStack(this.toastStack); this.show(); } if (this.toastStack.dataset.expanded === "true") { this.pause(); } requestAnimationFrame(() => { this.updateToastStack(this.toastStack); if (this.stacked) { this.style.removeProperty("visibility"); this.toastStack.style.removeProperty("--wje-toast-stack-layout-duration"); this.toastStack.style.removeProperty("--wje-toast-stack-visual-duration"); requestAnimationFrame(() => this.style.setProperty("--wje-toast-enter-offset", "0px")); } }); (_a = this.updateComplete) == null ? void 0 : _a.then(() => this.updateToastStack(this.toastStack)); this.addEventListener("wje-toast:after-hide", this.removeChildAndStack); resolve(this); }); }); this.toastStack = this.createToastStack(); } /** * Set headline value of the toast. * @param value */ set headline(value) { this.setAttribute("headline", value); } /** * Get headline value of the toast. * @returns {string} */ get headline() { return this.getAttribute("headline"); } /** * Set open value of the toast. * @param value */ set open(value) { this.removeAttribute("open"); if (WjElementUtils.stringToBoolean(value)) this.setAttribute("open", value); } /** * Get open value of the toast. * @returns {boolean} */ get open() { return this.hasAttribute("open"); } /** * Set duration value of the toast. * @param value */ set duration(value) { this.setAttribute("duration", value); } /** * Get duration value of the toast. * @returns {number} */ get duration() { return +this.getAttribute("duration"); } /** * Set closable value of the toast. * @param value */ set closable(value) { this.setAttribute("closable", value || ""); } /** * Get closable value of the toast. * @returns {boolean} */ get closable() { return this.hasAttribute("closable"); } /** * Set color value of the toast. * @param value */ set color(value) { this.setAttribute("color", value); } /** * Get color value of the toast. * @returns {string} */ get color() { return this.getAttribute("color"); } /** * Set countdown value of the toast. * @param value */ set countdown(value) { if (value) this.setAttribute("countdown", value); } /** * Get countdown value of the toast. * @returns {boolean} */ get countdown() { return this.hasAttribute("countdown"); } /** * Set stacked value of the toast. * @param value */ set stacked(value) { this.toggleAttribute("stacked", WjElementUtils.stringToBoolean(value)); } /** * Get stacked value of the toast. * @returns {boolean} */ get stacked() { return this.hasAttribute("stacked"); } /** * Set stack depth of the toast. * @param value */ set stackDepth(value) { if (value === null || value === void 0 || value === "") { this.removeAttribute("stack-depth"); return; } this.setAttribute("stack-depth", value); } /** * Get stack depth of the toast. * @returns {number} */ get stackDepth() { let value = Number.parseInt(this.getAttribute("stack-depth"), 10); if (Number.isFinite(value) && value > 0) { return value; } return DEFAULT_STACK_DEPTH; } /** * Set stack position of the toast. * @param value */ set stackPosition(value) { if (!value) { this.removeAttribute("stack-position"); return; } this.setAttribute("stack-position", value); } /** * Get stack position of the toast. * @returns {string} */ get stackPosition() { let value = this.getAttribute("stack-position"); if (VALID_STACK_POSITIONS.has(value)) { return value; } if (this.getAttribute("position") === "bottom") { return "bottom-end"; } return DEFAULT_STACK_POSITION; } /** * Set icon value of the toast. * @param value */ set icon(value) { this.setAttribute("icon", value); } /** * Get icon value of the toast. * @returns {string} */ get icon() { return this.getAttribute("icon"); } /** * Creates a toast stack container. * @returns {HTMLDivElement} */ createToastStack() { let stack = Object.assign(document.createElement("div"), { className: "wje-toast-stack" }); stack.addEventListener("mouseenter", () => setStackExpandedState(stack, true)); stack.addEventListener("mouseleave", () => requestAnimationFrame(() => syncStackExpandedState(stack))); stack.addEventListener("focusin", () => setStackExpandedState(stack, true)); stack.addEventListener("focusout", () => requestAnimationFrame(() => syncStackExpandedState(stack))); this.syncToastStack(stack); return stack; } /** * Returns the key of the toast stack. * @returns {string} */ getToastStackKey() { return `${this.stackPosition}:${this.stacked ? `stacked:${this.stackDepth}` : "default"}`; } /** * Applies the stack placement directly on the element so demo/app layout CSS cannot override it accidentally. * @param {HTMLDivElement} stack */ applyToastStackPlacement(stack = this.toastStack) { const positions = { "top-start": { top: "0", bottom: "auto", left: "0", right: "auto", transform: "none", margin: "0.5rem" }, "top-center": { top: "0", bottom: "auto", left: "50%", right: "auto", transform: "translateX(-50%)", margin: "0.5rem 0 0" }, "top-end": { top: "0", bottom: "auto", left: "auto", right: "0", transform: "none", margin: "0.5rem" }, "bottom-start": { top: "auto", bottom: "0", left: "0", right: "auto", transform: "none", margin: "0 0.5rem 0.5rem" }, "bottom-center": { top: "auto", bottom: "0", left: "50%", right: "auto", transform: "translateX(-50%)", margin: "0 0 0.5rem" }, "bottom-end": { top: "auto", bottom: "0", left: "auto", right: "0", transform: "none", margin: "0 0.5rem 0.5rem" } }; stack.style.removeProperty("inset-inline"); stack.style.removeProperty("inset-inline-start"); stack.style.removeProperty("inset-inline-end"); Object.assign(stack.style, positions[this.stackPosition] || positions[DEFAULT_STACK_POSITION]); } /** * Applies the current toast stack configuration to a stack element. * @param {HTMLDivElement} stack */ syncToastStack(stack = this.toastStack) { stack.dataset.position = this.stackPosition; stack.dataset.stackKey = this.getToastStackKey(); stack.updateToastLayout = () => this.updateToastStack(stack); stack.style.display = "flex"; stack.style.alignItems = "stretch"; stack.style.width = "min(var(--wje-toast-stack-width, 300px), calc(100vw - 1rem))"; stack.style.maxWidth = "calc(100vw - 1rem)"; stack.style.maxHeight = "calc(100vh - 1rem)"; stack.style.zIndex = "9999"; this.applyToastStackPlacement(stack); if (this.stacked) { stack.dataset.stacked = "true"; stack.dataset.stackDepth = String(this.stackDepth); } else { delete stack.dataset.stacked; delete stack.dataset.stackDepth; delete stack.dataset.expanded; } } /** * Clears transient stack styling from a toast. * @param {Toast} toast */ clearStackItemStyles(toast) { [ "--wje-toast-stack-scale", "--wje-toast-stack-shift", "--wje-toast-stack-opacity", "--wje-toast-stack-z", "--wje-toast-stack-origin", "--wje-toast-stack-host-margin-top", "--wje-toast-stack-host-margin-bottom", "order", "position", "top", "left", "right", "width", "margin", "margin-top", "margin-bottom" ].forEach((property) => toast.style.removeProperty(property)); } /** * Measures the rendered height of a toast for stack overlap calculations. * @param {Toast} toast * @returns {number} */ getToastVisualHeight(toast) { var _a, _b; let hostHeight = toast.getBoundingClientRect().height; let nativeHeight = ((_b = (_a = toast.shadowRoot) == null ? void 0 : _a.querySelector(".native-toast")) == null ? void 0 : _b.getBoundingClientRect().height) || 0; return Math.max(hostHeight, nativeHeight, toast.offsetHeight || 0); } /** * Recomputes the visual order of toasts inside the stack. * @param {HTMLDivElement} stack */ updateToastStack(stack = this.toastStack) { var _a, _b; let toasts = Array.from(stack.children).filter((child) => child.tagName === "WJE-TOAST"); let isStacked = stack.dataset.stacked === "true"; let isExpanded = stack.dataset.expanded === "true"; let isBottomStack = (_a = stack.dataset.position) == null ? void 0 : _a.startsWith("bottom"); let transformOrigin = ((_b = stack.dataset.position) == null ? void 0 : _b.startsWith("bottom")) ? "center bottom" : "center top"; let stackHeight = 0; stack.dataset.count = String(toasts.length); stack.style.gap = "var(--wje-spacing-x-small)"; stack.style.flexDirection = "column"; stack.style.overflow = isStacked ? isExpanded ? "auto" : "visible" : "auto"; if (isStacked) { stack.style.paddingTop = isExpanded ? isBottomStack ? STACKED_PADDING : "0px" : STACKED_PADDING; stack.style.paddingBottom = isExpanded ? isBottomStack ? "0px" : STACKED_PADDING : STACKED_PADDING; } else { stack.style.removeProperty("padding-top"); stack.style.removeProperty("padding-bottom"); } if (!isStacked || isExpanded) { stack.style.removeProperty("height"); } toasts.forEach((toast, index) => { this.clearStackItemStyles(toast); toast.style.setProperty("--wje-toast-stack-z", String(index + 1)); if (!isStacked) { return; } if (isExpanded) { let visualOrder = isBottomStack ? index : toasts.length - index - 1; let isVisualFirst = visualOrder === 0; let isVisualLast = visualOrder === toasts.length - 1; toast.style.setProperty("--wje-toast-stack-scale", "1.000"); toast.style.setProperty("--wje-toast-stack-shift", "0px"); toast.style.setProperty("--wje-toast-stack-opacity", "1.000"); toast.style.setProperty("--wje-toast-stack-origin", transformOrigin); toast.style.order = String(visualOrder); toast.style.width = "100%"; toast.style.setProperty( "--wje-toast-stack-host-margin-top", isBottomStack && !isVisualFirst ? STACKED_EXPANDED_MARGIN : "0px" ); toast.style.setProperty( "--wje-toast-stack-host-margin-bottom", !isBottomStack && !isVisualLast ? STACKED_EXPANDED_MARGIN : "0px" ); return; } let toastHeight = this.getToastVisualHeight(toast); let maxDepth = Math.max(0, this.stackDepth - 1); let visibleLevels = Math.min(toasts.length, this.stackDepth); let depth = Math.min(toasts.length - index - 1, maxDepth); let visibleIndex = Math.max(0, index - Math.max(0, toasts.length - this.stackDepth)); let targetTop = isBottomStack ? visibleIndex * STACKED_VISIBLE_SLICE : (visibleLevels - 1 - visibleIndex) * STACKED_VISIBLE_SLICE; let scale = Math.max(STACKED_MIN_SCALE, 1 - depth * STACKED_SCALE_STEP); let opacity = Math.max(STACKED_MIN_OPACITY, 1 - depth * 0.08); toast.style.setProperty("--wje-toast-stack-scale", scale.toFixed(3)); toast.style.setProperty("--wje-toast-stack-shift", "0px"); toast.style.setProperty("--wje-toast-stack-opacity", opacity.toFixed(3)); toast.style.setProperty("--wje-toast-stack-origin", transformOrigin); toast.style.position = "absolute"; toast.style.top = `${targetTop}px`; toast.style.left = "0"; toast.style.right = "0"; toast.style.width = "100%"; toast.style.setProperty("--wje-toast-stack-host-margin-top", "0px"); toast.style.setProperty("--wje-toast-stack-host-margin-bottom", "0px"); stackHeight = Math.max(stackHeight, targetTop + toastHeight); }); if (isStacked && !isExpanded) { stack.style.height = `${stackHeight}px`; } } /** * Returns the CSS stylesheet for the component. * @static * @returns {CSSStyleSheet} The CSS stylesheet */ static get cssStyleSheet() { return styles; } /** * Setup attributes for the Button element. */ setupAttributes() { this.isShadowRoot = "open"; this.setAriaState({ role: "status" }); } /** * Draw method for the toast notification. * @returns {object} Document fragment */ draw() { let fragment = document.createDocumentFragment(); let native = document.createElement("div"); native.setAttribute("part", "native"); native.classList.add("native-toast"); let mediaSlot = document.createElement("slot"); mediaSlot.setAttribute("name", "media"); mediaSlot.classList.add("media"); mediaSlot.addEventListener("slotchange", () => { if (WjElementUtils.hasSlotContent(this.context, "media")) { mediaSlot.parentElement.classList.add("has-media"); } else { mediaSlot.parentElement.classList.remove("has-media"); } }); let content = document.createElement("div"); content.classList.add("content"); content.innerHTML = `<div class="headline">${this.headline}</div><div class="message"><slot></slot></div>`; let iconX = document.createElement("wje-icon"); iconX.setAttribute("name", "x"); let closeBtn = document.createElement("wje-button"); closeBtn.setAttribute("fill", "link"); closeBtn.setAttribute("color", this.color); closeBtn.setAttribute("size", "small"); closeBtn.classList.add("close"); closeBtn.setAttribute("aria-label", "Close"); let countdownEl = document.createElement("div"); countdownEl.classList.add("countdown"); let countdownBar = document.createElement("div"); countdownBar.classList.add("countdown-bar"); closeBtn.appendChild(iconX); countdownEl.appendChild(countdownBar); if (this.hasAttribute("icon") && this.icon) { let icon = document.createElement("wje-icon"); icon.setAttribute("name", this.icon); icon.setAttribute("color", this.color); icon.setAttribute("slot", "media"); icon.setAttribute("part", "icon"); this.appendChild(icon); } native.appendChild(mediaSlot); native.appendChild(content); if (this.closable) native.appendChild(closeBtn); if (this.hasAttribute("countdown")) native.appendChild(countdownEl); fragment.appendChild(native); this.closeBtn = closeBtn; this.countdownBar = countdownBar; return fragment; } /** * After draw method for the toast notification. */ afterDraw() { this.closeBtn.addEventListener("wje-button:click", this.hide); this.addEventListener("mouseenter", this.pause); this.addEventListener("mouseleave", this.resume); if (this.hasAttribute("countdown")) { const startWidth = "100%"; const endWidth = "0"; this.countdownAnimation = this.countdownBar.animate([{ width: startWidth }, { width: endWidth }], { duration: this.duration, easing: "linear" }); } if (this.duration > 0) { this.remainingTime = this.duration; this.startTimer(); } } /** * Before disconnect method * This method is called before the element is disconnected from the document. */ beforeDisconnect() { var _a; (_a = this.closeBtn) == null ? void 0 : _a.removeEventListener("wje-button:click", this.hide); this.removeEventListener("wje-toast:after-hide", this.removeChildAndStack); this.removeEventListener("mouseenter", this.pause); this.removeEventListener("mouseleave", this.resume); clearTimeout(this.timeoutID); } /** * Starts the timer. * This method sets the `startTime` property to the current time and sets * the `timeoutID` property to the ID of the timeout. The method also * dispatches the `wje-toast:after-hide` custom event when the timeout * expires. */ startTimer() { this.startTime = Date.now(); if (this.timeoutID) { clearTimeout(this.timeoutID); } this.isTimerPaused = false; this.timeoutID = window.setTimeout(() => { this.hide(); }, this.remainingTime); } /** * Stops the timer. * This method clears the timeout and calculates the remaining time. * The method is called when the toast notification is paused. */ stopTimer() { if (!this.timeoutID || this.isTimerPaused) { return; } window.clearTimeout(this.timeoutID); this.timeoutID = null; const elapsedTime = Date.now() - this.startTime; this.remainingTime = Math.max(0, this.remainingTime - elapsedTime); this.isTimerPaused = true; } /** * Resumes the timer. * This method resumes the timer if the remaining time is greater * than zero. The method is called when the toast notification is resumed. */ resumeTimer() { if (this.isTimerPaused && this.remainingTime > 0) { this.startTimer(); } } /** * Removes the toast notification and the toast stack. * * This method removes the toast notification from the toast stack and * removes the toast stack from the document body if the toast stack is * empty. */ removeChildAndStack() { if (this.parentElement === this.toastStack) { this.toastStack.removeChild(this); } this.toastStack.style.setProperty("--wje-toast-stack-layout-duration", "0s"); this.toastStack.style.setProperty("--wje-toast-stack-visual-duration", "0s"); this.updateToastStack(this.toastStack); requestAnimationFrame(() => { this.toastStack.style.removeProperty("--wje-toast-stack-layout-duration"); this.toastStack.style.removeProperty("--wje-toast-stack-visual-duration"); }); if (this.toastStack.querySelector("wje-toast") === null) { this.toastStack.remove(); } } } Toast.define("wje-toast", Toast); export { Toast as default }; //# sourceMappingURL=wje-toast.js.map