@justeattakeaway/pie-toast 0.3.3 → 0.4.0
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/custom-elements.json +90 -1
- package/dist/index.d.ts +44 -2
- package/dist/index.js +161 -102
- package/dist/react.d.ts +44 -2
- package/dist/react.js +14 -25
- package/package.json +6 -6
- package/src/defs-react.ts +1 -1
- package/src/defs.ts +8 -0
- package/src/index.ts +115 -9
- package/src/react.ts +1 -1
- package/src/toast.scss +37 -0
package/custom-elements.json
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"type": {
|
|
61
61
|
"text": "DefaultProps"
|
|
62
62
|
},
|
|
63
|
-
"default": "{\n isOpen: true,\n variant: 'neutral',\n isStrong: false,\n isDismissible: true,\n isMultiline: false,\n}"
|
|
63
|
+
"default": "{\n isOpen: true,\n variant: 'neutral',\n isStrong: false,\n isDismissible: true,\n isMultiline: false,\n duration: 5000,\n}"
|
|
64
64
|
}
|
|
65
65
|
],
|
|
66
66
|
"exports": [
|
|
@@ -180,6 +180,12 @@
|
|
|
180
180
|
"privacy": "public",
|
|
181
181
|
"attribute": "leadingAction"
|
|
182
182
|
},
|
|
183
|
+
{
|
|
184
|
+
"kind": "field",
|
|
185
|
+
"name": "duration",
|
|
186
|
+
"privacy": "public",
|
|
187
|
+
"attribute": "duration"
|
|
188
|
+
},
|
|
183
189
|
{
|
|
184
190
|
"kind": "field",
|
|
185
191
|
"name": "actionButton",
|
|
@@ -187,6 +193,13 @@
|
|
|
187
193
|
"text": "HTMLElement | undefined"
|
|
188
194
|
}
|
|
189
195
|
},
|
|
196
|
+
{
|
|
197
|
+
"kind": "field",
|
|
198
|
+
"name": "closeButton",
|
|
199
|
+
"type": {
|
|
200
|
+
"text": "HTMLElement | undefined"
|
|
201
|
+
}
|
|
202
|
+
},
|
|
190
203
|
{
|
|
191
204
|
"kind": "field",
|
|
192
205
|
"name": "_actionButtonOffset",
|
|
@@ -205,6 +218,36 @@
|
|
|
205
218
|
"privacy": "private",
|
|
206
219
|
"default": "0"
|
|
207
220
|
},
|
|
221
|
+
{
|
|
222
|
+
"kind": "field",
|
|
223
|
+
"name": "_timeoutId",
|
|
224
|
+
"type": {
|
|
225
|
+
"text": "NodeJS.Timeout | null"
|
|
226
|
+
},
|
|
227
|
+
"privacy": "private",
|
|
228
|
+
"default": "null"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"kind": "field",
|
|
232
|
+
"name": "_abortController",
|
|
233
|
+
"type": {
|
|
234
|
+
"text": "AbortController | null"
|
|
235
|
+
},
|
|
236
|
+
"privacy": "private",
|
|
237
|
+
"default": "null"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"kind": "method",
|
|
241
|
+
"name": "setAutoDismiss",
|
|
242
|
+
"privacy": "private",
|
|
243
|
+
"description": "Create a timeout function and set its id into a private attribute."
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"kind": "method",
|
|
247
|
+
"name": "abortAndCleanEventListeners",
|
|
248
|
+
"privacy": "private",
|
|
249
|
+
"description": "If the _abortController is set, it aborts all event\nlisteners in this controller and the controller turns into null."
|
|
250
|
+
},
|
|
208
251
|
{
|
|
209
252
|
"kind": "method",
|
|
210
253
|
"name": "getMessageMaxWidth",
|
|
@@ -246,6 +289,48 @@
|
|
|
246
289
|
],
|
|
247
290
|
"description": "Calculates and returns the width of the message based on the toast properties."
|
|
248
291
|
},
|
|
292
|
+
{
|
|
293
|
+
"kind": "method",
|
|
294
|
+
"name": "addListenersToElement",
|
|
295
|
+
"privacy": "private",
|
|
296
|
+
"parameters": [
|
|
297
|
+
{
|
|
298
|
+
"name": "element",
|
|
299
|
+
"type": {
|
|
300
|
+
"text": "typeof this | HTMLElement | undefined"
|
|
301
|
+
},
|
|
302
|
+
"description": "The element to which the listeners will be added. It can be the current instance, an HTMLElement, or undefined."
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"name": "inEvent",
|
|
306
|
+
"type": {
|
|
307
|
+
"text": "keyof HTMLElementEventMap"
|
|
308
|
+
},
|
|
309
|
+
"description": "The event type to listen for when entering the element. (e.g., 'mouseenter', 'focusin')."
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"name": "outEvent",
|
|
313
|
+
"type": {
|
|
314
|
+
"text": "keyof HTMLElementEventMap"
|
|
315
|
+
},
|
|
316
|
+
"description": "The event type to listen for when leaving the element. (e.g., 'mouseleave', 'focusout')."
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"name": "abortSignal",
|
|
320
|
+
"type": {
|
|
321
|
+
"text": "AddEventListenerOptions['signal']"
|
|
322
|
+
},
|
|
323
|
+
"description": "An AbortSignal that can be used to remove the event listeners."
|
|
324
|
+
}
|
|
325
|
+
],
|
|
326
|
+
"description": "Adds event listeners to the specified element for handling the auto dismiss behavior."
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"kind": "method",
|
|
330
|
+
"name": "createAutoDismissEventListeners",
|
|
331
|
+
"privacy": "private",
|
|
332
|
+
"description": "It creates all event listeners to handle the auto-dismiss capability\nas well the controller responsible to remove the events when needed."
|
|
333
|
+
},
|
|
249
334
|
{
|
|
250
335
|
"kind": "method",
|
|
251
336
|
"name": "handleActionClick",
|
|
@@ -385,6 +470,10 @@
|
|
|
385
470
|
"text": "ToastProps['leadingAction']"
|
|
386
471
|
},
|
|
387
472
|
"fieldName": "leadingAction"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"name": "duration",
|
|
476
|
+
"fieldName": "duration"
|
|
388
477
|
}
|
|
389
478
|
],
|
|
390
479
|
"mixins": [
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
|
2
2
|
import type { CSSResult } from 'lit';
|
|
3
3
|
import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
4
4
|
import type { LitElement } from 'lit';
|
|
5
|
-
import type { nothing } from 'lit';
|
|
6
5
|
import type { PropertyValues } from 'lit';
|
|
7
6
|
import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
8
7
|
import type { TemplateResult } from 'lit';
|
|
@@ -58,10 +57,27 @@ export declare class PieToast extends PieToast_base implements ToastProps {
|
|
|
58
57
|
isDismissible: boolean;
|
|
59
58
|
isMultiline: boolean;
|
|
60
59
|
leadingAction: ToastProps['leadingAction'];
|
|
60
|
+
duration: number | null;
|
|
61
61
|
actionButton?: HTMLElement;
|
|
62
|
+
closeButton?: HTMLElement;
|
|
62
63
|
private _actionButtonOffset;
|
|
63
64
|
private _messageAreaMaxWidth;
|
|
65
|
+
private _timeoutId;
|
|
66
|
+
private _abortController;
|
|
64
67
|
static styles: CSSResult;
|
|
68
|
+
/**
|
|
69
|
+
* Create a timeout function and set its id into a private attribute.
|
|
70
|
+
*
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
private setAutoDismiss;
|
|
74
|
+
/**
|
|
75
|
+
* If the _abortController is set, it aborts all event
|
|
76
|
+
* listeners in this controller and the controller turns into null.
|
|
77
|
+
*
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
private abortAndCleanEventListeners;
|
|
65
81
|
/**
|
|
66
82
|
* Calculates and returns the width of the message based on the toast properties.
|
|
67
83
|
*
|
|
@@ -73,9 +89,29 @@ export declare class PieToast extends PieToast_base implements ToastProps {
|
|
|
73
89
|
* @returns {number} - The width of the message in pixels.
|
|
74
90
|
*/
|
|
75
91
|
private getMessageMaxWidth;
|
|
92
|
+
/**
|
|
93
|
+
* Adds event listeners to the specified element for handling the auto dismiss behavior.
|
|
94
|
+
*
|
|
95
|
+
* @param {typeof this | HTMLElement | undefined} element - The element to which the listeners will be added. It can be the current instance, an HTMLElement, or undefined.
|
|
96
|
+
* @param {keyof HTMLElementEventMap} inEvent - The event type to listen for when entering the element. (e.g., 'mouseenter', 'focusin').
|
|
97
|
+
* @param {keyof HTMLElementEventMap} outEvent - The event type to listen for when leaving the element. (e.g., 'mouseleave', 'focusout').
|
|
98
|
+
* @param {AddEventListenerOptions['signal']} abortSignal - An AbortSignal that can be used to remove the event listeners.
|
|
99
|
+
*
|
|
100
|
+
* @private
|
|
101
|
+
*/
|
|
102
|
+
private addListenersToElement;
|
|
103
|
+
/**
|
|
104
|
+
* It creates all event listeners to handle the auto-dismiss capability
|
|
105
|
+
* as well the controller responsible to remove the events when needed.
|
|
106
|
+
*
|
|
107
|
+
* @private
|
|
108
|
+
*/
|
|
109
|
+
private createAutoDismissEventListeners;
|
|
76
110
|
/**
|
|
77
111
|
* Lifecycle method executed when component is updated.
|
|
78
112
|
* It dispatches an event if toast is opened.
|
|
113
|
+
* It adds event listeners when toast is opened and if the duration is not null
|
|
114
|
+
* It aborts all event listeners when toast is closed.
|
|
79
115
|
* It calculates _messageAreaMaxWidth
|
|
80
116
|
*/
|
|
81
117
|
protected updated(_changedProperties: PropertyValues<this>): Promise<void>;
|
|
@@ -146,7 +182,7 @@ export declare class PieToast extends PieToast_base implements ToastProps {
|
|
|
146
182
|
* @private
|
|
147
183
|
*/
|
|
148
184
|
private shouldNotUseInverseBtnVariant;
|
|
149
|
-
render(): TemplateResult<1
|
|
185
|
+
render(): TemplateResult<1>;
|
|
150
186
|
}
|
|
151
187
|
|
|
152
188
|
declare const PieToast_base: GenericConstructor<RTLInterface> & typeof LitElement;
|
|
@@ -180,6 +216,12 @@ export declare interface ToastProps {
|
|
|
180
216
|
* The leading action for the toast.
|
|
181
217
|
*/
|
|
182
218
|
leadingAction?: ActionProps;
|
|
219
|
+
/**
|
|
220
|
+
* Sets the duration of the toast in milliseconds before it auto-dismisses.
|
|
221
|
+
* If the value is null auto-dismiss is disabled
|
|
222
|
+
* If the value is not provided it auto-dismisses after 5 seconds (5000 milliseconds)
|
|
223
|
+
*/
|
|
224
|
+
duration?: number | null;
|
|
183
225
|
}
|
|
184
226
|
|
|
185
227
|
export declare const variants: readonly ["neutral", "info", "warning", "success", "error"];
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
import { property as
|
|
3
|
-
import { classMap as
|
|
4
|
-
import { RtlMixin as
|
|
1
|
+
import { LitElement as C, unsafeCSS as w, html as l, nothing as d } from "lit";
|
|
2
|
+
import { property as u, query as y } from "lit/decorators.js";
|
|
3
|
+
import { classMap as $ } from "lit/directives/class-map.js";
|
|
4
|
+
import { RtlMixin as O, dispatchCustomEvent as f, validPropertyValues as E, defineCustomElement as _ } from "@justeattakeaway/pie-webc-core";
|
|
5
5
|
import "@justeattakeaway/pie-icon-button";
|
|
6
6
|
import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
|
|
7
7
|
import "@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js";
|
|
@@ -9,22 +9,41 @@ import "@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js";
|
|
|
9
9
|
import "@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js";
|
|
10
10
|
import "@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js";
|
|
11
11
|
import "@justeattakeaway/pie-button";
|
|
12
|
-
const
|
|
13
|
-
`, _ = ["neutral", "info", "warning", "success", "error"], i = "pie-toast", a = "c-toast", N = `${i}-close`, k = `${i}-open`, I = `${i}-leading-action-click`, g = {
|
|
12
|
+
const k = "*,*:after,*:before{box-sizing:inherit}.c-toast{--toast-border-radius: var(--dt-radius-rounded-b);--toast-background-color: var(--dt-color-container-inverse);--toast-font-color: var(--dt-color-content-inverse);--toast-font-size: calc(var(--dt-font-body-s-size) * 1px);--toast-line-height: calc(var(--dt-font-body-s-line-height) * 1px);--toast-icon-fill: var(--dt-color-content-default);--toast-message-max-width: 100%;display:flex;flex-direction:column;justify-content:center;min-height:48px;max-height:122px;min-width:300px;max-width:420px;padding:var(--dt-spacing-a) var(--dt-spacing-c) var(--dt-spacing-a) var(--dt-spacing-d);border-radius:var(--toast-border-radius);gap:var(--dt-spacing-a);background-color:var(--toast-background-color);box-shadow:var(--dt-elevation-03);color:var(--toast-font-color);font-size:var(--toast-font-size);line-height:var(--toast-line-height);transition-property:all;transition-duration:var(--dt-motion-timing-100);transition-timing-function:var(--dt-motion-easing-in)}.c-toast--animate-in{animation-duration:var(--dt-motion-timing-200);animation-name:animate-in;animation-timing-function:var(--dt-motion-easing-in);transform:translate(0)}.c-toast--animate-out{animation-duration:var(--dt-motion-timing-100);animation-name:animate-out;animation-timing-function:var(--dt-motion-easing-out);transform:translate(100%);opacity:0}.c-toast--info{--toast-icon-fill: var(--dt-color-support-info-inverse)}.c-toast--info.c-toast--strong{--toast-background-color: var(--dt-color-support-info);--toast-icon-fill: var(--dt-color-content-inverse)}.c-toast--warning{--toast-icon-fill: var(--dt-color-support-warning-inverse)}.c-toast--warning.c-toast--strong{--toast-background-color: var(--dt-color-support-warning);--toast-icon-fill: var(--dt-color-content-dark);--toast-font-color: var(--dt-color-content-dark)}.c-toast--success{--toast-icon-fill: var(--dt-color-support-positive-inverse)}.c-toast--success.c-toast--strong{--toast-background-color: var(--dt-color-support-positive);--toast-icon-fill: var(--dt-color-content-inverse)}.c-toast--error{--toast-icon-fill: var(--dt-color-support-error-inverse)}.c-toast--error.c-toast--strong{--toast-background-color: var(--dt-color-support-error);--toast-icon-fill: var(--dt-color-content-inverse)}.c-toast-contentArea{display:flex;gap:var(--dt-spacing-b);justify-content:space-between}.c-toast-messageArea{display:flex;align-items:center;gap:var(--dt-spacing-b);padding:calc(var(--dt-spacing-03) / 2) 0}.c-toast-messageArea span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;max-width:var(--toast-message-max-width)}.c-toast-messageArea.c-toast--multiline{align-items:flex-start}.c-toast-messageArea.c-toast--multiline span{max-height:60px;white-space:inherit;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.c-toast-actionsArea{display:flex;gap:var(--dt-spacing-b)}.c-toast-footer{display:flex;justify-content:flex-end}.c-toast-icon{color:var(--toast-icon-fill)}@keyframes animate-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes animate-out{0%{transform:translate(0)}to{transform:translate(100%)}}", B = ["neutral", "info", "warning", "success", "error"], o = "pie-toast", s = "c-toast", M = `${o}-close`, I = `${o}-open`, T = `${o}-leading-action-click`, h = {
|
|
14
13
|
isOpen: !0,
|
|
15
14
|
variant: "neutral",
|
|
16
15
|
isStrong: !1,
|
|
17
16
|
isDismissible: !0,
|
|
18
|
-
isMultiline: !1
|
|
17
|
+
isMultiline: !1,
|
|
18
|
+
duration: 5e3
|
|
19
19
|
};
|
|
20
|
-
var
|
|
21
|
-
for (var
|
|
22
|
-
(
|
|
23
|
-
return
|
|
20
|
+
var L = Object.defineProperty, c = (v, t, i, n) => {
|
|
21
|
+
for (var e = void 0, r = v.length - 1, p; r >= 0; r--)
|
|
22
|
+
(p = v[r]) && (e = p(t, i, e) || e);
|
|
23
|
+
return e && L(t, i, e), e;
|
|
24
24
|
};
|
|
25
|
-
class
|
|
25
|
+
const g = class g extends O(C) {
|
|
26
26
|
constructor() {
|
|
27
|
-
super(...arguments), this.message = "", this.isOpen =
|
|
27
|
+
super(...arguments), this.message = "", this.isOpen = h.isOpen, this.variant = h.variant, this.isStrong = h.isStrong, this.isDismissible = h.isDismissible, this.isMultiline = h.isMultiline, this.duration = h.duration, this._actionButtonOffset = 0, this._messageAreaMaxWidth = 0, this._timeoutId = null, this._abortController = null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create a timeout function and set its id into a private attribute.
|
|
31
|
+
*
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
setAutoDismiss() {
|
|
35
|
+
this.duration !== null && (this._timeoutId = setTimeout(() => {
|
|
36
|
+
this.closeToastComponent();
|
|
37
|
+
}, this.duration));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* If the _abortController is set, it aborts all event
|
|
41
|
+
* listeners in this controller and the controller turns into null.
|
|
42
|
+
*
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
abortAndCleanEventListeners() {
|
|
46
|
+
this._abortController && (this._abortController.abort(), this._abortController = null);
|
|
28
47
|
}
|
|
29
48
|
/**
|
|
30
49
|
* Calculates and returns the width of the message based on the toast properties.
|
|
@@ -36,20 +55,50 @@ class r extends A(y) {
|
|
|
36
55
|
*
|
|
37
56
|
* @returns {number} - The width of the message in pixels.
|
|
38
57
|
*/
|
|
39
|
-
getMessageMaxWidth(t,
|
|
40
|
-
let
|
|
41
|
-
return t && (
|
|
58
|
+
getMessageMaxWidth(t, i, n, e) {
|
|
59
|
+
let m = 0;
|
|
60
|
+
return t && (m += 28), !i && n && (m += this._actionButtonOffset + 8), e && (m += 40), 392 - m;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Adds event listeners to the specified element for handling the auto dismiss behavior.
|
|
64
|
+
*
|
|
65
|
+
* @param {typeof this | HTMLElement | undefined} element - The element to which the listeners will be added. It can be the current instance, an HTMLElement, or undefined.
|
|
66
|
+
* @param {keyof HTMLElementEventMap} inEvent - The event type to listen for when entering the element. (e.g., 'mouseenter', 'focusin').
|
|
67
|
+
* @param {keyof HTMLElementEventMap} outEvent - The event type to listen for when leaving the element. (e.g., 'mouseleave', 'focusout').
|
|
68
|
+
* @param {AddEventListenerOptions['signal']} abortSignal - An AbortSignal that can be used to remove the event listeners.
|
|
69
|
+
*
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
addListenersToElement(t, i, n, e) {
|
|
73
|
+
t && (t.addEventListener(i, () => {
|
|
74
|
+
this._timeoutId && clearTimeout(this._timeoutId);
|
|
75
|
+
}, { signal: e }), t.addEventListener(n, () => {
|
|
76
|
+
this.setAutoDismiss();
|
|
77
|
+
}, { signal: e }));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* It creates all event listeners to handle the auto-dismiss capability
|
|
81
|
+
* as well the controller responsible to remove the events when needed.
|
|
82
|
+
*
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
createAutoDismissEventListeners() {
|
|
86
|
+
this._abortController = new AbortController(), this.setAutoDismiss();
|
|
87
|
+
const { signal: t } = this._abortController;
|
|
88
|
+
this.addListenersToElement(this.actionButton, "focus", "focusout", t), this.addListenersToElement(this.closeButton, "focus", "focusout", t), this.addListenersToElement(this, "mouseover", "mouseout", t);
|
|
42
89
|
}
|
|
43
90
|
/**
|
|
44
91
|
* Lifecycle method executed when component is updated.
|
|
45
92
|
* It dispatches an event if toast is opened.
|
|
93
|
+
* It adds event listeners when toast is opened and if the duration is not null
|
|
94
|
+
* It aborts all event listeners when toast is closed.
|
|
46
95
|
* It calculates _messageAreaMaxWidth
|
|
47
96
|
*/
|
|
48
97
|
async updated(t) {
|
|
49
|
-
var
|
|
50
|
-
t.has("isOpen") && this.isOpen &&
|
|
51
|
-
const
|
|
52
|
-
this._messageAreaMaxWidth = this.getMessageMaxWidth(
|
|
98
|
+
var n;
|
|
99
|
+
t.has("isOpen") && this.isOpen && (f(this, I, { targetNotification: this }), this.duration !== null && this.createAutoDismissEventListeners()), t.has("isOpen") && !this.isOpen && this.abortAndCleanEventListeners(), await this.updateComplete, this.actionButton && (this._actionButtonOffset = this.actionButton.offsetWidth);
|
|
100
|
+
const i = this.variantHasIcon(this.variant);
|
|
101
|
+
this._messageAreaMaxWidth = this.getMessageMaxWidth(i, this.isMultiline, !!((n = this.leadingAction) != null && n.text), this.isDismissible), (t.has("variant") || t.has("isStrong") || t.has("message") || t.has("isDismissible") || t.has("isMultiline") || t.has("leadingAction") || t.has("duration")) && this.requestUpdate();
|
|
53
102
|
}
|
|
54
103
|
/**
|
|
55
104
|
* It handle the action button action.
|
|
@@ -57,7 +106,7 @@ class r extends A(y) {
|
|
|
57
106
|
* @private
|
|
58
107
|
*/
|
|
59
108
|
handleActionClick() {
|
|
60
|
-
|
|
109
|
+
f(this, T, { targetNotification: this });
|
|
61
110
|
}
|
|
62
111
|
/**
|
|
63
112
|
* Render the action button depending on action type and its action.
|
|
@@ -68,16 +117,16 @@ class r extends A(y) {
|
|
|
68
117
|
* @private
|
|
69
118
|
*/
|
|
70
119
|
renderActionButton(t) {
|
|
71
|
-
const { text:
|
|
72
|
-
return
|
|
120
|
+
const { text: i, ariaLabel: n } = t;
|
|
121
|
+
return l`
|
|
73
122
|
<pie-button
|
|
74
123
|
variant="${this.shouldNotUseInverseBtnVariant() ? "ghost" : "ghost-inverse"}"
|
|
75
124
|
size="xsmall"
|
|
76
|
-
aria-label="${
|
|
125
|
+
aria-label="${n || d}"
|
|
77
126
|
@click="${() => this.handleActionClick()}"
|
|
78
|
-
data-test-id="${
|
|
127
|
+
data-test-id="${o}-leading-action"
|
|
79
128
|
type="button">
|
|
80
|
-
${
|
|
129
|
+
${i}
|
|
81
130
|
</pie-button>
|
|
82
131
|
`;
|
|
83
132
|
}
|
|
@@ -90,9 +139,9 @@ class r extends A(y) {
|
|
|
90
139
|
*/
|
|
91
140
|
renderFooter() {
|
|
92
141
|
const { leadingAction: t } = this;
|
|
93
|
-
return
|
|
94
|
-
<footer class="${
|
|
95
|
-
${t ? this.renderActionButton(t) :
|
|
142
|
+
return l`
|
|
143
|
+
<footer class="${s}-footer" data-test-id="${o}-footer" >
|
|
144
|
+
${t ? this.renderActionButton(t) : d}
|
|
96
145
|
</footer>
|
|
97
146
|
`;
|
|
98
147
|
}
|
|
@@ -103,11 +152,11 @@ class r extends A(y) {
|
|
|
103
152
|
* @private
|
|
104
153
|
*/
|
|
105
154
|
renderCloseButton() {
|
|
106
|
-
return
|
|
155
|
+
return l`
|
|
107
156
|
<pie-icon-button
|
|
108
157
|
variant="${this.shouldNotUseInverseBtnVariant() ? "ghost-secondary" : "ghost-inverse"}"
|
|
109
158
|
size="xsmall"
|
|
110
|
-
data-test-id="${
|
|
159
|
+
data-test-id="${o}-close"
|
|
111
160
|
@click="${this.closeToastComponent}">
|
|
112
161
|
<icon-close></icon-close>
|
|
113
162
|
</pie-icon-button>`;
|
|
@@ -121,9 +170,9 @@ class r extends A(y) {
|
|
|
121
170
|
*
|
|
122
171
|
* @private
|
|
123
172
|
*/
|
|
124
|
-
renderMessage(t,
|
|
125
|
-
return
|
|
126
|
-
<span style="--toast-message-max-width: ${
|
|
173
|
+
renderMessage(t, i) {
|
|
174
|
+
return l`
|
|
175
|
+
<span style="--toast-message-max-width: ${i}px" data-test-id="${o}-message">
|
|
127
176
|
${t}
|
|
128
177
|
</span>
|
|
129
178
|
`;
|
|
@@ -135,7 +184,7 @@ class r extends A(y) {
|
|
|
135
184
|
* @private
|
|
136
185
|
*/
|
|
137
186
|
closeToastComponent() {
|
|
138
|
-
this.isOpen = !1,
|
|
187
|
+
this.isOpen = !1, f(this, M, { targetNotification: this }), this.abortAndCleanEventListeners();
|
|
139
188
|
}
|
|
140
189
|
/**
|
|
141
190
|
* Util method that returns an icon from a variant that has default icon.
|
|
@@ -145,15 +194,15 @@ class r extends A(y) {
|
|
|
145
194
|
getVariantIcon() {
|
|
146
195
|
switch (this.variant) {
|
|
147
196
|
case "info":
|
|
148
|
-
return
|
|
197
|
+
return l`<icon-info-circle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-info"></icon-info-circle>`;
|
|
149
198
|
case "success":
|
|
150
|
-
return
|
|
199
|
+
return l`<icon-check-circle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-success"></icon-check-circle>`;
|
|
151
200
|
case "warning":
|
|
152
|
-
return
|
|
201
|
+
return l`<icon-alert-triangle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-warning"></icon-alert-triangle>`;
|
|
153
202
|
case "error":
|
|
154
|
-
return
|
|
203
|
+
return l`<icon-alert-circle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-error"></icon-alert-circle>`;
|
|
155
204
|
default:
|
|
156
|
-
return
|
|
205
|
+
return d;
|
|
157
206
|
}
|
|
158
207
|
}
|
|
159
208
|
/**
|
|
@@ -177,74 +226,84 @@ class r extends A(y) {
|
|
|
177
226
|
render() {
|
|
178
227
|
const {
|
|
179
228
|
isOpen: t,
|
|
180
|
-
variant:
|
|
181
|
-
message:
|
|
182
|
-
isDismissible:
|
|
183
|
-
leadingAction:
|
|
184
|
-
isMultiline:
|
|
185
|
-
isStrong:
|
|
229
|
+
variant: i,
|
|
230
|
+
message: n,
|
|
231
|
+
isDismissible: e,
|
|
232
|
+
leadingAction: r,
|
|
233
|
+
isMultiline: p,
|
|
234
|
+
isStrong: b,
|
|
186
235
|
_messageAreaMaxWidth: x
|
|
187
|
-
} = this
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
[
|
|
192
|
-
[`${
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
[`${
|
|
196
|
-
[`${a}--multiline`]: d
|
|
236
|
+
} = this, m = {
|
|
237
|
+
[s]: !0,
|
|
238
|
+
[`${s}--${i}`]: !0,
|
|
239
|
+
[`${s}--strong`]: b,
|
|
240
|
+
[`${s}--animate-in`]: t,
|
|
241
|
+
[`${s}--animate-out`]: !t
|
|
242
|
+
}, A = {
|
|
243
|
+
[`${s}-messageArea`]: !0,
|
|
244
|
+
[`${s}--multiline`]: p
|
|
197
245
|
};
|
|
198
|
-
return
|
|
199
|
-
<div
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
246
|
+
return l`
|
|
247
|
+
<div
|
|
248
|
+
data-test-id="${o}"
|
|
249
|
+
class="${$(m)}"
|
|
250
|
+
aria-live="${i === "error" ? "assertive" : "polite"}"
|
|
251
|
+
>
|
|
252
|
+
<div class="${s}-contentArea">
|
|
253
|
+
<div class="${$(A)}">
|
|
254
|
+
${this.variantHasIcon(i) ? this.getVariantIcon() : d}
|
|
255
|
+
${n === "" ? d : this.renderMessage(n, x)}
|
|
204
256
|
</div>
|
|
205
|
-
<div class="${
|
|
206
|
-
${!
|
|
207
|
-
${
|
|
257
|
+
<div class="${s}-actionsArea">
|
|
258
|
+
${!p && (r != null && r.text) ? this.renderActionButton(r) : d}
|
|
259
|
+
${e ? this.renderCloseButton() : d}
|
|
208
260
|
</div>
|
|
209
261
|
</div>
|
|
210
|
-
${
|
|
262
|
+
${p && (r != null && r.text) ? this.renderFooter() : d}
|
|
211
263
|
</div>`;
|
|
212
264
|
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
265
|
+
};
|
|
266
|
+
g.styles = w(k);
|
|
267
|
+
let a = g;
|
|
268
|
+
c([
|
|
269
|
+
u()
|
|
270
|
+
], a.prototype, "message");
|
|
271
|
+
c([
|
|
272
|
+
u({ type: Boolean })
|
|
273
|
+
], a.prototype, "isOpen");
|
|
274
|
+
c([
|
|
275
|
+
u(),
|
|
276
|
+
E(o, B, h.variant)
|
|
277
|
+
], a.prototype, "variant");
|
|
278
|
+
c([
|
|
279
|
+
u({ type: Boolean })
|
|
280
|
+
], a.prototype, "isStrong");
|
|
281
|
+
c([
|
|
282
|
+
u({ type: Boolean })
|
|
283
|
+
], a.prototype, "isDismissible");
|
|
284
|
+
c([
|
|
285
|
+
u({ type: Boolean })
|
|
286
|
+
], a.prototype, "isMultiline");
|
|
287
|
+
c([
|
|
288
|
+
u({ type: Object })
|
|
289
|
+
], a.prototype, "leadingAction");
|
|
290
|
+
c([
|
|
291
|
+
u({ type: Number })
|
|
292
|
+
], a.prototype, "duration");
|
|
293
|
+
c([
|
|
294
|
+
y("pie-button")
|
|
295
|
+
], a.prototype, "actionButton");
|
|
296
|
+
c([
|
|
297
|
+
y("pie-icon-button")
|
|
298
|
+
], a.prototype, "closeButton");
|
|
299
|
+
_(o, a);
|
|
241
300
|
export {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
301
|
+
M as ON_TOAST_CLOSE_EVENT,
|
|
302
|
+
T as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
|
|
303
|
+
I as ON_TOAST_OPEN_EVENT,
|
|
304
|
+
a as PieToast,
|
|
305
|
+
s as componentClass,
|
|
306
|
+
o as componentSelector,
|
|
307
|
+
h as defaultProps,
|
|
308
|
+
B as variants
|
|
250
309
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
|
2
2
|
import type { CSSResult } from 'lit';
|
|
3
3
|
import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
4
4
|
import type { LitElement } from 'lit';
|
|
5
|
-
import type { nothing } from 'lit';
|
|
6
5
|
import type { PropertyValues } from 'lit';
|
|
7
6
|
import * as React_2 from 'react';
|
|
8
7
|
import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
@@ -61,10 +60,27 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
|
|
|
61
60
|
isDismissible: boolean;
|
|
62
61
|
isMultiline: boolean;
|
|
63
62
|
leadingAction: ToastProps['leadingAction'];
|
|
63
|
+
duration: number | null;
|
|
64
64
|
actionButton?: HTMLElement;
|
|
65
|
+
closeButton?: HTMLElement;
|
|
65
66
|
private _actionButtonOffset;
|
|
66
67
|
private _messageAreaMaxWidth;
|
|
68
|
+
private _timeoutId;
|
|
69
|
+
private _abortController;
|
|
67
70
|
static styles: CSSResult;
|
|
71
|
+
/**
|
|
72
|
+
* Create a timeout function and set its id into a private attribute.
|
|
73
|
+
*
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
private setAutoDismiss;
|
|
77
|
+
/**
|
|
78
|
+
* If the _abortController is set, it aborts all event
|
|
79
|
+
* listeners in this controller and the controller turns into null.
|
|
80
|
+
*
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
private abortAndCleanEventListeners;
|
|
68
84
|
/**
|
|
69
85
|
* Calculates and returns the width of the message based on the toast properties.
|
|
70
86
|
*
|
|
@@ -76,9 +92,29 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
|
|
|
76
92
|
* @returns {number} - The width of the message in pixels.
|
|
77
93
|
*/
|
|
78
94
|
private getMessageMaxWidth;
|
|
95
|
+
/**
|
|
96
|
+
* Adds event listeners to the specified element for handling the auto dismiss behavior.
|
|
97
|
+
*
|
|
98
|
+
* @param {typeof this | HTMLElement | undefined} element - The element to which the listeners will be added. It can be the current instance, an HTMLElement, or undefined.
|
|
99
|
+
* @param {keyof HTMLElementEventMap} inEvent - The event type to listen for when entering the element. (e.g., 'mouseenter', 'focusin').
|
|
100
|
+
* @param {keyof HTMLElementEventMap} outEvent - The event type to listen for when leaving the element. (e.g., 'mouseleave', 'focusout').
|
|
101
|
+
* @param {AddEventListenerOptions['signal']} abortSignal - An AbortSignal that can be used to remove the event listeners.
|
|
102
|
+
*
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
private addListenersToElement;
|
|
106
|
+
/**
|
|
107
|
+
* It creates all event listeners to handle the auto-dismiss capability
|
|
108
|
+
* as well the controller responsible to remove the events when needed.
|
|
109
|
+
*
|
|
110
|
+
* @private
|
|
111
|
+
*/
|
|
112
|
+
private createAutoDismissEventListeners;
|
|
79
113
|
/**
|
|
80
114
|
* Lifecycle method executed when component is updated.
|
|
81
115
|
* It dispatches an event if toast is opened.
|
|
116
|
+
* It adds event listeners when toast is opened and if the duration is not null
|
|
117
|
+
* It aborts all event listeners when toast is closed.
|
|
82
118
|
* It calculates _messageAreaMaxWidth
|
|
83
119
|
*/
|
|
84
120
|
protected updated(_changedProperties: PropertyValues<this>): Promise<void>;
|
|
@@ -149,7 +185,7 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
|
|
|
149
185
|
* @private
|
|
150
186
|
*/
|
|
151
187
|
private shouldNotUseInverseBtnVariant;
|
|
152
|
-
render(): TemplateResult<1
|
|
188
|
+
render(): TemplateResult<1>;
|
|
153
189
|
}
|
|
154
190
|
|
|
155
191
|
declare const PieToast_base: GenericConstructor<RTLInterface> & typeof LitElement;
|
|
@@ -185,6 +221,12 @@ export declare interface ToastProps {
|
|
|
185
221
|
* The leading action for the toast.
|
|
186
222
|
*/
|
|
187
223
|
leadingAction?: ActionProps;
|
|
224
|
+
/**
|
|
225
|
+
* Sets the duration of the toast in milliseconds before it auto-dismisses.
|
|
226
|
+
* If the value is null auto-dismiss is disabled
|
|
227
|
+
* If the value is not provided it auto-dismisses after 5 seconds (5000 milliseconds)
|
|
228
|
+
*/
|
|
229
|
+
duration?: number | null;
|
|
188
230
|
}
|
|
189
231
|
|
|
190
232
|
export declare const variants: readonly ["neutral", "info", "warning", "success", "error"];
|
package/dist/react.js
CHANGED
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
import * as t from "react";
|
|
2
|
-
import { createComponent as
|
|
3
|
-
import { PieToast as
|
|
4
|
-
import { ON_TOAST_CLOSE_EVENT as
|
|
5
|
-
|
|
6
|
-
import "lit/decorators.js";
|
|
7
|
-
import "lit/directives/class-map.js";
|
|
8
|
-
import "@justeattakeaway/pie-webc-core";
|
|
9
|
-
import "@justeattakeaway/pie-icon-button";
|
|
10
|
-
import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
|
|
11
|
-
import "@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js";
|
|
12
|
-
import "@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js";
|
|
13
|
-
import "@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js";
|
|
14
|
-
import "@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js";
|
|
15
|
-
import "@justeattakeaway/pie-button";
|
|
16
|
-
const r = o({
|
|
2
|
+
import { createComponent as e } from "@lit/react";
|
|
3
|
+
import { PieToast as o } from "./index.js";
|
|
4
|
+
import { ON_TOAST_CLOSE_EVENT as n, ON_TOAST_LEADING_ACTION_CLICK_EVENT as p, ON_TOAST_OPEN_EVENT as N, componentClass as _, componentSelector as c, defaultProps as E, variants as O } from "./index.js";
|
|
5
|
+
const a = e({
|
|
17
6
|
displayName: "PieToast",
|
|
18
|
-
elementClass:
|
|
7
|
+
elementClass: o,
|
|
19
8
|
react: t,
|
|
20
9
|
tagName: "pie-toast",
|
|
21
10
|
events: {}
|
|
22
|
-
}),
|
|
11
|
+
}), r = a;
|
|
23
12
|
export {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
13
|
+
n as ON_TOAST_CLOSE_EVENT,
|
|
14
|
+
p as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
|
|
15
|
+
N as ON_TOAST_OPEN_EVENT,
|
|
16
|
+
r as PieToast,
|
|
17
|
+
_ as componentClass,
|
|
18
|
+
c as componentSelector,
|
|
19
|
+
E as defaultProps,
|
|
20
|
+
O as variants
|
|
32
21
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justeattakeaway/pie-toast",
|
|
3
3
|
"description": "PIE Design System Toast built using Web Components",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@custom-elements-manifest/analyzer": "0.9.0",
|
|
39
39
|
"@justeattakeaway/pie-components-config": "0.18.0",
|
|
40
|
-
"@justeattakeaway/pie-css": "0.
|
|
40
|
+
"@justeattakeaway/pie-css": "0.13.1",
|
|
41
41
|
"cem-plugin-module-file-extensions": "0.0.5"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@justeattakeaway/pie-button": "0.49.
|
|
45
|
-
"@justeattakeaway/pie-icon-button": "0.28.
|
|
46
|
-
"@justeattakeaway/pie-icons-webc": "0.25.
|
|
47
|
-
"@justeattakeaway/pie-webc-core": "0.24.
|
|
44
|
+
"@justeattakeaway/pie-button": "0.49.3",
|
|
45
|
+
"@justeattakeaway/pie-icon-button": "0.28.14",
|
|
46
|
+
"@justeattakeaway/pie-icons-webc": "0.25.3",
|
|
47
|
+
"@justeattakeaway/pie-webc-core": "0.24.2"
|
|
48
48
|
},
|
|
49
49
|
"volta": {
|
|
50
50
|
"extends": "../../../package.json"
|
package/src/defs-react.ts
CHANGED
package/src/defs.ts
CHANGED
|
@@ -44,6 +44,13 @@ export interface ToastProps {
|
|
|
44
44
|
* The leading action for the toast.
|
|
45
45
|
*/
|
|
46
46
|
leadingAction?: ActionProps;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Sets the duration of the toast in milliseconds before it auto-dismisses.
|
|
50
|
+
* If the value is null auto-dismiss is disabled
|
|
51
|
+
* If the value is not provided it auto-dismisses after 5 seconds (5000 milliseconds)
|
|
52
|
+
*/
|
|
53
|
+
duration?: number | null;
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
export const componentSelector = 'pie-toast';
|
|
@@ -78,4 +85,5 @@ export const defaultProps: DefaultProps = {
|
|
|
78
85
|
isStrong: false,
|
|
79
86
|
isDismissible: true,
|
|
80
87
|
isMultiline: false,
|
|
88
|
+
duration: 5000,
|
|
81
89
|
};
|
package/src/index.ts
CHANGED
|
@@ -24,10 +24,10 @@ import '@justeattakeaway/pie-button';
|
|
|
24
24
|
|
|
25
25
|
import styles from './toast.scss?inline';
|
|
26
26
|
import {
|
|
27
|
-
ToastProps,
|
|
27
|
+
type ToastProps,
|
|
28
28
|
componentSelector,
|
|
29
29
|
componentClass,
|
|
30
|
-
ActionProps,
|
|
30
|
+
type ActionProps,
|
|
31
31
|
ON_TOAST_CLOSE_EVENT,
|
|
32
32
|
ON_TOAST_OPEN_EVENT,
|
|
33
33
|
ON_TOAST_LEADING_ACTION_CLICK_EVENT,
|
|
@@ -64,15 +64,52 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
|
|
|
64
64
|
@property({ type: Object })
|
|
65
65
|
public leadingAction: ToastProps['leadingAction'];
|
|
66
66
|
|
|
67
|
+
@property({ type: Number })
|
|
68
|
+
public duration = defaultProps.duration;
|
|
69
|
+
|
|
67
70
|
@query('pie-button') actionButton?: HTMLElement;
|
|
68
71
|
|
|
72
|
+
@query('pie-icon-button') closeButton?: HTMLElement;
|
|
73
|
+
|
|
69
74
|
private _actionButtonOffset = 0;
|
|
70
75
|
|
|
71
76
|
private _messageAreaMaxWidth = 0;
|
|
72
77
|
|
|
78
|
+
private _timeoutId: NodeJS.Timeout | null = null;
|
|
79
|
+
|
|
80
|
+
private _abortController: AbortController | null = null;
|
|
81
|
+
|
|
73
82
|
// Renders a `CSSResult` generated from SCSS by Vite
|
|
74
83
|
static styles = unsafeCSS(styles);
|
|
75
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Create a timeout function and set its id into a private attribute.
|
|
87
|
+
*
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
private setAutoDismiss () {
|
|
91
|
+
if (this.duration === null) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this._timeoutId = setTimeout(() => {
|
|
96
|
+
this.closeToastComponent();
|
|
97
|
+
}, this.duration);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* If the _abortController is set, it aborts all event
|
|
102
|
+
* listeners in this controller and the controller turns into null.
|
|
103
|
+
*
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
private abortAndCleanEventListeners () {
|
|
107
|
+
if (this._abortController) {
|
|
108
|
+
this._abortController.abort();
|
|
109
|
+
this._abortController = null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
76
113
|
/**
|
|
77
114
|
* Calculates and returns the width of the message based on the toast properties.
|
|
78
115
|
*
|
|
@@ -111,16 +148,76 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
|
|
|
111
148
|
return toastMaxWidthWithoutPadding - offset;
|
|
112
149
|
}
|
|
113
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Adds event listeners to the specified element for handling the auto dismiss behavior.
|
|
153
|
+
*
|
|
154
|
+
* @param {typeof this | HTMLElement | undefined} element - The element to which the listeners will be added. It can be the current instance, an HTMLElement, or undefined.
|
|
155
|
+
* @param {keyof HTMLElementEventMap} inEvent - The event type to listen for when entering the element. (e.g., 'mouseenter', 'focusin').
|
|
156
|
+
* @param {keyof HTMLElementEventMap} outEvent - The event type to listen for when leaving the element. (e.g., 'mouseleave', 'focusout').
|
|
157
|
+
* @param {AddEventListenerOptions['signal']} abortSignal - An AbortSignal that can be used to remove the event listeners.
|
|
158
|
+
*
|
|
159
|
+
* @private
|
|
160
|
+
*/
|
|
161
|
+
private addListenersToElement (
|
|
162
|
+
element: typeof this | HTMLElement | undefined,
|
|
163
|
+
inEvent: keyof HTMLElementEventMap,
|
|
164
|
+
outEvent: keyof HTMLElementEventMap,
|
|
165
|
+
abortSignal: AddEventListenerOptions['signal'],
|
|
166
|
+
) {
|
|
167
|
+
if (element) {
|
|
168
|
+
element.addEventListener(inEvent, () => {
|
|
169
|
+
if (this._timeoutId) {
|
|
170
|
+
clearTimeout(this._timeoutId);
|
|
171
|
+
}
|
|
172
|
+
}, { signal: abortSignal });
|
|
173
|
+
element.addEventListener(outEvent, () => {
|
|
174
|
+
this.setAutoDismiss();
|
|
175
|
+
}, { signal: abortSignal });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* It creates all event listeners to handle the auto-dismiss capability
|
|
181
|
+
* as well the controller responsible to remove the events when needed.
|
|
182
|
+
*
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
private createAutoDismissEventListeners () {
|
|
186
|
+
this._abortController = new AbortController();
|
|
187
|
+
|
|
188
|
+
this.setAutoDismiss();
|
|
189
|
+
|
|
190
|
+
const { signal } = this._abortController;
|
|
191
|
+
|
|
192
|
+
this.addListenersToElement(this.actionButton, 'focus', 'focusout', signal);
|
|
193
|
+
this.addListenersToElement(this.closeButton, 'focus', 'focusout', signal);
|
|
194
|
+
this.addListenersToElement(this, 'mouseover', 'mouseout', signal);
|
|
195
|
+
}
|
|
196
|
+
|
|
114
197
|
/**
|
|
115
198
|
* Lifecycle method executed when component is updated.
|
|
116
199
|
* It dispatches an event if toast is opened.
|
|
200
|
+
* It adds event listeners when toast is opened and if the duration is not null
|
|
201
|
+
* It aborts all event listeners when toast is closed.
|
|
117
202
|
* It calculates _messageAreaMaxWidth
|
|
118
203
|
*/
|
|
119
204
|
protected async updated (_changedProperties: PropertyValues<this>) {
|
|
120
205
|
if (_changedProperties.has('isOpen') && this.isOpen) {
|
|
121
206
|
dispatchCustomEvent(this, ON_TOAST_OPEN_EVENT, { targetNotification: this });
|
|
207
|
+
|
|
208
|
+
if (this.duration !== null) {
|
|
209
|
+
this.createAutoDismissEventListeners();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (_changedProperties.has('isOpen') && !this.isOpen) {
|
|
214
|
+
this.abortAndCleanEventListeners();
|
|
122
215
|
}
|
|
123
216
|
|
|
217
|
+
// This lifecycle method is async on purpose because we
|
|
218
|
+
// need to wait for the component to complete its rendering
|
|
219
|
+
// so we can calculate _messageAreaMaxWidth based on
|
|
220
|
+
// existing components such as icons and action buttons.
|
|
124
221
|
await this.updateComplete;
|
|
125
222
|
|
|
126
223
|
if (this.actionButton) {
|
|
@@ -131,13 +228,19 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
|
|
|
131
228
|
|
|
132
229
|
this._messageAreaMaxWidth = this.getMessageMaxWidth(hasIcon, this.isMultiline, !!this.leadingAction?.text, this.isDismissible);
|
|
133
230
|
|
|
231
|
+
// It checks if there are changes on one of the properties
|
|
232
|
+
// below and requests a new update in order to repeat the
|
|
233
|
+
// lifecycle and perform new calculations.
|
|
234
|
+
// This will make sure that all components will re-render
|
|
235
|
+
// properly on Storybook.
|
|
134
236
|
if (
|
|
135
237
|
_changedProperties.has('variant') ||
|
|
136
238
|
_changedProperties.has('isStrong') ||
|
|
137
239
|
_changedProperties.has('message') ||
|
|
138
240
|
_changedProperties.has('isDismissible') ||
|
|
139
241
|
_changedProperties.has('isMultiline') ||
|
|
140
|
-
_changedProperties.has('leadingAction')
|
|
242
|
+
_changedProperties.has('leadingAction') ||
|
|
243
|
+
_changedProperties.has('duration')) {
|
|
141
244
|
this.requestUpdate();
|
|
142
245
|
}
|
|
143
246
|
}
|
|
@@ -234,6 +337,7 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
|
|
|
234
337
|
private closeToastComponent () {
|
|
235
338
|
this.isOpen = false;
|
|
236
339
|
dispatchCustomEvent(this, ON_TOAST_CLOSE_EVENT, { targetNotification: this });
|
|
340
|
+
this.abortAndCleanEventListeners();
|
|
237
341
|
}
|
|
238
342
|
|
|
239
343
|
/**
|
|
@@ -288,14 +392,12 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
|
|
|
288
392
|
_messageAreaMaxWidth,
|
|
289
393
|
} = this;
|
|
290
394
|
|
|
291
|
-
if (!isOpen) {
|
|
292
|
-
return nothing;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
395
|
const componentWrapperClasses = {
|
|
296
396
|
[componentClass]: true,
|
|
297
397
|
[`${componentClass}--${variant}`]: true,
|
|
298
398
|
[`${componentClass}--strong`]: isStrong,
|
|
399
|
+
[`${componentClass}--animate-in`]: isOpen,
|
|
400
|
+
[`${componentClass}--animate-out`]: !isOpen,
|
|
299
401
|
};
|
|
300
402
|
|
|
301
403
|
const messageAreaClasses = {
|
|
@@ -304,11 +406,15 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
|
|
|
304
406
|
};
|
|
305
407
|
|
|
306
408
|
return html`
|
|
307
|
-
<div
|
|
409
|
+
<div
|
|
410
|
+
data-test-id="${componentSelector}"
|
|
411
|
+
class="${classMap(componentWrapperClasses)}"
|
|
412
|
+
aria-live="${variant === 'error' ? 'assertive' : 'polite'}"
|
|
413
|
+
>
|
|
308
414
|
<div class="${componentClass}-contentArea">
|
|
309
415
|
<div class="${classMap(messageAreaClasses)}">
|
|
310
416
|
${this.variantHasIcon(variant) ? this.getVariantIcon() : nothing}
|
|
311
|
-
${message === '' ? nothing : this.renderMessage(message, _messageAreaMaxWidth)}
|
|
417
|
+
${message === '' ? nothing : this.renderMessage(message, _messageAreaMaxWidth)}
|
|
312
418
|
</div>
|
|
313
419
|
<div class="${componentClass}-actionsArea">
|
|
314
420
|
${!isMultiline && leadingAction?.text ? this.renderActionButton(leadingAction) : nothing}
|
package/src/react.ts
CHANGED
package/src/toast.scss
CHANGED
|
@@ -25,6 +25,24 @@
|
|
|
25
25
|
color: var(--toast-font-color);
|
|
26
26
|
font-size: var(--toast-font-size);
|
|
27
27
|
line-height: var(--toast-line-height);
|
|
28
|
+
transition-property: all;
|
|
29
|
+
transition-duration: var(--dt-motion-timing-100);
|
|
30
|
+
transition-timing-function: var(--dt-motion-easing-in);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.c-toast--animate-in {
|
|
34
|
+
animation-duration: var(--dt-motion-timing-200);
|
|
35
|
+
animation-name: animate-in;
|
|
36
|
+
animation-timing-function: var(--dt-motion-easing-in);
|
|
37
|
+
transform: translateX(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.c-toast--animate-out {
|
|
41
|
+
animation-duration: var(--dt-motion-timing-100);
|
|
42
|
+
animation-name: animate-out;
|
|
43
|
+
animation-timing-function: var(--dt-motion-easing-out);
|
|
44
|
+
transform: translateX(100%);
|
|
45
|
+
opacity: 0;
|
|
28
46
|
}
|
|
29
47
|
|
|
30
48
|
.c-toast--info {
|
|
@@ -114,3 +132,22 @@
|
|
|
114
132
|
color: var(--toast-icon-fill);
|
|
115
133
|
}
|
|
116
134
|
|
|
135
|
+
@keyframes animate-in {
|
|
136
|
+
from {
|
|
137
|
+
transform: translateX(100%);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
to {
|
|
141
|
+
transform: translateX(0);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@keyframes animate-out {
|
|
146
|
+
from {
|
|
147
|
+
transform: translateX(0);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
to {
|
|
151
|
+
transform: translateX(100%);
|
|
152
|
+
}
|
|
153
|
+
}
|