juice-toast 1.2.1 → 1.3.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.
@@ -1,15 +1,15 @@
1
- /* --------------------------------------------------
2
- * 2026 (C) OpenDN Foundation
3
- * Juice Toast v1.2.0-rc.2026 Type Definitions
4
- * -------------------------------------------------- */
5
-
6
- export type ToastTheme = {
7
- bg?: string;
8
- color?: string;
9
- border?: string;
10
- };
11
-
12
- export type ToastSizePreset = "sm" | "md" | "lg";
1
+ /* JuiceToast v1.3.1
2
+ * (C) 2026 OpenDN Foundation
3
+ * Type Definitions
4
+ */
5
+
6
+ export type ToastType =
7
+ | "success"
8
+ | "error"
9
+ | "warning"
10
+ | "info"
11
+ | "loading"
12
+ | string
13
13
 
14
14
  export type ToastPosition =
15
15
  | "top-left"
@@ -17,91 +17,113 @@ export type ToastPosition =
17
17
  | "bottom-left"
18
18
  | "bottom-right"
19
19
  | "top-center"
20
- | "bottom-center";
21
-
22
- export type ToastAnimation =
23
- | "slide-in"
24
- | "fade-in"
25
- | "bounce-in"
26
- | string;
27
-
28
- export type ToastAction = {
29
- label: string;
30
- onClick?: (event: Event) => void;
31
- closeOnClick?: boolean;
32
- };
33
-
34
- export type ToastPayload = {
35
- message?: string;
36
- title?: string;
37
-
38
- duration?: number; // ms, 0 = persistent
39
- position?: ToastPosition;
40
- theme?: string;
41
- bg?: string;
42
- size?: ToastSizePreset;
43
- width?: string;
44
- height?: string;
45
- compact?: boolean;
46
- closable?: boolean;
47
- glassUI?: boolean | number;
48
-
49
- icon?: string;
50
- iconPack?: string;
51
- iconSize?: string;
52
- iconPosition?: "left" | "right" | "top";
53
- iconLink?: string;
54
- iconAnimate?: string;
55
-
56
- animation?: ToastAnimation;
57
-
58
- actions?: ToastAction[];
59
- };
60
-
61
- export type ToastDefaults = {
62
- duration: number;
63
- maxVisible: number;
64
- swipeThreshold: number;
65
- glassUI: number;
66
- playSound: string | null;
67
- };
68
-
69
- export interface JuiceToast {
70
- /* ================= PUBLIC API ================= */
71
-
72
- setup(cfg?: Record<string, ToastPayload>): void;
73
-
74
- addType(name: string, cfg?: ToastPayload): void;
75
-
76
- defineTheme(name: string, styles?: ToastTheme): void;
77
-
78
- setTheme(name: string): void;
79
-
80
- clear(): void;
20
+ | "bottom-center"
21
+
22
+ export type ToastSize = "sm" | "md" | "lg"
23
+
24
+ export type AnimationType =
25
+ | "spin"
26
+ | "pulse"
27
+ | "shake"
28
+ | "bounce"
29
+ | "wiggle"
30
+ | "pop"
31
+ | string
32
+
33
+ export interface ToastAction {
34
+ label: string
35
+ onClick?: (event: MouseEvent) => void
36
+ closeOnClick?: boolean
37
+ }
81
38
 
82
- destroy(): void;
39
+ export interface ToastOptions {
40
+ /* content */
41
+ title?: string
42
+ message?: string
43
+
44
+ /* icon */
45
+ icon?: string
46
+ iconPack?: string
47
+ iconSize?: string | number
48
+ iconPosition?: "left" | "right" | "top"
49
+ iconLink?: string
50
+ iconAnimate?: AnimationType
51
+
52
+ /* layout */
53
+ position?: ToastPosition
54
+ size?: ToastSize
55
+ width?: string
56
+ height?: string
57
+ compact?: boolean
58
+
59
+ /* behavior */
60
+ duration?: number
61
+ closable?: boolean
62
+ progress?: boolean
63
+ progressColor?: string
64
+ swipeThreshold?: number
65
+
66
+ /* style */
67
+ theme?: string
68
+ bg?: string
69
+ color?: string
70
+ border?: string
71
+ glassUI?: boolean | number
72
+
73
+ /* animation */
74
+ animation?: AnimationType
75
+ enterAnimation?: AnimationType
76
+
77
+ /* actions */
78
+ actions?: ToastAction[]
79
+
80
+ /* sound */
81
+ playSound?: string | null
82
+ }
83
83
 
84
- /* ================= INTERNAL ================= */
84
+ export interface JuiceToastConfig {
85
+ duration?: number
86
+ maxVisible?: number
87
+ swipeThreshold?: number
88
+ glassUI?: number | boolean
89
+ playSound?: string | null
90
+ dev?: boolean
91
+ injectCSS?: boolean
92
+ css?: string
93
+
94
+ [type: string]: any
95
+ }
85
96
 
86
- _config: Record<string, ToastPayload>;
87
- _queue: Array<{ type: string; payload: any }>;
88
- _showing: boolean;
89
- _theme: string;
90
- _defaults: ToastDefaults;
97
+ export interface ToastPluginContext {
98
+ toast: HTMLElement
99
+ cfg: ToastOptions
100
+ type: ToastType
101
+ root: HTMLElement
102
+ }
91
103
 
92
- _registerTypes(): void;
93
- _enqueue(type: string, payload: any): void;
94
- _next(): void;
95
- _normalizeGlass(value?: boolean | number): number;
96
- _getRoot(position?: ToastPosition): HTMLElement | null;
97
- _playSound(src?: string): void;
98
- _showToast(type: string, payload: ToastPayload | string): void;
104
+ export type JuiceToastPlugin = (ctx: ToastPluginContext) => void
99
105
 
100
- /* ================= DYNAMIC TOAST METHODS ================= */
101
- [type: string]: ((payload?: ToastPayload | string) => void) | any;
106
+ export interface JuiceToast {
107
+ /* core */
108
+ setup(config?: JuiceToastConfig): void
109
+ clear(): void
110
+ destroy(): void
111
+
112
+ /* toast types */
113
+ [key: string]: any
114
+
115
+ /* extension */
116
+ use(plugin: JuiceToastPlugin): void
117
+ addType(type: ToastType, defaults?: Partial<ToastOptions>): void
118
+ defineTheme(name: string, theme: {
119
+ bg?: string
120
+ color?: string
121
+ border?: string
122
+ }): void
123
+ setTheme(name: string): void
102
124
  }
103
125
 
104
- declare const juiceToast: JuiceToast;
126
+ declare const juiceToast: JuiceToast
105
127
 
106
- export default juiceToast;
107
- export { juiceToast };
128
+ export default juiceToast
129
+ export { juiceToast }
@@ -1,6 +1,312 @@
1
1
  /**
2
2
  * 2026 (C) OpenDN Foundation
3
- * v1.2.0-rc.2026 Juice Toast
4
- * ESM (ECMAScript Module (import/export))
3
+ * v1.3.1 (STABLE)
4
+ * ESM (ECMAScript Module)
5
5
  */
6
- let isBrowser="undefined"!=typeof window&&"undefined"!=typeof document,themes={light:{bg:"#ffffff",color:"#111",border:"1px solid #e5e7eb"},dark:{bg:"#1f2937",color:"#fff",border:"1px solid rgba(255,255,255,.08)"}},sizePreset={sm:{width:"260px",padding:"10px"},md:{width:"320px",padding:"14px"},lg:{width:"420px",padding:"18px"}},juiceToast={_config:{},_queue:[],_showing:!1,_theme:"dark",setup(e={}){this._config=e,this._defaults={...this._defaults,...e},this._registerTypes()},addType(e,t={}){this._config[e]=t,this._registerTypes()},defineTheme(e,t={}){themes[e]={...themes[e]||{},...t}},setTheme(e){if(this._theme=e,!isBrowser)return;let t=document.getElementById("juice-toast-root");t&&(t.dataset.theme=e)},clear(){this._queue.length=0},destroy(){this.clear(),isBrowser&&document.getElementById("juice-toast-root")?.remove()},_registerTypes(){Object.keys(this._config).forEach(e=>{if("function"==typeof this[e]&&!this[e].__auto)return;let t=t=>this._enqueue(e,t);t.__auto=!0,this[e]=t})},_enqueue(e,t){this._queue.push({type:e,payload:t}),this._showing||this._next()},_next(){if(!this._queue.length){this._showing=!1;return}this._showing=!0;let e=this._queue.shift();this._showToast(e.type,e.payload)},_normalizeGlass(e){if(!0===e)return 60;if(!1===e||null==e)return 0;let t=Number(e);return Number.isFinite(t)?Math.max(0,Math.min(100,t)):0},_getRoot(e="bottom-right"){if(!isBrowser)return null;let t=document.getElementById(`juice-toast-root-${e}`);if(!t){switch((t=document.createElement("div")).id=`juice-toast-root-${e}`,t.dataset.position=e,t.dataset.theme=this._theme,t.style.position="fixed",t.style.zIndex=9999,e){case"top-left":t.style.top="20px",t.style.left="20px";break;case"top-right":t.style.top="20px",t.style.right="20px";break;case"bottom-left":t.style.bottom="20px",t.style.left="20px";break;case"bottom-right":t.style.bottom="20px",t.style.right="20px";break;case"top-center":t.style.top="20px",t.style.left="50%",t.style.transform="translateX(-50%)";break;case"bottom-center":t.style.bottom="20px",t.style.left="50%",t.style.transform="translateX(-50%)"}document.body.appendChild(t)}return t},_defaults:{duration:2500,maxVisible:3,swipeThreshold:60,glassUI:0,playSound:null},_playSound(e){if(!isBrowser)return;let t="string"==typeof e&&e?e:this._defaults.playSound;if(t)try{let s=new Audio(t);s.volume=.6,s.play().catch(()=>{})}catch{}},_showToast(e,t){if(!isBrowser)return;let s=this._config[e]||{},i="object"==typeof t?t:{message:String(t)},o={...s,...i};o.icon=o.icon??o.icon_left_top,o.iconPack=o.iconPack??o.icon_config,o.iconLink=o.iconLink??o.icon_onClick_url,o.iconAnimate=o.iconAnimate??o.icon_onClick_animate,o.position=o.position??o.toast,o.closable=o.closable??o.closeable,o.iconPosition=o.iconPosition||"left",o.compact=!!o.compact;let n=themes[o.theme||this._theme]||{},a=document.createElement("div");a.className="juice-toast";let l=o.animation||"slide-in";if(a.style.animation=`${l} 0.4s ease forwards`,a.setAttribute("role","alert"),a.setAttribute("aria-live","polite"),a.tabIndex=0,o.size&&sizePreset[o.size]){let r=sizePreset[o.size];r.width&&(a.style.width=r.width),r.padding&&(a.style.padding=r.padding)}let d=this._normalizeGlass(o.glassUI??this._defaults.glassUI);d>0&&(a.classList.add("jt-glass"),a.style.setProperty("--jt-glass",d)),d||(a.style.background=o.bg||n.bg),a.style.color=o.color||n.color,a.style.border=o.border||n.border,o.compact&&a.classList.add("jt-compact"),(o.glassUI??this._defaults.glassUI)&&a.classList.add("jt-glass"),o.width&&(a.style.width=o.width),o.height&&(a.style.height=o.height);let c=null;o.icon&&((c=document.createElement("i")).className=["icon",o.iconPack||"",o.icon].join(" ").trim(),o.iconSize&&(c.style.fontSize=o.iconSize),(o.iconLink||o.iconAnimate)&&(c.classList.add("icon-clickable"),c.onclick=e=>{e.stopPropagation(),o.iconAnimate&&(c.classList.remove(o.iconAnimate),c.offsetWidth,c.classList.add(o.iconAnimate)),o.iconLink&&window.open(o.iconLink,"_blank","noopener")}));let h=0,p=0;a.addEventListener("touchstart",e=>{h=e.touches[0].clientX}),a.addEventListener("touchmove",e=>{p=e.touches[0].clientX-h,a.style.transform=`translateX(${p}px)`}),a.addEventListener("touchend",()=>{Math.abs(p)>this._defaults.swipeThreshold?(a.style.transform=`translateX(${p>0?1e3:-1e3}px)`,setTimeout(()=>{a.remove(),this._next()},200)):a.style.transform="",h=p=0});let m=document.createElement("div");if(m.className="jt-content",o.title){let u=document.createElement("div");u.className="jt-title",u.textContent=o.title,m.appendChild(u)}let f=document.createElement("div");if(f.className="jt-message",f.textContent=o.message||"",m.appendChild(f),c&&"top"===o.iconPosition?(a.classList.add("jt-icon-top"),a.appendChild(c),a.appendChild(m)):c&&"right"===o.iconPosition?(a.appendChild(m),a.appendChild(c)):(c&&a.appendChild(c),a.appendChild(m)),Array.isArray(o.actions)&&o.actions.length){let g=document.createElement("div");g.className="jt-actions",o.actions.forEach(e=>{let t=document.createElement("button");t.className="jt-action",t.textContent=e.label,t.onclick=t=>{t.stopPropagation(),e.onClick?.(t),e.closeOnClick&&(a.remove(),this._next())},g.appendChild(t)}),m.appendChild(g)}if(o.closable){let $=document.createElement("span");$.className="juice-toast-close",$.innerHTML="\xd7",$.onclick=()=>{a.remove(),this._next()},a.appendChild($)}let y=this._getRoot(o.position),b=this._defaults.maxVisible;b&&y.children.length>=b&&y.firstChild.remove(),y.appendChild(a),requestAnimationFrame(()=>a.classList.add("show"));let x=o.duration??2500;if(0===x)return;let w=Date.now(),k=o.duration??this._defaults.duration,v,L=()=>{if(a.__paused)w=Date.now();else{let e=Date.now();k-=e-w,w=e}k<=0?(a.classList.remove("show"),setTimeout(()=>{a.remove(),this._next()},300)):v=requestAnimationFrame(L)};a.addEventListener("mouseenter",()=>a.__paused=!0),a.addEventListener("mouseleave",()=>a.__paused=!1),a.addEventListener("touchstart",()=>a.__paused=!0),a.addEventListener("touchend",()=>a.__paused=!1),requestAnimationFrame(L)}};export default juiceToast;export{juiceToast};
6
+ let isBrowser="undefined"!=typeof window&&"undefined"!=typeof document,reduceMotion=isBrowser&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,TYPE_ANIMATION={success:"bounce",error:"shake",warning:"wiggle",info:"pulse",loading:"spin"},__cssInjected=!1,BASE_CSS=`
7
+ #juice-toast-root {
8
+ position: fixed;
9
+ z-index: 9999;
10
+ display: flex;
11
+ gap: 10px;
12
+ pointer-events: none;
13
+ }
14
+
15
+ /* bottom (default) */
16
+ #juice-toast-root[data-position="bottom"] {
17
+ bottom: 20px;
18
+ left: 50%;
19
+ transform: translateX(-50%);
20
+ flex-direction: column;
21
+ align-items: center;
22
+ }
23
+
24
+ /* top */
25
+ #juice-toast-root[data-position="top"] {
26
+ top: 20px;
27
+ left: 50%;
28
+ transform: translateX(-50%);
29
+ flex-direction: column;
30
+ align-items: center;
31
+ }
32
+
33
+ /* center */
34
+ #juice-toast-root[data-position="center"] {
35
+ top: 50%;
36
+ left: 50%;
37
+ transform: translate(-50%, -50%);
38
+ flex-direction: column;
39
+ align-items: center;
40
+ }
41
+
42
+ [id^="juice-toast-root-"] {
43
+ position: fixed;
44
+ z-index: 9999;
45
+ display: flex;
46
+ gap: 10px;
47
+ pointer-events: none;
48
+ }
49
+
50
+
51
+ /* ================= TOAST ================= */
52
+
53
+ .juice-toast {
54
+ /* animation vars (safe for swipe) */
55
+ --jt-x: 0px;
56
+ --jt-y: 12px;
57
+
58
+ pointer-events: auto;
59
+ display: flex;
60
+ gap: 12px;
61
+ align-items: flex-start;
62
+
63
+ min-width: 220px;
64
+ max-width: 420px;
65
+ padding: 12px 16px;
66
+ margin: 6px 0;
67
+
68
+ border-radius: 8px;
69
+ background: #333;
70
+ color: #fff;
71
+
72
+ font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial;
73
+ font-size: 14px;
74
+
75
+ opacity: 0;
76
+ transform: translate(var(--jt-x), var(--jt-y));
77
+ transition:
78
+ opacity .25s ease,
79
+ transform .25s ease,
80
+ background .25s ease,
81
+ color .25s ease,
82
+ box-shadow .25s ease;
83
+
84
+ position: relative;
85
+ box-sizing: border-box;
86
+ overflow: hidden;
87
+ }
88
+
89
+ /* visible */
90
+ .juice-toast.show {
91
+ opacity: 1;
92
+ --jt-y: 0px;
93
+ }
94
+
95
+ /* ================= ICON ================= */
96
+
97
+ .juice-toast .icon {
98
+ width: 28px;
99
+ height: 28px;
100
+ display: inline-flex;
101
+ align-items: center;
102
+ justify-content: center;
103
+ font-size: 16px;
104
+ line-height: 1;
105
+ flex: 0 0 28px;
106
+ }
107
+
108
+ /* clickable icon */
109
+ .icon-clickable {
110
+ opacity: 0.85;
111
+ cursor: pointer;
112
+ }
113
+
114
+ .icon-clickable:hover {
115
+ opacity: 1;
116
+ }
117
+
118
+ /* ================= CONTENT ================= */
119
+
120
+ .juice-toast .jt-content {
121
+ display: flex;
122
+ flex-direction: column;
123
+ gap: 4px;
124
+ flex: 1 1 auto;
125
+ }
126
+
127
+ /* title */
128
+ .juice-toast .jt-title {
129
+ font-weight: 700;
130
+ font-size: 13px;
131
+ line-height: 1.1;
132
+ }
133
+
134
+ /* message */
135
+ .juice-toast .jt-message {
136
+ font-size: 13px;
137
+ line-height: 1.3;
138
+ opacity: 0.95;
139
+ }
140
+
141
+ /* ================= ICON POSITION ================= */
142
+
143
+ .jt-icon-top {
144
+ flex-direction: column;
145
+ align-items: flex-start;
146
+ }
147
+
148
+ .jt-icon-top .icon {
149
+ align-self: center;
150
+ margin-bottom: 6px;
151
+ }
152
+
153
+ /* ================= CLOSE ================= */
154
+
155
+ .juice-toast-close {
156
+ position: absolute;
157
+ top: 6px;
158
+ right: 8px;
159
+ cursor: pointer;
160
+ font-size: 16px;
161
+ opacity: 0.75;
162
+ padding: 4px;
163
+ border-radius: 4px;
164
+ }
165
+
166
+ .juice-toast-close:hover {
167
+ opacity: 1;
168
+ background: rgba(255,255,255,0.06);
169
+ }
170
+
171
+ /* ================= ACTIONS ================= */
172
+
173
+ .jt-actions {
174
+ display: flex;
175
+ gap: 8px;
176
+ margin-top: 10px;
177
+ }
178
+
179
+ .jt-action {
180
+ background: transparent;
181
+ border: 1px solid currentColor;
182
+ padding: 4px 10px;
183
+ border-radius: 6px;
184
+ cursor: pointer;
185
+ font-size: 12px;
186
+ }
187
+
188
+ /* ================= COMPACT ================= */
189
+
190
+ .jt-compact {
191
+ padding: 8px 10px;
192
+ gap: 8px;
193
+ font-size: 0.9em;
194
+ }
195
+
196
+ /* ================= GLASS UI ================= */
197
+
198
+ .jt-glass {
199
+ --g: calc(var(--jt-glass, 60) / 100);
200
+
201
+ background: rgba(30, 30, 30, calc(0.2 + var(--g)));
202
+ backdrop-filter: blur(calc(6px + (14px * var(--g))))
203
+ saturate(calc(1 + (0.4 * var(--g))));
204
+ -webkit-backdrop-filter: blur(calc(6px + (14px * var(--g))))
205
+ saturate(calc(1 + (0.4 * var(--g))));
206
+ }
207
+
208
+ /* light theme support */
209
+ [data-theme="light"] .jt-glass {
210
+ background:
211
+ linear-gradient(
212
+ rgba(255,255,255, calc(0.6 * var(--g))),
213
+ rgba(255,255,255, calc(0.35 * var(--g)))
214
+ ),
215
+ rgba(255,255,255, calc(0.55 - (0.25 * var(--g))));
216
+
217
+ color: #111;
218
+
219
+ border:
220
+ 1px solid rgba(0,0,0, calc(0.05 + 0.12 * var(--g)));
221
+
222
+ box-shadow:
223
+ 0 10px 30px rgba(0,0,0, calc(0.08 + 0.18 * var(--g))),
224
+ inset 0 1px 0 rgba(255,255,255, calc(0.4 * var(--g)));
225
+ }
226
+
227
+ /* ================= PROGRESS BAR ================= */
228
+ .jt-progress {
229
+ position: absolute;
230
+ left: 0;
231
+ bottom: 0;
232
+
233
+ height: 3px;
234
+ width: 100%;
235
+
236
+ background: rgba(255,255,255,.7);
237
+ transform-origin: left;
238
+ transform: scaleX(1);
239
+ opacity: .85;
240
+ }
241
+
242
+ /* ================= ANIMATIONS ================= */
243
+
244
+ @keyframes jt-spin {
245
+ to { transform: rotate(360deg); }
246
+ }
247
+
248
+ @keyframes jt-pulse {
249
+ 50% { transform: scale(1.15); }
250
+ }
251
+
252
+ @keyframes jt-shake {
253
+ 25% { transform: translateX(-3px); }
254
+ 50% { transform: translateX(3px); }
255
+ 75% { transform: translateX(-3px); }
256
+ }
257
+
258
+ @keyframes jt-bounce {
259
+ 0% { transform: scale(1); }
260
+ 30% { transform: scale(1.25); }
261
+ 60% { transform: scale(.95); }
262
+ 100% { transform: scale(1); }
263
+ }
264
+
265
+ @keyframes jt-wiggle {
266
+ 0% { transform: rotate(0); }
267
+ 25% { transform: rotate(-10deg); }
268
+ 50% { transform: rotate(10deg); }
269
+ 75% { transform: rotate(-6deg); }
270
+ 100% { transform: rotate(0); }
271
+ }
272
+
273
+ @keyframes jt-pop {
274
+ 0% { transform: scale(.7); opacity: 0; }
275
+ 70% { transform: scale(1.05); opacity: 1; }
276
+ 100% { transform: scale(1); }
277
+ }
278
+
279
+ /* ================= CLASSES ================= */
280
+
281
+ .spin { animation: jt-spin .6s linear; }
282
+ .pulse { animation: jt-pulse .4s ease; }
283
+ .shake { animation: jt-shake .4s ease; }
284
+ .bounce { animation: jt-bounce .45s ease; }
285
+ .wiggle { animation: jt-wiggle .5s ease; }
286
+ .pop { animation: jt-pop .35s ease-out; }
287
+
288
+ /* ================= ICON INTERACTION ================= */
289
+
290
+ .icon-clickable {
291
+ cursor: pointer;
292
+ transition: transform .15s ease, opacity .15s ease;
293
+ }
294
+
295
+ .icon-clickable:hover {
296
+ transform: scale(1.1);
297
+ opacity: .85;
298
+ }
299
+
300
+ /* ================= ACCESSIBILITY ================= */
301
+
302
+ @media (prefers-reduced-motion: reduce) {
303
+ .spin,
304
+ .pulse,
305
+ .shake,
306
+ .bounce,
307
+ .wiggle,
308
+ .pop {
309
+ animation: none !important;
310
+ }
311
+ }
312
+ `;function injectCSS(e){if(!isBrowser||__cssInjected)return;let t=document.createElement("style");t.id="juice-toast-style",t.textContent=e,document.head.appendChild(t),__cssInjected=!0}let themes={light:{bg:"#ffffff",color:"#111",border:"1px solid #e5e7eb"},dark:{bg:"#1f2937",color:"#fff",border:"1px solid rgba(255,255,255,.08)"}},sizePreset={sm:{width:"260px",padding:"10px"},md:{width:"320px",padding:"14px"},lg:{width:"420px",padding:"18px"}},juiceToast={_config:{},_queue:[],_showing:!1,_theme:"dark",_plugins:[],setup(e={}){this._config=e,this._defaults={...this._defaults,...e},this._registerTypes()},use(e){"function"==typeof e&&this._plugins.push(e)},addType(e,t={}){this._config[e]=t,this._registerTypes()},defineTheme(e,t={}){themes[e]={...themes[e]||{},...t}},setTheme(e){if(this._theme=e,!isBrowser)return;let t=document.getElementById("juice-toast-root");t&&(t.dataset.theme=e)},clear(){this._queue.length=0},destroy(){this.clear(),isBrowser&&document.getElementById("juice-toast-root")?.remove()},_registerTypes(){Object.keys(this._config).forEach(e=>{if("function"==typeof this[e]&&!this[e].__auto)return;let t=t=>this._enqueue(e,t);t.__auto=!0,this[e]=t})},_enqueue(e,t){this._queue.push({type:e,payload:t}),this._showing||this._next()},_next(){if(!this._queue.length){this._showing=!1;return}this._showing=!0;let e=this._queue.shift();this._showToast(e.type,e.payload)},_runPlugins(e){this._plugins.forEach(t=>{try{t(e)}catch(s){this._warn("Plugin error: "+s.message)}})},_normalizeGlass(e){if(!0===e)return 60;if(!1===e||null==e)return 0;let t=Number(e);return Number.isFinite(t)?Math.max(0,Math.min(100,t)):0},_getRoot(e="bottom-right"){if(!isBrowser)return null;let t=document.getElementById(`juice-toast-root-${e}`);if(!t){switch((t=document.createElement("div")).id=`juice-toast-root-${e}`,t.dataset.position=e,t.dataset.theme=this._theme,t.style.position="fixed",t.style.zIndex=9999,e){case"top-left":t.style.top="20px",t.style.left="20px";break;case"top-right":t.style.top="20px",t.style.right="20px";break;case"bottom-left":t.style.bottom="20px",t.style.left="20px";break;case"bottom-right":t.style.bottom="20px",t.style.right="20px";break;case"top-center":t.style.top="20px",t.style.left="50%",t.style.transform="translateX(-50%)";break;case"bottom-center":t.style.bottom="20px",t.style.left="50%",t.style.transform="translateX(-50%)"}document.body.appendChild(t)}return t},_defaults:{duration:2500,maxVisible:3,swipeThreshold:60,glassUI:0,playSound:null,dev:!1,injectCSS:!0,css:null},_warn(e){this._defaults.dev&&"undefined"!=typeof console&&console.warn("[JuiceToast]",e)},_playSound(e){if(!isBrowser)return;let t="string"==typeof e&&e?e:this._defaults.playSound;if(t)try{let s=new Audio(t);s.volume=.6,s.play().catch(()=>{})}catch{}},_showToast(e,t){if(!isBrowser)return;!1!==this._defaults.injectCSS&&injectCSS(this._defaults.css||BASE_CSS);let s=this._config[e]||{},i="object"==typeof t?t:{message:String(t)},a={...s,...i};a.icon=a.icon??a.icon_left_top,a.iconPack=a.iconPack??a.icon_config,a.iconLink=a.iconLink??a.icon_onClick_url,a.iconAnimate=a.iconAnimate??a.icon_onClick_animate,a.position=a.position??a.toast,a.closable=a.closable??a.closeable,a.iconPosition=a.iconPosition||"left",a.compact=!!a.compact;let o=themes[a.theme||this._theme]||{},n=document.createElement("div");n.className="juice-toast";let r=a.animation||"slide-in";if(a.enterAnimation||(n.style.animation=`${r} 0.4s ease forwards`),n.setAttribute("role","alert"),n.setAttribute("aria-live","polite"),n.tabIndex=0,a.size&&sizePreset[a.size]){let l=sizePreset[a.size];l.width&&(n.style.width=l.width),l.padding&&(n.style.padding=l.padding)}let c=null;a.progress&&(a.duration??this._defaults.duration)>0&&((c=document.createElement("div")).className="jt-progress",a.progressColor&&(c.style.background=a.progressColor||"rgba(255,255,255,.7)"),n.appendChild(c));let p=this._normalizeGlass(a.glassUI??this._defaults.glassUI);p>0&&(n.classList.add("jt-glass"),n.style.setProperty("--jt-glass",p)),p||(n.style.background=a.bg||o.bg),n.style.color=a.color||o.color,n.style.border=a.border||o.border,a.compact&&n.classList.add("jt-compact"),(a.glassUI??this._defaults.glassUI)&&n.classList.add("jt-glass"),a.width&&(n.style.width=a.width),a.height&&(n.style.height=a.height);let d=null;if(a.icon){(d=document.createElement("i")).className=["icon",a.iconPack||"",a.icon].join(" ").trim(),a.iconSize&&(d.style.fontSize=a.iconSize),(a.iconLink||a.iconAnimate)&&(d.classList.add("icon-clickable"),d.onclick=e=>{e.stopPropagation(),a.iconAnimate&&(d.classList.remove(a.iconAnimate),d.offsetWidth,d.classList.add(a.iconAnimate)),a.iconLink&&window.open(a.iconLink,"_blank","noopener")});let u=a.iconAnimate??TYPE_ANIMATION[e];u&&(d.classList.add(u),d.addEventListener("click",()=>{d.classList.remove(u),d.offsetWidth,d.classList.add(u)}))}reduceMotion&&(n.classList.remove("pop","bounce","shake","wiggle","pulse","spin"),d?.classList.remove("bounce","shake","wiggle","pulse","spin")),a.message||a.title||this._warn("Toast created without message or title"),a.icon&&!a.iconPack&&this._warn("icon provided without iconPack"),a.duration<0&&this._warn("duration cannot be negative");let h=0,m=0;n.addEventListener("touchstart",e=>{h=e.touches[0].clientX}),n.addEventListener("touchmove",e=>{m=e.touches[0].clientX-h,n.style.transform=`translateX(${m}px)`}),n.addEventListener("touchend",()=>{Math.abs(m)>this._defaults.swipeThreshold?(n.style.transform=`translateX(${m>0?1e3:-1e3}px)`,setTimeout(()=>{n.remove(),this._next()},200)):n.style.transform="",h=m=0});let f=document.createElement("div");f.className="jt-content";let g=a.enterAnimation??"pop";if(g&&!reduceMotion&&n.classList.add(g),a.title){let $=document.createElement("div");$.className="jt-title",$.textContent=a.title,f.appendChild($)}let x=document.createElement("div");if(x.className="jt-message",x.textContent=a.message||"",f.appendChild(x),d&&"top"===a.iconPosition?(n.classList.add("jt-icon-top"),n.appendChild(d),n.appendChild(f)):d&&"right"===a.iconPosition?(n.appendChild(f),n.appendChild(d)):(d&&n.appendChild(d),n.appendChild(f)),Array.isArray(a.actions)&&a.actions.length){let b=document.createElement("div");b.className="jt-actions",a.actions.forEach(e=>{let t=document.createElement("button");t.className="jt-action",t.textContent=e.label,t.onclick=t=>{t.stopPropagation(),e.onClick?.(t),e.closeOnClick&&(n.remove(),this._next())},b.appendChild(t)}),f.appendChild(b)}if(a.closable){let y=document.createElement("span");y.className="juice-toast-close",y.innerHTML="\xd7",y.onclick=()=>{n.remove(),this._next()},n.appendChild(y)}let _=this._getRoot(a.position),j=this._defaults.maxVisible;j&&_.children.length>=j&&_.firstChild.remove(),_.appendChild(n),this._runPlugins({toast:n,cfg:a,type:e,root:_}),requestAnimationFrame(()=>n.classList.add("show"));let w=a.duration??2500;if(0===w)return;let k=Date.now(),v=a.duration??this._defaults.duration,C,E=()=>{if(n.__paused)k=Date.now();else{let e=Date.now();v-=e-k,k=e}v<=0?(n.classList.remove("show"),setTimeout(()=>{n.remove(),this._next()},300)):C=requestAnimationFrame(E),c&&(c.style.transform=`scaleX(${Math.max(0,v/w)})`)};n.addEventListener("mouseenter",()=>n.__paused=!0),n.addEventListener("mouseleave",()=>n.__paused=!1),n.addEventListener("touchstart",()=>n.__paused=!0),n.addEventListener("touchend",()=>n.__paused=!1),requestAnimationFrame(E)}};export default juiceToast;export{juiceToast};