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
JavaScript
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