@yusufceng1z/ding 0.0.0-stage → 0.0.1

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