@limetech/lime-elements
Version:
380 lines (379 loc) • 11.2 kB
JavaScript
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