@justeattakeaway/pie-toast-provider 1.2.2 → 1.3.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/dist/index.js CHANGED
@@ -1,17 +1,19 @@
1
- import { LitElement as _, unsafeCSS as b, nothing as y, html as u } from "lit";
2
- import { property as h, state as g } from "lit/decorators.js";
3
- import { ifDefined as T } from "lit/directives/if-defined.js";
4
- import { classMap as f } from "lit/directives/class-map.js";
5
- import { validPropertyValues as P, safeCustomElement as $, dispatchCustomEvent as x } from "@justeattakeaway/pie-webc-core";
6
- import { defaultProps as m } from "@justeattakeaway/pie-toast";
7
- const l = class l extends _ {
1
+ import { LitElement as g, unsafeCSS as T, nothing as b, html as v } from "lit";
2
+ import { property as u, state as p } from "lit/decorators.js";
3
+ import { ifDefined as y } from "lit/directives/if-defined.js";
4
+ import { classMap as k } from "lit/directives/class-map.js";
5
+ import { live as $ } from "lit/directives/live.js";
6
+ import { repeat as f } from "lit/directives/repeat.js";
7
+ import { validPropertyValues as w, safeCustomElement as x, dispatchCustomEvent as P } from "@justeattakeaway/pie-webc-core";
8
+ import { defaultProps as _ } from "@justeattakeaway/pie-toast";
9
+ const m = class m extends g {
8
10
  willUpdate() {
9
- this.getAttribute("v") || this.setAttribute("v", l.v);
11
+ this.getAttribute("v") || this.setAttribute("v", m.v);
10
12
  }
11
13
  };
12
- l.v = "1.2.2";
13
- let d = l;
14
- const w = "*,*:after,*:before{box-sizing:inherit}:root{--pie-animation-slide-translate-start: -100%}.pie-animation--slide-in{animation:pie-animation-slide-in var(--dt-motion-timing-200) var(--dt-motion-easing-out)}.pie-animation--slide-out{animation:pie-animation-slide-out var(--dt-motion-timing-100) var(--dt-motion-easing-in)}@keyframes pie-animation-slide-in{0%{transform:translate(var(--pie-animation-slide-translate-start))}to{transform:translate(0)}}@keyframes pie-animation-slide-out{0%{transform:translate(0)}to{transform:translate(var(--pie-animation-slide-translate-start))}}:host{--toast-provider-z-index: var(--dt-z-index-toast);--toast-provider-position: fixed;--toast-provider-offset: var(--dt-spacing-d)}@media(min-width:769px){:host{--toast-provider-offset: var(--dt-spacing-e)}}.c-toast-provider{position:var(--toast-provider-position);z-index:var(--toast-provider-z-index)}.c-toast-provider-announcer{position:absolute;display:block;height:1px;width:1px;border:0;padding:0;margin:-1px;overflow:hidden;white-space:nowrap;clip:rect(0,0,0,0);clip-path:inset(50%)}.c-toast-provider-announcer *{overflow:hidden}.c-toast-provider.c-toast-provider--default{inset-inline-start:var(--toast-provider-offset);inset-block-end:var(--toast-provider-offset)}.c-toast-provider.c-toast-provider--default:dir(rtl){--pie-animation-slide-translate-start: 100%}.c-toast-provider.c-toast-provider--bottom-left{--pie-animation-slide-translate-start: -100%;left:var(--toast-provider-offset);bottom:var(--toast-provider-offset)}.c-toast-provider.c-toast-provider--bottom-right{--pie-animation-slide-translate-start: 100%;right:var(--toast-provider-offset);bottom:var(--toast-provider-offset)}.c-toast-provider.c-toast-provider--bottom-center{--pie-animation-slide-translate-start: 0, 100%;left:50%;bottom:var(--toast-provider-offset);transform:translate(-50%)}", A = {
14
+ m.v = "1.3.0";
15
+ let h = m;
16
+ const A = "*,*:after,*:before{box-sizing:inherit}:root{--pie-animation-slide-translate-start: -100%}.pie-animation--slide-in{animation:pie-animation-slide-in var(--dt-motion-timing-200) var(--dt-motion-easing-out)}.pie-animation--slide-out{animation:pie-animation-slide-out var(--dt-motion-timing-100) var(--dt-motion-easing-in)}@keyframes pie-animation-slide-in{0%{transform:translate(var(--pie-animation-slide-translate-start))}to{transform:translate(0)}}@keyframes pie-animation-slide-out{0%{transform:translate(0)}to{transform:translate(var(--pie-animation-slide-translate-start))}}:host{--toast-provider-z-index: var(--dt-z-index-toast);--toast-provider-position: fixed;--toast-provider-offset: var(--dt-spacing-d)}@media(min-width:769px){:host{--toast-provider-offset: var(--dt-spacing-e)}}.c-toast-provider{position:var(--toast-provider-position);z-index:var(--toast-provider-z-index);display:flex;flex-direction:column-reverse}.c-toast-provider-announcer{position:absolute;display:block;height:1px;width:1px;border:0;padding:0;margin:-1px;overflow:hidden;white-space:nowrap;clip:rect(0,0,0,0);clip-path:inset(50%)}.c-toast-provider-announcer *{overflow:hidden}.c-toast-provider.c-toast-provider--default{inset-inline-start:var(--toast-provider-offset);inset-block-end:var(--toast-provider-offset)}.c-toast-provider.c-toast-provider--default:dir(rtl){--pie-animation-slide-translate-start: 100%}.c-toast-provider.c-toast-provider--bottom-left{--pie-animation-slide-translate-start: -100%;left:var(--toast-provider-offset);bottom:var(--toast-provider-offset)}.c-toast-provider.c-toast-provider--bottom-right{--pie-animation-slide-translate-start: 100%;right:var(--toast-provider-offset);bottom:var(--toast-provider-offset)}.c-toast-provider .c-toast-provider-item{display:grid;grid-template-rows:1fr;padding-block-start:var(--dt-spacing-d);transition:grid-template-rows var(--dt-motion-timing-200) var(--dt-motion-easing-in),padding-block-start var(--dt-motion-timing-200) var(--dt-motion-easing-in)}.c-toast-provider .c-toast-provider-item>pie-toast{min-block-size:0;overflow:hidden}.c-toast-provider .c-toast-provider-item--collapsing{grid-template-rows:0fr;padding-block-start:0}.c-toast-provider .c-toast-provider-item--collapsing>pie-toast{visibility:hidden}.c-toast-provider.c-toast-provider--bottom-center{--pie-animation-slide-translate-start: 0, 100%;left:50%;bottom:var(--toast-provider-offset);transform:translate(-50%)}", M = {
15
17
  "error-actionable": 1,
16
18
  error: 2,
17
19
  "warning-actionable": 3,
@@ -22,53 +24,72 @@ const w = "*,*:after,*:before{box-sizing:inherit}:root{--pie-animation-slide-tra
22
24
  success: 8,
23
25
  info: 9,
24
26
  neutral: 10
25
- }, E = ["default", "bottom-left", "bottom-right", "bottom-center"], c = {
27
+ }, O = ["default", "bottom-left", "bottom-right", "bottom-center"], c = {
26
28
  options: {},
27
- position: "default"
28
- }, O = "pie-toast-provider-queue-update", I = {
29
- _getToastProvider(o) {
30
- if (o) {
31
- const e = document.getElementById(o);
32
- return !e || e.tagName.toLowerCase() !== "pie-toast-provider" ? (console.error(`No pie-toast-provider found with id "${o}".`), null) : e;
29
+ position: "default",
30
+ isStacked: !1
31
+ }, S = "pie-toast-provider-queue-update", F = 3, q = {
32
+ _getToastProvider(t) {
33
+ if (t) {
34
+ const e = document.getElementById(t);
35
+ return !e || e.tagName.toLowerCase() !== "pie-toast-provider" ? (console.error(`No pie-toast-provider found with id "${t}".`), null) : e;
33
36
  }
34
- let t = document.activeElement;
35
- for (; t; ) {
36
- const e = t.parentElement;
37
+ let i = document.activeElement;
38
+ for (; i; ) {
39
+ const e = i.parentElement;
37
40
  if (e) {
38
- const i = e.querySelector(":scope > pie-toast-provider");
39
- if (i) return i;
41
+ const a = e.querySelector(":scope > pie-toast-provider");
42
+ if (a) return a;
40
43
  }
41
- t = e;
44
+ i = e;
42
45
  }
43
- const s = document.querySelectorAll("pie-toast-provider");
44
- return s.length === 0 ? (console.error("No pie-toast-provider found in the DOM. Add a <pie-toast-provider> element to your page or at the root of your application."), null) : s.length > 1 ? (console.error("Multiple pie-toast-provider elements found. Use the `providerId` option to target a specific provider."), null) : s[0];
46
+ const o = document.querySelectorAll("pie-toast-provider");
47
+ return o.length === 0 ? (console.error("No pie-toast-provider found in the DOM. Add a <pie-toast-provider> element to your page or at the root of your application."), null) : o.length > 1 ? (console.error("Multiple pie-toast-provider elements found. Use the `providerId` option to target a specific provider."), null) : o[0];
45
48
  },
46
- create(o) {
47
- const t = this._getToastProvider(o.providerId);
48
- t && t.createToast(o);
49
+ create(t) {
50
+ const i = this._getToastProvider(t.providerId);
51
+ i && i.createToast(t);
49
52
  },
50
- clearAll(o) {
51
- const t = this._getToastProvider(o);
52
- t && t.clearToasts();
53
+ clearAll(t) {
54
+ const i = this._getToastProvider(t);
55
+ i && i.clearToasts();
53
56
  }
54
57
  };
55
- var D = Object.defineProperty, S = Object.getOwnPropertyDescriptor, p = (o, t, s, e) => {
56
- for (var i = e > 1 ? void 0 : e ? S(t, s) : t, a = o.length - 1, n; a >= 0; a--)
57
- (n = o[a]) && (i = (e ? n(t, s, i) : n(i)) || i);
58
- return e && i && D(t, s, i), i;
58
+ var C = Object.defineProperty, E = Object.getOwnPropertyDescriptor, n = (t, i, o, e) => {
59
+ for (var a = e > 1 ? void 0 : e ? E(i, o) : i, l = t.length - 1, s; l >= 0; l--)
60
+ (s = t[l]) && (a = (e ? s(i, o, a) : s(a)) || a);
61
+ return e && a && C(i, o, a), a;
59
62
  };
60
- const C = "pie-toast-provider";
61
- let r = class extends d {
63
+ const D = "pie-toast-provider", z = 500;
64
+ let r = class extends h {
62
65
  constructor() {
63
- super(...arguments), this.options = c.options, this.position = c.position, this._toasts = [], this._currentToast = null;
66
+ super(...arguments), this.options = c.options, this.position = c.position, this.isStacked = c.isStacked, this._toasts = [], this._visibleToasts = [], this._dismissingToasts = [], this._collapsingToasts = [], this._announcements = [], this._motionFallbacks = /* @__PURE__ */ new Map();
64
67
  }
65
- updated(o) {
66
- o.has("_toasts") && this._dispatchQueueUpdateEvent();
68
+ disconnectedCallback() {
69
+ this._clearMotionFallbacks(), super.disconnectedCallback();
70
+ }
71
+ /**
72
+ * Replaces any pending fallback for `toast` with one that runs `advance`.
73
+ *
74
+ * Each phase supersedes the previous phase's fallback, so a toast only ever has one timer.
75
+ */
76
+ _scheduleMotionFallback(t, i) {
77
+ this._clearMotionFallback(t), this._motionFallbacks.set(t, setTimeout(i, z));
78
+ }
79
+ _clearMotionFallback(t) {
80
+ const i = this._motionFallbacks.get(t);
81
+ i && (clearTimeout(i), this._motionFallbacks.delete(t));
82
+ }
83
+ _clearMotionFallbacks() {
84
+ this._motionFallbacks.forEach((t) => clearTimeout(t)), this._motionFallbacks.clear();
85
+ }
86
+ updated(t) {
87
+ t.has("_toasts") && this._dispatchQueueUpdateEvent();
67
88
  }
68
89
  _dispatchQueueUpdateEvent() {
69
- x(
90
+ P(
70
91
  this,
71
- O,
92
+ S,
72
93
  this._toasts
73
94
  );
74
95
  }
@@ -78,113 +99,176 @@ let r = class extends d {
78
99
  * @param {boolean} hasAction - Whether the toast has an action.
79
100
  * @returns {number} - The priority based on the variant and action.
80
101
  */
81
- getPriority(o = m.variant, t = !1) {
82
- const s = `${o}${t ? "-actionable" : ""}`;
83
- return A[s];
102
+ getPriority(t = _.variant, i = !1) {
103
+ const o = `${t}${i ? "-actionable" : ""}`;
104
+ return M[o];
84
105
  }
85
106
  /**
86
- * Handles the dismissal of the current toast and displays the next one in the queue (if any).
107
+ * Starts the slide-out animation for the dismissed toast.
87
108
  */
88
- _dismissToast() {
89
- var o, t;
90
- (t = (o = this._currentToast) == null ? void 0 : o.onPieToastClose) == null || t.call(o), this._currentToast = null, requestAnimationFrame(() => {
91
- this._showNextToast();
92
- });
109
+ _dismissToast(t) {
110
+ var i;
111
+ this._dismissingToasts.includes(t) || ((i = t.onPieToastClose) == null || i.call(t), this._dismissingToasts = [...this._dismissingToasts, t], this._scheduleMotionFallback(t, () => this._finalizeDismiss(t)));
112
+ }
113
+ /**
114
+ * Forwards the toast's open event to the consumer.
115
+ *
116
+ * `isOpen` is bound with the `live` directive, so a toast that sets `isOpen` to false while
117
+ * dismissing is reopened on the next render in order to keep it visible for the slide-out
118
+ * animation. That reopen dispatches a second `pie-toast-open`, which is not a real open, so it
119
+ * is not forwarded.
120
+ */
121
+ _handleToastOpen(t) {
122
+ var i;
123
+ this._dismissingToasts.includes(t) || (i = t.onPieToastOpen) == null || i.call(t);
124
+ }
125
+ _getToastClass(t) {
126
+ return this._dismissingToasts.includes(t) ? "pie-animation--slide-out" : this._collapsingToasts.includes(t) ? "" : "pie-animation--slide-in";
127
+ }
128
+ _getToastDuration(t) {
129
+ return this._dismissingToasts.includes(t) || this._collapsingToasts.includes(t) ? null : typeof t.duration > "u" ? b : t.duration;
93
130
  }
94
131
  /**
95
- * Displays the next toast in the queue, if available.
132
+ * Starts the height-collapse phase after the slide-out animation ends.
133
+ */
134
+ _finalizeDismiss(t) {
135
+ this._dismissingToasts.includes(t) && (this._dismissingToasts = this._dismissingToasts.filter((i) => i !== t), this._collapsingToasts = [...this._collapsingToasts, t], this._scheduleMotionFallback(t, () => this._finalizeCollapse(t)));
136
+ }
137
+ /**
138
+ * Called after the collapse transition ends. Removes the toast from DOM and promotes the next queued toast.
139
+ */
140
+ _finalizeCollapse(t) {
141
+ this._collapsingToasts.includes(t) && (this._clearMotionFallback(t), this._collapsingToasts = this._collapsingToasts.filter((i) => i !== t), this._visibleToasts = this._visibleToasts.filter((i) => i !== t), this._announcements = this._announcements.filter((i) => i !== t), this._showNextToast());
142
+ }
143
+ /**
144
+ * Fills the visible slots from the queue.
145
+ *
146
+ * The loop only ever adds toasts, so turning `isStacked` off while several are on screen
147
+ * does not remove any: the extras stay until they dismiss normally, then the provider
148
+ * settles back to one at a time.
96
149
  */
97
150
  _showNextToast() {
98
- if (this._toasts.length > 0) {
99
- const [o, ...t] = this._toasts;
100
- this._currentToast = o, this._toasts = t;
101
- } else
102
- this._currentToast = null;
151
+ const t = this.isStacked ? F : 1;
152
+ for (; this._visibleToasts.length < t && this._toasts.length > 0; ) {
153
+ const [i, ...o] = this._toasts;
154
+ this._visibleToasts = [...this._visibleToasts, i], this._toasts = o, this._announcements = [...this._announcements, i];
155
+ }
103
156
  }
104
157
  /**
105
- * Adds a new toast to the queue and triggers its display if no toast is currently active.
158
+ * Adds a new toast to the queue (sorted by priority) and fills visible slots.
106
159
  * @param {ToastProps} toast - The toast props to display.
107
160
  */
108
- createToast(o) {
109
- const t = { ...m, ...this.options, ...o };
110
- this._toasts = [...this._toasts, t].sort((s, e) => {
111
- var n, v;
112
- const i = this.getPriority(e.variant, !!((n = e.leadingAction) != null && n.text));
113
- return this.getPriority(s.variant, !!((v = s.leadingAction) != null && v.text)) - i;
114
- }), this._currentToast || this._showNextToast();
161
+ createToast(t) {
162
+ const i = { ..._, ...this.options, ...t };
163
+ this._toasts = [...this._toasts, i].sort((o, e) => {
164
+ var s, d;
165
+ const a = this.getPriority(o.variant, !!((s = o.leadingAction) != null && s.text)), l = this.getPriority(e.variant, !!((d = e.leadingAction) != null && d.text));
166
+ return a - l;
167
+ }), this._showNextToast();
115
168
  }
116
169
  /**
117
- *
118
- * Clears all toasts from the queue and dismisses the currently visible toast.
170
+ * Clears all toasts from the queue and dismisses all visible toasts.
119
171
  */
120
172
  clearToasts() {
121
- this._toasts = [], this._currentToast = null;
173
+ this._clearMotionFallbacks(), this._toasts = [], this._visibleToasts = [], this._dismissingToasts = [], this._collapsingToasts = [], this._announcements = [];
122
174
  }
123
175
  render() {
124
176
  const {
125
- position: o,
126
- _currentToast: t
127
- } = this, s = {
177
+ position: t,
178
+ _visibleToasts: i
179
+ } = this, o = {
128
180
  "c-toast-provider": !0,
129
- [`c-toast-provider--${o}`]: !0
130
- }, e = {
131
- "pie-animation--slide-in": !!t,
132
- "pie-animation--slide-out": t === null
133
- }, i = (t == null ? void 0 : t.variant) === "error", a = { ...t == null ? void 0 : t.aria, live: "off" };
134
- return u`
181
+ [`c-toast-provider--${t}`]: !0
182
+ }, e = this._announcements.filter(({ variant: s }) => s !== "error"), a = this._announcements.filter(({ variant: s }) => s === "error"), l = (s) => f(
183
+ s,
184
+ (d) => d,
185
+ (d) => v`<div>${d.message}</div>`
186
+ );
187
+ return v`
135
188
  <div
136
- class=${f(s)}
189
+ class=${k(o)}
137
190
  data-test-id="pie-toast-provider">
138
191
  <div
139
- class="c-toast-provider-announcer is-visuallyHidden"
140
- role="${i ? "alert" : "status"}"
141
- aria-live="${i ? "assertive" : "polite"}"
142
- aria-atomic="true"
192
+ class="c-toast-provider-announcer"
193
+ role="status"
194
+ aria-live="polite"
195
+ aria-atomic="false"
143
196
  data-test-id="pie-toast-provider-announcer">
144
- ${(t == null ? void 0 : t.message) ?? ""}
197
+ ${l(e)}
198
+ </div>
199
+ <div
200
+ class="c-toast-provider-announcer"
201
+ role="alert"
202
+ aria-live="assertive"
203
+ aria-atomic="false"
204
+ data-test-id="pie-toast-provider-announcer-assertive">
205
+ ${l(a)}
145
206
  </div>
146
- ${t && u`
147
- <pie-toast
148
- class=${f(e)}
149
- message="${t.message}"
150
- variant="${T(t.variant)}"
151
- ?isStrong="${t.isStrong}"
152
- ?isDismissible="${t.isDismissible}"
153
- ?isMultiline="${t.isMultiline}"
154
- .leadingAction="${t.leadingAction}"
155
- .aria="${a}"
156
- .duration="${typeof t.duration > "u" ? y : t.duration}"
157
- @pie-toast-close="${this._dismissToast}"
158
- @pie-toast-open="${t.onPieToastOpen}"
159
- @pie-toast-leading-action-click="${t.onPieToastLeadingActionClick}">
160
- </pie-toast>
161
- `}
207
+ ${f(i, (s) => s, (s) => v`
208
+ <div
209
+ class="c-toast-provider-item${this._collapsingToasts.includes(s) ? " c-toast-provider-item--collapsing" : ""}"
210
+ @transitionend="${() => {
211
+ this._collapsingToasts.includes(s) && this._finalizeCollapse(s);
212
+ }}">
213
+ <pie-toast
214
+ class="${this._getToastClass(s)}"
215
+ .isOpen="${$(!0)}"
216
+ message="${s.message}"
217
+ variant="${y(s.variant)}"
218
+ ?isStrong="${s.isStrong}"
219
+ ?isDismissible="${s.isDismissible}"
220
+ ?isMultiline="${s.isMultiline}"
221
+ .leadingAction="${s.leadingAction}"
222
+ .aria="${{ ...s.aria, live: "off" }}"
223
+ .duration="${this._getToastDuration(s)}"
224
+ @pie-toast-close="${() => this._dismissToast(s)}"
225
+ @pie-toast-open="${() => this._handleToastOpen(s)}"
226
+ @pie-toast-leading-action-click="${s.onPieToastLeadingActionClick}"
227
+ @animationend="${() => {
228
+ this._dismissingToasts.includes(s) && this._finalizeDismiss(s);
229
+ }}">
230
+ </pie-toast>
231
+ </div>
232
+ `)}
162
233
  </div>
163
234
  `;
164
235
  }
165
236
  };
166
- r.styles = b(w);
167
- p([
168
- h({ type: Object })
237
+ r.styles = T(A);
238
+ n([
239
+ u({ type: Object })
169
240
  ], r.prototype, "options", 2);
170
- p([
171
- h({ type: String }),
172
- P(C, E, c.position)
241
+ n([
242
+ u({ type: String }),
243
+ w(D, O, c.position)
173
244
  ], r.prototype, "position", 2);
174
- p([
175
- g()
245
+ n([
246
+ u({ type: Boolean })
247
+ ], r.prototype, "isStacked", 2);
248
+ n([
249
+ p()
176
250
  ], r.prototype, "_toasts", 2);
177
- p([
178
- g()
179
- ], r.prototype, "_currentToast", 2);
180
- r = p([
181
- $("pie-toast-provider")
251
+ n([
252
+ p()
253
+ ], r.prototype, "_visibleToasts", 2);
254
+ n([
255
+ p()
256
+ ], r.prototype, "_dismissingToasts", 2);
257
+ n([
258
+ p()
259
+ ], r.prototype, "_collapsingToasts", 2);
260
+ n([
261
+ p()
262
+ ], r.prototype, "_announcements", 2);
263
+ r = n([
264
+ x("pie-toast-provider")
182
265
  ], r);
183
266
  export {
184
- O as ON_TOAST_PROVIDER_QUEUE_UPDATE_EVENT,
185
- A as PRIORITY_ORDER,
267
+ F as MAX_VISIBLE_TOASTS,
268
+ S as ON_TOAST_PROVIDER_QUEUE_UPDATE_EVENT,
269
+ M as PRIORITY_ORDER,
186
270
  r as PieToastProvider,
187
271
  c as defaultProps,
188
- E as positions,
189
- I as toaster
272
+ O as positions,
273
+ q as toaster
190
274
  };
package/dist/react.d.ts CHANGED
@@ -30,6 +30,15 @@ export declare interface ExtendedToastProps extends ToastProps {
30
30
  onPieToastLeadingActionClick?: (event: Event) => void;
31
31
  }
32
32
 
33
+ /**
34
+ * The most toasts the provider will display at once when `isStacked` is true.
35
+ *
36
+ * With `isStacked` false (the default) a single toast is displayed regardless of this value.
37
+ *
38
+ * @constant
39
+ */
40
+ export declare const MAX_VISIBLE_TOASTS = 3;
41
+
33
42
  /**
34
43
  * Event name for when the toast provider queue is updated.
35
44
  *
@@ -46,8 +55,29 @@ export declare const PieToastProvider: React_2.ForwardRefExoticComponent<React_2
46
55
  declare class PieToastProvider_2 extends PieElement implements ToastProviderProps {
47
56
  options: Partial<ExtendedToastProps>;
48
57
  position: "default" | "bottom-left" | "bottom-right" | "bottom-center";
58
+ isStacked: boolean;
49
59
  private _toasts;
50
- private _currentToast;
60
+ private _visibleToasts;
61
+ private _dismissingToasts;
62
+ private _collapsingToasts;
63
+ /**
64
+ * Messages currently held in the live regions, in the order they became visible.
65
+ *
66
+ * The toast objects themselves are reused as entries: they are unique per `createToast`, which
67
+ * gives `repeat` a stable key and lets the entries be pruned by identity when a toast leaves.
68
+ */
69
+ private _announcements;
70
+ /** Pending {@link MOTION_FALLBACK_MS} timers, keyed by the toast they will advance. */
71
+ private _motionFallbacks;
72
+ disconnectedCallback(): void;
73
+ /**
74
+ * Replaces any pending fallback for `toast` with one that runs `advance`.
75
+ *
76
+ * Each phase supersedes the previous phase's fallback, so a toast only ever has one timer.
77
+ */
78
+ private _scheduleMotionFallback;
79
+ private _clearMotionFallback;
80
+ private _clearMotionFallbacks;
51
81
  updated(changedProperties: PropertyValues<this>): void;
52
82
  private _dispatchQueueUpdateEvent;
53
83
  /**
@@ -58,21 +88,43 @@ declare class PieToastProvider_2 extends PieElement implements ToastProviderProp
58
88
  */
59
89
  private getPriority;
60
90
  /**
61
- * Handles the dismissal of the current toast and displays the next one in the queue (if any).
91
+ * Starts the slide-out animation for the dismissed toast.
62
92
  */
63
93
  private _dismissToast;
64
94
  /**
65
- * Displays the next toast in the queue, if available.
95
+ * Forwards the toast's open event to the consumer.
96
+ *
97
+ * `isOpen` is bound with the `live` directive, so a toast that sets `isOpen` to false while
98
+ * dismissing is reopened on the next render in order to keep it visible for the slide-out
99
+ * animation. That reopen dispatches a second `pie-toast-open`, which is not a real open, so it
100
+ * is not forwarded.
101
+ */
102
+ private _handleToastOpen;
103
+ private _getToastClass;
104
+ private _getToastDuration;
105
+ /**
106
+ * Starts the height-collapse phase after the slide-out animation ends.
107
+ */
108
+ private _finalizeDismiss;
109
+ /**
110
+ * Called after the collapse transition ends. Removes the toast from DOM and promotes the next queued toast.
111
+ */
112
+ private _finalizeCollapse;
113
+ /**
114
+ * Fills the visible slots from the queue.
115
+ *
116
+ * The loop only ever adds toasts, so turning `isStacked` off while several are on screen
117
+ * does not remove any: the extras stay until they dismiss normally, then the provider
118
+ * settles back to one at a time.
66
119
  */
67
120
  private _showNextToast;
68
121
  /**
69
- * Adds a new toast to the queue and triggers its display if no toast is currently active.
122
+ * Adds a new toast to the queue (sorted by priority) and fills visible slots.
70
123
  * @param {ToastProps} toast - The toast props to display.
71
124
  */
72
125
  createToast(toast: ExtendedToastProps): void;
73
126
  /**
74
- *
75
- * Clears all toasts from the queue and dismisses the currently visible toast.
127
+ * Clears all toasts from the queue and dismisses all visible toasts.
76
128
  */
77
129
  clearToasts(): void;
78
130
  render(): TemplateResult<1>;
@@ -112,6 +164,11 @@ export declare interface ToastProviderProps {
112
164
  * When set to `default`, the toasts will be positioned at bottom-left for RTL languages and bottom-right for LTR languages.
113
165
  */
114
166
  position?: typeof positions[number];
167
+ /**
168
+ * When true, up to 3 toasts are displayed at the same time in a vertical stack. When false,
169
+ * a single toast is displayed at a time and the rest wait in the queue.
170
+ */
171
+ isStacked?: boolean;
115
172
  }
116
173
 
117
174
  export { }
package/dist/react.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as e from "react";
2
2
  import { createComponent as o } from "@lit/react";
3
3
  import { PieToastProvider as t } from "./index.js";
4
- import { ON_TOAST_PROVIDER_QUEUE_UPDATE_EVENT as d, PRIORITY_ORDER as m, defaultProps as T, positions as v } from "./index.js";
4
+ import { MAX_VISIBLE_TOASTS as T, ON_TOAST_PROVIDER_QUEUE_UPDATE_EVENT as d, PRIORITY_ORDER as m, defaultProps as v, positions as n } from "./index.js";
5
5
  const r = o({
6
6
  displayName: "PieToastProvider",
7
7
  elementClass: t,
@@ -13,9 +13,10 @@ const r = o({
13
13
  }
14
14
  }), s = r;
15
15
  export {
16
+ T as MAX_VISIBLE_TOASTS,
16
17
  d as ON_TOAST_PROVIDER_QUEUE_UPDATE_EVENT,
17
18
  m as PRIORITY_ORDER,
18
19
  s as PieToastProvider,
19
- T as defaultProps,
20
- v as positions
20
+ v as defaultProps,
21
+ n as positions
21
22
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-toast-provider",
3
3
  "description": "PIE Design System Toast Provider built using Web Components",
4
- "version": "1.2.2",
4
+ "version": "1.3.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/justeattakeaway/pie",
@@ -42,12 +42,12 @@
42
42
  "license": "Apache-2.0",
43
43
  "devDependencies": {
44
44
  "@justeattakeaway/pie-components-config": "0.21.4",
45
- "@justeattakeaway/pie-css": "1.7.0",
46
- "@justeattakeaway/pie-monorepo-utils": "0.9.9"
45
+ "@justeattakeaway/pie-css": "1.9.0",
46
+ "@justeattakeaway/pie-monorepo-utils": "0.9.10"
47
47
  },
48
48
  "dependencies": {
49
- "@justeattakeaway/pie-toast": "1.2.2",
50
- "@justeattakeaway/pie-webc-core": "20.0.0"
49
+ "@justeattakeaway/pie-toast": "1.2.4",
50
+ "@justeattakeaway/pie-webc-core": "22.0.0"
51
51
  },
52
52
  "customElements": "custom-elements.json",
53
53
  "sideEffects": [
package/src/defs.ts CHANGED
@@ -53,6 +53,12 @@ export interface ToastProviderProps {
53
53
  * When set to `default`, the toasts will be positioned at bottom-left for RTL languages and bottom-right for LTR languages.
54
54
  */
55
55
  position?: typeof positions[number];
56
+
57
+ /**
58
+ * When true, up to 3 toasts are displayed at the same time in a vertical stack. When false,
59
+ * a single toast is displayed at a time and the rest wait in the queue.
60
+ */
61
+ isStacked?: boolean;
56
62
  }
57
63
 
58
64
  export type DefaultProps = ComponentDefaultProps<ToastProviderProps>;
@@ -60,6 +66,7 @@ export type DefaultProps = ComponentDefaultProps<ToastProviderProps>;
60
66
  export const defaultProps: DefaultProps = {
61
67
  options: {},
62
68
  position: 'default',
69
+ isStacked: false,
63
70
  };
64
71
 
65
72
  /**
@@ -69,3 +76,12 @@ export const defaultProps: DefaultProps = {
69
76
  */
70
77
 
71
78
  export const ON_TOAST_PROVIDER_QUEUE_UPDATE_EVENT = 'pie-toast-provider-queue-update';
79
+
80
+ /**
81
+ * The most toasts the provider will display at once when `isStacked` is true.
82
+ *
83
+ * With `isStacked` false (the default) a single toast is displayed regardless of this value.
84
+ *
85
+ * @constant
86
+ */
87
+ export const MAX_VISIBLE_TOASTS = 3;