juice-toast 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # 🍹 JuiceToast
2
2
 
3
+ > Lightweight, powerful, modern toast notification library.
4
+ > Zero dependencies. Promise-ready. Plugin system. Priority queue.
3
5
 
4
6
  ![npm download wekkly](https://img.shields.io/npm/dw/juice-toast)
5
7
  ![npm download](https://img.shields.io/npm/dt/juice-toast)
@@ -12,234 +14,406 @@
12
14
  ![deps](https://img.shields.io/badge/dependencies-0-brightgreen)
13
15
  ![ts](https://img.shields.io/badge/types-TypeScript-blue)
14
16
  ![last commit](https://img.shields.io/github/last-commit/KhairyK/juiceToast)
15
-
17
+
16
18
  ---
17
19
 
20
+ ## ❓ What is JuiceToast
21
+
18
22
  **JuiceToast** is a lightweight, flexible, and dependency-free toast notification library for modern web applications.
19
23
  Designed with a **clean API**, **extensive customization**, and **strong backward compatibility**, JuiceToast fits both small projects and enterprise-scale systems.
20
24
 
21
- It supports **ESM**, **dynamic toast types**, **theme management**, **queue handling**, and **legacy API compatibility** out of the box.
25
+ It supports **UMD & ESM**, **dynamic toast types**, **theme management**, **queue handling**, **legacy API compatibility**, and more.
22
26
 
23
27
  ---
24
28
 
25
- ## ✨ Key Features
26
-
27
- - 🚀 Zero dependencies
28
- - 📦 Supports **ESM**
29
- - 🔁 Built-in queue system (one toast displayed at a time)
30
- - 🎨 Theme system (light, dark, and custom themes)
31
- - 🧩 Dynamic toast types (`success`, `error`, etc.)
32
- - Auto-dismiss & sticky toasts
33
- - Closable toasts
34
- - Icon support (position, animation, link)
35
- - 📐 Size presets and manual sizing
36
- - 🧱 Full backward compatibility with legacy APIs
29
+ ## ✨ Features
30
+
31
+ - Lightweight & fast
32
+ - 📦 Zero dependencies
33
+ - 🎨 Built-in themes (dark, light, glass)
34
+ - 🧠 Promise support
35
+ - 🔥 Priority queue (max-heap based)
36
+ - 👆 Swipe to dismiss (mobile friendly)
37
+ - Animated progress bar
38
+ - 🔁 Grouped notifications (auto counter)
39
+ - 🎭 Avatar support
40
+ - 🔊 Sound support
41
+ - 🧩 Plugin system
42
+ - ♿ Accessible (ARIA + focus/hover pause)
37
43
 
38
44
  ---
39
45
 
40
46
  ## 📦 Installation
41
47
 
48
+ ### NPM
49
+ ```bash
50
+ npm install juice-toast
51
+ ```
52
+
42
53
  ### ESM
43
54
  ```js
44
- import juiceToast from "https://npdn.kyrt.my.id/npm/juice-toast@1.3.2dist/juice-toast.esm.js";
55
+ import juiceToast from "https://cdn.jsdelivr.net/npm/juice-toast/dist/juice-toast.esm.js";
56
+ ```
57
+
58
+ ### UMD
59
+ ```html
60
+ <script src="https://cdn.jsdelivr.net/npm/juice-toast/dist/juice-toast.umd.js"></script>
45
61
  ```
46
62
 
47
63
  ---
48
64
 
49
- ## 🚀 Quick Start
65
+ ## 🚀 Basic Usage
50
66
 
51
67
  ```js
52
- juiceToast.setup({
53
- success: {
54
- icon: "check",
55
- theme: "light",
56
- duration: 2000
57
- },
58
- error: {
59
- icon: "x",
60
- bg: "#7f1d1d",
61
- color: "#fff",
62
- closable: true
63
- }
68
+ juiceToast.success("Success!");
69
+ juiceToast.error("Something went wrong!");
70
+ juiceToast.info("Information message");
71
+ juiceToast.warning("Warning message");
72
+ ```
73
+
74
+ ---
75
+
76
+ ## 🧠 Advanced Usage
77
+
78
+ ### With Title
79
+
80
+ ```js
81
+ juiceToast.success({
82
+ title: "Success",
83
+ message: "Data saved successfully!"
64
84
  });
85
+ ```
86
+
87
+ ---
88
+
89
+ ### HTML Content (Sanitized)
65
90
 
66
- juiceToast.success("Operation completed successfully.");
67
- juiceToast.error({
68
- title: "Error",
69
- message: "An unexpected error occurred."
91
+ ```js
92
+ juiceToast.info({
93
+ html: "<b>Hello</b> <i>World</i>"
70
94
  });
71
95
  ```
72
96
 
73
97
  ---
74
98
 
75
- ## 🧠 Core Concepts
99
+ ### With Actions
100
+
101
+ ```js
102
+ juiceToast.info({
103
+ message: "Delete this item?",
104
+ actions: [
105
+ {
106
+ label: "Confirm",
107
+ onClick: () => console.log("Confirmed"),
108
+ closeOnClick: true
109
+ }
110
+ ]
111
+ });
112
+ ```
76
113
 
77
- ### Toast Types
114
+ ---
78
115
 
79
- Toasts are triggered based on **types** registered using `setup()` or `addType()`.
116
+ ### With Avatar
80
117
 
81
118
  ```js
82
- juiceToast.info("Information message");
83
- juiceToast.warning({
84
- message: "Proceed with caution",
85
- duration: 4000
119
+ juiceToast.success({
120
+ title: "New Message",
121
+ message: "You received a new message",
122
+ avatar: "https://example.com/avatar.jpg",
123
+ avatarPosition: "left"
86
124
  });
87
125
  ```
88
126
 
89
- This approach allows a clear separation between **toast configuration** and **runtime usage**.
127
+ Positions:
128
+ - `left`
129
+ - `right`
130
+ - `top`
90
131
 
91
132
  ---
92
133
 
93
- ## ⚙️ API Reference
134
+ ### Progress Bar
135
+
136
+ ```js
137
+ juiceToast.success({
138
+ message: "Uploading...",
139
+ progress: true,
140
+ duration: 5000
141
+ });
142
+ ```
143
+
144
+ ---
94
145
 
95
- ### `setup(config)`
96
- Registers all toast types and their default configuration.
146
+ ### Custom Duration
97
147
 
98
148
  ```js
99
- juiceToast.setup({
100
- success: { bg: "green" },
101
- error: { bg: "red" }
149
+ juiceToast.info({
150
+ message: "Auto close in 10s",
151
+ duration: 10000
102
152
  });
103
153
  ```
104
154
 
105
155
  ---
106
156
 
107
- ### `addType(name, config)`
108
- Adds a new toast type dynamically at runtime.
157
+ ## 🧠 Promise Support
109
158
 
110
159
  ```js
111
- juiceToast.addType("warning", {
112
- bg: "#facc15",
113
- color: "#111"
160
+ const request = fetch("/api/data");
161
+
162
+ juiceToast.promise(request, {
163
+ loading: "Loading...",
164
+ success: "Data loaded!",
165
+ error: "Failed to fetch",
166
+ timeout: 5000,
167
+ timeoutMessage: "Request timeout"
114
168
  });
115
169
  ```
116
170
 
117
171
  ---
118
172
 
119
- ### `defineTheme(name, styles)`
120
- Creates or overrides a theme.
173
+ ## 🎨 Themes
174
+
175
+ ### Change Theme
121
176
 
122
177
  ```js
123
- juiceToast.defineTheme("ocean", {
124
- bg: "#0ea5e9",
125
- color: "#ffffff",
126
- border: "1px solid #0284c7"
178
+ juiceToast.setTheme("light");
179
+ ```
180
+
181
+ Available:
182
+ - `dark`
183
+ - `light`
184
+ - `glass`
185
+
186
+ ---
187
+
188
+ ### Custom Theme
189
+
190
+ ```js
191
+ juiceToast.defineTheme("myTheme", {
192
+ bg: "#111",
193
+ color: "#fff",
194
+ border: "1px solid #333"
127
195
  });
196
+
197
+ juiceToast.setTheme("myTheme");
128
198
  ```
129
199
 
130
200
  ---
131
201
 
132
- ### `setTheme(name)`
133
- Sets the global theme.
202
+ ## 📍 Positions
134
203
 
135
204
  ```js
136
- juiceToast.setTheme("dark");
205
+ juiceToast.success({
206
+ message: "Top Left",
207
+ position: "top-left"
208
+ });
137
209
  ```
138
210
 
211
+ Available:
212
+ - `top-left`
213
+ - `top-right`
214
+ - `bottom-left`
215
+ - `bottom-right`
216
+ - `top-center`
217
+ - `bottom-center`
218
+
139
219
  ---
140
220
 
141
- ### `clear()`
142
- Clears all pending toast queues.
221
+ ## ⚡ Priority System
143
222
 
144
223
  ```js
145
- juiceToast.clear();
224
+ juiceToast.success({
225
+ message: "Urgent message",
226
+ priority: "urgent"
227
+ });
146
228
  ```
147
229
 
230
+ Priority levels:
231
+ - `low`
232
+ - `normal`
233
+ - `high`
234
+ - `urgent`
235
+
236
+ Internally powered by a max-heap queue system.
237
+
148
238
  ---
149
239
 
150
- ### `destroy()`
151
- Removes all queues and the root DOM element.
240
+ ## 🔁 Grouped Toast
152
241
 
153
242
  ```js
154
- juiceToast.destroy();
243
+ juiceToast.info({
244
+ message: "New notification",
245
+ groupId: "notifications"
246
+ });
155
247
  ```
156
248
 
249
+ Same `groupId` = counter increment instead of duplicate toast.
250
+
157
251
  ---
158
252
 
159
- ## 🧾 Toast Payload Interface
253
+ ## 🔊 Sound Support
160
254
 
161
- ```ts
162
- interface ToastPayload {
163
- message?: string;
164
- title?: string;
255
+ ```js
256
+ juiceToast.setup({
257
+ playSound: "/sound.mp3"
258
+ });
259
+ ```
165
260
 
166
- bg?: string;
167
- color?: string;
168
- border?: string;
169
- theme?: string;
261
+ Per toast:
170
262
 
171
- duration?: number; // milliseconds, 0 = sticky
172
- position?: "top" | "center" | "bottom";
173
- toast?: "top" | "center" | "bottom"; // legacy support
263
+ ```js
264
+ juiceToast.success({
265
+ message: "With sound",
266
+ playSound: "/sound.mp3"
267
+ });
268
+ ```
174
269
 
175
- closable?: boolean;
176
- closeable?: boolean; // legacy support
270
+ ---
177
271
 
178
- icon?: string;
179
- iconPack?: string;
180
- iconLink?: string;
181
- iconAnimate?: string;
182
- iconPosition?: "left" | "right" | "top";
272
+ ## 🔄 Undo Support
183
273
 
184
- size?: "sm" | "md" | "lg";
185
- width?: string;
186
- height?: string;
274
+ ```js
275
+ juiceToast.success({
276
+ message: "Item deleted",
277
+ undo: () => console.log("Undo action"),
278
+ undoTimeout: 5000
279
+ });
280
+ ```
187
281
 
188
- animation?: string;
282
+ ---
189
283
 
190
- actions?: {
191
- label: string;
192
- onClick?: (event: MouseEvent) => void;
193
- closeOnClick?: boolean;
194
- }[];
284
+ ## 🧩 Plugin System
195
285
 
196
- [key: string]: any;
286
+ ```js
287
+ juiceToast.use((ctx) => {
288
+ console.log("Toast created:", ctx);
289
+ });
290
+ ```
291
+
292
+ Plugin context:
293
+
294
+ ```js
295
+ {
296
+ toast,
297
+ cfg,
298
+ type,
299
+ root
197
300
  }
198
301
  ```
199
302
 
200
303
  ---
201
304
 
202
- ## 🔄 Backward Compatibility
203
-
204
- JuiceToast automatically maps legacy options to the modern API.
305
+ ## Global Setup
205
306
 
206
- | Legacy Option | Current Option |
207
- |--------------|----------------|
208
- | `toast` | `position` |
209
- | `closeable` | `closable` |
210
- | `icon_left_top` | `icon` |
211
- | `icon_config` | `iconPack` |
212
- | `icon_onClick_url` | `iconLink` |
213
- | `icon_onClick_animate` | `iconAnimate` |
307
+ ```js
308
+ juiceToast.setup({
309
+ duration: 3000,
310
+ maxVisible: 5,
311
+ swipeThreshold: 80,
312
+ glassUI: true,
313
+ dev: true
314
+ });
315
+ ```
214
316
 
215
317
  ---
216
318
 
217
- ## 🎨 Default Themes
319
+ ## 🗑 API
218
320
 
219
321
  ```js
220
- light: {
221
- bg: "#ffffff",
222
- color: "#111",
223
- border: "1px solid #e5e7eb"
224
- }
322
+ juiceToast.clear(); // Clear queue
323
+ juiceToast.destroy(); // Remove all toast roots
324
+ ```
225
325
 
226
- dark: {
227
- bg: "#1f2937",
228
- color: "#ffffff",
229
- border: "1px solid rgba(255,255,255,.08)"
230
- }
326
+ ## Modal
327
+
328
+ ```js
329
+ juiceToast.modal({
330
+ title: "Delete File?",
331
+ message: "Are you sure you want to delete this file?",
332
+ actions: [
333
+ { label: "Cancel" },
334
+ {
335
+ label: "Delete",
336
+ onClick: () => console.log("Deleted!"),
337
+ closeOnClick: true
338
+ }
339
+ ]
340
+ });
231
341
  ```
232
342
 
233
343
  ---
234
344
 
235
- ## 📌 Notes
345
+ # 🆚 Comparison
346
+
347
+ | Feature | 🍹 JuiceToast | 🌟 SweetAlert2 | 🍞 Toastify |
348
+ |----------|---------------|---------------|-------------|
349
+ | Zero Dependency | ✅ | ❌ | ✅ |
350
+ | Lightweight | ✅ | ❌ (larger bundle) | ✅ |
351
+ | Promise Integration | ✅ Built-in | ✅ | ❌ |
352
+ | Priority Queue | ✅ | ❌ | ❌ |
353
+ | Grouped Toast Counter | ✅ | ❌ | ❌ |
354
+ | Plugin System | ✅ | ❌ | ❌ |
355
+ | Swipe to Dismiss | ✅ | ❌ | ❌ |
356
+ | Avatar Support | ✅ | ❌ | ❌ |
357
+ | Custom Themes | ✅ | ✅ | Limited |
358
+ | Modal Support | ✅ | ✅ | ❌ |
359
+ | Designed for Toast Only | ✅ | ❌ (modal-focused) | ✅ |
236
360
 
237
- - Browser-only (DOM required)
238
- - Root element is automatically created: `#juice-toast-root`
239
- - Suitable for frameworks, custom runtimes, etc.
361
+ ### Compared to SweetAlert2
362
+
363
+ SweetAlert2 is powerful and great for modal dialogs, but it's heavier and focused on popups rather than pure toast systems.
364
+
365
+ JuiceToast is:
366
+ - Smaller
367
+ - Toast-focused
368
+ - Queue-driven
369
+ - Plugin-extensible
240
370
 
241
371
  ---
242
372
 
243
- ## 📄 License
373
+ ### Compared to Toastify
374
+
375
+ Toastify is simple and lightweight, but lacks:
376
+
377
+ - Priority queue
378
+ - Promise integration
379
+ - Grouping system
380
+ - Plugin system
381
+ - Advanced control
382
+
383
+ JuiceToast provides more advanced architecture while staying dependency-free.
384
+
385
+ ---
386
+
387
+ # ♿ Accessibility
388
+
389
+ - `role="status"`
390
+ - Hover pause
391
+ - Focus pause
392
+ - Reduced motion support
393
+
394
+ ---
395
+
396
+ # 📄 License
397
+
398
+ MIT License (C) 2026 OpenDN Foundation
399
+
400
+ ---
401
+
402
+ # ❤️ Contributing
403
+
404
+ Pull requests are welcome.
405
+ If you find bugs, open an issue.
406
+
407
+ ---
408
+
409
+ # 🔥 Why JuiceToast?
410
+
411
+ Because simple toast libraries are boring.
244
412
 
245
- MIT License © OpenDN Foundation
413
+ JuiceToast gives you:
414
+ - Real queue system
415
+ - Promise integration
416
+ - Plugins
417
+ - Advanced control
418
+ - Performance focus
419
+ - Clean modern UI
@@ -0,0 +1,150 @@
1
+ export type ToastPosition =
2
+ | "top-left"
3
+ | "top-right"
4
+ | "bottom-left"
5
+ | "bottom-right"
6
+ | "top-center"
7
+ | "bottom-center";
8
+
9
+ export type ToastPriority = "low" | "normal" | "high" | "urgent";
10
+
11
+ export type ToastSize = "sm" | "md" | "lg";
12
+
13
+ export type ToastTheme = string;
14
+
15
+ export interface ToastAction {
16
+ label?: string;
17
+ onClick?: (event: Event) => void;
18
+ closeOnClick?: boolean;
19
+ primary?: boolean;
20
+ }
21
+
22
+ export interface ToastOptions {
23
+ id?: string;
24
+ title?: string;
25
+ message?: string;
26
+ html?: string;
27
+
28
+ duration?: number;
29
+ position?: ToastPosition;
30
+ priority?: ToastPriority;
31
+ size?: ToastSize;
32
+
33
+ theme?: ToastTheme;
34
+
35
+ bg?: string;
36
+ color?: string;
37
+ border?: string;
38
+
39
+ icon?: string;
40
+ iconPack?: string;
41
+ iconSize?: string;
42
+ iconAnim?: string;
43
+ iconPosition?: "left" | "right" | "top";
44
+ iconLink?: string;
45
+ iconAnimate?: string;
46
+
47
+ avatar?: boolean | string;
48
+ avatarSrc?: string;
49
+ avatarAlt?: string;
50
+ avatarPosition?: "left" | "right" | "top";
51
+ avatarSpacing?: string;
52
+ avatarLazy?: boolean;
53
+
54
+ progress?: boolean;
55
+ progressColor?: string;
56
+
57
+ closable?: boolean;
58
+ closeable?: boolean;
59
+
60
+ actions?: ToastAction[];
61
+
62
+ undo?: () => void;
63
+ undoTimeout?: number;
64
+
65
+ groupId?: string;
66
+ dedupeKey?: string;
67
+
68
+ playSound?: string | null;
69
+ }
70
+
71
+ export interface PromiseStates<T = any> {
72
+ loading?: ToastOptions | string;
73
+ success?: ToastOptions | string | ((value: T) => string);
74
+ error?: ToastOptions | string | ((error: any) => string);
75
+
76
+ timeout?: number;
77
+ timeoutMessage?: string;
78
+ cancelMessage?: string;
79
+ }
80
+
81
+ export interface ModalOptions {
82
+ title?: string;
83
+ message?: string;
84
+ html?: string;
85
+
86
+ block?: boolean;
87
+ blur?: boolean;
88
+ closeOnOverlay?: boolean;
89
+ closable?: boolean;
90
+
91
+ animation?: "scale" | "slide" | "fade";
92
+ theme?: ToastTheme;
93
+
94
+ actions?: ToastAction[];
95
+ }
96
+
97
+ export interface JuiceToastDefaults {
98
+ duration?: number;
99
+ maxVisible?: number;
100
+ swipeThreshold?: number;
101
+ glassUI?: number;
102
+ playSound?: string | null;
103
+ dev?: boolean;
104
+ injectCSS?: boolean;
105
+ css?: string | null;
106
+ }
107
+
108
+ export interface JuiceToastInstance {
109
+ setup(config?: Record<string, ToastOptions> & JuiceToastDefaults): void;
110
+
111
+ use(plugin: (context: {
112
+ toast: HTMLElement;
113
+ cfg: ToastOptions;
114
+ type: string;
115
+ root: HTMLElement;
116
+ }) => void): void;
117
+
118
+ addType(name: string, config?: ToastOptions): void;
119
+
120
+ defineTheme(name: string, styles?: {
121
+ bg?: string;
122
+ color?: string;
123
+ border?: string;
124
+ }): void;
125
+
126
+ setTheme(name: string): void;
127
+
128
+ clear(): void;
129
+ destroy(): void;
130
+
131
+ promise<T = any>(
132
+ promise: Promise<T>,
133
+ states?: PromiseStates<T>
134
+ ): { cancel: () => void };
135
+
136
+ modal(options?: ModalOptions): { close: () => void };
137
+
138
+ success(options?: ToastOptions | string): void;
139
+ error(options?: ToastOptions | string): void;
140
+ info(options?: ToastOptions | string): void;
141
+ warning(options?: ToastOptions | string): void;
142
+ loading(options?: ToastOptions | string): void;
143
+
144
+ [customType: string]: any;
145
+ }
146
+
147
+ declare const juiceToast: JuiceToastInstance;
148
+
149
+ export default juiceToast;
150
+ export { juiceToast };