ga-toasts 2.0.0 → 2.1.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 +67 -7
- package/dist/ga-toasts.css +61 -7
- package/dist/ga-toasts.global.js +1 -555
- package/dist/index.cjs +1117 -1389
- package/dist/index.d.cts +118 -45
- package/dist/index.d.ts +118 -45
- package/dist/index.js +1117 -1390
- package/package.json +18 -5
package/dist/index.js
CHANGED
|
@@ -1,580 +1,18 @@
|
|
|
1
1
|
// src/styles.generated.ts
|
|
2
|
-
var css = `/**
|
|
3
|
-
* GA Toasts 2.x \u2014 stylesheet.
|
|
4
|
-
*
|
|
5
|
-
* Self-contained: all design tokens are namespaced (--gat-*) and scoped to the
|
|
6
|
-
* toast elements so they never collide with a host app's own variables.
|
|
7
|
-
* Vertical position + stacking is driven by inline transforms from the engine;
|
|
8
|
-
* this file only styles the cards and provides the transition timing.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/* ---------------- Design tokens ---------------- */
|
|
12
|
-
.ga-toast-container {
|
|
13
|
-
--gat-width: 380px;
|
|
14
|
-
--gat-radius: 14px;
|
|
15
|
-
--gat-gap: 14px;
|
|
16
|
-
--gat-edge: 22px;
|
|
17
|
-
|
|
18
|
-
--gat-font: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
19
|
-
Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
20
|
-
|
|
21
|
-
--gat-surface: rgba(255, 255, 255, 0.82);
|
|
22
|
-
--gat-surface-solid: #ffffff;
|
|
23
|
-
--gat-border: rgba(15, 23, 42, 0.07);
|
|
24
|
-
--gat-ring: rgba(15, 23, 42, 0.05); /* hairline definition ring */
|
|
25
|
-
--gat-highlight: rgba(255, 255, 255, 0.75); /* inset top edge highlight */
|
|
26
|
-
--gat-text: #0f172a;
|
|
27
|
-
--gat-text-soft: #475569;
|
|
28
|
-
--gat-text-muted: #64748b; /* meets WCAG AA on the surface */
|
|
29
|
-
--gat-shadow: 0 1px 2px rgba(15, 23, 42, 0.05),
|
|
30
|
-
0 8px 20px -12px rgba(15, 23, 42, 0.16);
|
|
31
|
-
--gat-shadow-hover: 0 2px 4px -2px rgba(15, 23, 42, 0.12),
|
|
32
|
-
0 14px 32px -12px rgba(15, 23, 42, 0.26);
|
|
33
|
-
--gat-chip: rgba(15, 23, 42, 0.05);
|
|
34
|
-
|
|
35
|
-
--gat-success: #16a34a;
|
|
36
|
-
--gat-error: #e11d48;
|
|
37
|
-
--gat-warning: #d97706;
|
|
38
|
-
--gat-info: #2563eb;
|
|
39
|
-
--gat-primary: #6366f1;
|
|
40
|
-
--gat-secondary: #64748b;
|
|
41
|
-
--gat-loading: #2563eb;
|
|
42
|
-
|
|
43
|
-
--gat-ease: cubic-bezier(0.22, 1, 0.36, 1);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/* Dark theme \u2014 via explicit attribute/class or the OS preference. */
|
|
47
|
-
[data-ga-theme="dark"] .ga-toast-container,
|
|
48
|
-
.ga-theme-dark .ga-toast-container,
|
|
49
|
-
.ga-toast-container.ga-theme-dark {
|
|
50
|
-
--gat-surface: rgba(24, 27, 34, 0.82);
|
|
51
|
-
--gat-surface-solid: #191c22;
|
|
52
|
-
--gat-border: rgba(255, 255, 255, 0.09);
|
|
53
|
-
--gat-ring: rgba(255, 255, 255, 0.06);
|
|
54
|
-
--gat-highlight: rgba(255, 255, 255, 0.07);
|
|
55
|
-
--gat-text: #f8fafc;
|
|
56
|
-
--gat-text-soft: #cbd5e1;
|
|
57
|
-
--gat-text-muted: #9aa7ba;
|
|
58
|
-
--gat-shadow: 0 1px 2px rgba(0, 0, 0, 0.35),
|
|
59
|
-
0 10px 28px -14px rgba(0, 0, 0, 0.5);
|
|
60
|
-
--gat-shadow-hover: 0 2px 6px -2px rgba(0, 0, 0, 0.5),
|
|
61
|
-
0 16px 38px -12px rgba(0, 0, 0, 0.64);
|
|
62
|
-
--gat-chip: rgba(255, 255, 255, 0.08);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/* Auto (OS) dark mode \u2014 applies ONLY when no explicit theme is set on the root,
|
|
66
|
-
so an app that pins data-ga-theme="light" (like the demo) is never overridden. */
|
|
67
|
-
@media (prefers-color-scheme: dark) {
|
|
68
|
-
:root:not([data-ga-theme]):not(.ga-theme-light):not(.ga-theme-dark) .ga-toast-container {
|
|
69
|
-
--gat-surface: rgba(24, 27, 34, 0.82);
|
|
70
|
-
--gat-surface-solid: #191c22;
|
|
71
|
-
--gat-border: rgba(255, 255, 255, 0.09);
|
|
72
|
-
--gat-ring: rgba(255, 255, 255, 0.06);
|
|
73
|
-
--gat-highlight: rgba(255, 255, 255, 0.07);
|
|
74
|
-
--gat-text: #f8fafc;
|
|
75
|
-
--gat-text-soft: #cbd5e1;
|
|
76
|
-
--gat-text-muted: #9aa7ba;
|
|
77
|
-
--gat-shadow: 0 1px 2px rgba(0, 0, 0, 0.35),
|
|
78
|
-
0 10px 28px -14px rgba(0, 0, 0, 0.5);
|
|
79
|
-
--gat-chip: rgba(255, 255, 255, 0.08);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/* ---------------- Modal backdrop (confirm) ---------------- */
|
|
84
|
-
.ga-toast-backdrop {
|
|
85
|
-
position: fixed;
|
|
86
|
-
inset: 0;
|
|
87
|
-
z-index: 2147482990; /* just under the toast containers */
|
|
88
|
-
background: rgba(10, 12, 20, 0.42);
|
|
89
|
-
backdrop-filter: blur(2px);
|
|
90
|
-
-webkit-backdrop-filter: blur(2px);
|
|
91
|
-
opacity: 0;
|
|
92
|
-
transition: opacity 0.22s ease;
|
|
93
|
-
}
|
|
94
|
-
.ga-toast-backdrop-show { opacity: 1; }
|
|
95
|
-
@media (prefers-reduced-transparency: reduce) {
|
|
96
|
-
.ga-toast-backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; }
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/* ---------------- Container + positioning ---------------- */
|
|
100
|
-
.ga-toast-container {
|
|
101
|
-
position: fixed;
|
|
102
|
-
z-index: 2147483000;
|
|
103
|
-
width: var(--gat-width);
|
|
104
|
-
max-width: calc(100vw - 2 * var(--gat-edge));
|
|
105
|
-
pointer-events: none;
|
|
106
|
-
font-family: var(--gat-font);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/* Logical inline positioning so -start/-end mirror automatically under RTL. */
|
|
110
|
-
.ga-toast-container-top-start { inset-block-start: var(--gat-edge); inset-inline-start: var(--gat-edge); }
|
|
111
|
-
.ga-toast-container-top-end { inset-block-start: var(--gat-edge); inset-inline-end: var(--gat-edge); }
|
|
112
|
-
.ga-toast-container-top-center {
|
|
113
|
-
inset-block-start: var(--gat-edge); left: 50%; transform: translateX(-50%);
|
|
114
|
-
}
|
|
115
|
-
.ga-toast-container-bottom-start { inset-block-end: var(--gat-edge); inset-inline-start: var(--gat-edge); }
|
|
116
|
-
.ga-toast-container-bottom-end { inset-block-end: var(--gat-edge); inset-inline-end: var(--gat-edge); }
|
|
117
|
-
.ga-toast-container-bottom-center {
|
|
118
|
-
inset-block-end: var(--gat-edge); left: 50%; transform: translateX(-50%);
|
|
119
|
-
}
|
|
120
|
-
.ga-toast-container-middle-start { top: 50%; inset-inline-start: var(--gat-edge); }
|
|
121
|
-
.ga-toast-container-middle-end { top: 50%; inset-inline-end: var(--gat-edge); }
|
|
122
|
-
.ga-toast-container-middle-center { top: 50%; left: 50%; transform: translateX(-50%); }
|
|
123
|
-
|
|
124
|
-
/* ---------------- Toast card ---------------- */
|
|
125
|
-
.ga-toast {
|
|
126
|
-
position: absolute;
|
|
127
|
-
inset-inline: 0;
|
|
128
|
-
width: 100%;
|
|
129
|
-
box-sizing: border-box;
|
|
130
|
-
display: flex;
|
|
131
|
-
flex-direction: row;
|
|
132
|
-
align-items: flex-start;
|
|
133
|
-
gap: 11px;
|
|
134
|
-
padding: 14px 16px;
|
|
135
|
-
color: var(--gat-text);
|
|
136
|
-
background: var(--gat-surface-solid);
|
|
137
|
-
border: none;
|
|
138
|
-
border-radius: var(--gat-radius);
|
|
139
|
-
box-shadow:
|
|
140
|
-
var(--gat-shadow),
|
|
141
|
-
inset 0 1px 0 var(--gat-highlight);
|
|
142
|
-
pointer-events: auto;
|
|
143
|
-
opacity: 0;
|
|
144
|
-
transform: translateY(-140%);
|
|
145
|
-
transition:
|
|
146
|
-
transform 0.5s var(--gat-ease),
|
|
147
|
-
opacity 0.35s ease,
|
|
148
|
-
box-shadow 0.2s ease;
|
|
149
|
-
will-change: transform, opacity;
|
|
150
|
-
overflow: hidden;
|
|
151
|
-
font-size: 0.875rem;
|
|
152
|
-
line-height: 1.5;
|
|
153
|
-
-webkit-font-smoothing: antialiased;
|
|
154
|
-
text-align: start;
|
|
155
|
-
touch-action: pan-y;
|
|
156
|
-
overscroll-behavior: contain;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/* Subtle lift on hover (shadow only \u2014 transforms are owned by the engine, so
|
|
160
|
-
changing them here would fight the stack layout). */
|
|
161
|
-
@media (hover: hover) {
|
|
162
|
-
.ga-toast:hover {
|
|
163
|
-
box-shadow:
|
|
164
|
-
var(--gat-shadow-hover),
|
|
165
|
-
inset 0 1px 0 var(--gat-highlight);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
[data-ga-position^="top"] .ga-toast,
|
|
170
|
-
[data-ga-position^="middle"] .ga-toast { top: 0; transform-origin: top center; }
|
|
171
|
-
[data-ga-position^="bottom"] .ga-toast { bottom: 0; transform-origin: bottom center; }
|
|
172
|
-
|
|
173
|
-
.ga-toast-glass {
|
|
174
|
-
background: var(--gat-surface);
|
|
175
|
-
backdrop-filter: blur(16px) saturate(160%);
|
|
176
|
-
-webkit-backdrop-filter: blur(16px) saturate(160%);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/* No leading accent stripe \u2014 the colored icon carries the type identity, for a
|
|
180
|
-
cleaner, more minimal card (\xE0 la Sonner/Linear). */
|
|
181
|
-
|
|
182
|
-
.ga-toast-hide { pointer-events: none; }
|
|
183
|
-
|
|
184
|
-
/* Per-type accent colors. */
|
|
185
|
-
.ga-toast-success { --gat-accent: var(--gat-success); }
|
|
186
|
-
.ga-toast-error { --gat-accent: var(--gat-error); }
|
|
187
|
-
.ga-toast-warning { --gat-accent: var(--gat-warning); }
|
|
188
|
-
.ga-toast-info { --gat-accent: var(--gat-info); }
|
|
189
|
-
.ga-toast-primary { --gat-accent: var(--gat-primary); }
|
|
190
|
-
.ga-toast-secondary { --gat-accent: var(--gat-secondary); }
|
|
191
|
-
.ga-toast-loading { --gat-accent: var(--gat-loading); }
|
|
192
|
-
|
|
193
|
-
/* ---------------- Content column ---------------- */
|
|
194
|
-
/* The content column sits between the leading icon and the trailing close. */
|
|
195
|
-
.ga-toast-content {
|
|
196
|
-
display: flex;
|
|
197
|
-
flex-direction: column;
|
|
198
|
-
gap: 4px;
|
|
199
|
-
flex: 1;
|
|
200
|
-
min-width: 0;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.ga-toast-header {
|
|
204
|
-
display: flex;
|
|
205
|
-
align-items: center;
|
|
206
|
-
gap: 8px;
|
|
207
|
-
min-width: 0;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/* Small inline colored glyph \u2014 no chunky chip (Sonner/Linear style). Leads the
|
|
211
|
-
row and aligns with the first line of text, so title-less toasts read well. */
|
|
212
|
-
.ga-toast-icon {
|
|
213
|
-
flex-shrink: 0;
|
|
214
|
-
display: inline-flex;
|
|
215
|
-
align-items: center;
|
|
216
|
-
justify-content: center;
|
|
217
|
-
margin-top: 1px;
|
|
218
|
-
color: var(--gat-accent, var(--gat-info));
|
|
219
|
-
}
|
|
220
|
-
.ga-toast-icon svg { width: 1.25rem; height: 1.25rem; display: block; overflow: visible; }
|
|
221
|
-
|
|
222
|
-
.ga-toast-spinner { animation: ga-toast-spin 0.8s linear infinite; }
|
|
223
|
-
|
|
224
|
-
/* Icons draw themselves in on mount (skipped under reduced motion). */
|
|
225
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
226
|
-
.ga-toast-icon .ga-ic-ring {
|
|
227
|
-
stroke-dasharray: 64;
|
|
228
|
-
stroke-dashoffset: 64;
|
|
229
|
-
animation: ga-toast-ic-draw 0.5s var(--gat-ease) 0.02s forwards;
|
|
230
|
-
}
|
|
231
|
-
.ga-toast-icon .ga-ic-draw {
|
|
232
|
-
stroke-dasharray: 28;
|
|
233
|
-
stroke-dashoffset: 28;
|
|
234
|
-
animation: ga-toast-ic-draw 0.4s var(--gat-ease) 0.16s forwards;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
@keyframes ga-toast-ic-draw {
|
|
238
|
-
to { stroke-dashoffset: 0; }
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
.ga-toast-avatar {
|
|
242
|
-
flex-shrink: 0;
|
|
243
|
-
width: 34px;
|
|
244
|
-
height: 34px;
|
|
245
|
-
border-radius: 50%;
|
|
246
|
-
object-fit: cover;
|
|
247
|
-
border: 1px solid var(--gat-border);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
.ga-toast-unread-dot {
|
|
251
|
-
flex-shrink: 0;
|
|
252
|
-
width: 8px;
|
|
253
|
-
height: 8px;
|
|
254
|
-
border-radius: 50%;
|
|
255
|
-
background: var(--gat-accent, var(--gat-info));
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
.ga-toast-title {
|
|
259
|
-
font-weight: 600;
|
|
260
|
-
font-size: 0.9rem;
|
|
261
|
-
color: var(--gat-text);
|
|
262
|
-
flex: 1;
|
|
263
|
-
min-width: 0;
|
|
264
|
-
letter-spacing: -0.011em;
|
|
265
|
-
}
|
|
266
|
-
.ga-toast-title-truncate {
|
|
267
|
-
white-space: nowrap;
|
|
268
|
-
overflow: hidden;
|
|
269
|
-
text-overflow: ellipsis;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
.ga-toast-status {
|
|
273
|
-
flex-shrink: 0;
|
|
274
|
-
padding: 2px 9px;
|
|
275
|
-
border-radius: 999px;
|
|
276
|
-
font-size: 0.6875rem;
|
|
277
|
-
font-weight: 600;
|
|
278
|
-
text-transform: uppercase;
|
|
279
|
-
letter-spacing: 0.04em;
|
|
280
|
-
/* Darkened accent ink on a stronger tint so the small label clears AA. */
|
|
281
|
-
color: var(--gat-accent, var(--gat-info));
|
|
282
|
-
color: color-mix(in srgb, var(--gat-accent, var(--gat-info)) 58%, var(--gat-text));
|
|
283
|
-
background: var(--gat-chip); /* fallback if color-mix is unsupported */
|
|
284
|
-
background: color-mix(in srgb, var(--gat-accent, var(--gat-info)) 18%, transparent);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/* ---------------- Close button ---------------- */
|
|
288
|
-
.ga-toast-close {
|
|
289
|
-
flex-shrink: 0;
|
|
290
|
-
align-self: flex-start;
|
|
291
|
-
margin-top: -1px;
|
|
292
|
-
margin-inline-end: -4px; /* pull toward the corner without losing hit area */
|
|
293
|
-
display: inline-flex;
|
|
294
|
-
align-items: center;
|
|
295
|
-
justify-content: center;
|
|
296
|
-
width: 26px;
|
|
297
|
-
height: 26px;
|
|
298
|
-
padding: 0;
|
|
299
|
-
border: none;
|
|
300
|
-
border-radius: 7px;
|
|
301
|
-
color: var(--gat-text-muted);
|
|
302
|
-
background: transparent;
|
|
303
|
-
cursor: pointer;
|
|
304
|
-
opacity: 0.9; /* stays >=3:1 at rest; full on hover/focus */
|
|
305
|
-
transition: background 0.15s ease, color 0.15s ease, opacity 0.15s ease;
|
|
306
|
-
}
|
|
307
|
-
.ga-toast:hover .ga-toast-close,
|
|
308
|
-
.ga-toast:focus-within .ga-toast-close { opacity: 1; }
|
|
309
|
-
.ga-toast-close svg { width: 15px; height: 15px; display: block; }
|
|
310
|
-
.ga-toast-close:hover {
|
|
311
|
-
background: var(--gat-chip);
|
|
312
|
-
color: var(--gat-text);
|
|
313
|
-
}
|
|
314
|
-
/* currentColor is guaranteed to contrast with its own surface (white on filled,
|
|
315
|
-
muted on default, etc.), so the focus ring is never accent-on-accent. */
|
|
316
|
-
.ga-toast-close:focus-visible {
|
|
317
|
-
outline: 2px solid currentColor;
|
|
318
|
-
outline-offset: 2px;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/* ---------------- Body ---------------- */
|
|
322
|
-
.ga-toast-body { min-width: 0; }
|
|
323
|
-
.ga-toast-meta {
|
|
324
|
-
font-size: 0.75rem;
|
|
325
|
-
color: var(--gat-text-muted);
|
|
326
|
-
margin-bottom: 2px;
|
|
327
|
-
}
|
|
328
|
-
.ga-toast-message {
|
|
329
|
-
color: var(--gat-text-soft);
|
|
330
|
-
font-size: 0.85rem;
|
|
331
|
-
word-break: break-word;
|
|
332
|
-
/* Clamp very long content so a toast can't fill the viewport. */
|
|
333
|
-
max-height: 40vh;
|
|
334
|
-
overflow-y: auto;
|
|
335
|
-
overscroll-behavior: contain;
|
|
336
|
-
}
|
|
337
|
-
.ga-toast-message a {
|
|
338
|
-
color: var(--gat-accent, var(--gat-info));
|
|
339
|
-
font-weight: 500;
|
|
340
|
-
text-decoration: underline; /* affordance beyond color (WCAG 1.4.1) */
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/* When there's no header, let the message carry the toast on its own \u2014 but not
|
|
344
|
-
on filled toasts, whose message must stay light (specificity guard). */
|
|
345
|
-
.ga-toast:not([class*="-filled"]) .ga-toast-content > .ga-toast-body:only-child .ga-toast-message {
|
|
346
|
-
color: var(--gat-text);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/* ---------------- Actions ---------------- */
|
|
350
|
-
.ga-toast-actions {
|
|
351
|
-
display: flex;
|
|
352
|
-
gap: 8px;
|
|
353
|
-
margin-top: 2px;
|
|
354
|
-
}
|
|
355
|
-
.ga-toast-btn {
|
|
356
|
-
flex: 1;
|
|
357
|
-
padding: 8px 14px;
|
|
358
|
-
font: inherit;
|
|
359
|
-
font-size: 0.8125rem;
|
|
360
|
-
font-weight: 600;
|
|
361
|
-
border-radius: 9px;
|
|
362
|
-
border: 1px solid var(--gat-border);
|
|
363
|
-
background: var(--gat-chip);
|
|
364
|
-
color: var(--gat-text);
|
|
365
|
-
cursor: pointer;
|
|
366
|
-
transition: filter 0.15s ease, background 0.15s ease;
|
|
367
|
-
}
|
|
368
|
-
.ga-toast-btn:hover { filter: brightness(0.97); }
|
|
369
|
-
.ga-toast-btn:focus-visible {
|
|
370
|
-
outline: 2px solid currentColor;
|
|
371
|
-
outline-offset: 2px;
|
|
372
|
-
}
|
|
373
|
-
.ga-toast-btn-primary {
|
|
374
|
-
background: var(--gat-accent, var(--gat-primary));
|
|
375
|
-
border-color: transparent;
|
|
376
|
-
color: #fff;
|
|
377
|
-
}
|
|
378
|
-
.ga-toast-btn-primary:hover { filter: brightness(1.06); }
|
|
379
|
-
|
|
380
|
-
/* ---------------- Progress bar ---------------- */
|
|
381
|
-
.ga-toast-progress {
|
|
382
|
-
position: absolute;
|
|
383
|
-
left: 0;
|
|
384
|
-
bottom: 0;
|
|
385
|
-
height: 2px;
|
|
386
|
-
width: 100%;
|
|
387
|
-
transform: scaleX(1);
|
|
388
|
-
transform-origin: left center;
|
|
389
|
-
background: var(--gat-accent, var(--gat-info));
|
|
390
|
-
opacity: 0.4; /* a quiet hint, not a slab */
|
|
391
|
-
}
|
|
392
|
-
.ga-toast-progress-top { top: 0; bottom: auto; }
|
|
393
|
-
|
|
394
|
-
/* ---------------- Segmented steps ---------------- */
|
|
395
|
-
.ga-toast-steps { display: flex; gap: 4px; margin-top: 4px; }
|
|
396
|
-
.ga-toast-step {
|
|
397
|
-
flex: 1;
|
|
398
|
-
height: 3px;
|
|
399
|
-
border-radius: 999px;
|
|
400
|
-
background: var(--gat-chip);
|
|
401
|
-
}
|
|
402
|
-
.ga-toast-step-active { background: var(--gat-accent, var(--gat-info)); }
|
|
403
|
-
|
|
404
|
-
/* ---------------- Variants ---------------- */
|
|
405
|
-
/* Filled: solid accent, white ink, white stroke glyph directly on the fill.
|
|
406
|
-
Per-type fills are darkened where needed so white body text clears WCAG AA
|
|
407
|
-
(4.5:1); no top sheen (it dragged the top region under AA). */
|
|
408
|
-
.ga-toast[class*="-filled"] {
|
|
409
|
-
background: var(--gat-accent, var(--gat-info));
|
|
410
|
-
border-color: transparent;
|
|
411
|
-
color: #fff;
|
|
412
|
-
}
|
|
413
|
-
.ga-toast-success[class*="-filled"] { background: #15803d; } /* white \u2248 5.0:1 */
|
|
414
|
-
.ga-toast-primary[class*="-filled"] { background: #4f46e5; } /* white \u2248 6.3:1 */
|
|
415
|
-
.ga-toast[class*="-filled"] .ga-toast-title,
|
|
416
|
-
.ga-toast[class*="-filled"] .ga-toast-message,
|
|
417
|
-
.ga-toast[class*="-filled"] .ga-toast-meta,
|
|
418
|
-
.ga-toast[class*="-filled"] .ga-toast-icon,
|
|
419
|
-
.ga-toast[class*="-filled"] .ga-toast-close { color: #fff; }
|
|
420
|
-
.ga-toast[class*="-filled"] .ga-toast-close:hover { background: rgba(255, 255, 255, 0.2); }
|
|
421
|
-
/* Accent-colored bits would vanish on the accent fill \u2014 force them light. */
|
|
422
|
-
.ga-toast[class*="-filled"] .ga-toast-progress { background: #fff; opacity: 0.55; }
|
|
423
|
-
.ga-toast[class*="-filled"] .ga-toast-step { background: rgba(255, 255, 255, 0.28); }
|
|
424
|
-
.ga-toast[class*="-filled"] .ga-toast-step-active { background: #fff; }
|
|
425
|
-
.ga-toast[class*="-filled"] .ga-toast-status {
|
|
426
|
-
color: #fff;
|
|
427
|
-
background: rgba(255, 255, 255, 0.22);
|
|
428
|
-
}
|
|
429
|
-
.ga-toast[class*="-filled"] .ga-toast-message a { color: #fff; text-decoration: underline; }
|
|
430
|
-
|
|
431
|
-
/* Amber is too light for white text \u2014 filled warnings use dark ink throughout. */
|
|
432
|
-
.ga-toast-warning[class*="-filled"],
|
|
433
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-title,
|
|
434
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-message,
|
|
435
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-meta,
|
|
436
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-icon,
|
|
437
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-close,
|
|
438
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-message a {
|
|
439
|
-
color: #2e2100; /* \u2248 5.2:1 on the amber fill */
|
|
440
|
-
}
|
|
441
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-progress { background: #2e2100; opacity: 0.6; }
|
|
442
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-step { background: rgba(0, 0, 0, 0.18); }
|
|
443
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-step-active { background: #2e2100; }
|
|
444
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-status {
|
|
445
|
-
color: #2e2100;
|
|
446
|
-
background: rgba(0, 0, 0, 0.16);
|
|
447
|
-
}
|
|
448
|
-
.ga-toast-warning[class*="-filled"] .ga-toast-close:hover { background: rgba(0, 0, 0, 0.14); }
|
|
449
|
-
|
|
450
|
-
/* Light: a translucent accent wash over the (translucent) surface so glass still
|
|
451
|
-
shows through, plus an accent-tinted border. Secondary text is darkened to
|
|
452
|
-
keep AA over the tint. */
|
|
453
|
-
.ga-toast[class*="-light"] {
|
|
454
|
-
background: var(--gat-surface); /* stays translucent \u2192 glass blur still works */
|
|
455
|
-
background-image: linear-gradient(
|
|
456
|
-
0deg,
|
|
457
|
-
color-mix(in srgb, var(--gat-accent, var(--gat-info)) 14%, transparent),
|
|
458
|
-
color-mix(in srgb, var(--gat-accent, var(--gat-info)) 14%, transparent)
|
|
459
|
-
);
|
|
460
|
-
border-color: color-mix(in srgb, var(--gat-accent, var(--gat-info)) 38%, var(--gat-border));
|
|
461
|
-
}
|
|
462
|
-
.ga-toast[class*="-light"] .ga-toast-meta { color: var(--gat-text-soft); }
|
|
463
|
-
.ga-toast[class*="-light"] .ga-toast-message a {
|
|
464
|
-
color: color-mix(in srgb, var(--gat-accent, var(--gat-info)) 55%, var(--gat-text));
|
|
465
|
-
text-decoration: underline;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/* ---------------- Sizes (density) ---------------- */
|
|
469
|
-
.ga-toast-xs { padding: 10px 13px; font-size: 0.78rem; }
|
|
470
|
-
.ga-toast-xs .ga-toast-icon svg { width: 1.05rem; height: 1.05rem; }
|
|
471
|
-
.ga-toast-xs .ga-toast-message { font-size: 0.78rem; }
|
|
472
|
-
.ga-toast-sm { padding: 12px 15px; }
|
|
473
|
-
.ga-toast-lg { padding: 18px 20px; }
|
|
474
|
-
.ga-toast-lg .ga-toast-title { font-size: 1rem; }
|
|
475
|
-
.ga-toast-lg .ga-toast-message { font-size: 0.95rem; }
|
|
476
|
-
.ga-toast-lg .ga-toast-icon svg { width: 1.4rem; height: 1.4rem; }
|
|
477
|
-
.ga-toast-xl { padding: 22px 24px; }
|
|
478
|
-
.ga-toast-xl .ga-toast-title { font-size: 1.125rem; }
|
|
479
|
-
.ga-toast-xl .ga-toast-message { font-size: 1.05rem; }
|
|
480
|
-
.ga-toast-xl .ga-toast-icon svg { width: 1.6rem; height: 1.6rem; }
|
|
481
|
-
|
|
482
|
-
/* ---------------- Compact ---------------- */
|
|
483
|
-
/* The card is already an icon \xB7 content \xB7 close row, so compact just tightens
|
|
484
|
-
the padding and vertically centres the single line. */
|
|
485
|
-
.ga-toast-compact {
|
|
486
|
-
align-items: center;
|
|
487
|
-
gap: 10px;
|
|
488
|
-
padding: 10px 14px;
|
|
489
|
-
}
|
|
490
|
-
.ga-toast-compact .ga-toast-content { gap: 2px; }
|
|
491
|
-
.ga-toast-compact .ga-toast-icon { margin-top: 0; }
|
|
492
|
-
.ga-toast-compact .ga-toast-close { align-self: center; margin-top: 0; }
|
|
493
|
-
.ga-toast-compact .ga-toast-steps { display: none; }
|
|
494
|
-
.ga-toast-compact .ga-toast-icon svg { width: 1.05rem; height: 1.05rem; }
|
|
495
|
-
|
|
496
|
-
/* ---------------- Live region (screen-reader only) ---------------- */
|
|
497
|
-
.ga-toast-live-region {
|
|
498
|
-
position: fixed;
|
|
499
|
-
width: 1px;
|
|
500
|
-
height: 1px;
|
|
501
|
-
padding: 0;
|
|
502
|
-
margin: -1px;
|
|
503
|
-
overflow: hidden;
|
|
504
|
-
clip: rect(0 0 0 0);
|
|
505
|
-
clip-path: inset(50%);
|
|
506
|
-
white-space: nowrap;
|
|
507
|
-
border: 0;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/* ---------------- Responsive ---------------- */
|
|
511
|
-
@media (max-width: 520px) {
|
|
512
|
-
.ga-toast-container {
|
|
513
|
-
--gat-width: auto;
|
|
514
|
-
left: var(--gat-edge);
|
|
515
|
-
right: var(--gat-edge);
|
|
516
|
-
transform: none;
|
|
517
|
-
}
|
|
518
|
-
.ga-toast-container-top-center,
|
|
519
|
-
.ga-toast-container-bottom-center,
|
|
520
|
-
.ga-toast-container-middle-center { transform: none; }
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
/* ---------------- RTL ---------------- */
|
|
524
|
-
[dir="rtl"] .ga-toast-progress { transform-origin: right center; }
|
|
525
|
-
|
|
526
|
-
/* ---------------- Reduced motion ---------------- */
|
|
527
|
-
@media (prefers-reduced-motion: reduce) {
|
|
528
|
-
.ga-toast {
|
|
529
|
-
transition: opacity 0.15s ease;
|
|
530
|
-
}
|
|
531
|
-
.ga-toast-spinner { animation-duration: 1.4s; }
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/* ---------------- Reduced transparency ---------------- */
|
|
535
|
-
@media (prefers-reduced-transparency: reduce) {
|
|
536
|
-
.ga-toast-glass {
|
|
537
|
-
background: var(--gat-surface-solid);
|
|
538
|
-
backdrop-filter: none;
|
|
539
|
-
-webkit-backdrop-filter: none;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/* ---------------- Custom content (toast.custom) ---------------- */
|
|
544
|
-
.ga-toast-custom { min-width: 0; }
|
|
545
|
-
.ga-toast-has-custom { padding: 0; }
|
|
546
|
-
.ga-toast-has-custom .ga-toast-close {
|
|
547
|
-
position: absolute;
|
|
548
|
-
inset-block-start: 8px;
|
|
549
|
-
inset-inline-end: 8px;
|
|
550
|
-
z-index: 1;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
@keyframes ga-toast-spin {
|
|
554
|
-
to { transform: rotate(360deg); }
|
|
555
|
-
}
|
|
556
|
-
`;
|
|
2
|
+
var css = '.ga-toast-container{--gat-width: 380px;--gat-radius: 14px;--gat-gap: 14px;--gat-edge: 22px;--gat-pad-y: 12px;--gat-pad-x: 16px;--gat-font-size: .875rem;--gat-accent-edge: 0px;--gat-font: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--gat-surface: rgba(255, 255, 255, .82);--gat-surface-solid: #ffffff;--gat-border: rgba(15, 23, 42, .07);--gat-ring: rgba(15, 23, 42, .05);--gat-highlight: rgba(255, 255, 255, .75);--gat-text: #0f172a;--gat-text-soft: #475569;--gat-text-muted: #64748b;--gat-shadow: 0 1px 2px rgba(15, 23, 42, .05), 0 8px 20px -12px rgba(15, 23, 42, .16);--gat-shadow-hover: 0 2px 4px -2px rgba(15, 23, 42, .12), 0 14px 32px -12px rgba(15, 23, 42, .26);--gat-chip: rgba(15, 23, 42, .05);--gat-success: #16a34a;--gat-error: #e11d48;--gat-warning: #d97706;--gat-info: #2563eb;--gat-primary: #6366f1;--gat-secondary: #64748b;--gat-loading: #2563eb;--gat-ease: cubic-bezier(.22, 1, .36, 1)}[data-ga-theme=dark] .ga-toast-container,.ga-theme-dark .ga-toast-container,.ga-toast-container.ga-theme-dark{--gat-surface: rgba(30, 34, 44, .72);--gat-surface-solid: #22262f;--gat-border: rgba(255, 255, 255, .09);--gat-ring: rgba(255, 255, 255, .06);--gat-highlight: rgba(255, 255, 255, .07);--gat-text: #f8fafc;--gat-text-soft: #cbd5e1;--gat-text-muted: #9aa7ba;--gat-shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 10px 28px -14px rgba(0, 0, 0, .5);--gat-shadow-hover: 0 2px 6px -2px rgba(0, 0, 0, .5), 0 16px 38px -12px rgba(0, 0, 0, .64);--gat-chip: rgba(255, 255, 255, .08)}@media(prefers-color-scheme:dark){:root:not([data-ga-theme]):not(.ga-theme-light):not(.ga-theme-dark) .ga-toast-container{--gat-surface: rgba(24, 27, 34, .82);--gat-surface-solid: #191c22;--gat-border: rgba(255, 255, 255, .09);--gat-ring: rgba(255, 255, 255, .06);--gat-highlight: rgba(255, 255, 255, .07);--gat-text: #f8fafc;--gat-text-soft: #cbd5e1;--gat-text-muted: #9aa7ba;--gat-shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 10px 28px -14px rgba(0, 0, 0, .5);--gat-chip: rgba(255, 255, 255, .08)}}.ga-toast-backdrop{position:fixed;inset:0;z-index:2147482990;background:#0a0c146b;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);opacity:0;transition:opacity .22s ease}.ga-toast-backdrop-show{opacity:1}@media(prefers-reduced-transparency:reduce){.ga-toast-backdrop{backdrop-filter:none;-webkit-backdrop-filter:none}}.ga-toast-container{position:fixed;z-index:2147483000;width:var(--gat-width);max-width:calc(100vw - 2 * var(--gat-edge));pointer-events:none;font-family:var(--gat-font)}.ga-toast-container-top-start{inset-block-start:var(--gat-edge);inset-inline-start:var(--gat-edge)}.ga-toast-container-top-end{inset-block-start:var(--gat-edge);inset-inline-end:var(--gat-edge)}.ga-toast-container-top-center{inset-block-start:var(--gat-edge);left:50%;transform:translate(-50%)}.ga-toast-container-bottom-start{inset-block-end:var(--gat-edge);inset-inline-start:var(--gat-edge)}.ga-toast-container-bottom-end{inset-block-end:var(--gat-edge);inset-inline-end:var(--gat-edge)}.ga-toast-container-bottom-center{inset-block-end:var(--gat-edge);left:50%;transform:translate(-50%)}.ga-toast-container-middle-start{top:50%;inset-inline-start:var(--gat-edge)}.ga-toast-container-middle-end{top:50%;inset-inline-end:var(--gat-edge)}.ga-toast-container-middle-center{top:50%;left:50%;transform:translate(-50%)}.ga-toast{position:absolute;inset-inline:0;width:100%;box-sizing:border-box;display:flex;flex-direction:row;align-items:flex-start;gap:11px;padding:var(--gat-pad-y, 12px) var(--gat-pad-x, 16px);color:var(--gat-text);background:var(--gat-surface-solid);border:none;border-radius:var(--gat-radius);box-shadow:var(--gat-shadow),inset 0 1px 0 var(--gat-highlight);pointer-events:auto;opacity:0;transform:translateY(-140%);transition:transform .5s var(--gat-ease),opacity .35s ease,box-shadow .2s ease;will-change:transform,opacity;overflow:hidden;font-size:var(--gat-font-size, .875rem);line-height:1.5;-webkit-font-smoothing:antialiased;text-align:start;touch-action:pan-y;overscroll-behavior:contain}@media(hover:hover){.ga-toast:hover{box-shadow:var(--gat-shadow-hover),inset 0 1px 0 var(--gat-highlight)}}[data-ga-position^=top] .ga-toast,[data-ga-position^=middle] .ga-toast{top:0;transform-origin:top center}[data-ga-position^=bottom] .ga-toast{bottom:0;transform-origin:bottom center}.ga-toast-glass{background:var(--gat-surface);backdrop-filter:blur(16px) saturate(160%);-webkit-backdrop-filter:blur(16px) saturate(160%)}.ga-toast-outline{background:transparent;border:1px solid var(--gat-border);box-shadow:var(--gat-shadow);backdrop-filter:none;-webkit-backdrop-filter:none}.ga-toast:before{content:"";position:absolute;inset-block:0;inset-inline-start:0;width:var(--gat-accent-edge, 0px);background:var(--gat-accent, var(--gat-info));pointer-events:none}.ga-toast-hide{pointer-events:none}.ga-toast-swiping,.ga-toast-swiping *{user-select:none;-webkit-user-select:none;cursor:grabbing}.ga-toast-success{--gat-accent: var(--gat-success)}.ga-toast-error{--gat-accent: var(--gat-error)}.ga-toast-warning{--gat-accent: var(--gat-warning)}.ga-toast-info{--gat-accent: var(--gat-info)}.ga-toast-primary{--gat-accent: var(--gat-primary)}.ga-toast-secondary{--gat-accent: var(--gat-secondary)}.ga-toast-loading{--gat-accent: var(--gat-loading)}.ga-toast-content{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.ga-toast-header{display:flex;align-items:center;gap:8px;min-width:0}.ga-toast-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;margin-top:1px;color:var(--gat-accent, var(--gat-info))}.ga-toast-icon svg{width:1.25rem;height:1.25rem;display:block;overflow:visible}.ga-toast-spinner{animation:ga-toast-spin .8s linear infinite}.ga-toast-icon-ring{position:relative;width:2rem;height:2rem;margin-top:0}.ga-toast-icon-ring>svg:not(.ga-toast-ring){width:1.1rem;height:1.1rem}.ga-toast-ring{position:absolute;inset:0;width:100%!important;height:100%!important;transform:rotate(-90deg);overflow:visible}.ga-toast-ring-track{fill:none;stroke:var(--gat-chip);stroke-width:2.4}.ga-toast-ring-bar{fill:none;stroke:var(--gat-accent, var(--gat-info));stroke-width:2.4;stroke-linecap:round}@media(prefers-reduced-motion:no-preference){.ga-toast-icon .ga-ic-ring{stroke-dasharray:64;stroke-dashoffset:64;animation:ga-toast-ic-draw .5s var(--gat-ease) .02s forwards}.ga-toast-icon .ga-ic-draw{stroke-dasharray:28;stroke-dashoffset:28;animation:ga-toast-ic-draw .4s var(--gat-ease) .16s forwards}}@keyframes ga-toast-ic-draw{to{stroke-dashoffset:0}}.ga-toast-avatar{flex-shrink:0;width:34px;height:34px;border-radius:50%;object-fit:cover;border:1px solid var(--gat-border)}.ga-toast-unread-dot{flex-shrink:0;width:8px;height:8px;border-radius:50%;background:var(--gat-accent, var(--gat-info))}.ga-toast-title{font-weight:600;font-size:.9rem;color:var(--gat-text);flex:1;min-width:0;letter-spacing:-.011em}.ga-toast-title-truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ga-toast-status{flex-shrink:0;padding:2px 9px;border-radius:999px;font-size:.6875rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--gat-accent, var(--gat-info));color:color-mix(in srgb,var(--gat-accent, var(--gat-info)) 58%,var(--gat-text));background:var(--gat-chip);background:color-mix(in srgb,var(--gat-accent, var(--gat-info)) 18%,transparent)}.ga-toast-close{flex-shrink:0;align-self:flex-start;margin-top:-1px;margin-inline-end:-4px;display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:none;border-radius:7px;color:var(--gat-text-muted);background:transparent;cursor:pointer;opacity:.9;transition:background .15s ease,color .15s ease,opacity .15s ease}.ga-toast:hover .ga-toast-close,.ga-toast:focus-within .ga-toast-close{opacity:1}.ga-toast-close svg{width:15px;height:15px;display:block}.ga-toast-close:hover{background:var(--gat-chip);color:var(--gat-text)}.ga-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}.ga-toast-body{min-width:0}.ga-toast-meta{font-size:.75rem;color:var(--gat-text-muted);margin-bottom:2px}.ga-toast-message{color:var(--gat-text-soft);font-size:.85rem;word-break:break-word;max-height:40vh;overflow-y:auto;overscroll-behavior:contain}.ga-toast-message a{color:var(--gat-accent, var(--gat-info));font-weight:500;text-decoration:underline}.ga-toast:not([class*=-filled]) .ga-toast-content>.ga-toast-body:only-child .ga-toast-message{color:var(--gat-text)}.ga-toast-actions{display:flex;gap:8px;margin-top:2px}.ga-toast-btn{flex:1;padding:8px 14px;font:inherit;font-size:.8125rem;font-weight:600;border-radius:9px;border:1px solid var(--gat-border);background:var(--gat-chip);color:var(--gat-text);cursor:pointer;transition:filter .15s ease,background .15s ease}.ga-toast-btn:hover{filter:brightness(.97)}.ga-toast-btn:focus-visible{outline:2px solid currentColor;outline-offset:2px}.ga-toast-btn-primary{background:var(--gat-accent, var(--gat-primary));border-color:transparent;color:#fff}.ga-toast-btn-primary:hover{filter:brightness(1.06)}.ga-toast-progress{position:absolute;left:0;bottom:0;height:2px;width:100%;transform:scaleX(1);transform-origin:left center;background:var(--gat-accent, var(--gat-info));opacity:.4}.ga-toast-progress-top{top:0;bottom:auto}.ga-toast-steps{display:flex;gap:4px;margin-top:4px}.ga-toast-step{flex:1;height:3px;border-radius:999px;background:var(--gat-chip)}.ga-toast-step-active{background:var(--gat-accent, var(--gat-info))}.ga-toast[class*=-filled]{background:var(--gat-accent, var(--gat-info));border-color:transparent;color:#fff}.ga-toast-success[class*=-filled]{background:#15803d}.ga-toast-primary[class*=-filled]{background:#4f46e5}.ga-toast[class*=-filled] .ga-toast-title,.ga-toast[class*=-filled] .ga-toast-message,.ga-toast[class*=-filled] .ga-toast-meta,.ga-toast[class*=-filled] .ga-toast-icon,.ga-toast[class*=-filled] .ga-toast-close{color:#fff}.ga-toast[class*=-filled] .ga-toast-close:hover{background:#fff3}.ga-toast[class*=-filled] .ga-toast-progress{background:#fff;opacity:.55}.ga-toast[class*=-filled] .ga-toast-step{background:#ffffff47}.ga-toast[class*=-filled] .ga-toast-step-active{background:#fff}.ga-toast[class*=-filled] .ga-toast-status{color:#fff;background:#ffffff38}.ga-toast[class*=-filled] .ga-toast-message a{color:#fff;text-decoration:underline}.ga-toast-warning[class*=-filled],.ga-toast-warning[class*=-filled] .ga-toast-title,.ga-toast-warning[class*=-filled] .ga-toast-message,.ga-toast-warning[class*=-filled] .ga-toast-meta,.ga-toast-warning[class*=-filled] .ga-toast-icon,.ga-toast-warning[class*=-filled] .ga-toast-close,.ga-toast-warning[class*=-filled] .ga-toast-message a{color:#2e2100}.ga-toast-warning[class*=-filled] .ga-toast-progress{background:#2e2100;opacity:.6}.ga-toast-warning[class*=-filled] .ga-toast-step{background:#0000002e}.ga-toast-warning[class*=-filled] .ga-toast-step-active{background:#2e2100}.ga-toast-warning[class*=-filled] .ga-toast-status{color:#2e2100;background:#00000029}.ga-toast-warning[class*=-filled] .ga-toast-close:hover{background:#00000024}.ga-toast[class*=-light]{background:var(--gat-surface);background-image:linear-gradient(0deg,color-mix(in srgb,var(--gat-accent, var(--gat-info)) 14%,transparent),color-mix(in srgb,var(--gat-accent, var(--gat-info)) 14%,transparent));border-color:color-mix(in srgb,var(--gat-accent, var(--gat-info)) 38%,var(--gat-border))}.ga-toast[class*=-light] .ga-toast-meta{color:var(--gat-text-soft)}.ga-toast[class*=-light] .ga-toast-message a{color:color-mix(in srgb,var(--gat-accent, var(--gat-info)) 55%,var(--gat-text));text-decoration:underline}.ga-toast-xs{padding:10px 13px;font-size:.78rem}.ga-toast-xs .ga-toast-icon svg{width:1.05rem;height:1.05rem}.ga-toast-xs .ga-toast-message{font-size:.78rem}.ga-toast-sm{padding:11px 14px;gap:9px}.ga-toast-lg{padding:18px 20px}.ga-toast-lg .ga-toast-title{font-size:1rem}.ga-toast-lg .ga-toast-message{font-size:.95rem}.ga-toast-lg .ga-toast-icon svg{width:1.4rem;height:1.4rem}.ga-toast-xl{padding:22px 24px}.ga-toast-xl .ga-toast-title{font-size:1.125rem}.ga-toast-xl .ga-toast-message{font-size:1.05rem}.ga-toast-xl .ga-toast-icon svg{width:1.6rem;height:1.6rem}.ga-toast-compact{align-items:center;gap:10px;padding:10px 14px}.ga-toast-compact .ga-toast-content{gap:2px}.ga-toast-compact .ga-toast-icon{margin-top:0}.ga-toast-compact .ga-toast-close{align-self:center;margin-top:0}.ga-toast-compact .ga-toast-steps{display:none}.ga-toast-compact .ga-toast-icon svg{width:1.05rem;height:1.05rem}.ga-toast-live-region{position:fixed;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}@media(max-width:520px){.ga-toast-container{--gat-width: auto;left:var(--gat-edge);right:var(--gat-edge);transform:none}.ga-toast-container-top-center,.ga-toast-container-bottom-center,.ga-toast-container-middle-center{transform:none}}[dir=rtl] .ga-toast-progress{transform-origin:right center}@media(prefers-reduced-motion:reduce){.ga-toast{transition:opacity .15s ease}.ga-toast-spinner{animation-duration:1.4s}}@media(prefers-reduced-transparency:reduce){.ga-toast-glass{background:var(--gat-surface-solid);backdrop-filter:none;-webkit-backdrop-filter:none}}.ga-toast-custom{min-width:0}.ga-toast-has-custom{padding:0}.ga-toast-has-custom .ga-toast-close{position:absolute;inset-block-start:8px;inset-inline-end:8px;z-index:1}@keyframes ga-toast-spin{to{transform:rotate(360deg)}}';
|
|
557
3
|
|
|
558
4
|
// src/index.ts
|
|
559
5
|
var canUseDOM = typeof window !== "undefined" && typeof document !== "undefined";
|
|
560
6
|
var PREFIX = "ga-toast";
|
|
561
7
|
var STYLE_ID = "ga-toasts-styles";
|
|
562
|
-
var PEEK = 14;
|
|
563
|
-
var STACK_GAP = 14;
|
|
564
|
-
var MAX_VISIBLE = 3;
|
|
565
8
|
var REMOVE_FALLBACK = 450;
|
|
566
|
-
var
|
|
567
|
-
var
|
|
568
|
-
var
|
|
569
|
-
var
|
|
570
|
-
var
|
|
571
|
-
var escapeBound = false;
|
|
572
|
-
var visibilityBound = false;
|
|
573
|
-
var idCounter = 0;
|
|
574
|
-
var activeModalId = null;
|
|
575
|
-
var backdropEl = null;
|
|
9
|
+
var COLLAPSE_DELAY = 140;
|
|
10
|
+
var DEFAULT_MAX_VISIBLE = 3;
|
|
11
|
+
var DEFAULT_PEEK = 14;
|
|
12
|
+
var DEFAULT_STACK_GAP = 14;
|
|
13
|
+
var DEFAULT_SCALE_STEP = 0.05;
|
|
576
14
|
var S = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">';
|
|
577
|
-
var
|
|
15
|
+
var DEFAULT_ICONS = {
|
|
578
16
|
success: `${S}<circle cx="12" cy="12" r="9" class="ga-ic-ring"/><path d="M7.75 12.5l2.75 2.75L16.5 9" class="ga-ic-draw"/></svg>`,
|
|
579
17
|
error: `${S}<circle cx="12" cy="12" r="9" class="ga-ic-ring"/><path d="M15 9l-6 6M9 9l6 6" class="ga-ic-draw"/></svg>`,
|
|
580
18
|
warning: `${S}<path d="M12 3.6 2.4 20.4h19.2L12 3.6z" class="ga-ic-ring"/><path d="M12 10v4" class="ga-ic-draw"/><path d="M12 17.4v.01"/></svg>`,
|
|
@@ -583,60 +21,8 @@ var ICONS = {
|
|
|
583
21
|
secondary: `${S}<path d="M6 9a6 6 0 0112 0c0 4.5 1.8 5.6 1.8 5.6H4.2S6 13.5 6 9z" class="ga-ic-draw"/><path d="M10 19a2 2 0 004 0"/></svg>`,
|
|
584
22
|
loading: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" aria-hidden="true" class="ga-toast-spinner"><circle cx="12" cy="12" r="9" opacity="0.25"/><path d="M12 3a9 9 0 019 9"/></svg>'
|
|
585
23
|
};
|
|
586
|
-
var
|
|
24
|
+
var DEFAULT_CLOSE_ICON = '<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg>';
|
|
587
25
|
var ASSERTIVE_TYPES = /* @__PURE__ */ new Set(["error", "warning"]);
|
|
588
|
-
function now() {
|
|
589
|
-
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
590
|
-
}
|
|
591
|
-
function nextId() {
|
|
592
|
-
idCounter += 1;
|
|
593
|
-
const rand = Math.random().toString(36).slice(2, 8);
|
|
594
|
-
return `${PREFIX}-${idCounter}-${rand}`;
|
|
595
|
-
}
|
|
596
|
-
function log(event, payload) {
|
|
597
|
-
if (logger) {
|
|
598
|
-
try {
|
|
599
|
-
logger(event, payload);
|
|
600
|
-
} catch {
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
function prefersReducedMotion() {
|
|
605
|
-
return canUseDOM && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
606
|
-
}
|
|
607
|
-
function injectStyles() {
|
|
608
|
-
if (!canUseDOM) return;
|
|
609
|
-
if (document.getElementById(STYLE_ID)) return;
|
|
610
|
-
const el2 = document.createElement("style");
|
|
611
|
-
el2.id = STYLE_ID;
|
|
612
|
-
el2.textContent = css;
|
|
613
|
-
document.head.appendChild(el2);
|
|
614
|
-
}
|
|
615
|
-
function ensureLiveRegions() {
|
|
616
|
-
if (!canUseDOM) return;
|
|
617
|
-
if (liveRegions && liveRegions.polite.isConnected && liveRegions.assertive.isConnected)
|
|
618
|
-
return;
|
|
619
|
-
const make = (politeness) => {
|
|
620
|
-
const region = document.createElement("div");
|
|
621
|
-
region.className = "ga-toast-live-region";
|
|
622
|
-
region.setAttribute("aria-live", politeness);
|
|
623
|
-
region.setAttribute("aria-atomic", "true");
|
|
624
|
-
region.setAttribute("role", politeness === "assertive" ? "alert" : "status");
|
|
625
|
-
document.body.appendChild(region);
|
|
626
|
-
return region;
|
|
627
|
-
};
|
|
628
|
-
liveRegions = { polite: make("polite"), assertive: make("assertive") };
|
|
629
|
-
}
|
|
630
|
-
function announce(text, assertive) {
|
|
631
|
-
if (!text) return;
|
|
632
|
-
ensureLiveRegions();
|
|
633
|
-
if (!liveRegions) return;
|
|
634
|
-
const region = assertive ? liveRegions.assertive : liveRegions.polite;
|
|
635
|
-
region.textContent = "";
|
|
636
|
-
window.setTimeout(() => {
|
|
637
|
-
region.textContent = text;
|
|
638
|
-
}, 50);
|
|
639
|
-
}
|
|
640
26
|
var POSITIONS = [
|
|
641
27
|
"top-start",
|
|
642
28
|
"top-center",
|
|
@@ -648,6 +34,76 @@ var POSITIONS = [
|
|
|
648
34
|
"bottom-center",
|
|
649
35
|
"bottom-end"
|
|
650
36
|
];
|
|
37
|
+
var DEFAULT_DURATIONS = {
|
|
38
|
+
success: 5e3,
|
|
39
|
+
error: 8e3,
|
|
40
|
+
warning: 6e3,
|
|
41
|
+
info: 4e3,
|
|
42
|
+
primary: 5e3,
|
|
43
|
+
secondary: 5e3,
|
|
44
|
+
loading: 0
|
|
45
|
+
};
|
|
46
|
+
var PRESETS = {
|
|
47
|
+
soft: {},
|
|
48
|
+
solid: { surface: "solid", elevation: "raised" },
|
|
49
|
+
minimal: { surface: "outline", elevation: "flat", radius: 10, accentEdge: 0 },
|
|
50
|
+
sharp: { radius: 4 },
|
|
51
|
+
material: { surface: "solid", elevation: "floating", radius: 12 }
|
|
52
|
+
};
|
|
53
|
+
var DENSITY = {
|
|
54
|
+
// padY, padX, font-size
|
|
55
|
+
compact: ["8px", "13px", "0.82rem"],
|
|
56
|
+
comfortable: ["12px", "16px", "0.875rem"],
|
|
57
|
+
spacious: ["16px", "20px", "0.94rem"]
|
|
58
|
+
};
|
|
59
|
+
var ELEVATION = {
|
|
60
|
+
flat: "0 1px 2px rgba(15,23,42,0.06)",
|
|
61
|
+
raised: "0 1px 2px rgba(15,23,42,0.05), 0 8px 20px -12px rgba(15,23,42,0.16)",
|
|
62
|
+
floating: "0 4px 10px -3px rgba(15,23,42,0.12), 0 20px 44px -14px rgba(15,23,42,0.34)"
|
|
63
|
+
};
|
|
64
|
+
function px(v) {
|
|
65
|
+
return typeof v === "number" ? `${v}px` : String(v);
|
|
66
|
+
}
|
|
67
|
+
function resolveTheme(theme) {
|
|
68
|
+
if (!theme) return {};
|
|
69
|
+
if (typeof theme === "string") return { ...PRESETS[theme] || {} };
|
|
70
|
+
const { preset, ...rest } = theme;
|
|
71
|
+
const base = preset ? PRESETS[preset] || {} : {};
|
|
72
|
+
return { ...base, ...rest };
|
|
73
|
+
}
|
|
74
|
+
function themeVars(t) {
|
|
75
|
+
const v = {};
|
|
76
|
+
if (t.width != null) v["--gat-width"] = px(t.width);
|
|
77
|
+
if (t.radius != null) v["--gat-radius"] = px(t.radius);
|
|
78
|
+
if (t.gap != null) v["--gat-gap"] = px(t.gap);
|
|
79
|
+
if (t.edge != null) v["--gat-edge"] = px(t.edge);
|
|
80
|
+
if (t.font) v["--gat-font"] = t.font;
|
|
81
|
+
if (t.density && DENSITY[t.density]) {
|
|
82
|
+
const [py, pxv, fs] = DENSITY[t.density];
|
|
83
|
+
v["--gat-pad-y"] = py;
|
|
84
|
+
v["--gat-pad-x"] = pxv;
|
|
85
|
+
v["--gat-font-size"] = fs;
|
|
86
|
+
}
|
|
87
|
+
if (t.elevation && ELEVATION[t.elevation]) v["--gat-shadow"] = ELEVATION[t.elevation];
|
|
88
|
+
if (t.accentEdge != null) v["--gat-accent-edge"] = px(t.accentEdge);
|
|
89
|
+
if (t.accent) v["--gat-primary"] = t.accent;
|
|
90
|
+
if (t.colors) {
|
|
91
|
+
for (const k of Object.keys(t.colors))
|
|
92
|
+
if (t.colors[k]) v[`--gat-${k}`] = t.colors[k];
|
|
93
|
+
}
|
|
94
|
+
if (t.text) v["--gat-text"] = t.text;
|
|
95
|
+
if (t.textSoft) v["--gat-text-soft"] = t.textSoft;
|
|
96
|
+
if (t.textMuted) v["--gat-text-muted"] = t.textMuted;
|
|
97
|
+
if (t.surfaceColor) {
|
|
98
|
+
v["--gat-surface"] = t.surfaceColor;
|
|
99
|
+
v["--gat-surface-solid"] = t.surfaceColor;
|
|
100
|
+
}
|
|
101
|
+
if (t.border) v["--gat-border"] = t.border;
|
|
102
|
+
if (t.shadow) v["--gat-shadow"] = t.shadow;
|
|
103
|
+
if (t.chip) v["--gat-chip"] = t.chip;
|
|
104
|
+
if (t.ease) v["--gat-ease"] = t.ease;
|
|
105
|
+
return v;
|
|
106
|
+
}
|
|
651
107
|
function verticalDir(position) {
|
|
652
108
|
return position.startsWith("bottom") ? -1 : 1;
|
|
653
109
|
}
|
|
@@ -664,845 +120,1116 @@ function offscreenTransform(position) {
|
|
|
664
120
|
if (position.endsWith("end")) return rtl ? inFromLeft : inFromRight;
|
|
665
121
|
return verticalDir(position) === 1 ? "translateY(-140%)" : "translateY(140%)";
|
|
666
122
|
}
|
|
667
|
-
function getContainer(position) {
|
|
668
|
-
const existing = containers.get(position);
|
|
669
|
-
if (existing && existing.isConnected) return existing;
|
|
670
|
-
const container = document.createElement("div");
|
|
671
|
-
container.className = `ga-toast-container ga-toast-container-${position}`;
|
|
672
|
-
container.setAttribute("data-ga-position", position);
|
|
673
|
-
container.setAttribute("role", "region");
|
|
674
|
-
container.setAttribute("aria-label", "Notifications");
|
|
675
|
-
const expand = () => setExpanded(container, true);
|
|
676
|
-
const collapse = () => setExpanded(container, false);
|
|
677
|
-
container.addEventListener("pointerenter", expand);
|
|
678
|
-
container.addEventListener("pointerleave", collapse);
|
|
679
|
-
container.addEventListener("focusin", expand);
|
|
680
|
-
container.addEventListener("focusout", (e) => {
|
|
681
|
-
if (!container.contains(e.relatedTarget)) collapse();
|
|
682
|
-
});
|
|
683
|
-
document.body.appendChild(container);
|
|
684
|
-
containers.set(position, container);
|
|
685
|
-
return container;
|
|
686
|
-
}
|
|
687
|
-
function setExpanded(container, expanded) {
|
|
688
|
-
if (container.dataset.gaExpanded === "true" === expanded) return;
|
|
689
|
-
container.dataset.gaExpanded = expanded ? "true" : "false";
|
|
690
|
-
layout(container);
|
|
691
|
-
}
|
|
692
|
-
function instancesIn(container) {
|
|
693
|
-
return Array.from(container.children).map((child) => registry.get(child.id)).filter((inst) => !!inst);
|
|
694
|
-
}
|
|
695
|
-
function layout(container) {
|
|
696
|
-
const all = instancesIn(container);
|
|
697
|
-
const position = container.dataset.gaPosition || "top-end";
|
|
698
|
-
const dir = verticalDir(position);
|
|
699
|
-
const expanded = container.dataset.gaExpanded === "true";
|
|
700
|
-
const reduce = prefersReducedMotion();
|
|
701
|
-
const front = all.slice().reverse();
|
|
702
|
-
container.style.setProperty("--ga-toasts-count", String(front.length));
|
|
703
|
-
let cumulative = 0;
|
|
704
|
-
front.forEach((inst, frontIndex) => {
|
|
705
|
-
if (inst.closing) return;
|
|
706
|
-
if (!inst.el.dataset.gaMounted) {
|
|
707
|
-
cumulative += inst.height + STACK_GAP;
|
|
708
|
-
return;
|
|
709
|
-
}
|
|
710
|
-
let translateY;
|
|
711
|
-
let scale;
|
|
712
|
-
let opacity;
|
|
713
|
-
if (expanded || reduce) {
|
|
714
|
-
translateY = dir * cumulative;
|
|
715
|
-
scale = 1;
|
|
716
|
-
opacity = 1;
|
|
717
|
-
} else {
|
|
718
|
-
translateY = dir * frontIndex * PEEK;
|
|
719
|
-
scale = Math.max(1 - frontIndex * 0.05, 0.85);
|
|
720
|
-
opacity = frontIndex >= MAX_VISIBLE ? 0 : 1;
|
|
721
|
-
}
|
|
722
|
-
const swipe = inst.swipeX ? ` translateX(${inst.swipeX}px)` : "";
|
|
723
|
-
const ty = position.startsWith("middle") ? `calc(-50% + ${translateY}px)` : `${translateY}px`;
|
|
724
|
-
inst.el.style.transform = `translateY(${ty})${swipe} scale(${scale})`;
|
|
725
|
-
inst.el.style.opacity = inst.swipeX ? String(swipeOpacity(inst.swipeX)) : String(opacity);
|
|
726
|
-
inst.el.style.zIndex = String(1e3 + front.length - frontIndex);
|
|
727
|
-
inst.el.style.pointerEvents = opacity === 0 ? "none" : "auto";
|
|
728
|
-
inst.el.setAttribute("aria-hidden", opacity === 0 ? "true" : "false");
|
|
729
|
-
cumulative += inst.height + STACK_GAP;
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
123
|
function swipeOpacity(dx) {
|
|
733
124
|
return Math.max(0.15, 1 - Math.abs(dx) / 220);
|
|
734
125
|
}
|
|
735
|
-
function
|
|
736
|
-
|
|
737
|
-
if (h > 0) inst.height = h;
|
|
738
|
-
}
|
|
739
|
-
function resolveOptions(options) {
|
|
740
|
-
const merged = {
|
|
741
|
-
type: "info",
|
|
742
|
-
duration: 5e3,
|
|
743
|
-
closable: true,
|
|
744
|
-
position: "top-end",
|
|
745
|
-
animation: "slide",
|
|
746
|
-
swipeToClose: true,
|
|
747
|
-
closeOnEscape: true,
|
|
748
|
-
progress: true,
|
|
749
|
-
progressPosition: "bottom",
|
|
750
|
-
pauseOnHover: true,
|
|
751
|
-
pauseOnPageHidden: true,
|
|
752
|
-
autoIcon: true,
|
|
753
|
-
glassmorphism: true,
|
|
754
|
-
html: false,
|
|
755
|
-
...globalDefaults,
|
|
756
|
-
...options
|
|
757
|
-
};
|
|
758
|
-
merged.position = merged.position || "top-end";
|
|
759
|
-
if (!POSITIONS.includes(merged.position)) merged.position = "top-end";
|
|
760
|
-
return merged;
|
|
126
|
+
function normalizeId(idOrSelector) {
|
|
127
|
+
return idOrSelector.startsWith("#") ? idOrSelector.slice(1) : idOrSelector;
|
|
761
128
|
}
|
|
762
|
-
function
|
|
763
|
-
|
|
764
|
-
close2.type = "button";
|
|
765
|
-
close2.className = "ga-toast-close";
|
|
766
|
-
close2.setAttribute("aria-label", "Close notification");
|
|
767
|
-
close2.setAttribute("data-ga-close", "");
|
|
768
|
-
close2.innerHTML = CLOSE_ICON;
|
|
769
|
-
return close2;
|
|
129
|
+
function now() {
|
|
130
|
+
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
770
131
|
}
|
|
771
|
-
function
|
|
772
|
-
|
|
773
|
-
return null;
|
|
774
|
-
const p = document.createElement("div");
|
|
775
|
-
p.className = `ga-toast-progress ga-toast-progress-${type}` + (opts.progressPosition === "top" ? " ga-toast-progress-top" : "");
|
|
776
|
-
el2.appendChild(p);
|
|
777
|
-
return p;
|
|
132
|
+
function prefersReducedMotion() {
|
|
133
|
+
return canUseDOM && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
778
134
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
135
|
+
var toasterSeq = 0;
|
|
136
|
+
function makeToaster(config = {}) {
|
|
137
|
+
const seq = toasterSeq += 1;
|
|
138
|
+
const instanceClass = `ga-toaster-${seq}`;
|
|
139
|
+
const registry = /* @__PURE__ */ new Map();
|
|
140
|
+
const containers = /* @__PURE__ */ new Map();
|
|
141
|
+
let globalDefaults = { ...config.defaults || {} };
|
|
142
|
+
let logger = config.logger || null;
|
|
143
|
+
let liveRegions = null;
|
|
144
|
+
let escapeBound = false;
|
|
145
|
+
let visibilityBound = false;
|
|
146
|
+
let idCounter = 0;
|
|
147
|
+
let activeModalId = null;
|
|
148
|
+
let backdropEl = null;
|
|
149
|
+
const icons = { ...DEFAULT_ICONS };
|
|
150
|
+
let closeIcon = DEFAULT_CLOSE_ICON;
|
|
151
|
+
const durations = { ...DEFAULT_DURATIONS };
|
|
152
|
+
let maxVisible = DEFAULT_MAX_VISIBLE;
|
|
153
|
+
let peek = DEFAULT_PEEK;
|
|
154
|
+
let stackGap = DEFAULT_STACK_GAP;
|
|
155
|
+
let scaleStep = DEFAULT_SCALE_STEP;
|
|
156
|
+
let expandMode = "hover";
|
|
157
|
+
let newestOnTop = false;
|
|
158
|
+
let injectEnabled = config.injectStyles !== false;
|
|
159
|
+
const styleNonce = config.styleNonce;
|
|
160
|
+
const renderFn = config.render || null;
|
|
161
|
+
let themeTokens = {};
|
|
162
|
+
let surfaceMode;
|
|
163
|
+
let progressMode = "bar";
|
|
164
|
+
let themeStyleEl = null;
|
|
165
|
+
const mount = config.root || (canUseDOM ? document.body : null);
|
|
166
|
+
const isShadow = !!config.root && typeof config.root.host !== "undefined";
|
|
167
|
+
const styleTarget = isShadow ? config.root : canUseDOM ? document.head : null;
|
|
168
|
+
function applyConfigDurations(d) {
|
|
169
|
+
if (!d) return;
|
|
170
|
+
for (const k of Object.keys(d))
|
|
171
|
+
if (typeof d[k] === "number") durations[k] = d[k];
|
|
801
172
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
const
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
return { el: el2, progressEl: appendProgress(el2, opts, type) };
|
|
173
|
+
function applyConfigIcons(ic) {
|
|
174
|
+
if (!ic) return;
|
|
175
|
+
for (const k of Object.keys(ic)) {
|
|
176
|
+
if (k === "close") {
|
|
177
|
+
if (ic.close) closeIcon = ic.close;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
icons[k] = ic[k];
|
|
181
|
+
}
|
|
812
182
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
183
|
+
function applyConfigStack(s) {
|
|
184
|
+
if (!s) return;
|
|
185
|
+
if (typeof s.peek === "number") peek = s.peek;
|
|
186
|
+
if (typeof s.gap === "number") stackGap = s.gap;
|
|
187
|
+
if (typeof s.scaleStep === "number") scaleStep = s.scaleStep;
|
|
188
|
+
if (s.expand) expandMode = s.expand;
|
|
189
|
+
if (typeof s.newestOnTop === "boolean") newestOnTop = s.newestOnTop;
|
|
819
190
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
191
|
+
applyConfigDurations(config.durations);
|
|
192
|
+
applyConfigIcons(config.icons);
|
|
193
|
+
applyConfigStack(config.stack);
|
|
194
|
+
if (typeof config.maxVisible === "number")
|
|
195
|
+
maxVisible = Math.max(1, Math.floor(config.maxVisible) || 1);
|
|
196
|
+
function nextId() {
|
|
197
|
+
idCounter += 1;
|
|
198
|
+
const rand = Math.random().toString(36).slice(2, 8);
|
|
199
|
+
return `${PREFIX}-${idCounter}-${rand}`;
|
|
829
200
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
const dot = document.createElement("span");
|
|
837
|
-
dot.className = "ga-toast-unread-dot";
|
|
838
|
-
header.appendChild(dot);
|
|
839
|
-
}
|
|
840
|
-
if (opts.title) {
|
|
841
|
-
const title = document.createElement("div");
|
|
842
|
-
title.className = "ga-toast-title" + (opts.truncateTitle ? " ga-toast-title-truncate" : "");
|
|
843
|
-
title.textContent = opts.title;
|
|
844
|
-
header.appendChild(title);
|
|
845
|
-
}
|
|
846
|
-
if (opts.showStatus) {
|
|
847
|
-
const status = document.createElement("span");
|
|
848
|
-
status.className = "ga-toast-status";
|
|
849
|
-
const label = String(opts.statusText || type);
|
|
850
|
-
status.textContent = label.charAt(0).toUpperCase() + label.slice(1);
|
|
851
|
-
header.appendChild(status);
|
|
201
|
+
function log(event, payload) {
|
|
202
|
+
if (logger) {
|
|
203
|
+
try {
|
|
204
|
+
logger(event, payload);
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
852
207
|
}
|
|
853
|
-
content.appendChild(header);
|
|
854
208
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
if (
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
209
|
+
function injectStyles() {
|
|
210
|
+
if (!canUseDOM || !injectEnabled || !styleTarget) return;
|
|
211
|
+
const doc = document;
|
|
212
|
+
if (styleTarget.querySelector?.(`#${STYLE_ID}`)) return;
|
|
213
|
+
if (styleTarget === doc.head && doc.getElementById(STYLE_ID)) return;
|
|
214
|
+
const el = doc.createElement("style");
|
|
215
|
+
el.id = STYLE_ID;
|
|
216
|
+
if (styleNonce) el.setAttribute("nonce", styleNonce);
|
|
217
|
+
el.textContent = css;
|
|
218
|
+
styleTarget.appendChild(el);
|
|
219
|
+
}
|
|
220
|
+
function applyTheme() {
|
|
221
|
+
if (!canUseDOM || !styleTarget) return;
|
|
222
|
+
const t = themeTokens;
|
|
223
|
+
surfaceMode = t.surface;
|
|
224
|
+
progressMode = t.progress || "bar";
|
|
225
|
+
const sel = `.${instanceClass}.ga-toast-container`;
|
|
226
|
+
const light = themeVars(t);
|
|
227
|
+
const lightBody = Object.entries(light).map(([k, v]) => `${k}:${v}`).join(";");
|
|
228
|
+
const darkVars = t.dark ? themeVars(t.dark) : {};
|
|
229
|
+
const darkBody = Object.entries(darkVars).map(([k, v]) => `${k}:${v}`).join(";");
|
|
230
|
+
let cssText = "";
|
|
231
|
+
if (lightBody) cssText += `${sel}{${lightBody}}`;
|
|
232
|
+
if (darkBody)
|
|
233
|
+
cssText += `[data-ga-theme="dark"] ${sel},.ga-theme-dark ${sel}{${darkBody}}`;
|
|
234
|
+
if (!cssText) {
|
|
235
|
+
themeStyleEl?.remove();
|
|
236
|
+
themeStyleEl = null;
|
|
237
|
+
return;
|
|
863
238
|
}
|
|
864
|
-
if (
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
if (
|
|
868
|
-
|
|
869
|
-
body.appendChild(message);
|
|
239
|
+
if (!themeStyleEl) {
|
|
240
|
+
themeStyleEl = document.createElement("style");
|
|
241
|
+
themeStyleEl.id = `ga-toasts-theme-${seq}`;
|
|
242
|
+
if (styleNonce) themeStyleEl.setAttribute("nonce", styleNonce);
|
|
243
|
+
styleTarget.appendChild(themeStyleEl);
|
|
870
244
|
}
|
|
871
|
-
|
|
245
|
+
themeStyleEl.textContent = cssText;
|
|
872
246
|
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
}
|
|
887
|
-
content.appendChild(actions);
|
|
247
|
+
function ensureLiveRegions() {
|
|
248
|
+
if (!canUseDOM || !mount) return;
|
|
249
|
+
if (liveRegions && liveRegions.polite.isConnected && liveRegions.assertive.isConnected)
|
|
250
|
+
return;
|
|
251
|
+
const make = (politeness) => {
|
|
252
|
+
const region = document.createElement("div");
|
|
253
|
+
region.className = "ga-toast-live-region";
|
|
254
|
+
region.setAttribute("aria-live", politeness);
|
|
255
|
+
region.setAttribute("aria-atomic", "true");
|
|
256
|
+
region.setAttribute("role", politeness === "assertive" ? "alert" : "status");
|
|
257
|
+
mount.appendChild(region);
|
|
258
|
+
return region;
|
|
259
|
+
};
|
|
260
|
+
liveRegions = { polite: make("polite"), assertive: make("assertive") };
|
|
888
261
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
}
|
|
898
|
-
content.appendChild(steps);
|
|
262
|
+
function announce(text, assertive) {
|
|
263
|
+
if (!text) return;
|
|
264
|
+
ensureLiveRegions();
|
|
265
|
+
if (!liveRegions) return;
|
|
266
|
+
const region = assertive ? liveRegions.assertive : liveRegions.polite;
|
|
267
|
+
region.textContent = "";
|
|
268
|
+
window.setTimeout(() => {
|
|
269
|
+
region.textContent = text;
|
|
270
|
+
}, 50);
|
|
899
271
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
clearTimeout(timer.handle);
|
|
916
|
-
timer.handle = null;
|
|
917
|
-
timer.paused = true;
|
|
918
|
-
const elapsed = now() - timer.startedAt;
|
|
919
|
-
timer.remaining = Math.max(0, timer.remaining - elapsed);
|
|
920
|
-
freezeProgress(inst);
|
|
921
|
-
}
|
|
922
|
-
function resumeTimer(inst) {
|
|
923
|
-
if (!inst.timer.paused) return;
|
|
924
|
-
startTimer(inst);
|
|
925
|
-
}
|
|
926
|
-
function animateProgress(inst, ms) {
|
|
927
|
-
const bar = inst.progressEl;
|
|
928
|
-
if (!bar) return;
|
|
929
|
-
const fraction = inst.timer.duration > 0 ? ms / inst.timer.duration : 0;
|
|
930
|
-
bar.style.transition = "none";
|
|
931
|
-
bar.style.transform = `scaleX(${fraction})`;
|
|
932
|
-
void bar.offsetWidth;
|
|
933
|
-
bar.style.transition = `transform ${ms}ms linear`;
|
|
934
|
-
bar.style.transform = "scaleX(0)";
|
|
935
|
-
}
|
|
936
|
-
function freezeProgress(inst) {
|
|
937
|
-
const bar = inst.progressEl;
|
|
938
|
-
if (!bar) return;
|
|
939
|
-
const fraction = inst.timer.duration > 0 ? inst.timer.remaining / inst.timer.duration : 0;
|
|
940
|
-
bar.style.transition = "none";
|
|
941
|
-
bar.style.transform = `scaleX(${fraction})`;
|
|
942
|
-
}
|
|
943
|
-
function attachHandlers(inst, opts) {
|
|
944
|
-
const { el: el2, controller } = inst;
|
|
945
|
-
const signal = controller.signal;
|
|
946
|
-
el2.addEventListener(
|
|
947
|
-
"click",
|
|
948
|
-
(e) => {
|
|
949
|
-
const target = e.target;
|
|
950
|
-
if (target.closest("[data-ga-close]")) {
|
|
951
|
-
e.preventDefault();
|
|
952
|
-
close(inst.id);
|
|
953
|
-
return;
|
|
954
|
-
}
|
|
955
|
-
const actionBtn = target.closest("[data-ga-action]");
|
|
956
|
-
if (actionBtn && opts.actions) {
|
|
957
|
-
const idx = Array.from(
|
|
958
|
-
actionBtn.parentElement?.children || []
|
|
959
|
-
).indexOf(actionBtn);
|
|
960
|
-
const action = opts.actions[idx];
|
|
961
|
-
if (action) {
|
|
962
|
-
const handler = action.onClick || action.click;
|
|
963
|
-
if (handler) handler(e, inst.handle);
|
|
964
|
-
if (action.closeOnClick !== false) close(inst.id);
|
|
272
|
+
function getContainer(position) {
|
|
273
|
+
const existing = containers.get(position);
|
|
274
|
+
if (existing && existing.isConnected) return existing;
|
|
275
|
+
const container = document.createElement("div");
|
|
276
|
+
container.className = `ga-toast-container ga-toast-container-${position} ${instanceClass}`;
|
|
277
|
+
container.setAttribute("data-ga-position", position);
|
|
278
|
+
container.setAttribute("role", "region");
|
|
279
|
+
container.setAttribute("aria-label", "Notifications");
|
|
280
|
+
if (expandMode === "always") container.dataset.gaExpanded = "true";
|
|
281
|
+
if (expandMode === "hover") {
|
|
282
|
+
let collapseTimer = null;
|
|
283
|
+
const cancelCollapse = () => {
|
|
284
|
+
if (collapseTimer != null) {
|
|
285
|
+
clearTimeout(collapseTimer);
|
|
286
|
+
collapseTimer = null;
|
|
965
287
|
}
|
|
288
|
+
};
|
|
289
|
+
const expand = () => {
|
|
290
|
+
cancelCollapse();
|
|
291
|
+
setExpanded(container, true);
|
|
292
|
+
};
|
|
293
|
+
const collapse = () => {
|
|
294
|
+
cancelCollapse();
|
|
295
|
+
collapseTimer = setTimeout(() => {
|
|
296
|
+
collapseTimer = null;
|
|
297
|
+
setExpanded(container, false);
|
|
298
|
+
}, COLLAPSE_DELAY);
|
|
299
|
+
};
|
|
300
|
+
container.addEventListener("pointerenter", expand);
|
|
301
|
+
container.addEventListener("pointerleave", collapse);
|
|
302
|
+
container.addEventListener("focusin", expand);
|
|
303
|
+
container.addEventListener("focusout", (e) => {
|
|
304
|
+
if (!container.contains(e.relatedTarget)) collapse();
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
mount?.appendChild(container);
|
|
308
|
+
containers.set(position, container);
|
|
309
|
+
return container;
|
|
310
|
+
}
|
|
311
|
+
function setExpanded(container, expanded) {
|
|
312
|
+
if (expandMode !== "hover") return;
|
|
313
|
+
if (container.dataset.gaExpanded === "true" === expanded) return;
|
|
314
|
+
container.dataset.gaExpanded = expanded ? "true" : "false";
|
|
315
|
+
layout(container);
|
|
316
|
+
}
|
|
317
|
+
function instancesIn(container) {
|
|
318
|
+
return Array.from(container.children).map((child) => registry.get(child.id)).filter((inst) => !!inst);
|
|
319
|
+
}
|
|
320
|
+
function layout(container) {
|
|
321
|
+
const all = instancesIn(container);
|
|
322
|
+
const position = container.dataset.gaPosition || "top-end";
|
|
323
|
+
const dir = verticalDir(position);
|
|
324
|
+
const expanded = expandMode === "always" || expandMode === "hover" && container.dataset.gaExpanded === "true";
|
|
325
|
+
const reduce = prefersReducedMotion();
|
|
326
|
+
const front = newestOnTop ? all.slice() : all.slice().reverse();
|
|
327
|
+
container.style.setProperty("--ga-toasts-count", String(front.length));
|
|
328
|
+
let cumulative = 0;
|
|
329
|
+
front.forEach((inst, frontIndex) => {
|
|
330
|
+
if (inst.closing) return;
|
|
331
|
+
if (!inst.el.dataset.gaMounted) {
|
|
332
|
+
cumulative += inst.height + stackGap;
|
|
966
333
|
return;
|
|
967
334
|
}
|
|
968
|
-
|
|
969
|
-
|
|
335
|
+
let translateY;
|
|
336
|
+
let scale;
|
|
337
|
+
let opacity;
|
|
338
|
+
const overflow = frontIndex >= maxVisible;
|
|
339
|
+
if (overflow) pauseTimer(inst, "overflow");
|
|
340
|
+
else resumeTimer(inst, "overflow");
|
|
341
|
+
if (expanded || reduce) {
|
|
342
|
+
translateY = dir * cumulative;
|
|
343
|
+
scale = 1;
|
|
344
|
+
opacity = 1;
|
|
345
|
+
} else {
|
|
346
|
+
translateY = dir * frontIndex * peek;
|
|
347
|
+
scale = Math.max(1 - frontIndex * scaleStep, 0.85);
|
|
348
|
+
opacity = overflow ? 0 : 1;
|
|
970
349
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
350
|
+
const swipe = inst.swipeX ? ` translateX(${inst.swipeX}px)` : "";
|
|
351
|
+
const ty = position.startsWith("middle") ? `calc(-50% + ${translateY}px)` : `${translateY}px`;
|
|
352
|
+
inst.el.style.transform = `translateY(${ty})${swipe} scale(${scale})`;
|
|
353
|
+
inst.el.style.opacity = inst.swipeX ? String(swipeOpacity(inst.swipeX)) : String(opacity);
|
|
354
|
+
inst.el.style.zIndex = String(1e3 + front.length - frontIndex);
|
|
355
|
+
inst.el.style.pointerEvents = opacity === 0 ? "none" : "auto";
|
|
356
|
+
inst.el.setAttribute("aria-hidden", opacity === 0 ? "true" : "false");
|
|
357
|
+
cumulative += inst.height + stackGap;
|
|
358
|
+
});
|
|
979
359
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
"keydown",
|
|
984
|
-
(e) => {
|
|
985
|
-
if (e.key !== "Tab") return;
|
|
986
|
-
const focusables = el2.querySelectorAll(
|
|
987
|
-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
988
|
-
);
|
|
989
|
-
if (!focusables.length) return;
|
|
990
|
-
const first = focusables[0];
|
|
991
|
-
const last = focusables[focusables.length - 1];
|
|
992
|
-
const active = document.activeElement;
|
|
993
|
-
if (e.shiftKey && active === first) {
|
|
994
|
-
e.preventDefault();
|
|
995
|
-
last.focus();
|
|
996
|
-
} else if (!e.shiftKey && active === last) {
|
|
997
|
-
e.preventDefault();
|
|
998
|
-
first.focus();
|
|
999
|
-
}
|
|
1000
|
-
},
|
|
1001
|
-
{ signal }
|
|
1002
|
-
);
|
|
360
|
+
function measure(inst) {
|
|
361
|
+
const h = inst.el.offsetHeight;
|
|
362
|
+
if (h > 0) inst.height = h;
|
|
1003
363
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
364
|
+
function resolveOptions(options) {
|
|
365
|
+
const merged = {
|
|
366
|
+
type: "info",
|
|
367
|
+
duration: 5e3,
|
|
368
|
+
closable: true,
|
|
369
|
+
position: "top-end",
|
|
370
|
+
animation: "slide",
|
|
371
|
+
swipeToClose: true,
|
|
372
|
+
closeOnEscape: true,
|
|
373
|
+
progress: true,
|
|
374
|
+
progressPosition: "bottom",
|
|
375
|
+
pauseOnHover: true,
|
|
376
|
+
pauseOnPageHidden: true,
|
|
377
|
+
autoIcon: true,
|
|
378
|
+
glassmorphism: true,
|
|
379
|
+
html: false,
|
|
380
|
+
...globalDefaults,
|
|
381
|
+
...options
|
|
382
|
+
};
|
|
383
|
+
merged.position = merged.position || "top-end";
|
|
384
|
+
if (!POSITIONS.includes(merged.position)) merged.position = "top-end";
|
|
385
|
+
return merged;
|
|
386
|
+
}
|
|
387
|
+
function iconFor(type) {
|
|
388
|
+
return icons[type] ?? icons.info ?? null;
|
|
389
|
+
}
|
|
390
|
+
function createCloseButton() {
|
|
391
|
+
const btn = document.createElement("button");
|
|
392
|
+
btn.type = "button";
|
|
393
|
+
btn.className = "ga-toast-close";
|
|
394
|
+
btn.setAttribute("aria-label", "Close notification");
|
|
395
|
+
btn.setAttribute("data-ga-close", "");
|
|
396
|
+
btn.innerHTML = closeIcon;
|
|
397
|
+
return btn;
|
|
398
|
+
}
|
|
399
|
+
function appendProgress(el, opts, type) {
|
|
400
|
+
if (progressMode === "ring" || !opts.progress || (opts.duration || 0) <= 0 || opts.progressPosition === "none")
|
|
401
|
+
return null;
|
|
402
|
+
const p = document.createElement("div");
|
|
403
|
+
p.className = `ga-toast-progress ga-toast-progress-${type}` + (opts.progressPosition === "top" ? " ga-toast-progress-top" : "");
|
|
404
|
+
el.appendChild(p);
|
|
405
|
+
return p;
|
|
406
|
+
}
|
|
407
|
+
function buildIcon(iconHtml, opts) {
|
|
408
|
+
const icon = document.createElement("div");
|
|
409
|
+
icon.className = "ga-toast-icon";
|
|
410
|
+
icon.innerHTML = iconHtml;
|
|
411
|
+
const wantRing = progressMode === "ring" && opts.progress !== false && (opts.duration || 0) > 0;
|
|
412
|
+
if (!wantRing) return { el: icon, ring: null };
|
|
413
|
+
icon.classList.add("ga-toast-icon-ring");
|
|
414
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
415
|
+
const svg = document.createElementNS(ns, "svg");
|
|
416
|
+
svg.setAttribute("class", "ga-toast-ring");
|
|
417
|
+
svg.setAttribute("viewBox", "0 0 36 36");
|
|
418
|
+
svg.setAttribute("aria-hidden", "true");
|
|
419
|
+
const track = document.createElementNS(ns, "circle");
|
|
420
|
+
track.setAttribute("class", "ga-toast-ring-track");
|
|
421
|
+
track.setAttribute("cx", "18");
|
|
422
|
+
track.setAttribute("cy", "18");
|
|
423
|
+
track.setAttribute("r", "16");
|
|
424
|
+
const bar = document.createElementNS(ns, "circle");
|
|
425
|
+
bar.setAttribute("class", "ga-toast-ring-bar");
|
|
426
|
+
bar.setAttribute("cx", "18");
|
|
427
|
+
bar.setAttribute("cy", "18");
|
|
428
|
+
bar.setAttribute("r", "16");
|
|
429
|
+
svg.appendChild(track);
|
|
430
|
+
svg.appendChild(bar);
|
|
431
|
+
icon.appendChild(svg);
|
|
432
|
+
return { el: icon, ring: bar };
|
|
433
|
+
}
|
|
434
|
+
function buildToastElement(opts, id) {
|
|
435
|
+
const type = opts.type || "info";
|
|
436
|
+
const el = document.createElement("div");
|
|
437
|
+
el.id = id;
|
|
438
|
+
const glass = surfaceMode === "glass" || surfaceMode === void 0 && opts.glassmorphism;
|
|
439
|
+
el.className = [
|
|
440
|
+
"ga-toast",
|
|
441
|
+
`ga-toast-${type}`,
|
|
442
|
+
opts.size ? `ga-toast-${opts.size}` : "",
|
|
443
|
+
opts.variant ? `ga-toast-${type}-${opts.variant}` : "",
|
|
444
|
+
opts.animation || "",
|
|
445
|
+
opts.compact ? "ga-toast-compact" : "",
|
|
446
|
+
glass ? "ga-toast-glass" : "",
|
|
447
|
+
surfaceMode === "outline" ? "ga-toast-outline" : "",
|
|
448
|
+
type === "loading" ? "ga-toast-loading" : "",
|
|
449
|
+
opts.className || ""
|
|
450
|
+
].filter(Boolean).join(" ");
|
|
451
|
+
const role = opts.role || (ASSERTIVE_TYPES.has(type) ? "alert" : "status");
|
|
452
|
+
el.setAttribute("role", role);
|
|
453
|
+
el.setAttribute("aria-live", "off");
|
|
454
|
+
el.setAttribute("data-ga-type", type);
|
|
455
|
+
if (role === "alertdialog" || role === "dialog") {
|
|
456
|
+
const label = [opts.title, opts.message].filter(Boolean).join(". ");
|
|
457
|
+
if (label) el.setAttribute("aria-label", label);
|
|
458
|
+
}
|
|
459
|
+
let customEl = null;
|
|
460
|
+
if (opts.content != null) {
|
|
461
|
+
customEl = typeof opts.content === "function" ? opts.content() : opts.content;
|
|
462
|
+
} else if (renderFn) {
|
|
463
|
+
const produced = renderFn(opts, { id, close: () => close(id) });
|
|
464
|
+
if (produced) customEl = produced;
|
|
465
|
+
}
|
|
466
|
+
if (customEl != null) {
|
|
467
|
+
el.classList.add("ga-toast-has-custom");
|
|
468
|
+
const wrap = document.createElement("div");
|
|
469
|
+
wrap.className = "ga-toast-custom";
|
|
470
|
+
if (typeof customEl === "string") wrap.innerHTML = customEl;
|
|
471
|
+
else wrap.appendChild(customEl);
|
|
472
|
+
el.appendChild(wrap);
|
|
473
|
+
if (opts.closable) el.appendChild(createCloseButton());
|
|
474
|
+
return { el, progressEl: appendProgress(el, opts, type), ring: null };
|
|
475
|
+
}
|
|
476
|
+
if (opts.avatar) {
|
|
477
|
+
const avatar = document.createElement("img");
|
|
478
|
+
avatar.className = "ga-toast-avatar";
|
|
479
|
+
avatar.src = opts.avatar;
|
|
480
|
+
avatar.alt = opts.avatarAlt || opts.title || "Notification";
|
|
481
|
+
el.appendChild(avatar);
|
|
482
|
+
}
|
|
483
|
+
let iconHtml = null;
|
|
484
|
+
if (opts.icon) iconHtml = String(opts.icon);
|
|
485
|
+
else if (opts.icon !== false && opts.autoIcon !== false && !opts.avatar)
|
|
486
|
+
iconHtml = iconFor(type);
|
|
487
|
+
let ring = null;
|
|
488
|
+
if (iconHtml) {
|
|
489
|
+
const built = buildIcon(iconHtml, opts);
|
|
490
|
+
ring = built.ring;
|
|
491
|
+
el.appendChild(built.el);
|
|
492
|
+
}
|
|
493
|
+
const content = document.createElement("div");
|
|
494
|
+
content.className = "ga-toast-content";
|
|
495
|
+
if (opts.title || opts.showStatus || opts.unread) {
|
|
496
|
+
const header = document.createElement("div");
|
|
497
|
+
header.className = "ga-toast-header";
|
|
498
|
+
if (opts.unread) {
|
|
499
|
+
const dot = document.createElement("span");
|
|
500
|
+
dot.className = "ga-toast-unread-dot";
|
|
501
|
+
header.appendChild(dot);
|
|
1025
502
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
if (
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
},
|
|
1041
|
-
{ signal }
|
|
1042
|
-
);
|
|
1043
|
-
const end = (e) => {
|
|
1044
|
-
if (!dragging) return;
|
|
1045
|
-
dragging = false;
|
|
1046
|
-
const dx = e.clientX - startX;
|
|
1047
|
-
if (Math.abs(dx) > THRESHOLD) {
|
|
1048
|
-
const dir = dx > 0 ? 1 : -1;
|
|
1049
|
-
inst.el.style.transition = "transform 0.2s ease, opacity 0.2s ease";
|
|
1050
|
-
inst.el.style.transform = `translateX(${dir * 400}px)`;
|
|
1051
|
-
inst.el.style.opacity = "0";
|
|
1052
|
-
close(inst.id);
|
|
1053
|
-
} else {
|
|
1054
|
-
inst.swipeX = 0;
|
|
1055
|
-
const container = el2.parentElement;
|
|
1056
|
-
if (container) layout(container);
|
|
1057
|
-
resumeTimer(inst);
|
|
503
|
+
if (opts.title) {
|
|
504
|
+
const title = document.createElement("div");
|
|
505
|
+
title.className = "ga-toast-title" + (opts.truncateTitle ? " ga-toast-title-truncate" : "");
|
|
506
|
+
title.textContent = opts.title;
|
|
507
|
+
header.appendChild(title);
|
|
508
|
+
}
|
|
509
|
+
if (opts.showStatus) {
|
|
510
|
+
const status = document.createElement("span");
|
|
511
|
+
status.className = "ga-toast-status";
|
|
512
|
+
const label = String(opts.statusText || type);
|
|
513
|
+
status.textContent = label.charAt(0).toUpperCase() + label.slice(1);
|
|
514
|
+
header.appendChild(status);
|
|
515
|
+
}
|
|
516
|
+
content.appendChild(header);
|
|
1058
517
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
518
|
+
if (opts.message || opts.meta) {
|
|
519
|
+
const body = document.createElement("div");
|
|
520
|
+
body.className = "ga-toast-body";
|
|
521
|
+
if (opts.meta) {
|
|
522
|
+
const meta = document.createElement("div");
|
|
523
|
+
meta.className = "ga-toast-meta";
|
|
524
|
+
meta.textContent = opts.meta;
|
|
525
|
+
body.appendChild(meta);
|
|
526
|
+
}
|
|
527
|
+
if (opts.message) {
|
|
528
|
+
const message = document.createElement("div");
|
|
529
|
+
message.className = "ga-toast-message";
|
|
530
|
+
if (opts.html) message.innerHTML = opts.message;
|
|
531
|
+
else message.textContent = opts.message;
|
|
532
|
+
body.appendChild(message);
|
|
533
|
+
}
|
|
534
|
+
content.appendChild(body);
|
|
1073
535
|
}
|
|
1074
|
-
if (
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
} else if (!(typeof inst.el.matches === "function" && inst.el.matches(":hover"))) {
|
|
1088
|
-
resumeTimer(inst);
|
|
536
|
+
if (opts.actions && opts.actions.length && !opts.compact) {
|
|
537
|
+
const actions = document.createElement("div");
|
|
538
|
+
actions.className = "ga-toast-actions";
|
|
539
|
+
for (const action of opts.actions) {
|
|
540
|
+
const btn = document.createElement("button");
|
|
541
|
+
btn.type = "button";
|
|
542
|
+
btn.className = [
|
|
543
|
+
"ga-toast-btn",
|
|
544
|
+
action.className || action.class || "ga-toast-btn-secondary"
|
|
545
|
+
].join(" ");
|
|
546
|
+
btn.textContent = action.text;
|
|
547
|
+
btn.setAttribute("data-ga-action", "");
|
|
548
|
+
actions.appendChild(btn);
|
|
1089
549
|
}
|
|
550
|
+
content.appendChild(actions);
|
|
1090
551
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
requestAnimationFrame(() => bd.classList.add("ga-toast-backdrop-show"));
|
|
1102
|
-
}
|
|
1103
|
-
function hideBackdrop() {
|
|
1104
|
-
if (!backdropEl) return;
|
|
1105
|
-
const bd = backdropEl;
|
|
1106
|
-
bd.classList.remove("ga-toast-backdrop-show");
|
|
1107
|
-
setTimeout(() => {
|
|
1108
|
-
if (activeModalId == null && bd.parentNode) bd.remove();
|
|
1109
|
-
}, 220);
|
|
1110
|
-
}
|
|
1111
|
-
function noopHandle(id) {
|
|
1112
|
-
const handle = {
|
|
1113
|
-
id,
|
|
1114
|
-
el: canUseDOM ? document.createElement("div") : {},
|
|
1115
|
-
update: () => handle,
|
|
1116
|
-
close: () => {
|
|
552
|
+
if (opts.steps && opts.steps > 1) {
|
|
553
|
+
const steps = document.createElement("div");
|
|
554
|
+
steps.className = "ga-toast-steps";
|
|
555
|
+
const active = Math.min(opts.steps, Math.max(1, opts.currentStep || 1));
|
|
556
|
+
for (let i = 1; i <= opts.steps; i += 1) {
|
|
557
|
+
const step = document.createElement("div");
|
|
558
|
+
step.className = "ga-toast-step" + (i <= active ? " ga-toast-step-active" : "");
|
|
559
|
+
steps.appendChild(step);
|
|
560
|
+
}
|
|
561
|
+
content.appendChild(steps);
|
|
1117
562
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
563
|
+
el.appendChild(content);
|
|
564
|
+
if (opts.closable) el.appendChild(createCloseButton());
|
|
565
|
+
return { el, progressEl: appendProgress(el, opts, type), ring };
|
|
566
|
+
}
|
|
567
|
+
const RING_CIRC = 2 * Math.PI * 16;
|
|
568
|
+
function startTimer(inst) {
|
|
569
|
+
const { timer } = inst;
|
|
570
|
+
if (timer.duration <= 0 || timer.remaining <= 0) return;
|
|
571
|
+
if (timer.holds.size > 0) return;
|
|
572
|
+
timer.startedAt = now();
|
|
573
|
+
timer.handle = setTimeout(() => close(inst.id), timer.remaining);
|
|
574
|
+
animateProgress(inst, timer.remaining);
|
|
1126
575
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
576
|
+
function pauseTimer(inst, reason) {
|
|
577
|
+
const { timer } = inst;
|
|
578
|
+
const wasHeld = timer.holds.size > 0;
|
|
579
|
+
timer.holds.add(reason);
|
|
580
|
+
if (wasHeld || timer.handle == null) return;
|
|
581
|
+
clearTimeout(timer.handle);
|
|
582
|
+
timer.handle = null;
|
|
583
|
+
const elapsed = now() - timer.startedAt;
|
|
584
|
+
timer.remaining = Math.max(0, timer.remaining - elapsed);
|
|
585
|
+
freezeProgress(inst);
|
|
586
|
+
}
|
|
587
|
+
function resumeTimer(inst, reason) {
|
|
588
|
+
const { timer } = inst;
|
|
589
|
+
if (!timer.holds.delete(reason)) return;
|
|
590
|
+
if (timer.holds.size > 0) return;
|
|
591
|
+
startTimer(inst);
|
|
592
|
+
}
|
|
593
|
+
function animateProgress(inst, ms) {
|
|
594
|
+
const fraction = inst.timer.duration > 0 ? ms / inst.timer.duration : 0;
|
|
595
|
+
if (inst.ring) {
|
|
596
|
+
const ring = inst.ring;
|
|
597
|
+
ring.style.transition = "none";
|
|
598
|
+
ring.style.strokeDasharray = String(RING_CIRC);
|
|
599
|
+
ring.style.strokeDashoffset = String(RING_CIRC * (1 - fraction));
|
|
600
|
+
void ring.getBoundingClientRect?.();
|
|
601
|
+
ring.style.transition = `stroke-dashoffset ${ms}ms linear`;
|
|
602
|
+
ring.style.strokeDashoffset = String(RING_CIRC);
|
|
603
|
+
return;
|
|
1130
604
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
605
|
+
const bar = inst.progressEl;
|
|
606
|
+
if (!bar) return;
|
|
607
|
+
bar.style.transition = "none";
|
|
608
|
+
bar.style.transform = `scaleX(${fraction})`;
|
|
609
|
+
void bar.offsetWidth;
|
|
610
|
+
bar.style.transition = `transform ${ms}ms linear`;
|
|
611
|
+
bar.style.transform = "scaleX(0)";
|
|
1134
612
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
paused: false
|
|
1147
|
-
};
|
|
1148
|
-
const handle = {
|
|
1149
|
-
id,
|
|
1150
|
-
el: el2,
|
|
1151
|
-
update: (o) => update(id, o) ? handle : handle,
|
|
1152
|
-
close: () => close(id)
|
|
1153
|
-
};
|
|
1154
|
-
const inst = {
|
|
1155
|
-
id,
|
|
1156
|
-
el: el2,
|
|
1157
|
-
handle,
|
|
1158
|
-
opts,
|
|
1159
|
-
controller,
|
|
1160
|
-
progressEl,
|
|
1161
|
-
timer,
|
|
1162
|
-
height: 0,
|
|
1163
|
-
closing: false,
|
|
1164
|
-
swipeX: 0,
|
|
1165
|
-
resizeObserver: null,
|
|
1166
|
-
prevFocus: opts.moveFocus ? document.activeElement : null
|
|
1167
|
-
};
|
|
1168
|
-
registry.set(id, inst);
|
|
1169
|
-
if (opts.modal) {
|
|
1170
|
-
activeModalId = id;
|
|
1171
|
-
el2.setAttribute("aria-modal", "true");
|
|
1172
|
-
showBackdrop();
|
|
613
|
+
function freezeProgress(inst) {
|
|
614
|
+
const fraction = inst.timer.duration > 0 ? inst.timer.remaining / inst.timer.duration : 0;
|
|
615
|
+
if (inst.ring) {
|
|
616
|
+
inst.ring.style.transition = "none";
|
|
617
|
+
inst.ring.style.strokeDashoffset = String(RING_CIRC * (1 - fraction));
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
const bar = inst.progressEl;
|
|
621
|
+
if (!bar) return;
|
|
622
|
+
bar.style.transition = "none";
|
|
623
|
+
bar.style.transform = `scaleX(${fraction})`;
|
|
1173
624
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
625
|
+
function attachHandlers(inst, opts) {
|
|
626
|
+
const { el, controller } = inst;
|
|
627
|
+
const signal = controller.signal;
|
|
628
|
+
el.addEventListener(
|
|
629
|
+
"click",
|
|
630
|
+
(e) => {
|
|
631
|
+
const target = e.target;
|
|
632
|
+
if (target.closest("[data-ga-close]")) {
|
|
633
|
+
e.preventDefault();
|
|
634
|
+
close(inst.id);
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
const actionBtn = target.closest("[data-ga-action]");
|
|
638
|
+
if (actionBtn && opts.actions) {
|
|
639
|
+
const idx = Array.from(
|
|
640
|
+
actionBtn.parentElement?.children || []
|
|
641
|
+
).indexOf(actionBtn);
|
|
642
|
+
const action = opts.actions[idx];
|
|
643
|
+
if (action) {
|
|
644
|
+
const handler = action.onClick || action.click;
|
|
645
|
+
if (handler) handler(e, inst.handle);
|
|
646
|
+
if (action.closeOnClick !== false) close(inst.id);
|
|
647
|
+
}
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (opts.clickToClose && !target.closest(".ga-toast-actions")) {
|
|
651
|
+
close(inst.id);
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
{ signal }
|
|
655
|
+
);
|
|
656
|
+
if (opts.pauseOnHover) {
|
|
657
|
+
el.addEventListener("pointerenter", () => pauseTimer(inst, "hover"), { signal });
|
|
658
|
+
el.addEventListener("pointerleave", () => resumeTimer(inst, "hover"), { signal });
|
|
659
|
+
el.addEventListener("focusin", () => pauseTimer(inst, "focus"), { signal });
|
|
660
|
+
el.addEventListener("focusout", () => resumeTimer(inst, "focus"), { signal });
|
|
661
|
+
}
|
|
662
|
+
if (opts.swipeToClose) attachSwipe(inst);
|
|
663
|
+
if (opts.modal) {
|
|
664
|
+
el.addEventListener(
|
|
665
|
+
"keydown",
|
|
666
|
+
(e) => {
|
|
667
|
+
if (e.key !== "Tab") return;
|
|
668
|
+
const focusables = el.querySelectorAll(
|
|
669
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
670
|
+
);
|
|
671
|
+
if (!focusables.length) return;
|
|
672
|
+
const first = focusables[0];
|
|
673
|
+
const last = focusables[focusables.length - 1];
|
|
674
|
+
const active = document.activeElement;
|
|
675
|
+
if (e.shiftKey && active === first) {
|
|
676
|
+
e.preventDefault();
|
|
677
|
+
last.focus();
|
|
678
|
+
} else if (!e.shiftKey && active === last) {
|
|
679
|
+
e.preventDefault();
|
|
680
|
+
first.focus();
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
{ signal }
|
|
684
|
+
);
|
|
685
|
+
}
|
|
1186
686
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
687
|
+
function attachSwipe(inst) {
|
|
688
|
+
const { el, controller } = inst;
|
|
689
|
+
const signal = controller.signal;
|
|
690
|
+
const THRESHOLD = 70;
|
|
691
|
+
let dragging = false;
|
|
692
|
+
let swiping = false;
|
|
693
|
+
let startX = 0;
|
|
694
|
+
let startY = 0;
|
|
695
|
+
el.addEventListener(
|
|
696
|
+
"pointerdown",
|
|
697
|
+
(e) => {
|
|
698
|
+
if (e.pointerType === "mouse" && e.button !== 0) return;
|
|
699
|
+
if (e.target.closest("button, a, input, textarea, select"))
|
|
700
|
+
return;
|
|
701
|
+
dragging = true;
|
|
702
|
+
swiping = false;
|
|
703
|
+
startX = e.clientX;
|
|
704
|
+
startY = e.clientY;
|
|
705
|
+
pauseTimer(inst, "swipe");
|
|
1198
706
|
try {
|
|
1199
|
-
|
|
707
|
+
el.setPointerCapture(e.pointerId);
|
|
1200
708
|
} catch {
|
|
1201
709
|
}
|
|
710
|
+
},
|
|
711
|
+
{ signal }
|
|
712
|
+
);
|
|
713
|
+
el.addEventListener(
|
|
714
|
+
"pointermove",
|
|
715
|
+
(e) => {
|
|
716
|
+
if (!dragging) return;
|
|
717
|
+
const dx = e.clientX - startX;
|
|
718
|
+
const dy = e.clientY - startY;
|
|
719
|
+
if (Math.abs(dx) < 6 || Math.abs(dx) < Math.abs(dy)) return;
|
|
720
|
+
e.preventDefault();
|
|
721
|
+
if (!swiping) {
|
|
722
|
+
swiping = true;
|
|
723
|
+
el.classList.add("ga-toast-swiping");
|
|
724
|
+
const sel = typeof window !== "undefined" && typeof window.getSelection === "function" ? window.getSelection() : null;
|
|
725
|
+
sel?.removeAllRanges();
|
|
726
|
+
}
|
|
727
|
+
inst.swipeX = dx;
|
|
728
|
+
const container = el.parentElement;
|
|
729
|
+
if (container) layout(container);
|
|
730
|
+
},
|
|
731
|
+
{ signal }
|
|
732
|
+
);
|
|
733
|
+
const end = (e) => {
|
|
734
|
+
if (!dragging) return;
|
|
735
|
+
dragging = false;
|
|
736
|
+
swiping = false;
|
|
737
|
+
el.classList.remove("ga-toast-swiping");
|
|
738
|
+
const dx = e.clientX - startX;
|
|
739
|
+
if (Math.abs(dx) > THRESHOLD) {
|
|
740
|
+
const dir = dx > 0 ? 1 : -1;
|
|
741
|
+
inst.el.style.transition = "transform 0.2s ease, opacity 0.2s ease";
|
|
742
|
+
inst.el.style.transform = `translateX(${dir * 400}px)`;
|
|
743
|
+
inst.el.style.opacity = "0";
|
|
744
|
+
close(inst.id);
|
|
745
|
+
} else {
|
|
746
|
+
inst.swipeX = 0;
|
|
747
|
+
const container = el.parentElement;
|
|
748
|
+
if (container) layout(container);
|
|
749
|
+
resumeTimer(inst, "swipe");
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
el.addEventListener("pointerup", end, { signal });
|
|
753
|
+
el.addEventListener("pointercancel", end, { signal });
|
|
754
|
+
}
|
|
755
|
+
function bindEscape() {
|
|
756
|
+
if (escapeBound || !canUseDOM) return;
|
|
757
|
+
escapeBound = true;
|
|
758
|
+
document.addEventListener("keydown", (e) => {
|
|
759
|
+
if (e.key !== "Escape") return;
|
|
760
|
+
let newest = null;
|
|
761
|
+
for (const inst of registry.values()) {
|
|
762
|
+
if (inst.closing) continue;
|
|
763
|
+
if (inst.opts.closeOnEscape === false || !inst.opts.closable) continue;
|
|
764
|
+
newest = inst;
|
|
765
|
+
}
|
|
766
|
+
if (newest) close(newest.id);
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
function bindVisibility() {
|
|
770
|
+
if (visibilityBound || !canUseDOM || typeof document.addEventListener !== "function")
|
|
771
|
+
return;
|
|
772
|
+
visibilityBound = true;
|
|
773
|
+
document.addEventListener("visibilitychange", () => {
|
|
774
|
+
const hidden = document.hidden;
|
|
775
|
+
for (const inst of registry.values()) {
|
|
776
|
+
if (inst.closing || inst.opts.pauseOnPageHidden === false) continue;
|
|
777
|
+
if (hidden) pauseTimer(inst, "tab");
|
|
778
|
+
else resumeTimer(inst, "tab");
|
|
1202
779
|
}
|
|
1203
780
|
});
|
|
1204
|
-
});
|
|
1205
|
-
if (!opts.modal && opts.role !== "alertdialog") {
|
|
1206
|
-
announce(
|
|
1207
|
-
[opts.title, opts.message].filter(Boolean).join(". "),
|
|
1208
|
-
ASSERTIVE_TYPES.has(opts.type || "info")
|
|
1209
|
-
);
|
|
1210
781
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
782
|
+
function showBackdrop() {
|
|
783
|
+
if (!canUseDOM || !mount) return;
|
|
784
|
+
if (!backdropEl) {
|
|
785
|
+
backdropEl = document.createElement("div");
|
|
786
|
+
backdropEl.className = "ga-toast-backdrop";
|
|
1216
787
|
}
|
|
788
|
+
if (!backdropEl.isConnected) mount.appendChild(backdropEl);
|
|
789
|
+
const bd = backdropEl;
|
|
790
|
+
requestAnimationFrame(() => bd.classList.add("ga-toast-backdrop-show"));
|
|
1217
791
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
if (!inst || inst.closing) return;
|
|
1226
|
-
inst.closing = true;
|
|
1227
|
-
if (inst.timer.handle != null) {
|
|
1228
|
-
clearTimeout(inst.timer.handle);
|
|
1229
|
-
inst.timer.handle = null;
|
|
792
|
+
function hideBackdrop() {
|
|
793
|
+
if (!backdropEl) return;
|
|
794
|
+
const bd = backdropEl;
|
|
795
|
+
bd.classList.remove("ga-toast-backdrop-show");
|
|
796
|
+
setTimeout(() => {
|
|
797
|
+
if (activeModalId == null && bd.parentNode) bd.remove();
|
|
798
|
+
}, 220);
|
|
1230
799
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
800
|
+
function noopHandle(id) {
|
|
801
|
+
const handle = {
|
|
802
|
+
id,
|
|
803
|
+
el: canUseDOM ? document.createElement("div") : {},
|
|
804
|
+
update: () => handle,
|
|
805
|
+
close: () => {
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
return handle;
|
|
1240
809
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
registry.delete(id);
|
|
1247
|
-
el2.remove();
|
|
1248
|
-
if (activeModalId === id) {
|
|
1249
|
-
activeModalId = null;
|
|
1250
|
-
hideBackdrop();
|
|
810
|
+
function show(options = {}) {
|
|
811
|
+
if (!canUseDOM) return noopHandle(options.id || nextId());
|
|
812
|
+
const opts = resolveOptions(options);
|
|
813
|
+
if (opts.id && registry.has(opts.id)) {
|
|
814
|
+
return update(opts.id, options) || noopHandle(opts.id);
|
|
1251
815
|
}
|
|
1252
|
-
if (
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
try {
|
|
1256
|
-
prev.focus({ preventScroll: true });
|
|
1257
|
-
} catch {
|
|
816
|
+
if (opts.modal) {
|
|
817
|
+
if (activeModalId && registry.has(activeModalId)) {
|
|
818
|
+
return registry.get(activeModalId).handle;
|
|
1258
819
|
}
|
|
820
|
+
opts.swipeToClose = false;
|
|
821
|
+
opts.closeOnEscape = false;
|
|
822
|
+
opts.moveFocus = true;
|
|
823
|
+
}
|
|
824
|
+
injectStyles();
|
|
825
|
+
bindEscape();
|
|
826
|
+
bindVisibility();
|
|
827
|
+
const id = opts.id || nextId();
|
|
828
|
+
const { el, progressEl, ring } = buildToastElement(opts, id);
|
|
829
|
+
const controller = new AbortController();
|
|
830
|
+
const timer = {
|
|
831
|
+
duration: opts.duration || 0,
|
|
832
|
+
remaining: opts.duration || 0,
|
|
833
|
+
startedAt: 0,
|
|
834
|
+
handle: null,
|
|
835
|
+
holds: /* @__PURE__ */ new Set()
|
|
836
|
+
};
|
|
837
|
+
const handle = {
|
|
838
|
+
id,
|
|
839
|
+
el,
|
|
840
|
+
update: (o) => update(id, o) ? handle : handle,
|
|
841
|
+
close: () => close(id)
|
|
842
|
+
};
|
|
843
|
+
const inst = {
|
|
844
|
+
id,
|
|
845
|
+
el,
|
|
846
|
+
handle,
|
|
847
|
+
opts,
|
|
848
|
+
controller,
|
|
849
|
+
progressEl,
|
|
850
|
+
ring,
|
|
851
|
+
timer,
|
|
852
|
+
height: 0,
|
|
853
|
+
closing: false,
|
|
854
|
+
swipeX: 0,
|
|
855
|
+
resizeObserver: null,
|
|
856
|
+
prevFocus: opts.moveFocus ? document.activeElement : null
|
|
857
|
+
};
|
|
858
|
+
registry.set(id, inst);
|
|
859
|
+
if (opts.modal) {
|
|
860
|
+
activeModalId = id;
|
|
861
|
+
el.setAttribute("aria-modal", "true");
|
|
862
|
+
showBackdrop();
|
|
1259
863
|
}
|
|
1260
|
-
|
|
864
|
+
const container = getContainer(opts.position);
|
|
865
|
+
el.style.transform = offscreenTransform(opts.position);
|
|
866
|
+
el.style.opacity = "0";
|
|
867
|
+
container.appendChild(el);
|
|
868
|
+
attachHandlers(inst, opts);
|
|
869
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
870
|
+
inst.resizeObserver = new ResizeObserver(() => {
|
|
871
|
+
measure(inst);
|
|
872
|
+
const parent = el.parentElement;
|
|
873
|
+
if (parent) layout(parent);
|
|
874
|
+
});
|
|
875
|
+
inst.resizeObserver.observe(el);
|
|
876
|
+
}
|
|
877
|
+
requestAnimationFrame(() => {
|
|
878
|
+
requestAnimationFrame(() => {
|
|
879
|
+
if (!registry.has(id)) return;
|
|
880
|
+
measure(inst);
|
|
881
|
+
el.dataset.gaMounted = "true";
|
|
882
|
+
el.style.opacity = "1";
|
|
883
|
+
layout(container);
|
|
884
|
+
startTimer(inst);
|
|
885
|
+
if (opts.moveFocus) {
|
|
886
|
+
const target = el.querySelector("[data-ga-action]") || el;
|
|
887
|
+
if (target === el) el.tabIndex = -1;
|
|
888
|
+
try {
|
|
889
|
+
target.focus({ preventScroll: true });
|
|
890
|
+
} catch {
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
});
|
|
895
|
+
if (!opts.modal && opts.role !== "alertdialog") {
|
|
896
|
+
announce(
|
|
897
|
+
[opts.title, opts.message].filter(Boolean).join(". "),
|
|
898
|
+
ASSERTIVE_TYPES.has(opts.type || "info")
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
if (opts.onShow) {
|
|
1261
902
|
try {
|
|
1262
|
-
|
|
903
|
+
opts.onShow(handle);
|
|
1263
904
|
} catch (err) {
|
|
1264
|
-
log("toast:
|
|
905
|
+
log("toast:onShow:error", err);
|
|
1265
906
|
}
|
|
1266
907
|
}
|
|
1267
|
-
log("toast:
|
|
1268
|
-
|
|
1269
|
-
const onEnd = (e) => {
|
|
1270
|
-
if (e.target === el2 && (e.propertyName === "transform" || e.propertyName === "opacity"))
|
|
1271
|
-
finalize();
|
|
1272
|
-
};
|
|
1273
|
-
el2.addEventListener("transitionend", onEnd);
|
|
1274
|
-
setTimeout(finalize, REMOVE_FALLBACK);
|
|
1275
|
-
}
|
|
1276
|
-
function normalizeId(idOrSelector) {
|
|
1277
|
-
return idOrSelector.startsWith("#") ? idOrSelector.slice(1) : idOrSelector;
|
|
1278
|
-
}
|
|
1279
|
-
function update(target, options) {
|
|
1280
|
-
const id = typeof target === "string" ? normalizeId(target) : target.id;
|
|
1281
|
-
const inst = registry.get(id);
|
|
1282
|
-
if (!inst) {
|
|
1283
|
-
log("toast:update:not-found", id);
|
|
1284
|
-
return null;
|
|
908
|
+
log("toast:show", { id, type: opts.type });
|
|
909
|
+
return handle;
|
|
1285
910
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
911
|
+
function close(target) {
|
|
912
|
+
if (!target) return;
|
|
913
|
+
const id = typeof target === "string" ? normalizeId(target) : target.id;
|
|
914
|
+
const inst = registry.get(id);
|
|
915
|
+
if (!inst || inst.closing) return;
|
|
916
|
+
inst.closing = true;
|
|
917
|
+
if (inst.timer.handle != null) {
|
|
918
|
+
clearTimeout(inst.timer.handle);
|
|
919
|
+
inst.timer.handle = null;
|
|
920
|
+
}
|
|
921
|
+
inst.controller.abort();
|
|
922
|
+
inst.resizeObserver?.disconnect();
|
|
923
|
+
const { el } = inst;
|
|
924
|
+
const container = el.parentElement;
|
|
925
|
+
if (!inst.swipeX) {
|
|
926
|
+
el.style.transition = "";
|
|
927
|
+
el.classList.add("ga-toast-hide");
|
|
928
|
+
el.style.transform = offscreenTransform(inst.opts.position);
|
|
929
|
+
el.style.opacity = "0";
|
|
930
|
+
}
|
|
931
|
+
let removed = false;
|
|
932
|
+
const finalize = () => {
|
|
933
|
+
if (removed) return;
|
|
934
|
+
removed = true;
|
|
935
|
+
el.removeEventListener("transitionend", onEnd);
|
|
936
|
+
registry.delete(id);
|
|
937
|
+
el.remove();
|
|
938
|
+
if (activeModalId === id) {
|
|
939
|
+
activeModalId = null;
|
|
940
|
+
hideBackdrop();
|
|
941
|
+
}
|
|
942
|
+
if (container) layout(container);
|
|
943
|
+
const prev = inst.prevFocus;
|
|
944
|
+
if (prev && typeof prev.focus === "function" && document.contains(prev)) {
|
|
945
|
+
try {
|
|
946
|
+
prev.focus({ preventScroll: true });
|
|
947
|
+
} catch {
|
|
1297
948
|
}
|
|
1298
|
-
title = document.createElement("div");
|
|
1299
|
-
title.className = "ga-toast-title";
|
|
1300
|
-
header.appendChild(title);
|
|
1301
949
|
}
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
950
|
+
if (inst.opts.onClose) {
|
|
951
|
+
try {
|
|
952
|
+
inst.opts.onClose(inst.handle);
|
|
953
|
+
} catch (err) {
|
|
954
|
+
log("toast:onClose:error", err);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
log("toast:close", { id });
|
|
958
|
+
};
|
|
959
|
+
const onEnd = (e) => {
|
|
960
|
+
if (e.target === el && (e.propertyName === "transform" || e.propertyName === "opacity"))
|
|
961
|
+
finalize();
|
|
962
|
+
};
|
|
963
|
+
el.addEventListener("transitionend", onEnd);
|
|
964
|
+
setTimeout(finalize, REMOVE_FALLBACK);
|
|
1305
965
|
}
|
|
1306
|
-
|
|
1307
|
-
const
|
|
1308
|
-
|
|
1309
|
-
if (!
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
966
|
+
function update(target, options) {
|
|
967
|
+
const id = typeof target === "string" ? normalizeId(target) : target.id;
|
|
968
|
+
const inst = registry.get(id);
|
|
969
|
+
if (!inst) {
|
|
970
|
+
log("toast:update:not-found", id);
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
const opts = inst.opts;
|
|
974
|
+
if (options.title !== void 0) {
|
|
975
|
+
let title = inst.el.querySelector(".ga-toast-title");
|
|
976
|
+
if (!title && options.title) {
|
|
1314
977
|
const content = inst.el.querySelector(".ga-toast-content");
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
978
|
+
if (content) {
|
|
979
|
+
let header = content.querySelector(".ga-toast-header");
|
|
980
|
+
if (!header) {
|
|
981
|
+
header = document.createElement("div");
|
|
982
|
+
header.className = "ga-toast-header";
|
|
983
|
+
content.insertBefore(header, content.firstChild);
|
|
984
|
+
}
|
|
985
|
+
title = document.createElement("div");
|
|
986
|
+
title.className = "ga-toast-title";
|
|
987
|
+
header.appendChild(title);
|
|
988
|
+
}
|
|
1318
989
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
body.appendChild(message);
|
|
990
|
+
if (title) title.textContent = options.title;
|
|
991
|
+
opts.title = options.title;
|
|
1322
992
|
}
|
|
1323
|
-
if (message) {
|
|
1324
|
-
|
|
1325
|
-
|
|
993
|
+
if (options.message !== void 0) {
|
|
994
|
+
const useHtml = options.html ?? opts.html;
|
|
995
|
+
let message = inst.el.querySelector(".ga-toast-message");
|
|
996
|
+
if (!message && options.message) {
|
|
997
|
+
let body = inst.el.querySelector(".ga-toast-body");
|
|
998
|
+
if (!body) {
|
|
999
|
+
body = document.createElement("div");
|
|
1000
|
+
body.className = "ga-toast-body";
|
|
1001
|
+
const content = inst.el.querySelector(".ga-toast-content");
|
|
1002
|
+
const anchor = content?.querySelector(".ga-toast-actions, .ga-toast-steps");
|
|
1003
|
+
if (anchor) content.insertBefore(body, anchor);
|
|
1004
|
+
else content?.appendChild(body);
|
|
1005
|
+
}
|
|
1006
|
+
message = document.createElement("div");
|
|
1007
|
+
message.className = "ga-toast-message";
|
|
1008
|
+
body.appendChild(message);
|
|
1009
|
+
}
|
|
1010
|
+
if (message) {
|
|
1011
|
+
if (useHtml) message.innerHTML = options.message;
|
|
1012
|
+
else message.textContent = options.message;
|
|
1013
|
+
}
|
|
1014
|
+
opts.message = options.message;
|
|
1326
1015
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
);
|
|
1016
|
+
if (options.type && options.type !== opts.type) {
|
|
1017
|
+
const prev = opts.type;
|
|
1018
|
+
inst.el.classList.remove(`ga-toast-${prev}`, "ga-toast-loading");
|
|
1019
|
+
inst.el.classList.add(`ga-toast-${options.type}`);
|
|
1020
|
+
inst.el.setAttribute("data-ga-type", options.type);
|
|
1021
|
+
if (options.type === "loading") inst.el.classList.add("ga-toast-loading");
|
|
1022
|
+
if (inst.progressEl) {
|
|
1023
|
+
inst.progressEl.className = inst.progressEl.className.replace(
|
|
1024
|
+
/ga-toast-progress-\w+/,
|
|
1025
|
+
`ga-toast-progress-${options.type}`
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
const iconEl = inst.el.querySelector(".ga-toast-icon");
|
|
1029
|
+
if (iconEl && opts.autoIcon !== false && !options.icon) {
|
|
1030
|
+
const next = iconFor(options.type);
|
|
1031
|
+
if (next != null) iconEl.innerHTML = next;
|
|
1032
|
+
}
|
|
1033
|
+
opts.type = options.type;
|
|
1340
1034
|
}
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
iconEl =
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
inst.el.insertBefore(iconEl, content);
|
|
1035
|
+
if (options.icon !== void 0) {
|
|
1036
|
+
let iconEl = inst.el.querySelector(".ga-toast-icon");
|
|
1037
|
+
if (options.icon) {
|
|
1038
|
+
if (!iconEl) {
|
|
1039
|
+
iconEl = document.createElement("div");
|
|
1040
|
+
iconEl.className = "ga-toast-icon";
|
|
1041
|
+
const content = inst.el.querySelector(".ga-toast-content");
|
|
1042
|
+
inst.el.insertBefore(iconEl, content);
|
|
1043
|
+
}
|
|
1044
|
+
iconEl.innerHTML = String(options.icon);
|
|
1045
|
+
} else if (iconEl) {
|
|
1046
|
+
iconEl.remove();
|
|
1354
1047
|
}
|
|
1355
|
-
iconEl.innerHTML = String(options.icon);
|
|
1356
|
-
} else if (iconEl) {
|
|
1357
|
-
iconEl.remove();
|
|
1358
1048
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1049
|
+
if (options.closable !== void 0) {
|
|
1050
|
+
const existing = inst.el.querySelector(":scope > .ga-toast-close");
|
|
1051
|
+
if (options.closable && !existing) {
|
|
1052
|
+
inst.el.insertBefore(createCloseButton(), inst.progressEl || null);
|
|
1053
|
+
} else if (!options.closable && existing) {
|
|
1054
|
+
existing.remove();
|
|
1055
|
+
}
|
|
1056
|
+
opts.closable = options.closable;
|
|
1057
|
+
}
|
|
1058
|
+
if (options.duration !== void 0) {
|
|
1059
|
+
if (inst.timer.handle != null) clearTimeout(inst.timer.handle);
|
|
1060
|
+
inst.timer.duration = options.duration;
|
|
1061
|
+
inst.timer.remaining = options.duration;
|
|
1062
|
+
opts.duration = options.duration;
|
|
1063
|
+
if (options.duration > 0 && inst.el.dataset.gaMounted) startTimer(inst);
|
|
1366
1064
|
}
|
|
1367
|
-
|
|
1065
|
+
const parent = inst.el.parentElement;
|
|
1066
|
+
if (parent) layout(parent);
|
|
1067
|
+
log("toast:update", { id });
|
|
1068
|
+
return inst.handle;
|
|
1368
1069
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
inst.timer.duration = options.duration;
|
|
1372
|
-
inst.timer.remaining = options.duration;
|
|
1373
|
-
opts.duration = options.duration;
|
|
1374
|
-
if (options.duration > 0 && el(inst).dataset.gaMounted) startTimer(inst);
|
|
1070
|
+
function closeAll() {
|
|
1071
|
+
for (const id of Array.from(registry.keys())) close(id);
|
|
1375
1072
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
}
|
|
1381
|
-
function
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
}
|
|
1387
|
-
function
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1073
|
+
function clear(type) {
|
|
1074
|
+
if (!type) return closeAll();
|
|
1075
|
+
for (const inst of Array.from(registry.values()))
|
|
1076
|
+
if (inst.opts.type === type) close(inst.id);
|
|
1077
|
+
}
|
|
1078
|
+
function getCount(type) {
|
|
1079
|
+
if (!type) return registry.size;
|
|
1080
|
+
let n = 0;
|
|
1081
|
+
for (const inst of registry.values()) if (inst.opts.type === type) n += 1;
|
|
1082
|
+
return n;
|
|
1083
|
+
}
|
|
1084
|
+
function exists(id) {
|
|
1085
|
+
return registry.has(normalizeId(id));
|
|
1086
|
+
}
|
|
1087
|
+
function get(id) {
|
|
1088
|
+
return registry.get(normalizeId(id))?.el || null;
|
|
1089
|
+
}
|
|
1090
|
+
function typed(type) {
|
|
1091
|
+
return (message, options = {}) => show({ ...options, type, message, duration: options.duration ?? durations[type] });
|
|
1092
|
+
}
|
|
1093
|
+
const success = typed("success");
|
|
1094
|
+
const error = typed("error");
|
|
1095
|
+
const warning = typed("warning");
|
|
1096
|
+
const info = typed("info");
|
|
1097
|
+
function loading(message = "Loading\u2026", options = {}) {
|
|
1098
|
+
return show({
|
|
1099
|
+
closable: false,
|
|
1100
|
+
...options,
|
|
1101
|
+
type: "loading",
|
|
1102
|
+
message,
|
|
1103
|
+
duration: 0,
|
|
1104
|
+
progress: false
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
function confirm(message, options = {}) {
|
|
1108
|
+
const { confirmText, cancelText, onConfirm, onCancel, ...rest } = options;
|
|
1109
|
+
return show({
|
|
1110
|
+
type: "warning",
|
|
1111
|
+
duration: 0,
|
|
1112
|
+
closable: false,
|
|
1113
|
+
swipeToClose: false,
|
|
1114
|
+
role: "alertdialog",
|
|
1115
|
+
moveFocus: true,
|
|
1116
|
+
modal: true,
|
|
1117
|
+
position: "middle-center",
|
|
1118
|
+
...rest,
|
|
1119
|
+
message,
|
|
1120
|
+
actions: [
|
|
1121
|
+
{
|
|
1122
|
+
text: cancelText || "Cancel",
|
|
1123
|
+
className: "ga-toast-btn-secondary",
|
|
1124
|
+
onClick: () => onCancel?.()
|
|
1125
|
+
},
|
|
1126
|
+
{
|
|
1127
|
+
text: confirmText || "Confirm",
|
|
1128
|
+
className: "ga-toast-btn-primary",
|
|
1129
|
+
onClick: () => onConfirm?.()
|
|
1130
|
+
}
|
|
1131
|
+
]
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
function promise(input, messages, options = {}) {
|
|
1135
|
+
const p = typeof input === "function" ? input() : input;
|
|
1136
|
+
const handle = loading(messages.loading, options);
|
|
1137
|
+
return p.then(
|
|
1138
|
+
(value) => {
|
|
1139
|
+
handle.update({
|
|
1140
|
+
type: "success",
|
|
1141
|
+
message: typeof messages.success === "function" ? messages.success(value) : messages.success,
|
|
1142
|
+
duration: options.duration ?? durations.success,
|
|
1143
|
+
closable: true
|
|
1144
|
+
});
|
|
1145
|
+
return value;
|
|
1439
1146
|
},
|
|
1440
|
-
{
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1147
|
+
(err) => {
|
|
1148
|
+
handle.update({
|
|
1149
|
+
type: "error",
|
|
1150
|
+
message: typeof messages.error === "function" ? messages.error(err) : messages.error,
|
|
1151
|
+
duration: options.duration ?? durations.error,
|
|
1152
|
+
closable: true
|
|
1153
|
+
});
|
|
1154
|
+
throw err;
|
|
1444
1155
|
}
|
|
1445
|
-
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
(
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
function custom(content, options = {}) {
|
|
1159
|
+
return show({ ...options, content });
|
|
1160
|
+
}
|
|
1161
|
+
function setDefaults(defaults) {
|
|
1162
|
+
globalDefaults = { ...globalDefaults, ...defaults };
|
|
1163
|
+
}
|
|
1164
|
+
function setLogger(fn) {
|
|
1165
|
+
logger = typeof fn === "function" ? fn : null;
|
|
1166
|
+
}
|
|
1167
|
+
function setMaxVisible(count) {
|
|
1168
|
+
maxVisible = Math.max(1, Math.floor(count) || 1);
|
|
1169
|
+
containers.forEach((container) => layout(container));
|
|
1170
|
+
}
|
|
1171
|
+
function theme(tokens) {
|
|
1172
|
+
themeTokens = resolveTheme(tokens);
|
|
1173
|
+
applyTheme();
|
|
1174
|
+
containers.forEach((container) => layout(container));
|
|
1175
|
+
return api;
|
|
1176
|
+
}
|
|
1177
|
+
function configure(cfg) {
|
|
1178
|
+
if (cfg.defaults) setDefaults(cfg.defaults);
|
|
1179
|
+
if (cfg.logger !== void 0) logger = cfg.logger;
|
|
1180
|
+
applyConfigDurations(cfg.durations);
|
|
1181
|
+
applyConfigIcons(cfg.icons);
|
|
1182
|
+
applyConfigStack(cfg.stack);
|
|
1183
|
+
if (typeof cfg.maxVisible === "number")
|
|
1184
|
+
maxVisible = Math.max(1, Math.floor(cfg.maxVisible) || 1);
|
|
1185
|
+
if (cfg.injectStyles !== void 0) injectEnabled = cfg.injectStyles !== false;
|
|
1186
|
+
if (cfg.theme !== void 0) {
|
|
1187
|
+
themeTokens = resolveTheme(cfg.theme);
|
|
1188
|
+
applyTheme();
|
|
1189
|
+
}
|
|
1190
|
+
containers.forEach((container) => layout(container));
|
|
1191
|
+
return api;
|
|
1192
|
+
}
|
|
1193
|
+
const api = Object.assign(
|
|
1194
|
+
(message, options) => info(message, options),
|
|
1195
|
+
{
|
|
1196
|
+
show,
|
|
1197
|
+
success,
|
|
1198
|
+
error,
|
|
1199
|
+
warning,
|
|
1200
|
+
info,
|
|
1201
|
+
loading,
|
|
1202
|
+
confirm,
|
|
1203
|
+
promise,
|
|
1204
|
+
custom,
|
|
1205
|
+
close,
|
|
1206
|
+
closeAll,
|
|
1207
|
+
dismiss: close,
|
|
1208
|
+
dismissAll: closeAll,
|
|
1209
|
+
clear,
|
|
1210
|
+
update,
|
|
1211
|
+
get,
|
|
1212
|
+
exists,
|
|
1213
|
+
getCount,
|
|
1214
|
+
setDefaults,
|
|
1215
|
+
setMaxVisible,
|
|
1216
|
+
setLogger,
|
|
1217
|
+
configure,
|
|
1218
|
+
theme,
|
|
1219
|
+
injectStyles
|
|
1469
1220
|
}
|
|
1470
1221
|
);
|
|
1222
|
+
if (config.theme !== void 0) {
|
|
1223
|
+
themeTokens = resolveTheme(config.theme);
|
|
1224
|
+
applyTheme();
|
|
1225
|
+
}
|
|
1226
|
+
return api;
|
|
1471
1227
|
}
|
|
1472
|
-
function
|
|
1473
|
-
|
|
1474
|
-
}
|
|
1475
|
-
function setLogger(fn) {
|
|
1476
|
-
logger = typeof fn === "function" ? fn : null;
|
|
1477
|
-
}
|
|
1478
|
-
function custom(content, options = {}) {
|
|
1479
|
-
return show({ ...options, content });
|
|
1228
|
+
function createToaster(config = {}) {
|
|
1229
|
+
return makeToaster(config);
|
|
1480
1230
|
}
|
|
1481
|
-
var toast =
|
|
1482
|
-
(message, options) => info(message, options),
|
|
1483
|
-
{
|
|
1484
|
-
show,
|
|
1485
|
-
success,
|
|
1486
|
-
error,
|
|
1487
|
-
warning,
|
|
1488
|
-
info,
|
|
1489
|
-
loading,
|
|
1490
|
-
confirm,
|
|
1491
|
-
promise,
|
|
1492
|
-
custom,
|
|
1493
|
-
close,
|
|
1494
|
-
closeAll,
|
|
1495
|
-
clear,
|
|
1496
|
-
update,
|
|
1497
|
-
get,
|
|
1498
|
-
exists,
|
|
1499
|
-
getCount,
|
|
1500
|
-
setDefaults,
|
|
1501
|
-
setLogger,
|
|
1502
|
-
injectStyles
|
|
1503
|
-
}
|
|
1504
|
-
);
|
|
1231
|
+
var toast = makeToaster();
|
|
1505
1232
|
var GaToasts = toast;
|
|
1506
1233
|
var src_default = toast;
|
|
1507
1234
|
|
|
1508
|
-
export { GaToasts, src_default as default, toast };
|
|
1235
|
+
export { GaToasts, createToaster, src_default as default, toast };
|