UNPKG

@limetech/lime-elements

Version:
380 lines (379 loc) 11.2 kB
import { h, } from '@stencil/core'; import translate from '../../global/translations'; import { SnackbarContainer } from './container'; import { createRandomString } from '../../util/random-string'; const container = new SnackbarContainer(); const hideAnimationDuration = 300; /** * A Snackbar –also known as "Toast"– is used to inform the end user * about an action or a process in the system. * The information could vary from announcing that a process has just started, * is taking place now, has ended, or has been interrupted or canceled. * * The information that you provide using a snackbar should be: * - temporary * - contextual * - short * - and most importantly, ignorable. * * It means if the user misses the information, it shouldn't be a big deal. * * :::note * If the information you want to display has a higher importance or priority, * and you need to make sure that the user takes an action to dismiss it, * consider using the [Banner](/#/component/limel-banner/) component instead. * For more complex interactions and for delivering more detailed information, * [Dialog](/#/component/limel-dialog/) is a better choice. * ::: * * @exampleComponent limel-example-snackbar * @exampleComponent limel-example-snackbar-with-action * @exampleComponent limel-example-snackbar-with-changing-messages * @exampleComponent limel-example-snackbar-dismissible * @exampleComponent limel-example-snackbar-persistent * @exampleComponent limel-example-snackbar-persistent-non-dismissible */ export class Snackbar { constructor() { this.handleOpen = () => { if (this.isOpen) { return; } this.isOpen = true; this.closing = false; container.add(this.host); if (this.timeout && this.timeout !== -1) { this.timeoutId = window.setTimeout(this.handleClose, Math.max(this.timeout - hideAnimationDuration, hideAnimationDuration)); } }; this.handleClose = () => { if (!this.isOpen) { return; } this.closing = true; if (this.timeoutId) { clearTimeout(this.timeoutId); this.timeoutId = undefined; } setTimeout(() => { this.isOpen = false; container.remove(this.host); this.hide.emit(); this.offset = 0; }, hideAnimationDuration); }; this.handleClickAction = () => { this.action.emit(); }; this.open = false; this.message = undefined; this.timeout = 5000; this.actionText = undefined; this.dismissible = true; this.multiline = undefined; this.language = 'en'; this.offset = 0; this.isOpen = false; this.closing = true; this.snackbarId = createRandomString(); } componentDidLoad() { if (this.open) { requestAnimationFrame(this.handleOpen); } } onChangeIndex(event) { event.stopPropagation(); this.offset = event.detail; } watchOpen() { if (this.open) { this.handleOpen(); } else { this.handleClose(); } this.isOpen = this.open; } /** * Show the snackbar * @deprecated Use the `open` property instead. */ async show() { console.warn('The `show` method in `limel-snackbar` is deprecated. Please use the `open` property instead.'); if (!this.open) { this.handleOpen(); } } render() { return (h("aside", { popover: "manual", style: { '--snackbar-timeout': `${Math.max(this.timeout || 0, 0)}ms`, '--snackbar-distance-to-top-edge': `${this.offset}px`, }, class: { open: this.open, 'is-closing': this.closing, 'limel-portal--parent': true, }, id: this.snackbarId, role: this.setAriaRoles(), "aria-relevant": this.open ? 'additions' : undefined }, h("div", { class: "surface", "aria-atomic": "false" }, h("div", { class: "label" }, this.message), this.renderActions(this.actionText), this.renderDismissButton(this.dismissible)))); } setAriaRoles() { if (!this.open) { return; } if (!this.timeout || this.timeout === -1) { return 'alertdialog'; } return 'status'; } renderActions(actionText) { if (!actionText) { return; } return (h("div", { class: "actions", "aria-atomic": "true" }, this.renderActionButton(actionText))); } renderActionButton(actionText) { if (!actionText) { return; } return (h("limel-button", { label: actionText, onClick: this.handleClickAction })); } renderDismissButton(dismissible) { if (!dismissible) { return; } const label = translate.get('snackbar.dismiss', this.language); return (h("div", { class: "dismiss" }, this.renderTimeoutVisualization(), h("limel-icon-button", { class: "dismiss-button", icon: "multiply", label: label, onClick: this.handleClose, "aria-controls": this.snackbarId }))); } renderTimeoutVisualization() { if (!this.timeout || this.timeout === -1) { return; } return (h("svg", { width: "36", height: "36", viewBox: "0 0 36 36" }, h("circle", { r: "18", cx: "18", cy: "18", fill: "var(--track-color)" }), h("path", { class: "track", d: "M 18,18 m -16,0 a 16,16 0 1,0 32,0 a 16,16 0 1,0 -32,0", stroke: "var(--fill-color)" }))); } static get is() { return "limel-snackbar"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["snackbar.scss"] }; } static get styleUrls() { return { "$": ["snackbar.css"] }; } static get properties() { return { "open": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "`true` if the snackbar is open, `false` otherwise." }, "attribute": "open", "reflect": true, "defaultValue": "false" }, "message": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The text message to display." }, "attribute": "message", "reflect": false }, "timeout": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The amount of time in milliseconds to show the snackbar.\nIf set to `-1`, the snackbar will be persistent.\nThis means:\n- either the end user will need to close it manually,\nwhich requires the `dismissible` property to be set to `true`.\n- or the snackbar needs to be closed programmatically." }, "attribute": "timeout", "reflect": true, "defaultValue": "5000" }, "actionText": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The text to display for the action button." }, "attribute": "action-text", "reflect": false }, "dismissible": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "When `true` displays a dismiss button on the snackbar,\nallowing users to close it." }, "attribute": "dismissible", "reflect": false, "defaultValue": "true" }, "multiline": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [{ "name": "deprecated", "text": "Setting this property no longer has any effect. The property will be removed in a future major version." }], "text": "Whether to show the snackbar with space for multiple lines of text" }, "attribute": "multiline", "reflect": false }, "language": { "type": "string", "mutable": false, "complexType": { "original": "Languages", "resolved": "\"da\" | \"de\" | \"en\" | \"fi\" | \"fr\" | \"nb\" | \"nl\" | \"no\" | \"sv\"", "references": { "Languages": { "location": "import", "path": "../date-picker/date.types" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Defines the language for translations." }, "attribute": "language", "reflect": false, "defaultValue": "'en'" } }; } static get states() { return { "offset": {}, "isOpen": {}, "closing": {} }; } static get events() { return [{ "method": "action", "name": "action", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when the action button is pressed" }, "complexType": { "original": "void", "resolved": "void", "references": {} } }, { "method": "hide", "name": "hide", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when the snackbar hides itself" }, "complexType": { "original": "void", "resolved": "void", "references": {} } }]; } static get methods() { return { "show": { "complexType": { "signature": "() => Promise<void>", "parameters": [], "references": { "Promise": { "location": "global" } }, "return": "Promise<void>" }, "docs": { "text": "Show the snackbar", "tags": [{ "name": "deprecated", "text": "Use the `open` property instead." }] } } }; } static get elementRef() { return "host"; } static get watchers() { return [{ "propName": "open", "methodName": "watchOpen" }]; } static get listeners() { return [{ "name": "changeOffset", "method": "onChangeIndex", "target": undefined, "capture": false, "passive": false }]; } } //# sourceMappingURL=snackbar.js.map