@aurodesignsystem-dev/auro-toast 0.0.0-pr147.0 → 0.0.0-pr147.10

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
@@ -107,7 +107,7 @@ You can do this by importing only the component class and using the `register(na
107
107
 
108
108
  <pre class="language-js"><code class="language-js">// Import the class only
109
109
  import { AuroToast } from '@aurodesignsystem/auro-toast/class';
110
- ​
110
+
111
111
  // Register with a custom name if desired
112
112
  AuroToast.register('custom-toast');</code></pre>
113
113
 
@@ -0,0 +1,458 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "readme": "",
4
+ "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "src/auro-toast.js",
8
+ "declarations": [
9
+ {
10
+ "kind": "class",
11
+ "description": "The `auro-toast` element provides users a way to display short, temporary messages.",
12
+ "name": "AuroToast",
13
+ "cssParts": [
14
+ {
15
+ "description": "Apply css to the toast close button",
16
+ "name": "close-button"
17
+ },
18
+ {
19
+ "description": "Apply css to the toast type icon",
20
+ "name": "type-icon"
21
+ }
22
+ ],
23
+ "members": [
24
+ {
25
+ "kind": "method",
26
+ "name": "_cancelFadeOut",
27
+ "description": "Cancels an in-progress fade-out, if any, and restores the toast's\nvisibility. Without this, interrupting a fade (e.g. escalating to\nvariant=\"error\" mid-fade) would clear the pending close but leave the\n\"hidden\" CSS class in place, permanently hiding a toast that remains\nopen.",
28
+ "privacy": "private",
29
+ "return": {
30
+ "type": {
31
+ "text": "void"
32
+ }
33
+ }
34
+ },
35
+ {
36
+ "kind": "method",
37
+ "name": "_hasAncestorLiveRegion",
38
+ "description": "Walks the DOM ancestors (crossing shadow boundaries) looking for any\nactive live region — either an aria-live=\"polite/assertive\" attribute or\nan implicit live region role (alert, status, log).\naria-live=\"off\" is not considered active and is intentionally ignored.",
39
+ "privacy": "private",
40
+ "return": {
41
+ "type": {
42
+ "text": "boolean"
43
+ }
44
+ }
45
+ },
46
+ {
47
+ "kind": "method",
48
+ "name": "_initializeDefaults",
49
+ "type": {
50
+ "text": "_initializeDefaults() => void"
51
+ }
52
+ },
53
+ {
54
+ "kind": "method",
55
+ "name": "_returnFocus",
56
+ "description": "Returns focus to the trigger element when the toast is manually closed.\nNot called on auto-dismiss — moving focus during auto-dismiss would\ninterrupt the AT user's current position in the page.",
57
+ "privacy": "private",
58
+ "return": {
59
+ "type": {
60
+ "text": "void"
61
+ }
62
+ }
63
+ },
64
+ {
65
+ "kind": "method",
66
+ "name": "_syncStandaloneRole",
67
+ "description": "Sets or removes the live-region role on the host depending on whether\nthe toast is standalone. Extracted so connectedCallback and updated()\nstay in sync without duplicating the logic.",
68
+ "privacy": "private",
69
+ "return": {
70
+ "type": {
71
+ "text": "void"
72
+ }
73
+ }
74
+ },
75
+ {
76
+ "kind": "method",
77
+ "name": "clickToClose",
78
+ "privacy": "private",
79
+ "return": {
80
+ "type": {
81
+ "text": "void"
82
+ }
83
+ }
84
+ },
85
+ {
86
+ "kind": "method",
87
+ "name": "closeToast",
88
+ "privacy": "private",
89
+ "return": {
90
+ "type": {
91
+ "text": "void"
92
+ }
93
+ }
94
+ },
95
+ {
96
+ "kind": "field",
97
+ "name": "disableAutoHide",
98
+ "privacy": "public",
99
+ "type": {
100
+ "text": "boolean"
101
+ },
102
+ "description": "Prevents the toast from auto-hiding on the default time.",
103
+ "attribute": "disableautohide",
104
+ "reflects": true
105
+ },
106
+ {
107
+ "kind": "method",
108
+ "name": "fadeOutToast",
109
+ "privacy": "private",
110
+ "return": {
111
+ "type": {
112
+ "text": "void"
113
+ }
114
+ }
115
+ },
116
+ {
117
+ "kind": "method",
118
+ "name": "getVariantIcon",
119
+ "description": "Determines which type icon to render based on the variant prop.",
120
+ "privacy": "private",
121
+ "return": {
122
+ "type": {
123
+ "text": "HTMLElement"
124
+ }
125
+ }
126
+ },
127
+ {
128
+ "kind": "method",
129
+ "name": "handleSlotContent",
130
+ "description": "Mirrors any defined custom type svg into the correct place in the template.",
131
+ "privacy": "private",
132
+ "return": {
133
+ "type": {
134
+ "text": "void"
135
+ }
136
+ }
137
+ },
138
+ {
139
+ "kind": "field",
140
+ "name": "noIcon",
141
+ "privacy": "public",
142
+ "type": {
143
+ "text": "boolean"
144
+ },
145
+ "description": "Removes icon from the toast UI.",
146
+ "attribute": "noicon",
147
+ "reflects": true
148
+ },
149
+ {
150
+ "kind": "method",
151
+ "name": "register",
152
+ "static": true,
153
+ "parameters": [
154
+ {
155
+ "name": "name",
156
+ "default": "\"auro-toast\"",
157
+ "description": "The name of the element that you want to register.",
158
+ "optional": true,
159
+ "type": {
160
+ "text": "string"
161
+ }
162
+ }
163
+ ],
164
+ "description": "This will register this element with the browser.",
165
+ "type": {
166
+ "text": "register(name?: string = \"auro-toast\") => void"
167
+ }
168
+ },
169
+ {
170
+ "kind": "method",
171
+ "name": "setOnClick",
172
+ "description": "For mobile, set the onclick function so the toast can be dismissed if it is tapped on anywhere inside the toast.",
173
+ "privacy": "private",
174
+ "return": {
175
+ "type": {
176
+ "text": "void"
177
+ }
178
+ }
179
+ },
180
+ {
181
+ "kind": "field",
182
+ "name": "timeTilHide",
183
+ "privacy": "public",
184
+ "type": {
185
+ "text": "number"
186
+ },
187
+ "description": "Sets the time in milliseconds until the toast hides.",
188
+ "attribute": "timetilhide",
189
+ "reflects": true
190
+ },
191
+ {
192
+ "kind": "field",
193
+ "name": "trigger",
194
+ "privacy": "public",
195
+ "type": {
196
+ "text": "string"
197
+ },
198
+ "description": "The id of the element that triggered the toast.\nWhen the toast is manually closed, focus will return to this element.\nTakes precedence over the triggerElement property if both are set.",
199
+ "attribute": "trigger",
200
+ "reflects": true
201
+ },
202
+ {
203
+ "kind": "field",
204
+ "name": "triggerElement",
205
+ "privacy": "public",
206
+ "type": {
207
+ "text": "HTMLElement"
208
+ },
209
+ "description": "A direct reference to the element that triggered the toast.\nWhen the toast is manually closed, focus will return to this element.\nUse the trigger attribute instead if you prefer a declarative approach."
210
+ },
211
+ {
212
+ "kind": "field",
213
+ "name": "variant",
214
+ "privacy": "public",
215
+ "type": {
216
+ "text": "'error' | 'success' | 'custom'"
217
+ },
218
+ "description": "Component will render visually based on which variant value is set.",
219
+ "attribute": "variant",
220
+ "reflects": true
221
+ },
222
+ {
223
+ "kind": "field",
224
+ "name": "visible",
225
+ "privacy": "public",
226
+ "type": {
227
+ "text": "boolean"
228
+ },
229
+ "description": "Sets state of toast to visible",
230
+ "attribute": "visible",
231
+ "reflects": true
232
+ }
233
+ ],
234
+ "events": [
235
+ {
236
+ "name": "toast-close",
237
+ "type": {
238
+ "text": "{ visible: boolean }"
239
+ },
240
+ "description": "Notifies that the toast has been closed. `detail` is `{ visible: false }`."
241
+ },
242
+ {
243
+ "name": "onToastClose",
244
+ "type": {
245
+ "text": "Object"
246
+ },
247
+ "description": "**Deprecated**, use `toast-close` event instead. Note: `detail` is the toast element, not `{ visible }` — the two events do not share a payload shape.",
248
+ "deprecated": "Use `toast-close` event instead."
249
+ }
250
+ ],
251
+ "attributes": [
252
+ {
253
+ "name": "disableautohide",
254
+ "type": {
255
+ "text": "boolean"
256
+ },
257
+ "description": "Prevents the toast from auto-hiding on the default time.",
258
+ "fieldName": "disableAutoHide"
259
+ },
260
+ {
261
+ "name": "noicon",
262
+ "type": {
263
+ "text": "boolean"
264
+ },
265
+ "description": "Removes icon from the toast UI.",
266
+ "fieldName": "noIcon"
267
+ },
268
+ {
269
+ "name": "timetilhide",
270
+ "type": {
271
+ "text": "number"
272
+ },
273
+ "description": "Sets the time in milliseconds until the toast hides.",
274
+ "fieldName": "timeTilHide"
275
+ },
276
+ {
277
+ "name": "trigger",
278
+ "type": {
279
+ "text": "string"
280
+ },
281
+ "description": "The id of the element that triggered the toast.\nWhen the toast is manually closed, focus will return to this element.\nTakes precedence over the triggerElement property if both are set.",
282
+ "fieldName": "trigger"
283
+ },
284
+ {
285
+ "name": "variant",
286
+ "type": {
287
+ "text": "'error' | 'success' | 'custom'"
288
+ },
289
+ "description": "Component will render visually based on which variant value is set.",
290
+ "fieldName": "variant"
291
+ },
292
+ {
293
+ "name": "visible",
294
+ "type": {
295
+ "text": "boolean"
296
+ },
297
+ "description": "Sets state of toast to visible",
298
+ "fieldName": "visible"
299
+ }
300
+ ],
301
+ "superclass": {
302
+ "name": "LitElement",
303
+ "package": "lit"
304
+ },
305
+ "tagName": "auro-toast",
306
+ "customElement": true,
307
+ "modulePath": "src/auro-toast.js"
308
+ }
309
+ ],
310
+ "exports": [
311
+ {
312
+ "kind": "js",
313
+ "name": "AuroToast",
314
+ "declaration": {
315
+ "name": "AuroToast",
316
+ "module": "src/auro-toast.js"
317
+ }
318
+ }
319
+ ]
320
+ },
321
+ {
322
+ "kind": "javascript-module",
323
+ "path": "src/auro-toaster.js",
324
+ "declarations": [
325
+ {
326
+ "kind": "class",
327
+ "description": "",
328
+ "name": "AuroToaster",
329
+ "members": [
330
+ {
331
+ "kind": "field",
332
+ "name": "_announcedErrorToasts",
333
+ "default": "new WeakSet()"
334
+ },
335
+ {
336
+ "kind": "field",
337
+ "name": "_assertiveResetTimer",
338
+ "default": "undefined"
339
+ },
340
+ {
341
+ "kind": "method",
342
+ "name": "_onSlotChange",
343
+ "parameters": [
344
+ {
345
+ "name": "e"
346
+ }
347
+ ],
348
+ "description": "Handles slot changes — checks if a newly slotted error toast\nis already visible at the time it is added to the toaster.",
349
+ "privacy": "private"
350
+ },
351
+ {
352
+ "kind": "field",
353
+ "name": "_onToastRequestAnnounce"
354
+ },
355
+ {
356
+ "kind": "method",
357
+ "name": "_setAssertiveTemporarily",
358
+ "description": "Temporarily sets the live region to assertive so the error toast\ninterrupts the screen reader, then resets to polite after 3 seconds.\nThis ensures subsequent polite toasts don't keep interrupting the user,\neven if the error toast remains visible (errors are never auto-dismissed).",
359
+ "privacy": "private"
360
+ },
361
+ {
362
+ "kind": "method",
363
+ "name": "register",
364
+ "static": true,
365
+ "parameters": [
366
+ {
367
+ "name": "name",
368
+ "default": "\"auro-toaster\"",
369
+ "description": "The name of the element that you want to register to.",
370
+ "optional": true,
371
+ "type": {
372
+ "text": "string"
373
+ }
374
+ }
375
+ ],
376
+ "description": "This will register this element with the browser."
377
+ }
378
+ ],
379
+ "superclass": {
380
+ "name": "LitElement",
381
+ "package": "lit"
382
+ },
383
+ "customElement": true,
384
+ "modulePath": "src/auro-toaster.js"
385
+ }
386
+ ],
387
+ "exports": [
388
+ {
389
+ "kind": "js",
390
+ "name": "AuroToaster",
391
+ "declaration": {
392
+ "name": "AuroToaster",
393
+ "module": "src/auro-toaster.js"
394
+ }
395
+ }
396
+ ]
397
+ },
398
+ {
399
+ "kind": "javascript-module",
400
+ "path": "src/buttonVersion.js",
401
+ "declarations": [],
402
+ "exports": [
403
+ {
404
+ "kind": "js",
405
+ "name": "default",
406
+ "declaration": {
407
+ "name": "12.3.2",
408
+ "module": "src/buttonVersion.js"
409
+ }
410
+ }
411
+ ]
412
+ },
413
+ {
414
+ "kind": "javascript-module",
415
+ "path": "src/iconVersion.js",
416
+ "declarations": [],
417
+ "exports": [
418
+ {
419
+ "kind": "js",
420
+ "name": "default",
421
+ "declaration": {
422
+ "name": "9.2.0",
423
+ "module": "src/iconVersion.js"
424
+ }
425
+ }
426
+ ]
427
+ },
428
+ {
429
+ "kind": "javascript-module",
430
+ "path": "src/index.js",
431
+ "declarations": [],
432
+ "exports": [
433
+ {
434
+ "kind": "js",
435
+ "name": "AuroToast",
436
+ "declaration": {
437
+ "name": "AuroToast",
438
+ "module": "src/index.js"
439
+ }
440
+ },
441
+ {
442
+ "kind": "js",
443
+ "name": "AuroToaster",
444
+ "declaration": {
445
+ "name": "AuroToaster",
446
+ "module": "src/index.js"
447
+ }
448
+ }
449
+ ]
450
+ },
451
+ {
452
+ "kind": "javascript-module",
453
+ "path": "src/registered.js",
454
+ "declarations": [],
455
+ "exports": []
456
+ }
457
+ ]
458
+ }
package/demo/api.md CHANGED
@@ -25,10 +25,10 @@ The `auro-toast` element provides users a way to display short, temporary messag
25
25
 
26
26
  ### Events
27
27
 
28
- | Name | Description |
29
- | ------------ | -------------------------------------------------- |
30
- | toast-close | Notifies that the toast has been closed |
31
- | onToastClose | ** Deprecated **, use `toast-close` event instead. |
28
+ | Name | Description |
29
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
30
+ | toast-close | Notifies that the toast has been closed. `detail` is `{ visible: false }`. |
31
+ | onToastClose | **Deprecated**, use `toast-close` event instead. Note: `detail` is the toast element, not `{ visible }` — the two events do not share a payload shape. |
32
32
 
33
33
  ### CSS Shadow Parts
34
34
 
@@ -514,7 +514,7 @@ export function initDynamicToastsExample() {
514
514
  console.log("Toast added:", toastId);
515
515
  ​
516
516
  // optional cleanup if your component doesn't auto-remove itself
517
- toast.addEventListener("onToastClose", () =&gt; {
517
+ toast.addEventListener("toast-close", () =&gt; {
518
518
  activeToasts.delete(toastId);
519
519
  });
520
520
  });
package/demo/api.min.js CHANGED
@@ -182,7 +182,7 @@ function initDynamicToastsExample() {
182
182
  console.log("Toast added:", toastId);
183
183
 
184
184
  // optional cleanup if your component doesn't auto-remove itself
185
- toast.addEventListener("onToastClose", () => {
185
+ toast.addEventListener("toast-close", () => {
186
186
  activeToasts.delete(toastId);
187
187
  });
188
188
  });
@@ -538,8 +538,8 @@ const FADE_OUT_DURATION = 300;
538
538
  *
539
539
  * @csspart type-icon - Apply css to the toast type icon
540
540
  * @csspart close-button - Apply css to the toast close button
541
- * @fires onToastClose - ** Deprecated **, use `toast-close` event instead.
542
- * @event toast-close - Notifies that the toast has been closed
541
+ * @fires onToastClose - **Deprecated**, use `toast-close` event instead. Note: `detail` is the toast element, not `{ visible }` — the two events do not share a payload shape.
542
+ * @event toast-close - Notifies that the toast has been closed. `detail` is `{ visible: false }`.
543
543
  */
544
544
 
545
545
  // build the component class
@@ -625,6 +625,11 @@ class AuroToast extends i$2 {
625
625
  */
626
626
  this.fadeOutTimer = undefined;
627
627
 
628
+ /**
629
+ * @private
630
+ */
631
+ this.fadeOutCompleteTimer = undefined;
632
+
628
633
  /**
629
634
  * True when the toast is not inside an auro-toaster and must manage its
630
635
  * own live region announcement. Set once in connectedCallback.
@@ -752,7 +757,6 @@ class AuroToast extends i$2 {
752
757
  clickToClose() {
753
758
  this._returnFocus();
754
759
  this.closeToast();
755
- clearTimeout(this.fadeOutTimer);
756
760
  }
757
761
 
758
762
  /**
@@ -760,16 +764,37 @@ class AuroToast extends i$2 {
760
764
  * @returns {void}
761
765
  */
762
766
  fadeOutToast() {
763
- if (!this.disableAutoHide) {
764
- const toastContainer = this.shadowRoot.querySelector(".toastContainer");
765
- if (toastContainer) {
766
- toastContainer.classList.add("hidden");
767
- }
767
+ // Guards against arming a redundant completion timer: when this fires
768
+ // after the toast is already closed (e.g. the mobile tap-to-dismiss
769
+ // handler runs after the close button's own click already closed it),
770
+ // or auto-hide is disabled.
771
+ if (!this.visible || this.disableAutoHide) {
772
+ return;
773
+ }
768
774
 
769
- setTimeout(() => {
770
- this.closeToast();
771
- }, FADE_OUT_DURATION);
775
+ const toastContainer = this.shadowRoot.querySelector(".toastContainer");
776
+ if (toastContainer) {
777
+ toastContainer.classList.add("hidden");
772
778
  }
779
+
780
+ clearTimeout(this.fadeOutCompleteTimer);
781
+ this.fadeOutCompleteTimer = setTimeout(() => {
782
+ this.closeToast();
783
+ }, FADE_OUT_DURATION);
784
+ }
785
+
786
+ /**
787
+ * Cancels an in-progress fade-out, if any, and restores the toast's
788
+ * visibility. Without this, interrupting a fade (e.g. escalating to
789
+ * variant="error" mid-fade) would clear the pending close but leave the
790
+ * "hidden" CSS class in place, permanently hiding a toast that remains
791
+ * open.
792
+ * @private
793
+ * @returns {void}
794
+ */
795
+ _cancelFadeOut() {
796
+ clearTimeout(this.fadeOutCompleteTimer);
797
+ this.shadowRoot?.querySelector(".toastContainer")?.classList.remove("hidden");
773
798
  }
774
799
 
775
800
  /**
@@ -778,6 +803,14 @@ class AuroToast extends i$2 {
778
803
  */
779
804
  closeToast() {
780
805
  clearTimeout(this.fadeOutTimer);
806
+ clearTimeout(this.fadeOutCompleteTimer);
807
+
808
+ // Idempotent: a close already in flight (e.g. the close button clicked
809
+ // while the auto-hide fade-out is in progress) must not dispatch twice.
810
+ if (!this.visible) {
811
+ return;
812
+ }
813
+
781
814
  this.visible = false;
782
815
 
783
816
  /**
@@ -785,13 +818,13 @@ class AuroToast extends i$2 {
785
818
  *
786
819
  * @deprecated Use `toast-close` event instead.
787
820
  * @event onToastClose
788
- * @type {{ visible: boolean }}
821
+ * @type {Object}
789
822
  */
790
823
  this.dispatchEvent(
791
824
  new CustomEvent("onToastClose", {
792
825
  bubbles: true,
793
826
  composed: true,
794
- detail: this,
827
+ detail: this, // unchanged for backwards compatibility; use `toast-close` for the new `{ visible }` shape
795
828
  }),
796
829
  );
797
830
 
@@ -805,7 +838,7 @@ class AuroToast extends i$2 {
805
838
  new CustomEvent("toast-close", {
806
839
  bubbles: true,
807
840
  composed: true,
808
- detail: this,
841
+ detail: { visible: false },
809
842
  }),
810
843
  );
811
844
  }
@@ -843,6 +876,14 @@ class AuroToast extends i$2 {
843
876
  super.connectedCallback();
844
877
  this.setOnClick();
845
878
 
879
+ // On a reconnect (hasUpdated is false on the initial connection, which
880
+ // Lit's own first-update cycle already handles), force updated() to
881
+ // re-run so a visible toast's auto-hide timer — cleared by
882
+ // disconnectedCallback() — gets re-armed instead of being lost forever.
883
+ if (this.hasUpdated && this.visible) {
884
+ this.requestUpdate();
885
+ }
886
+
846
887
  // Dispatch a cancelable event so auro-toaster can signal it will handle
847
888
  // announcements. If nothing cancels the event the toast is standalone and
848
889
  // must register its own live region on the host element — before
@@ -871,6 +912,17 @@ class AuroToast extends i$2 {
871
912
  this._syncStandaloneRole();
872
913
  }
873
914
 
915
+ disconnectedCallback() {
916
+ super.disconnectedCallback();
917
+ clearTimeout(this.fadeOutTimer);
918
+
919
+ // Not just clearTimeout(this.fadeOutCompleteTimer) — a reconnect's bare
920
+ // requestUpdate() delivers empty changedProperties, so updated()'s
921
+ // variant/disableAutoHide cancel branch won't run to remove a "hidden"
922
+ // class left over from a fade that was in progress at disconnect time.
923
+ this._cancelFadeOut();
924
+ }
925
+
874
926
  /**
875
927
  * Sets or removes the live-region role on the host depending on whether
876
928
  * the toast is standalone. Extracted so connectedCallback and updated()
@@ -912,6 +964,14 @@ class AuroToast extends i$2 {
912
964
  updated(changedProperties) {
913
965
  if (changedProperties.has("visible")) {
914
966
  this.handleSlotContent();
967
+
968
+ // Setting `visible` to false directly (bypassing closeToast()) would
969
+ // otherwise leave a pending fadeOutCompleteTimer armed; if `visible`
970
+ // is then set back to true before it fires, it would instantly
971
+ // re-close the freshly-reshown toast.
972
+ if (!this.visible) {
973
+ this._cancelFadeOut();
974
+ }
915
975
  }
916
976
 
917
977
  // Keep the standalone role in sync if variant changes after connection.
@@ -920,8 +980,24 @@ class AuroToast extends i$2 {
920
980
  this._syncStandaloneRole();
921
981
  }
922
982
 
983
+ // Cancel an in-flight fade-out when the toast becomes ineligible for
984
+ // auto-dismiss (escalated to variant="error", or disableAutoHide set) —
985
+ // a stale completion timer must not auto-close a now-persistent toast.
986
+ if (
987
+ (changedProperties.has("variant") || changedProperties.has("disableAutoHide")) &&
988
+ (this.variant === "error" || this.disableAutoHide)
989
+ ) {
990
+ this._cancelFadeOut();
991
+ }
992
+
923
993
  // do not auto dismiss for error toasts or if disableAutoHide is set
924
- if (this.visible && !this.disableAutoHide && this.variant !== "error") {
994
+ // Note: intentionally does not clear fadeOutCompleteTimer — this block
995
+ // re-runs on every update while visible, and clearing it here would
996
+ // cancel an in-flight fade-out on any unrelated property change.
997
+ // isConnected guards against requestUpdate()'s microtask resolving
998
+ // after a rapid disconnect, which would otherwise arm a timer on an
999
+ // already-detached element.
1000
+ if (this.isConnected && this.visible && !this.disableAutoHide && this.variant !== "error") {
925
1001
  clearTimeout(this.fadeOutTimer);
926
1002
  this.fadeOutTimer = setTimeout(() => {
927
1003
  this.fadeOutToast();