PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.5
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.5
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / assets / js / dist / admin / webhooks.js

webhooks.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.5, at assets/js/dist/admin/webhooks.js

5,873 lines 207.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ "./assets/src/js/utils.js"
5 /*!********************************!*\
6 !*** ./assets/src/js/utils.js ***!
7 \********************************/
8 (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
9
10 "use strict";
11 __webpack_require__.r(__webpack_exports__);
12 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
13 /* harmony export */ debounce: () => (/* binding */ debounce),
14 /* harmony export */ eventHandlers: () => (/* binding */ eventHandlers),
15 /* harmony export */ fullScreenView: () => (/* binding */ fullScreenView),
16 /* harmony export */ getDataOfForm: () => (/* binding */ getDataOfForm),
17 /* harmony export */ getFieldKeysOfForm: () => (/* binding */ getFieldKeysOfForm),
18 /* harmony export */ listenElementCreated: () => (/* binding */ listenElementCreated),
19 /* harmony export */ listenElementViewed: () => (/* binding */ listenElementViewed),
20 /* harmony export */ lpAddQueryArgs: () => (/* binding */ lpAddQueryArgs),
21 /* harmony export */ lpAjaxParseJsonOld: () => (/* binding */ lpAjaxParseJsonOld),
22 /* harmony export */ lpClassName: () => (/* binding */ lpClassName),
23 /* harmony export */ lpFetchAPI: () => (/* binding */ lpFetchAPI),
24 /* harmony export */ lpGetCurrentURLNoParam: () => (/* binding */ lpGetCurrentURLNoParam),
25 /* harmony export */ lpOnElementReady: () => (/* binding */ lpOnElementReady),
26 /* harmony export */ lpSetLoadingEl: () => (/* binding */ lpSetLoadingEl),
27 /* harmony export */ lpShowHideEl: () => (/* binding */ lpShowHideEl),
28 /* harmony export */ mergeDataWithDatForm: () => (/* binding */ mergeDataWithDatForm),
29 /* harmony export */ toggleCollapse: () => (/* binding */ toggleCollapse),
30 /* harmony export */ toggleEnable: () => (/* binding */ toggleEnable)
31 /* harmony export */ });
32 /**
33 * Utils functions
34 *
35 * @param url
36 * @param data
37 * @param functions
38 * @since 4.2.5.1
39 * @version 1.0.7
40 */
41 const lpClassName = {
42 hidden: 'lp-hidden',
43 loading: 'loading',
44 elCollapse: 'lp-collapse',
45 elSectionToggle: '.lp-section-toggle',
46 elTriggerToggle: '.lp-trigger-toggle',
47 elBtnFullScreen: '.lp-btn-full-screen-view',
48 elFullScreen: 'lp-full-screen-view',
49 elBtnFullScreenClose: 'lp-full-screen-view__close'
50 };
51 const lpFetchAPI = (url, data = {}, functions = {}) => {
52 if ('function' === typeof functions.before) {
53 functions.before();
54 }
55 fetch(url, {
56 method: 'GET',
57 ...data
58 }).then(response => response.json()).then(response => {
59 if ('function' === typeof functions.success) {
60 functions.success(response);
61 }
62 }).catch(err => {
63 if ('function' === typeof functions.error) {
64 functions.error(err);
65 }
66 }).finally(() => {
67 if ('function' === typeof functions.completed) {
68 functions.completed();
69 }
70 });
71 };
72
73 /**
74 * Get current URL without params.
75 *
76 * @since 4.2.5.1
77 */
78 const lpGetCurrentURLNoParam = () => {
79 let currentUrl = window.location.href;
80 const hasParams = currentUrl.includes('?');
81 if (hasParams) {
82 currentUrl = currentUrl.split('?')[0];
83 }
84 return currentUrl;
85 };
86 const lpAddQueryArgs = (endpoint, args) => {
87 const url = new URL(endpoint);
88 Object.keys(args).forEach(arg => {
89 url.searchParams.set(arg, args[arg]);
90 });
91 return url;
92 };
93
94 /**
95 * Listen element viewed.
96 *
97 * @param el
98 * @param callback
99 * @since 4.2.5.8
100 */
101 const listenElementViewed = (el, callback) => {
102 const observerSeeItem = new IntersectionObserver(function (entries) {
103 for (const entry of entries) {
104 if (entry.isIntersecting) {
105 callback(entry);
106 }
107 }
108 });
109 observerSeeItem.observe(el);
110 };
111
112 /**
113 * Listen element created.
114 *
115 * @param callback
116 * @since 4.2.5.8
117 */
118 const listenElementCreated = callback => {
119 const observerCreateItem = new MutationObserver(function (mutations) {
120 mutations.forEach(function (mutation) {
121 if (mutation.addedNodes) {
122 mutation.addedNodes.forEach(function (node) {
123 if (node.nodeType === 1) {
124 callback(node);
125 }
126 });
127 }
128 });
129 });
130 observerCreateItem.observe(document, {
131 childList: true,
132 subtree: true
133 });
134 // End.
135 };
136
137 /**
138 * Listen element created.
139 *
140 * @param selector
141 * @param callback
142 * @since 4.2.7.1
143 */
144 const lpOnElementReady = (selector, callback) => {
145 const element = document.querySelector(selector);
146 if (element) {
147 callback(element);
148 return;
149 }
150 const observer = new MutationObserver((mutations, obs) => {
151 const element = document.querySelector(selector);
152 if (element) {
153 obs.disconnect();
154 callback(element);
155 }
156 });
157 observer.observe(document.documentElement, {
158 childList: true,
159 subtree: true
160 });
161 };
162
163 // Parse JSON from string with content include LP_AJAX_START.
164 const lpAjaxParseJsonOld = data => {
165 if (typeof data !== 'string') {
166 return data;
167 }
168 const m = String.raw({
169 raw: data
170 }).match(/<-- LP_AJAX_START -->(.*)<-- LP_AJAX_END -->/s);
171 try {
172 if (m) {
173 data = JSON.parse(m[1].replace(/(?:\r\n|\r|\n)/g, ''));
174 } else {
175 data = JSON.parse(data);
176 }
177 } catch (e) {
178 data = {};
179 }
180 return data;
181 };
182
183 // status 0: hide, 1: show
184 const lpShowHideEl = (el, status = 0) => {
185 if (!el) {
186 return;
187 }
188 if (!status) {
189 el.classList.add(lpClassName.hidden);
190 } else {
191 el.classList.remove(lpClassName.hidden);
192 }
193 };
194
195 // status 0: hide, 1: show
196 const lpSetLoadingEl = (el, status) => {
197 if (!el) {
198 return;
199 }
200 if (!status) {
201 el.classList.remove(lpClassName.loading);
202 } else {
203 el.classList.add(lpClassName.loading);
204 }
205 };
206
207 // Toggle collapse section
208 const toggleCollapse = (e, target, elTriggerClassName = '', elsExclude = [], callback) => {
209 if (!elTriggerClassName) {
210 elTriggerClassName = lpClassName.elTriggerToggle;
211 }
212
213 // Exclude elements, which should not trigger the collapse toggle
214 if (elsExclude && elsExclude.length > 0) {
215 for (const elExclude of elsExclude) {
216 if (target.closest(elExclude)) {
217 return;
218 }
219 }
220 }
221 const elTrigger = target.closest(elTriggerClassName);
222 if (!elTrigger) {
223 return;
224 }
225
226 //console.log( 'elTrigger', elTrigger );
227
228 const elSectionToggle = elTrigger.closest(`${lpClassName.elSectionToggle}`);
229 if (!elSectionToggle) {
230 return;
231 }
232 elSectionToggle.classList.toggle(`${lpClassName.elCollapse}`);
233 if ('function' === typeof callback) {
234 callback(elSectionToggle);
235 }
236 };
237
238 // Get data of form
239 const getDataOfForm = form => {
240 const dataSend = {};
241 const formData = new FormData(form);
242 for (const pair of formData.entries()) {
243 const key = pair[0];
244 const value = formData.getAll(key);
245 if (!dataSend.hasOwnProperty(key)) {
246 // Convert value array to string.
247 dataSend[key] = value.join(',');
248 }
249 }
250 return dataSend;
251 };
252
253 // Get field keys of form
254 const getFieldKeysOfForm = form => {
255 const keys = [];
256 const elements = form.elements;
257 for (let i = 0; i < elements.length; i++) {
258 const name = elements[i].name;
259 if (name && !keys.includes(name)) {
260 keys.push(name);
261 }
262 }
263 return keys;
264 };
265
266 // Merge data handle with data form.
267 const mergeDataWithDatForm = (elForm, dataHandle) => {
268 const dataForm = getDataOfForm(elForm);
269 const keys = getFieldKeysOfForm(elForm);
270 keys.forEach(key => {
271 if (!dataForm.hasOwnProperty(key)) {
272 delete dataHandle[key];
273 } else if (dataForm[key][0] === '') {
274 delete dataForm[key];
275 delete dataHandle[key];
276 }
277 });
278 dataHandle = {
279 ...dataHandle,
280 ...dataForm
281 };
282 return dataHandle;
283 };
284
285 /**
286 * Event trigger
287 * For each list of event handlers, listen event on document.
288 *
289 * eventName: 'click', 'change', ...
290 * eventHandlers = [ { selector: '.lp-button', callBack: function(){}, class: object } ]
291 *
292 * @param eventName
293 * @param eventHandlers
294 */
295 const eventHandlers = (eventName, eventHandlers) => {
296 document.addEventListener(eventName, e => {
297 const target = e.target;
298 let args = {
299 e,
300 target
301 };
302 eventHandlers.forEach(eventHandler => {
303 args = {
304 ...args,
305 ...eventHandler
306 };
307
308 //console.log( args );
309
310 // Check condition before call back
311 if (eventHandler.conditionBeforeCallBack) {
312 if (eventHandler.conditionBeforeCallBack(args) !== true) {
313 return;
314 }
315 }
316
317 // Special check for keydown event with checkIsEventEnter = true
318 if (eventName === 'keydown' && eventHandler.checkIsEventEnter) {
319 if (e.key !== 'Enter') {
320 return;
321 }
322 }
323 if (target.closest(eventHandler.selector)) {
324 if (eventHandler.class) {
325 // Call method of class, function callBack will understand exactly {this} is class object.
326 eventHandler.class[eventHandler.callBack](args);
327 } else {
328 // For send args is objected, {this} is eventHandler object, not class object.
329 eventHandler.callBack(args);
330 }
331 }
332 });
333 });
334 };
335
336 /**
337 * Debounce - delays function execution until after `wait` ms of inactivity.
338 *
339 * Each call resets the timer. Only the last call in a burst executes.
340 *
341 * USE CASES:
342 * - Search inputs, form validation, window resize
343 * - Multiple elements need independent timers
344 * - When you need to call with different arguments
345 *
346 * EXAMPLES:
347 * const debouncedSearch = debounce( (query) => fetchResults(query), 300 );
348 * searchInput.addEventListener('input', (e) => debouncedSearch(e.target.value));
349 *
350 * const debouncedResize = debounce( recalculateLayout, 250 );
351 * window.addEventListener('resize', debouncedResize);
352 *
353 * ⚠️ Create ONCE outside event handlers, not inside.
354 *
355 * @param {Function} func - Function to debounce (can be anonymous)
356 * @param {number} wait - Milliseconds to wait (default: 500)
357 * @return {Function} Debounced wrapper function
358 * @since 4.3.7
359 * @version 1.0.0
360 */
361 const debounce = (func, wait = 500) => {
362 let timer;
363 return args => {
364 clearTimeout(timer);
365 timer = setTimeout(() => func(args), wait);
366 };
367 };
368
369 /**
370 * Initialize lp-toggle-enable components.
371 *
372 * Finds all `.lp-toggle-enable` elements and wires up toggle behavior.
373 * Reads initial state from `data-enabled` attribute ("true"/"false").
374 * Calls `data-on-toggle` callback (if provided via options) on state change.
375 *
376 * HTML structure:
377 * <label class="lp-toggle-enable" data-enabled="true">
378 * <input type="checkbox" class="lp-toggle-enable__input" />
379 * <span class="lp-toggle-enable__track"></span>
380 * </label>
381 *
382 * @param {string} selector CSS selector for toggle elements (default: '.lp-toggle-enable')
383 * @param {Function} onToggle Optional callback( el, isEnabled ) called on state change
384 * @since 4.4.5
385 * @version 1.0.0
386 */
387 window.lpToggleEnableInit = 0;
388 const toggleEnable = (onToggle = null) => {
389 if (window.lpToggleEnableInit) {
390 return;
391 }
392 window.lpToggleEnableInit = 1;
393 const selector = '.lp-toggle-enable';
394 const updateUI = (toggle, isEnabled) => {
395 toggle.classList.toggle('is-enabled', isEnabled);
396 const input = toggle.querySelector('.lp-toggle-enable__input');
397 if (input) {
398 input.checked = isEnabled;
399 input.value = isEnabled ? '1' : '0';
400 }
401 };
402
403 // Delegate click handling via eventHandlers.
404 eventHandlers('click', [{
405 selector,
406 callBack: args => {
407 const {
408 e,
409 target
410 } = args;
411 const toggle = target.closest(selector);
412 if (!toggle || toggle.classList.contains('is-disabled')) {
413 return;
414 }
415 e.preventDefault();
416 const isEnabled = !toggle.classList.contains('is-enabled');
417 updateUI(toggle, isEnabled);
418 if ('function' === typeof onToggle) {
419 onToggle(toggle, isEnabled);
420 }
421 }
422 }]);
423 };
424
425 /**
426 * Initialize custom fullscreen view buttons.
427 *
428 * Delegates clicks on `.lp-btn-full-screen-view` buttons to
429 * `lpToggleFullscreenView`. Reads the `data-target` attribute to find the
430 * target element. Falls back to the button's parent element when
431 * `data-target` is not provided.
432 *
433 * @since 4.4.5
434 * @version 1.0.0
435 */
436 window.lpFullScreenViewInit = 0;
437 const fullScreenView = () => {
438 if (window.lpFullScreenViewInit) {
439 return;
440 }
441 window.lpFullScreenViewInit = 1;
442 let lastScrollY = 0;
443 const lpToggleFullscreenView = (elTarget, elBtnFullScreen = null) => {
444 const isFullscreen = elTarget.classList.contains(lpClassName.elFullScreen);
445 if (isFullscreen) {
446 elTarget.classList.remove(lpClassName.elFullScreen);
447 document.documentElement.classList.remove('lp-full-screen-active');
448 window.scrollTo(0, lastScrollY);
449 } else {
450 lastScrollY = window.scrollY;
451 elTarget.classList.add(lpClassName.elFullScreen);
452 document.documentElement.classList.add('lp-full-screen-active');
453 }
454 if (!isFullscreen) {
455 if (!elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`)) {
456 const closeButton = document.createElement('button');
457 closeButton.type = 'button';
458 closeButton.className = lpClassName.elBtnFullScreenClose;
459 closeButton.setAttribute('aria-label', 'Close');
460 closeButton.innerHTML = lpData.i18n.closeButtonFullScreen || 'Close &times;';
461 closeButton.addEventListener('click', e => {
462 e.preventDefault();
463 lpToggleFullscreenView(elTarget);
464 });
465 elTarget.appendChild(closeButton);
466 }
467 } else {
468 const closeButton = elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`);
469 if (closeButton) {
470 closeButton.remove();
471 }
472 }
473 };
474 eventHandlers('click', [{
475 selector: lpClassName.elBtnFullScreen,
476 callBack: args => {
477 const {
478 e,
479 target
480 } = args;
481 const elBtnFullScreen = target.closest(lpClassName.elBtnFullScreen);
482 if (!elBtnFullScreen) {
483 console.log('No full screen button found');
484 return;
485 }
486 e.preventDefault();
487 let elTarget = null;
488 const targetSelector = elBtnFullScreen.dataset.targetFullscreen;
489 console.log(targetSelector);
490 if (targetSelector) {
491 elTarget = document.querySelector(targetSelector);
492 }
493 if (!elTarget) {
494 console.log('No target element found');
495 return;
496 }
497 lpToggleFullscreenView(elTarget, elBtnFullScreen);
498 }
499 }]);
500 };
501
502 /***/ },
503
504 /***/ "./node_modules/sweetalert2/dist/sweetalert2.all.js"
505 /*!**********************************************************!*\
506 !*** ./node_modules/sweetalert2/dist/sweetalert2.all.js ***!
507 \**********************************************************/
508 (module) {
509
510 /*!
511 * sweetalert2 v11.26.25
512 * Released under the MIT License.
513 */
514 (function (global, factory) {
515 true ? module.exports = factory() :
516 0;
517 })(this, (function () { 'use strict';
518
519 function _assertClassBrand(e, t, n) {
520 if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
521 throw new TypeError("Private element is not present on this object");
522 }
523 function _checkPrivateRedeclaration(e, t) {
524 if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
525 }
526 function _classPrivateFieldGet2(s, a) {
527 return s.get(_assertClassBrand(s, a));
528 }
529 function _classPrivateFieldInitSpec(e, t, a) {
530 _checkPrivateRedeclaration(e, t), t.set(e, a);
531 }
532 function _classPrivateFieldSet2(s, a, r) {
533 return s.set(_assertClassBrand(s, a), r), r;
534 }
535
536 const RESTORE_FOCUS_TIMEOUT = 100;
537
538 /** @type {GlobalState} */
539 const globalState = {};
540 const focusPreviousActiveElement = () => {
541 if (globalState.previousActiveElement instanceof HTMLElement) {
542 globalState.previousActiveElement.focus();
543 globalState.previousActiveElement = null;
544 } else if (document.body) {
545 document.body.focus();
546 }
547 };
548
549 /**
550 * Restore previous active (focused) element
551 *
552 * @param {boolean} returnFocus
553 * @returns {Promise<void>}
554 */
555 const restoreActiveElement = returnFocus => {
556 return new Promise(resolve => {
557 if (!returnFocus) {
558 return resolve();
559 }
560 const x = window.scrollX;
561 const y = window.scrollY;
562 globalState.restoreFocusTimeout = setTimeout(() => {
563 focusPreviousActiveElement();
564 resolve();
565 }, RESTORE_FOCUS_TIMEOUT); // issues/900
566
567 window.scrollTo(x, y);
568 });
569 };
570
571 const swalPrefix = 'swal2-';
572
573 /**
574 * @typedef {Record<SwalClass, string>} SwalClasses
575 */
576
577 /**
578 * @typedef {'success' | 'warning' | 'info' | 'question' | 'error'} SwalIcon
579 * @typedef {Record<SwalIcon, string>} SwalIcons
580 */
581
582 /** @type {SwalClass[]} */
583 const classNames = ['container', 'shown', 'height-auto', 'iosfix', 'popup', 'modal', 'no-backdrop', 'no-transition', 'toast', 'toast-shown', 'show', 'hide', 'close', 'title', 'html-container', 'actions', 'confirm', 'deny', 'cancel', 'footer', 'icon', 'icon-content', 'image', 'input', 'file', 'range', 'select', 'radio', 'checkbox', 'label', 'textarea', 'inputerror', 'input-label', 'validation-message', 'progress-steps', 'active-progress-step', 'progress-step', 'progress-step-line', 'loader', 'loading', 'styled', 'top', 'top-start', 'top-end', 'top-left', 'top-right', 'center', 'center-start', 'center-end', 'center-left', 'center-right', 'bottom', 'bottom-start', 'bottom-end', 'bottom-left', 'bottom-right', 'grow-row', 'grow-column', 'grow-fullscreen', 'rtl', 'timer-progress-bar', 'timer-progress-bar-container', 'scrollbar-measure', 'icon-success', 'icon-warning', 'icon-info', 'icon-question', 'icon-error', 'draggable', 'dragging'];
584 const swalClasses = classNames.reduce((acc, className) => {
585 acc[className] = swalPrefix + className;
586 return acc;
587 }, /** @type {SwalClasses} */{});
588
589 /** @type {SwalIcon[]} */
590 const icons = ['success', 'warning', 'info', 'question', 'error'];
591 const iconTypes = icons.reduce((acc, icon) => {
592 acc[icon] = swalPrefix + icon;
593 return acc;
594 }, /** @type {SwalIcons} */{});
595
596 const consolePrefix = 'SweetAlert2:';
597
598 /**
599 * Capitalize the first letter of a string
600 *
601 * @param {string} str
602 * @returns {string}
603 */
604 const capitalizeFirstLetter = str => str.charAt(0).toUpperCase() + str.slice(1);
605
606 /**
607 * Standardize console warnings
608 *
609 * @param {string | string[]} message
610 */
611 const warn = message => {
612 console.warn(`${consolePrefix} ${typeof message === 'object' ? message.join(' ') : message}`);
613 };
614
615 /**
616 * Standardize console errors
617 *
618 * @param {string} message
619 */
620 const error = message => {
621 console.error(`${consolePrefix} ${message}`);
622 };
623
624 /**
625 * Private global state for `warnOnce`
626 *
627 * @type {string[]}
628 * @private
629 */
630 const previousWarnOnceMessages = [];
631
632 /**
633 * Show a console warning, but only if it hasn't already been shown
634 *
635 * @param {string} message
636 */
637 const warnOnce = message => {
638 if (!previousWarnOnceMessages.includes(message)) {
639 previousWarnOnceMessages.push(message);
640 warn(message);
641 }
642 };
643
644 /**
645 * Show a one-time console warning about deprecated params/methods
646 *
647 * @param {string} deprecatedParam
648 * @param {string?} useInstead
649 */
650 const warnAboutDeprecation = (deprecatedParam, useInstead = null) => {
651 warnOnce(`"${deprecatedParam}" is deprecated and will be removed in the next major release.${useInstead ? ` Use "${useInstead}" instead.` : ''}`);
652 };
653
654 /**
655 * If `arg` is a function, call it (with no arguments or context) and return the result.
656 * Otherwise, just pass the value through
657 *
658 * @param {(() => *) | *} arg
659 * @returns {*}
660 */
661 const callIfFunction = arg => typeof arg === 'function' ? arg() : arg;
662
663 /**
664 * @param {*} arg
665 * @returns {boolean}
666 */
667 const hasToPromiseFn = arg => arg && typeof arg.toPromise === 'function';
668
669 /**
670 * @param {*} arg
671 * @returns {Promise<*>}
672 */
673 const asPromise = arg => hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg);
674
675 /**
676 * @param {*} arg
677 * @returns {boolean}
678 */
679 const isPromise = arg => arg && Promise.resolve(arg) === arg;
680
681 /**
682 * @returns {boolean}
683 */
684 const isFirefox = () => navigator.userAgent.includes('Firefox');
685
686 /**
687 * Gets the popup container which contains the backdrop and the popup itself.
688 *
689 * @returns {HTMLElement | null}
690 */
691 const getContainer = () => document.body.querySelector(`.${swalClasses.container}`);
692
693 /**
694 * @param {string} selectorString
695 * @returns {HTMLElement | null}
696 */
697 const elementBySelector = selectorString => {
698 const container = getContainer();
699 return container ? container.querySelector(selectorString) : null;
700 };
701
702 /**
703 * @param {string} className
704 * @returns {HTMLElement | null}
705 */
706 const elementByClass = className => {
707 return elementBySelector(`.${className}`);
708 };
709
710 /**
711 * @returns {HTMLElement | null}
712 */
713 const getPopup = () => elementByClass(swalClasses.popup);
714
715 /**
716 * @returns {HTMLElement | null}
717 */
718 const getIcon = () => elementByClass(swalClasses.icon);
719
720 /**
721 * @returns {HTMLElement | null}
722 */
723 const getIconContent = () => elementByClass(swalClasses['icon-content']);
724
725 /**
726 * @returns {HTMLElement | null}
727 */
728 const getTitle = () => elementByClass(swalClasses.title);
729
730 /**
731 * @returns {HTMLElement | null}
732 */
733 const getHtmlContainer = () => elementByClass(swalClasses['html-container']);
734
735 /**
736 * @returns {HTMLElement | null}
737 */
738 const getImage = () => elementByClass(swalClasses.image);
739
740 /**
741 * @returns {HTMLElement | null}
742 */
743 const getProgressSteps = () => elementByClass(swalClasses['progress-steps']);
744
745 /**
746 * @returns {HTMLElement | null}
747 */
748 const getValidationMessage = () => elementByClass(swalClasses['validation-message']);
749
750 /**
751 * @returns {HTMLButtonElement | null}
752 */
753 const getConfirmButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.confirm}`));
754
755 /**
756 * @returns {HTMLButtonElement | null}
757 */
758 const getCancelButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.cancel}`));
759
760 /**
761 * @returns {HTMLButtonElement | null}
762 */
763 const getDenyButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.deny}`));
764
765 /**
766 * @returns {HTMLElement | null}
767 */
768 const getInputLabel = () => elementByClass(swalClasses['input-label']);
769
770 /**
771 * @returns {HTMLElement | null}
772 */
773 const getLoader = () => elementBySelector(`.${swalClasses.loader}`);
774
775 /**
776 * @returns {HTMLElement | null}
777 */
778 const getActions = () => elementByClass(swalClasses.actions);
779
780 /**
781 * @returns {HTMLElement | null}
782 */
783 const getFooter = () => elementByClass(swalClasses.footer);
784
785 /**
786 * @returns {HTMLElement | null}
787 */
788 const getTimerProgressBar = () => elementByClass(swalClasses['timer-progress-bar']);
789
790 /**
791 * @returns {HTMLElement | null}
792 */
793 const getCloseButton = () => elementByClass(swalClasses.close);
794
795 // https://github.com/jkup/focusable/blob/master/index.js
796 const focusable = `
797 a[href],
798 area[href],
799 input:not([disabled]),
800 select:not([disabled]),
801 textarea:not([disabled]),
802 button:not([disabled]),
803 iframe,
804 object,
805 embed,
806 [tabindex="0"],
807 [contenteditable],
808 audio[controls],
809 video[controls],
810 summary
811 `;
812 /**
813 * @returns {HTMLElement[]}
814 */
815 const getFocusableElements = () => {
816 const popup = getPopup();
817 if (!popup) {
818 return [];
819 }
820 /** @type {NodeListOf<HTMLElement>} */
821 const focusableElementsWithTabindex = popup.querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])');
822 const focusableElementsWithTabindexSorted = Array.from(focusableElementsWithTabindex)
823 // sort according to tabindex
824 .sort((a, b) => {
825 const tabindexA = parseInt(a.getAttribute('tabindex') || '0');
826 const tabindexB = parseInt(b.getAttribute('tabindex') || '0');
827 if (tabindexA > tabindexB) {
828 return 1;
829 } else if (tabindexA < tabindexB) {
830 return -1;
831 }
832 return 0;
833 });
834
835 /** @type {NodeListOf<HTMLElement>} */
836 const otherFocusableElements = popup.querySelectorAll(focusable);
837 const otherFocusableElementsFiltered = Array.from(otherFocusableElements).filter(el => el.getAttribute('tabindex') !== '-1');
838 return [...new Set(focusableElementsWithTabindexSorted.concat(otherFocusableElementsFiltered))].filter(el => isVisible$1(el));
839 };
840
841 /**
842 * @returns {boolean}
843 */
844 const isModal = () => {
845 return hasClass(document.body, swalClasses.shown) && !hasClass(document.body, swalClasses['toast-shown']) && !hasClass(document.body, swalClasses['no-backdrop']);
846 };
847
848 /**
849 * @returns {boolean}
850 */
851 const isToast = () => {
852 const popup = getPopup();
853 if (!popup) {
854 return false;
855 }
856 return hasClass(popup, swalClasses.toast);
857 };
858
859 /**
860 * @returns {boolean}
861 */
862 const isLoading = () => {
863 const popup = getPopup();
864 if (!popup) {
865 return false;
866 }
867 return popup.hasAttribute('data-loading');
868 };
869
870 /**
871 * Securely set innerHTML of an element
872 * https://github.com/sweetalert2/sweetalert2/issues/1926
873 *
874 * @param {HTMLElement} elem
875 * @param {string} html
876 */
877 const setInnerHtml = (elem, html) => {
878 elem.textContent = '';
879 if (html) {
880 const parser = new DOMParser();
881 const parsed = parser.parseFromString(html, `text/html`);
882 const head = parsed.querySelector('head');
883 if (head) {
884 Array.from(head.childNodes).forEach(child => {
885 elem.appendChild(child);
886 });
887 }
888 const body = parsed.querySelector('body');
889 if (body) {
890 Array.from(body.childNodes).forEach(child => {
891 if (child instanceof HTMLVideoElement || child instanceof HTMLAudioElement) {
892 elem.appendChild(child.cloneNode(true)); // https://github.com/sweetalert2/sweetalert2/issues/2507
893 } else {
894 elem.appendChild(child);
895 }
896 });
897 }
898 }
899 };
900
901 /**
902 * @param {HTMLElement} elem
903 * @param {string} className
904 * @returns {boolean}
905 */
906 const hasClass = (elem, className) => {
907 if (!className) {
908 return false;
909 }
910 return className.split(/\s+/).every(cls => elem.classList.contains(cls));
911 };
912
913 /**
914 * @param {HTMLElement} elem
915 * @param {SweetAlertOptions} params
916 */
917 const removeCustomClasses = (elem, params) => {
918 Array.from(elem.classList).forEach(className => {
919 if (!Object.values(swalClasses).includes(className) && !Object.values(iconTypes).includes(className) && !Object.values(params.showClass || {}).includes(className)) {
920 elem.classList.remove(className);
921 }
922 });
923 };
924
925 /**
926 * @param {HTMLElement} elem
927 * @param {SweetAlertOptions} params
928 * @param {string} className
929 */
930 const applyCustomClass = (elem, params, className) => {
931 removeCustomClasses(elem, params);
932 if (!params.customClass) {
933 return;
934 }
935 const customClass = params.customClass[(/** @type {keyof SweetAlertCustomClass} */className)];
936 if (!customClass) {
937 return;
938 }
939 if (typeof customClass !== 'string' && !customClass.forEach) {
940 warn(`Invalid type of customClass.${className}! Expected string or iterable object, got "${typeof customClass}"`);
941 return;
942 }
943 addClass(elem, customClass);
944 };
945
946 /**
947 * @param {HTMLElement} popup
948 * @param {import('./renderers/renderInput').InputClass | SweetAlertInput} inputClass
949 * @returns {HTMLInputElement | null}
950 */
951 const getInput$1 = (popup, inputClass) => {
952 if (!inputClass) {
953 return null;
954 }
955 switch (inputClass) {
956 case 'select':
957 case 'textarea':
958 case 'file':
959 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses[inputClass]}`);
960 case 'checkbox':
961 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.checkbox} input`);
962 case 'radio':
963 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:checked`) || popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:first-child`);
964 case 'range':
965 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.range} input`);
966 default:
967 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.input}`);
968 }
969 };
970
971 /**
972 * @param {HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement} input
973 */
974 const focusInput = input => {
975 input.focus();
976
977 // place cursor at end of text in text input
978 if (input.type !== 'file') {
979 // http://stackoverflow.com/a/2345915
980 const val = input.value;
981 input.value = '';
982 input.value = val;
983 }
984 };
985
986 /**
987 * @param {HTMLElement | HTMLElement[] | null} target
988 * @param {string | string[] | readonly string[] | undefined} classList
989 * @param {boolean} condition
990 */
991 const toggleClass = (target, classList, condition) => {
992 if (!target || !classList) {
993 return;
994 }
995 const classes = typeof classList === 'string' ? classList.split(/\s+/).filter(Boolean) : classList;
996 const targets = Array.isArray(target) ? target : [target];
997 targets.forEach(elem => {
998 classes.forEach(className => {
999 if (condition) {
1000 elem.classList.add(className);
1001 } else {
1002 elem.classList.remove(className);
1003 }
1004 });
1005 });
1006 };
1007
1008 /**
1009 * @param {HTMLElement | HTMLElement[] | null} target
1010 * @param {string | string[] | readonly string[] | undefined} classList
1011 */
1012 const addClass = (target, classList) => {
1013 toggleClass(target, classList, true);
1014 };
1015
1016 /**
1017 * @param {HTMLElement | HTMLElement[] | null} target
1018 * @param {string | string[] | readonly string[] | undefined} classList
1019 */
1020 const removeClass = (target, classList) => {
1021 toggleClass(target, classList, false);
1022 };
1023
1024 /**
1025 * Get direct child of an element by class name
1026 *
1027 * @param {HTMLElement} elem
1028 * @param {string} className
1029 * @returns {HTMLElement | undefined}
1030 */
1031 const getDirectChildByClass = (elem, className) => (/** @type {HTMLElement | undefined} */
1032 Array.from(elem.children).find(child => child instanceof HTMLElement && hasClass(child, className)));
1033
1034 /**
1035 * @param {HTMLElement} elem
1036 * @param {string} property
1037 * @param {string | number | null | undefined} value
1038 */
1039 const applyNumericalStyle = (elem, property, value) => {
1040 if (value === `${parseInt(`${value}`)}`) {
1041 value = parseInt(value);
1042 }
1043 if (value || value === 0) {
1044 elem.style.setProperty(property, typeof value === 'number' ? `${value}px` : (/** @type {string} */value));
1045 } else {
1046 elem.style.removeProperty(property);
1047 }
1048 };
1049
1050 /**
1051 * @param {HTMLElement | null} elem
1052 * @param {string} display
1053 */
1054 const show = (elem, display = 'flex') => {
1055 if (!elem) {
1056 return;
1057 }
1058 elem.style.display = display;
1059 };
1060
1061 /**
1062 * @param {HTMLElement | null} elem
1063 */
1064 const hide = elem => {
1065 if (!elem) {
1066 return;
1067 }
1068 elem.style.display = 'none';
1069 };
1070
1071 /**
1072 * @param {HTMLElement | null} elem
1073 * @param {string} display
1074 */
1075 const showWhenInnerHtmlPresent = (elem, display = 'block') => {
1076 if (!elem) {
1077 return;
1078 }
1079 new MutationObserver(() => {
1080 toggle(elem, elem.innerHTML, display);
1081 }).observe(elem, {
1082 childList: true,
1083 subtree: true
1084 });
1085 };
1086
1087 /**
1088 * @param {HTMLElement} parent
1089 * @param {string} selector
1090 * @param {string} property
1091 * @param {string} value
1092 */
1093 const setStyle = (parent, selector, property, value) => {
1094 /** @type {HTMLElement | null} */
1095 const el = parent.querySelector(selector);
1096 if (el) {
1097 el.style.setProperty(property, value);
1098 }
1099 };
1100
1101 /**
1102 * @param {HTMLElement} elem
1103 * @param {boolean | string | null | undefined} condition
1104 * @param {string} display
1105 */
1106 const toggle = (elem, condition, display = 'flex') => {
1107 if (condition) {
1108 show(elem, display);
1109 } else {
1110 hide(elem);
1111 }
1112 };
1113
1114 /**
1115 * borrowed from jquery $(elem).is(':visible') implementation
1116 *
1117 * @param {HTMLElement | null} elem
1118 * @returns {boolean}
1119 */
1120 const isVisible$1 = elem => Boolean(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length));
1121
1122 /**
1123 * @returns {boolean}
1124 */
1125 const allButtonsAreHidden = () => !isVisible$1(getConfirmButton()) && !isVisible$1(getDenyButton()) && !isVisible$1(getCancelButton());
1126
1127 /**
1128 * @param {HTMLElement} elem
1129 * @returns {boolean}
1130 */
1131 const isScrollable = elem => Boolean(elem.scrollHeight > elem.clientHeight);
1132
1133 /**
1134 * @param {HTMLElement} element
1135 * @param {HTMLElement} stopElement
1136 * @returns {boolean}
1137 */
1138 const selfOrParentIsScrollable = (element, stopElement) => {
1139 let parent = /** @type {HTMLElement | null} */element;
1140 while (parent && parent !== stopElement) {
1141 if (isScrollable(parent)) {
1142 return true;
1143 }
1144 parent = parent.parentElement;
1145 }
1146 return false;
1147 };
1148
1149 /**
1150 * borrowed from https://stackoverflow.com/a/46352119
1151 *
1152 * @param {HTMLElement} elem
1153 * @returns {boolean}
1154 */
1155 const hasCssAnimation = elem => {
1156 const style = window.getComputedStyle(elem);
1157 const animDuration = parseFloat(style.getPropertyValue('animation-duration') || '0');
1158 const transDuration = parseFloat(style.getPropertyValue('transition-duration') || '0');
1159 return animDuration > 0 || transDuration > 0;
1160 };
1161
1162 /**
1163 * @param {number} timer
1164 * @param {boolean} reset
1165 */
1166 const animateTimerProgressBar = (timer, reset = false) => {
1167 const timerProgressBar = getTimerProgressBar();
1168 if (!timerProgressBar) {
1169 return;
1170 }
1171 if (isVisible$1(timerProgressBar)) {
1172 if (reset) {
1173 timerProgressBar.style.transition = 'none';
1174 timerProgressBar.style.width = '100%';
1175 }
1176 setTimeout(() => {
1177 timerProgressBar.style.transition = `width ${timer / 1000}s linear`;
1178 timerProgressBar.style.width = '0%';
1179 }, 10);
1180 }
1181 };
1182 const stopTimerProgressBar = () => {
1183 const timerProgressBar = getTimerProgressBar();
1184 if (!timerProgressBar) {
1185 return;
1186 }
1187 const timerProgressBarWidth = parseInt(window.getComputedStyle(timerProgressBar).width);
1188 timerProgressBar.style.removeProperty('transition');
1189 timerProgressBar.style.width = '100%';
1190 const timerProgressBarFullWidth = parseInt(window.getComputedStyle(timerProgressBar).width);
1191 const timerProgressBarPercent = timerProgressBarWidth / timerProgressBarFullWidth * 100;
1192 timerProgressBar.style.width = `${timerProgressBarPercent}%`;
1193 };
1194
1195 /**
1196 * Detect Node env
1197 *
1198 * @returns {boolean}
1199 */
1200 const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined';
1201
1202 const sweetHTML = `
1203 <div aria-labelledby="${swalClasses.title}" aria-describedby="${swalClasses['html-container']}" class="${swalClasses.popup}" tabindex="-1">
1204 <button type="button" class="${swalClasses.close}"></button>
1205 <ul class="${swalClasses['progress-steps']}"></ul>
1206 <div class="${swalClasses.icon}"></div>
1207 <img class="${swalClasses.image}" />
1208 <h2 class="${swalClasses.title}" id="${swalClasses.title}"></h2>
1209 <div class="${swalClasses['html-container']}" id="${swalClasses['html-container']}"></div>
1210 <input class="${swalClasses.input}" id="${swalClasses.input}" />
1211 <input type="file" class="${swalClasses.file}" />
1212 <div class="${swalClasses.range}">
1213 <input type="range" />
1214 <output></output>
1215 </div>
1216 <select class="${swalClasses.select}" id="${swalClasses.select}"></select>
1217 <div class="${swalClasses.radio}"></div>
1218 <label class="${swalClasses.checkbox}">
1219 <input type="checkbox" id="${swalClasses.checkbox}" />
1220 <span class="${swalClasses.label}"></span>
1221 </label>
1222 <textarea class="${swalClasses.textarea}" id="${swalClasses.textarea}"></textarea>
1223 <div class="${swalClasses['validation-message']}" id="${swalClasses['validation-message']}"></div>
1224 <div class="${swalClasses.actions}">
1225 <div class="${swalClasses.loader}"></div>
1226 <button type="button" class="${swalClasses.confirm}"></button>
1227 <button type="button" class="${swalClasses.deny}"></button>
1228 <button type="button" class="${swalClasses.cancel}"></button>
1229 </div>
1230 <div class="${swalClasses.footer}"></div>
1231 <div class="${swalClasses['timer-progress-bar-container']}">
1232 <div class="${swalClasses['timer-progress-bar']}"></div>
1233 </div>
1234 </div>
1235 `.replace(/(^|\n)\s*/g, '');
1236
1237 /**
1238 * @returns {boolean}
1239 */
1240 const resetOldContainer = () => {
1241 const oldContainer = getContainer();
1242 if (!oldContainer) {
1243 return false;
1244 }
1245 oldContainer.remove();
1246 removeClass([document.documentElement, document.body], [swalClasses['no-backdrop'], swalClasses['toast-shown'],
1247 // @ts-ignore: 'has-column' is not defined in swalClasses but may be set dynamically
1248 swalClasses['has-column']]);
1249 return true;
1250 };
1251 const resetValidationMessage$1 = () => {
1252 if (globalState.currentInstance) {
1253 globalState.currentInstance.resetValidationMessage();
1254 }
1255 };
1256 const addInputChangeListeners = () => {
1257 const popup = getPopup();
1258 if (!popup) {
1259 return;
1260 }
1261 const input = getDirectChildByClass(popup, swalClasses.input);
1262 const file = getDirectChildByClass(popup, swalClasses.file);
1263 /** @type {HTMLInputElement | null} */
1264 const range = popup.querySelector(`.${swalClasses.range} input`);
1265 /** @type {HTMLOutputElement | null} */
1266 const rangeOutput = popup.querySelector(`.${swalClasses.range} output`);
1267 const select = getDirectChildByClass(popup, swalClasses.select);
1268 /** @type {HTMLInputElement | null} */
1269 const checkbox = popup.querySelector(`.${swalClasses.checkbox} input`);
1270 const textarea = getDirectChildByClass(popup, swalClasses.textarea);
1271 if (input) {
1272 input.oninput = resetValidationMessage$1;
1273 }
1274 if (file) {
1275 file.onchange = resetValidationMessage$1;
1276 }
1277 if (select) {
1278 select.onchange = resetValidationMessage$1;
1279 }
1280 if (checkbox) {
1281 checkbox.onchange = resetValidationMessage$1;
1282 }
1283 if (textarea) {
1284 textarea.oninput = resetValidationMessage$1;
1285 }
1286 if (range && rangeOutput) {
1287 range.oninput = () => {
1288 resetValidationMessage$1();
1289 rangeOutput.value = range.value;
1290 };
1291 range.onchange = () => {
1292 resetValidationMessage$1();
1293 rangeOutput.value = range.value;
1294 };
1295 }
1296 };
1297
1298 /**
1299 * @param {string | HTMLElement} target
1300 * @returns {HTMLElement}
1301 */
1302 const getTarget = target => {
1303 if (typeof target === 'string') {
1304 const element = document.querySelector(target);
1305 if (!element) {
1306 throw new Error(`Target element "${target}" not found`);
1307 }
1308 return /** @type {HTMLElement} */element;
1309 }
1310 return target;
1311 };
1312
1313 /**
1314 * @param {SweetAlertOptions} params
1315 */
1316 const setupAccessibility = params => {
1317 const popup = getPopup();
1318 if (!popup) {
1319 return;
1320 }
1321 popup.setAttribute('role', params.toast ? 'alert' : 'dialog');
1322 popup.setAttribute('aria-live', params.toast ? 'polite' : 'assertive');
1323 if (!params.toast) {
1324 popup.setAttribute('aria-modal', 'true');
1325 }
1326 };
1327
1328 /**
1329 * @param {HTMLElement} targetElement
1330 */
1331 const setupRTL = targetElement => {
1332 if (window.getComputedStyle(targetElement).direction === 'rtl') {
1333 addClass(getContainer(), swalClasses.rtl);
1334 globalState.isRTL = true;
1335 }
1336 };
1337
1338 /**
1339 * Add modal + backdrop to DOM
1340 *
1341 * @param {SweetAlertOptions} params
1342 */
1343 const init = params => {
1344 // Clean up the old popup container if it exists
1345 const oldContainerExisted = resetOldContainer();
1346 if (isNodeEnv()) {
1347 error('SweetAlert2 requires document to initialize');
1348 return;
1349 }
1350 const container = document.createElement('div');
1351 container.className = swalClasses.container;
1352 if (oldContainerExisted) {
1353 addClass(container, swalClasses['no-transition']);
1354 }
1355 setInnerHtml(container, sweetHTML);
1356 container.dataset['swal2Theme'] = params.theme;
1357 const targetElement = getTarget(params.target || 'body');
1358 targetElement.appendChild(container);
1359 if (params.topLayer) {
1360 container.setAttribute('popover', '');
1361 container.showPopover();
1362 }
1363 setupAccessibility(params);
1364 setupRTL(targetElement);
1365 addInputChangeListeners();
1366 };
1367
1368 /**
1369 * @param {HTMLElement | object | string} param
1370 * @param {HTMLElement} target
1371 */
1372 const parseHtmlToContainer = (param, target) => {
1373 // DOM element
1374 if (param instanceof HTMLElement) {
1375 target.appendChild(param);
1376 }
1377
1378 // Object
1379 else if (typeof param === 'object') {
1380 handleObject(param, target);
1381 }
1382
1383 // Plain string
1384 else if (param) {
1385 setInnerHtml(target, param);
1386 }
1387 };
1388
1389 /**
1390 * @param {object} param
1391 * @param {HTMLElement} target
1392 */
1393 const handleObject = (param, target) => {
1394 // JQuery element(s)
1395 if ('jquery' in param) {
1396 handleJqueryElem(target, param);
1397 }
1398
1399 // For other objects use their string representation
1400 else {
1401 setInnerHtml(target, param.toString());
1402 }
1403 };
1404
1405 /**
1406 * @param {HTMLElement} target
1407 * @param {any} elem
1408 */
1409 const handleJqueryElem = (target, elem) => {
1410 target.textContent = '';
1411 if (0 in elem) {
1412 for (let i = 0; i in elem; i++) {
1413 target.appendChild(elem[i].cloneNode(true));
1414 }
1415 } else {
1416 target.appendChild(elem.cloneNode(true));
1417 }
1418 };
1419
1420 /**
1421 * @param {SweetAlert} instance
1422 * @param {SweetAlertOptions} params
1423 */
1424 const renderActions = (instance, params) => {
1425 const actions = getActions();
1426 const loader = getLoader();
1427 if (!actions || !loader) {
1428 return;
1429 }
1430
1431 // Actions (buttons) wrapper
1432 if (!params.showConfirmButton && !params.showDenyButton && !params.showCancelButton) {
1433 hide(actions);
1434 } else {
1435 show(actions);
1436 }
1437
1438 // Custom class
1439 applyCustomClass(actions, params, 'actions');
1440
1441 // Render all the buttons
1442 renderButtons(actions, loader, params);
1443
1444 // Loader
1445 setInnerHtml(loader, params.loaderHtml || '');
1446 applyCustomClass(loader, params, 'loader');
1447 };
1448
1449 /**
1450 * @param {HTMLElement} actions
1451 * @param {HTMLElement} loader
1452 * @param {SweetAlertOptions} params
1453 */
1454 function renderButtons(actions, loader, params) {
1455 const confirmButton = getConfirmButton();
1456 const denyButton = getDenyButton();
1457 const cancelButton = getCancelButton();
1458 if (!confirmButton || !denyButton || !cancelButton) {
1459 return;
1460 }
1461
1462 // Render buttons
1463 renderButton(confirmButton, 'confirm', params);
1464 renderButton(denyButton, 'deny', params);
1465 renderButton(cancelButton, 'cancel', params);
1466 handleButtonsStyling(confirmButton, denyButton, cancelButton, params);
1467 if (params.reverseButtons) {
1468 if (params.toast) {
1469 actions.insertBefore(cancelButton, confirmButton);
1470 actions.insertBefore(denyButton, confirmButton);
1471 } else {
1472 actions.insertBefore(cancelButton, loader);
1473 actions.insertBefore(denyButton, loader);
1474 actions.insertBefore(confirmButton, loader);
1475 }
1476 }
1477 }
1478
1479 /**
1480 * @param {HTMLElement} confirmButton
1481 * @param {HTMLElement} denyButton
1482 * @param {HTMLElement} cancelButton
1483 * @param {SweetAlertOptions} params
1484 */
1485 function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) {
1486 if (!params.buttonsStyling) {
1487 removeClass([confirmButton, denyButton, cancelButton], swalClasses.styled);
1488 return;
1489 }
1490 addClass([confirmButton, denyButton, cancelButton], swalClasses.styled);
1491
1492 // Apply custom background colors and outline colors to action buttons
1493 /** @type {[HTMLElement, string, string | undefined][]} */
1494 const buttons = [[confirmButton, 'confirm', params.confirmButtonColor], [denyButton, 'deny', params.denyButtonColor], [cancelButton, 'cancel', params.cancelButtonColor]];
1495 buttons.forEach(([button, type, color]) => {
1496 if (color) {
1497 button.style.setProperty(`--swal2-${type}-button-background-color`, color);
1498 }
1499 applyOutlineColor(button);
1500 });
1501 }
1502
1503 /**
1504 * @param {HTMLElement} button
1505 */
1506 function applyOutlineColor(button) {
1507 const buttonStyle = window.getComputedStyle(button);
1508 if (buttonStyle.getPropertyValue('--swal2-action-button-focus-box-shadow')) {
1509 // If the button already has a custom outline color, no need to change it
1510 return;
1511 }
1512 const outlineColor = buttonStyle.backgroundColor.replace(/rgba?\((\d+), (\d+), (\d+).*/, 'rgba($1, $2, $3, 0.5)');
1513 button.style.setProperty('--swal2-action-button-focus-box-shadow', buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`));
1514 }
1515
1516 /**
1517 * @param {HTMLElement} button
1518 * @param {'confirm' | 'deny' | 'cancel'} buttonType
1519 * @param {SweetAlertOptions} params
1520 */
1521 function renderButton(button, buttonType, params) {
1522 const buttonName = /** @type {'Confirm' | 'Deny' | 'Cancel'} */capitalizeFirstLetter(buttonType);
1523 toggle(button, params[`show${buttonName}Button`], 'inline-block');
1524 setInnerHtml(button, params[`${buttonType}ButtonText`] || ''); // Set caption text
1525 button.setAttribute('aria-label', params[`${buttonType}ButtonAriaLabel`] || ''); // ARIA label
1526
1527 // Add buttons custom classes
1528 button.className = swalClasses[buttonType];
1529 applyCustomClass(button, params, `${buttonType}Button`);
1530 }
1531
1532 /**
1533 * @param {SweetAlert} instance
1534 * @param {SweetAlertOptions} params
1535 */
1536 const renderCloseButton = (instance, params) => {
1537 const closeButton = getCloseButton();
1538 if (!closeButton) {
1539 return;
1540 }
1541 setInnerHtml(closeButton, params.closeButtonHtml || '');
1542
1543 // Custom class
1544 applyCustomClass(closeButton, params, 'closeButton');
1545 toggle(closeButton, params.showCloseButton);
1546 closeButton.setAttribute('aria-label', params.closeButtonAriaLabel || '');
1547 };
1548
1549 /**
1550 * @param {SweetAlert} instance
1551 * @param {SweetAlertOptions} params
1552 */
1553 const renderContainer = (instance, params) => {
1554 const container = getContainer();
1555 if (!container) {
1556 return;
1557 }
1558 handleBackdropParam(container, params.backdrop);
1559 handlePositionParam(container, params.position);
1560 handleGrowParam(container, params.grow);
1561
1562 // Custom class
1563 applyCustomClass(container, params, 'container');
1564 };
1565
1566 /**
1567 * @param {HTMLElement} container
1568 * @param {SweetAlertOptions['backdrop']} backdrop
1569 */
1570 function handleBackdropParam(container, backdrop) {
1571 if (typeof backdrop === 'string') {
1572 container.style.background = backdrop;
1573 } else if (!backdrop) {
1574 addClass([document.documentElement, document.body], swalClasses['no-backdrop']);
1575 }
1576 }
1577
1578 /**
1579 * @param {HTMLElement} container
1580 * @param {SweetAlertOptions['position']} position
1581 */
1582 function handlePositionParam(container, position) {
1583 if (!position) {
1584 return;
1585 }
1586 if (position in swalClasses) {
1587 addClass(container, swalClasses[position]);
1588 } else {
1589 warn('The "position" parameter is not valid, defaulting to "center"');
1590 addClass(container, swalClasses.center);
1591 }
1592 }
1593
1594 /**
1595 * @param {HTMLElement} container
1596 * @param {SweetAlertOptions['grow']} grow
1597 */
1598 function handleGrowParam(container, grow) {
1599 if (!grow) {
1600 return;
1601 }
1602 addClass(container, swalClasses[`grow-${grow}`]);
1603 }
1604
1605 /**
1606 * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
1607 * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
1608 * This is the approach that Babel will probably take to implement private methods/fields
1609 * https://github.com/tc39/proposal-private-methods
1610 * https://github.com/babel/babel/pull/7555
1611 * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
1612 * then we can use that language feature.
1613 */
1614
1615 var privateProps = {
1616 innerParams: new WeakMap(),
1617 domCache: new WeakMap(),
1618 focusedElement: new WeakMap()
1619 };
1620
1621 /// <reference path="../../../../sweetalert2.d.ts"/>
1622
1623
1624 /** @type {InputClass[]} */
1625 const inputClasses = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea'];
1626
1627 /**
1628 * @param {SweetAlert} instance
1629 * @param {SweetAlertOptions} params
1630 */
1631 const renderInput = (instance, params) => {
1632 const popup = getPopup();
1633 if (!popup) {
1634 return;
1635 }
1636 const innerParams = privateProps.innerParams.get(instance);
1637 const rerender = !innerParams || params.input !== innerParams.input;
1638 inputClasses.forEach(inputClass => {
1639 const inputContainer = getDirectChildByClass(popup, swalClasses[inputClass]);
1640 if (!inputContainer) {
1641 return;
1642 }
1643
1644 // set attributes
1645 setAttributes(inputClass, params.inputAttributes);
1646
1647 // set class
1648 inputContainer.className = swalClasses[inputClass];
1649 if (rerender) {
1650 hide(inputContainer);
1651 }
1652 });
1653 if (params.input) {
1654 if (rerender) {
1655 showInput(params);
1656 }
1657 // set custom class
1658 setCustomClass(params);
1659 }
1660 };
1661
1662 /**
1663 * @param {SweetAlertOptions} params
1664 */
1665 const showInput = params => {
1666 if (!params.input) {
1667 return;
1668 }
1669 if (!renderInputType[params.input]) {
1670 error(`Unexpected type of input! Expected ${Object.keys(renderInputType).join(' | ')}, got "${params.input}"`);
1671 return;
1672 }
1673 const inputContainer = getInputContainer(params.input);
1674 if (!inputContainer) {
1675 return;
1676 }
1677 const input = renderInputType[params.input](inputContainer, params);
1678 show(inputContainer);
1679
1680 // input autofocus
1681 if (params.inputAutoFocus) {
1682 setTimeout(() => {
1683 focusInput(input);
1684 });
1685 }
1686 };
1687
1688 /**
1689 * @param {HTMLInputElement} input
1690 */
1691 const removeAttributes = input => {
1692 for (const {
1693 name
1694 } of Array.from(input.attributes)) {
1695 if (!['id', 'type', 'value', 'style'].includes(name)) {
1696 input.removeAttribute(name);
1697 }
1698 }
1699 };
1700
1701 /**
1702 * @param {InputClass} inputClass
1703 * @param {SweetAlertOptions['inputAttributes']} inputAttributes
1704 */
1705 const setAttributes = (inputClass, inputAttributes) => {
1706 const popup = getPopup();
1707 if (!popup) {
1708 return;
1709 }
1710 const input = getInput$1(popup, inputClass);
1711 if (!input) {
1712 return;
1713 }
1714 removeAttributes(input);
1715 for (const attr in inputAttributes) {
1716 input.setAttribute(attr, inputAttributes[attr]);
1717 }
1718 };
1719
1720 /**
1721 * @param {SweetAlertOptions} params
1722 */
1723 const setCustomClass = params => {
1724 if (!params.input) {
1725 return;
1726 }
1727 const inputContainer = getInputContainer(params.input);
1728 if (inputContainer) {
1729 applyCustomClass(inputContainer, params, 'input');
1730 }
1731 };
1732
1733 /**
1734 * @param {HTMLInputElement | HTMLTextAreaElement} input
1735 * @param {SweetAlertOptions} params
1736 */
1737 const setInputPlaceholder = (input, params) => {
1738 if (!input.placeholder && params.inputPlaceholder) {
1739 input.placeholder = params.inputPlaceholder;
1740 }
1741 };
1742
1743 /**
1744 * @param {Input} input
1745 * @param {Input} prependTo
1746 * @param {SweetAlertOptions} params
1747 */
1748 const setInputLabel = (input, prependTo, params) => {
1749 if (params.inputLabel) {
1750 const label = document.createElement('label');
1751 const labelClass = swalClasses['input-label'];
1752 label.setAttribute('for', input.id);
1753 label.className = labelClass;
1754 if (typeof params.customClass === 'object') {
1755 addClass(label, params.customClass.inputLabel);
1756 }
1757 label.innerText = params.inputLabel;
1758 prependTo.insertAdjacentElement('beforebegin', label);
1759 }
1760 };
1761
1762 /**
1763 * @param {SweetAlertInput} inputType
1764 * @returns {HTMLElement | undefined}
1765 */
1766 const getInputContainer = inputType => {
1767 const popup = getPopup();
1768 if (!popup) {
1769 return;
1770 }
1771 return getDirectChildByClass(popup, swalClasses[(/** @type {SwalClass} */inputType)] || swalClasses.input);
1772 };
1773
1774 /**
1775 * @param {HTMLInputElement | HTMLOutputElement | HTMLTextAreaElement} input
1776 * @param {SweetAlertOptions['inputValue']} inputValue
1777 */
1778 const checkAndSetInputValue = (input, inputValue) => {
1779 if (['string', 'number'].includes(typeof inputValue)) {
1780 input.value = `${inputValue}`;
1781 } else if (!isPromise(inputValue)) {
1782 warn(`Unexpected type of inputValue! Expected "string", "number" or "Promise", got "${typeof inputValue}"`);
1783 }
1784 };
1785
1786 /** @type {Record<SweetAlertInput, (input: Input | HTMLElement, params: SweetAlertOptions) => Input>} */
1787 const renderInputType = {};
1788
1789 /**
1790 * @param {Input | HTMLElement} input
1791 * @param {SweetAlertOptions} params
1792 * @returns {Input}
1793 */
1794 renderInputType.text = renderInputType.email = renderInputType.password = renderInputType.number = renderInputType.tel = renderInputType.url = renderInputType.search = renderInputType.date = renderInputType['datetime-local'] = renderInputType.time = renderInputType.week = renderInputType.month = /** @type {(input: Input | HTMLElement, params: SweetAlertOptions) => Input} */
1795 (input, params) => {
1796 // oxfmt-ignore
1797 const inputElement = /** @type {HTMLInputElement} */input;
1798 checkAndSetInputValue(inputElement, params.inputValue);
1799 setInputLabel(inputElement, inputElement, params);
1800 setInputPlaceholder(inputElement, params);
1801 // oxfmt-ignore
1802 inputElement.type = /** @type {string} */params.input;
1803 return inputElement;
1804 };
1805
1806 /**
1807 * @param {Input | HTMLElement} input
1808 * @param {SweetAlertOptions} params
1809 * @returns {Input}
1810 */
1811 renderInputType.file = (input, params) => {
1812 const inputElement = /** @type {HTMLInputElement} */input;
1813 setInputLabel(inputElement, inputElement, params);
1814 setInputPlaceholder(inputElement, params);
1815 return inputElement;
1816 };
1817
1818 /**
1819 * @param {Input | HTMLElement} range
1820 * @param {SweetAlertOptions} params
1821 * @returns {Input}
1822 */
1823 renderInputType.range = (range, params) => {
1824 const rangeContainer = /** @type {HTMLElement} */range;
1825 const rangeInput = rangeContainer.querySelector('input');
1826 const rangeOutput = rangeContainer.querySelector('output');
1827 if (rangeInput) {
1828 checkAndSetInputValue(rangeInput, params.inputValue);
1829 rangeInput.type = /** @type {string} */params.input;
1830 setInputLabel(rangeInput, /** @type {Input} */range, params);
1831 }
1832 if (rangeOutput) {
1833 checkAndSetInputValue(rangeOutput, params.inputValue);
1834 }
1835 return /** @type {Input} */range;
1836 };
1837
1838 /**
1839 * @param {Input | HTMLElement} select
1840 * @param {SweetAlertOptions} params
1841 * @returns {Input}
1842 */
1843 renderInputType.select = (select, params) => {
1844 const selectElement = /** @type {HTMLSelectElement} */select;
1845 selectElement.textContent = '';
1846 if (params.inputPlaceholder) {
1847 const placeholder = document.createElement('option');
1848 setInnerHtml(placeholder, params.inputPlaceholder);
1849 placeholder.value = '';
1850 placeholder.disabled = true;
1851 placeholder.selected = true;
1852 selectElement.appendChild(placeholder);
1853 }
1854 setInputLabel(selectElement, selectElement, params);
1855 return selectElement;
1856 };
1857
1858 /**
1859 * @param {Input | HTMLElement} radio
1860 * @returns {Input}
1861 */
1862 renderInputType.radio = radio => {
1863 const radioElement = /** @type {HTMLElement} */radio;
1864 radioElement.textContent = '';
1865 return /** @type {Input} */radio;
1866 };
1867
1868 /**
1869 * @param {Input | HTMLElement} checkboxContainer
1870 * @param {SweetAlertOptions} params
1871 * @returns {Input}
1872 */
1873 renderInputType.checkbox = (checkboxContainer, params) => {
1874 const popup = getPopup();
1875 if (!popup) {
1876 throw new Error('Popup not found');
1877 }
1878 const checkbox = getInput$1(popup, 'checkbox');
1879 if (!checkbox) {
1880 throw new Error('Checkbox input not found');
1881 }
1882 checkbox.value = '1';
1883 checkbox.checked = Boolean(params.inputValue);
1884 const containerElement = /** @type {HTMLElement} */checkboxContainer;
1885 const label = containerElement.querySelector('span');
1886 if (label) {
1887 const placeholderOrLabel = params.inputPlaceholder || params.inputLabel;
1888 if (placeholderOrLabel) {
1889 setInnerHtml(label, placeholderOrLabel);
1890 }
1891 }
1892 return checkbox;
1893 };
1894
1895 /**
1896 * @param {Input | HTMLElement} textarea
1897 * @param {SweetAlertOptions} params
1898 * @returns {Input}
1899 */
1900 renderInputType.textarea = (textarea, params) => {
1901 const textareaElement = /** @type {HTMLTextAreaElement} */textarea;
1902 checkAndSetInputValue(textareaElement, params.inputValue);
1903 setInputPlaceholder(textareaElement, params);
1904 setInputLabel(textareaElement, textareaElement, params);
1905
1906 /**
1907 * @param {HTMLElement} el
1908 * @returns {number}
1909 */
1910 const getMargin = el => parseInt(window.getComputedStyle(el).marginLeft) + parseInt(window.getComputedStyle(el).marginRight);
1911
1912 // https://github.com/sweetalert2/sweetalert2/issues/2291
1913 setTimeout(() => {
1914 // https://github.com/sweetalert2/sweetalert2/issues/1699
1915 if ('MutationObserver' in window) {
1916 const popup = getPopup();
1917 if (!popup) {
1918 return;
1919 }
1920 const initialPopupWidth = parseInt(window.getComputedStyle(popup).width);
1921 const textareaResizeHandler = () => {
1922 // check if texarea is still in document (i.e. popup wasn't closed in the meantime)
1923 if (!document.body.contains(textareaElement)) {
1924 return;
1925 }
1926 const textareaWidth = textareaElement.offsetWidth + getMargin(textareaElement);
1927 const popupElement = getPopup();
1928 if (popupElement) {
1929 if (textareaWidth > initialPopupWidth) {
1930 popupElement.style.width = `${textareaWidth}px`;
1931 } else {
1932 applyNumericalStyle(popupElement, 'width', params.width);
1933 }
1934 }
1935 };
1936 new MutationObserver(textareaResizeHandler).observe(textareaElement, {
1937 attributes: true,
1938 attributeFilter: ['style']
1939 });
1940 }
1941 });
1942 return textareaElement;
1943 };
1944
1945 /**
1946 * @param {SweetAlert} instance
1947 * @param {SweetAlertOptions} params
1948 */
1949 const renderContent = (instance, params) => {
1950 const htmlContainer = getHtmlContainer();
1951 if (!htmlContainer) {
1952 return;
1953 }
1954 showWhenInnerHtmlPresent(htmlContainer);
1955 applyCustomClass(htmlContainer, params, 'htmlContainer');
1956
1957 // Content as HTML
1958 if (params.html) {
1959 parseHtmlToContainer(params.html, htmlContainer);
1960 show(htmlContainer, 'block');
1961 }
1962
1963 // Content as plain text
1964 else if (params.text) {
1965 htmlContainer.textContent = params.text;
1966 show(htmlContainer, 'block');
1967 }
1968
1969 // No content
1970 else {
1971 hide(htmlContainer);
1972 }
1973 renderInput(instance, params);
1974 };
1975
1976 /**
1977 * @param {SweetAlert} instance
1978 * @param {SweetAlertOptions} params
1979 */
1980 const renderFooter = (instance, params) => {
1981 const footer = getFooter();
1982 if (!footer) {
1983 return;
1984 }
1985 showWhenInnerHtmlPresent(footer);
1986 toggle(footer, Boolean(params.footer), 'block');
1987 if (params.footer) {
1988 parseHtmlToContainer(params.footer, footer);
1989 }
1990
1991 // Custom class
1992 applyCustomClass(footer, params, 'footer');
1993 };
1994
1995 /**
1996 * @param {SweetAlert} instance
1997 * @param {SweetAlertOptions} params
1998 */
1999 const renderIcon = (instance, params) => {
2000 const innerParams = privateProps.innerParams.get(instance);
2001 const icon = getIcon();
2002 if (!icon) {
2003 return;
2004 }
2005
2006 // if the given icon already rendered, apply the styling without re-rendering the icon
2007 if (innerParams && params.icon === innerParams.icon) {
2008 // Custom or default content
2009 setContent(icon, params);
2010 applyStyles(icon, params);
2011 return;
2012 }
2013 if (!params.icon && !params.iconHtml) {
2014 hide(icon);
2015 return;
2016 }
2017 if (params.icon && Object.keys(iconTypes).indexOf(params.icon) === -1) {
2018 error(`Unknown icon! Expected "success", "error", "warning", "info" or "question", got "${params.icon}"`);
2019 hide(icon);
2020 return;
2021 }
2022 show(icon);
2023
2024 // Custom or default content
2025 setContent(icon, params);
2026 applyStyles(icon, params);
2027
2028 // Animate icon
2029 addClass(icon, params.showClass && params.showClass.icon);
2030
2031 // Re-adjust the success icon on system theme change
2032 const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)');
2033 colorSchemeQueryList.addEventListener('change', adjustSuccessIconBackgroundColor);
2034 };
2035
2036 /**
2037 * @param {HTMLElement} icon
2038 * @param {SweetAlertOptions} params
2039 */
2040 const applyStyles = (icon, params) => {
2041 for (const [iconType, iconClassName] of Object.entries(iconTypes)) {
2042 if (params.icon !== iconType) {
2043 removeClass(icon, iconClassName);
2044 }
2045 }
2046 addClass(icon, params.icon && iconTypes[params.icon]);
2047
2048 // Icon color
2049 setColor(icon, params);
2050
2051 // Success icon background color
2052 adjustSuccessIconBackgroundColor();
2053
2054 // Custom class
2055 applyCustomClass(icon, params, 'icon');
2056 };
2057
2058 // Adjust success icon background color to match the popup background color
2059 const adjustSuccessIconBackgroundColor = () => {
2060 const popup = getPopup();
2061 if (!popup) {
2062 return;
2063 }
2064 const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color');
2065 /** @type {NodeListOf<HTMLElement>} */
2066 const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix');
2067 successIconParts.forEach(part => {
2068 part.style.backgroundColor = popupBackgroundColor;
2069 });
2070 };
2071
2072 /**
2073 *
2074 * @param {SweetAlertOptions} params
2075 * @returns {string}
2076 */
2077 const successIconHtml = params => `
2078 ${params.animation ? '<div class="swal2-success-circular-line-left"></div>' : ''}
2079 <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>
2080 <div class="swal2-success-ring"></div>
2081 ${params.animation ? '<div class="swal2-success-fix"></div>' : ''}
2082 ${params.animation ? '<div class="swal2-success-circular-line-right"></div>' : ''}
2083 `;
2084 const errorIconHtml = `
2085 <span class="swal2-x-mark">
2086 <span class="swal2-x-mark-line-left"></span>
2087 <span class="swal2-x-mark-line-right"></span>
2088 </span>
2089 `;
2090
2091 /**
2092 * @param {HTMLElement} icon
2093 * @param {SweetAlertOptions} params
2094 */
2095 const setContent = (icon, params) => {
2096 if (!params.icon && !params.iconHtml) {
2097 return;
2098 }
2099 let oldContent = icon.innerHTML;
2100 let newContent = '';
2101 if (params.iconHtml) {
2102 newContent = iconContent(params.iconHtml);
2103 } else if (params.icon === 'success') {
2104 newContent = successIconHtml(params);
2105 oldContent = oldContent.replace(/ style=".*?"/g, ''); // undo adjustSuccessIconBackgroundColor()
2106 } else if (params.icon === 'error') {
2107 newContent = errorIconHtml;
2108 } else if (params.icon) {
2109 const defaultIconHtml = {
2110 question: '?',
2111 warning: '!',
2112 info: 'i'
2113 };
2114 newContent = iconContent(defaultIconHtml[params.icon]);
2115 }
2116 if (oldContent.trim() !== newContent.trim()) {
2117 setInnerHtml(icon, newContent);
2118 }
2119 };
2120
2121 /**
2122 * @param {HTMLElement} icon
2123 * @param {SweetAlertOptions} params
2124 */
2125 const setColor = (icon, params) => {
2126 if (!params.iconColor) {
2127 return;
2128 }
2129 icon.style.color = params.iconColor;
2130 icon.style.borderColor = params.iconColor;
2131 for (const sel of ['.swal2-success-line-tip', '.swal2-success-line-long', '.swal2-x-mark-line-left', '.swal2-x-mark-line-right']) {
2132 setStyle(icon, sel, 'background-color', params.iconColor);
2133 }
2134 setStyle(icon, '.swal2-success-ring', 'border-color', params.iconColor);
2135 };
2136
2137 /**
2138 * @param {string} content
2139 * @returns {string}
2140 */
2141 const iconContent = content => `<div class="${swalClasses['icon-content']}">${content}</div>`;
2142
2143 /**
2144 * @param {SweetAlert} instance
2145 * @param {SweetAlertOptions} params
2146 */
2147 const renderImage = (instance, params) => {
2148 const image = getImage();
2149 if (!image) {
2150 return;
2151 }
2152 if (!params.imageUrl) {
2153 hide(image);
2154 return;
2155 }
2156 show(image, '');
2157
2158 // Src, alt
2159 image.setAttribute('src', params.imageUrl);
2160 image.setAttribute('alt', params.imageAlt || '');
2161
2162 // Width, height
2163 applyNumericalStyle(image, 'width', params.imageWidth);
2164 applyNumericalStyle(image, 'height', params.imageHeight);
2165
2166 // Class
2167 image.className = swalClasses.image;
2168 applyCustomClass(image, params, 'image');
2169 };
2170
2171 let dragging = false;
2172 let mousedownX = 0;
2173 let mousedownY = 0;
2174 let initialX = 0;
2175 let initialY = 0;
2176
2177 /**
2178 * @param {HTMLElement} popup
2179 */
2180 const addDraggableListeners = popup => {
2181 popup.addEventListener('mousedown', down);
2182 document.body.addEventListener('mousemove', move);
2183 popup.addEventListener('mouseup', up);
2184 popup.addEventListener('touchstart', down);
2185 document.body.addEventListener('touchmove', move);
2186 popup.addEventListener('touchend', up);
2187 };
2188
2189 /**
2190 * @param {HTMLElement} popup
2191 */
2192 const removeDraggableListeners = popup => {
2193 popup.removeEventListener('mousedown', down);
2194 document.body.removeEventListener('mousemove', move);
2195 popup.removeEventListener('mouseup', up);
2196 popup.removeEventListener('touchstart', down);
2197 document.body.removeEventListener('touchmove', move);
2198 popup.removeEventListener('touchend', up);
2199 };
2200
2201 /**
2202 * @param {MouseEvent | TouchEvent} event
2203 */
2204 const down = event => {
2205 const popup = getPopup();
2206 if (!popup) {
2207 return;
2208 }
2209 const icon = getIcon();
2210 if (event.target === popup || icon && icon.contains(/** @type {HTMLElement} */event.target)) {
2211 dragging = true;
2212 const clientXY = getClientXY(event);
2213 mousedownX = clientXY.clientX;
2214 mousedownY = clientXY.clientY;
2215 initialX = parseInt(popup.style.insetInlineStart) || 0;
2216 initialY = parseInt(popup.style.insetBlockStart) || 0;
2217 addClass(popup, 'swal2-dragging');
2218 }
2219 };
2220
2221 /**
2222 * @param {MouseEvent | TouchEvent} event
2223 */
2224 const move = event => {
2225 const popup = getPopup();
2226 if (!popup) {
2227 return;
2228 }
2229 if (dragging) {
2230 let {
2231 clientX,
2232 clientY
2233 } = getClientXY(event);
2234 const deltaX = clientX - mousedownX;
2235 // In RTL mode, negate the horizontal delta since insetInlineStart refers to the right edge
2236 popup.style.insetInlineStart = `${initialX + (globalState.isRTL ? -deltaX : deltaX)}px`;
2237 popup.style.insetBlockStart = `${initialY + (clientY - mousedownY)}px`;
2238 }
2239 };
2240 const up = () => {
2241 const popup = getPopup();
2242 dragging = false;
2243 removeClass(popup, 'swal2-dragging');
2244 };
2245
2246 /**
2247 * @param {MouseEvent | TouchEvent} event
2248 * @returns {{ clientX: number, clientY: number }}
2249 */
2250 const getClientXY = event => {
2251 const source = event.type.startsWith('touch') ? /** @type {TouchEvent} */event.touches[0] : (/** @type {MouseEvent} */event);
2252 return {
2253 clientX: source.clientX,
2254 clientY: source.clientY
2255 };
2256 };
2257
2258 /**
2259 * @param {SweetAlert} instance
2260 * @param {SweetAlertOptions} params
2261 */
2262 const renderPopup = (instance, params) => {
2263 const container = getContainer();
2264 const popup = getPopup();
2265 if (!container || !popup) {
2266 return;
2267 }
2268
2269 // Width
2270 // https://github.com/sweetalert2/sweetalert2/issues/2170
2271 if (params.toast) {
2272 applyNumericalStyle(container, 'width', params.width);
2273 popup.style.width = '100%';
2274 const loader = getLoader();
2275 if (loader) {
2276 popup.insertBefore(loader, getIcon());
2277 }
2278 } else {
2279 applyNumericalStyle(popup, 'width', params.width);
2280 }
2281
2282 // Padding
2283 applyNumericalStyle(popup, 'padding', params.padding);
2284
2285 // Color
2286 if (params.color) {
2287 popup.style.color = params.color;
2288 }
2289
2290 // Background
2291 if (params.background) {
2292 popup.style.background = params.background;
2293 }
2294 hide(getValidationMessage());
2295
2296 // Classes
2297 addClasses$1(popup, params);
2298 if (params.draggable && !params.toast) {
2299 addClass(popup, swalClasses.draggable);
2300 addDraggableListeners(popup);
2301 } else {
2302 removeClass(popup, swalClasses.draggable);
2303 removeDraggableListeners(popup);
2304 }
2305 };
2306
2307 /**
2308 * @param {HTMLElement} popup
2309 * @param {SweetAlertOptions} params
2310 */
2311 const addClasses$1 = (popup, params) => {
2312 const showClass = params.showClass || {};
2313 // Default Class + showClass when updating Swal.update({})
2314 popup.className = `${swalClasses.popup} ${isVisible$1(popup) ? showClass.popup : ''}`;
2315 if (params.toast) {
2316 addClass([document.documentElement, document.body], swalClasses['toast-shown']);
2317 addClass(popup, swalClasses.toast);
2318 } else {
2319 addClass(popup, swalClasses.modal);
2320 }
2321
2322 // Custom class
2323 applyCustomClass(popup, params, 'popup');
2324 // TODO: remove in the next major
2325 if (typeof params.customClass === 'string') {
2326 addClass(popup, params.customClass);
2327 }
2328
2329 // Icon class (#1842)
2330 if (params.icon) {
2331 addClass(popup, swalClasses[`icon-${params.icon}`]);
2332 }
2333 };
2334
2335 /**
2336 * @param {SweetAlert} instance
2337 * @param {SweetAlertOptions} params
2338 */
2339 const renderProgressSteps = (instance, params) => {
2340 const progressStepsContainer = getProgressSteps();
2341 if (!progressStepsContainer) {
2342 return;
2343 }
2344 const {
2345 progressSteps,
2346 currentProgressStep
2347 } = params;
2348 if (!progressSteps || progressSteps.length === 0 || currentProgressStep === undefined) {
2349 hide(progressStepsContainer);
2350 return;
2351 }
2352 show(progressStepsContainer);
2353 progressStepsContainer.textContent = '';
2354 if (currentProgressStep >= progressSteps.length) {
2355 warn('Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)');
2356 }
2357 progressSteps.forEach((step, index) => {
2358 const stepEl = createStepElement(step);
2359 progressStepsContainer.appendChild(stepEl);
2360 if (index === currentProgressStep) {
2361 addClass(stepEl, swalClasses['active-progress-step']);
2362 }
2363 if (index !== progressSteps.length - 1) {
2364 const lineEl = createLineElement(params);
2365 progressStepsContainer.appendChild(lineEl);
2366 }
2367 });
2368 };
2369
2370 /**
2371 * @param {string} step
2372 * @returns {HTMLLIElement}
2373 */
2374 const createStepElement = step => {
2375 const stepEl = document.createElement('li');
2376 addClass(stepEl, swalClasses['progress-step']);
2377 setInnerHtml(stepEl, step);
2378 return stepEl;
2379 };
2380
2381 /**
2382 * @param {SweetAlertOptions} params
2383 * @returns {HTMLLIElement}
2384 */
2385 const createLineElement = params => {
2386 const lineEl = document.createElement('li');
2387 addClass(lineEl, swalClasses['progress-step-line']);
2388 if (params.progressStepsDistance) {
2389 applyNumericalStyle(lineEl, 'width', params.progressStepsDistance);
2390 }
2391 return lineEl;
2392 };
2393
2394 /**
2395 * @param {SweetAlert} instance
2396 * @param {SweetAlertOptions} params
2397 */
2398 const renderTitle = (instance, params) => {
2399 const title = getTitle();
2400 if (!title) {
2401 return;
2402 }
2403 showWhenInnerHtmlPresent(title);
2404 toggle(title, Boolean(params.title || params.titleText), 'block');
2405 if (params.title) {
2406 parseHtmlToContainer(params.title, title);
2407 }
2408 if (params.titleText) {
2409 title.innerText = params.titleText;
2410 }
2411
2412 // Custom class
2413 applyCustomClass(title, params, 'title');
2414 };
2415
2416 /**
2417 * @param {SweetAlert} instance
2418 * @param {SweetAlertOptions} params
2419 */
2420 const render = (instance, params) => {
2421 var _globalState$eventEmi;
2422 renderPopup(instance, params);
2423 renderContainer(instance, params);
2424 renderProgressSteps(instance, params);
2425 renderIcon(instance, params);
2426 renderImage(instance, params);
2427 renderTitle(instance, params);
2428 renderCloseButton(instance, params);
2429 renderContent(instance, params);
2430 renderActions(instance, params);
2431 renderFooter(instance, params);
2432 const popup = getPopup();
2433 if (typeof params.didRender === 'function' && popup) {
2434 params.didRender(popup);
2435 }
2436 (_globalState$eventEmi = globalState.eventEmitter) === null || _globalState$eventEmi === void 0 || _globalState$eventEmi.emit('didRender', popup);
2437 };
2438
2439 /*
2440 * Global function to determine if SweetAlert2 popup is shown
2441 */
2442 const isVisible = () => {
2443 return isVisible$1(getPopup());
2444 };
2445
2446 /*
2447 * Global function to click 'Confirm' button
2448 */
2449 const clickConfirm = () => {
2450 var _dom$getConfirmButton;
2451 return (_dom$getConfirmButton = getConfirmButton()) === null || _dom$getConfirmButton === void 0 ? void 0 : _dom$getConfirmButton.click();
2452 };
2453
2454 /*
2455 * Global function to click 'Deny' button
2456 */
2457 const clickDeny = () => {
2458 var _dom$getDenyButton;
2459 return (_dom$getDenyButton = getDenyButton()) === null || _dom$getDenyButton === void 0 ? void 0 : _dom$getDenyButton.click();
2460 };
2461
2462 /*
2463 * Global function to click 'Cancel' button
2464 */
2465 const clickCancel = () => {
2466 var _dom$getCancelButton;
2467 return (_dom$getCancelButton = getCancelButton()) === null || _dom$getCancelButton === void 0 ? void 0 : _dom$getCancelButton.click();
2468 };
2469
2470 /** @type {Record<DismissReason, DismissReason>} */
2471 const DismissReason = Object.freeze({
2472 cancel: 'cancel',
2473 backdrop: 'backdrop',
2474 close: 'close',
2475 esc: 'esc',
2476 timer: 'timer'
2477 });
2478
2479 /**
2480 * @param {GlobalState} globalState
2481 */
2482 const removeKeydownHandler = globalState => {
2483 if (globalState.keydownTarget && globalState.keydownHandlerAdded && globalState.keydownHandler) {
2484 const handler = /** @type {EventListenerOrEventListenerObject} */
2485 /** @type {unknown} */globalState.keydownHandler;
2486 globalState.keydownTarget.removeEventListener('keydown', handler, {
2487 capture: globalState.keydownListenerCapture
2488 });
2489 globalState.keydownHandlerAdded = false;
2490 }
2491 };
2492
2493 /**
2494 * @param {GlobalState} globalState
2495 * @param {SweetAlertOptions} innerParams
2496 * @param {(dismiss: DismissReason) => void} dismissWith
2497 */
2498 const addKeydownHandler = (globalState, innerParams, dismissWith) => {
2499 removeKeydownHandler(globalState);
2500 if (!innerParams.toast) {
2501 /** @type {(this: HTMLElement, event: KeyboardEvent) => void} */
2502 const handler = e => keydownHandler(innerParams, e, dismissWith);
2503 globalState.keydownHandler = handler;
2504 const target = innerParams.keydownListenerCapture ? window : getPopup();
2505 if (target) {
2506 globalState.keydownTarget = target;
2507 globalState.keydownListenerCapture = innerParams.keydownListenerCapture;
2508 const eventHandler = /** @type {EventListenerOrEventListenerObject} */ /** @type {unknown} */handler;
2509 globalState.keydownTarget.addEventListener('keydown', eventHandler, {
2510 capture: globalState.keydownListenerCapture
2511 });
2512 globalState.keydownHandlerAdded = true;
2513 }
2514 }
2515 };
2516
2517 /**
2518 * @param {number} index
2519 * @param {number} increment
2520 * @returns {boolean} shouldPreventDefault
2521 */
2522 const setFocus = (index, increment) => {
2523 var _dom$getPopup;
2524 const focusableElements = getFocusableElements();
2525 // search for visible elements and select the next possible match
2526 if (focusableElements.length) {
2527 index = index + increment;
2528
2529 // shift + tab when .swal2-popup is focused
2530 if (index === -2) {
2531 index = focusableElements.length - 1;
2532 }
2533
2534 // rollover to first item
2535 if (index === focusableElements.length) {
2536 index = 0;
2537
2538 // go to last item
2539 } else if (index === -1) {
2540 index = focusableElements.length - 1;
2541 }
2542 focusableElements[index].focus();
2543
2544 // don't prevent default for iframes (Firefox fix)
2545 // https://github.com/sweetalert2/sweetalert2/issues/2931
2546 if (isFirefox() && focusableElements[index] instanceof HTMLIFrameElement) {
2547 return false;
2548 }
2549 return true;
2550 }
2551 // no visible focusable elements, focus the popup
2552 (_dom$getPopup = getPopup()) === null || _dom$getPopup === void 0 || _dom$getPopup.focus();
2553 return true;
2554 };
2555 const arrowKeysNextButton = ['ArrowRight', 'ArrowDown'];
2556 const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp'];
2557
2558 /**
2559 * @param {SweetAlertOptions} innerParams
2560 * @param {KeyboardEvent} event
2561 * @param {(dismiss: DismissReason) => void} dismissWith
2562 */
2563 const keydownHandler = (innerParams, event, dismissWith) => {
2564 if (!innerParams) {
2565 return; // This instance has already been destroyed
2566 }
2567
2568 // Ignore keydown during IME composition
2569 // https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event#ignoring_keydown_during_ime_composition
2570 // https://github.com/sweetalert2/sweetalert2/issues/720
2571 // https://github.com/sweetalert2/sweetalert2/issues/2406
2572 if (event.isComposing || event.keyCode === 229) {
2573 return;
2574 }
2575 if (innerParams.stopKeydownPropagation) {
2576 event.stopPropagation();
2577 }
2578
2579 // ENTER
2580 if (event.key === 'Enter') {
2581 handleEnter(event, innerParams);
2582 }
2583
2584 // TAB
2585 else if (event.key === 'Tab') {
2586 handleTab(event);
2587 }
2588
2589 // ARROWS - switch focus between buttons
2590 else if ([...arrowKeysNextButton, ...arrowKeysPreviousButton].includes(event.key)) {
2591 handleArrows(event.key);
2592 }
2593
2594 // ESC
2595 else if (event.key === 'Escape') {
2596 handleEsc(event, innerParams, dismissWith);
2597 }
2598 };
2599
2600 /**
2601 * @param {KeyboardEvent} event
2602 * @param {SweetAlertOptions} innerParams
2603 */
2604 const handleEnter = (event, innerParams) => {
2605 // https://github.com/sweetalert2/sweetalert2/issues/2386
2606 if (!callIfFunction(innerParams.allowEnterKey)) {
2607 return;
2608 }
2609 const popup = getPopup();
2610 if (!popup || !innerParams.input) {
2611 return;
2612 }
2613 const input = getInput$1(popup, innerParams.input);
2614 if (event.target && input && event.target instanceof HTMLElement && event.target.outerHTML === input.outerHTML) {
2615 if (['textarea', 'file'].includes(innerParams.input)) {
2616 return; // do not submit
2617 }
2618 clickConfirm();
2619 event.preventDefault();
2620 }
2621 };
2622
2623 /**
2624 * @param {KeyboardEvent} event
2625 */
2626 const handleTab = event => {
2627 const targetElement = event.target;
2628 const focusableElements = getFocusableElements();
2629 const btnIndex = focusableElements.findIndex(el => el === targetElement);
2630
2631 // don't prevent default for iframes (Firefox fix)
2632 // https://github.com/sweetalert2/sweetalert2/issues/2931
2633 let shouldPreventDefault = true;
2634
2635 // Cycle to the next button
2636 if (!event.shiftKey) {
2637 shouldPreventDefault = setFocus(btnIndex, 1);
2638 }
2639
2640 // Cycle to the prev button
2641 else {
2642 shouldPreventDefault = setFocus(btnIndex, -1);
2643 }
2644 event.stopPropagation();
2645 if (shouldPreventDefault) {
2646 event.preventDefault();
2647 }
2648 };
2649
2650 /**
2651 * @param {string} key
2652 */
2653 const handleArrows = key => {
2654 const actions = getActions();
2655 const confirmButton = getConfirmButton();
2656 const denyButton = getDenyButton();
2657 const cancelButton = getCancelButton();
2658 if (!actions || !confirmButton || !denyButton || !cancelButton) {
2659 return;
2660 }
2661 /** @type HTMLElement[] */
2662 const buttons = [confirmButton, denyButton, cancelButton];
2663 if (document.activeElement instanceof HTMLElement && !buttons.includes(document.activeElement)) {
2664 return;
2665 }
2666 const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling';
2667 let buttonToFocus = document.activeElement;
2668 if (!buttonToFocus) {
2669 return;
2670 }
2671 for (let i = 0; i < actions.children.length; i++) {
2672 buttonToFocus = buttonToFocus[sibling];
2673 if (!buttonToFocus) {
2674 return;
2675 }
2676 if (buttonToFocus instanceof HTMLButtonElement && isVisible$1(buttonToFocus)) {
2677 break;
2678 }
2679 }
2680 if (buttonToFocus instanceof HTMLButtonElement) {
2681 buttonToFocus.focus();
2682 }
2683 };
2684
2685 /**
2686 * @param {KeyboardEvent} event
2687 * @param {SweetAlertOptions} innerParams
2688 * @param {(dismiss: DismissReason) => void} dismissWith
2689 */
2690 const handleEsc = (event, innerParams, dismissWith) => {
2691 event.preventDefault();
2692 if (callIfFunction(innerParams.allowEscapeKey)) {
2693 dismissWith(DismissReason.esc);
2694 }
2695 };
2696
2697 /**
2698 * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
2699 * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
2700 * This is the approach that Babel will probably take to implement private methods/fields
2701 * https://github.com/tc39/proposal-private-methods
2702 * https://github.com/babel/babel/pull/7555
2703 * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
2704 * then we can use that language feature.
2705 */
2706
2707 var privateMethods = {
2708 swalPromiseResolve: new WeakMap(),
2709 swalPromiseReject: new WeakMap()
2710 };
2711
2712 // From https://developer.paciellogroup.com/blog/2018/06/the-current-state-of-modal-dialog-accessibility/
2713 // Adding aria-hidden="true" to elements outside of the active modal dialog ensures that
2714 // elements not within the active modal dialog will not be surfaced if a user opens a screen
2715 // reader’s list of elements (headings, form controls, landmarks, etc.) in the document.
2716
2717 const setAriaHidden = () => {
2718 const container = getContainer();
2719 const bodyChildren = Array.from(document.body.children);
2720 bodyChildren.forEach(el => {
2721 if (el.contains(container)) {
2722 return;
2723 }
2724 if (el.hasAttribute('aria-hidden')) {
2725 el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden') || '');
2726 }
2727 el.setAttribute('aria-hidden', 'true');
2728 });
2729 };
2730 const unsetAriaHidden = () => {
2731 const bodyChildren = Array.from(document.body.children);
2732 bodyChildren.forEach(el => {
2733 if (el.hasAttribute('data-previous-aria-hidden')) {
2734 el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden') || '');
2735 el.removeAttribute('data-previous-aria-hidden');
2736 } else {
2737 el.removeAttribute('aria-hidden');
2738 }
2739 });
2740 };
2741
2742 // @ts-ignore
2743 const isSafariOrIOS = typeof window !== 'undefined' && Boolean(window.GestureEvent); // true for Safari desktop + all iOS browsers https://stackoverflow.com/a/70585394
2744
2745 // @ts-ignore
2746 const isIOS = isSafariOrIOS && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
2747
2748 /**
2749 * Fix iOS scrolling
2750 * http://stackoverflow.com/q/39626302
2751 */
2752 const iOSfix = () => {
2753 if (isSafariOrIOS && !hasClass(document.body, swalClasses.iosfix)) {
2754 const offset = document.body.scrollTop;
2755 document.body.style.top = `${offset * -1}px`;
2756 addClass(document.body, swalClasses.iosfix);
2757 lockBodyScroll();
2758 }
2759 };
2760
2761 /**
2762 * https://github.com/sweetalert2/sweetalert2/issues/1246
2763 */
2764 const lockBodyScroll = () => {
2765 const container = getContainer();
2766 if (!container) {
2767 return;
2768 }
2769 /** @type {boolean} */
2770 let preventTouchMove;
2771 /**
2772 * @param {TouchEvent} event
2773 */
2774 container.ontouchstart = event => {
2775 preventTouchMove = shouldPreventTouchMove(event);
2776 };
2777 /**
2778 * @param {TouchEvent} event
2779 */
2780 container.ontouchmove = event => {
2781 if (preventTouchMove) {
2782 event.preventDefault();
2783 event.stopPropagation();
2784 }
2785 };
2786 };
2787
2788 /**
2789 * @param {TouchEvent} event
2790 * @returns {boolean}
2791 */
2792 const shouldPreventTouchMove = event => {
2793 const target = event.target;
2794 const container = getContainer();
2795 const htmlContainer = getHtmlContainer();
2796 if (!container || !htmlContainer) {
2797 return false;
2798 }
2799 if (isStylus(event) || isZoom(event)) {
2800 return false;
2801 }
2802 if (target === container) {
2803 return true;
2804 }
2805 if (!isScrollable(container) && target instanceof HTMLElement && !selfOrParentIsScrollable(target, htmlContainer) &&
2806 // #2823
2807 target.tagName !== 'INPUT' &&
2808 // #1603
2809 target.tagName !== 'TEXTAREA' &&
2810 // #2266
2811 !(isScrollable(htmlContainer) &&
2812 // #1944
2813 htmlContainer.contains(target))) {
2814 return true;
2815 }
2816 return false;
2817 };
2818
2819 /**
2820 * https://github.com/sweetalert2/sweetalert2/issues/1786
2821 *
2822 * @param {TouchEvent} event
2823 * @returns {boolean}
2824 */
2825 const isStylus = event => {
2826 return Boolean(event.touches && event.touches.length &&
2827 // @ts-ignore - touchType is not a standard property
2828 event.touches[0].touchType === 'stylus');
2829 };
2830
2831 /**
2832 * https://github.com/sweetalert2/sweetalert2/issues/1891
2833 *
2834 * @param {TouchEvent} event
2835 * @returns {boolean}
2836 */
2837 const isZoom = event => {
2838 return event.touches && event.touches.length > 1;
2839 };
2840 const undoIOSfix = () => {
2841 if (hasClass(document.body, swalClasses.iosfix)) {
2842 const offset = parseInt(document.body.style.top, 10);
2843 removeClass(document.body, swalClasses.iosfix);
2844 document.body.style.top = '';
2845 document.body.scrollTop = offset * -1;
2846 }
2847 };
2848
2849 /**
2850 * Measure scrollbar width for padding body during modal show/hide
2851 * https://github.com/twbs/bootstrap/blob/master/js/src/modal.js
2852 *
2853 * @returns {number}
2854 */
2855 const measureScrollbar = () => {
2856 const scrollDiv = document.createElement('div');
2857 scrollDiv.className = swalClasses['scrollbar-measure'];
2858 document.body.appendChild(scrollDiv);
2859 const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
2860 document.body.removeChild(scrollDiv);
2861 return scrollbarWidth;
2862 };
2863
2864 /**
2865 * Remember state in cases where opening and handling a modal will fiddle with it.
2866 * @type {number | null}
2867 */
2868 let previousBodyPadding = null;
2869
2870 /**
2871 * @param {string} initialBodyOverflow
2872 */
2873 const replaceScrollbarWithPadding = initialBodyOverflow => {
2874 // for queues, do not do this more than once
2875 if (previousBodyPadding !== null) {
2876 return;
2877 }
2878 // if the body has overflow
2879 if (document.body.scrollHeight > window.innerHeight || initialBodyOverflow === 'scroll' // https://github.com/sweetalert2/sweetalert2/issues/2663
2880 ) {
2881 // add padding so the content doesn't shift after removal of scrollbar
2882 previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'));
2883 document.body.style.paddingRight = `${previousBodyPadding + measureScrollbar()}px`;
2884 }
2885 };
2886 const undoReplaceScrollbarWithPadding = () => {
2887 if (previousBodyPadding !== null) {
2888 document.body.style.paddingRight = `${previousBodyPadding}px`;
2889 previousBodyPadding = null;
2890 }
2891 };
2892
2893 /**
2894 * @param {SweetAlert} instance
2895 * @param {HTMLElement} container
2896 * @param {boolean} returnFocus
2897 * @param {(() => void) | undefined} didClose
2898 */
2899 function removePopupAndResetState(instance, container, returnFocus, didClose) {
2900 if (isToast()) {
2901 triggerDidCloseAndDispose(instance, didClose);
2902 } else {
2903 restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose));
2904 removeKeydownHandler(globalState);
2905 }
2906
2907 // workaround for https://github.com/sweetalert2/sweetalert2/issues/2088
2908 // for some reason removing the container in Safari will scroll the document to bottom
2909 if (isSafariOrIOS) {
2910 container.setAttribute('style', 'display:none !important');
2911 container.removeAttribute('class');
2912 container.innerHTML = '';
2913 } else {
2914 container.remove();
2915 }
2916 if (isModal()) {
2917 undoReplaceScrollbarWithPadding();
2918 undoIOSfix();
2919 unsetAriaHidden();
2920 }
2921 removeBodyClasses();
2922 }
2923
2924 /**
2925 * Remove SweetAlert2 classes from body
2926 */
2927 function removeBodyClasses() {
2928 removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]);
2929 }
2930
2931 /**
2932 * Instance method to close sweetAlert
2933 *
2934 * @param {SweetAlertResult | undefined} resolveValue
2935 * @this {SweetAlert}
2936 */
2937 function close(resolveValue) {
2938 resolveValue = prepareResolveValue(resolveValue);
2939 const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this);
2940 const didClose = triggerClosePopup(this);
2941 if (this.isAwaitingPromise) {
2942 // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
2943 if (!resolveValue.isDismissed) {
2944 handleAwaitingPromise(this);
2945 swalPromiseResolve(resolveValue);
2946 }
2947 } else if (didClose) {
2948 // Resolve Swal promise
2949 swalPromiseResolve(resolveValue);
2950 }
2951 }
2952
2953 /**
2954 * @param {SweetAlert} instance
2955 * @returns {boolean}
2956 */
2957 const triggerClosePopup = instance => {
2958 const popup = getPopup();
2959 if (!popup) {
2960 return false;
2961 }
2962 const innerParams = privateProps.innerParams.get(instance);
2963 if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) {
2964 return false;
2965 }
2966 removeClass(popup, innerParams.showClass.popup);
2967 addClass(popup, innerParams.hideClass.popup);
2968 const backdrop = getContainer();
2969 removeClass(backdrop, innerParams.showClass.backdrop);
2970 addClass(backdrop, innerParams.hideClass.backdrop);
2971 handlePopupAnimation(instance, popup, innerParams);
2972 return true;
2973 };
2974
2975 /**
2976 * @param {Error | string} error
2977 * @this {SweetAlert}
2978 */
2979 function rejectPromise(error) {
2980 const rejectPromise = privateMethods.swalPromiseReject.get(this);
2981 handleAwaitingPromise(this);
2982 if (rejectPromise) {
2983 // Reject Swal promise
2984 rejectPromise(error);
2985 }
2986 }
2987
2988 /**
2989 * @param {SweetAlert} instance
2990 */
2991 const handleAwaitingPromise = instance => {
2992 if (instance.isAwaitingPromise) {
2993 // @ts-ignore
2994 delete instance.isAwaitingPromise;
2995 // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
2996 if (!privateProps.innerParams.get(instance)) {
2997 instance._destroy();
2998 }
2999 }
3000 };
3001
3002 /**
3003 * @param {SweetAlertResult | undefined} resolveValue
3004 * @returns {SweetAlertResult}
3005 */
3006 const prepareResolveValue = resolveValue => {
3007 // When user calls Swal.close()
3008 if (typeof resolveValue === 'undefined') {
3009 return {
3010 isConfirmed: false,
3011 isDenied: false,
3012 isDismissed: true
3013 };
3014 }
3015 return Object.assign({
3016 isConfirmed: false,
3017 isDenied: false,
3018 isDismissed: false
3019 }, resolveValue);
3020 };
3021
3022 /**
3023 * @param {SweetAlert} instance
3024 * @param {HTMLElement} popup
3025 * @param {SweetAlertOptions} innerParams
3026 */
3027 const handlePopupAnimation = (instance, popup, innerParams) => {
3028 var _globalState$eventEmi;
3029 const container = getContainer();
3030 // If animation is supported, animate
3031 const animationIsSupported = hasCssAnimation(popup);
3032 if (typeof innerParams.willClose === 'function') {
3033 innerParams.willClose(popup);
3034 }
3035 (_globalState$eventEmi = globalState.eventEmitter) === null || _globalState$eventEmi === void 0 || _globalState$eventEmi.emit('willClose', popup);
3036 if (animationIsSupported && container) {
3037 animatePopup(instance, popup, container, Boolean(innerParams.returnFocus), innerParams.didClose);
3038 } else if (container) {
3039 // Otherwise, remove immediately
3040 removePopupAndResetState(instance, container, Boolean(innerParams.returnFocus), innerParams.didClose);
3041 }
3042 };
3043
3044 /**
3045 * @param {SweetAlert} instance
3046 * @param {HTMLElement} popup
3047 * @param {HTMLElement} container
3048 * @param {boolean} returnFocus
3049 * @param {(() => void) | undefined} didClose
3050 */
3051 const animatePopup = (instance, popup, container, returnFocus, didClose) => {
3052 globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose);
3053 /**
3054 * @param {AnimationEvent | TransitionEvent} e
3055 */
3056 const swalCloseAnimationFinished = function (e) {
3057 if (e.target === popup) {
3058 var _globalState$swalClos;
3059 (_globalState$swalClos = globalState.swalCloseEventFinishedCallback) === null || _globalState$swalClos === void 0 || _globalState$swalClos.call(globalState);
3060 delete globalState.swalCloseEventFinishedCallback;
3061 popup.removeEventListener('animationend', swalCloseAnimationFinished);
3062 popup.removeEventListener('transitionend', swalCloseAnimationFinished);
3063 }
3064 };
3065 popup.addEventListener('animationend', swalCloseAnimationFinished);
3066 popup.addEventListener('transitionend', swalCloseAnimationFinished);
3067 };
3068
3069 /**
3070 * @param {SweetAlert} instance
3071 * @param {(() => void) | undefined} didClose
3072 */
3073 const triggerDidCloseAndDispose = (instance, didClose) => {
3074 setTimeout(() => {
3075 var _globalState$eventEmi2;
3076 if (typeof didClose === 'function') {
3077 didClose.bind(instance.params)();
3078 }
3079 (_globalState$eventEmi2 = globalState.eventEmitter) === null || _globalState$eventEmi2 === void 0 || _globalState$eventEmi2.emit('didClose');
3080 // instance might have been destroyed already
3081 if (instance._destroy) {
3082 instance._destroy();
3083 }
3084 });
3085 };
3086
3087 /**
3088 * Shows loader (spinner), this is useful with AJAX requests.
3089 * By default the loader be shown instead of the "Confirm" button.
3090 *
3091 * @param {HTMLButtonElement | null} [buttonToReplace]
3092 */
3093 const showLoading = buttonToReplace => {
3094 let popup = getPopup();
3095 if (!popup) {
3096 new Swal();
3097 }
3098 popup = getPopup();
3099 if (!popup) {
3100 return;
3101 }
3102 const loader = getLoader();
3103 if (isToast()) {
3104 hide(getIcon());
3105 } else {
3106 replaceButton(popup, buttonToReplace);
3107 }
3108 show(loader);
3109 popup.setAttribute('data-loading', 'true');
3110 popup.setAttribute('aria-busy', 'true');
3111 popup.focus();
3112 };
3113
3114 /**
3115 * @param {HTMLElement} popup
3116 * @param {HTMLButtonElement | null} [buttonToReplace]
3117 */
3118 const replaceButton = (popup, buttonToReplace) => {
3119 const actions = getActions();
3120 const loader = getLoader();
3121 if (!actions || !loader) {
3122 return;
3123 }
3124 if (!buttonToReplace && isVisible$1(getConfirmButton())) {
3125 buttonToReplace = getConfirmButton();
3126 }
3127 show(actions);
3128 if (buttonToReplace) {
3129 hide(buttonToReplace);
3130 loader.setAttribute('data-button-to-replace', buttonToReplace.className);
3131 actions.insertBefore(loader, buttonToReplace);
3132 }
3133 addClass([popup, actions], swalClasses.loading);
3134 };
3135
3136 /**
3137 * @param {SweetAlert} instance
3138 * @param {SweetAlertOptions} params
3139 */
3140 const handleInputOptionsAndValue = (instance, params) => {
3141 if (params.input === 'select' || params.input === 'radio') {
3142 handleInputOptions(instance, params);
3143 } else if (['text', 'email', 'number', 'tel', 'textarea'].some(i => i === params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {
3144 showLoading(getConfirmButton());
3145 handleInputValue(instance, params);
3146 }
3147 };
3148
3149 /**
3150 * @param {SweetAlert} instance
3151 * @param {SweetAlertOptions} innerParams
3152 * @returns {SweetAlertInputValue}
3153 */
3154 const getInputValue = (instance, innerParams) => {
3155 const input = instance.getInput();
3156 if (!input) {
3157 return null;
3158 }
3159 switch (innerParams.input) {
3160 case 'checkbox':
3161 return getCheckboxValue(input);
3162 case 'radio':
3163 return getRadioValue(input);
3164 case 'file':
3165 return getFileValue(input);
3166 default:
3167 return innerParams.inputAutoTrim ? input.value.trim() : input.value;
3168 }
3169 };
3170
3171 /**
3172 * @param {HTMLInputElement} input
3173 * @returns {number}
3174 */
3175 const getCheckboxValue = input => input.checked ? 1 : 0;
3176
3177 /**
3178 * @param {HTMLInputElement} input
3179 * @returns {string | null}
3180 */
3181 const getRadioValue = input => input.checked ? input.value : null;
3182
3183 /**
3184 * @param {HTMLInputElement} input
3185 * @returns {FileList | File | null}
3186 */
3187 const getFileValue = input => input.files && input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;
3188
3189 /**
3190 * @param {SweetAlert} instance
3191 * @param {SweetAlertOptions} params
3192 */
3193 const handleInputOptions = (instance, params) => {
3194 const popup = getPopup();
3195 if (!popup) {
3196 return;
3197 }
3198 /**
3199 * @param {*} inputOptions
3200 */
3201 const processInputOptions = inputOptions => {
3202 if (params.input === 'select') {
3203 populateSelectOptions(popup, formatInputOptions(inputOptions), params);
3204 } else if (params.input === 'radio') {
3205 populateRadioOptions(popup, formatInputOptions(inputOptions), params);
3206 }
3207 };
3208 if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
3209 showLoading(getConfirmButton());
3210 asPromise(params.inputOptions).then(inputOptions => {
3211 instance.hideLoading();
3212 processInputOptions(inputOptions);
3213 });
3214 } else if (typeof params.inputOptions === 'object') {
3215 processInputOptions(params.inputOptions);
3216 } else {
3217 error(`Unexpected type of inputOptions! Expected object, Map or Promise, got ${typeof params.inputOptions}`);
3218 }
3219 };
3220
3221 /**
3222 * @param {SweetAlert} instance
3223 * @param {SweetAlertOptions} params
3224 */
3225 const handleInputValue = (instance, params) => {
3226 const input = instance.getInput();
3227 if (!input) {
3228 return;
3229 }
3230 hide(input);
3231 asPromise(params.inputValue).then(inputValue => {
3232 input.value = params.input === 'number' ? `${parseFloat(inputValue) || 0}` : `${inputValue}`;
3233 show(input);
3234 input.focus();
3235 instance.hideLoading();
3236 }).catch(err => {
3237 error(`Error in inputValue promise: ${err}`);
3238 input.value = '';
3239 show(input);
3240 input.focus();
3241 instance.hideLoading();
3242 });
3243 };
3244
3245 /**
3246 * @param {HTMLElement} popup
3247 * @param {InputOptionFlattened[]} inputOptions
3248 * @param {SweetAlertOptions} params
3249 */
3250 function populateSelectOptions(popup, inputOptions, params) {
3251 const select = getDirectChildByClass(popup, swalClasses.select);
3252 if (!select) {
3253 return;
3254 }
3255 /**
3256 * @param {HTMLElement} parent
3257 * @param {string} optionLabel
3258 * @param {string} optionValue
3259 */
3260 const renderOption = (parent, optionLabel, optionValue) => {
3261 const option = document.createElement('option');
3262 option.value = optionValue;
3263 setInnerHtml(option, optionLabel);
3264 option.selected = isSelected(optionValue, params.inputValue);
3265 parent.appendChild(option);
3266 };
3267 inputOptions.forEach(inputOption => {
3268 const optionValue = inputOption[0];
3269 const optionLabel = inputOption[1];
3270 // <optgroup> spec:
3271 // https://www.w3.org/TR/html401/interact/forms.html#h-17.6
3272 // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
3273 // check whether this is a <optgroup>
3274 if (Array.isArray(optionLabel)) {
3275 // if it is an array, then it is an <optgroup>
3276 const optgroup = document.createElement('optgroup');
3277 optgroup.label = optionValue;
3278 optgroup.disabled = false; // not configurable for now
3279 select.appendChild(optgroup);
3280 optionLabel.forEach(o => renderOption(optgroup, o[1], o[0]));
3281 } else {
3282 // case of <option>
3283 renderOption(select, optionLabel, optionValue);
3284 }
3285 });
3286 select.focus();
3287 }
3288
3289 /**
3290 * @param {HTMLElement} popup
3291 * @param {InputOptionFlattened[]} inputOptions
3292 * @param {SweetAlertOptions} params
3293 */
3294 function populateRadioOptions(popup, inputOptions, params) {
3295 const radio = getDirectChildByClass(popup, swalClasses.radio);
3296 if (!radio) {
3297 return;
3298 }
3299 inputOptions.forEach(inputOption => {
3300 const radioValue = inputOption[0];
3301 const radioLabel = inputOption[1];
3302 const radioInput = document.createElement('input');
3303 const radioLabelElement = document.createElement('label');
3304 radioInput.type = 'radio';
3305 radioInput.name = swalClasses.radio;
3306 radioInput.value = radioValue;
3307 if (isSelected(radioValue, params.inputValue)) {
3308 radioInput.checked = true;
3309 }
3310 const label = document.createElement('span');
3311 setInnerHtml(label, radioLabel);
3312 label.className = swalClasses.label;
3313 radioLabelElement.appendChild(radioInput);
3314 radioLabelElement.appendChild(label);
3315 radio.appendChild(radioLabelElement);
3316 });
3317 const radios = radio.querySelectorAll('input');
3318 if (radios.length) {
3319 radios[0].focus();
3320 }
3321 }
3322
3323 /**
3324 * Converts `inputOptions` into an array of `[value, label]`s
3325 *
3326 * @param {*} inputOptions
3327 * @typedef {string[]} InputOptionFlattened
3328 * @returns {InputOptionFlattened[]}
3329 */
3330 const formatInputOptions = inputOptions => {
3331 const entries = inputOptions instanceof Map ? Array.from(inputOptions) : Object.entries(inputOptions);
3332 return entries.map(([key, value]) => [key, typeof value === 'object' ? formatInputOptions(value) : value]); // case of <optgroup>
3333 };
3334
3335 /**
3336 * @param {string} optionValue
3337 * @param {SweetAlertInputValue} inputValue
3338 * @returns {boolean}
3339 */
3340 const isSelected = (optionValue, inputValue) => Boolean(inputValue) && inputValue != null && inputValue.toString() === optionValue.toString();
3341
3342 /**
3343 * @param {SweetAlert} instance
3344 */
3345 const handleConfirmButtonClick = instance => {
3346 const innerParams = privateProps.innerParams.get(instance);
3347 instance.disableButtons();
3348 if (innerParams.input) {
3349 handleConfirmOrDenyWithInput(instance, 'confirm');
3350 } else {
3351 confirm(instance, true);
3352 }
3353 };
3354
3355 /**
3356 * @param {SweetAlert} instance
3357 */
3358 const handleDenyButtonClick = instance => {
3359 const innerParams = privateProps.innerParams.get(instance);
3360 instance.disableButtons();
3361 if (innerParams.returnInputValueOnDeny) {
3362 handleConfirmOrDenyWithInput(instance, 'deny');
3363 } else {
3364 deny(instance, false);
3365 }
3366 };
3367
3368 /**
3369 * @param {SweetAlert} instance
3370 * @param {(dismiss: DismissReason) => void} dismissWith
3371 */
3372 const handleCancelButtonClick = (instance, dismissWith) => {
3373 instance.disableButtons();
3374 dismissWith(DismissReason.cancel);
3375 };
3376
3377 /**
3378 * @param {SweetAlert} instance
3379 * @param {'confirm' | 'deny'} type
3380 */
3381 const handleConfirmOrDenyWithInput = (instance, type) => {
3382 const innerParams = privateProps.innerParams.get(instance);
3383 if (!innerParams.input) {
3384 error(`The "input" parameter is needed to be set when using returnInputValueOn${capitalizeFirstLetter(type)}`);
3385 return;
3386 }
3387 const input = instance.getInput();
3388 const inputValue = getInputValue(instance, innerParams);
3389 if (innerParams.inputValidator) {
3390 handleInputValidator(instance, inputValue, type);
3391 } else if (input && !input.checkValidity()) {
3392 instance.enableButtons();
3393 instance.showValidationMessage(innerParams.validationMessage || input.validationMessage);
3394 } else if (type === 'deny') {
3395 deny(instance, inputValue);
3396 } else {
3397 confirm(instance, inputValue);
3398 }
3399 };
3400
3401 /**
3402 * @param {SweetAlert} instance
3403 * @param {SweetAlertInputValue} inputValue
3404 * @param {'confirm' | 'deny'} type
3405 */
3406 const handleInputValidator = (instance, inputValue, type) => {
3407 const innerParams = privateProps.innerParams.get(instance);
3408 instance.disableInput();
3409 const validationPromise = Promise.resolve().then(() => asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage)));
3410 validationPromise.then(validationMessage => {
3411 instance.enableButtons();
3412 instance.enableInput();
3413 if (validationMessage) {
3414 instance.showValidationMessage(validationMessage);
3415 } else if (type === 'deny') {
3416 deny(instance, inputValue);
3417 } else {
3418 confirm(instance, inputValue);
3419 }
3420 });
3421 };
3422
3423 /**
3424 * @param {SweetAlert} instance
3425 * @param {*} value
3426 */
3427 const deny = (instance, value) => {
3428 const innerParams = privateProps.innerParams.get(instance);
3429 if (innerParams.showLoaderOnDeny) {
3430 showLoading(getDenyButton());
3431 }
3432 if (innerParams.preDeny) {
3433 instance.isAwaitingPromise = true; // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preDeny's promise is received
3434 const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage)));
3435 preDenyPromise.then(preDenyValue => {
3436 if (preDenyValue === false) {
3437 instance.hideLoading();
3438 handleAwaitingPromise(instance);
3439 } else {
3440 instance.close(/** @type SweetAlertResult */{
3441 isDenied: true,
3442 value: typeof preDenyValue === 'undefined' ? value : preDenyValue
3443 });
3444 }
3445 }).catch(error => rejectWith(instance, error));
3446 } else {
3447 instance.close(/** @type SweetAlertResult */{
3448 isDenied: true,
3449 value
3450 });
3451 }
3452 };
3453
3454 /**
3455 * @param {SweetAlert} instance
3456 * @param {*} value
3457 */
3458 const succeedWith = (instance, value) => {
3459 instance.close(/** @type SweetAlertResult */{
3460 isConfirmed: true,
3461 value
3462 });
3463 };
3464
3465 /**
3466 *
3467 * @param {SweetAlert} instance
3468 * @param {string} error
3469 */
3470 const rejectWith = (instance, error) => {
3471 instance.rejectPromise(error);
3472 };
3473
3474 /**
3475 *
3476 * @param {SweetAlert} instance
3477 * @param {*} value
3478 */
3479 const confirm = (instance, value) => {
3480 const innerParams = privateProps.innerParams.get(instance);
3481 if (innerParams.showLoaderOnConfirm) {
3482 showLoading();
3483 }
3484 if (innerParams.preConfirm) {
3485 instance.resetValidationMessage();
3486 instance.isAwaitingPromise = true; // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preConfirm's promise is received
3487 const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
3488 preConfirmPromise.then(preConfirmValue => {
3489 if (isVisible$1(getValidationMessage()) || preConfirmValue === false) {
3490 instance.hideLoading();
3491 handleAwaitingPromise(instance);
3492 } else {
3493 succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);
3494 }
3495 }).catch(error => rejectWith(instance, error));
3496 } else {
3497 succeedWith(instance, value);
3498 }
3499 };
3500
3501 /**
3502 * Hides loader and shows back the button which was hidden by .showLoading()
3503 * @this {SweetAlert}
3504 */
3505 function hideLoading() {
3506 // do nothing if popup is closed
3507 const innerParams = privateProps.innerParams.get(this);
3508 if (!innerParams) {
3509 return;
3510 }
3511 const domCache = privateProps.domCache.get(this);
3512 hide(domCache.loader);
3513 if (isToast()) {
3514 if (innerParams.icon) {
3515 show(getIcon());
3516 }
3517 } else {
3518 showRelatedButton(domCache);
3519 }
3520 removeClass([domCache.popup, domCache.actions], swalClasses.loading);
3521 domCache.popup.removeAttribute('aria-busy');
3522 domCache.popup.removeAttribute('data-loading');
3523 this.enableButtons();
3524 }
3525
3526 /**
3527 * @param {DomCache} domCache
3528 */
3529 const showRelatedButton = domCache => {
3530 const dataButtonToReplace = domCache.loader.getAttribute('data-button-to-replace');
3531 const buttonToReplace = dataButtonToReplace ? domCache.popup.getElementsByClassName(dataButtonToReplace) : [];
3532 if (buttonToReplace.length) {
3533 show(/** @type {HTMLElement} */buttonToReplace[0], 'inline-block');
3534 } else if (allButtonsAreHidden()) {
3535 hide(domCache.actions);
3536 }
3537 };
3538
3539 /**
3540 * Gets the input DOM node, this method works with input parameter.
3541 *
3542 * @returns {HTMLInputElement | null}
3543 * @this {SweetAlert}
3544 */
3545 function getInput() {
3546 const innerParams = privateProps.innerParams.get(this);
3547 const domCache = privateProps.domCache.get(this);
3548 if (!domCache) {
3549 return null;
3550 }
3551 return getInput$1(domCache.popup, innerParams.input);
3552 }
3553
3554 /**
3555 * @param {SweetAlert} instance
3556 * @param {string[]} buttons
3557 * @param {boolean} disabled
3558 */
3559 function setButtonsDisabled(instance, buttons, disabled) {
3560 const domCache = privateProps.domCache.get(instance);
3561 buttons.forEach(button => {
3562 domCache[button].disabled = disabled;
3563 });
3564 }
3565
3566 /**
3567 * @param {HTMLInputElement | null} input
3568 * @param {boolean} disabled
3569 */
3570 function setInputDisabled(input, disabled) {
3571 const popup = getPopup();
3572 if (!popup || !input) {
3573 return;
3574 }
3575 if (input.type === 'radio') {
3576 /** @type {NodeListOf<HTMLInputElement>} */
3577 const radios = popup.querySelectorAll(`[name="${swalClasses.radio}"]`);
3578 radios.forEach(radio => {
3579 radio.disabled = disabled;
3580 });
3581 } else {
3582 input.disabled = disabled;
3583 }
3584 }
3585
3586 /**
3587 * Enable all the buttons
3588 * @this {SweetAlert}
3589 */
3590 function enableButtons() {
3591 setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
3592 const focusedElement = privateProps.focusedElement.get(this);
3593 if (focusedElement instanceof HTMLElement && document.activeElement === document.body) {
3594 focusedElement.focus();
3595 }
3596 privateProps.focusedElement.delete(this);
3597 }
3598
3599 /**
3600 * Disable all the buttons
3601 * @this {SweetAlert}
3602 */
3603 function disableButtons() {
3604 privateProps.focusedElement.set(this, document.activeElement);
3605 setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
3606 }
3607
3608 /**
3609 * Enable the input field
3610 * @this {SweetAlert}
3611 */
3612 function enableInput() {
3613 setInputDisabled(this.getInput(), false);
3614 }
3615
3616 /**
3617 * Disable the input field
3618 * @this {SweetAlert}
3619 */
3620 function disableInput() {
3621 setInputDisabled(this.getInput(), true);
3622 }
3623
3624 /**
3625 * Show block with validation message
3626 *
3627 * @param {string} error
3628 * @this {SweetAlert}
3629 */
3630 function showValidationMessage(error) {
3631 const domCache = privateProps.domCache.get(this);
3632 const params = privateProps.innerParams.get(this);
3633 setInnerHtml(domCache.validationMessage, error);
3634 domCache.validationMessage.className = swalClasses['validation-message'];
3635 if (params.customClass && params.customClass.validationMessage) {
3636 addClass(domCache.validationMessage, params.customClass.validationMessage);
3637 }
3638 show(domCache.validationMessage);
3639 const input = this.getInput();
3640 if (input) {
3641 input.setAttribute('aria-invalid', 'true');
3642 input.setAttribute('aria-describedby', swalClasses['validation-message']);
3643 focusInput(input);
3644 addClass(input, swalClasses.inputerror);
3645 }
3646 }
3647
3648 /**
3649 * Hide block with validation message
3650 *
3651 * @this {SweetAlert}
3652 */
3653 function resetValidationMessage() {
3654 const domCache = privateProps.domCache.get(this);
3655 if (domCache.validationMessage) {
3656 hide(domCache.validationMessage);
3657 }
3658 const input = this.getInput();
3659 if (input) {
3660 input.removeAttribute('aria-invalid');
3661 input.removeAttribute('aria-describedby');
3662 removeClass(input, swalClasses.inputerror);
3663 }
3664 }
3665
3666 const defaultParams = {
3667 title: '',
3668 titleText: '',
3669 text: '',
3670 html: '',
3671 footer: '',
3672 icon: undefined,
3673 iconColor: undefined,
3674 iconHtml: undefined,
3675 template: undefined,
3676 toast: false,
3677 draggable: false,
3678 animation: true,
3679 theme: 'light',
3680 showClass: {
3681 popup: 'swal2-show',
3682 backdrop: 'swal2-backdrop-show',
3683 icon: 'swal2-icon-show'
3684 },
3685 hideClass: {
3686 popup: 'swal2-hide',
3687 backdrop: 'swal2-backdrop-hide',
3688 icon: 'swal2-icon-hide'
3689 },
3690 customClass: {},
3691 target: 'body',
3692 color: undefined,
3693 backdrop: true,
3694 heightAuto: true,
3695 allowOutsideClick: true,
3696 allowEscapeKey: true,
3697 allowEnterKey: true,
3698 stopKeydownPropagation: true,
3699 keydownListenerCapture: false,
3700 showConfirmButton: true,
3701 showDenyButton: false,
3702 showCancelButton: false,
3703 preConfirm: undefined,
3704 preDeny: undefined,
3705 confirmButtonText: 'OK',
3706 confirmButtonAriaLabel: '',
3707 confirmButtonColor: undefined,
3708 denyButtonText: 'No',
3709 denyButtonAriaLabel: '',
3710 denyButtonColor: undefined,
3711 cancelButtonText: 'Cancel',
3712 cancelButtonAriaLabel: '',
3713 cancelButtonColor: undefined,
3714 buttonsStyling: true,
3715 reverseButtons: false,
3716 focusConfirm: true,
3717 focusDeny: false,
3718 focusCancel: false,
3719 returnFocus: true,
3720 showCloseButton: false,
3721 closeButtonHtml: '&times;',
3722 closeButtonAriaLabel: 'Close this dialog',
3723 loaderHtml: '',
3724 showLoaderOnConfirm: false,
3725 showLoaderOnDeny: false,
3726 imageUrl: undefined,
3727 imageWidth: undefined,
3728 imageHeight: undefined,
3729 imageAlt: '',
3730 timer: undefined,
3731 timerProgressBar: false,
3732 width: undefined,
3733 padding: undefined,
3734 background: undefined,
3735 input: undefined,
3736 inputPlaceholder: '',
3737 inputLabel: '',
3738 inputValue: '',
3739 inputOptions: {},
3740 inputAutoFocus: true,
3741 inputAutoTrim: true,
3742 inputAttributes: {},
3743 inputValidator: undefined,
3744 returnInputValueOnDeny: false,
3745 validationMessage: undefined,
3746 grow: false,
3747 position: 'center',
3748 progressSteps: [],
3749 currentProgressStep: undefined,
3750 progressStepsDistance: undefined,
3751 willOpen: undefined,
3752 didOpen: undefined,
3753 didRender: undefined,
3754 willClose: undefined,
3755 didClose: undefined,
3756 didDestroy: undefined,
3757 scrollbarPadding: true,
3758 topLayer: false
3759 };
3760 const updatableParams = ['allowEscapeKey', 'allowOutsideClick', 'background', 'buttonsStyling', 'cancelButtonAriaLabel', 'cancelButtonColor', 'cancelButtonText', 'closeButtonAriaLabel', 'closeButtonHtml', 'color', 'confirmButtonAriaLabel', 'confirmButtonColor', 'confirmButtonText', 'currentProgressStep', 'customClass', 'denyButtonAriaLabel', 'denyButtonColor', 'denyButtonText', 'didClose', 'didDestroy', 'draggable', 'footer', 'hideClass', 'html', 'icon', 'iconColor', 'iconHtml', 'imageAlt', 'imageHeight', 'imageUrl', 'imageWidth', 'preConfirm', 'preDeny', 'progressSteps', 'returnFocus', 'reverseButtons', 'showCancelButton', 'showCloseButton', 'showConfirmButton', 'showDenyButton', 'text', 'title', 'titleText', 'theme', 'willClose'];
3761
3762 /** @type {Record<string, string | undefined>} */
3763 const deprecatedParams = {
3764 allowEnterKey: undefined
3765 };
3766 const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'draggable', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];
3767
3768 /**
3769 * Is valid parameter
3770 *
3771 * @param {string} paramName
3772 * @returns {boolean}
3773 */
3774 const isValidParameter = paramName => {
3775 return Object.prototype.hasOwnProperty.call(defaultParams, paramName);
3776 };
3777
3778 /**
3779 * Is valid parameter for Swal.update() method
3780 *
3781 * @param {string} paramName
3782 * @returns {boolean}
3783 */
3784 const isUpdatableParameter = paramName => {
3785 return updatableParams.indexOf(paramName) !== -1;
3786 };
3787
3788 /**
3789 * Is deprecated parameter
3790 *
3791 * @param {string} paramName
3792 * @returns {string | undefined}
3793 */
3794 const isDeprecatedParameter = paramName => {
3795 return deprecatedParams[paramName];
3796 };
3797
3798 /**
3799 * @param {string} param
3800 */
3801 const checkIfParamIsValid = param => {
3802 if (!isValidParameter(param)) {
3803 warn(`Unknown parameter "${param}"`);
3804 }
3805 };
3806
3807 /**
3808 * @param {string} param
3809 */
3810 const checkIfToastParamIsValid = param => {
3811 if (toastIncompatibleParams.includes(param)) {
3812 warn(`The parameter "${param}" is incompatible with toasts`);
3813 }
3814 };
3815
3816 /**
3817 * @param {string} param
3818 */
3819 const checkIfParamIsDeprecated = param => {
3820 const isDeprecated = isDeprecatedParameter(param);
3821 if (isDeprecated) {
3822 warnAboutDeprecation(param, isDeprecated);
3823 }
3824 };
3825
3826 /**
3827 * Show relevant warnings for given params
3828 *
3829 * @param {SweetAlertOptions} params
3830 */
3831 const showWarningsForParams = params => {
3832 if (params.backdrop === false && params.allowOutsideClick) {
3833 warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
3834 }
3835 if (params.theme && !['light', 'dark', 'auto', 'minimal', 'borderless', 'bootstrap-4', 'bootstrap-4-light', 'bootstrap-4-dark', 'bootstrap-5', 'bootstrap-5-light', 'bootstrap-5-dark', 'material-ui', 'material-ui-light', 'material-ui-dark', 'embed-iframe', 'bulma', 'bulma-light', 'bulma-dark'].includes(params.theme)) {
3836 warn(`Invalid theme "${params.theme}"`);
3837 }
3838 for (const param in params) {
3839 checkIfParamIsValid(param);
3840 if (params.toast) {
3841 checkIfToastParamIsValid(param);
3842 }
3843 checkIfParamIsDeprecated(param);
3844 }
3845 };
3846
3847 /**
3848 * Updates popup parameters.
3849 *
3850 * @this {any}
3851 * @param {SweetAlertOptions} params
3852 */
3853 function update(params) {
3854 const container = getContainer();
3855 const popup = getPopup();
3856 const innerParams = privateProps.innerParams.get(this);
3857 if (!popup || hasClass(popup, innerParams.hideClass.popup)) {
3858 warn(`You're trying to update the closed or closing popup, that won't work. Use the update() method in preConfirm parameter or show a new popup.`);
3859 return;
3860 }
3861 const validUpdatableParams = filterValidParams(params);
3862 const updatedParams = Object.assign({}, innerParams, validUpdatableParams);
3863 showWarningsForParams(updatedParams);
3864 if (container) {
3865 container.dataset['swal2Theme'] = updatedParams.theme;
3866 }
3867 render(this, updatedParams);
3868 privateProps.innerParams.set(this, updatedParams);
3869 Object.defineProperties(this, {
3870 params: {
3871 value: Object.assign({}, this.params, params),
3872 writable: false,
3873 enumerable: true
3874 }
3875 });
3876 }
3877
3878 /**
3879 * @param {SweetAlertOptions} params
3880 * @returns {SweetAlertOptions}
3881 */
3882 const filterValidParams = params => {
3883 /** @type {Record<string, any>} */
3884 const validUpdatableParams = {};
3885 Object.keys(params).forEach(param => {
3886 if (isUpdatableParameter(param)) {
3887 const typedParams = /** @type {Record<string, any>} */params;
3888 validUpdatableParams[param] = typedParams[param];
3889 } else {
3890 warn(`Invalid parameter to update: ${param}`);
3891 }
3892 });
3893 return validUpdatableParams;
3894 };
3895
3896 /**
3897 * Dispose the current SweetAlert2 instance
3898 * @this {SweetAlert}
3899 */
3900 function _destroy() {
3901 var _globalState$eventEmi;
3902 const domCache = privateProps.domCache.get(this);
3903 const innerParams = privateProps.innerParams.get(this);
3904 if (!innerParams) {
3905 disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
3906 return; // This instance has already been destroyed
3907 }
3908
3909 // Check if there is another Swal closing
3910 if (domCache.popup && globalState.swalCloseEventFinishedCallback) {
3911 globalState.swalCloseEventFinishedCallback();
3912 delete globalState.swalCloseEventFinishedCallback;
3913 }
3914 if (typeof innerParams.didDestroy === 'function') {
3915 innerParams.didDestroy();
3916 }
3917 (_globalState$eventEmi = globalState.eventEmitter) === null || _globalState$eventEmi === void 0 || _globalState$eventEmi.emit('didDestroy');
3918 disposeSwal(this);
3919 }
3920
3921 /**
3922 * @param {SweetAlert} instance
3923 */
3924 const disposeSwal = instance => {
3925 disposeWeakMaps(instance);
3926 // Unset this.params so GC will dispose it (#1569)
3927 // @ts-ignore
3928 delete instance.params;
3929 // Unset globalState props so GC will dispose globalState (#1569)
3930 delete globalState.keydownHandler;
3931 delete globalState.keydownTarget;
3932 // Unset currentInstance
3933 delete globalState.currentInstance;
3934 };
3935
3936 /**
3937 * @param {SweetAlert} instance
3938 */
3939 const disposeWeakMaps = instance => {
3940 // If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335
3941 if (instance.isAwaitingPromise) {
3942 unsetWeakMaps(privateProps, instance);
3943 instance.isAwaitingPromise = true;
3944 } else {
3945 unsetWeakMaps(privateMethods, instance);
3946 unsetWeakMaps(privateProps, instance);
3947
3948 // @ts-ignore
3949 delete instance.isAwaitingPromise;
3950 // Unset instance methods
3951 // @ts-ignore
3952 delete instance.disableButtons;
3953 // @ts-ignore
3954 delete instance.enableButtons;
3955 // @ts-ignore
3956 delete instance.getInput;
3957 // @ts-ignore
3958 delete instance.disableInput;
3959 // @ts-ignore
3960 delete instance.enableInput;
3961 // @ts-ignore
3962 delete instance.hideLoading;
3963 // @ts-ignore
3964 delete instance.disableLoading;
3965 // @ts-ignore
3966 delete instance.showValidationMessage;
3967 // @ts-ignore
3968 delete instance.resetValidationMessage;
3969 // @ts-ignore
3970 delete instance.close;
3971 // @ts-ignore
3972 delete instance.closePopup;
3973 // @ts-ignore
3974 delete instance.closeModal;
3975 // @ts-ignore
3976 delete instance.closeToast;
3977 // @ts-ignore
3978 delete instance.rejectPromise;
3979 // @ts-ignore
3980 delete instance.update;
3981 // @ts-ignore
3982 delete instance._destroy;
3983 }
3984 };
3985
3986 /**
3987 * @param {Record<string, WeakMap<any, any>>} obj
3988 * @param {SweetAlert} instance
3989 */
3990 const unsetWeakMaps = (obj, instance) => {
3991 for (const i in obj) {
3992 obj[i].delete(instance);
3993 }
3994 };
3995
3996 var instanceMethods = /*#__PURE__*/Object.freeze({
3997 __proto__: null,
3998 _destroy: _destroy,
3999 close: close,
4000 closeModal: close,
4001 closePopup: close,
4002 closeToast: close,
4003 disableButtons: disableButtons,
4004 disableInput: disableInput,
4005 disableLoading: hideLoading,
4006 enableButtons: enableButtons,
4007 enableInput: enableInput,
4008 getInput: getInput,
4009 handleAwaitingPromise: handleAwaitingPromise,
4010 hideLoading: hideLoading,
4011 rejectPromise: rejectPromise,
4012 resetValidationMessage: resetValidationMessage,
4013 showValidationMessage: showValidationMessage,
4014 update: update
4015 });
4016
4017 /**
4018 * @param {SweetAlertOptions} innerParams
4019 * @param {DomCache} domCache
4020 * @param {(dismiss: DismissReason) => void} dismissWith
4021 */
4022 const handlePopupClick = (innerParams, domCache, dismissWith) => {
4023 if (innerParams.toast) {
4024 handleToastClick(innerParams, domCache, dismissWith);
4025 } else {
4026 // Ignore click events that had mousedown on the popup but mouseup on the container
4027 // This can happen when the user drags a slider
4028 handleModalMousedown(domCache);
4029
4030 // Ignore click events that had mousedown on the container but mouseup on the popup
4031 handleContainerMousedown(domCache);
4032 handleModalClick(innerParams, domCache, dismissWith);
4033 }
4034 };
4035
4036 /**
4037 * @param {SweetAlertOptions} innerParams
4038 * @param {DomCache} domCache
4039 * @param {(dismiss: DismissReason) => void} dismissWith
4040 */
4041 const handleToastClick = (innerParams, domCache, dismissWith) => {
4042 // Closing toast by internal click
4043 domCache.popup.onclick = () => {
4044 if (innerParams && (isAnyButtonShown(innerParams) || innerParams.timer || innerParams.input)) {
4045 return;
4046 }
4047 dismissWith(DismissReason.close);
4048 };
4049 };
4050
4051 /**
4052 * @param {SweetAlertOptions} innerParams
4053 * @returns {boolean}
4054 */
4055 const isAnyButtonShown = innerParams => {
4056 return Boolean(innerParams.showConfirmButton || innerParams.showDenyButton || innerParams.showCancelButton || innerParams.showCloseButton);
4057 };
4058 let ignoreOutsideClick = false;
4059
4060 /**
4061 * @param {DomCache} domCache
4062 */
4063 const handleModalMousedown = domCache => {
4064 domCache.popup.onmousedown = () => {
4065 domCache.container.onmouseup = function (e) {
4066 domCache.container.onmouseup = () => {};
4067 // We only check if the mouseup target is the container because usually it doesn't
4068 // have any other direct children aside of the popup
4069 if (e.target === domCache.container) {
4070 ignoreOutsideClick = true;
4071 }
4072 };
4073 };
4074 };
4075
4076 /**
4077 * @param {DomCache} domCache
4078 */
4079 const handleContainerMousedown = domCache => {
4080 domCache.container.onmousedown = e => {
4081 // prevent the modal text from being selected on double click on the container (allowOutsideClick: false)
4082 if (e.target === domCache.container) {
4083 e.preventDefault();
4084 }
4085 domCache.popup.onmouseup = function (e) {
4086 domCache.popup.onmouseup = () => {};
4087 // We also need to check if the mouseup target is a child of the popup
4088 if (e.target === domCache.popup || e.target instanceof HTMLElement && domCache.popup.contains(e.target)) {
4089 ignoreOutsideClick = true;
4090 }
4091 };
4092 };
4093 };
4094
4095 /**
4096 * @param {SweetAlertOptions} innerParams
4097 * @param {DomCache} domCache
4098 * @param {(dismiss: DismissReason) => void} dismissWith
4099 */
4100 const handleModalClick = (innerParams, domCache, dismissWith) => {
4101 domCache.container.onclick = e => {
4102 if (ignoreOutsideClick) {
4103 ignoreOutsideClick = false;
4104 return;
4105 }
4106 if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) {
4107 dismissWith(DismissReason.backdrop);
4108 }
4109 };
4110 };
4111
4112 /**
4113 * @param {unknown} elem
4114 * @returns {boolean}
4115 */
4116 const isJqueryElement = elem => typeof elem === 'object' && elem !== null && 'jquery' in elem;
4117
4118 /**
4119 * @param {unknown} elem
4120 * @returns {boolean}
4121 */
4122 const isElement = elem => elem instanceof Element || isJqueryElement(elem);
4123
4124 /**
4125 * @param {ReadonlyArray<unknown>} args
4126 * @returns {SweetAlertOptions}
4127 */
4128 const argsToParams = args => {
4129 /** @type {Record<string, unknown>} */
4130 const params = {};
4131 if (typeof args[0] === 'object' && !isElement(args[0])) {
4132 Object.assign(params, args[0]);
4133 } else {
4134 ['title', 'html', 'icon'].forEach((name, index) => {
4135 const arg = args[index];
4136 if (typeof arg === 'string' || isElement(arg)) {
4137 params[name] = arg;
4138 } else if (arg !== undefined) {
4139 error(`Unexpected type of ${name}! Expected "string" or "Element", got ${typeof arg}`);
4140 }
4141 });
4142 }
4143 return /** @type {SweetAlertOptions} */params;
4144 };
4145
4146 /**
4147 * Main method to create a new SweetAlert2 popup
4148 *
4149 * @this {new (...args: any[]) => any}
4150 * @param {...SweetAlertOptions} args
4151 * @returns {Promise<SweetAlertResult>}
4152 */
4153 function fire(...args) {
4154 return new this(...args);
4155 }
4156
4157 /**
4158 * Returns an extended version of `Swal` containing `params` as defaults.
4159 * Useful for reusing Swal configuration.
4160 *
4161 * For example:
4162 *
4163 * Before:
4164 * const textPromptOptions = { input: 'text', showCancelButton: true }
4165 * const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' })
4166 * const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' })
4167 *
4168 * After:
4169 * const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true })
4170 * const {value: firstName} = await TextPrompt('What is your first name?')
4171 * const {value: lastName} = await TextPrompt('What is your last name?')
4172 *
4173 * @param {SweetAlertOptions} mixinParams
4174 * @returns {SweetAlert}
4175 * @this {typeof import('../SweetAlert.js').SweetAlert}
4176 */
4177 function mixin(mixinParams) {
4178 // @ts-ignore: 'this' refers to the SweetAlert constructor
4179 class MixinSwal extends this {
4180 /**
4181 * @param {any} params
4182 * @param {any} priorityMixinParams
4183 */
4184 _main(params, priorityMixinParams) {
4185 return super._main(params, Object.assign({}, mixinParams, priorityMixinParams));
4186 }
4187 }
4188 // @ts-ignore
4189 return MixinSwal;
4190 }
4191
4192 /**
4193 * If `timer` parameter is set, returns number of milliseconds of timer remained.
4194 * Otherwise, returns undefined.
4195 *
4196 * @returns {number | undefined}
4197 */
4198 const getTimerLeft = () => {
4199 return globalState.timeout && globalState.timeout.getTimerLeft();
4200 };
4201
4202 /**
4203 * Stop timer. Returns number of milliseconds of timer remained.
4204 * If `timer` parameter isn't set, returns undefined.
4205 *
4206 * @returns {number | undefined}
4207 */
4208 const stopTimer = () => {
4209 if (globalState.timeout) {
4210 stopTimerProgressBar();
4211 return globalState.timeout.stop();
4212 }
4213 };
4214
4215 /**
4216 * Resume timer. Returns number of milliseconds of timer remained.
4217 * If `timer` parameter isn't set, returns undefined.
4218 *
4219 * @returns {number | undefined}
4220 */
4221 const resumeTimer = () => {
4222 if (globalState.timeout) {
4223 const remaining = globalState.timeout.start();
4224 animateTimerProgressBar(remaining);
4225 return remaining;
4226 }
4227 };
4228
4229 /**
4230 * Resume timer. Returns number of milliseconds of timer remained.
4231 * If `timer` parameter isn't set, returns undefined.
4232 *
4233 * @returns {number | undefined}
4234 */
4235 const toggleTimer = () => {
4236 const timer = globalState.timeout;
4237 return timer && (timer.running ? stopTimer() : resumeTimer());
4238 };
4239
4240 /**
4241 * Increase timer. Returns number of milliseconds of an updated timer.
4242 * If `timer` parameter isn't set, returns undefined.
4243 *
4244 * @param {number} ms
4245 * @returns {number | undefined}
4246 */
4247 const increaseTimer = ms => {
4248 if (globalState.timeout) {
4249 const remaining = globalState.timeout.increase(ms);
4250 animateTimerProgressBar(remaining, true);
4251 return remaining;
4252 }
4253 };
4254
4255 /**
4256 * Check if timer is running. Returns true if timer is running
4257 * or false if timer is paused or stopped.
4258 * If `timer` parameter isn't set, returns undefined
4259 *
4260 * @returns {boolean}
4261 */
4262 const isTimerRunning = () => {
4263 return Boolean(globalState.timeout && globalState.timeout.isRunning());
4264 };
4265
4266 let bodyClickListenerAdded = false;
4267 /** @type {Record<string, any>} */
4268 const clickHandlers = {};
4269
4270 /**
4271 * @this {any}
4272 * @param {string} attr
4273 */
4274 function bindClickHandler(attr = 'data-swal-template') {
4275 clickHandlers[attr] = this;
4276 if (!bodyClickListenerAdded) {
4277 document.body.addEventListener('click', bodyClickListener);
4278 bodyClickListenerAdded = true;
4279 }
4280 }
4281
4282 /**
4283 * @param {MouseEvent} event
4284 */
4285 const bodyClickListener = event => {
4286 for (let el = /** @type {any} */event.target; el && el !== document; el = el.parentNode) {
4287 for (const attr in clickHandlers) {
4288 const template = el.getAttribute && el.getAttribute(attr);
4289 if (template) {
4290 clickHandlers[attr].fire({
4291 template
4292 });
4293 return;
4294 }
4295 }
4296 }
4297 };
4298
4299 // Source: https://gist.github.com/mudge/5830382?permalink_comment_id=2691957#gistcomment-2691957
4300
4301 class EventEmitter {
4302 constructor() {
4303 /** @type {Events} */
4304 this.events = {};
4305 }
4306
4307 /**
4308 * @param {string} eventName
4309 * @returns {EventHandlers}
4310 */
4311 _getHandlersByEventName(eventName) {
4312 if (typeof this.events[eventName] === 'undefined') {
4313 // not Set because we need to keep the FIFO order
4314 // https://github.com/sweetalert2/sweetalert2/pull/2763#discussion_r1748990334
4315 this.events[eventName] = [];
4316 }
4317 return this.events[eventName];
4318 }
4319
4320 /**
4321 * @param {string} eventName
4322 * @param {EventHandler} eventHandler
4323 */
4324 on(eventName, eventHandler) {
4325 const currentHandlers = this._getHandlersByEventName(eventName);
4326 if (!currentHandlers.includes(eventHandler)) {
4327 currentHandlers.push(eventHandler);
4328 }
4329 }
4330
4331 /**
4332 * @param {string} eventName
4333 * @param {EventHandler} eventHandler
4334 */
4335 once(eventName, eventHandler) {
4336 /**
4337 * @param {...any} args
4338 */
4339 const onceFn = (...args) => {
4340 this.removeListener(eventName, onceFn);
4341 // @ts-ignore
4342 eventHandler.apply(this, args);
4343 };
4344 this.on(eventName, onceFn);
4345 }
4346
4347 /**
4348 * @param {string} eventName
4349 * @param {...any} args
4350 */
4351 emit(eventName, ...args) {
4352 this._getHandlersByEventName(eventName).forEach(
4353 /**
4354 * @param {EventHandler} eventHandler
4355 */
4356 eventHandler => {
4357 try {
4358 // @ts-ignore
4359 eventHandler.apply(this, args);
4360 } catch (error) {
4361 console.error(error);
4362 }
4363 });
4364 }
4365
4366 /**
4367 * @param {string} eventName
4368 * @param {EventHandler} eventHandler
4369 */
4370 removeListener(eventName, eventHandler) {
4371 const currentHandlers = this._getHandlersByEventName(eventName);
4372 const index = currentHandlers.indexOf(eventHandler);
4373 if (index > -1) {
4374 currentHandlers.splice(index, 1);
4375 }
4376 }
4377
4378 /**
4379 * @param {string} eventName
4380 */
4381 removeAllListeners(eventName) {
4382 if (this.events[eventName] !== undefined) {
4383 // https://github.com/sweetalert2/sweetalert2/pull/2763#discussion_r1749239222
4384 this.events[eventName].length = 0;
4385 }
4386 }
4387 reset() {
4388 this.events = {};
4389 }
4390 }
4391
4392 globalState.eventEmitter = new EventEmitter();
4393
4394 /**
4395 * @param {string} eventName
4396 * @param {EventHandler} eventHandler
4397 */
4398 const on = (eventName, eventHandler) => {
4399 if (globalState.eventEmitter) {
4400 globalState.eventEmitter.on(eventName, eventHandler);
4401 }
4402 };
4403
4404 /**
4405 * @param {string} eventName
4406 * @param {EventHandler} eventHandler
4407 */
4408 const once = (eventName, eventHandler) => {
4409 if (globalState.eventEmitter) {
4410 globalState.eventEmitter.once(eventName, eventHandler);
4411 }
4412 };
4413
4414 /**
4415 * @param {string} [eventName]
4416 * @param {EventHandler} [eventHandler]
4417 */
4418 const off = (eventName, eventHandler) => {
4419 if (!globalState.eventEmitter) {
4420 return;
4421 }
4422
4423 // Remove all handlers for all events
4424 if (!eventName) {
4425 globalState.eventEmitter.reset();
4426 return;
4427 }
4428 if (eventHandler) {
4429 // Remove a specific handler
4430 globalState.eventEmitter.removeListener(eventName, eventHandler);
4431 } else {
4432 // Remove all handlers for a specific event
4433 globalState.eventEmitter.removeAllListeners(eventName);
4434 }
4435 };
4436
4437 var staticMethods = /*#__PURE__*/Object.freeze({
4438 __proto__: null,
4439 argsToParams: argsToParams,
4440 bindClickHandler: bindClickHandler,
4441 clickCancel: clickCancel,
4442 clickConfirm: clickConfirm,
4443 clickDeny: clickDeny,
4444 enableLoading: showLoading,
4445 fire: fire,
4446 getActions: getActions,
4447 getCancelButton: getCancelButton,
4448 getCloseButton: getCloseButton,
4449 getConfirmButton: getConfirmButton,
4450 getContainer: getContainer,
4451 getDenyButton: getDenyButton,
4452 getFocusableElements: getFocusableElements,
4453 getFooter: getFooter,
4454 getHtmlContainer: getHtmlContainer,
4455 getIcon: getIcon,
4456 getIconContent: getIconContent,
4457 getImage: getImage,
4458 getInputLabel: getInputLabel,
4459 getLoader: getLoader,
4460 getPopup: getPopup,
4461 getProgressSteps: getProgressSteps,
4462 getTimerLeft: getTimerLeft,
4463 getTimerProgressBar: getTimerProgressBar,
4464 getTitle: getTitle,
4465 getValidationMessage: getValidationMessage,
4466 increaseTimer: increaseTimer,
4467 isDeprecatedParameter: isDeprecatedParameter,
4468 isLoading: isLoading,
4469 isTimerRunning: isTimerRunning,
4470 isUpdatableParameter: isUpdatableParameter,
4471 isValidParameter: isValidParameter,
4472 isVisible: isVisible,
4473 mixin: mixin,
4474 off: off,
4475 on: on,
4476 once: once,
4477 resumeTimer: resumeTimer,
4478 showLoading: showLoading,
4479 stopTimer: stopTimer,
4480 toggleTimer: toggleTimer
4481 });
4482
4483 class Timer {
4484 /**
4485 * @param {() => void} callback
4486 * @param {number} delay
4487 */
4488 constructor(callback, delay) {
4489 this.callback = callback;
4490 this.remaining = delay;
4491 this.running = false;
4492 this.start();
4493 }
4494
4495 /**
4496 * @returns {number}
4497 */
4498 start() {
4499 if (!this.running) {
4500 this.running = true;
4501 this.started = new Date();
4502 this.id = setTimeout(this.callback, this.remaining);
4503 }
4504 return this.remaining;
4505 }
4506
4507 /**
4508 * @returns {number}
4509 */
4510 stop() {
4511 if (this.started && this.running) {
4512 this.running = false;
4513 clearTimeout(this.id);
4514 this.remaining -= new Date().getTime() - this.started.getTime();
4515 }
4516 return this.remaining;
4517 }
4518
4519 /**
4520 * @param {number} n
4521 * @returns {number}
4522 */
4523 increase(n) {
4524 const running = this.running;
4525 if (running) {
4526 this.stop();
4527 }
4528 this.remaining += n;
4529 if (running) {
4530 this.start();
4531 }
4532 return this.remaining;
4533 }
4534
4535 /**
4536 * @returns {number}
4537 */
4538 getTimerLeft() {
4539 if (this.running) {
4540 this.stop();
4541 this.start();
4542 }
4543 return this.remaining;
4544 }
4545
4546 /**
4547 * @returns {boolean}
4548 */
4549 isRunning() {
4550 return this.running;
4551 }
4552 }
4553
4554 const swalStringParams = ['swal-title', 'swal-html', 'swal-footer'];
4555
4556 /**
4557 * @param {SweetAlertOptions} params
4558 * @returns {SweetAlertOptions}
4559 */
4560 const getTemplateParams = params => {
4561 const template = typeof params.template === 'string' ? (/** @type {HTMLTemplateElement} */document.querySelector(params.template)) : params.template;
4562 if (!template) {
4563 return {};
4564 }
4565 /** @type {DocumentFragment} */
4566 const templateContent = template.content;
4567 showWarningsForElements(templateContent);
4568 const result = Object.assign(getSwalParams(templateContent), getSwalFunctionParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams));
4569 return result;
4570 };
4571
4572 /**
4573 * @param {DocumentFragment} templateContent
4574 * @returns {Record<string, string | boolean | number>}
4575 */
4576 const getSwalParams = templateContent => {
4577 /** @type {Record<string, string | boolean | number>} */
4578 const result = {};
4579 /** @type {HTMLElement[]} */
4580 const swalParams = Array.from(templateContent.querySelectorAll('swal-param'));
4581 swalParams.forEach(param => {
4582 showWarningsForAttributes(param, ['name', 'value']);
4583 const paramName = /** @type {keyof SweetAlertOptions} */param.getAttribute('name');
4584 const value = param.getAttribute('value');
4585 if (!paramName || !value) {
4586 return;
4587 }
4588 if (paramName in defaultParams && typeof defaultParams[(/** @type {keyof typeof defaultParams} */paramName)] === 'boolean') {
4589 result[paramName] = value !== 'false';
4590 } else if (paramName in defaultParams && typeof defaultParams[(/** @type {keyof typeof defaultParams} */paramName)] === 'object') {
4591 result[paramName] = JSON.parse(value);
4592 } else {
4593 result[paramName] = value;
4594 }
4595 });
4596 return result;
4597 };
4598
4599 /**
4600 * @param {DocumentFragment} templateContent
4601 * @returns {Record<string, () => void>}
4602 */
4603 const getSwalFunctionParams = templateContent => {
4604 /** @type {Record<string, () => void>} */
4605 const result = {};
4606 /** @type {HTMLElement[]} */
4607 const swalFunctions = Array.from(templateContent.querySelectorAll('swal-function-param'));
4608 swalFunctions.forEach(param => {
4609 const paramName = /** @type {keyof SweetAlertOptions} */param.getAttribute('name');
4610 const value = param.getAttribute('value');
4611 if (!paramName || !value) {
4612 return;
4613 }
4614 result[paramName] = new Function(`return ${value}`)();
4615 });
4616 return result;
4617 };
4618
4619 /**
4620 * @param {DocumentFragment} templateContent
4621 * @returns {Record<string, string | boolean>}
4622 */
4623 const getSwalButtons = templateContent => {
4624 /** @type {Record<string, string | boolean>} */
4625 const result = {};
4626 /** @type {HTMLElement[]} */
4627 const swalButtons = Array.from(templateContent.querySelectorAll('swal-button'));
4628 swalButtons.forEach(button => {
4629 showWarningsForAttributes(button, ['type', 'color', 'aria-label']);
4630 const type = button.getAttribute('type');
4631 if (!type || !['confirm', 'cancel', 'deny'].includes(type)) {
4632 return;
4633 }
4634 result[`${type}ButtonText`] = button.innerHTML;
4635 result[`show${capitalizeFirstLetter(type)}Button`] = true;
4636 const color = button.getAttribute('color');
4637 if (color !== null) {
4638 result[`${type}ButtonColor`] = color;
4639 }
4640 const ariaLabel = button.getAttribute('aria-label');
4641 if (ariaLabel !== null) {
4642 result[`${type}ButtonAriaLabel`] = ariaLabel;
4643 }
4644 });
4645 return result;
4646 };
4647
4648 /**
4649 * @param {DocumentFragment} templateContent
4650 * @returns {Pick<SweetAlertOptions, 'imageUrl' | 'imageWidth' | 'imageHeight' | 'imageAlt'>}
4651 */
4652 const getSwalImage = templateContent => {
4653 const result = {};
4654 /** @type {HTMLElement | null} */
4655 const image = templateContent.querySelector('swal-image');
4656 if (image) {
4657 showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']);
4658 // getAttribute returns null if attribute is absent; `|| undefined` converts empty string to undefined
4659 const src = image.getAttribute('src');
4660 if (src !== null) result.imageUrl = src || undefined;
4661 const width = image.getAttribute('width');
4662 if (width !== null) result.imageWidth = width || undefined;
4663 const height = image.getAttribute('height');
4664 if (height !== null) result.imageHeight = height || undefined;
4665 const alt = image.getAttribute('alt');
4666 if (alt !== null) result.imageAlt = alt || undefined;
4667 }
4668 return result;
4669 };
4670
4671 /**
4672 * @param {DocumentFragment} templateContent
4673 * @returns {object}
4674 */
4675 const getSwalIcon = templateContent => {
4676 const result = {};
4677 /** @type {HTMLElement | null} */
4678 const icon = templateContent.querySelector('swal-icon');
4679 if (icon) {
4680 showWarningsForAttributes(icon, ['type', 'color']);
4681 if (icon.hasAttribute('type')) {
4682 result.icon = icon.getAttribute('type');
4683 }
4684 if (icon.hasAttribute('color')) {
4685 result.iconColor = icon.getAttribute('color');
4686 }
4687 result.iconHtml = icon.innerHTML;
4688 }
4689 return result;
4690 };
4691
4692 /**
4693 * @param {DocumentFragment} templateContent
4694 * @returns {object}
4695 */
4696 const getSwalInput = templateContent => {
4697 /** @type {Record<string, any>} */
4698 const result = {};
4699 /** @type {HTMLElement | null} */
4700 const input = templateContent.querySelector('swal-input');
4701 if (input) {
4702 showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value']);
4703 result.input = input.getAttribute('type') || 'text';
4704 if (input.hasAttribute('label')) {
4705 result.inputLabel = input.getAttribute('label');
4706 }
4707 if (input.hasAttribute('placeholder')) {
4708 result.inputPlaceholder = input.getAttribute('placeholder');
4709 }
4710 if (input.hasAttribute('value')) {
4711 result.inputValue = input.getAttribute('value');
4712 }
4713 }
4714 /** @type {HTMLElement[]} */
4715 const inputOptions = Array.from(templateContent.querySelectorAll('swal-input-option'));
4716 if (inputOptions.length) {
4717 result.inputOptions = {};
4718 inputOptions.forEach(option => {
4719 showWarningsForAttributes(option, ['value']);
4720 const optionValue = option.getAttribute('value');
4721 if (!optionValue) {
4722 return;
4723 }
4724 const optionName = option.innerHTML;
4725 result.inputOptions[optionValue] = optionName;
4726 });
4727 }
4728 return result;
4729 };
4730
4731 /**
4732 * @param {DocumentFragment} templateContent
4733 * @param {string[]} paramNames
4734 * @returns {Record<string, string>}
4735 */
4736 const getSwalStringParams = (templateContent, paramNames) => {
4737 /** @type {Record<string, string>} */
4738 const result = {};
4739 for (const i in paramNames) {
4740 const paramName = paramNames[i];
4741 /** @type {HTMLElement | null} */
4742 const tag = templateContent.querySelector(paramName);
4743 if (tag) {
4744 showWarningsForAttributes(tag, []);
4745 result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim();
4746 }
4747 }
4748 return result;
4749 };
4750
4751 /**
4752 * @param {DocumentFragment} templateContent
4753 */
4754 const showWarningsForElements = templateContent => {
4755 const allowedElements = swalStringParams.concat(['swal-param', 'swal-function-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']);
4756 Array.from(templateContent.children).forEach(el => {
4757 const tagName = el.tagName.toLowerCase();
4758 if (!allowedElements.includes(tagName)) {
4759 warn(`Unrecognized element <${tagName}>`);
4760 }
4761 });
4762 };
4763
4764 /**
4765 * @param {HTMLElement} el
4766 * @param {string[]} allowedAttributes
4767 */
4768 const showWarningsForAttributes = (el, allowedAttributes) => {
4769 Array.from(el.attributes).forEach(attribute => {
4770 if (allowedAttributes.indexOf(attribute.name) === -1) {
4771 warn([`Unrecognized attribute "${attribute.name}" on <${el.tagName.toLowerCase()}>.`, `${allowedAttributes.length ? `Allowed attributes are: ${allowedAttributes.join(', ')}` : 'To set the value, use HTML within the element.'}`]);
4772 }
4773 });
4774 };
4775
4776 const SHOW_CLASS_TIMEOUT = 10;
4777
4778 /**
4779 * Open popup, add necessary classes and styles, fix scrollbar
4780 *
4781 * @param {SweetAlertOptions} params
4782 */
4783 const openPopup = params => {
4784 var _globalState$eventEmi, _globalState$eventEmi2;
4785 const container = getContainer();
4786 const popup = getPopup();
4787 if (!container || !popup) {
4788 return;
4789 }
4790 if (typeof params.willOpen === 'function') {
4791 params.willOpen(popup);
4792 }
4793 (_globalState$eventEmi = globalState.eventEmitter) === null || _globalState$eventEmi === void 0 || _globalState$eventEmi.emit('willOpen', popup);
4794 const bodyStyles = window.getComputedStyle(document.body);
4795 const initialBodyOverflow = bodyStyles.overflowY;
4796 addClasses(container, popup, params);
4797
4798 // scrolling is 'hidden' until animation is done, after that 'auto'
4799 setTimeout(() => {
4800 setScrollingVisibility(container, popup);
4801 }, SHOW_CLASS_TIMEOUT);
4802 if (isModal()) {
4803 fixScrollContainer(container, params.scrollbarPadding !== undefined ? params.scrollbarPadding : false, initialBodyOverflow);
4804 setAriaHidden();
4805 }
4806
4807 // https://github.com/sweetalert2/sweetalert2/issues/2923
4808 if (isIOS && params.backdrop === false && popup.scrollHeight > container.clientHeight) {
4809 // remove pointer-events: none from container, it breaks scrolling tall popups in iOS
4810 container.style.pointerEvents = 'auto';
4811 }
4812 if (!isToast() && !globalState.previousActiveElement) {
4813 globalState.previousActiveElement = document.activeElement;
4814 }
4815 if (typeof params.didOpen === 'function') {
4816 const didOpen = params.didOpen;
4817 setTimeout(() => didOpen(popup));
4818 }
4819 (_globalState$eventEmi2 = globalState.eventEmitter) === null || _globalState$eventEmi2 === void 0 || _globalState$eventEmi2.emit('didOpen', popup);
4820 };
4821
4822 /**
4823 * @param {Event} event
4824 */
4825 const swalOpenAnimationFinished = event => {
4826 const popup = getPopup();
4827 if (!popup || event.target !== popup) {
4828 return;
4829 }
4830 const container = getContainer();
4831 if (!container) {
4832 return;
4833 }
4834 popup.removeEventListener('animationend', swalOpenAnimationFinished);
4835 popup.removeEventListener('transitionend', swalOpenAnimationFinished);
4836 container.style.overflowY = 'auto';
4837
4838 // no-transition is added in init() in case one swal is opened right after another
4839 removeClass(container, swalClasses['no-transition']);
4840 };
4841
4842 /**
4843 * @param {HTMLElement} container
4844 * @param {HTMLElement} popup
4845 */
4846 const setScrollingVisibility = (container, popup) => {
4847 if (hasCssAnimation(popup)) {
4848 container.style.overflowY = 'hidden';
4849 popup.addEventListener('animationend', swalOpenAnimationFinished);
4850 popup.addEventListener('transitionend', swalOpenAnimationFinished);
4851 } else {
4852 container.style.overflowY = 'auto';
4853 }
4854 };
4855
4856 /**
4857 * @param {HTMLElement} container
4858 * @param {boolean} scrollbarPadding
4859 * @param {string} initialBodyOverflow
4860 */
4861 const fixScrollContainer = (container, scrollbarPadding, initialBodyOverflow) => {
4862 iOSfix();
4863 if (scrollbarPadding && initialBodyOverflow !== 'hidden') {
4864 replaceScrollbarWithPadding(initialBodyOverflow);
4865 }
4866
4867 // sweetalert2/issues/1247
4868 setTimeout(() => {
4869 container.scrollTop = 0;
4870 });
4871 };
4872
4873 /**
4874 * @param {HTMLElement} container
4875 * @param {HTMLElement} popup
4876 * @param {SweetAlertOptions} params
4877 */
4878 const addClasses = (container, popup, params) => {
4879 var _params$showClass;
4880 if ((_params$showClass = params.showClass) !== null && _params$showClass !== void 0 && _params$showClass.backdrop) {
4881 addClass(container, params.showClass.backdrop);
4882 }
4883 if (params.animation) {
4884 // this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059
4885 popup.style.setProperty('opacity', '0', 'important');
4886 show(popup, 'grid');
4887 setTimeout(() => {
4888 var _params$showClass2;
4889 // Animate popup right after showing it
4890 if ((_params$showClass2 = params.showClass) !== null && _params$showClass2 !== void 0 && _params$showClass2.popup) {
4891 addClass(popup, params.showClass.popup);
4892 }
4893 // and remove the opacity workaround
4894 popup.style.removeProperty('opacity');
4895 }, SHOW_CLASS_TIMEOUT); // 10ms in order to fix #2062
4896 } else {
4897 show(popup, 'grid');
4898 }
4899 addClass([document.documentElement, document.body], swalClasses.shown);
4900 if (params.heightAuto && params.backdrop && !params.toast) {
4901 addClass([document.documentElement, document.body], swalClasses['height-auto']);
4902 }
4903 };
4904
4905 var defaultInputValidators = {
4906 /**
4907 * @param {string} string
4908 * @param {string} [validationMessage]
4909 * @returns {Promise<string | void>}
4910 */
4911 email: (string, validationMessage) => {
4912 return /^[a-zA-Z0-9.+_'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]+$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid email address');
4913 },
4914 /**
4915 * @param {string} string
4916 * @param {string} [validationMessage]
4917 * @returns {Promise<string | void>}
4918 */
4919 url: (string, validationMessage) => {
4920 // taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #2013
4921 return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid URL');
4922 }
4923 };
4924
4925 /**
4926 * @param {SweetAlertOptions} params
4927 */
4928 function setDefaultInputValidators(params) {
4929 // Use default `inputValidator` for supported input types if not provided
4930 if (params.inputValidator) {
4931 return;
4932 }
4933 if (params.input === 'email') {
4934 params.inputValidator = defaultInputValidators['email'];
4935 }
4936 if (params.input === 'url') {
4937 params.inputValidator = defaultInputValidators['url'];
4938 }
4939 }
4940
4941 /**
4942 * @param {SweetAlertOptions} params
4943 */
4944 function validateCustomTargetElement(params) {
4945 // Determine if the custom target element is valid
4946 if (!params.target || typeof params.target === 'string' && !document.querySelector(params.target) || typeof params.target !== 'string' && !params.target.appendChild) {
4947 warn('Target parameter is not valid, defaulting to "body"');
4948 params.target = 'body';
4949 }
4950 }
4951
4952 /**
4953 * Set type, text and actions on popup
4954 *
4955 * @param {SweetAlertOptions} params
4956 */
4957 function setParameters(params) {
4958 setDefaultInputValidators(params);
4959
4960 // showLoaderOnConfirm && preConfirm
4961 if (params.showLoaderOnConfirm && !params.preConfirm) {
4962 warn('showLoaderOnConfirm is set to true, but preConfirm is not defined.\n' + 'showLoaderOnConfirm should be used together with preConfirm, see usage example:\n' + 'https://sweetalert2.github.io/#ajax-request');
4963 }
4964 validateCustomTargetElement(params);
4965
4966 // Replace newlines with <br> in title
4967 if (typeof params.title === 'string') {
4968 params.title = params.title.split('\n').join('<br />');
4969 }
4970 init(params);
4971 }
4972
4973 /** @type {SweetAlert} */
4974 let currentInstance;
4975 var _promise = /*#__PURE__*/new WeakMap();
4976 class SweetAlert {
4977 /**
4978 * @param {...(SweetAlertOptions | string)} args
4979 * @this {SweetAlert}
4980 */
4981 constructor(...args) {
4982 /**
4983 * @type {Promise<SweetAlertResult>}
4984 */
4985 _classPrivateFieldInitSpec(this, _promise, /** @type {Promise<SweetAlertResult>} */
4986 Promise.resolve({
4987 isConfirmed: false,
4988 isDenied: false,
4989 isDismissed: true
4990 }));
4991 // Prevent run in Node env
4992 if (typeof window === 'undefined') {
4993 return;
4994 }
4995 currentInstance = this;
4996
4997 // @ts-ignore
4998 const outerParams = Object.freeze(this.constructor.argsToParams(args));
4999
5000 /** @type {Readonly<SweetAlertOptions>} */
5001 this.params = outerParams;
5002
5003 /** @type {boolean} */
5004 this.isAwaitingPromise = false;
5005 _classPrivateFieldSet2(_promise, this, this._main(currentInstance.params));
5006 }
5007
5008 /**
5009 * @param {any} userParams
5010 * @param {any} mixinParams
5011 */
5012 _main(userParams, mixinParams = {}) {
5013 showWarningsForParams(Object.assign({}, mixinParams, userParams));
5014 if (globalState.currentInstance) {
5015 const swalPromiseResolve = privateMethods.swalPromiseResolve.get(globalState.currentInstance);
5016 const {
5017 isAwaitingPromise
5018 } = globalState.currentInstance;
5019 globalState.currentInstance._destroy();
5020 if (!isAwaitingPromise) {
5021 swalPromiseResolve({
5022 isDismissed: true
5023 });
5024 }
5025 if (isModal()) {
5026 unsetAriaHidden();
5027 }
5028 }
5029 globalState.currentInstance = currentInstance;
5030 const innerParams = prepareParams(userParams, mixinParams);
5031 setParameters(innerParams);
5032 Object.freeze(innerParams);
5033
5034 // clear the previous timer
5035 if (globalState.timeout) {
5036 globalState.timeout.stop();
5037 delete globalState.timeout;
5038 }
5039
5040 // clear the restore focus timeout
5041 clearTimeout(globalState.restoreFocusTimeout);
5042 const domCache = populateDomCache(currentInstance);
5043 render(currentInstance, innerParams);
5044 privateProps.innerParams.set(currentInstance, innerParams);
5045 return swalPromise(currentInstance, domCache, innerParams);
5046 }
5047
5048 // `catch` cannot be the name of a module export, so we define our thenable methods here instead
5049 /**
5050 * @param {any} onFulfilled
5051 */
5052 // oxlint-disable-next-line unicorn/no-thenable
5053 then(onFulfilled) {
5054 return _classPrivateFieldGet2(_promise, this).then(onFulfilled);
5055 }
5056
5057 /**
5058 * @param {any} onFinally
5059 */
5060 finally(onFinally) {
5061 return _classPrivateFieldGet2(_promise, this).finally(onFinally);
5062 }
5063 }
5064
5065 /**
5066 * @param {SweetAlert} instance
5067 * @param {DomCache} domCache
5068 * @param {SweetAlertOptions} innerParams
5069 * @returns {Promise<SweetAlertResult>}
5070 */
5071 const swalPromise = (instance, domCache, innerParams) => {
5072 return new Promise((resolve, reject) => {
5073 // functions to handle all closings/dismissals
5074 /**
5075 * @param {DismissReason} dismiss
5076 */
5077 const dismissWith = dismiss => {
5078 instance.close({
5079 isDismissed: true,
5080 dismiss,
5081 isConfirmed: false,
5082 isDenied: false
5083 });
5084 };
5085 privateMethods.swalPromiseResolve.set(instance, resolve);
5086 privateMethods.swalPromiseReject.set(instance, reject);
5087 domCache.confirmButton.onclick = () => {
5088 handleConfirmButtonClick(instance);
5089 };
5090 domCache.denyButton.onclick = () => {
5091 handleDenyButtonClick(instance);
5092 };
5093 domCache.cancelButton.onclick = () => {
5094 handleCancelButtonClick(instance, dismissWith);
5095 };
5096 domCache.closeButton.onclick = () => {
5097 dismissWith(DismissReason.close);
5098 };
5099 handlePopupClick(innerParams, domCache, dismissWith);
5100 addKeydownHandler(globalState, innerParams, dismissWith);
5101 handleInputOptionsAndValue(instance, innerParams);
5102 openPopup(innerParams);
5103 setupTimer(globalState, innerParams, dismissWith);
5104 initFocus(domCache, innerParams);
5105
5106 // Scroll container to top on open (#1247, #1946)
5107 setTimeout(() => {
5108 domCache.container.scrollTop = 0;
5109 });
5110 });
5111 };
5112
5113 /**
5114 * @param {SweetAlertOptions} userParams
5115 * @param {SweetAlertOptions} mixinParams
5116 * @returns {SweetAlertOptions}
5117 */
5118 const prepareParams = (userParams, mixinParams) => {
5119 const templateParams = getTemplateParams(userParams);
5120 const params = Object.assign({}, defaultParams, mixinParams, templateParams, userParams); // precedence is described in #2131
5121 params.showClass = Object.assign({}, defaultParams.showClass, params.showClass);
5122 params.hideClass = Object.assign({}, defaultParams.hideClass, params.hideClass);
5123 if (params.animation === false) {
5124 params.showClass = {
5125 backdrop: 'swal2-noanimation'
5126 };
5127 params.hideClass = {};
5128 }
5129 return params;
5130 };
5131
5132 /**
5133 * @param {SweetAlert} instance
5134 * @returns {DomCache}
5135 */
5136 const populateDomCache = instance => {
5137 const domCache = /** @type {DomCache} */{
5138 popup: (/** @type {HTMLElement} */getPopup()),
5139 container: (/** @type {HTMLElement} */getContainer()),
5140 actions: (/** @type {HTMLElement} */getActions()),
5141 confirmButton: (/** @type {HTMLElement} */getConfirmButton()),
5142 denyButton: (/** @type {HTMLElement} */getDenyButton()),
5143 cancelButton: (/** @type {HTMLElement} */getCancelButton()),
5144 loader: (/** @type {HTMLElement} */getLoader()),
5145 closeButton: (/** @type {HTMLElement} */getCloseButton()),
5146 validationMessage: (/** @type {HTMLElement} */getValidationMessage()),
5147 progressSteps: (/** @type {HTMLElement} */getProgressSteps())
5148 };
5149 privateProps.domCache.set(instance, domCache);
5150 return domCache;
5151 };
5152
5153 /**
5154 * @param {GlobalState} globalState
5155 * @param {SweetAlertOptions} innerParams
5156 * @param {(dismiss: DismissReason) => void} dismissWith
5157 */
5158 const setupTimer = (globalState, innerParams, dismissWith) => {
5159 const timerProgressBar = getTimerProgressBar();
5160 hide(timerProgressBar);
5161 if (innerParams.timer) {
5162 globalState.timeout = new Timer(() => {
5163 dismissWith('timer');
5164 delete globalState.timeout;
5165 }, innerParams.timer);
5166 if (innerParams.timerProgressBar && timerProgressBar) {
5167 show(timerProgressBar);
5168 applyCustomClass(timerProgressBar, innerParams, 'timerProgressBar');
5169 setTimeout(() => {
5170 if (globalState.timeout && globalState.timeout.running) {
5171 // timer can be already stopped or unset at this point
5172 animateTimerProgressBar(/** @type {number} */innerParams.timer);
5173 }
5174 });
5175 }
5176 }
5177 };
5178
5179 /**
5180 * Initialize focus in the popup:
5181 *
5182 * 1. If `toast` is `true`, don't steal focus from the document.
5183 * 2. Else if there is an [autofocus] element, focus it.
5184 * 3. Else if `focusConfirm` is `true` and confirm button is visible, focus it.
5185 * 4. Else if `focusDeny` is `true` and deny button is visible, focus it.
5186 * 5. Else if `focusCancel` is `true` and cancel button is visible, focus it.
5187 * 6. Else focus the first focusable element in a popup (if any).
5188 *
5189 * @param {DomCache} domCache
5190 * @param {SweetAlertOptions} innerParams
5191 */
5192 const initFocus = (domCache, innerParams) => {
5193 if (innerParams.toast) {
5194 return;
5195 }
5196 // TODO: this is dumb, remove `allowEnterKey` param in the next major version
5197 if (!callIfFunction(innerParams.allowEnterKey)) {
5198 warnAboutDeprecation('allowEnterKey', 'preConfirm: () => false');
5199 domCache.popup.focus();
5200 return;
5201 }
5202 if (focusAutofocus(domCache)) {
5203 return;
5204 }
5205 if (focusButton(domCache, innerParams)) {
5206 return;
5207 }
5208 setFocus(-1, 1);
5209 };
5210
5211 /**
5212 * @param {DomCache} domCache
5213 * @returns {boolean}
5214 */
5215 const focusAutofocus = domCache => {
5216 const autofocusElements = Array.from(domCache.popup.querySelectorAll('[autofocus]'));
5217 for (const autofocusElement of autofocusElements) {
5218 if (autofocusElement instanceof HTMLElement && isVisible$1(autofocusElement)) {
5219 autofocusElement.focus();
5220 return true;
5221 }
5222 }
5223 return false;
5224 };
5225
5226 /**
5227 * @param {DomCache} domCache
5228 * @param {SweetAlertOptions} innerParams
5229 * @returns {boolean}
5230 */
5231 const focusButton = (domCache, innerParams) => {
5232 if (innerParams.focusDeny && isVisible$1(domCache.denyButton)) {
5233 domCache.denyButton.focus();
5234 return true;
5235 }
5236 if (innerParams.focusCancel && isVisible$1(domCache.cancelButton)) {
5237 domCache.cancelButton.focus();
5238 return true;
5239 }
5240 if (innerParams.focusConfirm && isVisible$1(domCache.confirmButton)) {
5241 domCache.confirmButton.focus();
5242 return true;
5243 }
5244 return false;
5245 };
5246
5247 // Assign instance methods from src/instanceMethods/*.js to prototype
5248 SweetAlert.prototype.disableButtons = disableButtons;
5249 SweetAlert.prototype.enableButtons = enableButtons;
5250 SweetAlert.prototype.getInput = getInput;
5251 SweetAlert.prototype.disableInput = disableInput;
5252 SweetAlert.prototype.enableInput = enableInput;
5253 SweetAlert.prototype.hideLoading = hideLoading;
5254 SweetAlert.prototype.disableLoading = hideLoading;
5255 SweetAlert.prototype.showValidationMessage = showValidationMessage;
5256 SweetAlert.prototype.resetValidationMessage = resetValidationMessage;
5257 SweetAlert.prototype.close = close;
5258 SweetAlert.prototype.closePopup = close;
5259 SweetAlert.prototype.closeModal = close;
5260 SweetAlert.prototype.closeToast = close;
5261 SweetAlert.prototype.rejectPromise = rejectPromise;
5262 SweetAlert.prototype.update = update;
5263 SweetAlert.prototype._destroy = _destroy;
5264
5265 // Assign static methods from src/staticMethods/*.js to constructor
5266 Object.assign(SweetAlert, staticMethods);
5267
5268 // Proxy to instance methods to constructor, for now, for backwards compatibility
5269 Object.keys(instanceMethods).forEach(key => {
5270 /**
5271 * @param {...(SweetAlertOptions | string | undefined)} args
5272 * @returns {SweetAlertResult | Promise<SweetAlertResult> | undefined}
5273 */
5274 // @ts-ignore: Dynamic property assignment for backwards compatibility
5275 SweetAlert[key] = function (...args) {
5276 // @ts-ignore
5277 if (currentInstance && currentInstance[key]) {
5278 // @ts-ignore
5279 return currentInstance[key](...args);
5280 }
5281 return undefined;
5282 };
5283 });
5284 SweetAlert.DismissReason = DismissReason;
5285 SweetAlert.version = '11.26.25';
5286
5287 const Swal = SweetAlert;
5288 // @ts-ignore
5289 Swal.default = Swal;
5290
5291 return Swal;
5292
5293 }));
5294 if (typeof this !== 'undefined' && this.Sweetalert2){this.swal = this.sweetAlert = this.Swal = this.SweetAlert = this.Sweetalert2}
5295 "undefined"!=typeof document&&function(e,t){var n=e.createElement("style");if(e.getElementsByTagName("head")[0].appendChild(n),n.styleSheet)n.styleSheet.disabled||(n.styleSheet.cssText=t);else try{n.innerHTML=t}catch(e){n.innerText=t}}(document,":root{--swal2-outline: 0 0 0 3px rgba(100, 150, 200, 0.5);--swal2-container-padding: 0.625em;--swal2-backdrop: rgba(0, 0, 0, 0.4);--swal2-backdrop-transition: background-color 0.15s;--swal2-width: 32em;--swal2-padding: 0 0 1.25em;--swal2-border: none;--swal2-border-radius: 0.3125rem;--swal2-background: white;--swal2-color: #545454;--swal2-show-animation: swal2-show 0.3s;--swal2-hide-animation: swal2-hide 0.15s forwards;--swal2-icon-zoom: 1;--swal2-title-padding: 0.8em 1em 0;--swal2-html-container-padding: 1em 1.6em 0.3em;--swal2-input-border: 1px solid #d9d9d9;--swal2-input-border-radius: 0.1875em;--swal2-input-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06), 0 0 0 3px transparent;--swal2-input-background: transparent;--swal2-input-transition: border-color 0.2s, box-shadow 0.2s;--swal2-input-hover-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06), 0 0 0 3px transparent;--swal2-input-focus-border: 1px solid #b4dbed;--swal2-input-focus-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06), 0 0 0 3px rgba(100, 150, 200, 0.5);--swal2-progress-step-background: #add8e6;--swal2-validation-message-background: #f0f0f0;--swal2-validation-message-color: #666;--swal2-footer-border-color: #eee;--swal2-footer-background: transparent;--swal2-footer-color: inherit;--swal2-timer-progress-bar-background: rgba(0, 0, 0, 0.3);--swal2-close-button-position: initial;--swal2-close-button-inset: auto;--swal2-close-button-font-size: 2.5em;--swal2-close-button-color: #ccc;--swal2-close-button-transition: color 0.2s, box-shadow 0.2s;--swal2-close-button-outline: initial;--swal2-close-button-box-shadow: inset 0 0 0 3px transparent;--swal2-close-button-focus-box-shadow: inset var(--swal2-outline);--swal2-close-button-hover-transform: none;--swal2-actions-justify-content: center;--swal2-actions-width: auto;--swal2-actions-margin: 1.25em auto 0;--swal2-actions-padding: 0;--swal2-actions-border-radius: 0;--swal2-actions-background: transparent;--swal2-action-button-transition: background-color 0.2s, box-shadow 0.2s;--swal2-action-button-hover: black 10%;--swal2-action-button-active: black 10%;--swal2-confirm-button-box-shadow: none;--swal2-confirm-button-border-radius: 0.25em;--swal2-confirm-button-background-color: #7066e0;--swal2-confirm-button-color: #fff;--swal2-deny-button-box-shadow: none;--swal2-deny-button-border-radius: 0.25em;--swal2-deny-button-background-color: #dc3741;--swal2-deny-button-color: #fff;--swal2-cancel-button-box-shadow: none;--swal2-cancel-button-border-radius: 0.25em;--swal2-cancel-button-background-color: #6e7881;--swal2-cancel-button-color: #fff;--swal2-toast-show-animation: swal2-toast-show 0.5s;--swal2-toast-hide-animation: swal2-toast-hide 0.1s forwards;--swal2-toast-border: none;--swal2-toast-box-shadow: 0 0 1px hsl(0deg 0% 0% / 0.075), 0 1px 2px hsl(0deg 0% 0% / 0.075), 1px 2px 4px hsl(0deg 0% 0% / 0.075), 1px 3px 8px hsl(0deg 0% 0% / 0.075), 2px 4px 16px hsl(0deg 0% 0% / 0.075)}[data-swal2-theme=dark]{--swal2-dark-theme-black: #19191a;--swal2-dark-theme-white: #e1e1e1;--swal2-background: var(--swal2-dark-theme-black);--swal2-color: var(--swal2-dark-theme-white);--swal2-footer-border-color: #555;--swal2-input-background: color-mix(in srgb, var(--swal2-dark-theme-black), var(--swal2-dark-theme-white) 10%);--swal2-validation-message-background: color-mix( in srgb, var(--swal2-dark-theme-black), var(--swal2-dark-theme-white) 10% );--swal2-validation-message-color: var(--swal2-dark-theme-white);--swal2-timer-progress-bar-background: rgba(255, 255, 255, 0.7)}@media(prefers-color-scheme: dark){[data-swal2-theme=auto]{--swal2-dark-theme-black: #19191a;--swal2-dark-theme-white: #e1e1e1;--swal2-background: var(--swal2-dark-theme-black);--swal2-color: var(--swal2-dark-theme-white);--swal2-footer-border-color: #555;--swal2-input-background: color-mix(in srgb, var(--swal2-dark-theme-black), var(--swal2-dark-theme-white) 10%);--swal2-validation-message-background: color-mix( in srgb, var(--swal2-dark-theme-black), var(--swal2-dark-theme-white) 10% );--swal2-validation-message-color: var(--swal2-dark-theme-white);--swal2-timer-progress-bar-background: rgba(255, 255, 255, 0.7)}}body.swal2-shown:not(.swal2-no-backdrop,.swal2-toast-shown){overflow:hidden}body.swal2-height-auto{height:auto !important}body.swal2-no-backdrop .swal2-container{background-color:rgba(0,0,0,0) !important;pointer-events:none}body.swal2-no-backdrop .swal2-container .swal2-popup{pointer-events:auto}body.swal2-no-backdrop .swal2-container .swal2-modal{box-shadow:0 0 10px var(--swal2-backdrop)}body.swal2-toast-shown .swal2-container{box-sizing:border-box;width:360px;max-width:100%;background-color:rgba(0,0,0,0);pointer-events:none}body.swal2-toast-shown .swal2-container.swal2-top{inset:0 auto auto 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-top-end,body.swal2-toast-shown .swal2-container.swal2-top-right{inset:0 0 auto auto}body.swal2-toast-shown .swal2-container.swal2-top-start,body.swal2-toast-shown .swal2-container.swal2-top-left{inset:0 auto auto 0}body.swal2-toast-shown .swal2-container.swal2-center-start,body.swal2-toast-shown .swal2-container.swal2-center-left{inset:50% auto auto 0;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-center{inset:50% auto auto 50%;transform:translate(-50%, -50%)}body.swal2-toast-shown .swal2-container.swal2-center-end,body.swal2-toast-shown .swal2-container.swal2-center-right{inset:50% 0 auto auto;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-start,body.swal2-toast-shown .swal2-container.swal2-bottom-left{inset:auto auto 0 0}body.swal2-toast-shown .swal2-container.swal2-bottom{inset:auto auto 0 50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-end,body.swal2-toast-shown .swal2-container.swal2-bottom-right{inset:auto 0 0 auto}@media print{body.swal2-shown:not(.swal2-no-backdrop,.swal2-toast-shown){overflow-y:scroll !important}body.swal2-shown:not(.swal2-no-backdrop,.swal2-toast-shown)>[aria-hidden=true]{display:none}body.swal2-shown:not(.swal2-no-backdrop,.swal2-toast-shown) .swal2-container{position:static !important}}div:where(.swal2-container){display:grid;position:fixed;z-index:1060;inset:0;box-sizing:border-box;grid-template-areas:\"top-start top top-end\" \"center-start center center-end\" \"bottom-start bottom-center bottom-end\";grid-template-rows:minmax(min-content, auto) minmax(min-content, auto) minmax(min-content, auto);height:100%;padding:var(--swal2-container-padding);overflow-x:hidden;transition:var(--swal2-backdrop-transition);-webkit-overflow-scrolling:touch}div:where(.swal2-container).swal2-backdrop-show,div:where(.swal2-container).swal2-noanimation{background:var(--swal2-backdrop)}div:where(.swal2-container).swal2-backdrop-hide{background:rgba(0,0,0,0) !important}div:where(.swal2-container).swal2-top-start,div:where(.swal2-container).swal2-center-start,div:where(.swal2-container).swal2-bottom-start{grid-template-columns:minmax(0, 1fr) auto auto}div:where(.swal2-container).swal2-top,div:where(.swal2-container).swal2-center,div:where(.swal2-container).swal2-bottom{grid-template-columns:auto minmax(0, 1fr) auto}div:where(.swal2-container).swal2-top-end,div:where(.swal2-container).swal2-center-end,div:where(.swal2-container).swal2-bottom-end{grid-template-columns:auto auto minmax(0, 1fr)}div:where(.swal2-container).swal2-top-start>.swal2-popup{align-self:start}div:where(.swal2-container).swal2-top>.swal2-popup{grid-column:2;place-self:start center}div:where(.swal2-container).swal2-top-end>.swal2-popup,div:where(.swal2-container).swal2-top-right>.swal2-popup{grid-column:3;place-self:start end}div:where(.swal2-container).swal2-center-start>.swal2-popup,div:where(.swal2-container).swal2-center-left>.swal2-popup{grid-row:2;align-self:center}div:where(.swal2-container).swal2-center>.swal2-popup{grid-column:2;grid-row:2;place-self:center center}div:where(.swal2-container).swal2-center-end>.swal2-popup,div:where(.swal2-container).swal2-center-right>.swal2-popup{grid-column:3;grid-row:2;place-self:center end}div:where(.swal2-container).swal2-bottom-start>.swal2-popup,div:where(.swal2-container).swal2-bottom-left>.swal2-popup{grid-column:1;grid-row:3;align-self:end}div:where(.swal2-container).swal2-bottom>.swal2-popup{grid-column:2;grid-row:3;place-self:end center}div:where(.swal2-container).swal2-bottom-end>.swal2-popup,div:where(.swal2-container).swal2-bottom-right>.swal2-popup{grid-column:3;grid-row:3;place-self:end end}div:where(.swal2-container).swal2-grow-row>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-column:1/4;width:100%}div:where(.swal2-container).swal2-grow-column>.swal2-popup,div:where(.swal2-container).swal2-grow-fullscreen>.swal2-popup{grid-row:1/4;align-self:stretch}div:where(.swal2-container).swal2-no-transition{transition:none !important}div:where(.swal2-container)[popover]{width:auto;border:0}div:where(.swal2-container) div:where(.swal2-popup){display:none;position:relative;box-sizing:border-box;grid-template-columns:minmax(0, 100%);width:var(--swal2-width);max-width:100%;padding:var(--swal2-padding);border:var(--swal2-border);border-radius:var(--swal2-border-radius);background:var(--swal2-background);color:var(--swal2-color);font-family:inherit;font-size:1rem}div:where(.swal2-container) div:where(.swal2-popup):focus{outline:none}div:where(.swal2-container) div:where(.swal2-popup).swal2-loading{overflow-y:hidden}div:where(.swal2-container) div:where(.swal2-popup).swal2-draggable{cursor:grab}div:where(.swal2-container) div:where(.swal2-popup).swal2-draggable div:where(.swal2-icon){cursor:grab}div:where(.swal2-container) div:where(.swal2-popup).swal2-dragging{cursor:grabbing}div:where(.swal2-container) div:where(.swal2-popup).swal2-dragging div:where(.swal2-icon){cursor:grabbing}div:where(.swal2-container) h2:where(.swal2-title){position:relative;max-width:100%;margin:0;padding:var(--swal2-title-padding);color:inherit;font-size:1.875em;font-weight:600;text-align:center;text-transform:none;overflow-wrap:break-word;cursor:initial}div:where(.swal2-container) div:where(.swal2-actions){display:flex;z-index:1;box-sizing:border-box;flex-wrap:wrap;align-items:center;justify-content:var(--swal2-actions-justify-content);width:var(--swal2-actions-width);margin:var(--swal2-actions-margin);padding:var(--swal2-actions-padding);border-radius:var(--swal2-actions-border-radius);background:var(--swal2-actions-background)}div:where(.swal2-container) div:where(.swal2-loader){display:none;align-items:center;justify-content:center;width:2.2em;height:2.2em;margin:0 1.875em;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border-width:.25em;border-style:solid;border-radius:100%;border-color:#2778c4 rgba(0,0,0,0) #2778c4 rgba(0,0,0,0)}div:where(.swal2-container) button:where(.swal2-styled){margin:.3125em;padding:.625em 1.1em;transition:var(--swal2-action-button-transition);border:none;box-shadow:0 0 0 3px rgba(0,0,0,0);font-weight:500}div:where(.swal2-container) button:where(.swal2-styled):not([disabled]){cursor:pointer}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-confirm){border-radius:var(--swal2-confirm-button-border-radius);background:initial;background-color:var(--swal2-confirm-button-background-color);box-shadow:var(--swal2-confirm-button-box-shadow);color:var(--swal2-confirm-button-color);font-size:1em}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-confirm):hover{background-color:color-mix(in srgb, var(--swal2-confirm-button-background-color), var(--swal2-action-button-hover))}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-confirm):active{background-color:color-mix(in srgb, var(--swal2-confirm-button-background-color), var(--swal2-action-button-active))}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-deny){border-radius:var(--swal2-deny-button-border-radius);background:initial;background-color:var(--swal2-deny-button-background-color);box-shadow:var(--swal2-deny-button-box-shadow);color:var(--swal2-deny-button-color);font-size:1em}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-deny):hover{background-color:color-mix(in srgb, var(--swal2-deny-button-background-color), var(--swal2-action-button-hover))}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-deny):active{background-color:color-mix(in srgb, var(--swal2-deny-button-background-color), var(--swal2-action-button-active))}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-cancel){border-radius:var(--swal2-cancel-button-border-radius);background:initial;background-color:var(--swal2-cancel-button-background-color);box-shadow:var(--swal2-cancel-button-box-shadow);color:var(--swal2-cancel-button-color);font-size:1em}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-cancel):hover{background-color:color-mix(in srgb, var(--swal2-cancel-button-background-color), var(--swal2-action-button-hover))}div:where(.swal2-container) button:where(.swal2-styled):where(.swal2-cancel):active{background-color:color-mix(in srgb, var(--swal2-cancel-button-background-color), var(--swal2-action-button-active))}div:where(.swal2-container) button:where(.swal2-styled):focus-visible{outline:none;box-shadow:var(--swal2-action-button-focus-box-shadow)}div:where(.swal2-container) button:where(.swal2-styled)[disabled]:not(.swal2-loading){opacity:.4}div:where(.swal2-container) button:where(.swal2-styled)::-moz-focus-inner{border:0}div:where(.swal2-container) div:where(.swal2-footer){margin:1em 0 0;padding:1em 1em 0;border-top:1px solid var(--swal2-footer-border-color);background:var(--swal2-footer-background);color:var(--swal2-footer-color);font-size:1em;text-align:center;cursor:initial}div:where(.swal2-container) .swal2-timer-progress-bar-container{position:absolute;right:0;bottom:0;left:0;grid-column:auto !important;overflow:hidden;border-bottom-right-radius:var(--swal2-border-radius);border-bottom-left-radius:var(--swal2-border-radius)}div:where(.swal2-container) div:where(.swal2-timer-progress-bar){width:100%;height:.25em;background:var(--swal2-timer-progress-bar-background)}div:where(.swal2-container) img:where(.swal2-image){max-width:100%;margin:2em auto 1em;cursor:initial}div:where(.swal2-container) button:where(.swal2-close){position:var(--swal2-close-button-position);inset:var(--swal2-close-button-inset);z-index:2;align-items:center;justify-content:center;width:1.2em;height:1.2em;margin-top:0;margin-right:0;margin-bottom:-1.2em;padding:0;overflow:hidden;transition:var(--swal2-close-button-transition);border:none;border-radius:var(--swal2-border-radius);outline:var(--swal2-close-button-outline);background:rgba(0,0,0,0);color:var(--swal2-close-button-color);font-family:monospace;font-size:var(--swal2-close-button-font-size);cursor:pointer;justify-self:end}div:where(.swal2-container) button:where(.swal2-close):hover{transform:var(--swal2-close-button-hover-transform);background:rgba(0,0,0,0);color:#f27474}div:where(.swal2-container) button:where(.swal2-close):focus-visible{outline:none;box-shadow:var(--swal2-close-button-focus-box-shadow)}div:where(.swal2-container) button:where(.swal2-close)::-moz-focus-inner{border:0}div:where(.swal2-container) div:where(.swal2-html-container){z-index:1;justify-content:center;margin:0;padding:var(--swal2-html-container-padding);overflow:auto;color:inherit;font-size:1.125em;font-weight:normal;line-height:normal;text-align:center;overflow-wrap:break-word;word-break:break-word;cursor:initial}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea),div:where(.swal2-container) select:where(.swal2-select),div:where(.swal2-container) div:where(.swal2-radio),div:where(.swal2-container) label:where(.swal2-checkbox){margin:1em 2em 3px}div:where(.swal2-container) input:where(.swal2-input),div:where(.swal2-container) input:where(.swal2-file),div:where(.swal2-container) textarea:where(.swal2-textarea){box-sizing:border-box;width:auto;transition:var(--swal2-input-transition);border:var(--swal2-input-border);border-radius:var(--swal2-input-border-radius);background:var(--swal2-input-background);box-shadow:var(--swal2-input-box-shadow);color:inherit;font-size:1.125em}div:where(.swal2-container) input:where(.swal2-input).swal2-inputerror,div:where(.swal2-container) input:where(.swal2-file).swal2-inputerror,div:where(.swal2-container) textarea:where(.swal2-textarea).swal2-inputerror{border-color:#f27474 !important;box-shadow:0 0 2px #f27474 !important}div:where(.swal2-container) input:where(.swal2-input):hover,div:where(.swal2-container) input:where(.swal2-file):hover,div:where(.swal2-container) textarea:where(.swal2-textarea):hover{box-shadow:var(--swal2-input-hover-box-shadow)}div:where(.swal2-container) input:where(.swal2-input):focus,div:where(.swal2-container) input:where(.swal2-file):focus,div:where(.swal2-container) textarea:where(.swal2-textarea):focus{border:var(--swal2-input-focus-border);outline:none;box-shadow:var(--swal2-input-focus-box-shadow)}div:where(.swal2-container) input:where(.swal2-input)::placeholder,div:where(.swal2-container) input:where(.swal2-file)::placeholder,div:where(.swal2-container) textarea:where(.swal2-textarea)::placeholder{color:#ccc}div:where(.swal2-container) .swal2-range{margin:1em 2em 3px;background:var(--swal2-background)}div:where(.swal2-container) .swal2-range input{width:80%}div:where(.swal2-container) .swal2-range output{width:20%;color:inherit;font-weight:600;text-align:center}div:where(.swal2-container) .swal2-range input,div:where(.swal2-container) .swal2-range output{height:2.625em;padding:0;font-size:1.125em;line-height:2.625em}div:where(.swal2-container) .swal2-input{height:2.625em;padding:0 .75em}div:where(.swal2-container) .swal2-file{width:75%;margin-right:auto;margin-left:auto;background:var(--swal2-input-background);font-size:1.125em}div:where(.swal2-container) .swal2-textarea{height:6.75em;padding:.75em}div:where(.swal2-container) .swal2-select{min-width:50%;max-width:100%;padding:.375em .625em;background:var(--swal2-input-background);color:inherit;font-size:1.125em}div:where(.swal2-container) .swal2-radio,div:where(.swal2-container) .swal2-checkbox{align-items:center;justify-content:center;background:var(--swal2-background);color:inherit}div:where(.swal2-container) .swal2-radio label,div:where(.swal2-container) .swal2-checkbox label{margin:0 .6em;font-size:1.125em}div:where(.swal2-container) .swal2-radio input,div:where(.swal2-container) .swal2-checkbox input{flex-shrink:0;margin:0 .4em}div:where(.swal2-container) label:where(.swal2-input-label){display:flex;justify-content:center;margin:1em auto 0}div:where(.swal2-container) div:where(.swal2-validation-message){align-items:center;justify-content:center;margin:1em 0 0;padding:.625em;overflow:hidden;background:var(--swal2-validation-message-background);color:var(--swal2-validation-message-color);font-size:1em;font-weight:300}div:where(.swal2-container) div:where(.swal2-validation-message)::before{content:\"!\";display:inline-block;width:1.5em;min-width:1.5em;height:1.5em;margin:0 .625em;border-radius:50%;background-color:#f27474;color:#fff;font-weight:600;line-height:1.5em;text-align:center}div:where(.swal2-container) .swal2-progress-steps{flex-wrap:wrap;align-items:center;max-width:100%;margin:1.25em auto;padding:0;background:rgba(0,0,0,0);font-weight:600}div:where(.swal2-container) .swal2-progress-steps li{display:inline-block;position:relative}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step{z-index:20;flex-shrink:0;width:2em;height:2em;border-radius:2em;background:#2778c4;color:#fff;line-height:2em;text-align:center}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:#2778c4}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step{background:var(--swal2-progress-step-background);color:#fff}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step-line{background:var(--swal2-progress-step-background)}div:where(.swal2-container) .swal2-progress-steps .swal2-progress-step-line{z-index:10;flex-shrink:0;width:2.5em;height:.4em;margin:0 -1px;background:#2778c4}div:where(.swal2-icon){position:relative;box-sizing:content-box;justify-content:center;width:5em;height:5em;margin:2.5em auto .6em;zoom:var(--swal2-icon-zoom);border:.25em solid rgba(0,0,0,0);border-radius:50%;border-color:#000;font-family:inherit;line-height:5em;cursor:default;user-select:none}div:where(.swal2-icon) .swal2-icon-content{display:flex;align-items:center;font-size:3.75em}div:where(.swal2-icon).swal2-error{border-color:#f27474;color:#f27474}div:where(.swal2-icon).swal2-error .swal2-x-mark{position:relative;flex-grow:1}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line]{display:block;position:absolute;top:2.3125em;width:2.9375em;height:.3125em;border-radius:.125em;background-color:#f27474}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=left]{left:1.0625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-error [class^=swal2-x-mark-line][class$=right]{right:1em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-error.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-error.swal2-icon-show .swal2-x-mark{animation:swal2-animate-error-x-mark .5s}div:where(.swal2-icon).swal2-warning{border-color:#f8bb86;color:#f8bb86}div:where(.swal2-icon).swal2-warning.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-warning.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .5s}div:where(.swal2-icon).swal2-info{border-color:#3fc3ee;color:#3fc3ee}div:where(.swal2-icon).swal2-info.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-info.swal2-icon-show .swal2-icon-content{animation:swal2-animate-i-mark .8s}div:where(.swal2-icon).swal2-question{border-color:#87adbd;color:#87adbd}div:where(.swal2-icon).swal2-question.swal2-icon-show{animation:swal2-animate-error-icon .5s}div:where(.swal2-icon).swal2-question.swal2-icon-show .swal2-icon-content{animation:swal2-animate-question-mark .8s}div:where(.swal2-icon).swal2-success{border-color:#a5dc86;color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line]{position:absolute;width:3.75em;height:7.5em;border-radius:50%}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.4375em;left:-2.0635em;transform:rotate(-45deg);transform-origin:3.75em 3.75em;border-radius:7.5em 0 0 7.5em}div:where(.swal2-icon).swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.6875em;left:1.875em;transform:rotate(-45deg);transform-origin:0 3.75em;border-radius:0 7.5em 7.5em 0}div:where(.swal2-icon).swal2-success .swal2-success-ring{position:absolute;z-index:2;top:-0.25em;left:-0.25em;box-sizing:content-box;width:100%;height:100%;border:.25em solid rgba(165,220,134,.3);border-radius:50%}div:where(.swal2-icon).swal2-success .swal2-success-fix{position:absolute;z-index:1;top:.5em;left:1.625em;width:.4375em;height:5.625em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line]{display:block;position:absolute;z-index:2;height:.3125em;border-radius:.125em;background-color:#a5dc86}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=tip]{top:2.875em;left:.8125em;width:1.5625em;transform:rotate(45deg)}div:where(.swal2-icon).swal2-success [class^=swal2-success-line][class$=long]{top:2.375em;right:.5em;width:2.9375em;transform:rotate(-45deg)}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-animate-success-line-tip .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-animate-success-line-long .75s}div:where(.swal2-icon).swal2-success.swal2-icon-show .swal2-success-circular-line-right{animation:swal2-rotate-success-circular-line 4.25s ease-in}[class^=swal2]{-webkit-tap-highlight-color:rgba(0,0,0,0)}.swal2-show{animation:var(--swal2-show-animation)}.swal2-hide{animation:var(--swal2-hide-animation)}.swal2-noanimation{transition:none}.swal2-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.swal2-rtl .swal2-close{margin-right:initial;margin-left:0}.swal2-rtl .swal2-timer-progress-bar{right:0;left:auto}.swal2-toast{box-sizing:border-box;grid-column:1/4 !important;grid-row:1/4 !important;grid-template-columns:min-content auto min-content;padding:1em;overflow-y:hidden;border:var(--swal2-toast-border);background:var(--swal2-background);box-shadow:var(--swal2-toast-box-shadow);pointer-events:auto}.swal2-toast>*{grid-column:2}.swal2-toast h2:where(.swal2-title){margin:.5em 1em;padding:0;font-size:1em;text-align:initial}.swal2-toast .swal2-loading{justify-content:center}.swal2-toast input:where(.swal2-input){height:2em;margin:.5em;font-size:1em}.swal2-toast .swal2-validation-message{font-size:1em}.swal2-toast div:where(.swal2-footer){margin:.5em 0 0;padding:.5em 0 0;font-size:.8em}.swal2-toast button:where(.swal2-close){grid-column:3/3;grid-row:1/99;align-self:center;width:.8em;height:.8em;margin:0;font-size:2em}.swal2-toast div:where(.swal2-html-container){margin:.5em 1em;padding:0;overflow:initial;font-size:1em;text-align:initial}.swal2-toast div:where(.swal2-html-container):empty{padding:0}.swal2-toast .swal2-loader{grid-column:1;grid-row:1/99;align-self:center;width:2em;height:2em;margin:.25em}.swal2-toast .swal2-icon{grid-column:1;grid-row:1/99;align-self:center;width:2em;min-width:2em;height:2em;margin:0 .5em 0 0}.swal2-toast .swal2-icon .swal2-icon-content{display:flex;align-items:center;font-size:1.8em;font-weight:bold}.swal2-toast .swal2-icon.swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line]{top:.875em;width:1.375em}.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:.3125em}.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:.3125em}.swal2-toast div:where(.swal2-actions){justify-content:flex-start;height:auto;margin:0;margin-top:.5em;padding:0 .5em}.swal2-toast button:where(.swal2-styled){margin:.25em .5em;padding:.4em .6em;font-size:1em}.swal2-toast .swal2-success{border-color:#a5dc86}.swal2-toast .swal2-success [class^=swal2-success-circular-line]{position:absolute;width:1.6em;height:3em;border-radius:50%}.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left]{top:-0.8em;left:-0.5em;transform:rotate(-45deg);transform-origin:2em 2em;border-radius:4em 0 0 4em}.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right]{top:-0.25em;left:.9375em;transform-origin:0 1.5em;border-radius:0 4em 4em 0}.swal2-toast .swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-toast .swal2-success .swal2-success-fix{top:0;left:.4375em;width:.4375em;height:2.6875em}.swal2-toast .swal2-success [class^=swal2-success-line]{height:.3125em}.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip]{top:1.125em;left:.1875em;width:.75em}.swal2-toast .swal2-success [class^=swal2-success-line][class$=long]{top:.9375em;right:.1875em;width:1.375em}.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip{animation:swal2-toast-animate-success-line-tip .75s}.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long{animation:swal2-toast-animate-success-line-long .75s}.swal2-toast.swal2-show{animation:var(--swal2-toast-show-animation)}.swal2-toast.swal2-hide{animation:var(--swal2-toast-hide-animation)}@keyframes swal2-show{0%{transform:translate3d(0, -50px, 0) scale(0.9);opacity:0}100%{transform:translate3d(0, 0, 0) scale(1);opacity:1}}@keyframes swal2-hide{0%{transform:translate3d(0, 0, 0) scale(1);opacity:1}100%{transform:translate3d(0, -50px, 0) scale(0.9);opacity:0}}@keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-0.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.8125em;width:1.5625em}}@keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(0.4);opacity:0}50%{margin-top:1.625em;transform:scale(0.4);opacity:0}80%{margin-top:-0.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0deg);opacity:1}}@keyframes swal2-rotate-loading{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes swal2-animate-question-mark{0%{transform:rotateY(-360deg)}100%{transform:rotateY(0)}}@keyframes swal2-animate-i-mark{0%{transform:rotateZ(45deg);opacity:0}25%{transform:rotateZ(-25deg);opacity:.4}50%{transform:rotateZ(15deg);opacity:.8}75%{transform:rotateZ(-5deg);opacity:1}100%{transform:rotateX(0);opacity:1}}@keyframes swal2-toast-show{0%{transform:translateY(-0.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(0.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0deg)}}@keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-0.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}");
5296
5297 /***/ }
5298
5299 /******/ });
5300 /************************************************************************/
5301 /******/ // The module cache
5302 /******/ const __webpack_module_cache__ = {};
5303 /******/
5304 /******/ // The require function
5305 /******/ function __webpack_require__(moduleId) {
5306 /******/ // Check if module is in cache
5307 /******/ const cachedModule = __webpack_module_cache__[moduleId];
5308 /******/ if (cachedModule !== undefined) {
5309 /******/ return cachedModule.exports;
5310 /******/ }
5311 /******/ // Create a new module (and put it into the cache)
5312 /******/ const module = __webpack_module_cache__[moduleId] = {
5313 /******/ // no module.id needed
5314 /******/ // no module.loaded needed
5315 /******/ exports: {}
5316 /******/ };
5317 /******/
5318 /******/ // Execute the module function
5319 /******/ if (!(moduleId in __webpack_modules__)) {
5320 /******/ delete __webpack_module_cache__[moduleId];
5321 /******/ const e = new Error("Cannot find module '" + moduleId + "'");
5322 /******/ e.code = 'MODULE_NOT_FOUND';
5323 /******/ throw e;
5324 /******/ }
5325 /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
5326 /******/
5327 /******/ // Return the exports of the module
5328 /******/ return module.exports;
5329 /******/ }
5330 /******/
5331 /************************************************************************/
5332 /******/ /* webpack/runtime/compat get default export */
5333 /******/ (() => {
5334 /******/ // getDefaultExport function for compatibility with non-harmony modules
5335 /******/ __webpack_require__.n = (module) => {
5336 /******/ const getter = module && module.__esModule ?
5337 /******/ () => (module['default']) :
5338 /******/ () => (module);
5339 /******/ __webpack_require__.d(getter, { a: getter });
5340 /******/ return getter;
5341 /******/ };
5342 /******/ })();
5343 /******/
5344 /******/ /* webpack/runtime/define property getters */
5345 /******/ (() => {
5346 /******/ // define getter/value functions for harmony exports
5347 /******/ __webpack_require__.d = (exports, definition) => {
5348 /******/ if(Array.isArray(definition)) {
5349 /******/ var i = 0;
5350 /******/ while(i < definition.length) {
5351 /******/ var key = definition[i++];
5352 /******/ var binding = definition[i++];
5353 /******/ if(!__webpack_require__.o(exports, key)) {
5354 /******/ if(binding === 0) {
5355 /******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] });
5356 /******/ } else {
5357 /******/ Object.defineProperty(exports, key, { enumerable: true, get: binding });
5358 /******/ }
5359 /******/ } else if(binding === 0) { i++; }
5360 /******/ }
5361 /******/ } else {
5362 /******/ for(var key in definition) {
5363 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
5364 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
5365 /******/ }
5366 /******/ }
5367 /******/ }
5368 /******/ };
5369 /******/ })();
5370 /******/
5371 /******/ /* webpack/runtime/hasOwnProperty shorthand */
5372 /******/ (() => {
5373 /******/ __webpack_require__.o = (obj, prop) => (Object.hasOwn(obj, prop))
5374 /******/ })();
5375 /******/
5376 /******/ /* webpack/runtime/make namespace object */
5377 /******/ (() => {
5378 /******/ // define __esModule on exports
5379 /******/ __webpack_require__.r = (exports) => {
5380 /******/ if(Symbol.toStringTag) {
5381 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5382 /******/ }
5383 /******/ Object.defineProperty(exports, '__esModule', { value: true });
5384 /******/ };
5385 /******/ })();
5386 /******/
5387 /************************************************************************/
5388 let __webpack_exports__ = {};
5389 // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
5390 (() => {
5391 "use strict";
5392 /*!*****************************************!*\
5393 !*** ./assets/src/js/admin/webhooks.js ***!
5394 \*****************************************/
5395 __webpack_require__.r(__webpack_exports__);
5396 /* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sweetalert2 */ "./node_modules/sweetalert2/dist/sweetalert2.all.js");
5397 /* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sweetalert2__WEBPACK_IMPORTED_MODULE_0__);
5398 /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils.js */ "./assets/src/js/utils.js");
5399
5400
5401 (function () {
5402 'use strict';
5403
5404 const cfg = window.lpWebhooksSettings || {};
5405 if (!cfg.is_webhook_section) {
5406 return;
5407 }
5408 const ajaxHandle = window.lpAJAXG;
5409 if (!ajaxHandle || typeof ajaxHandle.fetchAJAX !== 'function') {
5410 return;
5411 }
5412 const actions = cfg.actions || {};
5413 const i18n = cfg.i18n || {};
5414 const elId = document.querySelector('#lp-webhook-id');
5415 const elName = document.querySelector('#lp-webhook-name');
5416 const elUrl = document.querySelector('#lp-webhook-delivery-url');
5417 const elSecret = document.querySelector('#lp-webhook-secret');
5418 const elWebhookStatus = document.querySelector('#lp-webhook-status');
5419 const elEvents = document.querySelector('#lp-webhook-events');
5420 const elSubmit = document.querySelector('#lp-webhook-submit');
5421 const elCancel = document.querySelector('#lp-webhook-cancel');
5422 const elRegenerate = document.querySelector('#lp-webhook-regenerate-editor');
5423 const elEditorTitle = document.querySelector('#lp-webhook-editor-title');
5424 const elEditorHolder = document.querySelector('#lp-webhook-editor-holder');
5425 const elEditor = document.querySelector('#lp-webhook-editor');
5426 const elEditorFields = document.querySelector('#lp-webhook-editor-fields');
5427 const elEditorActions = document.querySelector('#lp-webhook-editor-actions');
5428 const elStatusMessage = document.querySelector('#lp-webhook-status-message');
5429 const elSecretReveal = document.querySelector('#lp-webhook-secret-reveal');
5430 const elSecretValue = document.querySelector('#lp-webhook-secret-value');
5431 let isEditorDisabled = true;
5432 const getEventsTomSelect = () => {
5433 return elEvents?.tomselect || elEvents?.tomSelectInstance || null;
5434 };
5435 const initEventsTomSelect = () => {
5436 if (!elEvents || getEventsTomSelect()) {
5437 return;
5438 }
5439 if (typeof window.lpFindTomSelect === 'function') {
5440 window.lpFindTomSelect();
5441 }
5442 };
5443 const setStatus = (message = '', isError = false) => {
5444 if (!elStatusMessage) {
5445 return;
5446 }
5447 elStatusMessage.textContent = message;
5448 elStatusMessage.style.color = isError ? '#b32d2e' : '#1e1e1e';
5449 };
5450 const setLoading = isLoading => {
5451 if (!elSubmit) {
5452 return;
5453 }
5454 elSubmit.disabled = !!isLoading || isEditorDisabled;
5455 elSubmit.classList.toggle('loading', !!isLoading);
5456 };
5457 const setEditorDisabled = isDisabled => {
5458 isEditorDisabled = !!isDisabled;
5459 [elName, elUrl, elSecret, elWebhookStatus, elEvents, elSubmit, elCancel, elRegenerate].forEach(el => {
5460 if (!el) {
5461 return;
5462 }
5463 el.disabled = isEditorDisabled;
5464 });
5465 const eventsTomSelect = getEventsTomSelect();
5466 if (eventsTomSelect) {
5467 if (isEditorDisabled && typeof eventsTomSelect.disable === 'function') {
5468 eventsTomSelect.disable();
5469 } else if (typeof eventsTomSelect.enable === 'function') {
5470 eventsTomSelect.enable();
5471 }
5472 }
5473 if (elSubmit?.classList.contains('loading')) {
5474 elSubmit.disabled = true;
5475 }
5476 };
5477 const setSecretPlaceholder = (isEditing = false) => {
5478 if (!elSecret) {
5479 return;
5480 }
5481 elSecret.placeholder = isEditing ? i18n.secret_edit_placeholder || 'Leave blank to keep the current secret.' : i18n.secret_create_placeholder || 'Leave blank to auto-generate a secret.';
5482 };
5483 const setEditorFormVisible = (isVisible = true) => {
5484 if (elEditorFields) {
5485 elEditorFields.style.display = isVisible ? '' : 'none';
5486 }
5487 if (elEditorActions) {
5488 elEditorActions.style.display = '';
5489 }
5490 if (!isVisible) {
5491 [elSubmit, elCancel, elRegenerate].forEach(el => {
5492 if (el) {
5493 el.style.display = 'none';
5494 }
5495 });
5496 }
5497 };
5498 const hideSecret = () => {
5499 if (elSecretReveal) {
5500 elSecretReveal.style.display = 'none';
5501 }
5502 if (elSecretValue) {
5503 elSecretValue.value = '';
5504 }
5505 };
5506 const revealSecret = secret => {
5507 if (!secret || !elSecretReveal || !elSecretValue) {
5508 return;
5509 }
5510 elSecretValue.value = secret;
5511 elSecretReveal.style.display = 'block';
5512 };
5513 const openEditorPopup = () => {
5514 if (!elEditor || !elEditorHolder) {
5515 return;
5516 }
5517 sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().fire({
5518 html: '<div id="lp-webhook-editor-popup"></div>',
5519 width: 860,
5520 showConfirmButton: false,
5521 showCloseButton: true,
5522 showCancelButton: false,
5523 focusConfirm: false,
5524 customClass: {
5525 popup: 'lp-webhook-editor-popup'
5526 },
5527 didOpen: () => {
5528 const popup = typeof (sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().getPopup) === 'function' ? sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().getPopup() : null;
5529 const mount = popup?.querySelector('#lp-webhook-editor-popup');
5530 if (!mount) {
5531 return;
5532 }
5533 elEditor.style.display = 'block';
5534 mount.appendChild(elEditor);
5535 initEventsTomSelect();
5536 setEditorDisabled(false);
5537 elName?.focus();
5538 },
5539 willClose: () => {
5540 setEditorDisabled(true);
5541 elEditor.style.display = 'none';
5542 elEditorHolder.appendChild(elEditor);
5543 }
5544 });
5545 };
5546 const closeEditorPopup = () => {
5547 if (typeof (sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().close) === 'function') {
5548 sweetalert2__WEBPACK_IMPORTED_MODULE_0___default().close();
5549 }
5550 };
5551 const setSelectedEvents = (eventKeys = []) => {
5552 if (!elEvents) {
5553 return;
5554 }
5555 const eventsTomSelect = getEventsTomSelect();
5556 if (eventsTomSelect) {
5557 eventsTomSelect.setValue(eventKeys, true);
5558 return;
5559 }
5560 elEvents.querySelectorAll('option').forEach(option => {
5561 option.selected = eventKeys.includes(option.value);
5562 });
5563 };
5564 const getSelectedEvents = () => {
5565 if (!elEvents) {
5566 return [];
5567 }
5568 const eventsTomSelect = getEventsTomSelect();
5569 if (eventsTomSelect) {
5570 const value = eventsTomSelect.getValue();
5571 return Array.isArray(value) ? value : [value].filter(Boolean);
5572 }
5573 return Array.from(elEvents.querySelectorAll('option:checked')).map(option => option.value);
5574 };
5575 const resetEditor = () => {
5576 if (elId) {
5577 elId.value = '0';
5578 }
5579 if (elName) {
5580 elName.value = '';
5581 }
5582 if (elUrl) {
5583 elUrl.value = '';
5584 }
5585 if (elSecret) {
5586 elSecret.value = '';
5587 }
5588 setSecretPlaceholder();
5589 if (elWebhookStatus) {
5590 elWebhookStatus.value = 'active';
5591 }
5592 if (elEditorTitle) {
5593 elEditorTitle.textContent = i18n.create_title || 'Create Webhook';
5594 }
5595 if (elSubmit) {
5596 elSubmit.textContent = i18n.create_button || 'Create Webhook';
5597 elSubmit.style.display = '';
5598 }
5599 if (elCancel) {
5600 elCancel.style.display = 'none';
5601 }
5602 if (elRegenerate) {
5603 elRegenerate.style.display = 'none';
5604 }
5605 setEditorFormVisible();
5606 setSelectedEvents();
5607 hideSecret();
5608 setStatus();
5609 };
5610 const populateEditor = webhook => {
5611 if (!webhook) {
5612 return;
5613 }
5614 if (elId) {
5615 elId.value = webhook.webhook_id || 0;
5616 }
5617 if (elName) {
5618 elName.value = webhook.name || '';
5619 }
5620 if (elUrl) {
5621 elUrl.value = webhook.delivery_url || '';
5622 }
5623 if (elSecret) {
5624 elSecret.value = '';
5625 }
5626 setSecretPlaceholder(true);
5627 if (elWebhookStatus) {
5628 elWebhookStatus.value = webhook.status || 'active';
5629 }
5630 if (elEditorTitle) {
5631 elEditorTitle.textContent = i18n.edit_title || 'Edit Webhook';
5632 }
5633 if (elSubmit) {
5634 elSubmit.textContent = i18n.update_button || 'Update Webhook';
5635 elSubmit.style.display = '';
5636 }
5637 if (elCancel) {
5638 elCancel.style.display = '';
5639 }
5640 if (elRegenerate) {
5641 elRegenerate.style.display = '';
5642 }
5643 setEditorFormVisible();
5644 setSelectedEvents(Array.isArray(webhook.events) ? webhook.events : []);
5645 hideSecret();
5646 setStatus();
5647 openEditorPopup();
5648 };
5649 const runRequest = (dataSend, callbacks = {}) => {
5650 ajaxHandle.fetchAJAX(dataSend, {
5651 success: response => {
5652 if (typeof callbacks.success === 'function') {
5653 callbacks.success(response);
5654 }
5655 },
5656 error: error => {
5657 if (typeof callbacks.error === 'function') {
5658 callbacks.error(error);
5659 }
5660 },
5661 completed: () => {
5662 if (typeof callbacks.completed === 'function') {
5663 callbacks.completed();
5664 }
5665 }
5666 });
5667 };
5668 const refreshList = async () => {
5669 const currentList = document.querySelector('.lp-webhook-list');
5670 if (!currentList) {
5671 return;
5672 }
5673 try {
5674 const response = await fetch(window.location.href, {
5675 method: 'GET',
5676 credentials: 'same-origin',
5677 cache: 'no-store'
5678 });
5679 if (!response.ok) {
5680 return;
5681 }
5682 const html = await response.text();
5683 const doc = new DOMParser().parseFromString(html, 'text/html');
5684 const newList = doc.querySelector('.lp-webhook-list');
5685 if (newList) {
5686 currentList.replaceWith(newList);
5687 }
5688 } catch {
5689 // Keep the current table when refresh fails.
5690 }
5691 };
5692 const onSubmit = () => {
5693 if (!elSubmit || !elName || !elUrl) {
5694 return;
5695 }
5696 if (!elName.reportValidity() || !elUrl.reportValidity()) {
5697 return;
5698 }
5699 const webhookId = elId ? parseInt(elId.value, 10) || 0 : 0;
5700 const isUpdate = webhookId > 0;
5701 const dataSend = {
5702 action: isUpdate ? actions.update || 'update_webhook' : actions.create || 'create_webhook',
5703 webhook_id: webhookId,
5704 name: elName.value,
5705 delivery_url: elUrl.value,
5706 secret: elSecret ? elSecret.value : '',
5707 status: elWebhookStatus ? elWebhookStatus.value : 'active',
5708 events: getSelectedEvents()
5709 };
5710 setLoading(true);
5711 setStatus(i18n.processing || 'Processing...');
5712 runRequest(dataSend, {
5713 success: response => {
5714 const message = response?.message || i18n.request_failed || 'Request failed.';
5715 if (response?.status !== 'success') {
5716 setStatus(message, true);
5717 return;
5718 }
5719 refreshList();
5720 if (isUpdate) {
5721 closeEditorPopup();
5722 resetEditor();
5723 return;
5724 }
5725 const createdSecret = response?.data?.webhook?.secret || '';
5726 resetEditor();
5727 if (elEditorTitle) {
5728 elEditorTitle.textContent = i18n.created_title || 'Webhook Created';
5729 }
5730 setEditorFormVisible(false);
5731 revealSecret(createdSecret);
5732 setStatus(message);
5733 setEditorDisabled(true);
5734 },
5735 error: () => setStatus(i18n.request_failed || 'Request failed.', true),
5736 completed: () => setLoading(false)
5737 });
5738 };
5739 const onDelete = webhookId => {
5740 if (!webhookId || !window.confirm(i18n.confirm_delete || 'Delete this webhook?')) {
5741 return;
5742 }
5743 setStatus(i18n.processing || 'Processing...');
5744 runRequest({
5745 action: actions.delete || 'delete_webhook',
5746 webhook_id: webhookId
5747 }, {
5748 success: response => {
5749 const message = response?.message || i18n.request_failed || 'Request failed.';
5750 setStatus(message, response?.status !== 'success');
5751 if (response?.status === 'success') {
5752 if (elId && parseInt(elId.value, 10) === webhookId) {
5753 resetEditor();
5754 }
5755 refreshList();
5756 }
5757 },
5758 error: () => setStatus(i18n.request_failed || 'Request failed.', true)
5759 });
5760 };
5761 const onRegenerate = webhookId => {
5762 if (!webhookId || !window.confirm(i18n.confirm_regenerate || 'Regenerate this webhook secret?')) {
5763 return;
5764 }
5765 setStatus(i18n.processing || 'Processing...');
5766 runRequest({
5767 action: actions.regenerate || 'regenerate_webhook_secret',
5768 webhook_id: webhookId
5769 }, {
5770 success: response => {
5771 const message = response?.message || i18n.request_failed || 'Request failed.';
5772 setStatus(message, response?.status !== 'success');
5773 if (response?.status === 'success') {
5774 revealSecret(response?.data?.secret || '');
5775 refreshList();
5776 }
5777 },
5778 error: () => setStatus(i18n.request_failed || 'Request failed.', true)
5779 });
5780 };
5781 const onCopySecret = async () => {
5782 if (!elSecretValue) {
5783 return;
5784 }
5785 try {
5786 if (navigator.clipboard?.writeText) {
5787 await navigator.clipboard.writeText(elSecretValue.value);
5788 } else {
5789 elSecretValue.select();
5790 document.execCommand('copy');
5791 }
5792 setStatus(i18n.copy_success || 'Copied.');
5793 } catch {
5794 setStatus(i18n.copy_fallback || 'Copy this value manually.');
5795 }
5796 };
5797 _utils_js__WEBPACK_IMPORTED_MODULE_1__.eventHandlers('click', [{
5798 selector: '#lp-webhook-open-create',
5799 callBack: args => {
5800 const {
5801 e
5802 } = args;
5803 e.preventDefault();
5804 resetEditor();
5805 openEditorPopup();
5806 }
5807 }, {
5808 selector: '.lp-webhook-edit',
5809 callBack: args => {
5810 const {
5811 e,
5812 target
5813 } = args;
5814 e.preventDefault();
5815 const edit = target.closest('.lp-webhook-edit');
5816 try {
5817 populateEditor(JSON.parse(edit.dataset.webhook || '{}'));
5818 } catch {
5819 setStatus(i18n.request_failed || 'Request failed.', true);
5820 }
5821 }
5822 }, {
5823 selector: '.lp-webhook-delete',
5824 callBack: args => {
5825 const {
5826 e,
5827 target
5828 } = args;
5829 e.preventDefault();
5830 const deleteLink = target.closest('.lp-webhook-delete');
5831 onDelete(parseInt(deleteLink.dataset.webhookId, 10) || 0);
5832 }
5833 }, {
5834 selector: '.lp-webhook-regenerate',
5835 callBack: args => {
5836 const {
5837 e,
5838 target
5839 } = args;
5840 e.preventDefault();
5841 const regenerateLink = target.closest('.lp-webhook-regenerate');
5842 onRegenerate(parseInt(regenerateLink.dataset.webhookId, 10) || 0);
5843 }
5844 }, {
5845 selector: '#lp-webhook-submit',
5846 callBack: () => {
5847 onSubmit();
5848 }
5849 }, {
5850 selector: '#lp-webhook-cancel',
5851 callBack: () => {
5852 resetEditor();
5853 closeEditorPopup();
5854 }
5855 }, {
5856 selector: '#lp-webhook-regenerate-editor',
5857 callBack: () => {
5858 onRegenerate(elId ? parseInt(elId.value, 10) || 0 : 0);
5859 }
5860 }, {
5861 selector: '#lp-webhook-copy-secret',
5862 callBack: () => {
5863 onCopySecret();
5864 }
5865 }]);
5866 setSecretPlaceholder();
5867 setEditorDisabled(true);
5868 })();
5869 })();
5870
5871 /******/ })()
5872 ;
5873 //# sourceMappingURL=webhooks.js.map