@tsirosgeorge/toastnotification 5.3.2 → 5.4.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/Readme.md CHANGED
@@ -8,7 +8,7 @@ A lightweight, customizable, and dependency-free toast notification system writt
8
8
 
9
9
  ## 📦 Include package via cdn
10
10
  ```html
11
- <script src="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.2/toast.min.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.4.0/toast.min.js"></script>
12
12
  ```
13
13
 
14
14
  ## 📦 Include package via npm
@@ -41,8 +41,12 @@ toast('Data saved successfully!', {
41
41
  ```javascript
42
42
  toast.success('Saved!');
43
43
  toast.error('Failed!');
44
+ toast.warning('Careful!');
45
+ toast.info('Heads up.');
44
46
  ```
45
47
 
48
+ Each helper returns the toast element, so you can hand it to `toast.update()` later.
49
+
46
50
  ### ⚠️ Confirm (SweetAlert-like)
47
51
  - Promise API
48
52
  ```javascript
@@ -75,13 +79,19 @@ const name = await toast.confirm('Enter your name:', {
75
79
  confirmText: 'Submit',
76
80
  cancelText: 'Cancel',
77
81
  });
78
- if (name) {
79
- console.log('Hello', name);
82
+ if (name !== null) {
83
+ console.log('Hello', name); // may be '' if they submitted an empty field
80
84
  } else {
81
85
  console.log('Cancelled');
82
86
  }
83
87
  ```
84
88
 
89
+ > **Resolution contract.** Without `input`, `toast.confirm()` resolves `true` on confirm and
90
+ > `false` on cancel. With `input`, it resolves the field's **string** value on confirm — which
91
+ > may be `''` — and `null` on cancel. Check against `null`, not truthiness, or an empty
92
+ > submission reads as a cancel. Cancelling, clicking the backdrop and the `(×)` button all
93
+ > resolve the promise.
94
+
85
95
  - Callback API
86
96
  ```javascript
87
97
  toast('Are you sure?', {
@@ -155,4 +165,4 @@ This software is provided "as is", without warranty of any kind. Use at your own
155
165
 
156
166
  ---
157
167
 
158
- **Note:** This package is marked as `UNLICENSED` in `package.json` to reflect these restrictions.
168
+ **Note:** See the [LICENSE](LICENSE) file included in this package for full terms and conditions.
package/package.json CHANGED
@@ -1,32 +1,40 @@
1
1
  {
2
2
  "name": "@tsirosgeorge/toastnotification",
3
- "version": "5.3.2",
3
+ "version": "5.4.0",
4
4
  "description": "a toast notification plugin",
5
5
  "main": "toast.min.js",
6
6
  "module": "toast.module.js",
7
7
  "exports": {
8
8
  ".": {
9
+ "types": "./toast.d.ts",
9
10
  "import": "./toast.module.js",
10
11
  "require": "./toast.min.js"
11
- }
12
+ },
13
+ "./assets/css/toast.css": "./assets/css/toast.css",
14
+ "./assets/css/toast.min.css": "./assets/css/toast.min.css",
15
+ "./package.json": "./package.json"
12
16
  },
13
17
  "scripts": {
14
- "test": "echo \"Error: no test specified\" && exit 1",
15
- "build:css": "cleancss -o assets/css/toast.min.css assets/css/toast.css",
16
- "build:js": "terser toast.js --compress --mangle --output toast.min.js",
17
- "build": "npm run build:css && npm run build:js",
18
- "prepublishOnly": "npm run build",
19
- "release": "npm version && git push origin main --follow-tags && npm publish --access public"
18
+ "test": "tsc --noEmit --strict --skipLibCheck toast.d.ts",
19
+ "sync:version": "node scripts/sync-version.mjs",
20
+ "build:module": "node scripts/build-module.mjs",
21
+ "build:css": "cleancss -o assets/css/toast.min.css assets/css/toast.css",
22
+ "build:js": "terser toast.js --compress --mangle --output toast.min.js",
23
+ "build": "npm run sync:version && npm run build:module && npm run build:css && npm run build:js",
24
+ "prepublishOnly": "npm run build",
25
+ "release": "npm version ${V:-patch} && npm publish --access public && git push origin main --follow-tags"
20
26
  },
21
27
  "files": [
22
28
  "toast.js",
23
29
  "toast.min.js",
24
30
  "toast.module.js",
31
+ "toast.d.ts",
25
32
  "assets/css/toast.css",
26
33
  "assets/css/toast.min.css",
27
34
  "assets/img/",
35
+ "!assets/img/old/",
28
36
  "LICENSE",
29
- "README.md"
37
+ "Readme.md"
30
38
  ],
31
39
  "repository": {
32
40
  "type": "git",
@@ -49,6 +57,14 @@
49
57
  "homepage": "https://github.com/tsirosgeorge/toast-notification#readme",
50
58
  "devDependencies": {
51
59
  "clean-css-cli": "^5.6.3",
52
- "terser": "^5.40.0"
53
- }
54
- }
60
+ "terser": "^5.40.0",
61
+ "typescript": "^5.9.3"
62
+ },
63
+ "types": "toast.d.ts",
64
+ "sideEffects": [
65
+ "./toast.js",
66
+ "./toast.min.js",
67
+ "./toast.module.js",
68
+ "*.css"
69
+ ]
70
+ }
package/toast.d.ts ADDED
@@ -0,0 +1,89 @@
1
+ export type ToastType = 'info' | 'success' | 'warning' | 'error';
2
+
3
+ export type ToastPosition =
4
+ | 'top-left' | 'top-right' | 'top-center'
5
+ | 'bottom-left' | 'bottom-right' | 'bottom-center';
6
+
7
+ export type ToastAnimation =
8
+ | 'slide-top' | 'slide-bottom' | 'slide-left' | 'slide-right'
9
+ | 'zoom-in' | 'zoom-out' | 'flip';
10
+
11
+ export type ToastInput = 'text' | 'email' | 'password' | 'number' | 'textarea' | false;
12
+
13
+ /** Value handed to a confirm dialog's callbacks and promise. */
14
+ export type ConfirmResult = boolean | string | null;
15
+
16
+ export interface ToastElement extends HTMLDivElement {
17
+ /** Present in confirm mode: resolves when the user confirms, cancels or dismisses. */
18
+ result?: Promise<ConfirmResult>;
19
+ }
20
+
21
+ export interface ToastOptions {
22
+ position?: ToastPosition;
23
+ animation?: ToastAnimation;
24
+ type?: ToastType;
25
+ /** Auto-dismiss delay in ms. `0` keeps the toast until it is closed. */
26
+ duration?: number;
27
+ /** Emoji or text used instead of the bundled animated icon. */
28
+ icon?: string | null;
29
+ showLoader?: boolean;
30
+ /** `'confirm'` (alias `'swal'`) renders a modal dialog instead of a toast. */
31
+ mode?: 'alert' | 'confirm' | 'swal';
32
+ dismissOnClick?: boolean;
33
+ onClick?: (el: ToastElement) => void;
34
+ onShow?: (el: ToastElement) => void;
35
+ onDismiss?: (el: ToastElement) => void;
36
+ }
37
+
38
+ export interface ConfirmOptions extends ToastOptions {
39
+ title?: string | null;
40
+ confirmText?: string;
41
+ cancelText?: string;
42
+ input?: ToastInput;
43
+ inputPlaceholder?: string;
44
+ inputValue?: string;
45
+ confirmButtonBg?: string | null;
46
+ confirmButtonColor?: string | null;
47
+ cancelButtonBg?: string | null;
48
+ cancelButtonColor?: string | null;
49
+ useOverlay?: boolean;
50
+ closeOnOverlayClick?: boolean;
51
+ showClose?: boolean;
52
+ /** Receives the input's value when `input` is set, otherwise `true`. */
53
+ onConfirm?: (value: string | true, el: ToastElement) => void;
54
+ onCancel?: (el: ToastElement) => void;
55
+ onResult?: (result: ConfirmResult, el: ToastElement) => void;
56
+ }
57
+
58
+ export interface LoadingHandle {
59
+ update(message: string, options?: ToastOptions): void;
60
+ close(): void;
61
+ }
62
+
63
+ export interface Toast {
64
+ (message: string, options?: ToastOptions | ConfirmOptions): ToastElement;
65
+ success(message: string, options?: ToastOptions): ToastElement;
66
+ error(message: string, options?: ToastOptions): ToastElement;
67
+ warning(message: string, options?: ToastOptions): ToastElement;
68
+ info(message: string, options?: ToastOptions): ToastElement;
69
+ update(el: ToastElement, message: string, options?: ToastOptions): void;
70
+ loading(message: string, options?: ToastOptions): LoadingHandle;
71
+ /**
72
+ * Without `input`: resolves `true` on confirm, `false` on cancel/dismiss.
73
+ * With `input`: resolves the input's string value on confirm (possibly `''`),
74
+ * and `null` on cancel/dismiss — so an empty submission is not read as a cancel.
75
+ */
76
+ confirm(message: string, options?: ConfirmOptions): Promise<ConfirmResult>;
77
+ }
78
+
79
+ declare const toast: Toast;
80
+ export default toast;
81
+ export { toast };
82
+
83
+ declare global {
84
+ interface Window {
85
+ toast: Toast;
86
+ /** Set before loading the script to skip the CDN stylesheet injection. */
87
+ TS_TOAST_NO_CSS?: boolean;
88
+ }
89
+ }
package/toast.js CHANGED
@@ -1,10 +1,27 @@
1
1
  "use strict";
2
2
 
3
- // Dynamically load the external CSS file
4
- const link = document.createElement("link");
5
- link.rel = "stylesheet";
6
- link.href = "https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/css/toast.min.css";
7
- document.head.appendChild(link);
3
+ // Single source of truth for the CDN this build points at.
4
+ // `npm run sync:version` rewrites it from package.json, so it can never go stale.
5
+ const TS_TOAST_VERSION = "5.4.0";
6
+ // Point this at your own copy of assets/ to self-host the CSS and icons
7
+ // (useful offline, behind a strict CSP, or when you don't want a CDN dependency):
8
+ // window.TS_TOAST_ASSET_BASE = '/vendor/toastnotification';
9
+ const TS_TOAST_CDN = (typeof window !== 'undefined' && window.TS_TOAST_ASSET_BASE)
10
+ ? String(window.TS_TOAST_ASSET_BASE).replace(/\/+$/, '')
11
+ : `https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@${TS_TOAST_VERSION}`;
12
+
13
+ // Load the stylesheet from the CDN, unless the page opted out by importing it itself
14
+ // (set window.TS_TOAST_NO_CSS = true before loading, or ship assets/css/toast.css yourself).
15
+ (function loadStylesheet() {
16
+ const LINK_ID = 'ts-toast-stylesheet';
17
+ if (typeof window !== 'undefined' && window.TS_TOAST_NO_CSS) return;
18
+ if (document.getElementById(LINK_ID)) return;
19
+ const link = document.createElement("link");
20
+ link.id = LINK_ID;
21
+ link.rel = "stylesheet";
22
+ link.href = `${TS_TOAST_CDN}/assets/css/toast.min.css`;
23
+ document.head.appendChild(link);
24
+ })();
8
25
 
9
26
  // Inject minimal styles for confirm actions and overlay (kept tiny to avoid breaking existing CSS)
10
27
  (function injectInlineStyles() {
@@ -147,23 +164,16 @@ const toast = function (message, options = {}) {
147
164
  iconElement.textContent = icon;
148
165
  } else {
149
166
  const img = document.createElement('img');
150
- img.src = '';
167
+ img.alt = '';
168
+ img.setAttribute('aria-hidden', 'true');
151
169
  img.style.width = '30px';
152
170
  img.style.height = '30px';
153
171
  img.style.objectFit = 'contain';
154
172
 
155
- const baseUrl = 'https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/';
156
- const timestamp = new Date().getTime(); // 🔄 force refresh
157
-
158
- if (type === 'success') {
159
- img.src = `${baseUrl}success.gif?t=${timestamp}`;
160
- } else if (type === 'error') {
161
- img.src = `${baseUrl}error.gif?t=${timestamp}`;
162
- } else if (type === 'info') {
163
- img.src = `${baseUrl}info.gif?t=${timestamp}`;
164
- } else if (type === 'warning') {
165
- img.src = `${baseUrl}warning.gif?t=${timestamp}`;
166
- }
173
+ // No cache-buster: these GIFs are immutable per version, so let the
174
+ // browser and the CDN actually cache them.
175
+ const iconFile = { success: 'success.gif', error: 'error.gif', info: 'info.gif', warning: 'warning.gif' }[type];
176
+ if (iconFile) img.src = `${TS_TOAST_CDN}/assets/img/${iconFile}`;
167
177
 
168
178
  iconElement.appendChild(img);
169
179
  }
@@ -210,6 +220,9 @@ const toast = function (message, options = {}) {
210
220
  // Actions (for confirm mode)
211
221
  let actionsContainer = null;
212
222
  let resultResolver = null;
223
+ // Assigned in confirm mode; the overlay and (x) handlers below call it so that
224
+ // *every* way of dismissing the dialog settles the promise and the callbacks.
225
+ let resolveAndClose = null;
213
226
  if (isConfirm) {
214
227
  actionsContainer = document.createElement('div');
215
228
  actionsContainer.className = 'ts-toast-actions';
@@ -235,11 +248,19 @@ const toast = function (message, options = {}) {
235
248
  // Create a Promise that resolves on user choice; expose via property
236
249
  toastElement.result = new Promise((resolve) => { resultResolver = resolve; });
237
250
 
238
- const resolveAndClose = (value) => {
239
- const result = (value && inputElement !== null) ? inputElement.value : value;
251
+ let settled = false;
252
+ resolveAndClose = (confirmed) => {
253
+ if (settled) return; // a button click and a backdrop click can race
254
+ settled = true;
255
+ // With an input, confirming always yields a string (possibly '') and
256
+ // cancelling yields null, so an empty submission stays distinguishable
257
+ // from a cancel. Without an input the contract is still true/false.
258
+ const result = confirmed
259
+ ? (inputElement ? inputElement.value : true)
260
+ : (inputElement ? null : false);
240
261
  if (resultResolver) resultResolver(result);
241
- if (value && typeof onConfirm === 'function') onConfirm((inputElement !== null) ? inputElement.value : value, toastElement);
242
- if (!value && typeof onCancel === 'function') onCancel(toastElement);
262
+ if (confirmed && typeof onConfirm === 'function') onConfirm(result, toastElement);
263
+ if (!confirmed && typeof onCancel === 'function') onCancel(toastElement);
243
264
  if (typeof onResult === 'function') onResult(result, toastElement);
244
265
  // Use the same slide+fade removal as alerts
245
266
  removeWithAnimation(toastElement, () => {
@@ -265,7 +286,9 @@ const toast = function (message, options = {}) {
265
286
  let overlay = null;
266
287
  if (isConfirm && useOverlay) {
267
288
  overlay = document.createElement('div');
268
- overlay.className = `ts-toast-overlay ${position}`;
289
+ // A modal centres by default. The `position` default of 'top-right' is meant
290
+ // for toasts; applying it here parked the dialog in a corner of the backdrop.
291
+ overlay.className = 'ts-toast-overlay' + (options.position ? ` ${position}` : '');
269
292
  document.body.appendChild(overlay);
270
293
  overlay.appendChild(toastElement);
271
294
  if (showClose) {
@@ -275,28 +298,17 @@ const toast = function (message, options = {}) {
275
298
  closeBtn.innerHTML = '&times;';
276
299
  closeBtn.addEventListener('click', (e) => {
277
300
  e.stopPropagation();
278
- removeWithAnimation(toastElement, () => {
279
- if (onDismiss && typeof onDismiss === 'function') onDismiss(toastElement);
280
- if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
281
- });
301
+ // Dismissing via (x) is a cancel, so it has to settle like one.
302
+ resolveAndClose(false);
282
303
  });
283
304
  toastElement.appendChild(closeBtn);
284
305
  }
285
306
  if (closeOnOverlayClick) {
286
307
  overlay.addEventListener('click', (e) => {
287
- if (e.target === overlay) {
288
- // Overlay background click -> cancel
289
- if (toastElement.result) {
290
- // let the confirm logic close and cleanup
291
- if (typeof resultResolver === 'function') {
292
- resultResolver(false);
293
- }
294
- }
295
- removeWithAnimation(toastElement, () => {
296
- if (onDismiss && typeof onDismiss === 'function') onDismiss(toastElement);
297
- if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
298
- });
299
- }
308
+ // Backdrop click is a cancel: settle the promise and onCancel/onResult,
309
+ // then close. Previously this resolved only the internal el.result,
310
+ // so `await toast.confirm(...)` hung forever.
311
+ if (e.target === overlay) resolveAndClose(false);
300
312
  });
301
313
  }
302
314
  } else {
@@ -384,12 +396,21 @@ const toast = function (message, options = {}) {
384
396
  return toastElement;
385
397
  };
386
398
 
399
+ // Shorthands return the toast element so it can be passed to toast.update().
387
400
  toast.success = function (message, options) {
388
- toast(message, { ...options, type: 'success' });
401
+ return toast(message, { ...options, type: 'success' });
389
402
  };
390
403
 
391
404
  toast.error = function (message, options) {
392
- toast(message, { ...options, type: 'error' });
405
+ return toast(message, { ...options, type: 'error' });
406
+ };
407
+
408
+ toast.warning = function (message, options) {
409
+ return toast(message, { ...options, type: 'warning' });
410
+ };
411
+
412
+ toast.info = function (message, options) {
413
+ return toast(message, { ...options, type: 'info' });
393
414
  };
394
415
 
395
416
  // Update toast function to handle removal with animation
@@ -399,7 +420,6 @@ const toast = function (message, options = {}) {
399
420
  icon = null,
400
421
  showLoader = false,
401
422
  duration = 3000, // Default duration (in ms)
402
- position = 'top-right', // Default position,
403
423
  onClick = null, // Custom onClick event listener
404
424
  onShow = null, // Custom onShow event listener
405
425
  onDismiss = null // Custom onDismiss event listener
@@ -410,10 +430,13 @@ const toast = function (message, options = {}) {
410
430
  const oldIcon = toastElement.querySelector('.ts-toast-icon');
411
431
  if (oldLoader) oldLoader.remove();
412
432
 
413
- // Update toast class and message
433
+ // Update toast class and message. Swap only the type modifier: overwriting
434
+ // className dropped ts-toast-show (so the toast faded out), dropped
435
+ // ts-toast-confirm (so confirm dialogs lost their layout), and leaked the
436
+ // position onto the toast instead of the container.
414
437
  if (type) {
415
- // keep ts- prefix consistent
416
- toastElement.className = `ts-toast ts-toast-${type} show ${position}`;
438
+ ['success', 'error', 'info', 'warning'].forEach((t) => toastElement.classList.remove(`ts-toast-${t}`));
439
+ toastElement.classList.add('ts-toast', `ts-toast-${type}`, 'ts-toast-show');
417
440
  }
418
441
  const toastBody = toastElement.querySelector('.ts-toast-body');
419
442
  if (toastBody) {
@@ -433,25 +456,21 @@ const toast = function (message, options = {}) {
433
456
  iconElement.textContent = icon;
434
457
  } else {
435
458
  const img = document.createElement('img');
459
+ img.alt = '';
460
+ img.setAttribute('aria-hidden', 'true');
436
461
  img.style.width = '30px';
437
462
  img.style.height = '30px';
438
463
  img.style.objectFit = 'contain';
439
464
 
440
- if (type === 'success') {
441
- img.src = 'https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/success.gif';
442
- } else if (type === 'error') {
443
- img.src = 'https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/error.gif';
444
- } else if (type === 'info') {
445
- img.src = 'https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/info.gif';
446
- } else if (type === 'warning') {
447
- img.src = 'https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/warning.gif';
448
- }
465
+ const iconFile = { success: 'success.gif', error: 'error.gif', info: 'info.gif', warning: 'warning.gif' }[type];
466
+ if (iconFile) img.src = `${TS_TOAST_CDN}/assets/img/${iconFile}`;
449
467
 
450
468
  iconElement.appendChild(img);
451
469
  }
452
470
 
453
- // Append the new icon immediately
454
- toastElement.appendChild(iconElement);
471
+ // Append the new icon immediately (inside the content row for confirm dialogs)
472
+ const contentRow = toastElement.querySelector('.ts-toast-content');
473
+ (contentRow || toastElement).appendChild(iconElement);
455
474
 
456
475
  // Handle loader if requested
457
476
  if (showLoader) {
@@ -569,7 +588,9 @@ if (typeof window !== 'undefined') {
569
588
  window.toast = toast;
570
589
  }
571
590
 
591
+ /* build:cjs-start (stripped when generating toast.module.js) */
572
592
  // CommonJS export for Node/bundlers (safe no-op in browsers)
573
593
  if (typeof module !== 'undefined' && module.exports) {
574
594
  module.exports = toast;
575
- }
595
+ }
596
+ /* build:cjs-end */
package/toast.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";const link=document.createElement("link");link.rel="stylesheet",link.href="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/css/toast.min.css",document.head.appendChild(link),function(){const t="ts-toast-inline-extras";if(document.getElementById(t))return;const e=document.createElement("style");e.id=t,e.textContent="\n /* Ensure center positions exist even if external CSS lacks them */\n .ts-toast-container.top-center { top: 1rem; left: 50%; transform: translateX(-50%); align-items: center; }\n .ts-toast-container.bottom-center { bottom: 1rem; left: 50%; transform: translateX(-50%); align-items: center; }\n .ts-toast-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 2147483646; }\n .ts-toast.ts-toast-confirm { max-width: min(92vw, 440px); width: max(320px, 60%); flex-direction: column; gap: 12px; padding: 16px 20px; background: var(--toast-bg, #fff); color: var(--toast-color, #000); border: 1px solid var(--toast-border, #e5e7eb); border-radius: 12px; box-shadow: var(--toast-shadow, 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)); text-align: center; }\n .ts-toast.ts-toast-confirm .ts-toast-content { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; }\n .ts-toast-actions { display: flex; gap: 10px; justify-content: center; margin-top: 12px; }\n .ts-toast-btn { appearance: none; border: 0; padding: 8px 12px; border-radius: 8px; font-weight: 600; cursor: pointer; }\n .ts-toast-btn.cancel { background: #e9ecef; color: #1f2937; }\n .ts-toast-btn.confirm { background: #3b82f6; color: #fff; }\n .ts-toast.ts-toast-error .ts-toast-btn.confirm,\n .ts-toast.ts-toast-warning .ts-toast-btn.confirm { background: #ef4444; color: #fff; }\n .ts-toast.ts-toast-confirm .ts-toast-title { font-weight: 700; font-size: 1.05rem; margin-top: 4px; }\n .ts-toast.ts-toast-confirm .ts-toast-close { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; border-radius: 999px; border: 0; background: transparent; color: #6b7280; font-size: 20px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }\n .ts-toast.ts-toast-confirm .ts-toast-close:hover { background: rgba(0,0,0,0.06); }\n .ts-toast.ts-toast-confirm .ts-toast-icon { width: 64px; height: 64px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; }\n .ts-toast.ts-toast-confirm .ts-toast-icon img { width: 36px; height: 36px; }\n .ts-toast.ts-toast-confirm.ts-toast-success .ts-toast-icon { background: #dcfce7; }\n .ts-toast.ts-toast-confirm.ts-toast-info .ts-toast-icon { background: #dbeafe; }\n .ts-toast.ts-toast-confirm.ts-toast-warning .ts-toast-icon { background: #fef3c7; }\n .ts-toast.ts-toast-confirm.ts-toast-error .ts-toast-icon { background: #fee2e2; }\n ",document.head.appendChild(e)}();const toast=function(t,e={}){const{position:o="top-right",animation:s="slide-right",type:n="info",duration:a=3e3,icon:i=null,showLoader:l=!1,mode:r="alert",title:c=null,confirmText:d="Yes",cancelText:m="No",input:u=!1,inputPlaceholder:p="",inputValue:f="",confirmButtonBg:g=null,confirmButtonColor:h=null,cancelButtonBg:y=null,cancelButtonColor:x=null,onConfirm:v=null,onCancel:b=null,onResult:C=null,useOverlay:w=!0,closeOnOverlayClick:L=!0,showClose:E=!1,dismissOnClick:N=!0,onClick:k=null,onShow:T=null,onDismiss:$=null}=e,j="confirm"===r||"swal"===r,_="string"==typeof e.animation&&e.animation.trim()?{"slide-top":"ts-toast-slide-top","slide-bottom":"ts-toast-slide-bottom","slide-left":"ts-toast-slide-left","slide-right":"ts-toast-slide-right","zoom-in":"ts-toast-zoom-in","zoom-out":"ts-toast-zoom-out",flip:"ts-toast-flip"}[R=e.animation.trim()]||R:j?"ts-toast-zoom-in":o.startsWith("top")?"ts-toast-slide-top":o.startsWith("bottom")?"ts-toast-slide-bottom":o.endsWith("left")?"ts-toast-slide-left":"ts-toast-slide-right";var R;const B=(t,e)=>{const o=t.dataset&&t.dataset.anim?t.dataset.anim:t.style.animation||"";let s="";o.includes("ts-toast-slide-top")?s="translateY(-100%)":o.includes("ts-toast-slide-bottom")?s="translateY(100%)":(o.includes("ts-toast-slide-left")||o.includes("ts-toast-slide-right"))&&(s="translateX(100%)"),t.classList.add("ts-toast-slide-out"),t.classList.remove("ts-toast-show"),t.style.animation="",s&&(t.style.transform=s),t.style.opacity="0",setTimeout((()=>{t.classList.remove("ts-toast-slide-out"),t.parentNode&&t.parentNode.removeChild(t),"function"==typeof e&&e()}),500)},S=document.createElement("div");S.className=`ts-toast ts-toast-${n}${j?" ts-toast-confirm":""}`,S.dataset.anim=_,S.style.animation=`${_} 0.5s ease`,j||(S.style.flexDirection="row-reverse",S.style.justifyContent="flex-end");const z=document.createElement("span");if(z.className="ts-toast-icon",z.style.display="flex",i)z.textContent=i;else{const t=document.createElement("img");t.src="",t.style.width="30px",t.style.height="30px",t.style.objectFit="contain";const e="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/",o=(new Date).getTime();"success"===n?t.src=`${e}success.gif?t=${o}`:"error"===n?t.src=`${e}error.gif?t=${o}`:"info"===n?t.src=`${e}info.gif?t=${o}`:"warning"===n&&(t.src=`${e}warning.gif?t=${o}`),z.appendChild(t)}const q=document.createElement("div");q.className="ts-toast-body",q.innerHTML=t;let P=null;if(j){if(P=document.createElement("div"),P.className="ts-toast-content",P.appendChild(z),c){const t=document.createElement("div");t.className="ts-toast-title",t.textContent=c,P.appendChild(t)}P.appendChild(q),S.appendChild(P)}else S.appendChild(q);let O=null;j&&u&&("textarea"===u?(O=document.createElement("textarea"),O.rows=3):(O=document.createElement("input"),O.type="text"===u||"email"===u||"password"===u||"number"===u?u:"text"),O.className="ts-toast-input",O.placeholder=p,O.value=f,S.appendChild(O));let X=null,D=null;if(j){X=document.createElement("div"),X.className="ts-toast-actions";const t=document.createElement("button");t.className="ts-toast-btn cancel",t.textContent=m;const e=document.createElement("button");e.className="ts-toast-btn confirm",e.textContent=d,y&&(t.style.background=y),x&&(t.style.color=x),g&&(e.style.background=g),h&&(e.style.color=h),X.appendChild(t),X.appendChild(e),S.appendChild(X),S.result=new Promise((t=>{D=t}));const o=t=>{const e=t&&null!==O?O.value:t;D&&D(e),t&&"function"==typeof v&&v(null!==O?O.value:t,S),t||"function"!=typeof b||b(S),"function"==typeof C&&C(e,S),B(S,(()=>{$&&"function"==typeof $&&$(S),F&&F.parentNode&&F.parentNode.removeChild(F)}))};t.addEventListener("click",(t=>{t.stopPropagation(),o(!1)})),e.addEventListener("click",(t=>{t.stopPropagation(),o(!0)}))}let M=null;l&&(M=document.createElement("div"),M.className="ts-toast-loader",S.appendChild(M));let F=null;if(j&&w){if(F=document.createElement("div"),F.className=`ts-toast-overlay ${o}`,document.body.appendChild(F),F.appendChild(S),E){const t=document.createElement("button");t.className="ts-toast-close",t.setAttribute("aria-label","Close"),t.innerHTML="&times;",t.addEventListener("click",(t=>{t.stopPropagation(),B(S,(()=>{$&&"function"==typeof $&&$(S),F&&F.parentNode&&F.parentNode.removeChild(F)}))})),S.appendChild(t)}L&&F.addEventListener("click",(t=>{t.target===F&&(S.result&&"function"==typeof D&&D(!1),B(S,(()=>{$&&"function"==typeof $&&$(S),F&&F.parentNode&&F.parentNode.removeChild(F)})))}))}else{let t=document.querySelector(`.ts-toast-container.${o}`);t||(t=document.createElement("div"),t.className=`ts-toast-container ${o}`,document.body.appendChild(t)),t.appendChild(S)}if(T&&"function"==typeof T&&T(S),setTimeout((()=>{S.classList.add("ts-toast-show")}),100),l&&M&&setTimeout((()=>{S._managedByLoading||(M.classList.add("done"),M.remove(),S.contains(z)||(j&&P?P.appendChild(z):S.appendChild(z)))}),2e3),l||j||S.contains(z)||S.appendChild(z),!j&&a>0){const t=setTimeout((()=>{B(S,(()=>{$&&"function"==typeof $&&$(S)}))}),a);S._autoRemove=t}if(!j&&N&&S.addEventListener("click",(()=>{S._autoRemove&&clearTimeout(S._autoRemove),B(S,(()=>{k&&"function"==typeof k&&k(S),$&&"function"==typeof $&&$(S)}))})),!j){let t=0,e=0;S.addEventListener("touchstart",(e=>{t=e.changedTouches[0].screenX})),S.addEventListener("touchend",(o=>{e=o.changedTouches[0].screenX,Math.abs(t-e)>50&&(S._autoRemove&&clearTimeout(S._autoRemove),B(S,(()=>{$&&"function"==typeof $&&$(S)})))}))}return S};toast.success=function(t,e){toast(t,{...e,type:"success"})},toast.error=function(t,e){toast(t,{...e,type:"error"})},toast.update=function(t,e,o={}){const{type:s=null,icon:n=null,showLoader:a=!1,duration:i=3e3,position:l="top-right",onClick:r=null,onShow:c=null,onDismiss:d=null}=o,m=t.querySelector(".ts-toast-loader"),u=t.querySelector(".ts-toast-icon");m&&m.remove(),s&&(t.className=`ts-toast ts-toast-${s} show ${l}`);const p=t.querySelector(".ts-toast-body");p&&(p.innerHTML=e),u&&u.remove();const f=document.createElement("span");if(f.className="ts-toast-icon",f.style.display="flex",n)f.textContent=n;else{const t=document.createElement("img");t.style.width="30px",t.style.height="30px",t.style.objectFit="contain","success"===s?t.src="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/success.gif":"error"===s?t.src="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/error.gif":"info"===s?t.src="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/info.gif":"warning"===s&&(t.src="https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.3.0/assets/img/warning.gif"),f.appendChild(t)}if(t.appendChild(f),a){const e=document.createElement("div");e.className="ts-toast-loader",t.appendChild(e),setTimeout((()=>{e.classList.add("done")}),2e3)}t._autoRemove&&clearTimeout(t._autoRemove);const g=setTimeout((()=>{var e,o;o=()=>{d&&"function"==typeof d&&d(t)},(e=t).classList.add("ts-toast-slide-out"),e.classList.remove("ts-toast-show"),e.style.animation="",setTimeout((()=>{e.classList.remove("ts-toast-slide-out"),e.parentNode&&e.parentNode.removeChild(e),"function"==typeof o&&o()}),500)}),i);t._autoRemove=g},toast.loading=function(t,e={}){const o=toast(t,{...e,type:e.type||"info",duration:0,showLoader:!0,icon:null});requestAnimationFrame((()=>{o.classList.add("ts-toast-show")}));const s=o.querySelector(".ts-toast-loader");let n=o.querySelector(".ts-toast-icon");return n||(n=document.createElement("span"),n.className="ts-toast-icon",n.style.display="flex",o.appendChild(n)),o._managedByLoading=!0,s&&setTimeout((()=>{o._managedByLoading||s.classList.add("done")}),2e3),{update:(t,e={})=>{o._managedByLoading=!1,toast.update(o,t,{...e,showLoader:!1})},close:()=>{o._autoRemove&&clearTimeout(o._autoRemove),o.classList.add("ts-toast-slide-out"),o.classList.remove("ts-toast-show"),o.style.animation="",setTimeout((()=>{o.classList.remove("ts-toast-slide-out"),o.parentNode&&o.parentNode.removeChild(o)}),500)}}},toast.confirm=function(t,e={}){return new Promise((o=>{toast(t,{...e,mode:"confirm",duration:0,dismissOnClick:!1,onResult:t=>o(t)})}))},"undefined"!=typeof window&&(window.toast=toast),"undefined"!=typeof module&&module.exports&&(module.exports=toast);
1
+ "use strict";const TS_TOAST_VERSION="5.4.0",TS_TOAST_CDN="undefined"!=typeof window&&window.TS_TOAST_ASSET_BASE?String(window.TS_TOAST_ASSET_BASE).replace(/\/+$/,""):"https://cdn.jsdelivr.net/npm/@tsirosgeorge/toastnotification@5.4.0";!function(){const t="ts-toast-stylesheet";if("undefined"!=typeof window&&window.TS_TOAST_NO_CSS)return;if(document.getElementById(t))return;const e=document.createElement("link");e.id=t,e.rel="stylesheet",e.href=`${TS_TOAST_CDN}/assets/css/toast.min.css`,document.head.appendChild(e)}(),function(){const t="ts-toast-inline-extras";if(document.getElementById(t))return;const e=document.createElement("style");e.id=t,e.textContent="\n /* Ensure center positions exist even if external CSS lacks them */\n .ts-toast-container.top-center { top: 1rem; left: 50%; transform: translateX(-50%); align-items: center; }\n .ts-toast-container.bottom-center { bottom: 1rem; left: 50%; transform: translateX(-50%); align-items: center; }\n .ts-toast-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 2147483646; }\n .ts-toast.ts-toast-confirm { max-width: min(92vw, 440px); width: max(320px, 60%); flex-direction: column; gap: 12px; padding: 16px 20px; background: var(--toast-bg, #fff); color: var(--toast-color, #000); border: 1px solid var(--toast-border, #e5e7eb); border-radius: 12px; box-shadow: var(--toast-shadow, 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)); text-align: center; }\n .ts-toast.ts-toast-confirm .ts-toast-content { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; }\n .ts-toast-actions { display: flex; gap: 10px; justify-content: center; margin-top: 12px; }\n .ts-toast-btn { appearance: none; border: 0; padding: 8px 12px; border-radius: 8px; font-weight: 600; cursor: pointer; }\n .ts-toast-btn.cancel { background: #e9ecef; color: #1f2937; }\n .ts-toast-btn.confirm { background: #3b82f6; color: #fff; }\n .ts-toast.ts-toast-error .ts-toast-btn.confirm,\n .ts-toast.ts-toast-warning .ts-toast-btn.confirm { background: #ef4444; color: #fff; }\n .ts-toast.ts-toast-confirm .ts-toast-title { font-weight: 700; font-size: 1.05rem; margin-top: 4px; }\n .ts-toast.ts-toast-confirm .ts-toast-close { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; border-radius: 999px; border: 0; background: transparent; color: #6b7280; font-size: 20px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }\n .ts-toast.ts-toast-confirm .ts-toast-close:hover { background: rgba(0,0,0,0.06); }\n .ts-toast.ts-toast-confirm .ts-toast-icon { width: 64px; height: 64px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; }\n .ts-toast.ts-toast-confirm .ts-toast-icon img { width: 36px; height: 36px; }\n .ts-toast.ts-toast-confirm.ts-toast-success .ts-toast-icon { background: #dcfce7; }\n .ts-toast.ts-toast-confirm.ts-toast-info .ts-toast-icon { background: #dbeafe; }\n .ts-toast.ts-toast-confirm.ts-toast-warning .ts-toast-icon { background: #fef3c7; }\n .ts-toast.ts-toast-confirm.ts-toast-error .ts-toast-icon { background: #fee2e2; }\n ",document.head.appendChild(e)}();const toast=function(t,e={}){const{position:o="top-right",animation:s="slide-right",type:n="info",duration:a=3e3,icon:i=null,showLoader:l=!1,mode:r="alert",title:c=null,confirmText:d="Yes",cancelText:u="No",input:m=!1,inputPlaceholder:p="",inputValue:f="",confirmButtonBg:h=null,confirmButtonColor:g=null,cancelButtonBg:y=null,cancelButtonColor:x=null,onConfirm:b=null,onCancel:v=null,onResult:w=null,useOverlay:C=!0,closeOnOverlayClick:T=!0,showClose:E=!1,dismissOnClick:S=!0,onClick:L=null,onShow:_=null,onDismiss:N=null}=e,k="confirm"===r||"swal"===r,A="string"==typeof e.animation&&e.animation.trim()?{"slide-top":"ts-toast-slide-top","slide-bottom":"ts-toast-slide-bottom","slide-left":"ts-toast-slide-left","slide-right":"ts-toast-slide-right","zoom-in":"ts-toast-zoom-in","zoom-out":"ts-toast-zoom-out",flip:"ts-toast-flip"}[O=e.animation.trim()]||O:k?"ts-toast-zoom-in":o.startsWith("top")?"ts-toast-slide-top":o.startsWith("bottom")?"ts-toast-slide-bottom":o.endsWith("left")?"ts-toast-slide-left":"ts-toast-slide-right";var O;const B=(t,e)=>{const o=t.dataset&&t.dataset.anim?t.dataset.anim:t.style.animation||"";let s="";o.includes("ts-toast-slide-top")?s="translateY(-100%)":o.includes("ts-toast-slide-bottom")?s="translateY(100%)":(o.includes("ts-toast-slide-left")||o.includes("ts-toast-slide-right"))&&(s="translateX(100%)"),t.classList.add("ts-toast-slide-out"),t.classList.remove("ts-toast-show"),t.style.animation="",s&&(t.style.transform=s),t.style.opacity="0",setTimeout((()=>{t.classList.remove("ts-toast-slide-out"),t.parentNode&&t.parentNode.removeChild(t),"function"==typeof e&&e()}),500)},$=document.createElement("div");$.className=`ts-toast ts-toast-${n}${k?" ts-toast-confirm":""}`,$.dataset.anim=A,$.style.animation=`${A} 0.5s ease`,k||($.style.flexDirection="row-reverse",$.style.justifyContent="flex-end");const R=document.createElement("span");if(R.className="ts-toast-icon",R.style.display="flex",i)R.textContent=i;else{const t=document.createElement("img");t.alt="",t.setAttribute("aria-hidden","true"),t.style.width="30px",t.style.height="30px",t.style.objectFit="contain";const e={success:"success.gif",error:"error.gif",info:"info.gif",warning:"warning.gif"}[n];e&&(t.src=`${TS_TOAST_CDN}/assets/img/${e}`),R.appendChild(t)}const j=document.createElement("div");j.className="ts-toast-body",j.innerHTML=t;let q=null;if(k){if(q=document.createElement("div"),q.className="ts-toast-content",q.appendChild(R),c){const t=document.createElement("div");t.className="ts-toast-title",t.textContent=c,q.appendChild(t)}q.appendChild(j),$.appendChild(q)}else $.appendChild(j);let z=null;k&&m&&("textarea"===m?(z=document.createElement("textarea"),z.rows=3):(z=document.createElement("input"),z.type="text"===m||"email"===m||"password"===m||"number"===m?m:"text"),z.className="ts-toast-input",z.placeholder=p,z.value=f,$.appendChild(z));let D=null,P=null,X=null;if(k){D=document.createElement("div"),D.className="ts-toast-actions";const t=document.createElement("button");t.className="ts-toast-btn cancel",t.textContent=u;const e=document.createElement("button");e.className="ts-toast-btn confirm",e.textContent=d,y&&(t.style.background=y),x&&(t.style.color=x),h&&(e.style.background=h),g&&(e.style.color=g),D.appendChild(t),D.appendChild(e),$.appendChild(D),$.result=new Promise((t=>{P=t}));let o=!1;X=t=>{if(o)return;o=!0;const e=t?!z||z.value:!!z&&null;P&&P(e),t&&"function"==typeof b&&b(e,$),t||"function"!=typeof v||v($),"function"==typeof w&&w(e,$),B($,(()=>{N&&"function"==typeof N&&N($),F&&F.parentNode&&F.parentNode.removeChild(F)}))},t.addEventListener("click",(t=>{t.stopPropagation(),X(!1)})),e.addEventListener("click",(t=>{t.stopPropagation(),X(!0)}))}let M=null;l&&(M=document.createElement("div"),M.className="ts-toast-loader",$.appendChild(M));let F=null;if(k&&C){if(F=document.createElement("div"),F.className="ts-toast-overlay"+(e.position?` ${o}`:""),document.body.appendChild(F),F.appendChild($),E){const t=document.createElement("button");t.className="ts-toast-close",t.setAttribute("aria-label","Close"),t.innerHTML="&times;",t.addEventListener("click",(t=>{t.stopPropagation(),X(!1)})),$.appendChild(t)}T&&F.addEventListener("click",(t=>{t.target===F&&X(!1)}))}else{let t=document.querySelector(`.ts-toast-container.${o}`);t||(t=document.createElement("div"),t.className=`ts-toast-container ${o}`,document.body.appendChild(t)),t.appendChild($)}if(_&&"function"==typeof _&&_($),setTimeout((()=>{$.classList.add("ts-toast-show")}),100),l&&M&&setTimeout((()=>{$._managedByLoading||(M.classList.add("done"),M.remove(),$.contains(R)||(k&&q?q.appendChild(R):$.appendChild(R)))}),2e3),l||k||$.contains(R)||$.appendChild(R),!k&&a>0){const t=setTimeout((()=>{B($,(()=>{N&&"function"==typeof N&&N($)}))}),a);$._autoRemove=t}if(!k&&S&&$.addEventListener("click",(()=>{$._autoRemove&&clearTimeout($._autoRemove),B($,(()=>{L&&"function"==typeof L&&L($),N&&"function"==typeof N&&N($)}))})),!k){let t=0,e=0;$.addEventListener("touchstart",(e=>{t=e.changedTouches[0].screenX})),$.addEventListener("touchend",(o=>{e=o.changedTouches[0].screenX,Math.abs(t-e)>50&&($._autoRemove&&clearTimeout($._autoRemove),B($,(()=>{N&&"function"==typeof N&&N($)})))}))}return $};toast.success=function(t,e){return toast(t,{...e,type:"success"})},toast.error=function(t,e){return toast(t,{...e,type:"error"})},toast.warning=function(t,e){return toast(t,{...e,type:"warning"})},toast.info=function(t,e){return toast(t,{...e,type:"info"})},toast.update=function(t,e,o={}){const{type:s=null,icon:n=null,showLoader:a=!1,duration:i=3e3,onClick:l=null,onShow:r=null,onDismiss:c=null}=o,d=t.querySelector(".ts-toast-loader"),u=t.querySelector(".ts-toast-icon");d&&d.remove(),s&&(["success","error","info","warning"].forEach((e=>t.classList.remove(`ts-toast-${e}`))),t.classList.add("ts-toast",`ts-toast-${s}`,"ts-toast-show"));const m=t.querySelector(".ts-toast-body");m&&(m.innerHTML=e),u&&u.remove();const p=document.createElement("span");if(p.className="ts-toast-icon",p.style.display="flex",n)p.textContent=n;else{const t=document.createElement("img");t.alt="",t.setAttribute("aria-hidden","true"),t.style.width="30px",t.style.height="30px",t.style.objectFit="contain";const e={success:"success.gif",error:"error.gif",info:"info.gif",warning:"warning.gif"}[s];e&&(t.src=`${TS_TOAST_CDN}/assets/img/${e}`),p.appendChild(t)}if((t.querySelector(".ts-toast-content")||t).appendChild(p),a){const e=document.createElement("div");e.className="ts-toast-loader",t.appendChild(e),setTimeout((()=>{e.classList.add("done")}),2e3)}t._autoRemove&&clearTimeout(t._autoRemove);const f=setTimeout((()=>{var e,o;o=()=>{c&&"function"==typeof c&&c(t)},(e=t).classList.add("ts-toast-slide-out"),e.classList.remove("ts-toast-show"),e.style.animation="",setTimeout((()=>{e.classList.remove("ts-toast-slide-out"),e.parentNode&&e.parentNode.removeChild(e),"function"==typeof o&&o()}),500)}),i);t._autoRemove=f},toast.loading=function(t,e={}){const o=toast(t,{...e,type:e.type||"info",duration:0,showLoader:!0,icon:null});requestAnimationFrame((()=>{o.classList.add("ts-toast-show")}));const s=o.querySelector(".ts-toast-loader");let n=o.querySelector(".ts-toast-icon");return n||(n=document.createElement("span"),n.className="ts-toast-icon",n.style.display="flex",o.appendChild(n)),o._managedByLoading=!0,s&&setTimeout((()=>{o._managedByLoading||s.classList.add("done")}),2e3),{update:(t,e={})=>{o._managedByLoading=!1,toast.update(o,t,{...e,showLoader:!1})},close:()=>{o._autoRemove&&clearTimeout(o._autoRemove),o.classList.add("ts-toast-slide-out"),o.classList.remove("ts-toast-show"),o.style.animation="",setTimeout((()=>{o.classList.remove("ts-toast-slide-out"),o.parentNode&&o.parentNode.removeChild(o)}),500)}}},toast.confirm=function(t,e={}){return new Promise((o=>{toast(t,{...e,mode:"confirm",duration:0,dismissOnClick:!1,onResult:t=>o(t)})}))},"undefined"!=typeof window&&(window.toast=toast),"undefined"!=typeof module&&module.exports&&(module.exports=toast);