@yusufceng1z/ding 0.0.0-stage → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,943 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ICONS: () => ICONS,
24
+ TIMING: () => TIMING,
25
+ bindToast: () => bindToast,
26
+ buildCss: () => buildCss,
27
+ chime: () => chime,
28
+ createToaster: () => createToaster,
29
+ getSprings: () => getSprings,
30
+ injectStyles: () => injectStyles,
31
+ mountToaster: () => mountToaster,
32
+ onToastKey: () => onToastKey,
33
+ setSprings: () => setSprings,
34
+ springEasing: () => springEasing,
35
+ toast: () => toast
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/sound.ts
40
+ var ctx;
41
+ var CUES = {
42
+ success: [[392, 0, 1], [523.3, 0.1, 1]],
43
+ error: [[233.1, 0, 1], [185, 0.13, 1]],
44
+ warning: [[349.2, 0, 0.8], [349.2, 0.16, 0.6]],
45
+ info: [[466.2, 0, 0.9]]
46
+ };
47
+ function tone(c, out, freq, at, level) {
48
+ const t = c.currentTime + at;
49
+ const f = freq * (1 + (Math.random() - 0.5) * 8e-3);
50
+ for (const [mult, gain, decay] of [[1, 0.6, 0.5], [2, 0.06, 0.15]]) {
51
+ const osc = c.createOscillator();
52
+ const g = c.createGain();
53
+ osc.frequency.value = f * mult;
54
+ g.gain.setValueAtTime(1e-4, t);
55
+ g.gain.linearRampToValueAtTime(gain * level, t + 0.015);
56
+ g.gain.exponentialRampToValueAtTime(1e-4, t + decay);
57
+ osc.connect(g).connect(out);
58
+ osc.start(t);
59
+ osc.stop(t + decay + 0.05);
60
+ }
61
+ }
62
+ function chime(type, volume = 0.5) {
63
+ const cue = CUES[type];
64
+ if (!cue || typeof AudioContext === "undefined") return;
65
+ try {
66
+ ctx ??= new AudioContext();
67
+ if (ctx.state === "suspended") void ctx.resume();
68
+ if (ctx.state === "closed") return;
69
+ const master = ctx.createGain();
70
+ master.gain.value = Math.min(1, Math.max(0, volume)) * 0.45;
71
+ const soften = ctx.createBiquadFilter();
72
+ soften.type = "lowpass";
73
+ soften.frequency.value = 1300;
74
+ const echo = ctx.createDelay();
75
+ echo.delayTime.value = 0.11;
76
+ const wet = ctx.createGain();
77
+ wet.gain.value = 0.1;
78
+ master.connect(soften);
79
+ soften.connect(ctx.destination);
80
+ soften.connect(echo).connect(wet).connect(ctx.destination);
81
+ for (const [f, at, level] of cue) tone(ctx, master, f, at, level);
82
+ } catch {
83
+ }
84
+ }
85
+
86
+ // src/store.ts
87
+ var TIMING = {
88
+ /** shape arrives, then the pill opens */
89
+ openDelay: 450,
90
+ /** text erase + shrink back to shape */
91
+ closing: 340,
92
+ /** shape leaves the screen */
93
+ exit: 220,
94
+ duration: 5e3
95
+ };
96
+ var autoDuration = (type, hasAction) => type === "loading" || type === "error" || hasAction ? 0 : TIMING.duration;
97
+ function createToaster() {
98
+ let state = { toasts: [], position: "top-center", theme: "system", status: "", alert: "" };
99
+ let flip = false;
100
+ const subs = /* @__PURE__ */ new Set();
101
+ const entries = /* @__PURE__ */ new Map();
102
+ let counter = 0;
103
+ let sound = false;
104
+ let volume = 0.5;
105
+ const live = /* @__PURE__ */ new Map();
106
+ const owner = /* @__PURE__ */ new Map();
107
+ const emit = () => subs.forEach((fn) => fn());
108
+ const setToasts = (toasts) => {
109
+ state = { ...state, toasts };
110
+ emit();
111
+ };
112
+ const announce = (type, title, description) => {
113
+ if (typeof sound === "function") sound(type);
114
+ else if (sound) chime(type, volume);
115
+ flip = !flip;
116
+ const text = (description ? `${title}. ${description}` : title) + (flip ? "\xA0" : "");
117
+ state = { ...state, [type === "error" ? "alert" : "status"]: text };
118
+ emit();
119
+ };
120
+ const find = (id) => state.toasts.find((t) => t.id === id);
121
+ const patch = (id, p) => setToasts(state.toasts.map((t) => t.id === id ? { ...t, ...p } : t));
122
+ function startLife(id) {
123
+ const e = entries.get(id);
124
+ if (!e) return;
125
+ clearTimeout(e.lifeTimer);
126
+ e.lifeTimer = void 0;
127
+ if (find(id)?.phase !== "open" || e.paused || e.remaining <= 0) return;
128
+ e.startedAt = Date.now();
129
+ e.lifeTimer = setTimeout(() => dismiss(id), e.remaining);
130
+ }
131
+ function show(type, title, opts = {}) {
132
+ if (opts.id === void 0 && !opts.action && !opts.secondary && !opts.image && !opts.meta) {
133
+ const dup = state.toasts.at(-1);
134
+ if (dup && dup.type === type && dup.title === title && dup.description === opts.description && (dup.phase === "enter" || dup.phase === "open")) {
135
+ bump(dup.id);
136
+ return dup.id;
137
+ }
138
+ }
139
+ const id = opts.id ?? `toast-${++counter}`;
140
+ const cur = state.toasts.filter((t) => t.phase === "enter" || t.phase === "open").at(-1);
141
+ if (cur) {
142
+ live.set(id, cur.id);
143
+ owner.set(cur.id, id);
144
+ patch(cur.id, { count: 1 });
145
+ apply(cur.id, {
146
+ type,
147
+ title,
148
+ description: opts.description ?? "",
149
+ action: opts.action ?? null,
150
+ secondary: opts.secondary ?? null,
151
+ meta: opts.meta ?? null,
152
+ image: opts.image ?? null,
153
+ progress: opts.progress ?? null,
154
+ ...opts.duration !== void 0 && { duration: opts.duration }
155
+ });
156
+ return id;
157
+ }
158
+ owner.set(id, id);
159
+ const first = opts.duration ?? autoDuration(type, !!(opts.action || opts.secondary));
160
+ const e = { startedAt: 0, remaining: first, base: first, paused: false };
161
+ entries.set(id, e);
162
+ setToasts([
163
+ ...state.toasts,
164
+ { id, type, title, description: opts.description, phase: "enter", duration: e.remaining, action: opts.action, secondary: opts.secondary, meta: opts.meta, image: opts.image, progress: opts.progress, count: 1 }
165
+ ]);
166
+ announce(type, title, opts.description);
167
+ e.phaseTimer = setTimeout(() => {
168
+ if (find(id)?.phase !== "enter") return;
169
+ patch(id, { phase: "open" });
170
+ startLife(id);
171
+ }, TIMING.openDelay);
172
+ return id;
173
+ }
174
+ function update(callerId, p) {
175
+ const id = live.get(callerId) ?? callerId;
176
+ if (owner.get(id) === callerId) apply(id, p);
177
+ }
178
+ function apply(id, p) {
179
+ const t = find(id);
180
+ const e = entries.get(id);
181
+ if (!t || !e) return;
182
+ patch(id, {
183
+ ...p.title !== void 0 && { title: p.title },
184
+ ...p.description !== void 0 && { description: p.description },
185
+ ...p.progress !== void 0 && { progress: p.progress ?? void 0 },
186
+ ...p.action !== void 0 && { action: p.action ?? void 0 },
187
+ ...p.secondary !== void 0 && { secondary: p.secondary ?? void 0 },
188
+ ...p.meta !== void 0 && { meta: p.meta ?? void 0 },
189
+ ...p.image !== void 0 && { image: p.image ?? void 0 },
190
+ ...p.type !== void 0 && { type: p.type }
191
+ });
192
+ if (p.duration !== void 0) e.remaining = p.duration;
193
+ else if (p.type !== void 0 || p.action !== void 0 || p.secondary !== void 0) {
194
+ const n = find(id);
195
+ e.remaining = autoDuration(n.type, !!(n.action || n.secondary));
196
+ }
197
+ if (p.duration !== void 0 || p.type !== void 0 || p.action !== void 0 || p.secondary !== void 0) e.base = e.remaining, patch(id, { duration: e.remaining });
198
+ startLife(id);
199
+ const quiet = p.progress !== void 0 && p.type === void 0;
200
+ if (!quiet && (p.title !== void 0 || p.description !== void 0 || p.type !== void 0)) {
201
+ announce(p.type ?? t.type, p.title ?? t.title, p.description ?? t.description);
202
+ }
203
+ }
204
+ function act(id, which = "action") {
205
+ const result = find(id)?.[which]?.onClick();
206
+ if (result && typeof result === "object") apply(id, { action: null, secondary: null, ...result });
207
+ else dismiss(id);
208
+ }
209
+ function bump(id) {
210
+ const e = entries.get(id);
211
+ const t = find(id);
212
+ if (!e || !t) return;
213
+ patch(id, { count: t.count + 1 });
214
+ e.remaining = e.base;
215
+ startLife(id);
216
+ }
217
+ function dismiss(id, opts = {}) {
218
+ if (id === void 0) return state.toasts.forEach((t2) => dismiss(t2.id, opts));
219
+ id = live.get(id) ?? id;
220
+ const t = find(id);
221
+ const e = entries.get(id);
222
+ if (!t || !e || t.phase === "exit" || t.phase === "closing" && !opts.immediate) return;
223
+ clearTimeout(e.phaseTimer);
224
+ clearTimeout(e.lifeTimer);
225
+ const leave = () => {
226
+ patch(id, { phase: "exit" });
227
+ e.phaseTimer = setTimeout(() => {
228
+ entries.delete(id);
229
+ owner.delete(id);
230
+ live.forEach((v, k) => v === id && live.delete(k));
231
+ setToasts(state.toasts.filter((x) => x.id !== id));
232
+ }, TIMING.exit);
233
+ };
234
+ if (opts.immediate) return leave();
235
+ patch(id, { phase: "closing" });
236
+ e.phaseTimer = setTimeout(leave, TIMING.closing);
237
+ }
238
+ function pause(id) {
239
+ if (id === void 0) return [...entries.keys()].forEach(pause);
240
+ const e = entries.get(id);
241
+ if (!e || e.paused) return;
242
+ e.paused = true;
243
+ if (e.lifeTimer) {
244
+ clearTimeout(e.lifeTimer);
245
+ e.lifeTimer = void 0;
246
+ e.remaining = Math.max(0, e.remaining - (Date.now() - e.startedAt));
247
+ }
248
+ }
249
+ function resume(id) {
250
+ if (id === void 0) return [...entries.keys()].forEach(resume);
251
+ const e = entries.get(id);
252
+ if (!e) return;
253
+ e.paused = false;
254
+ startLife(id);
255
+ }
256
+ function promise(p, m) {
257
+ const id = show("loading", m.loading);
258
+ const pr = typeof p === "function" ? p() : p;
259
+ pr.then(
260
+ (v) => update(id, { type: "success", title: typeof m.success === "function" ? m.success(v) : m.success }),
261
+ (err) => update(id, { type: "error", title: typeof m.error === "function" ? m.error(err) : m.error })
262
+ );
263
+ return pr;
264
+ }
265
+ return {
266
+ show,
267
+ success: (title, o) => show("success", title, o),
268
+ error: (title, o) => show("error", title, o),
269
+ warning: (title, o) => show("warning", title, o),
270
+ info: (title, o) => show("info", title, o),
271
+ loading: (title, o) => show("loading", title, o),
272
+ promise,
273
+ update,
274
+ act,
275
+ dismiss,
276
+ pause,
277
+ resume,
278
+ configure(c) {
279
+ if (c.sound !== void 0) sound = c.sound;
280
+ if (c.volume !== void 0) volume = c.volume;
281
+ state = { ...state, ...c.position && { position: c.position }, ...c.theme && { theme: c.theme } };
282
+ emit();
283
+ },
284
+ subscribe(fn) {
285
+ subs.add(fn);
286
+ return () => void subs.delete(fn);
287
+ },
288
+ getState: () => state
289
+ };
290
+ }
291
+ var toast = createToaster();
292
+
293
+ // src/spring.ts
294
+ function position(t, k, c, m) {
295
+ const w0 = Math.sqrt(k / m);
296
+ const z = c / (2 * Math.sqrt(k * m));
297
+ if (z < 1) {
298
+ const wd = w0 * Math.sqrt(1 - z * z);
299
+ return 1 - Math.exp(-z * w0 * t) * (Math.cos(wd * t) + z * w0 / wd * Math.sin(wd * t));
300
+ }
301
+ if (z === 1) return 1 - Math.exp(-w0 * t) * (1 + w0 * t);
302
+ const s = w0 * Math.sqrt(z * z - 1);
303
+ const r1 = -z * w0 + s;
304
+ const r2 = -z * w0 - s;
305
+ return 1 - (r2 * Math.exp(r1 * t) - r1 * Math.exp(r2 * t)) / (r2 - r1);
306
+ }
307
+ function springEasing(config = {}) {
308
+ const { stiffness = 170, damping = 18, mass = 1 } = config;
309
+ const f = (t) => position(t, stiffness, damping, mass);
310
+ const dt = 1 / 120;
311
+ const maxT = 5;
312
+ let settle = 0;
313
+ for (let t = 0; t <= maxT; t += dt) if (Math.abs(1 - f(t)) > 1e-3) settle = t;
314
+ settle = Math.max(settle + dt, 0.05);
315
+ const steps = Math.max(2, Math.ceil(settle * 60));
316
+ const pts = [];
317
+ for (let i = 0; i <= steps; i++) pts.push(String(+f(i / steps * settle).toFixed(4)));
318
+ pts[steps] = "1";
319
+ return { easing: `linear(${pts.join(",")})`, duration: Math.round(settle * 1e3) };
320
+ }
321
+
322
+ // src/styles.ts
323
+ var configs = {
324
+ enter: { stiffness: 320, damping: 26 },
325
+ // arrival: quick, lands with a hint of overshoot
326
+ morph: { stiffness: 340, damping: 27 },
327
+ // pill opening: liquid but controlled
328
+ stack: { stiffness: 400, damping: 36 }
329
+ // stack shuffle + fold/unfold: tight, no wobble
330
+ };
331
+ var cache;
332
+ var getSpringConfigs = () => configs;
333
+ function getSprings() {
334
+ return cache ??= { enter: springEasing(configs.enter), morph: springEasing(configs.morph), stack: springEasing(configs.stack) };
335
+ }
336
+ function setSprings(p) {
337
+ Object.assign(configs.enter, p.enter);
338
+ Object.assign(configs.morph, p.morph);
339
+ Object.assign(configs.stack, p.stack);
340
+ cache = void 0;
341
+ if (typeof document !== "undefined") {
342
+ const el2 = document.querySelector("style[data-toast]");
343
+ if (el2) el2.textContent = buildCss();
344
+ }
345
+ }
346
+ function buildCss() {
347
+ const { stack, enter } = getSprings();
348
+ return `
349
+ .tst-viewport{color-scheme:light dark;--tst-stack:${stack.easing};--tst-stack-dur:${stack.duration}ms;--tst-pop:${enter.easing};--tst-pop-dur:${enter.duration}ms;
350
+ --tst-bg:light-dark(#fff,#0c0c0d);--tst-fg:light-dark(#0f0f13,#fafafa);--tst-ring:light-dark(oklch(0 0 0/.08),oklch(1 0 0/.1));
351
+ --tst-shadow:0 0 0 1px var(--tst-ring),0 4px 12px -4px light-dark(oklch(0 0 0/.14),oklch(0 0 0/.45));
352
+ --tst-success:light-dark(#12a36b,#4ade80);--tst-error:light-dark(#e5484d,#f87171);--tst-warning:light-dark(#c77d00,#fbbf24);--tst-info:light-dark(#2f7de1,#60a5fa);
353
+ --tst-size:44px;--tst-radius:22px;--tst-gap:8px;--tst-pad:16px;--tst-stack-offset:10px;--tst-stack-scale:.05;
354
+ position:fixed;inset:0;z-index:2147483647;pointer-events:none;font:500 14px/1.3 ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;-webkit-font-smoothing:antialiased}
355
+ .tst-viewport[data-theme=light]{color-scheme:light}
356
+ .tst-viewport[data-theme=dark]{color-scheme:dark}
357
+ .tst-viewport:dir(rtl){--tst-flip:-1}
358
+ .tst-viewport:dir(rtl) .tst-progress::after{transform-origin:right}
359
+ .tst-viewport[data-position^=top]{--tst-dir:-1}
360
+ .tst-viewport[data-position^=bottom]{--tst-dir:1}
361
+ .tst-viewport{--tst-y0:calc(var(--tst-dir,-1)*(var(--tst-size) + var(--tst-pad) + 24px))}
362
+ .tst-viewport[data-position$=center]{--tst-ox:50%;--tx:-50%}
363
+ .tst-viewport[data-position$=left]{--tst-ox:0%;--tx:0px}
364
+ .tst-viewport[data-position$=right]{--tst-ox:100%;--tx:0px}
365
+ .tst-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
366
+ .tst-slot{position:absolute;pointer-events:auto;touch-action:none;user-select:none;cursor:grab;--tst-i:0;
367
+ --y:calc(var(--tst-dir)*-1*var(--tst-i)*var(--tst-stack-offset));--s:calc(1 - var(--tst-i)*var(--tst-stack-scale));
368
+ transform:translate(calc(var(--tx) + var(--dx,0px)),calc(var(--y) + var(--dy,0px))) scale(var(--s));
369
+ transform-origin:var(--tst-ox) var(--tst-oy);z-index:calc(100 - var(--tst-i));
370
+ transition-property:transform,opacity;transition-duration:var(--tst-stack-dur),.25s;transition-timing-function:var(--tst-stack),ease-out}
371
+ .tst-slot::after{content:'';position:absolute;z-index:-1;left:0;right:0;top:calc(var(--tst-gap)/-2);bottom:calc(var(--tst-gap)/-2)}
372
+ .tst-slot[data-dragging]{transition:none;cursor:grabbing}
373
+ .tst-slot[data-flung]{transition:transform .38s cubic-bezier(.2,.8,.3,1),opacity .25s ease-out;opacity:0;pointer-events:none}
374
+ .tst-viewport[data-position^=top] .tst-slot{top:calc(var(--tst-pad) + env(safe-area-inset-top,0px));--tst-oy:0%}
375
+ .tst-viewport[data-position^=bottom] .tst-slot{bottom:calc(var(--tst-pad) + env(safe-area-inset-bottom,0px));--tst-oy:100%}
376
+ .tst-viewport[data-position$=center] .tst-slot{left:50%}
377
+ .tst-viewport[data-position$=left] .tst-slot{left:var(--tst-pad)}
378
+ .tst-viewport[data-position$=right] .tst-slot{right:var(--tst-pad)}
379
+ /* --c: status color for the glyph \xB7 --fill/--on: status surface + its text (used by filled styles) */
380
+ .tst{--c:var(--tst-fg);--fill:var(--tst-bg);--on:var(--tst-fg);--tp:0;--ap:0;position:relative;box-sizing:border-box;width:var(--tst-size);height:var(--tst-size);border:1px solid transparent;
381
+ border-radius:var(--r,min(var(--tst-radius),calc(var(--tst-size)/2)));overflow:hidden;color:var(--on);background:var(--fill);box-shadow:var(--tst-shadow);
382
+ translate:0 var(--tst-y0);scale:var(--tst-enter-scale,.5);opacity:0;will-change:translate,scale}
383
+ .tst[data-settled]{will-change:auto}
384
+ .tst[data-settled] .tst-body{filter:none;transform:none}
385
+ .tst[data-phase=exit]{animation:tst-out .15s ease-out both}
386
+ .tst[data-type=success]{--c:var(--tst-success)}
387
+ .tst[data-type=error]{--c:var(--tst-error)}
388
+ .tst[data-type=warning]{--c:var(--tst-warning)}
389
+ .tst[data-type=info]{--c:var(--tst-info)}
390
+
391
+ .tst-icon{position:absolute;inset-inline-start:0;top:0;width:var(--tst-size);height:var(--tst-size);display:grid;place-items:center}
392
+ .tst-media{width:28px;height:28px;border-radius:50%;object-fit:cover;outline:1px solid light-dark(oklch(0 0 0/.1),oklch(1 0 0/.1));outline-offset:-1px;animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both}
393
+ .tst-badge{position:relative;width:24px;height:24px;display:grid;place-items:center}
394
+ .tst-svg{width:22px;height:22px;fill:none;stroke:var(--c);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:stroke .3s cubic-bezier(.2,0,0,1);animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both}
395
+ .tst-svg path{stroke-dasharray:1;stroke-dashoffset:1;animation:tst-draw .5s cubic-bezier(.4,0,.2,1) .15s forwards}
396
+ .tst-svg path:first-child{stroke-dasharray:1 1;transition:stroke-dasharray .65s cubic-bezier(.4,0,.2,1)}
397
+ .tst[data-type=loading] .tst-svg path:first-child{stroke-dasharray:.28 .72}
398
+ .tst{--md:.55s}
399
+ .tst[data-ready]{--md:.05s}
400
+ .tst-svg path{transform-box:fill-box;transform-origin:center}
401
+ .tst-svg path:nth-child(n+2){animation-duration:.32s;animation-delay:var(--md)}
402
+ .tst-svg path:nth-child(3){animation-delay:calc(var(--md) + .08s)}
403
+ /* each status has its own little gesture, built from the parts of its glyph */
404
+ .tst[data-type=success] .tst-svg{animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both,tst-pulse .45s var(--tst-pop) calc(var(--md) + .25s)}
405
+ .tst[data-type=success] .tst-badge::after{content:'';position:absolute;inset:1px;border-radius:50%;border:1.5px solid var(--c);opacity:0;animation:tst-ripple .7s cubic-bezier(.2,0,0,1) calc(var(--md) + .25s)}
406
+ .tst[data-type=error] .tst-svg{animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both,tst-shake .42s cubic-bezier(.3,0,.3,1) calc(var(--md) + .3s)}
407
+ .tst[data-type=warning] .tst-svg path:nth-child(2){stroke-dasharray:none;stroke-dashoffset:0;animation:tst-drop .5s var(--tst-pop) var(--md) both}
408
+ .tst[data-type=warning] .tst-svg path:nth-child(3){stroke-dasharray:none;stroke-dashoffset:0;animation:tst-dot .38s var(--tst-pop) calc(var(--md) + .16s) both}
409
+ .tst[data-type=info] .tst-svg path:nth-child(3){stroke-dasharray:none;stroke-dashoffset:0;animation:tst-dot .4s var(--tst-pop) var(--md) both}
410
+ .tst[data-type=info] .tst-svg path:nth-child(2){animation-delay:calc(var(--md) + .16s)}
411
+
412
+ .tst-body{position:absolute;inset-inline-start:calc(var(--tst-size) - 1px);top:-1px;display:flex;flex-wrap:wrap;align-items:center;gap:0 8px;width:max-content;max-width:calc(100vw - 2*var(--tst-pad) - var(--tst-size) + 1px);min-height:var(--tst-size);padding-inline-end:18px;
413
+ opacity:calc(var(--tp)*1.5 - .25);filter:blur(calc((1 - var(--tp))*10px));transform:translateX(calc((1 - var(--tp))*-12px*var(--tst-flip,1)))}
414
+ .tst-body:has(.tst-action,.tst-close){padding-inline-end:8px;padding-bottom:0}
415
+ .tst-body[data-wrapped]{padding-bottom:10px}
416
+ .tst-body[data-wrapped] .tst-copy{flex-basis:100%;max-width:none}
417
+ .tst-body[data-wrapped] .tst-copy + *{margin-inline-start:auto}
418
+ .tst-copy{width:max-content;max-width:min(340px,calc(100vw - 176px));padding-block:12px;padding-inline:0 6px;line-height:1.4;text-wrap:pretty;overflow-wrap:anywhere}
419
+ .tst-title{font-weight:550;font-variant-numeric:tabular-nums}
420
+ .tst-count,.tst-meta{margin-inline-start:6px;opacity:.7}
421
+ .tst-meta{font-weight:450;font-size:12px}
422
+ .tst-timer{position:absolute;inset:auto 0 0 0;height:2px;background:var(--c);opacity:.45;transform-origin:left;animation:tst-timer var(--tst-life) linear forwards;pointer-events:none}
423
+ .tst-viewport:hover .tst-timer,.tst-viewport:has(:focus-visible) .tst-timer{animation-play-state:paused}
424
+ .tst-viewport:dir(rtl) .tst-timer{transform-origin:right}
425
+ .tst-ghost{position:absolute;inset-inline-start:0;top:0;pointer-events:none}
426
+ .tst-progress{position:absolute;inset:auto 0 0 0;height:3px;background:color-mix(in srgb,var(--tst-fg) 14%,transparent);opacity:var(--tp);pointer-events:none}
427
+ .tst-progress::after{content:'';position:absolute;inset:0;background:var(--c);transform-origin:left;transform:scaleX(var(--pg,0));transition:transform .3s cubic-bezier(.2,0,0,1)}
428
+ .tst-desc{margin-top:3px;font-size:13px;font-weight:450;opacity:.65}
429
+ .tst[data-phase=open] .tst-desc{animation:tst-in-up var(--tst-pop-dur) var(--tst-pop) .1s both}
430
+ .tst[data-phase=open] .tst-action,.tst[data-phase=open] .tst-close{animation:tst-in-btn var(--tst-pop-dur) var(--tst-pop) .16s backwards}
431
+ .tst[data-phase=open] .tst-secondary{animation-delay:.1s}
432
+ .tst-action,.tst-close{flex:none;border:0;color:inherit;font:inherit;cursor:pointer;background:transparent;
433
+ opacity:calc(var(--ap)*1.3 - .15);transform:scale(calc(.85 + var(--ap)*.15));
434
+ transition-property:background-color,scale;transition-duration:.15s;transition-timing-function:ease-out}
435
+ .tst-action{height:30px;padding:0 14px;border-radius:999px;font-size:13px;font-weight:600;background:var(--tst-fg);color:var(--tst-bg)}
436
+ .tst-secondary{background:transparent;color:color-mix(in srgb,var(--tst-fg) 65%,transparent);padding:0 10px}
437
+ .tst-close{width:30px;height:30px;padding:0;border-radius:50%;display:grid;place-items:center}
438
+ .tst-close svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round}
439
+ @media (hover:hover){.tst-action:hover{background:color-mix(in srgb,var(--tst-fg) 82%,var(--tst-bg))}.tst-secondary:hover,.tst-close:hover{background:color-mix(in srgb,var(--tst-fg) 10%,transparent);color:var(--tst-fg)}}
440
+ .tst-action:not(:disabled):active,.tst-close:not(:disabled):active{scale:.96}
441
+ .tst-action:focus-visible,.tst-close:focus-visible{outline:2px solid var(--tst-fg);outline-offset:2px}
442
+
443
+ @keyframes tst-out{to{transform:translateY(calc(var(--tst-dir)*12px)) scale(.92);opacity:0;filter:blur(4px)}}
444
+ @keyframes tst-swap{from{opacity:0;scale:.25;filter:blur(4px)}}
445
+ @keyframes tst-timer{to{transform:scaleX(0)}}
446
+ @keyframes tst-in-btn{from{opacity:0;translate:0 8px;filter:blur(4px)}}
447
+ @keyframes tst-in-up{from{opacity:0;transform:translateY(12px);filter:blur(4px)}}
448
+ @keyframes tst-draw{to{stroke-dashoffset:0}}
449
+ @keyframes tst-pulse{40%{transform:scale(1.14)}}
450
+ @keyframes tst-ripple{from{opacity:.55;transform:scale(1)}to{opacity:0;transform:scale(1.9)}}
451
+ @keyframes tst-shake{20%{translate:-2.5px 0}45%{translate:2.5px 0}70%{translate:-1.5px 0}to{translate:0}}
452
+ @keyframes tst-drop{from{opacity:0;translate:0 -5px}}
453
+ @keyframes tst-dot{from{opacity:0;scale:0}}
454
+ @keyframes tst-fade{from{opacity:0}}
455
+ @keyframes tst-fade-out{to{opacity:0}}
456
+ @media (prefers-reduced-motion:reduce){
457
+ .tst{translate:none!important;scale:none!important;animation:tst-fade .2s ease-out both}
458
+ .tst[data-phase=exit],.tst-body{filter:none!important;transform:none!important}
459
+ .tst-svg,.tst-desc,.tst-media,.tst-action,.tst-close,.tst-badge::after{animation:none!important}
460
+ .tst-timer{display:none}
461
+ .tst-svg path{animation:none!important;stroke-dashoffset:0!important}
462
+ .tst-slot{transition-property:opacity}
463
+ }
464
+ `;
465
+ }
466
+ function injectStyles(doc = document) {
467
+ if (doc.querySelector("style[data-toast]")) return;
468
+ const el2 = doc.createElement("style");
469
+ el2.setAttribute("data-toast", "");
470
+ el2.textContent = buildCss();
471
+ doc.head.prepend(el2);
472
+ }
473
+
474
+ // src/motion.ts
475
+ var Spring = class {
476
+ constructor(x, cfg) {
477
+ this.x = x;
478
+ this.to = x;
479
+ this.cfg = { stiffness: 170, damping: 18, mass: 1, ...cfg };
480
+ }
481
+ x;
482
+ v = 0;
483
+ to;
484
+ cfg;
485
+ tune(c) {
486
+ Object.assign(this.cfg, c);
487
+ }
488
+ /** Advance dt seconds. Returns true while still moving. */
489
+ step(dt) {
490
+ const { stiffness: k, damping: c, mass: m } = this.cfg;
491
+ const h = 1 / 240;
492
+ for (let t = 0; t < dt; t += h) {
493
+ this.v += (-k * (this.x - this.to) - c * this.v) / m * h;
494
+ this.x += this.v * h;
495
+ }
496
+ if (Math.abs(this.v) < 0.05 && Math.abs(this.x - this.to) < 0.05) {
497
+ this.x = this.to;
498
+ this.v = 0;
499
+ return false;
500
+ }
501
+ return true;
502
+ }
503
+ };
504
+ var tasks = /* @__PURE__ */ new Set();
505
+ var raf = 0;
506
+ var last = 0;
507
+ function tick(now) {
508
+ const dt = Math.min(0.1, (now - last) / 1e3);
509
+ last = now;
510
+ for (const t of tasks) if (!t(dt)) tasks.delete(t);
511
+ raf = tasks.size ? requestAnimationFrame(tick) : 0;
512
+ }
513
+ function run(task) {
514
+ tasks.add(task);
515
+ if (!raf) {
516
+ last = performance.now();
517
+ raf = requestAnimationFrame(tick);
518
+ }
519
+ }
520
+
521
+ // src/bind.ts
522
+ var reduced = () => typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
523
+ var clamp = (v, a = 0, b = 1) => Math.min(b, Math.max(a, v));
524
+ function watchMotion(slot, id, t) {
525
+ const pill = slot.firstElementChild;
526
+ if (!(pill instanceof HTMLElement)) return () => {
527
+ };
528
+ const body = pill.querySelector(".tst-body");
529
+ const cs = getComputedStyle(pill);
530
+ const SIZE = parseFloat(cs.getPropertyValue("--tst-size")) || 44;
531
+ const dir = Number(cs.getPropertyValue("--tst-dir")) || -1;
532
+ const Y0 = dir * (SIZE + (parseFloat(cs.getPropertyValue("--tst-pad")) || 16) + 24);
533
+ const maxR = parseFloat(cs.getPropertyValue("--tst-radius")) || 24;
534
+ const num = (name, d) => {
535
+ const v = parseFloat(cs.getPropertyValue(name));
536
+ return Number.isNaN(v) ? d : v;
537
+ };
538
+ const s0 = num("--tst-enter-scale", 0.5);
539
+ const stretchOn = num("--tst-stretch", 1);
540
+ const cfg = getSpringConfigs();
541
+ const w = new Spring(SIZE, cfg.morph);
542
+ const h = new Spring(SIZE, cfg.morph);
543
+ const y = new Spring(Y0, cfg.enter);
544
+ y.to = 0;
545
+ const x = new Spring(0, { stiffness: 520, damping: 13 });
546
+ let phase = t.getState().toasts.find((x2) => x2.id === id)?.phase ?? "enter";
547
+ let copyEnd = SIZE, actionW = 0, fullW = SIZE, fullH = SIZE;
548
+ const apply = () => {
549
+ const tp = clamp((w.x - SIZE) / Math.max(1, copyEnd - SIZE));
550
+ const ap = actionW > 2 ? clamp((w.x - copyEnd) / actionW) : clamp((tp - 0.45) / 0.55);
551
+ const e = (y.x - Y0) / -Y0;
552
+ const stretch = clamp(Math.abs(y.v) / 6e3, 0, 0.18) * stretchOn;
553
+ const squash = clamp(Math.abs(w.v) / 2e4, 0, 0.05);
554
+ const k = s0 + (1 - s0) * e;
555
+ pill.style.width = `${w.x}px`;
556
+ pill.style.height = `${h.x}px`;
557
+ pill.style.setProperty("--r", `${Math.min(h.x / 2, maxR)}px`);
558
+ pill.style.translate = `${x.x}px ${y.x}px`;
559
+ pill.style.scale = `${k * (1 - stretch * 0.7) * (1 + squash * 0.5)} ${k * (1 + stretch) * (1 - squash)}`;
560
+ pill.style.opacity = String(clamp(e * 2));
561
+ pill.style.setProperty("--tp", tp.toFixed(3));
562
+ pill.style.setProperty("--ap", ap.toFixed(3));
563
+ pill.toggleAttribute("data-settled", tp >= 1);
564
+ };
565
+ const task = (dt) => {
566
+ const moving = [w.step(dt), h.step(dt), y.step(dt), x.step(dt)].some(Boolean);
567
+ apply();
568
+ if (!moving && phase !== "exit") {
569
+ pill.style.translate = "none";
570
+ pill.style.scale = "none";
571
+ }
572
+ return moving;
573
+ };
574
+ const kick = () => {
575
+ if (reduced()) {
576
+ [w, h, y, x].forEach((s) => (s.x = s.to, s.v = 0));
577
+ apply();
578
+ } else run(task);
579
+ };
580
+ const aim = () => {
581
+ const open = phase === "open";
582
+ w.to = open ? fullW : SIZE;
583
+ h.to = open ? fullH : SIZE;
584
+ };
585
+ const measure = () => {
586
+ if (!body) return;
587
+ const copy2 = body.querySelector(".tst-copy");
588
+ const action = body.querySelector(".tst-action, .tst-close");
589
+ const wrapped = !!copy2 && [...body.querySelectorAll(".tst-action, .tst-close")].some((b) => b.offsetTop >= copy2.offsetTop + copy2.offsetHeight);
590
+ body.toggleAttribute("data-wrapped", wrapped);
591
+ fullW = Math.ceil((SIZE + body.offsetWidth) / 2) * 2;
592
+ fullH = Math.max(SIZE, body.offsetHeight);
593
+ const stacked = !!action && !!copy2 && action.offsetTop >= copy2.offsetTop + copy2.offsetHeight;
594
+ copyEnd = action && copy2 && !stacked ? SIZE + copy2.offsetWidth + 6 : fullW;
595
+ actionW = fullW - copyEnd;
596
+ if (phase === "open") aim(), kick();
597
+ };
598
+ const ro = new ResizeObserver(measure);
599
+ if (body) ro.observe(body);
600
+ measure();
601
+ if (phase === "open") [w.x, h.x] = [fullW, fullH];
602
+ kick();
603
+ const react = (type) => {
604
+ if (reduced()) return;
605
+ if (type === "error") x.v = 380;
606
+ else if (type === "warning") y.v = -dir * 200;
607
+ else return;
608
+ kick();
609
+ };
610
+ let lastType = t.getState().toasts.find((e) => e.id === id)?.type;
611
+ let count = t.getState().toasts.find((x2) => x2.id === id)?.count ?? 1;
612
+ const unsub = t.subscribe(() => {
613
+ const it = t.getState().toasts.find((x2) => x2.id === id);
614
+ if (!it) return;
615
+ if (it.count > count && phase === "open") {
616
+ y.v = -dir * 240;
617
+ kick();
618
+ }
619
+ count = it.count;
620
+ if (it.type !== lastType) {
621
+ lastType = it.type;
622
+ if (phase === "open") react(it.type);
623
+ }
624
+ if (it.phase === phase) return;
625
+ phase = it.phase;
626
+ if (phase === "closing") {
627
+ w.tune({ stiffness: 380, damping: 36 });
628
+ h.tune({ stiffness: 380, damping: 36 });
629
+ w.v = 320;
630
+ } else {
631
+ w.tune(cfg.morph);
632
+ h.tune(cfg.morph);
633
+ if (phase === "open") {
634
+ w.v = -260;
635
+ setTimeout(() => lastType && react(lastType), 200);
636
+ }
637
+ }
638
+ if (phase !== "exit") aim(), kick();
639
+ });
640
+ const copy = body?.querySelector(".tst-copy");
641
+ let snap = copy ? { html: copy.innerHTML, w: copy.offsetWidth } : void 0;
642
+ let ghost;
643
+ let lastRoll = 0;
644
+ const mo = new MutationObserver(() => {
645
+ if (!copy || !body) return;
646
+ const prev = snap;
647
+ snap = { html: copy.innerHTML, w: copy.offsetWidth };
648
+ if (!prev || prev.html === snap.html || phase !== "open" || reduced()) return;
649
+ if (performance.now() - lastRoll < 450) return;
650
+ lastRoll = performance.now();
651
+ ghost?.remove();
652
+ ghost = document.createElement("div");
653
+ ghost.className = "tst-copy tst-ghost";
654
+ ghost.setAttribute("aria-hidden", "true");
655
+ ghost.style.width = `${prev.w}px`;
656
+ ghost.innerHTML = prev.html;
657
+ body.append(ghost);
658
+ const g = ghost;
659
+ const easing = "cubic-bezier(.2,.8,.2,1)";
660
+ g.animate(
661
+ [{ opacity: 1, transform: "none", filter: "blur(0)" }, { opacity: 0, transform: "translateY(-12px)", filter: "blur(4px)" }],
662
+ { duration: 280, easing, fill: "forwards" }
663
+ ).onfinish = () => g.remove();
664
+ copy.animate(
665
+ [{ opacity: 0, transform: "translateY(12px)", filter: "blur(4px)" }, { opacity: 1, transform: "none", filter: "blur(0)" }],
666
+ { duration: 380, easing }
667
+ );
668
+ });
669
+ if (copy) mo.observe(copy, { childList: true, characterData: true, subtree: true });
670
+ const getSvg = () => pill.querySelector(".tst-svg");
671
+ let spin;
672
+ let spinOn = null;
673
+ const startSpin = () => {
674
+ spin?.cancel();
675
+ spin = void 0;
676
+ spinOn = getSvg();
677
+ if (spinOn && !reduced()) spin = spinOn.animate([{ rotate: "0deg" }, { rotate: "360deg" }], { duration: 800, iterations: Infinity });
678
+ };
679
+ let curType = pill.dataset.type;
680
+ if (curType === "loading") startSpin();
681
+ const ready = setTimeout(() => pill.setAttribute("data-ready", ""), 900);
682
+ const tmo = new MutationObserver(() => {
683
+ const next = pill.dataset.type;
684
+ if (next === curType) return;
685
+ const was = curType;
686
+ curType = next;
687
+ if (next === "loading") return startSpin();
688
+ const now = getSvg();
689
+ if (now && was !== "loading" && !reduced()) {
690
+ const { easing, duration } = getSprings().stack;
691
+ now.animate([{ scale: 0.6, opacity: 0.3 }, { scale: 1, opacity: 1 }], { duration, easing });
692
+ }
693
+ const svg2 = spinOn;
694
+ if (was === "loading" && spin && svg2?.isConnected) {
695
+ const deg = Number(spin.currentTime) % 800 / 800 * 360;
696
+ spin.cancel();
697
+ spin = void 0;
698
+ svg2.animate([{ rotate: `${deg}deg` }, { rotate: "360deg" }], { duration: 650, easing: "cubic-bezier(.2,.7,.2,1)" });
699
+ }
700
+ });
701
+ const imo = new MutationObserver(() => {
702
+ if (curType === "loading" && (!spinOn?.isConnected || spinOn !== getSvg())) startSpin();
703
+ });
704
+ imo.observe(pill, { childList: true, subtree: true });
705
+ tmo.observe(pill, { attributes: true, attributeFilter: ["data-type"] });
706
+ return () => {
707
+ clearTimeout(ready);
708
+ imo.disconnect();
709
+ tmo.disconnect();
710
+ spin?.cancel();
711
+ ro.disconnect();
712
+ mo.disconnect();
713
+ unsub();
714
+ ghost?.remove();
715
+ };
716
+ }
717
+ function watchDrag(slot, id, t) {
718
+ let sx = 0, sy = 0, t0 = 0, active = false;
719
+ const edge = () => slot.closest(".tst-viewport")?.dataset.position?.startsWith("top") ? -1 : 1;
720
+ const down = (e) => {
721
+ if (e.button !== 0 || e.target.closest("button")) return;
722
+ [sx, sy, t0, active] = [e.clientX, e.clientY, e.timeStamp, true];
723
+ slot.setPointerCapture(e.pointerId);
724
+ slot.setAttribute("data-dragging", "");
725
+ };
726
+ const move = (e) => {
727
+ if (!active) return;
728
+ const dx = e.clientX - sx;
729
+ let dy = e.clientY - sy;
730
+ if (dy * edge() < 0) dy *= 0.2;
731
+ slot.style.setProperty("--dx", `${dx}px`);
732
+ slot.style.setProperty("--dy", `${dy}px`);
733
+ };
734
+ const up = (e) => {
735
+ if (!active) return;
736
+ active = false;
737
+ const dx = e.clientX - sx;
738
+ const rawDy = e.clientY - sy;
739
+ const dy = rawDy * edge();
740
+ const speed = Math.hypot(dx, dy) / Math.max(1, e.timeStamp - t0);
741
+ const away = dy > 40 || Math.abs(dx) > 80 || speed > 0.5 && (dy > 15 || Math.abs(dx) > 15);
742
+ slot.removeAttribute("data-dragging");
743
+ if (away) {
744
+ const len = Math.hypot(dx, rawDy) || 1;
745
+ const reach = Math.max(160, speed * 320);
746
+ slot.setAttribute("data-flung", "");
747
+ slot.style.setProperty("--dx", `${dx / len * reach}px`);
748
+ slot.style.setProperty("--dy", `${rawDy / len * reach}px`);
749
+ t.dismiss(id, { immediate: true });
750
+ } else slot.style.removeProperty("--dx"), slot.style.removeProperty("--dy");
751
+ };
752
+ slot.addEventListener("pointerdown", down);
753
+ slot.addEventListener("pointermove", move);
754
+ slot.addEventListener("pointerup", up);
755
+ slot.addEventListener("pointercancel", up);
756
+ return () => {
757
+ slot.removeEventListener("pointerdown", down);
758
+ slot.removeEventListener("pointermove", move);
759
+ slot.removeEventListener("pointerup", up);
760
+ slot.removeEventListener("pointercancel", up);
761
+ };
762
+ }
763
+ function bindToast(slot, id, t = toast) {
764
+ const stopDrag = watchDrag(slot, id, t);
765
+ const stopMotion = watchMotion(slot, id, t);
766
+ return () => (stopDrag(), stopMotion());
767
+ }
768
+
769
+ // src/icons.ts
770
+ var RING = "M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18";
771
+ var ICONS = {
772
+ success: [RING, "M7.9 12.4l3 3 5.3-6"],
773
+ error: [RING, "M9.3 9.3l5.4 5.4", "M14.7 9.3l-5.4 5.4"],
774
+ warning: [RING, "M12 7.6v5.2", "M12 16.3h.01"],
775
+ info: [RING, "M12 11v5.2", "M12 7.8h.01"],
776
+ loading: [RING]
777
+ };
778
+
779
+ // src/vanilla.ts
780
+ function onToastKey(e) {
781
+ if (e.defaultPrevented || !toast.getState().toasts.length) return;
782
+ if (e.key === "Escape") toast.dismiss();
783
+ else if (e.altKey && e.code === "KeyT") document.querySelector('.tst-viewport button:not([tabindex="-1"])')?.focus();
784
+ }
785
+ var el = (tag, cls, parent) => {
786
+ const n = document.createElement(tag);
787
+ n.className = cls;
788
+ parent?.append(n);
789
+ return n;
790
+ };
791
+ var svg = (cls, paths) => {
792
+ const s = document.createElementNS("http://www.w3.org/2000/svg", "svg");
793
+ s.setAttribute("viewBox", "0 0 24 24");
794
+ s.setAttribute("aria-hidden", "true");
795
+ s.setAttribute("class", cls);
796
+ for (const d of paths) {
797
+ const p = document.createElementNS("http://www.w3.org/2000/svg", "path");
798
+ p.setAttribute("d", d);
799
+ p.setAttribute("pathLength", "1");
800
+ s.append(p);
801
+ }
802
+ return s;
803
+ };
804
+ function mountToaster(opts = {}) {
805
+ if (typeof document === "undefined") return () => {
806
+ };
807
+ injectStyles();
808
+ toast.configure(opts);
809
+ const vp = el("div", "tst-viewport", document.body);
810
+ vp.setAttribute("role", "region");
811
+ vp.setAttribute("aria-label", "Notifications");
812
+ const status = el("div", "tst-sr", vp);
813
+ status.setAttribute("role", "status");
814
+ const alert = el("div", "tst-sr", vp);
815
+ alert.setAttribute("role", "alert");
816
+ vp.onpointerenter = () => toast.pause();
817
+ vp.onpointerleave = () => toast.resume();
818
+ vp.addEventListener("focusin", (e) => e.target.matches(":focus-visible") && toast.pause());
819
+ vp.addEventListener("focusout", () => toast.resume());
820
+ document.addEventListener("keydown", onToastKey);
821
+ const nodes = /* @__PURE__ */ new Map();
822
+ function build(t) {
823
+ const slot = el("div", "tst-slot", vp);
824
+ el("div", "tst", slot);
825
+ return { slot };
826
+ }
827
+ function render() {
828
+ const s = toast.getState();
829
+ vp.dataset.position = s.position;
830
+ vp.dataset.theme = s.theme;
831
+ status.textContent = s.status;
832
+ alert.textContent = s.alert;
833
+ const live = new Set(s.toasts.map((t) => t.id));
834
+ for (const [id, n] of nodes) if (!live.has(id)) n.off?.(), n.slot.remove(), nodes.delete(id);
835
+ s.toasts.forEach((t, idx) => {
836
+ let n = nodes.get(t.id);
837
+ if (!n) nodes.set(t.id, n = build(t));
838
+ const i = s.toasts.length - 1 - idx;
839
+ n.slot.style.setProperty("--tst-i", String(i));
840
+ const card = n.slot.firstElementChild;
841
+ card.dataset.phase = t.phase;
842
+ card.dataset.type = t.type;
843
+ card.style.setProperty("--tst-life", `${t.duration}ms`);
844
+ const iconKey = t.image ?? t.type;
845
+ if (n.type !== iconKey) {
846
+ card.querySelector(".tst-icon")?.remove();
847
+ const icon = el("div", "tst-icon");
848
+ if (t.image) Object.assign(el("img", "tst-media", icon), { src: t.image, alt: "" });
849
+ else el("div", "tst-badge", icon).append(svg("tst-svg", ICONS[t.type]));
850
+ card.prepend(icon);
851
+ n.type = iconKey;
852
+ }
853
+ const timed = (t.action || t.secondary) && t.duration > 0;
854
+ const timer = card.querySelector(".tst-timer");
855
+ if (!timed || timer?.dataset.k !== String(t.duration)) {
856
+ timer?.remove();
857
+ if (timed) el("div", "tst-timer", card).dataset.k = String(t.duration);
858
+ }
859
+ let bar = card.querySelector(".tst-progress");
860
+ if (t.progress === void 0) bar?.remove();
861
+ else (bar ??= card.insertBefore(el("div", "tst-progress"), card.firstChild)).style.setProperty("--pg", String(t.progress));
862
+ let body = card.querySelector(".tst-body");
863
+ if (!body) {
864
+ body = el("div", "tst-body", card);
865
+ const copy2 = el("div", "tst-copy", body);
866
+ el("div", "tst-title", copy2);
867
+ }
868
+ const copy = body.querySelector(".tst-copy");
869
+ const title = copy.querySelector(".tst-title");
870
+ const label = `${t.title}|${t.count}|${t.meta ?? ""}`;
871
+ if (title.dataset.k !== label) {
872
+ title.textContent = t.title;
873
+ if (t.count > 1) el("span", "tst-count", title).textContent = `\xD7${t.count}`;
874
+ if (t.meta) el("span", "tst-meta", title).textContent = t.meta;
875
+ title.dataset.k = label;
876
+ }
877
+ let desc = copy.querySelector(".tst-desc");
878
+ if (!t.description) desc?.remove();
879
+ else (desc ??= el("div", "tst-desc", copy)).textContent = t.description;
880
+ let sec = body.querySelector(".tst-secondary");
881
+ if (!t.secondary) sec?.remove();
882
+ else {
883
+ if (!sec) {
884
+ sec = el("button", "tst-action tst-secondary");
885
+ sec.type = "button";
886
+ sec.onclick = () => toast.act(t.id, "secondary");
887
+ body.insertBefore(sec, body.querySelector(".tst-action"));
888
+ }
889
+ sec.textContent = t.secondary.label;
890
+ sec.tabIndex = t.phase === "open" ? 0 : -1;
891
+ }
892
+ let act = body.querySelector(".tst-action:not(.tst-secondary)");
893
+ if (!t.action) act?.remove();
894
+ else {
895
+ if (!act) {
896
+ act = el("button", "tst-action", body);
897
+ act.type = "button";
898
+ act.onclick = () => toast.act(t.id);
899
+ }
900
+ act.textContent = t.action.label;
901
+ act.tabIndex = t.phase === "open" ? 0 : -1;
902
+ }
903
+ const sticky = t.duration === 0 && t.type !== "loading" && !t.secondary;
904
+ let close = body.querySelector(".tst-close");
905
+ if (!sticky) close?.remove();
906
+ else {
907
+ if (!close) {
908
+ close = el("button", "tst-close", body);
909
+ close.type = "button";
910
+ close.setAttribute("aria-label", "Dismiss notification");
911
+ close.append(svg("", ["M6 6l12 12M18 6L6 18"]));
912
+ close.onclick = () => toast.dismiss(t.id);
913
+ }
914
+ close.tabIndex = t.phase === "open" ? 0 : -1;
915
+ }
916
+ n.off ??= bindToast(n.slot, t.id);
917
+ });
918
+ }
919
+ const off = toast.subscribe(render);
920
+ render();
921
+ return () => {
922
+ off();
923
+ document.removeEventListener("keydown", onToastKey);
924
+ nodes.forEach((n) => n.off?.());
925
+ vp.remove();
926
+ };
927
+ }
928
+ // Annotate the CommonJS export names for ESM import in node:
929
+ 0 && (module.exports = {
930
+ ICONS,
931
+ TIMING,
932
+ bindToast,
933
+ buildCss,
934
+ chime,
935
+ createToaster,
936
+ getSprings,
937
+ injectStyles,
938
+ mountToaster,
939
+ onToastKey,
940
+ setSprings,
941
+ springEasing,
942
+ toast
943
+ });