lit-toaster 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/index.d.ts +12 -10
- package/dist/lit-toaster.js +75 -32
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img alt="
|
|
2
|
+
<img alt="lit toaster logo" src="https://res.cloudinary.com/ddlhtsgmp/image/upload/w_300,h_300,c_fill,r_10/v1755055178/lit-toaster-logo-full.png"/>
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
<br />
|
|
@@ -82,9 +82,9 @@ declare global {
|
|
|
82
82
|
|
|
83
83
|
## Toaster element properties
|
|
84
84
|
|
|
85
|
-
| Name
|
|
86
|
-
|
|
|
87
|
-
| `
|
|
85
|
+
| Name | Attribute |
|
|
86
|
+
| ------------- | --------- |
|
|
87
|
+
| `toastsLimit` | false |
|
|
88
88
|
|
|
89
89
|
## Documentation
|
|
90
90
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3,42 +3,44 @@ import { LitElement, TemplateResult } from 'lit';
|
|
|
3
3
|
|
|
4
4
|
type ToastKind = 'success' | 'error' | 'warning' | 'info';
|
|
5
5
|
type ToastPosition = 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center';
|
|
6
|
+
type ToastState = 'enter' | 'leave';
|
|
6
7
|
type Toast = {
|
|
7
8
|
id: string;
|
|
8
9
|
message: string;
|
|
9
10
|
duration: number;
|
|
10
11
|
type: ToastKind;
|
|
11
12
|
position: ToastPosition;
|
|
13
|
+
state: ToastState;
|
|
12
14
|
};
|
|
13
15
|
declare enum ToastEmitterEvent {
|
|
14
|
-
|
|
16
|
+
TOASTS_LIMIT_CHANGE = "toasts-limit-change",
|
|
15
17
|
TOASTS_CHANGE = "toasts-change"
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
declare class ToastEmitter extends EventTarget {
|
|
19
|
-
private
|
|
21
|
+
private _toastsLimit;
|
|
20
22
|
private _toasts;
|
|
21
23
|
get toasts(): Toast[];
|
|
22
|
-
set
|
|
24
|
+
set toastsLimit(value: string | number);
|
|
23
25
|
show(message: string, duration?: number, type?: ToastKind, position?: ToastPosition): void;
|
|
24
|
-
remove(
|
|
25
|
-
private
|
|
26
|
+
remove(toast: Toast): void;
|
|
27
|
+
private emitToastsLimitChange;
|
|
26
28
|
private emitToastsChange;
|
|
27
29
|
}
|
|
28
30
|
declare const toast: ToastEmitter;
|
|
29
31
|
|
|
30
32
|
declare class ToasterElement extends LitElement {
|
|
31
|
-
set
|
|
32
|
-
get
|
|
33
|
+
set toastsLimit(value: number | undefined);
|
|
34
|
+
get toastsLimit(): number | undefined;
|
|
33
35
|
private _toastsList;
|
|
34
|
-
private
|
|
36
|
+
private _toastsLimit?;
|
|
35
37
|
connectedCallback(): void;
|
|
36
38
|
disconnectedCallback(): void;
|
|
37
39
|
private get groupedToasts();
|
|
38
40
|
render(): TemplateResult;
|
|
39
41
|
private getToastIcon;
|
|
40
42
|
private dismiss;
|
|
41
|
-
private
|
|
43
|
+
private onToastsLimitChange;
|
|
42
44
|
private onToastsChange;
|
|
43
45
|
static styles: lit.CSSResult;
|
|
44
46
|
}
|
|
@@ -49,4 +51,4 @@ declare global {
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
export { ToastEmitterEvent, ToasterElement, toast };
|
|
52
|
-
export type { Toast, ToastKind, ToastPosition };
|
|
54
|
+
export type { Toast, ToastKind, ToastPosition, ToastState };
|
package/dist/lit-toaster.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! lit-toaster v0.1
|
|
1
|
+
/*! lit-toaster v0.2.1 Copyright (c) 2025 Bryson Ward and contributors MIT License*/
|
|
2
2
|
import { css, LitElement, html } from 'lit';
|
|
3
3
|
import { property, state, customElement } from 'lit/decorators.js';
|
|
4
4
|
|
|
@@ -15,7 +15,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
15
15
|
|
|
16
16
|
var ToastEmitterEvent;
|
|
17
17
|
(function (ToastEmitterEvent) {
|
|
18
|
-
ToastEmitterEvent["
|
|
18
|
+
ToastEmitterEvent["TOASTS_LIMIT_CHANGE"] = "toasts-limit-change";
|
|
19
19
|
ToastEmitterEvent["TOASTS_CHANGE"] = "toasts-change";
|
|
20
20
|
})(ToastEmitterEvent || (ToastEmitterEvent = {}));
|
|
21
21
|
|
|
@@ -26,6 +26,7 @@ const TOAST_TYPES = [
|
|
|
26
26
|
'warning',
|
|
27
27
|
'info',
|
|
28
28
|
];
|
|
29
|
+
const TOAST_ANIMATION_DURATION = 200;
|
|
29
30
|
|
|
30
31
|
const GUID = (() => {
|
|
31
32
|
let count = 0;
|
|
@@ -37,28 +38,28 @@ const GUID = (() => {
|
|
|
37
38
|
class ToastEmitter extends EventTarget {
|
|
38
39
|
constructor() {
|
|
39
40
|
super(...arguments);
|
|
40
|
-
this.
|
|
41
|
+
this._toastsLimit = DEFAULT_TOASTS_LIMIT;
|
|
41
42
|
this._toasts = [];
|
|
42
43
|
}
|
|
43
44
|
get toasts() {
|
|
44
45
|
return this._toasts;
|
|
45
46
|
}
|
|
46
|
-
set
|
|
47
|
-
let
|
|
47
|
+
set toastsLimit(value) {
|
|
48
|
+
let updatedToastsLimit = this._toastsLimit;
|
|
48
49
|
if (typeof value === 'number') {
|
|
49
|
-
|
|
50
|
+
updatedToastsLimit = value;
|
|
50
51
|
}
|
|
51
52
|
if (typeof value === 'string') {
|
|
52
53
|
const valueToNum = Number(value);
|
|
53
54
|
if (!isNaN(valueToNum)) {
|
|
54
|
-
|
|
55
|
+
updatedToastsLimit = valueToNum;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
58
|
+
this._toastsLimit = Math.max(0, updatedToastsLimit);
|
|
59
|
+
this.emitToastsLimitChange();
|
|
59
60
|
}
|
|
60
61
|
show(message, duration = 7000, type = 'success', position = 'top-center') {
|
|
61
|
-
if (this.
|
|
62
|
+
if (this._toastsLimit > 0 && this._toasts.length + 1 >= this._toastsLimit) {
|
|
62
63
|
const existingWarningToast = this._toasts.find((t) => t.type === 'warning' &&
|
|
63
64
|
t.message.toLowerCase().includes('too many notifications'));
|
|
64
65
|
if (!existingWarningToast) {
|
|
@@ -68,8 +69,9 @@ class ToastEmitter extends EventTarget {
|
|
|
68
69
|
duration,
|
|
69
70
|
type: 'warning',
|
|
70
71
|
position: 'bottom-center',
|
|
72
|
+
state: 'enter',
|
|
71
73
|
};
|
|
72
|
-
this._toasts = [...this._toasts
|
|
74
|
+
this._toasts = [warningToast, ...this._toasts];
|
|
73
75
|
this.emitToastsChange();
|
|
74
76
|
setTimeout(() => this.remove(warningToast), duration);
|
|
75
77
|
}
|
|
@@ -83,20 +85,28 @@ class ToastEmitter extends EventTarget {
|
|
|
83
85
|
duration,
|
|
84
86
|
type,
|
|
85
87
|
position,
|
|
88
|
+
state: 'enter',
|
|
86
89
|
};
|
|
87
|
-
this._toasts = [...this._toasts
|
|
90
|
+
this._toasts = [newToast, ...this._toasts];
|
|
88
91
|
this.emitToastsChange();
|
|
89
92
|
if (duration > 0) {
|
|
90
93
|
setTimeout(() => this.remove(newToast), duration);
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
|
-
remove(
|
|
94
|
-
|
|
96
|
+
remove(toast) {
|
|
97
|
+
const index = this._toasts.indexOf(toast);
|
|
98
|
+
if (index === -1)
|
|
99
|
+
return;
|
|
100
|
+
this._toasts[index].state = 'leave';
|
|
95
101
|
this.emitToastsChange();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
this._toasts = this._toasts.filter((item) => item !== toast);
|
|
104
|
+
this.emitToastsChange();
|
|
105
|
+
}, TOAST_ANIMATION_DURATION);
|
|
106
|
+
}
|
|
107
|
+
emitToastsLimitChange() {
|
|
108
|
+
this.dispatchEvent(new CustomEvent(ToastEmitterEvent.TOASTS_LIMIT_CHANGE, {
|
|
109
|
+
detail: this._toastsLimit,
|
|
100
110
|
}));
|
|
101
111
|
}
|
|
102
112
|
emitToastsChange() {
|
|
@@ -111,10 +121,10 @@ let ToasterElement = class ToasterElement extends LitElement {
|
|
|
111
121
|
constructor() {
|
|
112
122
|
super(...arguments);
|
|
113
123
|
this._toastsList = [];
|
|
114
|
-
this.
|
|
124
|
+
this.onToastsLimitChange = (event) => {
|
|
115
125
|
if (event instanceof CustomEvent) {
|
|
116
|
-
if (event.detail !== undefined && this.
|
|
117
|
-
this.
|
|
126
|
+
if (event.detail !== undefined && this._toastsLimit !== event.detail) {
|
|
127
|
+
this._toastsLimit = event.detail;
|
|
118
128
|
this.requestUpdate();
|
|
119
129
|
}
|
|
120
130
|
}
|
|
@@ -126,23 +136,23 @@ let ToasterElement = class ToasterElement extends LitElement {
|
|
|
126
136
|
}
|
|
127
137
|
};
|
|
128
138
|
}
|
|
129
|
-
set
|
|
130
|
-
this.
|
|
139
|
+
set toastsLimit(value) {
|
|
140
|
+
this._toastsLimit = value;
|
|
131
141
|
if (value !== undefined) {
|
|
132
|
-
toast.
|
|
142
|
+
toast.toastsLimit = value;
|
|
133
143
|
}
|
|
134
144
|
}
|
|
135
|
-
get
|
|
136
|
-
return this.
|
|
145
|
+
get toastsLimit() {
|
|
146
|
+
return this._toastsLimit;
|
|
137
147
|
}
|
|
138
148
|
connectedCallback() {
|
|
139
149
|
super.connectedCallback();
|
|
140
|
-
toast.addEventListener(ToastEmitterEvent.
|
|
150
|
+
toast.addEventListener(ToastEmitterEvent.TOASTS_LIMIT_CHANGE, this.onToastsLimitChange);
|
|
141
151
|
toast.addEventListener(ToastEmitterEvent.TOASTS_CHANGE, this.onToastsChange);
|
|
142
152
|
}
|
|
143
153
|
disconnectedCallback() {
|
|
144
154
|
super.disconnectedCallback();
|
|
145
|
-
toast.removeEventListener(ToastEmitterEvent.
|
|
155
|
+
toast.removeEventListener(ToastEmitterEvent.TOASTS_LIMIT_CHANGE, this.onToastsLimitChange);
|
|
146
156
|
toast.removeEventListener(ToastEmitterEvent.TOASTS_CHANGE, this.onToastsChange);
|
|
147
157
|
}
|
|
148
158
|
get groupedToasts() {
|
|
@@ -167,7 +177,7 @@ let ToasterElement = class ToasterElement extends LitElement {
|
|
|
167
177
|
${toasts.map((toast) => html `
|
|
168
178
|
<div
|
|
169
179
|
id="toast-${toast.type}-${toast.id}"
|
|
170
|
-
class="toast"
|
|
180
|
+
class="toast ${toast.state}"
|
|
171
181
|
role="alert"
|
|
172
182
|
>
|
|
173
183
|
<div class="toast-${toast.type} toast-icon">
|
|
@@ -232,7 +242,7 @@ ToasterElement.styles = css `
|
|
|
232
242
|
0 1px 3px #0000001a;
|
|
233
243
|
}
|
|
234
244
|
|
|
235
|
-
/** Screen
|
|
245
|
+
/** Screen reader only */
|
|
236
246
|
.sr-only {
|
|
237
247
|
position: absolute;
|
|
238
248
|
width: 1px;
|
|
@@ -345,6 +355,39 @@ ToasterElement.styles = css `
|
|
|
345
355
|
flex-direction: column-reverse;
|
|
346
356
|
}
|
|
347
357
|
|
|
358
|
+
.toast.enter {
|
|
359
|
+
animation: onToastEnter 250ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.toast.leave {
|
|
363
|
+
animation: onToastLeave 200ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@keyframes onToastEnter {
|
|
367
|
+
from {
|
|
368
|
+
opacity: 0;
|
|
369
|
+
transform: translateY(12px);
|
|
370
|
+
}
|
|
371
|
+
to {
|
|
372
|
+
opacity: 1;
|
|
373
|
+
transform: translateY(0);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@keyframes onToastLeave {
|
|
378
|
+
0% {
|
|
379
|
+
opacity: 1;
|
|
380
|
+
transform: translateY(0) scaleY(1);
|
|
381
|
+
}
|
|
382
|
+
50% {
|
|
383
|
+
transform: translateY(4px) scaleY(0.95);
|
|
384
|
+
}
|
|
385
|
+
100% {
|
|
386
|
+
opacity: 0;
|
|
387
|
+
transform: translateY(24px) scaleY(0.8);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
348
391
|
/* Apply dark mode styles if user’s system or browser theme is set to 'dark' */
|
|
349
392
|
@media (prefers-color-scheme: dark) {
|
|
350
393
|
.toast {
|
|
@@ -355,13 +398,13 @@ ToasterElement.styles = css `
|
|
|
355
398
|
`;
|
|
356
399
|
__decorate([
|
|
357
400
|
property({ type: Number, attribute: false })
|
|
358
|
-
], ToasterElement.prototype, "
|
|
401
|
+
], ToasterElement.prototype, "toastsLimit", null);
|
|
359
402
|
__decorate([
|
|
360
403
|
state()
|
|
361
404
|
], ToasterElement.prototype, "_toastsList", void 0);
|
|
362
405
|
__decorate([
|
|
363
406
|
state()
|
|
364
|
-
], ToasterElement.prototype, "
|
|
407
|
+
], ToasterElement.prototype, "_toastsLimit", void 0);
|
|
365
408
|
ToasterElement = __decorate([
|
|
366
409
|
customElement('app-toaster')
|
|
367
410
|
], ToasterElement);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lit-toaster",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20",
|
|
6
6
|
"npm": ">=9.6.3",
|
|
@@ -61,13 +61,13 @@
|
|
|
61
61
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
62
62
|
"@rollup/plugin-typescript": "^12.1.4",
|
|
63
63
|
"@size-limit/file": "^11.2.0",
|
|
64
|
-
"@testing-library/jest-dom": "^6.
|
|
64
|
+
"@testing-library/jest-dom": "^6.8.0",
|
|
65
65
|
"@testing-library/user-event": "^14.6.1",
|
|
66
66
|
"@types/eslint-plugin-security": "^3.0.0",
|
|
67
67
|
"@types/jest": "^30.0.0",
|
|
68
68
|
"@vitest/coverage-v8": "^3.2.4",
|
|
69
69
|
"auto-changelog": "^2.5.0",
|
|
70
|
-
"eslint": "^9.
|
|
70
|
+
"eslint": "^9.35.0",
|
|
71
71
|
"eslint-config-prettier": "^10.1.8",
|
|
72
72
|
"eslint-plugin-lit": "^2.1.1",
|
|
73
73
|
"eslint-plugin-prettier": "^5.5.4",
|
|
@@ -75,15 +75,15 @@
|
|
|
75
75
|
"jsdom": "^26.1.0",
|
|
76
76
|
"prettier": "^3.6.2",
|
|
77
77
|
"release-it": "^19.0.4",
|
|
78
|
-
"rollup": "^4.
|
|
78
|
+
"rollup": "^4.50.1",
|
|
79
79
|
"rollup-plugin-cleanup": "^3.2.1",
|
|
80
80
|
"rollup-plugin-delete": "^3.0.1",
|
|
81
|
-
"rollup-plugin-dts": "^6.2.
|
|
81
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
82
82
|
"size-limit": "^11.2.0",
|
|
83
|
-
"typedoc": "^0.28.
|
|
83
|
+
"typedoc": "^0.28.12",
|
|
84
84
|
"typedoc-plugin-markdown": "^4.8.1",
|
|
85
85
|
"typescript": "^5.9.2",
|
|
86
|
-
"typescript-eslint": "^8.
|
|
86
|
+
"typescript-eslint": "^8.43.0",
|
|
87
87
|
"vitest": "^3.2.4"
|
|
88
88
|
},
|
|
89
89
|
"release-it": {
|