UNPKG

@telekom/scale-components

Version:

Scale is the digital design system for Telekom products and experiences.

406 lines (405 loc) 11.6 kB
/** * @license * Scale https://github.com/telekom/scale * * Copyright (c) 2021 Egor Kirpichev and contributors, Deutsche Telekom AG * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { Component, Prop, h, Element, Event, State, Host, Watch, } from '@stencil/core'; import cn from 'classnames'; import { animationsFinished } from '../../utils/utils'; const ICON_SIZE = 20; const iconVariantNameMap = { informational: 'scale-icon-alert-information', warning: 'scale-icon-alert-warning', success: 'scale-icon-action-success', danger: 'scale-icon-alert-error', }; export class Notification { constructor() { /** (optional) Type */ this.type = 'inline'; /** (optional) Variant */ this.variant = 'informational'; /** (optional) Show the close button */ this.dismissible = false; /** (optional) `aria-live` of element */ this.innerAriaLive = 'assertive'; /** (optional) Label for close button */ this.closeButtonLabel = 'Close'; /** (optional) `title` for close button */ this.closeButtonTitle = 'Close'; /** Default aria-level for heading */ this.headingLevel = 2; /** (optional) string prepended to the heading */ this.ariaHeading = 'Information'; /** What actually triggers opening/closing the notification */ this.isOpen = this.opened || false; this.role = 'alert'; this.hasTextSlot = false; this.lastCloseEventTrigger = null; this.open = () => { this.isOpen = true; this.role = 'alert'; this.animationState = 'in'; requestAnimationFrame(async () => { await animationsFinished(this.hostElement.shadowRoot); this.animationState = undefined; this.scaleOpen.emit(); if (this.delay !== undefined) { setTimeout(this.timeout, this.delay); } }); }; this.close = () => { const event = this.scaleBeforeClose.emit({ trigger: this.lastCloseEventTrigger, }); this.lastCloseEventTrigger = null; const prevented = event.defaultPrevented; if (prevented) { this.opened = true; return; } this.animationState = 'out'; requestAnimationFrame(async () => { await animationsFinished(this.hostElement.shadowRoot); this.animationState = undefined; this.isOpen = false; this.scaleClose.emit(); }); }; this.timeout = () => { this.lastCloseEventTrigger = 'TIMEOUT'; this.opened = false; }; } connectedCallback() { if (this.hostElement.hasAttribute('opened')) { // Do not use `role="alert"` if opened/visible on page load this.role = undefined; this.isOpen = true; } if (this.delay !== undefined) { setTimeout(this.timeout, this.delay); } this.hasTextSlot = this.hostElement.querySelector('[slot="text"]') != null; // this.hasActionSlot = // this.hostElement.querySelector('[slot="action"]') != null; } openedChanged(newValue) { if (newValue === true) { this.open(); this.lastCloseEventTrigger = 'ATTRIBUTE'; } else if (this.isOpen) { this.close(); } } render() { const IconTag = iconVariantNameMap[this.variant]; return (h(Host, null, this.styles && h("style", null, this.styles), h("div", { part: cn('base', this.animationState, `type-${this.type}`, `variant-${this.variant}`, this.isOpen && 'open'), role: this.role }, h("div", { part: "icon", "aria-hidden": "true" }, h("slot", { name: "icon" }, h(IconTag, { size: ICON_SIZE, selected: this.type === 'toast' }))), h("div", { part: "body", "aria-live": this.role === undefined ? undefined : this.innerAriaLive }, h("div", { part: "heading", role: "heading", "aria-level": this.headingLevel, "aria-label": `${this.ariaHeading} ${this.heading}` }, h("span", null, this.heading)), this.hasTextSlot && (h("div", { part: "text" }, h("slot", { name: "text" })))), this.dismissible && (h("scale-button", { part: "close-button", variant: "ghost", onClick: () => { this.lastCloseEventTrigger = 'CLOSE_BUTTON'; this.opened = false; } }, h("slot", { name: "close-icon" }, h("scale-icon-action-circle-close", { "aria-label": this.closeButtonLabel, accessibilityTitle: this.closeButtonTitle, decorative: true, size: ICON_SIZE }))))))); } static get is() { return "scale-notification"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["./notification.css"] }; } static get styleUrls() { return { "$": ["notification.css"] }; } static get properties() { return { "heading": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Heading" }, "attribute": "heading", "reflect": false }, "type": { "type": "string", "mutable": false, "complexType": { "original": "'inline' | 'banner' | 'toast'", "resolved": "\"banner\" | \"inline\" | \"toast\"", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) Type" }, "attribute": "type", "reflect": false, "defaultValue": "'inline'" }, "variant": { "type": "string", "mutable": false, "complexType": { "original": "'danger' | 'warning' | 'success' | 'informational'", "resolved": "\"danger\" | \"informational\" | \"success\" | \"warning\"", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) Variant" }, "attribute": "variant", "reflect": false, "defaultValue": "'informational'" }, "opened": { "type": "boolean", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) Visible" }, "attribute": "opened", "reflect": true }, "dismissible": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) Show the close button" }, "attribute": "dismissible", "reflect": false, "defaultValue": "false" }, "delay": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) Time in milliseconds until it closes by itself" }, "attribute": "delay", "reflect": false }, "innerAriaLive": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) `aria-live` of element" }, "attribute": "inner-aria-live", "reflect": false, "defaultValue": "'assertive'" }, "closeButtonLabel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) Label for close button" }, "attribute": "close-button-label", "reflect": false, "defaultValue": "'Close'" }, "closeButtonTitle": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) `title` for close button" }, "attribute": "close-button-title", "reflect": false, "defaultValue": "'Close'" }, "headingLevel": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Default aria-level for heading" }, "attribute": "heading-level", "reflect": false, "defaultValue": "2" }, "ariaHeading": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) string prepended to the heading" }, "attribute": "aria-heading", "reflect": false, "defaultValue": "'Information'" }, "styles": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "(optional) Injected styles" }, "attribute": "styles", "reflect": false } }; } static get states() { return { "isOpen": {}, "animationState": {}, "role": {}, "hasTextSlot": {} }; } static get events() { return [{ "method": "scaleOpen", "name": "scale-open", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Fires after the notification has been opened" }, "complexType": { "original": "void", "resolved": "void", "references": {} } }, { "method": "scaleBeforeClose", "name": "scale-before-close", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Fires on every close attempt. Calling `event.preventDefault()` will prevent the modal from closing" }, "complexType": { "original": "BeforeCloseEventDetail", "resolved": "BeforeCloseEventDetail", "references": { "BeforeCloseEventDetail": { "location": "local" } } } }, { "method": "scaleClose", "name": "scale-close", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Fires after the notification has been closed" }, "complexType": { "original": "void", "resolved": "void", "references": {} } }]; } static get elementRef() { return "hostElement"; } static get watchers() { return [{ "propName": "opened", "methodName": "openedChanged" }]; } }