@cookified/toastify 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,779 @@
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
+ DefaultToastIcon: () => DefaultToastIcon,
24
+ FadeAnimation: () => FadeAnimation,
25
+ FolderStackAnimation: () => FolderStackAnimation,
26
+ SlideAnimation: () => SlideAnimation,
27
+ Toast: () => Toast,
28
+ ToastAnimation: () => ToastAnimation,
29
+ ToastContainer: () => ToastContainer,
30
+ Toaster: () => Toaster,
31
+ defaultSpring: () => defaultSpring,
32
+ toast: () => toast,
33
+ toastStore: () => toastStore
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/toastify/Toaster.tsx
38
+ var import_react4 = require("motion/react");
39
+ var import_react5 = require("react");
40
+
41
+ // src/toastify/Toast.tsx
42
+ var import_lucide_react = require("lucide-react");
43
+ var import_jsx_runtime = require("react/jsx-runtime");
44
+ function DefaultToastIcon({ type }) {
45
+ const badgeClasses = "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-neutral-900 text-white shadow-xs dark:bg-white dark:text-neutral-950";
46
+ switch (type) {
47
+ case "loading":
48
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: badgeClasses, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2, { size: 12, strokeWidth: 2.5, className: "animate-spin" }) });
49
+ case "success":
50
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: badgeClasses, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Check, { size: 12, strokeWidth: 2.5 }) });
51
+ case "error":
52
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: badgeClasses, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { size: 12, strokeWidth: 2.5 }) });
53
+ case "warning":
54
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: badgeClasses, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
55
+ "svg",
56
+ {
57
+ width: "12",
58
+ height: "12",
59
+ viewBox: "0 0 24 24",
60
+ fill: "none",
61
+ stroke: "currentColor",
62
+ strokeWidth: 2.5,
63
+ strokeLinecap: "round",
64
+ strokeLinejoin: "round",
65
+ "aria-hidden": "true",
66
+ children: [
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
68
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
69
+ ]
70
+ }
71
+ ) });
72
+ case "info":
73
+ case "neutral":
74
+ default:
75
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: badgeClasses, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
76
+ "svg",
77
+ {
78
+ width: "12",
79
+ height: "12",
80
+ viewBox: "0 0 24 24",
81
+ fill: "none",
82
+ stroke: "currentColor",
83
+ strokeWidth: 2.5,
84
+ strokeLinecap: "round",
85
+ strokeLinejoin: "round",
86
+ "aria-hidden": "true",
87
+ children: [
88
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
89
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
90
+ ]
91
+ }
92
+ ) });
93
+ }
94
+ }
95
+ function Toast({
96
+ toast: toast2,
97
+ onDismiss,
98
+ closeOnClick = false,
99
+ globalIcons,
100
+ globalOptions
101
+ }) {
102
+ if (toast2.customRenderer) {
103
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: toast2.customRenderer(toast2.id) });
104
+ }
105
+ const icon = toast2.icon ?? globalIcons?.[toast2.type] ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultToastIcon, { type: toast2.type });
106
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
107
+ "div",
108
+ {
109
+ onClick: () => closeOnClick && onDismiss(),
110
+ className: `toastify-toast flex h-14 w-full select-none items-center justify-between gap-3 rounded-md border border-neutral-200/90 bg-white px-3.5 shadow-md shadow-neutral-950/5 dark:border-neutral-800/90 dark:bg-neutral-900 dark:shadow-neutral-950/40 ${globalOptions?.className ?? ""} ${toast2.className ?? ""}`,
111
+ style: { ...globalOptions?.style, ...toast2.style },
112
+ children: [
113
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
114
+ icon,
115
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex min-w-0 flex-col justify-center", children: [
116
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "truncate text-[13px] font-medium leading-4 text-neutral-900 dark:text-neutral-100", children: toast2.title }),
117
+ toast2.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-0.5 truncate text-[12px] leading-4 text-neutral-500 dark:text-neutral-400", children: toast2.description })
118
+ ] })
119
+ ] }),
120
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
121
+ toast2.cancel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
+ "button",
123
+ {
124
+ type: "button",
125
+ onClick: (event) => {
126
+ event.stopPropagation();
127
+ try {
128
+ toast2.cancel?.onClick(event);
129
+ } catch (err) {
130
+ console.error("Toast cancel handler failed:", err);
131
+ }
132
+ onDismiss();
133
+ },
134
+ className: "cursor-pointer rounded px-2 py-1 text-xs font-medium text-neutral-600 transition-colors hover:bg-neutral-100 hover:text-neutral-900 dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-neutral-100",
135
+ children: toast2.cancel.label
136
+ }
137
+ ),
138
+ toast2.action && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
139
+ "button",
140
+ {
141
+ type: "button",
142
+ onClick: (event) => {
143
+ event.stopPropagation();
144
+ try {
145
+ toast2.action?.onClick(event);
146
+ } catch (err) {
147
+ console.error("Toast action handler failed:", err);
148
+ }
149
+ onDismiss();
150
+ },
151
+ className: "cursor-pointer rounded px-2.5 py-1 text-xs font-medium bg-neutral-900 text-white transition-all hover:bg-neutral-800 shadow-[inset_0_-2px_4px_rgba(0,0,0,0.5),0_1px_2px_rgba(0,0,0,0.08)] active:shadow-[inset_0_2px_4px_rgba(0,0,0,0.4)] dark:bg-neutral-100 dark:text-neutral-900 dark:hover:bg-neutral-200 dark:shadow-[inset_0_-2px_4px_rgba(0,0,0,0.22),0_1px_2px_rgba(0,0,0,0.15)] dark:active:shadow-[inset_0_2px_4px_rgba(0,0,0,0.25)]",
152
+ children: toast2.action.label
153
+ }
154
+ )
155
+ ] })
156
+ ]
157
+ }
158
+ );
159
+ }
160
+
161
+ // src/toastify/animations/FadeAnimation.tsx
162
+ var import_react = require("motion/react");
163
+
164
+ // src/toastify/animations/constants.ts
165
+ var defaultSpring = {
166
+ stiffness: 220,
167
+ damping: 26,
168
+ mass: 1
169
+ };
170
+
171
+ // src/toastify/animations/FadeAnimation.tsx
172
+ var import_jsx_runtime2 = require("react/jsx-runtime");
173
+ function FadeAnimation({
174
+ index,
175
+ position,
176
+ isDismissing,
177
+ onDismiss,
178
+ springConfig = defaultSpring,
179
+ children
180
+ }) {
181
+ const isTop = position.startsWith("top");
182
+ const stackStep = 66;
183
+ const targetY = isTop ? index * stackStep : -index * stackStep;
184
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
185
+ import_react.motion.article,
186
+ {
187
+ role: "status",
188
+ "aria-live": "polite",
189
+ initial: {
190
+ opacity: 0,
191
+ scale: 0.9,
192
+ y: targetY,
193
+ filter: "blur(4px)"
194
+ },
195
+ animate: {
196
+ opacity: isDismissing ? 0 : 1,
197
+ scale: isDismissing ? 0.9 : 1,
198
+ y: targetY,
199
+ filter: isDismissing ? "blur(4px)" : "blur(0px)",
200
+ zIndex: 50 - index,
201
+ pointerEvents: !isDismissing ? "auto" : "none"
202
+ },
203
+ exit: {
204
+ opacity: 0,
205
+ scale: 0.9,
206
+ filter: "blur(4px)",
207
+ transition: {
208
+ duration: 0.22,
209
+ ease: "easeOut"
210
+ }
211
+ },
212
+ transition: {
213
+ type: "spring",
214
+ ...springConfig
215
+ },
216
+ drag: "x",
217
+ dragConstraints: { left: 0, right: 0 },
218
+ dragElastic: 0.6,
219
+ onDragEnd: (_, info) => {
220
+ if (Math.abs(info.offset.x) > 60 || Math.abs(info.velocity.x) > 500) {
221
+ onDismiss();
222
+ }
223
+ },
224
+ className: "absolute h-14 w-full select-none cursor-grab active:cursor-grabbing",
225
+ style: {
226
+ [isTop ? "top" : "bottom"]: 0,
227
+ left: 0,
228
+ right: 0
229
+ },
230
+ children
231
+ }
232
+ );
233
+ }
234
+
235
+ // src/toastify/animations/FolderStackAnimation.tsx
236
+ var import_react2 = require("motion/react");
237
+ var import_jsx_runtime3 = require("react/jsx-runtime");
238
+ function FolderStackAnimation({
239
+ index,
240
+ isHovered,
241
+ position,
242
+ isDismissing,
243
+ onDismiss,
244
+ springConfig = defaultSpring,
245
+ children
246
+ }) {
247
+ const isTop = position.startsWith("top");
248
+ const isCenter = position.endsWith("center");
249
+ const isLeft = position.endsWith("left");
250
+ const collapsed = !isHovered;
251
+ const isVisible = !collapsed || index < 3;
252
+ const stackStep = 66;
253
+ const offset = collapsed ? index * 10 : index * stackStep;
254
+ const targetY = isTop ? offset : -offset;
255
+ const targetScale = collapsed ? Math.max(0.88, 1 - index * 0.05) : 1;
256
+ const targetOpacity = !isVisible ? 0 : collapsed ? index === 0 ? 1 : index === 1 ? 0.94 : 0.84 : 1;
257
+ const exitX = isCenter ? 0 : isLeft ? -36 : 36;
258
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
259
+ import_react2.motion.article,
260
+ {
261
+ role: "status",
262
+ "aria-live": "polite",
263
+ initial: {
264
+ opacity: 0,
265
+ x: 0,
266
+ y: isTop ? targetY - 14 : targetY + 14,
267
+ scale: 0.94
268
+ },
269
+ animate: {
270
+ opacity: isDismissing ? 0 : targetOpacity,
271
+ x: isDismissing ? exitX : 0,
272
+ y: targetY,
273
+ scale: isDismissing ? 0.94 : targetScale,
274
+ zIndex: 50 - index,
275
+ pointerEvents: !isDismissing && isVisible ? "auto" : "none"
276
+ },
277
+ exit: {
278
+ opacity: 0,
279
+ x: exitX,
280
+ scale: 0.94,
281
+ transition: {
282
+ duration: 0.24,
283
+ ease: [0.16, 1, 0.3, 1]
284
+ }
285
+ },
286
+ transition: {
287
+ type: "spring",
288
+ ...springConfig
289
+ },
290
+ drag: index === 0 || isHovered ? "x" : false,
291
+ dragConstraints: { left: 0, right: 0 },
292
+ dragElastic: 0.6,
293
+ onDragEnd: (_, info) => {
294
+ if (Math.abs(info.offset.x) > 60 || Math.abs(info.velocity.x) > 500) {
295
+ onDismiss();
296
+ }
297
+ },
298
+ className: "absolute h-14 w-full select-none cursor-grab active:cursor-grabbing",
299
+ style: {
300
+ [isTop ? "top" : "bottom"]: 0,
301
+ left: 0,
302
+ right: 0,
303
+ transformOrigin: isTop ? "top center" : "bottom center"
304
+ },
305
+ children
306
+ }
307
+ );
308
+ }
309
+
310
+ // src/toastify/animations/SlideAnimation.tsx
311
+ var import_react3 = require("motion/react");
312
+ var import_jsx_runtime4 = require("react/jsx-runtime");
313
+ function SlideAnimation({
314
+ index,
315
+ position,
316
+ isDismissing,
317
+ onDismiss,
318
+ springConfig = defaultSpring,
319
+ children
320
+ }) {
321
+ const isTop = position.startsWith("top");
322
+ const isCenter = position.endsWith("center");
323
+ const isLeft = position.endsWith("left");
324
+ const stackStep = 66;
325
+ const targetY = isTop ? index * stackStep : -index * stackStep;
326
+ const entryX = isCenter ? 0 : isLeft ? -120 : 120;
327
+ const exitX = isCenter ? 0 : isLeft ? -140 : 140;
328
+ const initialY = isCenter ? isTop ? targetY - 30 : targetY + 30 : targetY;
329
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
330
+ import_react3.motion.article,
331
+ {
332
+ role: "status",
333
+ "aria-live": "polite",
334
+ initial: {
335
+ opacity: 0,
336
+ x: entryX,
337
+ y: initialY,
338
+ scale: 0.95
339
+ },
340
+ animate: {
341
+ opacity: isDismissing ? 0 : 1,
342
+ x: isDismissing ? exitX : 0,
343
+ y: targetY,
344
+ scale: 1,
345
+ zIndex: 50 - index,
346
+ pointerEvents: !isDismissing ? "auto" : "none"
347
+ },
348
+ exit: {
349
+ opacity: 0,
350
+ x: exitX,
351
+ scale: 0.95,
352
+ transition: {
353
+ duration: 0.22,
354
+ ease: [0.16, 1, 0.3, 1]
355
+ }
356
+ },
357
+ transition: {
358
+ type: "spring",
359
+ ...springConfig
360
+ },
361
+ drag: "x",
362
+ dragConstraints: { left: 0, right: 0 },
363
+ dragElastic: 0.6,
364
+ onDragEnd: (_, info) => {
365
+ if (Math.abs(info.offset.x) > 60 || Math.abs(info.velocity.x) > 500) {
366
+ onDismiss();
367
+ }
368
+ },
369
+ className: "absolute h-14 w-full select-none cursor-grab active:cursor-grabbing",
370
+ style: {
371
+ [isTop ? "top" : "bottom"]: 0,
372
+ left: 0,
373
+ right: 0
374
+ },
375
+ children
376
+ }
377
+ );
378
+ }
379
+
380
+ // src/toastify/animations/index.tsx
381
+ var import_jsx_runtime5 = require("react/jsx-runtime");
382
+ function ToastAnimation({
383
+ animation = "stack",
384
+ ...props
385
+ }) {
386
+ if (typeof animation === "function") {
387
+ const CustomAnimation = animation;
388
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CustomAnimation, { ...props });
389
+ }
390
+ if (animation === "slide") {
391
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SlideAnimation, { ...props });
392
+ }
393
+ if (animation === "fade") {
394
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FadeAnimation, { ...props });
395
+ }
396
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FolderStackAnimation, { ...props });
397
+ }
398
+
399
+ // src/toastify/store.ts
400
+ var MAX_TOASTS = 30;
401
+ var toasts = [];
402
+ var listeners = /* @__PURE__ */ new Set();
403
+ function generateId() {
404
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
405
+ return crypto.randomUUID();
406
+ }
407
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
408
+ }
409
+ function sanitizeDuration(duration) {
410
+ if (duration === false) return false;
411
+ if (typeof duration === "number") {
412
+ return Number.isFinite(duration) && duration >= 0 ? duration : 3500;
413
+ }
414
+ return void 0;
415
+ }
416
+ function emit() {
417
+ const snapshot = [...toasts];
418
+ listeners.forEach((listener) => {
419
+ try {
420
+ listener(snapshot);
421
+ } catch (err) {
422
+ console.error("Toast listener threw an error:", err);
423
+ }
424
+ });
425
+ }
426
+ function subscribe(listener) {
427
+ listeners.add(listener);
428
+ try {
429
+ listener([...toasts]);
430
+ } catch (err) {
431
+ console.error("Initial toast listener threw an error:", err);
432
+ }
433
+ return () => {
434
+ listeners.delete(listener);
435
+ };
436
+ }
437
+ function remove(id) {
438
+ if (id) {
439
+ toasts = toasts.filter((toast2) => toast2.id !== id);
440
+ } else {
441
+ toasts = [];
442
+ }
443
+ emit();
444
+ }
445
+ function update(id, updates) {
446
+ toasts = toasts.map(
447
+ (toast2) => toast2.id === id ? { ...toast2, ...updates } : toast2
448
+ );
449
+ emit();
450
+ }
451
+ function create(type, title, options = {}) {
452
+ const id = options.id ?? generateId();
453
+ const duration = sanitizeDuration(options.autoClose ?? options.duration);
454
+ const existing = toasts.find((t) => t.id === id);
455
+ if (existing) {
456
+ update(id, {
457
+ type,
458
+ title,
459
+ description: options.description,
460
+ action: options.action,
461
+ cancel: options.cancel,
462
+ icon: options.icon,
463
+ className: options.className,
464
+ style: options.style,
465
+ duration
466
+ });
467
+ return id;
468
+ }
469
+ const toastItem = {
470
+ id,
471
+ type,
472
+ title,
473
+ description: options.description,
474
+ action: options.action,
475
+ cancel: options.cancel,
476
+ icon: options.icon,
477
+ className: options.className,
478
+ style: options.style,
479
+ duration,
480
+ createdAt: Date.now()
481
+ };
482
+ toasts = [toastItem, ...toasts].slice(0, MAX_TOASTS);
483
+ emit();
484
+ return id;
485
+ }
486
+ function promise(promiseOrFn, options) {
487
+ const id = create("loading", options.loading, {
488
+ duration: false
489
+ });
490
+ const p = typeof promiseOrFn === "function" ? promiseOrFn() : promiseOrFn;
491
+ const promiseChain = p.then((data) => {
492
+ let successTitle;
493
+ try {
494
+ successTitle = typeof options.success === "function" ? options.success(data) : options.success;
495
+ } catch {
496
+ successTitle = "Completed successfully";
497
+ }
498
+ let description;
499
+ if (options.description) {
500
+ try {
501
+ description = typeof options.description === "function" ? options.description(data) : options.description;
502
+ } catch {
503
+ description = void 0;
504
+ }
505
+ }
506
+ update(id, {
507
+ type: "success",
508
+ title: successTitle,
509
+ description,
510
+ action: options.action,
511
+ cancel: options.cancel,
512
+ duration: 3500
513
+ });
514
+ return data;
515
+ }).catch((err) => {
516
+ let errorTitle;
517
+ try {
518
+ errorTitle = typeof options.error === "function" ? options.error(err) : options.error;
519
+ } catch {
520
+ errorTitle = "An error occurred";
521
+ }
522
+ update(id, {
523
+ type: "error",
524
+ title: errorTitle,
525
+ action: options.action,
526
+ cancel: options.cancel,
527
+ duration: 4e3
528
+ });
529
+ return Promise.reject(err);
530
+ });
531
+ promiseChain.catch(() => {
532
+ });
533
+ return promiseChain;
534
+ }
535
+ var toastStore = {
536
+ subscribe,
537
+ remove,
538
+ update,
539
+ getToasts: () => [...toasts]
540
+ };
541
+ function toastFn(title, options) {
542
+ return create("neutral", title, options);
543
+ }
544
+ var toast = Object.assign(toastFn, {
545
+ show(title, options) {
546
+ return create("neutral", title, options);
547
+ },
548
+ success(title, options) {
549
+ return create("success", title, options);
550
+ },
551
+ error(title, options) {
552
+ return create("error", title, options);
553
+ },
554
+ warning(title, options) {
555
+ return create("warning", title, options);
556
+ },
557
+ info(title, options) {
558
+ return create("info", title, options);
559
+ },
560
+ loading(title, options) {
561
+ return create("loading", title, { ...options, duration: false });
562
+ },
563
+ custom(renderer, options = {}) {
564
+ const id = options.id ?? generateId();
565
+ const duration = sanitizeDuration(options.autoClose ?? options.duration);
566
+ const toastItem = {
567
+ id,
568
+ type: "custom",
569
+ title: "",
570
+ customRenderer: renderer,
571
+ duration,
572
+ className: options.className,
573
+ style: options.style,
574
+ createdAt: Date.now()
575
+ };
576
+ toasts = [toastItem, ...toasts].slice(0, MAX_TOASTS);
577
+ emit();
578
+ return id;
579
+ },
580
+ promise,
581
+ dismiss(id) {
582
+ remove(id);
583
+ },
584
+ update(id, options) {
585
+ update(id, options);
586
+ }
587
+ });
588
+
589
+ // src/toastify/Toaster.tsx
590
+ var import_jsx_runtime6 = require("react/jsx-runtime");
591
+ var positionClasses = {
592
+ "top-left": "top-6 left-6",
593
+ "top-center": "top-6 left-0 right-0 mx-auto",
594
+ "top-right": "top-6 right-6",
595
+ "bottom-left": "bottom-6 left-6",
596
+ "bottom-center": "bottom-6 left-0 right-0 mx-auto",
597
+ "bottom-right": "bottom-6 right-6"
598
+ };
599
+ function ToasterItem({
600
+ toast: toast2,
601
+ index,
602
+ totalToasts,
603
+ isHovered,
604
+ position,
605
+ duration = 3500,
606
+ autoClose,
607
+ closeOnClick = false,
608
+ animation = "stack",
609
+ springConfig,
610
+ icons,
611
+ toastOptions,
612
+ onDismiss
613
+ }) {
614
+ const itemDuration = toast2.type === "loading" ? false : toast2.duration !== void 0 ? toast2.duration : toastOptions?.duration !== void 0 ? toastOptions.duration : autoClose ?? duration;
615
+ const onDismissRef = (0, import_react5.useRef)(onDismiss);
616
+ (0, import_react5.useEffect)(() => {
617
+ onDismissRef.current = onDismiss;
618
+ }, [onDismiss]);
619
+ const [isDismissing, setIsDismissing] = (0, import_react5.useState)(false);
620
+ const handleDismiss = () => {
621
+ setIsDismissing(true);
622
+ onDismissRef.current();
623
+ };
624
+ const remainingTimeRef = (0, import_react5.useRef)(itemDuration);
625
+ (0, import_react5.useEffect)(() => {
626
+ remainingTimeRef.current = itemDuration;
627
+ }, [itemDuration]);
628
+ (0, import_react5.useEffect)(() => {
629
+ if (itemDuration === false || isHovered) {
630
+ return;
631
+ }
632
+ const startTime = Date.now();
633
+ const currentRemaining = remainingTimeRef.current === false ? itemDuration : remainingTimeRef.current;
634
+ const timer = window.setTimeout(() => {
635
+ handleDismiss();
636
+ }, currentRemaining);
637
+ return () => {
638
+ window.clearTimeout(timer);
639
+ if (remainingTimeRef.current !== false) {
640
+ const elapsed = Date.now() - startTime;
641
+ remainingTimeRef.current = Math.max(0, remainingTimeRef.current - elapsed);
642
+ }
643
+ };
644
+ }, [isHovered, itemDuration]);
645
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
646
+ ToastAnimation,
647
+ {
648
+ animation,
649
+ toast: toast2,
650
+ index,
651
+ totalToasts,
652
+ isHovered,
653
+ position,
654
+ isDismissing,
655
+ onDismiss: handleDismiss,
656
+ springConfig,
657
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
658
+ Toast,
659
+ {
660
+ toast: toast2,
661
+ onDismiss: handleDismiss,
662
+ closeOnClick,
663
+ globalIcons: icons,
664
+ globalOptions: toastOptions
665
+ }
666
+ )
667
+ }
668
+ );
669
+ }
670
+ function Toaster({
671
+ position = "bottom-right",
672
+ duration = 3500,
673
+ autoClose,
674
+ theme = "light",
675
+ className,
676
+ style,
677
+ visibleToasts = 5,
678
+ closeOnClick = false,
679
+ animation = "stack",
680
+ springConfig,
681
+ icons,
682
+ toastOptions
683
+ }) {
684
+ const [toasts2, setToasts] = (0, import_react5.useState)([]);
685
+ const [isHovered, setIsHovered] = (0, import_react5.useState)(false);
686
+ const [hoverExpandedCount, setHoverExpandedCount] = (0, import_react5.useState)(null);
687
+ const leaveTimeoutRef = (0, import_react5.useRef)(null);
688
+ (0, import_react5.useEffect)(() => toastStore.subscribe(setToasts), []);
689
+ const isTop = position.startsWith("top");
690
+ const hasToasts = toasts2.length > 0;
691
+ const activeCount = Math.min(toasts2.length, visibleToasts);
692
+ const effectiveCount = isHovered && hoverExpandedCount !== null ? Math.max(activeCount, hoverExpandedCount) : activeCount;
693
+ const containerHeight = hasToasts && isHovered && effectiveCount > 0 ? (effectiveCount - 1) * 66 + 56 : 56;
694
+ const handleMouseEnter = () => {
695
+ if (leaveTimeoutRef.current) {
696
+ window.clearTimeout(leaveTimeoutRef.current);
697
+ leaveTimeoutRef.current = null;
698
+ }
699
+ setHoverExpandedCount((prev) => Math.max(prev ?? 0, activeCount));
700
+ setIsHovered(true);
701
+ };
702
+ const handleMouseLeave = () => {
703
+ leaveTimeoutRef.current = window.setTimeout(() => {
704
+ setIsHovered(false);
705
+ setHoverExpandedCount(null);
706
+ }, 140);
707
+ };
708
+ (0, import_react5.useEffect)(() => {
709
+ return () => {
710
+ if (leaveTimeoutRef.current) {
711
+ window.clearTimeout(leaveTimeoutRef.current);
712
+ }
713
+ };
714
+ }, []);
715
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
716
+ import_react4.motion.div,
717
+ {
718
+ "data-toastify-toaster": "true",
719
+ role: "region",
720
+ "aria-label": "Notifications",
721
+ "aria-live": "polite",
722
+ tabIndex: -1,
723
+ className: `toastify-toaster fixed z-50 w-[356px] max-w-[calc(100vw-32px)] ${hasToasts ? "pointer-events-auto" : "pointer-events-none"} ${positionClasses[position]} ${theme === "dark" ? "dark" : ""} ${className ?? ""}`,
724
+ style,
725
+ animate: {
726
+ height: containerHeight
727
+ },
728
+ transition: {
729
+ type: "spring",
730
+ stiffness: 220,
731
+ damping: 26,
732
+ mass: 1,
733
+ ...springConfig
734
+ },
735
+ onMouseEnter: handleMouseEnter,
736
+ onMouseLeave: handleMouseLeave,
737
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
738
+ "div",
739
+ {
740
+ className: `relative w-full h-full flex ${isTop ? "flex-col" : "flex-col-reverse"}`,
741
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react4.AnimatePresence, { children: toasts2.slice(0, visibleToasts).map((toastItem, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
742
+ ToasterItem,
743
+ {
744
+ toast: toastItem,
745
+ index,
746
+ totalToasts: toasts2.length,
747
+ isHovered,
748
+ position,
749
+ duration,
750
+ autoClose,
751
+ closeOnClick,
752
+ animation,
753
+ springConfig,
754
+ icons,
755
+ toastOptions,
756
+ onDismiss: () => toastStore.remove(toastItem.id)
757
+ },
758
+ toastItem.id
759
+ )) })
760
+ }
761
+ )
762
+ }
763
+ );
764
+ }
765
+ var ToastContainer = Toaster;
766
+ // Annotate the CommonJS export names for ESM import in node:
767
+ 0 && (module.exports = {
768
+ DefaultToastIcon,
769
+ FadeAnimation,
770
+ FolderStackAnimation,
771
+ SlideAnimation,
772
+ Toast,
773
+ ToastAnimation,
774
+ ToastContainer,
775
+ Toaster,
776
+ defaultSpring,
777
+ toast,
778
+ toastStore
779
+ });