@synergy-design-system/components
Version:
This package provides the base of the Synergy Design System as native web components. It uses [lit](https://www.lit.dev) and parts of [shoelace](https://shoelace.style/). Synergy officially supports the latest two versions of all major browsers (as define
299 lines (292 loc) • 8.73 kB
JavaScript
import {
blurActiveElement
} from "./chunk.WXVOTRW5.js";
import {
SynIconButton
} from "./chunk.RJPPRJP3.js";
import {
waitForEvent
} from "./chunk.C2ENQBPM.js";
import {
animateTo,
stopAnimations
} from "./chunk.G6ITZTTW.js";
import {
getAnimation,
setDefaultAnimation
} from "./chunk.7JGKUB4A.js";
import {
HasSlotController
} from "./chunk.WVVQK5TE.js";
import {
LocalizeController
} from "./chunk.OAQRCZOO.js";
import {
enableDefaultSettings
} from "./chunk.HYFCK7MM.js";
import {
watch
} from "./chunk.BVZQ6QSY.js";
import {
component_styles_default
} from "./chunk.NLYVOJGK.js";
import {
SynergyElement
} from "./chunk.3THJTCRO.js";
import {
alert_custom_styles_default
} from "./chunk.ZCUURSJU.js";
import {
alert_styles_default
} from "./chunk.BXY667C7.js";
import {
__decorateClass
} from "./chunk.Z4XV3SMG.js";
// src/components/alert/alert.component.ts
import { classMap } from "lit/directives/class-map.js";
import { html } from "lit";
import { property, query, state } from "lit/decorators.js";
var SynAlert = class extends SynergyElement {
constructor() {
super(...arguments);
this.hasSlotController = new HasSlotController(this, "icon", "suffix");
this.localize = new LocalizeController(this);
this.open = false;
this.closable = false;
this.variant = "primary";
this.duration = Infinity;
this.size = "medium";
this.remainingTime = this.duration;
}
static get toastStack() {
if (!this.currentToastStack) {
this.currentToastStack = Object.assign(document.createElement("div"), {
className: "syn-toast-stack"
});
}
return this.currentToastStack;
}
firstUpdated() {
this.base.hidden = !this.open;
}
restartAutoHide() {
this.handleCountdownChange();
clearTimeout(this.autoHideTimeout);
clearInterval(this.remainingTimeInterval);
if (this.open && this.duration < Infinity) {
this.autoHideTimeout = window.setTimeout(() => this.hide(), this.duration);
this.remainingTime = this.duration;
this.remainingTimeInterval = window.setInterval(() => {
this.remainingTime -= 100;
}, 100);
}
}
pauseAutoHide() {
var _a;
(_a = this.countdownAnimation) == null ? void 0 : _a.pause();
clearTimeout(this.autoHideTimeout);
clearInterval(this.remainingTimeInterval);
}
resumeAutoHide() {
var _a;
if (this.duration < Infinity) {
this.autoHideTimeout = window.setTimeout(() => this.hide(), this.remainingTime);
this.remainingTimeInterval = window.setInterval(() => {
this.remainingTime -= 100;
}, 100);
(_a = this.countdownAnimation) == null ? void 0 : _a.play();
}
}
handleCountdownChange() {
if (this.open && this.duration < Infinity && this.countdown) {
const { countdownElement } = this;
const start = "100%";
const end = "0";
this.countdownAnimation = countdownElement.animate([{ width: start }, { width: end }], {
duration: this.duration,
easing: "linear"
});
}
}
handleCloseClick() {
this.hide();
}
async handleOpenChange() {
if (this.open) {
this.emit("syn-show");
if (this.duration < Infinity) {
this.restartAutoHide();
}
await stopAnimations(this.base);
this.base.hidden = false;
const { keyframes, options } = getAnimation(this, "alert.show", { dir: this.localize.dir() });
await animateTo(this.base, keyframes, options);
this.emit("syn-after-show");
} else {
blurActiveElement(this);
this.emit("syn-hide");
clearTimeout(this.autoHideTimeout);
clearInterval(this.remainingTimeInterval);
await stopAnimations(this.base);
const { keyframes, options } = getAnimation(this, "alert.hide", { dir: this.localize.dir() });
await animateTo(this.base, keyframes, options);
this.base.hidden = true;
this.emit("syn-after-hide");
}
}
handleDurationChange() {
this.restartAutoHide();
}
/** Shows the alert. */
async show() {
if (this.open) {
return void 0;
}
this.open = true;
return waitForEvent(this, "syn-after-show");
}
/** Hides the alert */
async hide() {
if (!this.open) {
return void 0;
}
this.open = false;
return waitForEvent(this, "syn-after-hide");
}
/**
* Displays the alert as a toast notification. This will move the alert out of its position in the DOM and, when
* dismissed, it will be removed from the DOM completely. By storing a reference to the alert, you can reuse it by
* calling this method again. The returned promise will resolve after the alert is hidden.
*/
async toast() {
return new Promise((resolve) => {
this.handleCountdownChange();
if (SynAlert.toastStack.parentElement === null) {
document.body.append(SynAlert.toastStack);
}
SynAlert.toastStack.appendChild(this);
requestAnimationFrame(() => {
this.clientWidth;
this.show();
});
this.addEventListener(
"syn-after-hide",
() => {
SynAlert.toastStack.removeChild(this);
resolve();
if (SynAlert.toastStack.querySelector("syn-alert") === null) {
SynAlert.toastStack.remove();
}
},
{ once: true }
);
});
}
render() {
return html`
<div
part="base"
class=${classMap({
alert: true,
"alert--open": this.open,
"alert--small": this.size === "small",
"alert--medium": this.size === "medium",
"alert--large": this.size === "large",
"alert--closable": this.closable,
"alert--has-icon": this.hasSlotController.test("icon"),
"alert--primary": this.variant === "primary",
"alert--success": this.variant === "success",
"alert--neutral": this.variant === "neutral",
"alert--warning": this.variant === "warning",
"alert--danger": this.variant === "danger"
})}
role="alert"
aria-hidden=${this.open ? "false" : "true"}
=${this.pauseAutoHide}
=${this.resumeAutoHide}
>
<div part="icon" class="alert__icon">
<slot name="icon"></slot>
</div>
<div part="message" class="alert__message" aria-live="polite">
<slot></slot>
</div>
${this.closable ? html`
<syn-icon-button
part="close-button"
exportparts="base:close-button__base"
class="alert__close-button"
name="x-lg"
library="system"
label=${this.localize.term("close")}
=${this.handleCloseClick}
></syn-icon-button>
` : ""}
<div role="timer" class="alert__timer">${this.remainingTime}</div>
${this.countdown ? html`
<div
class=${classMap({
alert__countdown: true,
"alert__countdown--ltr": this.countdown === "ltr"
})}
>
<div class="alert__countdown-elapsed"></div>
</div>
` : ""}
</div>
`;
}
};
SynAlert.styles = [component_styles_default, alert_styles_default, alert_custom_styles_default];
SynAlert.dependencies = { "syn-icon-button": SynIconButton };
__decorateClass([
query('[part~="base"]')
], SynAlert.prototype, "base", 2);
__decorateClass([
query(".alert__countdown-elapsed")
], SynAlert.prototype, "countdownElement", 2);
__decorateClass([
property({ type: Boolean, reflect: true })
], SynAlert.prototype, "open", 2);
__decorateClass([
property({ type: Boolean, reflect: true })
], SynAlert.prototype, "closable", 2);
__decorateClass([
property({ reflect: true })
], SynAlert.prototype, "variant", 2);
__decorateClass([
property({ type: Number })
], SynAlert.prototype, "duration", 2);
__decorateClass([
property({ reflect: true })
], SynAlert.prototype, "size", 2);
__decorateClass([
state()
], SynAlert.prototype, "remainingTime", 2);
__decorateClass([
watch("open", { waitUntilFirstUpdate: true })
], SynAlert.prototype, "handleOpenChange", 1);
__decorateClass([
watch("duration")
], SynAlert.prototype, "handleDurationChange", 1);
SynAlert = __decorateClass([
enableDefaultSettings("SynAlert")
], SynAlert);
setDefaultAnimation("alert.show", {
keyframes: [
{ opacity: 0, scale: 0.8 },
{ opacity: 1, scale: 1 }
],
options: { duration: 250, easing: "ease" }
});
setDefaultAnimation("alert.hide", {
keyframes: [
{ opacity: 1, scale: 1 },
{ opacity: 0, scale: 0.8 }
],
options: { duration: 250, easing: "ease" }
});
export {
SynAlert
};
//# sourceMappingURL=chunk.LLOONJ33.js.map