import { html, LitElement, css, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; import { fontSize, Size, } from "@supersoniks/concorde/core/components/ui/_css/size"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; const icon = { warning: "warning-circled-outline", success: "check-circled-outline", error: "warning-circled-outline", info: "info-empty", default: "info-empty", }; export type AlertStatus = keyof typeof icon; const tagName = "sonic-alert"; /** * Affiche un message en ligne. * Soit par ses simples attributs "label" et "text", soit par son slot pour des messages plus complexes. */ @customElement(tagName) export class Alert extends LitElement { static styles = [ fontSize, css` :host { --sc_color: var(--sc-base-content, #000); --sc_rounded: var(--sc-rounded); --sc_fw: var(--sc-font-weight-base, 400); --sc_fst: var(--sc-font-style-base, normal); --sc_label-fw: bold; font-weight: var(--sc_fw); font-style: var(--sc_fst); color: var(--sc_color); position: relative; display: flex; gap: 0.4em; border-radius: var(--sc_rounded); } .label { font-weight: var(--sc_label-fw); margin-bottom: 0.15em; display: block; } :host([status="warning"]) { --sc_color: var(--sc-warning, var(--sc-base-content, #000)); } :host([status="error"]) { --sc_color: var(--sc-danger, var(--sc-base-content, #000)); } :host([status="info"]) { --sc_color: var(--sc-info, var(--sc-base-content, #000)); } :host([status="success"]) { --sc_color: var(--sc-success, var(--sc-base-content, #000)); } /*background*/ :host([dismissible]), :host([background]) { background: var(--sc-base, #fff); padding: 0.8em 1.15em; } :host([dismissible]):before, :host([background]):before { background-color: currentColor; content: ""; display: block; position: absolute; left: 0; top: 0; right: 0; bottom: 0; opacity: 0.08; border-radius: var(--sc_rounded); pointer-events: none; } .content { z-index: 2; position: relative; flex: 1; } slot { display: block; } .hidden { display: none !important; } /*Rounded*/ :host([size="2xs"]), :host([size="xs"]), :host([size="sm"]) { --sc_rounded: var(--sc-rounded-sm); } /*Dismissible*/ :host([dismissible]) { padding-right: 3rem; } :host([dismissible]) .close-btn { position: absolute; top: 0.4rem; right: 0.3rem; } `, ]; /** * Titre du message d'erreur */ @property({ type: String }) label = ""; @property({ type: Boolean, reflect: true }) noIcon = false; /** * Peut être renseigné dans le slot pour créer des messages plus complexes */ @property({ type: String }) text = ""; @property({ type: String }) id = new Date().getTime().toString(); @property({ type: String, reflect: true }) size?: Size; @property({ type: Boolean, reflect: true }) dismissible = false; @property({ type: Boolean, reflect: true }) background = false; @property({ type: String, reflect: true }) status: AlertStatus = "default"; @property({ type: Boolean, reflect: true }) dismissForever = false; connectedCallback() { if (this.dismissForever) { const dismissed = localStorage.getItem("sonic-alert-dismissed") || "{}"; const dismissedObj = JSON.parse(dismissed); if (dismissedObj[this.id]) { this.remove(); } } super.connectedCallback(); } render() { return html` ${!this.noIcon ? html`
${this.status && html``}
` : nothing}
${this.label ? html`${unsafeHTML(this.label)}` : nothing}
${this.text}
${this.dismissible ? html` ` : nothing} `; } close() { this.remove(); // if dismiss forever, save in localstorage if (this.dismissForever) { const dismissed = localStorage.getItem("sonic-alert-dismissed") || "{}"; const dismissedObj = JSON.parse(dismissed); dismissedObj[this.id] = true; localStorage.setItem( "sonic-alert-dismissed", JSON.stringify(dismissedObj) ); } } }