@justeattakeaway/pie-toast 0.4.5 → 0.5.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/README.md CHANGED
@@ -8,15 +8,6 @@
8
8
  </a>
9
9
  </p>
10
10
 
11
- # Table of Contents
12
-
13
- 1. [Introduction](#pie-toast)
14
- 2. [Installation](#installation)
15
- 3. [Importing the component](#importing-the-component)
16
- 4. [Peer Dependencies](#peer-dependencies)
17
- 5. [Props](#props)
18
- 6. [Contributing](#contributing)
19
-
20
11
  ## pie-toast
21
12
 
22
13
  `pie-toast` is a Web Component built using the Lit library.
@@ -29,63 +20,19 @@ This component can be easily integrated into various frontend frameworks and cus
29
20
  To install `pie-toast` in your application, run the following on your command line:
30
21
 
31
22
  ```bash
32
- # npm
33
- $ npm i @justeattakeaway/pie-toast
23
+ npm i @justeattakeaway/pie-toast
34
24
 
35
- # yarn
36
- $ yarn add @justeattakeaway/pie-toast
25
+ yarn add @justeattakeaway/pie-toast
37
26
  ```
38
27
 
39
- For full information on using PIE components as part of an application, check out the [Getting Started Guide](https://github.com/justeattakeaway/pie/wiki/Getting-started-with-PIE-Web-Components).
40
-
41
-
42
- ### Importing the component
43
-
44
- #### JavaScript
45
- ```js
46
- // Default – for Native JS Applications, Vue, Angular, Svelte, etc.
47
- import { PieToast } from '@justeattakeaway/pie-toast';
48
-
49
- // If you don't need to reference the imported object, you can simply
50
- // import the module which registers the component as a custom element.
51
- import '@justeattakeaway/pie-toast';
52
- ```
53
-
54
- #### React
55
- ```js
56
- // React
57
- // For React, you will need to import our React-specific component build
58
- // which wraps the web component using ​@lit/react
59
- import { PieToast } from '@justeattakeaway/pie-toast/dist/react';
60
- ```
28
+ ## Documentation
61
29
 
62
- > [!NOTE]
63
- > When using the React version of the component, please make sure to also
64
- > include React as a [peer dependency](#peer-dependencies) in your project.
30
+ Visit [Toast | PIE Design System](https://pie.design/components/toast) to view more information on this component.
65
31
 
32
+ ## Questions
66
33
 
67
- ## Peer Dependencies
68
-
69
- > [!IMPORTANT]
70
- > When using `pie-toast`, you will also need to include a couple of dependencies to ensure the component renders as expected. See [the PIE Wiki](https://github.com/justeattakeaway/pie/wiki/Getting-started-with-PIE-Web-Components#expected-dependencies) for more information and how to include these in your application.
71
-
72
-
73
- ## Props
74
-
75
- | Property | Type | Default | Description |
76
- |---|---|---|---|
77
- | - | - | - | - |
78
-
79
- In your markup or JSX, you can then use these to set the properties for the `pie-toast` component:
80
-
81
- ```html
82
- <!-- Native HTML -->
83
- <pie-toast></pie-toast>
84
-
85
- <!-- JSX -->
86
- <PieToast></PieToast>
87
- ```
34
+ Please head to [FAQs | PIE Design System](https://pie.design/support/contact-us/) to see our FAQs and get in touch.
88
35
 
89
36
  ## Contributing
90
37
 
91
- Check out our [contributing guide](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide) for more information on [local development](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#local-development) and how to run specific [component tests](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#testing).
38
+ Check out our [contributing guide](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide) for more information on [local development](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#local-development) and how to run specific [component tests](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#testing).
@@ -198,24 +198,6 @@
198
198
  },
199
199
  "privacy": "private"
200
200
  },
201
- {
202
- "kind": "field",
203
- "name": "_actionButtonOffset",
204
- "type": {
205
- "text": "number"
206
- },
207
- "privacy": "private",
208
- "default": "0"
209
- },
210
- {
211
- "kind": "field",
212
- "name": "_messageAreaMaxWidth",
213
- "type": {
214
- "text": "number"
215
- },
216
- "privacy": "private",
217
- "default": "0"
218
- },
219
201
  {
220
202
  "kind": "field",
221
203
  "name": "_timeoutId",
@@ -246,47 +228,6 @@
246
228
  "privacy": "private",
247
229
  "description": "If the _abortController is set, it aborts all event\nlisteners in this controller and the controller turns into null."
248
230
  },
249
- {
250
- "kind": "method",
251
- "name": "getMessageMaxWidth",
252
- "privacy": "private",
253
- "return": {
254
- "type": {
255
- "text": "number"
256
- }
257
- },
258
- "parameters": [
259
- {
260
- "name": "hasIcon",
261
- "type": {
262
- "text": "boolean"
263
- },
264
- "description": "Indicates if the toast has an icon."
265
- },
266
- {
267
- "name": "isMultiline",
268
- "type": {
269
- "text": "boolean"
270
- },
271
- "description": "Indicates if the message is multiline."
272
- },
273
- {
274
- "name": "hasActionButton",
275
- "type": {
276
- "text": "boolean"
277
- },
278
- "description": "Indicates if the toast has an action button."
279
- },
280
- {
281
- "name": "hasCloseIcon",
282
- "type": {
283
- "text": "boolean"
284
- },
285
- "description": "Indicates if the toast has a close icon."
286
- }
287
- ],
288
- "description": "Calculates and returns the width of the message based on the toast properties."
289
- },
290
231
  {
291
232
  "kind": "method",
292
233
  "name": "addListenersToElement",
@@ -388,13 +329,6 @@
388
329
  "text": "string"
389
330
  },
390
331
  "description": "The message to be displayed."
391
- },
392
- {
393
- "name": "messageAreaMaxWidth",
394
- "type": {
395
- "text": "number"
396
- },
397
- "description": "The maximum width of the message area calculated in the lifecycle method."
398
332
  }
399
333
  ],
400
334
  "description": "Template for the toast message. Called within the\nmain render function."
@@ -433,6 +367,29 @@
433
367
  "description": "util method that returns true if the variant is warning and is strong."
434
368
  }
435
369
  ],
370
+ "events": [
371
+ {
372
+ "type": {
373
+ "text": "CustomEvent"
374
+ },
375
+ "description": "when a user clicks close button or when the toast auto dismiss.",
376
+ "name": "pie-toast-close"
377
+ },
378
+ {
379
+ "type": {
380
+ "text": "CustomEvent"
381
+ },
382
+ "description": "when the toast is opened.",
383
+ "name": "pie-toast-open"
384
+ },
385
+ {
386
+ "type": {
387
+ "text": "CustomEvent"
388
+ },
389
+ "description": "when the user interacts with the leading action.",
390
+ "name": "pie-toast-leading-action-click"
391
+ }
392
+ ],
436
393
  "attributes": [
437
394
  {
438
395
  "name": "message",
package/dist/index.d.ts CHANGED
@@ -48,6 +48,9 @@ export declare const ON_TOAST_OPEN_EVENT: string;
48
48
 
49
49
  /**
50
50
  * @tagname pie-toast
51
+ * @event {CustomEvent} pie-toast-close - when a user clicks close button or when the toast auto dismiss.
52
+ * @event {CustomEvent} pie-toast-open - when the toast is opened.
53
+ * @event {CustomEvent} pie-toast-leading-action-click - when the user interacts with the leading action.
51
54
  */
52
55
  export declare class PieToast extends PieToast_base implements ToastProps {
53
56
  message: string;
@@ -60,8 +63,6 @@ export declare class PieToast extends PieToast_base implements ToastProps {
60
63
  duration: number | null;
61
64
  private actionButton?;
62
65
  private closeButton?;
63
- private _actionButtonOffset;
64
- private _messageAreaMaxWidth;
65
66
  private _timeoutId;
66
67
  private _abortController;
67
68
  static styles: CSSResult;
@@ -78,17 +79,6 @@ export declare class PieToast extends PieToast_base implements ToastProps {
78
79
  * @private
79
80
  */
80
81
  private abortAndCleanEventListeners;
81
- /**
82
- * Calculates and returns the width of the message based on the toast properties.
83
- *
84
- * @param {boolean} hasIcon - Indicates if the toast has an icon.
85
- * @param {boolean} isMultiline - Indicates if the message is multiline.
86
- * @param {boolean} hasActionButton - Indicates if the toast has an action button.
87
- * @param {boolean} hasCloseIcon - Indicates if the toast has a close icon.
88
- *
89
- * @returns {number} - The width of the message in pixels.
90
- */
91
- private getMessageMaxWidth;
92
82
  /**
93
83
  * Adds event listeners to the specified element for handling the auto dismiss behavior.
94
84
  *
@@ -112,7 +102,6 @@ export declare class PieToast extends PieToast_base implements ToastProps {
112
102
  * It dispatches an event if toast is opened.
113
103
  * It adds event listeners when toast is opened and if the duration is not null
114
104
  * It aborts all event listeners when toast is closed.
115
- * It calculates _messageAreaMaxWidth
116
105
  */
117
106
  protected updated(_changedProperties: PropertyValues<this>): Promise<void>;
118
107
  /**
@@ -150,7 +139,6 @@ export declare class PieToast extends PieToast_base implements ToastProps {
150
139
  * main render function.
151
140
  *
152
141
  * @param {string} message - The message to be displayed.
153
- * @param {number} messageAreaMaxWidth - The maximum width of the message area calculated in the lifecycle method.
154
142
  *
155
143
  * @private
156
144
  */
@@ -209,7 +197,7 @@ export declare interface ToastProps {
209
197
  */
210
198
  message: string;
211
199
  /**
212
- * It allows the message content being displayed as multiline limited to three rows.
200
+ * Allows the message content to be displayed as multiline, limited to three rows.
213
201
  */
214
202
  isMultiline?: boolean;
215
203
  /**
@@ -219,7 +207,7 @@ export declare interface ToastProps {
219
207
  /**
220
208
  * Sets the duration of the toast in milliseconds before it auto-dismisses.
221
209
  * If the value is null auto-dismiss is disabled
222
- * If the value is not provided it auto-dismisses after 5 seconds (5000 milliseconds)
210
+ * If the value is not provided it auto-dismisses after 5 seconds
223
211
  */
224
212
  duration?: number | null;
225
213
  }
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
- import { LitElement as C, unsafeCSS as w, html as l, nothing as d } from "lit";
2
- import { property as p, 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";
1
+ import { LitElement as x, unsafeCSS as A, html as c, nothing as l } from "lit";
2
+ import { property as p, query as g } from "lit/decorators.js";
3
+ import { classMap as C } from "lit/directives/class-map.js";
4
+ import { RtlMixin as w, dispatchCustomEvent as v, validPropertyValues as k, defineCustomElement as E } from "@justeattakeaway/pie-webc-core";
5
5
  import "@justeattakeaway/pie-icon-button";
6
+ import "@justeattakeaway/pie-button";
6
7
  import "@justeattakeaway/pie-icons-webc/dist/IconClose.js";
7
8
  import "@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js";
8
9
  import "@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js";
9
10
  import "@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js";
10
11
  import "@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js";
11
- import "@justeattakeaway/pie-button";
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`, u = {
12
+ const _ = "*,*: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-offset: var(--dt-spacing-d);--toast-translate-start: -100%;--toast-translate-end: 0;position:absolute;inset-inline-start:var(--toast-offset);inset-block-end:var(--toast-offset);display:flex;flex-direction:column;justify-content:center;min-height:48px;max-height:122px;min-width:300px;max-width:420px;padding:var(--dt-spacing-b) var(--dt-spacing-c) var(--dt-spacing-b) var(--dt-spacing-d);border-radius:var(--toast-border-radius);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)}@media (min-width: 769px){.c-toast{--toast-offset: var(--dt-spacing-e)}}.c-toast--rtl{--toast-translate-start: 100%}.c-toast--animate-in{animation-duration:var(--dt-motion-timing-200);animation-name:animate-in;animation-timing-function:var(--dt-motion-easing-out);transform:translate(var(--toast-translate-end))}.c-toast--animate-out{animation-duration:var(--dt-motion-timing-100);animation-name:animate-out;animation-timing-function:var(--dt-motion-easing-in);transform:translate(var(--toast-translate-start));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:6px var(--dt-spacing-a) 6px 0;overflow:hidden}.c-toast-messageArea span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.c-toast-actionsArea{display:flex;gap:var(--dt-spacing-b);flex-shrink:0}.c-toast--multiline .c-toast-contentArea{align-items:flex-start;gap:0}.c-toast--multiline .c-toast-messageArea{align-items:flex-start;padding-block-end:var(--dt-spacing-b)}.c-toast--multiline .c-toast-messageArea span{max-height:60px;white-space:inherit;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.c-toast-footer{display:flex;justify-content:flex-end}.c-toast-icon{color:var(--toast-icon-fill)}@keyframes animate-in{0%{transform:translate(var(--toast-translate-start))}to{transform:translate(var(--toast-translate-end))}}@keyframes animate-out{0%{transform:translate(var(--toast-translate-end))}to{transform:translate(var(--toast-translate-start))}}", O = ["neutral", "info", "warning", "success", "error"], s = "pie-toast", o = "c-toast", T = `${s}-close`, L = `${s}-open`, B = `${s}-leading-action-click`, d = {
13
13
  message: "",
14
14
  isOpen: !0,
15
15
  variant: "neutral",
@@ -18,14 +18,14 @@ const k = "*,*:after,*:before{box-sizing:inherit}.c-toast{--toast-border-radius:
18
18
  isMultiline: !1,
19
19
  duration: 5e3
20
20
  };
21
- var L = Object.defineProperty, c = (v, t, i, n) => {
22
- for (var e = void 0, r = v.length - 1, h; r >= 0; r--)
23
- (h = v[r]) && (e = h(t, i, e) || e);
24
- return e && L(t, i, e), e;
21
+ var N = Object.defineProperty, r = (f, t, n, u) => {
22
+ for (var e = void 0, a = f.length - 1, m; a >= 0; a--)
23
+ (m = f[a]) && (e = m(t, n, e) || e);
24
+ return e && N(t, n, e), e;
25
25
  };
26
- const g = class g extends O(C) {
26
+ const h = class h extends w(x) {
27
27
  constructor() {
28
- super(...arguments), this.message = u.message, this.isOpen = u.isOpen, this.variant = u.variant, this.isStrong = u.isStrong, this.isDismissible = u.isDismissible, this.isMultiline = u.isMultiline, this.duration = u.duration, this._actionButtonOffset = 0, this._messageAreaMaxWidth = 0, this._timeoutId = null, this._abortController = null;
28
+ super(...arguments), this.message = d.message, this.isOpen = d.isOpen, this.variant = d.variant, this.isStrong = d.isStrong, this.isDismissible = d.isDismissible, this.isMultiline = d.isMultiline, this.duration = d.duration, this._timeoutId = null, this._abortController = null;
29
29
  }
30
30
  /**
31
31
  * Create a timeout function and set its id into a private attribute.
@@ -46,20 +46,6 @@ const g = class g extends O(C) {
46
46
  abortAndCleanEventListeners() {
47
47
  this._abortController && (this._abortController.abort(), this._abortController = null);
48
48
  }
49
- /**
50
- * Calculates and returns the width of the message based on the toast properties.
51
- *
52
- * @param {boolean} hasIcon - Indicates if the toast has an icon.
53
- * @param {boolean} isMultiline - Indicates if the message is multiline.
54
- * @param {boolean} hasActionButton - Indicates if the toast has an action button.
55
- * @param {boolean} hasCloseIcon - Indicates if the toast has a close icon.
56
- *
57
- * @returns {number} - The width of the message in pixels.
58
- */
59
- getMessageMaxWidth(t, i, n, e) {
60
- let m = 0;
61
- return t && (m += 28), !i && n && (m += this._actionButtonOffset + 8), e && (m += 40), 392 - m;
62
- }
63
49
  /**
64
50
  * Adds event listeners to the specified element for handling the auto dismiss behavior.
65
51
  *
@@ -70,10 +56,10 @@ const g = class g extends O(C) {
70
56
  *
71
57
  * @private
72
58
  */
73
- addListenersToElement(t, i, n, e) {
74
- t && (t.addEventListener(i, () => {
59
+ addListenersToElement(t, n, u, e) {
60
+ t && (t.addEventListener(n, () => {
75
61
  this._timeoutId && clearTimeout(this._timeoutId);
76
- }, { signal: e }), t.addEventListener(n, () => {
62
+ }, { signal: e }), t.addEventListener(u, () => {
77
63
  this.setAutoDismiss();
78
64
  }, { signal: e }));
79
65
  }
@@ -93,13 +79,9 @@ const g = class g extends O(C) {
93
79
  * It dispatches an event if toast is opened.
94
80
  * It adds event listeners when toast is opened and if the duration is not null
95
81
  * It aborts all event listeners when toast is closed.
96
- * It calculates _messageAreaMaxWidth
97
82
  */
98
83
  async updated(t) {
99
- var n;
100
- 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);
101
- const i = this.variantHasIcon(this.variant);
102
- 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();
84
+ t.has("isOpen") && this.isOpen && (v(this, L, { targetNotification: this }), this.duration !== null && this.createAutoDismissEventListeners()), t.has("isOpen") && !this.isOpen && this.abortAndCleanEventListeners();
103
85
  }
104
86
  /**
105
87
  * It handle the action button action.
@@ -107,7 +89,7 @@ const g = class g extends O(C) {
107
89
  * @private
108
90
  */
109
91
  handleActionClick() {
110
- f(this, T, { targetNotification: this });
92
+ v(this, B, { targetNotification: this });
111
93
  }
112
94
  /**
113
95
  * Render the action button depending on action type and its action.
@@ -118,16 +100,16 @@ const g = class g extends O(C) {
118
100
  * @private
119
101
  */
120
102
  renderActionButton(t) {
121
- const { text: i, ariaLabel: n } = t;
122
- return l`
103
+ const { text: n, ariaLabel: u } = t;
104
+ return c`
123
105
  <pie-button
124
106
  variant="${this.shouldNotUseInverseBtnVariant() ? "ghost" : "ghost-inverse"}"
125
107
  size="xsmall"
126
- aria-label="${n || d}"
108
+ aria-label="${u || l}"
127
109
  @click="${() => this.handleActionClick()}"
128
- data-test-id="${o}-leading-action"
110
+ data-test-id="${s}-leading-action"
129
111
  type="button">
130
- ${i}
112
+ ${n}
131
113
  </pie-button>
132
114
  `;
133
115
  }
@@ -140,9 +122,9 @@ const g = class g extends O(C) {
140
122
  */
141
123
  renderFooter() {
142
124
  const { leadingAction: t } = this;
143
- return l`
144
- <footer class="${s}-footer" data-test-id="${o}-footer" >
145
- ${t ? this.renderActionButton(t) : d}
125
+ return c`
126
+ <footer class="${o}-footer" data-test-id="${s}-footer" >
127
+ ${t ? this.renderActionButton(t) : l}
146
128
  </footer>
147
129
  `;
148
130
  }
@@ -153,11 +135,11 @@ const g = class g extends O(C) {
153
135
  * @private
154
136
  */
155
137
  renderCloseButton() {
156
- return l`
138
+ return c`
157
139
  <pie-icon-button
158
140
  variant="${this.shouldNotUseInverseBtnVariant() ? "ghost-secondary" : "ghost-inverse"}"
159
141
  size="xsmall"
160
- data-test-id="${o}-close"
142
+ data-test-id="${s}-close"
161
143
  @click="${this.closeToastComponent}">
162
144
  <icon-close></icon-close>
163
145
  </pie-icon-button>`;
@@ -167,13 +149,12 @@ const g = class g extends O(C) {
167
149
  * main render function.
168
150
  *
169
151
  * @param {string} message - The message to be displayed.
170
- * @param {number} messageAreaMaxWidth - The maximum width of the message area calculated in the lifecycle method.
171
152
  *
172
153
  * @private
173
154
  */
174
- renderMessage(t, i) {
175
- return l`
176
- <span style="--toast-message-max-width: ${i}px" data-test-id="${o}-message">
155
+ renderMessage(t) {
156
+ return c`
157
+ <span data-test-id="${s}-message">
177
158
  ${t}
178
159
  </span>
179
160
  `;
@@ -185,7 +166,7 @@ const g = class g extends O(C) {
185
166
  * @private
186
167
  */
187
168
  closeToastComponent() {
188
- this.isOpen = !1, f(this, M, { targetNotification: this }), this.abortAndCleanEventListeners();
169
+ this.isOpen = !1, v(this, T, { targetNotification: this }), this.abortAndCleanEventListeners();
189
170
  }
190
171
  /**
191
172
  * Util method that returns an icon from a variant that has default icon.
@@ -195,15 +176,15 @@ const g = class g extends O(C) {
195
176
  getVariantIcon() {
196
177
  switch (this.variant) {
197
178
  case "info":
198
- return l`<icon-info-circle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-info"></icon-info-circle>`;
179
+ return c`<icon-info-circle class="${o}-icon" size="s" data-test-id="${s}-heading-icon-info"></icon-info-circle>`;
199
180
  case "success":
200
- return l`<icon-check-circle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-success"></icon-check-circle>`;
181
+ return c`<icon-check-circle class="${o}-icon" size="s" data-test-id="${s}-heading-icon-success"></icon-check-circle>`;
201
182
  case "warning":
202
- return l`<icon-alert-triangle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-warning"></icon-alert-triangle>`;
183
+ return c`<icon-alert-triangle class="${o}-icon" size="s" data-test-id="${s}-heading-icon-warning"></icon-alert-triangle>`;
203
184
  case "error":
204
- return l`<icon-alert-circle class="${s}-icon" size="s" data-test-id="${o}-heading-icon-error"></icon-alert-circle>`;
185
+ return c`<icon-alert-circle class="${o}-icon" size="s" data-test-id="${s}-heading-icon-error"></icon-alert-circle>`;
205
186
  default:
206
- return d;
187
+ return l;
207
188
  }
208
189
  }
209
190
  /**
@@ -227,83 +208,82 @@ const g = class g extends O(C) {
227
208
  render() {
228
209
  const {
229
210
  isOpen: t,
230
- variant: i,
231
- message: n,
211
+ variant: n,
212
+ message: u,
232
213
  isDismissible: e,
233
- leadingAction: r,
234
- isMultiline: h,
214
+ leadingAction: a,
215
+ isMultiline: m,
235
216
  isStrong: b,
236
- _messageAreaMaxWidth: x
237
- } = this, m = {
238
- [s]: !0,
239
- [`${s}--${i}`]: !0,
240
- [`${s}--strong`]: b,
241
- [`${s}--animate-in`]: t,
242
- [`${s}--animate-out`]: !t
243
- }, A = {
244
- [`${s}-messageArea`]: !0,
245
- [`${s}--multiline`]: h
217
+ isRTL: $
218
+ } = this, y = {
219
+ [o]: !0,
220
+ [`${o}--rtl`]: $,
221
+ [`${o}--multiline`]: m,
222
+ [`${o}--${n}`]: !0,
223
+ [`${o}--strong`]: b,
224
+ [`${o}--animate-in`]: t,
225
+ [`${o}--animate-out`]: !t
246
226
  };
247
- return l`
227
+ return c`
248
228
  <div
249
- role="${i === "error" ? "alert" : "status"}"
250
- data-test-id="${o}"
251
- class="${$(m)}">
252
- <div class="${s}-contentArea">
253
- <div class="${$(A)}">
254
- ${this.variantHasIcon(i) ? this.getVariantIcon() : d}
255
- ${n === "" ? d : this.renderMessage(n, x)}
229
+ role="${n === "error" ? "alert" : "status"}"
230
+ data-test-id="${s}"
231
+ class="${C(y)}">
232
+ <div class="${o}-contentArea">
233
+ <div class="${o}-messageArea">
234
+ ${this.variantHasIcon(n) ? this.getVariantIcon() : l}
235
+ ${u === "" ? l : this.renderMessage(u)}
256
236
  </div>
257
- <div class="${s}-actionsArea">
258
- ${!h && (r != null && r.text) ? this.renderActionButton(r) : d}
259
- ${e ? this.renderCloseButton() : d}
237
+ <div class="${o}-actionsArea">
238
+ ${!m && (a != null && a.text) ? this.renderActionButton(a) : l}
239
+ ${e ? this.renderCloseButton() : l}
260
240
  </div>
261
241
  </div>
262
- ${h && (r != null && r.text) ? this.renderFooter() : d}
242
+ ${m && (a != null && a.text) ? this.renderFooter() : l}
263
243
  </div>`;
264
244
  }
265
245
  };
266
- g.styles = w(k);
267
- let a = g;
268
- c([
246
+ h.styles = A(_);
247
+ let i = h;
248
+ r([
269
249
  p({ type: String })
270
- ], a.prototype, "message");
271
- c([
250
+ ], i.prototype, "message");
251
+ r([
272
252
  p({ type: Boolean })
273
- ], a.prototype, "isOpen");
274
- c([
253
+ ], i.prototype, "isOpen");
254
+ r([
275
255
  p({ type: String }),
276
- E(o, B, u.variant)
277
- ], a.prototype, "variant");
278
- c([
256
+ k(s, O, d.variant)
257
+ ], i.prototype, "variant");
258
+ r([
279
259
  p({ type: Boolean })
280
- ], a.prototype, "isStrong");
281
- c([
260
+ ], i.prototype, "isStrong");
261
+ r([
282
262
  p({ type: Boolean })
283
- ], a.prototype, "isDismissible");
284
- c([
263
+ ], i.prototype, "isDismissible");
264
+ r([
285
265
  p({ type: Boolean })
286
- ], a.prototype, "isMultiline");
287
- c([
266
+ ], i.prototype, "isMultiline");
267
+ r([
288
268
  p({ type: Object })
289
- ], a.prototype, "leadingAction");
290
- c([
269
+ ], i.prototype, "leadingAction");
270
+ r([
291
271
  p({ 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);
272
+ ], i.prototype, "duration");
273
+ r([
274
+ g("pie-button")
275
+ ], i.prototype, "actionButton");
276
+ r([
277
+ g("pie-icon-button")
278
+ ], i.prototype, "closeButton");
279
+ E(s, i);
300
280
  export {
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
- u as defaultProps,
308
- B as variants
281
+ T as ON_TOAST_CLOSE_EVENT,
282
+ B as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
283
+ L as ON_TOAST_OPEN_EVENT,
284
+ i as PieToast,
285
+ o as componentClass,
286
+ s as componentSelector,
287
+ d as defaultProps,
288
+ O as variants
309
289
  };
package/dist/react.d.ts CHANGED
@@ -47,10 +47,13 @@ export declare const ON_TOAST_LEADING_ACTION_CLICK_EVENT: string;
47
47
  */
48
48
  export declare const ON_TOAST_OPEN_EVENT: string;
49
49
 
50
- export declare const PieToast: React_2.ForwardRefExoticComponent<ToastProps & React_2.RefAttributes<PieToast_2> & ReactBaseType>;
50
+ export declare const PieToast: React_2.ForwardRefExoticComponent<ToastProps & React_2.RefAttributes<PieToast_2> & PieToastEvents & ReactBaseType>;
51
51
 
52
52
  /**
53
53
  * @tagname pie-toast
54
+ * @event {CustomEvent} pie-toast-close - when a user clicks close button or when the toast auto dismiss.
55
+ * @event {CustomEvent} pie-toast-open - when the toast is opened.
56
+ * @event {CustomEvent} pie-toast-leading-action-click - when the user interacts with the leading action.
54
57
  */
55
58
  declare class PieToast_2 extends PieToast_base implements ToastProps {
56
59
  message: string;
@@ -63,8 +66,6 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
63
66
  duration: number | null;
64
67
  private actionButton?;
65
68
  private closeButton?;
66
- private _actionButtonOffset;
67
- private _messageAreaMaxWidth;
68
69
  private _timeoutId;
69
70
  private _abortController;
70
71
  static styles: CSSResult;
@@ -81,17 +82,6 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
81
82
  * @private
82
83
  */
83
84
  private abortAndCleanEventListeners;
84
- /**
85
- * Calculates and returns the width of the message based on the toast properties.
86
- *
87
- * @param {boolean} hasIcon - Indicates if the toast has an icon.
88
- * @param {boolean} isMultiline - Indicates if the message is multiline.
89
- * @param {boolean} hasActionButton - Indicates if the toast has an action button.
90
- * @param {boolean} hasCloseIcon - Indicates if the toast has a close icon.
91
- *
92
- * @returns {number} - The width of the message in pixels.
93
- */
94
- private getMessageMaxWidth;
95
85
  /**
96
86
  * Adds event listeners to the specified element for handling the auto dismiss behavior.
97
87
  *
@@ -115,7 +105,6 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
115
105
  * It dispatches an event if toast is opened.
116
106
  * It adds event listeners when toast is opened and if the duration is not null
117
107
  * It aborts all event listeners when toast is closed.
118
- * It calculates _messageAreaMaxWidth
119
108
  */
120
109
  protected updated(_changedProperties: PropertyValues<this>): Promise<void>;
121
110
  /**
@@ -153,7 +142,6 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
153
142
  * main render function.
154
143
  *
155
144
  * @param {string} message - The message to be displayed.
156
- * @param {number} messageAreaMaxWidth - The maximum width of the message area calculated in the lifecycle method.
157
145
  *
158
146
  * @private
159
147
  */
@@ -190,6 +178,12 @@ declare class PieToast_2 extends PieToast_base implements ToastProps {
190
178
 
191
179
  declare const PieToast_base: GenericConstructor<RTLInterface> & typeof LitElement;
192
180
 
181
+ declare type PieToastEvents = {
182
+ onPieToastClose?: (event: CustomEvent) => void;
183
+ onPieToastOpen?: (event: CustomEvent) => void;
184
+ onPieToastLeadingActionClick?: (event: CustomEvent) => void;
185
+ };
186
+
193
187
  declare type ReactBaseType = React_2.HTMLAttributes<HTMLElement>;
194
188
 
195
189
  export declare interface ToastProps {
@@ -214,7 +208,7 @@ export declare interface ToastProps {
214
208
  */
215
209
  message: string;
216
210
  /**
217
- * It allows the message content being displayed as multiline limited to three rows.
211
+ * Allows the message content to be displayed as multiline, limited to three rows.
218
212
  */
219
213
  isMultiline?: boolean;
220
214
  /**
@@ -224,7 +218,7 @@ export declare interface ToastProps {
224
218
  /**
225
219
  * Sets the duration of the toast in milliseconds before it auto-dismisses.
226
220
  * If the value is null auto-dismiss is disabled
227
- * If the value is not provided it auto-dismisses after 5 seconds (5000 milliseconds)
221
+ * If the value is not provided it auto-dismisses after 5 seconds
228
222
  */
229
223
  duration?: number | null;
230
224
  }
package/dist/react.js CHANGED
@@ -1,21 +1,28 @@
1
- import * as t from "react";
1
+ import * as o from "react";
2
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";
3
+ import { PieToast as t } from "./index.js";
4
+ import { ON_TOAST_CLOSE_EVENT as c, ON_TOAST_LEADING_ACTION_CLICK_EVENT as r, ON_TOAST_OPEN_EVENT as m, componentClass as l, componentSelector as N, defaultProps as _, variants as O } from "./index.js";
5
5
  const a = e({
6
6
  displayName: "PieToast",
7
- elementClass: o,
8
- react: t,
7
+ elementClass: t,
8
+ react: o,
9
9
  tagName: "pie-toast",
10
- events: {}
11
- }), r = a;
10
+ events: {
11
+ onPieToastClose: "pie-toast-close",
12
+ // when a user clicks close button or when the toast auto dismiss.
13
+ onPieToastOpen: "pie-toast-open",
14
+ // when the toast is opened.
15
+ onPieToastLeadingActionClick: "pie-toast-leading-action-click"
16
+ // when the user interacts with the leading action.
17
+ }
18
+ }), n = a;
12
19
  export {
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
+ c as ON_TOAST_CLOSE_EVENT,
21
+ r as ON_TOAST_LEADING_ACTION_CLICK_EVENT,
22
+ m as ON_TOAST_OPEN_EVENT,
23
+ n as PieToast,
24
+ l as componentClass,
25
+ N as componentSelector,
26
+ _ as defaultProps,
20
27
  O as variants
21
28
  };
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.5",
4
+ "version": "0.5.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
package/src/defs.ts CHANGED
@@ -37,7 +37,7 @@ export interface ToastProps {
37
37
  */
38
38
  message: string;
39
39
  /**
40
- * It allows the message content being displayed as multiline limited to three rows.
40
+ * Allows the message content to be displayed as multiline, limited to three rows.
41
41
  */
42
42
  isMultiline?: boolean;
43
43
  /**
@@ -48,7 +48,7 @@ export interface ToastProps {
48
48
  /**
49
49
  * Sets the duration of the toast in milliseconds before it auto-dismisses.
50
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)
51
+ * If the value is not provided it auto-dismisses after 5 seconds
52
52
  */
53
53
  duration?: number | null;
54
54
  }
package/src/index.ts CHANGED
@@ -15,24 +15,24 @@ import {
15
15
  validPropertyValues,
16
16
  } from '@justeattakeaway/pie-webc-core';
17
17
  import '@justeattakeaway/pie-icon-button';
18
+ import '@justeattakeaway/pie-button';
18
19
  import '@justeattakeaway/pie-icons-webc/dist/IconClose.js';
19
20
  import '@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js';
20
21
  import '@justeattakeaway/pie-icons-webc/dist/IconAlertCircle.js';
21
22
  import '@justeattakeaway/pie-icons-webc/dist/IconAlertTriangle.js';
22
23
  import '@justeattakeaway/pie-icons-webc/dist/IconCheckCircle.js';
23
- import '@justeattakeaway/pie-button';
24
24
 
25
25
  import styles from './toast.scss?inline';
26
26
  import {
27
- type ToastProps,
28
27
  componentSelector,
29
28
  componentClass,
30
- type ActionProps,
29
+ defaultProps,
30
+ variants,
31
31
  ON_TOAST_CLOSE_EVENT,
32
32
  ON_TOAST_OPEN_EVENT,
33
33
  ON_TOAST_LEADING_ACTION_CLICK_EVENT,
34
- defaultProps,
35
- variants,
34
+ type ToastProps,
35
+ type ActionProps,
36
36
  } from './defs';
37
37
 
38
38
  // Valid values available to consumers
@@ -40,6 +40,9 @@ export * from './defs';
40
40
 
41
41
  /**
42
42
  * @tagname pie-toast
43
+ * @event {CustomEvent} pie-toast-close - when a user clicks close button or when the toast auto dismiss.
44
+ * @event {CustomEvent} pie-toast-open - when the toast is opened.
45
+ * @event {CustomEvent} pie-toast-leading-action-click - when the user interacts with the leading action.
43
46
  */
44
47
  export class PieToast extends RtlMixin(LitElement) implements ToastProps {
45
48
  @property({ type: String })
@@ -73,10 +76,6 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
73
76
  @query('pie-icon-button')
74
77
  private closeButton?: HTMLElement;
75
78
 
76
- private _actionButtonOffset = 0;
77
-
78
- private _messageAreaMaxWidth = 0;
79
-
80
79
  private _timeoutId: NodeJS.Timeout | null = null;
81
80
 
82
81
  private _abortController: AbortController | null = null;
@@ -112,44 +111,6 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
112
111
  }
113
112
  }
114
113
 
115
- /**
116
- * Calculates and returns the width of the message based on the toast properties.
117
- *
118
- * @param {boolean} hasIcon - Indicates if the toast has an icon.
119
- * @param {boolean} isMultiline - Indicates if the message is multiline.
120
- * @param {boolean} hasActionButton - Indicates if the toast has an action button.
121
- * @param {boolean} hasCloseIcon - Indicates if the toast has a close icon.
122
- *
123
- * @returns {number} - The width of the message in pixels.
124
- */
125
- private getMessageMaxWidth (
126
- hasIcon: boolean,
127
- isMultiline: boolean,
128
- hasActionButton: boolean,
129
- hasCloseIcon: boolean,
130
- ): number {
131
- const iconOffset = 20;
132
- const closeIconOffset = 32;
133
- const gap = 8;
134
- const toastMaxWidthWithoutPadding = 392;
135
-
136
- let offset = 0;
137
-
138
- if (hasIcon) {
139
- offset += iconOffset + gap;
140
- }
141
-
142
- if (!isMultiline && hasActionButton) {
143
- offset += this._actionButtonOffset + gap;
144
- }
145
-
146
- if (hasCloseIcon) {
147
- offset += closeIconOffset + gap;
148
- }
149
-
150
- return toastMaxWidthWithoutPadding - offset;
151
- }
152
-
153
114
  /**
154
115
  * Adds event listeners to the specified element for handling the auto dismiss behavior.
155
116
  *
@@ -201,7 +162,6 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
201
162
  * It dispatches an event if toast is opened.
202
163
  * It adds event listeners when toast is opened and if the duration is not null
203
164
  * It aborts all event listeners when toast is closed.
204
- * It calculates _messageAreaMaxWidth
205
165
  */
206
166
  protected async updated (_changedProperties: PropertyValues<this>) {
207
167
  if (_changedProperties.has('isOpen') && this.isOpen) {
@@ -215,36 +175,6 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
215
175
  if (_changedProperties.has('isOpen') && !this.isOpen) {
216
176
  this.abortAndCleanEventListeners();
217
177
  }
218
-
219
- // This lifecycle method is async on purpose because we
220
- // need to wait for the component to complete its rendering
221
- // so we can calculate _messageAreaMaxWidth based on
222
- // existing components such as icons and action buttons.
223
- await this.updateComplete;
224
-
225
- if (this.actionButton) {
226
- this._actionButtonOffset = this.actionButton.offsetWidth;
227
- }
228
-
229
- const hasIcon = this.variantHasIcon(this.variant);
230
-
231
- this._messageAreaMaxWidth = this.getMessageMaxWidth(hasIcon, this.isMultiline, !!this.leadingAction?.text, this.isDismissible);
232
-
233
- // It checks if there are changes on one of the properties
234
- // below and requests a new update in order to repeat the
235
- // lifecycle and perform new calculations.
236
- // This will make sure that all components will re-render
237
- // properly on Storybook.
238
- if (
239
- _changedProperties.has('variant') ||
240
- _changedProperties.has('isStrong') ||
241
- _changedProperties.has('message') ||
242
- _changedProperties.has('isDismissible') ||
243
- _changedProperties.has('isMultiline') ||
244
- _changedProperties.has('leadingAction') ||
245
- _changedProperties.has('duration')) {
246
- this.requestUpdate();
247
- }
248
178
  }
249
179
 
250
180
  /**
@@ -318,13 +248,12 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
318
248
  * main render function.
319
249
  *
320
250
  * @param {string} message - The message to be displayed.
321
- * @param {number} messageAreaMaxWidth - The maximum width of the message area calculated in the lifecycle method.
322
251
  *
323
252
  * @private
324
253
  */
325
- private renderMessage (message: string, messageAreaMaxWidth: number): TemplateResult {
254
+ private renderMessage (message: string): TemplateResult {
326
255
  return html`
327
- <span style="--toast-message-max-width: ${messageAreaMaxWidth}px" data-test-id="${componentSelector}-message">
256
+ <span data-test-id="${componentSelector}-message">
328
257
  ${message}
329
258
  </span>
330
259
  `;
@@ -391,31 +320,28 @@ export class PieToast extends RtlMixin(LitElement) implements ToastProps {
391
320
  leadingAction,
392
321
  isMultiline,
393
322
  isStrong,
394
- _messageAreaMaxWidth,
323
+ isRTL,
395
324
  } = this;
396
325
 
397
326
  const componentWrapperClasses = {
398
327
  [componentClass]: true,
328
+ [`${componentClass}--rtl`]: isRTL,
329
+ [`${componentClass}--multiline`]: isMultiline,
399
330
  [`${componentClass}--${variant}`]: true,
400
331
  [`${componentClass}--strong`]: isStrong,
401
332
  [`${componentClass}--animate-in`]: isOpen,
402
333
  [`${componentClass}--animate-out`]: !isOpen,
403
334
  };
404
335
 
405
- const messageAreaClasses = {
406
- [`${componentClass}-messageArea`]: true,
407
- [`${componentClass}--multiline`]: isMultiline,
408
- };
409
-
410
336
  return html`
411
337
  <div
412
338
  role="${variant === 'error' ? 'alert' : 'status'}"
413
339
  data-test-id="${componentSelector}"
414
340
  class="${classMap(componentWrapperClasses)}">
415
341
  <div class="${componentClass}-contentArea">
416
- <div class="${classMap(messageAreaClasses)}">
342
+ <div class="${componentClass}-messageArea">
417
343
  ${this.variantHasIcon(variant) ? this.getVariantIcon() : nothing}
418
- ${message === '' ? nothing : this.renderMessage(message, _messageAreaMaxWidth)}
344
+ ${message === '' ? nothing : this.renderMessage(message)}
419
345
  </div>
420
346
  <div class="${componentClass}-actionsArea">
421
347
  ${!isMultiline && leadingAction?.text ? this.renderActionButton(leadingAction) : nothing}
package/src/react.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { createComponent } from '@lit/react';
2
+ import { createComponent, type EventName } from '@lit/react';
3
3
  import { PieToast as PieToastLit } from './index';
4
4
  import { type ToastProps } from './defs';
5
5
 
@@ -10,10 +10,20 @@ const PieToastReact = createComponent({
10
10
  elementClass: PieToastLit,
11
11
  react: React,
12
12
  tagName: 'pie-toast',
13
- events: {},
13
+ events: {
14
+ onPieToastClose: 'pie-toast-close' as EventName<CustomEvent>, // when a user clicks close button or when the toast auto dismiss.
15
+ onPieToastOpen: 'pie-toast-open' as EventName<CustomEvent>, // when the toast is opened.
16
+ onPieToastLeadingActionClick: 'pie-toast-leading-action-click' as EventName<CustomEvent>, // when the user interacts with the leading action.
17
+ },
14
18
  });
15
19
 
16
20
  type ReactBaseType = React.HTMLAttributes<HTMLElement>
17
21
 
22
+ type PieToastEvents = {
23
+ onPieToastClose?: (event: CustomEvent) => void;
24
+ onPieToastOpen?: (event: CustomEvent) => void;
25
+ onPieToastLeadingActionClick?: (event: CustomEvent) => void;
26
+ };
27
+
18
28
  export const PieToast = PieToastReact as React.ForwardRefExoticComponent<React.PropsWithoutRef<ToastProps>
19
- & React.RefAttributes<PieToastLit> & ReactBaseType>;
29
+ & React.RefAttributes<PieToastLit> & PieToastEvents & ReactBaseType>;
package/src/toast.scss CHANGED
@@ -1,4 +1,5 @@
1
1
  @use '@justeattakeaway/pie-css/scss' as p;
2
+ @use '@justeattakeaway/pie-css/scss/settings' as *;
2
3
 
3
4
  .c-toast {
4
5
  --toast-border-radius: var(--dt-radius-rounded-b);
@@ -7,8 +8,13 @@
7
8
  --toast-font-size: #{p.font-size(--dt-font-body-s-size)};
8
9
  --toast-line-height: #{p.line-height(--dt-font-body-s-line-height)};
9
10
  --toast-icon-fill: var(--dt-color-content-default);
10
- --toast-message-max-width: 100%;
11
+ --toast-offset: var(--dt-spacing-d);
12
+ --toast-translate-start: -100%;
13
+ --toast-translate-end: 0;
11
14
 
15
+ position: absolute;
16
+ inset-inline-start: var(--toast-offset);
17
+ inset-block-end: var(--toast-offset);
12
18
  display: flex;
13
19
  flex-direction: column;
14
20
  justify-content: center;
@@ -16,10 +22,9 @@
16
22
  max-height: 122px;
17
23
  min-width: 300px;
18
24
  max-width: 420px;
19
-
20
- padding: var(--dt-spacing-a) var(--dt-spacing-c) var(--dt-spacing-a) var(--dt-spacing-d);
25
+
26
+ padding: var(--dt-spacing-b) var(--dt-spacing-c) var(--dt-spacing-b) var(--dt-spacing-d);
21
27
  border-radius: var(--toast-border-radius);
22
- gap: var(--dt-spacing-a);
23
28
  background-color: var(--toast-background-color);
24
29
  box-shadow: var(--dt-elevation-03);
25
30
  color: var(--toast-font-color);
@@ -28,20 +33,28 @@
28
33
  transition-property: all;
29
34
  transition-duration: var(--dt-motion-timing-100);
30
35
  transition-timing-function: var(--dt-motion-easing-in);
36
+
37
+ @include media('>md') {
38
+ --toast-offset: var(--dt-spacing-e);
39
+ }
40
+ }
41
+
42
+ .c-toast--rtl {
43
+ --toast-translate-start: 100%;
31
44
  }
32
45
 
33
46
  .c-toast--animate-in {
34
47
  animation-duration: var(--dt-motion-timing-200);
35
48
  animation-name: animate-in;
36
- animation-timing-function: var(--dt-motion-easing-in);
37
- transform: translateX(0);
49
+ animation-timing-function: var(--dt-motion-easing-out);
50
+ transform: translateX(var(--toast-translate-end));
38
51
  }
39
52
 
40
- .c-toast--animate-out {
53
+ .c-toast--animate-out {
41
54
  animation-duration: var(--dt-motion-timing-100);
42
55
  animation-name: animate-out;
43
- animation-timing-function: var(--dt-motion-easing-out);
44
- transform: translateX(100%);
56
+ animation-timing-function: var(--dt-motion-easing-in);
57
+ transform: translateX(var(--toast-translate-start));
45
58
  opacity: 0;
46
59
  }
47
60
 
@@ -92,18 +105,32 @@
92
105
  display: flex;
93
106
  align-items: center;
94
107
  gap: var(--dt-spacing-b);
95
- padding: calc(var(--dt-spacing-03) / 2) 0;
108
+ padding: 6px var(--dt-spacing-a) 6px 0;
109
+ overflow: hidden;
96
110
 
97
111
  span {
98
112
  text-overflow: ellipsis;
99
113
  white-space: nowrap;
100
114
  overflow: hidden;
101
- max-width: var(--toast-message-max-width);
102
115
  }
116
+ }
103
117
 
104
- &.c-toast--multiline {
118
+ .c-toast-actionsArea {
119
+ display: flex;
120
+ gap: var(--dt-spacing-b);
121
+ flex-shrink: 0;
122
+ }
123
+
124
+ .c-toast--multiline {
125
+ .c-toast-contentArea {
126
+ align-items: flex-start;
127
+ gap: 0;
128
+ }
129
+
130
+ .c-toast-messageArea {
105
131
  align-items: flex-start;
106
-
132
+ padding-block-end: var(--dt-spacing-b);
133
+
107
134
  span {
108
135
  max-height: 60px;
109
136
  white-space: inherit;
@@ -118,11 +145,6 @@
118
145
  }
119
146
  }
120
147
 
121
- .c-toast-actionsArea {
122
- display: flex;
123
- gap: var(--dt-spacing-b);
124
- }
125
-
126
148
  .c-toast-footer {
127
149
  display: flex;
128
150
  justify-content: flex-end;
@@ -134,20 +156,20 @@
134
156
 
135
157
  @keyframes animate-in {
136
158
  from {
137
- transform: translateX(100%);
159
+ transform: translateX(var(--toast-translate-start));
138
160
  }
139
161
 
140
162
  to {
141
- transform: translateX(0);
163
+ transform: translateX(var(--toast-translate-end));
142
164
  }
143
165
  }
144
166
 
145
167
  @keyframes animate-out {
146
168
  from {
147
- transform: translateX(0);
169
+ transform: translateX(var(--toast-translate-end));
148
170
  }
149
171
 
150
172
  to {
151
- transform: translateX(100%);
173
+ transform: translateX(var(--toast-translate-start));
152
174
  }
153
175
  }