LaravelTest
3391 строка · 105.6 Кб
1/*!
2* sweetalert2 v11.4.0
3* Released under the MIT License.
4*/
5(function (global, factory) {6typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :7typeof define === 'function' && define.amd ? define(factory) :8(global = global || self, global.Sweetalert2 = factory());9}(this, function () { 'use strict';10
11const consolePrefix = 'SweetAlert2:';12/**13* Filter the unique values into a new array
14* @param arr
15*/
16
17const uniqueArray = arr => {18const result = [];19
20for (let i = 0; i < arr.length; i++) {21if (result.indexOf(arr[i]) === -1) {22result.push(arr[i]);23}24}25
26return result;27};28/**29* Capitalize the first letter of a string
30* @param {string} str
31* @returns {string}
32*/
33
34const capitalizeFirstLetter = str => str.charAt(0).toUpperCase() + str.slice(1);35/**36* @param {NodeList | HTMLCollection | NamedNodeMap} nodeList
37* @returns {array}
38*/
39
40const toArray = nodeList => Array.prototype.slice.call(nodeList);41/**42* Standardize console warnings
43* @param {string | array} message
44*/
45
46const warn = message => {47console.warn("".concat(consolePrefix, " ").concat(typeof message === 'object' ? message.join(' ') : message));48};49/**50* Standardize console errors
51* @param {string} message
52*/
53
54const error = message => {55console.error("".concat(consolePrefix, " ").concat(message));56};57/**58* Private global state for `warnOnce`
59* @type {Array}
60* @private
61*/
62
63const previousWarnOnceMessages = [];64/**65* Show a console warning, but only if it hasn't already been shown
66* @param {string} message
67*/
68
69const warnOnce = message => {70if (!previousWarnOnceMessages.includes(message)) {71previousWarnOnceMessages.push(message);72warn(message);73}74};75/**76* Show a one-time console warning about deprecated params/methods
77*/
78
79const warnAboutDeprecation = (deprecatedParam, useInstead) => {80warnOnce("\"".concat(deprecatedParam, "\" is deprecated and will be removed in the next major release. Please use \"").concat(useInstead, "\" instead."));81};82/**83* If `arg` is a function, call it (with no arguments or context) and return the result.
84* Otherwise, just pass the value through
85* @param arg
86*/
87
88const callIfFunction = arg => typeof arg === 'function' ? arg() : arg;89const hasToPromiseFn = arg => arg && typeof arg.toPromise === 'function';90const asPromise = arg => hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg);91const isPromise = arg => arg && Promise.resolve(arg) === arg;92
93const defaultParams = {94title: '',95titleText: '',96text: '',97html: '',98footer: '',99icon: undefined,100iconColor: undefined,101iconHtml: undefined,102template: undefined,103toast: false,104showClass: {105popup: 'swal2-show',106backdrop: 'swal2-backdrop-show',107icon: 'swal2-icon-show'108},109hideClass: {110popup: 'swal2-hide',111backdrop: 'swal2-backdrop-hide',112icon: 'swal2-icon-hide'113},114customClass: {},115target: 'body',116color: undefined,117backdrop: true,118heightAuto: true,119allowOutsideClick: true,120allowEscapeKey: true,121allowEnterKey: true,122stopKeydownPropagation: true,123keydownListenerCapture: false,124showConfirmButton: true,125showDenyButton: false,126showCancelButton: false,127preConfirm: undefined,128preDeny: undefined,129confirmButtonText: 'OK',130confirmButtonAriaLabel: '',131confirmButtonColor: undefined,132denyButtonText: 'No',133denyButtonAriaLabel: '',134denyButtonColor: undefined,135cancelButtonText: 'Cancel',136cancelButtonAriaLabel: '',137cancelButtonColor: undefined,138buttonsStyling: true,139reverseButtons: false,140focusConfirm: true,141focusDeny: false,142focusCancel: false,143returnFocus: true,144showCloseButton: false,145closeButtonHtml: '×',146closeButtonAriaLabel: 'Close this dialog',147loaderHtml: '',148showLoaderOnConfirm: false,149showLoaderOnDeny: false,150imageUrl: undefined,151imageWidth: undefined,152imageHeight: undefined,153imageAlt: '',154timer: undefined,155timerProgressBar: false,156width: undefined,157padding: undefined,158background: undefined,159input: undefined,160inputPlaceholder: '',161inputLabel: '',162inputValue: '',163inputOptions: {},164inputAutoTrim: true,165inputAttributes: {},166inputValidator: undefined,167returnInputValueOnDeny: false,168validationMessage: undefined,169grow: false,170position: 'center',171progressSteps: [],172currentProgressStep: undefined,173progressStepsDistance: undefined,174willOpen: undefined,175didOpen: undefined,176didRender: undefined,177willClose: undefined,178didClose: undefined,179didDestroy: undefined,180scrollbarPadding: true181};182const updatableParams = ['allowEscapeKey', 'allowOutsideClick', 'background', 'buttonsStyling', 'cancelButtonAriaLabel', 'cancelButtonColor', 'cancelButtonText', 'closeButtonAriaLabel', 'closeButtonHtml', 'color', 'confirmButtonAriaLabel', 'confirmButtonColor', 'confirmButtonText', 'currentProgressStep', 'customClass', 'denyButtonAriaLabel', 'denyButtonColor', 'denyButtonText', 'didClose', 'didDestroy', 'footer', 'hideClass', 'html', 'icon', 'iconColor', 'iconHtml', 'imageAlt', 'imageHeight', 'imageUrl', 'imageWidth', 'preConfirm', 'preDeny', 'progressSteps', 'returnFocus', 'reverseButtons', 'showCancelButton', 'showCloseButton', 'showConfirmButton', 'showDenyButton', 'text', 'title', 'titleText', 'willClose'];183const deprecatedParams = {};184const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];185/**186* Is valid parameter
187* @param {string} paramName
188*/
189
190const isValidParameter = paramName => {191return Object.prototype.hasOwnProperty.call(defaultParams, paramName);192};193/**194* Is valid parameter for Swal.update() method
195* @param {string} paramName
196*/
197
198const isUpdatableParameter = paramName => {199return updatableParams.indexOf(paramName) !== -1;200};201/**202* Is deprecated parameter
203* @param {string} paramName
204*/
205
206const isDeprecatedParameter = paramName => {207return deprecatedParams[paramName];208};209
210const checkIfParamIsValid = param => {211if (!isValidParameter(param)) {212warn("Unknown parameter \"".concat(param, "\""));213}214};215
216const checkIfToastParamIsValid = param => {217if (toastIncompatibleParams.includes(param)) {218warn("The parameter \"".concat(param, "\" is incompatible with toasts"));219}220};221
222const checkIfParamIsDeprecated = param => {223if (isDeprecatedParameter(param)) {224warnAboutDeprecation(param, isDeprecatedParameter(param));225}226};227/**228* Show relevant warnings for given params
229*
230* @param params
231*/
232
233
234const showWarningsForParams = params => {235if (!params.backdrop && params.allowOutsideClick) {236warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');237}238
239for (const param in params) {240checkIfParamIsValid(param);241
242if (params.toast) {243checkIfToastParamIsValid(param);244}245
246checkIfParamIsDeprecated(param);247}248};249
250const swalPrefix = 'swal2-';251const prefix = items => {252const result = {};253
254for (const i in items) {255result[items[i]] = swalPrefix + items[i];256}257
258return result;259};260const swalClasses = prefix(['container', 'shown', 'height-auto', 'iosfix', 'popup', 'modal', 'no-backdrop', 'no-transition', 'toast', 'toast-shown', 'show', 'hide', 'close', 'title', 'html-container', 'actions', 'confirm', 'deny', 'cancel', 'default-outline', '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']);261const iconTypes = prefix(['success', 'warning', 'info', 'question', 'error']);262
263/**264* Gets the popup container which contains the backdrop and the popup itself.
265*
266* @returns {HTMLElement | null}
267*/
268
269const getContainer = () => document.body.querySelector(".".concat(swalClasses.container));270const elementBySelector = selectorString => {271const container = getContainer();272return container ? container.querySelector(selectorString) : null;273};274
275const elementByClass = className => {276return elementBySelector(".".concat(className));277};278
279const getPopup = () => elementByClass(swalClasses.popup);280const getIcon = () => elementByClass(swalClasses.icon);281const getTitle = () => elementByClass(swalClasses.title);282const getHtmlContainer = () => elementByClass(swalClasses['html-container']);283const getImage = () => elementByClass(swalClasses.image);284const getProgressSteps = () => elementByClass(swalClasses['progress-steps']);285const getValidationMessage = () => elementByClass(swalClasses['validation-message']);286const getConfirmButton = () => elementBySelector(".".concat(swalClasses.actions, " .").concat(swalClasses.confirm));287const getDenyButton = () => elementBySelector(".".concat(swalClasses.actions, " .").concat(swalClasses.deny));288const getInputLabel = () => elementByClass(swalClasses['input-label']);289const getLoader = () => elementBySelector(".".concat(swalClasses.loader));290const getCancelButton = () => elementBySelector(".".concat(swalClasses.actions, " .").concat(swalClasses.cancel));291const getActions = () => elementByClass(swalClasses.actions);292const getFooter = () => elementByClass(swalClasses.footer);293const getTimerProgressBar = () => elementByClass(swalClasses['timer-progress-bar']);294const getCloseButton = () => elementByClass(swalClasses.close); // https://github.com/jkup/focusable/blob/master/index.js295
296const focusable = "\n a[href],\n area[href],\n input:not([disabled]),\n select:not([disabled]),\n textarea:not([disabled]),\n button:not([disabled]),\n iframe,\n object,\n embed,\n [tabindex=\"0\"],\n [contenteditable],\n audio[controls],\n video[controls],\n summary\n";297const getFocusableElements = () => {298const focusableElementsWithTabindex = toArray(getPopup().querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')) // sort according to tabindex299.sort((a, b) => {300const tabindexA = parseInt(a.getAttribute('tabindex'));301const tabindexB = parseInt(b.getAttribute('tabindex'));302
303if (tabindexA > tabindexB) {304return 1;305} else if (tabindexA < tabindexB) {306return -1;307}308
309return 0;310});311const otherFocusableElements = toArray(getPopup().querySelectorAll(focusable)).filter(el => el.getAttribute('tabindex') !== '-1');312return uniqueArray(focusableElementsWithTabindex.concat(otherFocusableElements)).filter(el => isVisible(el));313};314const isModal = () => {315return !hasClass(document.body, swalClasses['toast-shown']) && !hasClass(document.body, swalClasses['no-backdrop']);316};317const isToast = () => {318return getPopup() && hasClass(getPopup(), swalClasses.toast);319};320const isLoading = () => {321return getPopup().hasAttribute('data-loading');322};323
324const states = {325previousBodyPadding: null326};327/**328* Securely set innerHTML of an element
329* https://github.com/sweetalert2/sweetalert2/issues/1926
330*
331* @param {HTMLElement} elem
332* @param {string} html
333*/
334
335const setInnerHtml = (elem, html) => {336elem.textContent = '';337
338if (html) {339const parser = new DOMParser();340const parsed = parser.parseFromString(html, "text/html");341toArray(parsed.querySelector('head').childNodes).forEach(child => {342elem.appendChild(child);343});344toArray(parsed.querySelector('body').childNodes).forEach(child => {345elem.appendChild(child);346});347}348};349/**350* @param {HTMLElement} elem
351* @param {string} className
352* @returns {boolean}
353*/
354
355const hasClass = (elem, className) => {356if (!className) {357return false;358}359
360const classList = className.split(/\s+/);361
362for (let i = 0; i < classList.length; i++) {363if (!elem.classList.contains(classList[i])) {364return false;365}366}367
368return true;369};370
371const removeCustomClasses = (elem, params) => {372toArray(elem.classList).forEach(className => {373if (!Object.values(swalClasses).includes(className) && !Object.values(iconTypes).includes(className) && !Object.values(params.showClass).includes(className)) {374elem.classList.remove(className);375}376});377};378
379const applyCustomClass = (elem, params, className) => {380removeCustomClasses(elem, params);381
382if (params.customClass && params.customClass[className]) {383if (typeof params.customClass[className] !== 'string' && !params.customClass[className].forEach) {384return warn("Invalid type of customClass.".concat(className, "! Expected string or iterable object, got \"").concat(typeof params.customClass[className], "\""));385}386
387addClass(elem, params.customClass[className]);388}389};390/**391* @param {HTMLElement} popup
392* @param {string} inputType
393* @returns {HTMLInputElement | null}
394*/
395
396const getInput = (popup, inputType) => {397if (!inputType) {398return null;399}400
401switch (inputType) {402case 'select':403case 'textarea':404case 'file':405return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses[inputType]));406
407case 'checkbox':408return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.checkbox, " input"));409
410case 'radio':411return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.radio, " input:checked")) || popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.radio, " input:first-child"));412
413case 'range':414return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.range, " input"));415
416default:417return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.input));418}419};420/**421* @param {HTMLInputElement} input
422*/
423
424const focusInput = input => {425input.focus(); // place cursor at end of text in text input426
427if (input.type !== 'file') {428// http://stackoverflow.com/a/2345915429const val = input.value;430input.value = '';431input.value = val;432}433};434/**435* @param {HTMLElement | HTMLElement[] | null} target
436* @param {string | string[]} classList
437* @param {boolean} condition
438*/
439
440const toggleClass = (target, classList, condition) => {441if (!target || !classList) {442return;443}444
445if (typeof classList === 'string') {446classList = classList.split(/\s+/).filter(Boolean);447}448
449classList.forEach(className => {450if (Array.isArray(target)) {451target.forEach(elem => {452condition ? elem.classList.add(className) : elem.classList.remove(className);453});454} else {455condition ? target.classList.add(className) : target.classList.remove(className);456}457});458};459/**460* @param {HTMLElement | HTMLElement[] | null} target
461* @param {string | string[]} classList
462*/
463
464const addClass = (target, classList) => {465toggleClass(target, classList, true);466};467/**468* @param {HTMLElement | HTMLElement[] | null} target
469* @param {string | string[]} classList
470*/
471
472const removeClass = (target, classList) => {473toggleClass(target, classList, false);474};475/**476* Get direct child of an element by class name
477*
478* @param {HTMLElement} elem
479* @param {string} className
480* @returns {HTMLElement | null}
481*/
482
483const getDirectChildByClass = (elem, className) => {484const childNodes = toArray(elem.childNodes);485
486for (let i = 0; i < childNodes.length; i++) {487if (hasClass(childNodes[i], className)) {488return childNodes[i];489}490}491};492/**493* @param {HTMLElement} elem
494* @param {string} property
495* @param {*} value
496*/
497
498const applyNumericalStyle = (elem, property, value) => {499if (value === "".concat(parseInt(value))) {500value = parseInt(value);501}502
503if (value || parseInt(value) === 0) {504elem.style[property] = typeof value === 'number' ? "".concat(value, "px") : value;505} else {506elem.style.removeProperty(property);507}508};509/**510* @param {HTMLElement} elem
511* @param {string} display
512*/
513
514const show = function (elem) {515let display = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'flex';516elem.style.display = display;517};518/**519* @param {HTMLElement} elem
520*/
521
522const hide = elem => {523elem.style.display = 'none';524};525const setStyle = (parent, selector, property, value) => {526const el = parent.querySelector(selector);527
528if (el) {529el.style[property] = value;530}531};532const toggle = (elem, condition, display) => {533condition ? show(elem, display) : hide(elem);534}; // borrowed from jquery $(elem).is(':visible') implementation535
536const isVisible = elem => !!(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length));537const allButtonsAreHidden = () => !isVisible(getConfirmButton()) && !isVisible(getDenyButton()) && !isVisible(getCancelButton());538const isScrollable = elem => !!(elem.scrollHeight > elem.clientHeight); // borrowed from https://stackoverflow.com/a/46352119539
540const hasCssAnimation = elem => {541const style = window.getComputedStyle(elem);542const animDuration = parseFloat(style.getPropertyValue('animation-duration') || '0');543const transDuration = parseFloat(style.getPropertyValue('transition-duration') || '0');544return animDuration > 0 || transDuration > 0;545};546const animateTimerProgressBar = function (timer) {547let reset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;548const timerProgressBar = getTimerProgressBar();549
550if (isVisible(timerProgressBar)) {551if (reset) {552timerProgressBar.style.transition = 'none';553timerProgressBar.style.width = '100%';554}555
556setTimeout(() => {557timerProgressBar.style.transition = "width ".concat(timer / 1000, "s linear");558timerProgressBar.style.width = '0%';559}, 10);560}561};562const stopTimerProgressBar = () => {563const timerProgressBar = getTimerProgressBar();564const timerProgressBarWidth = parseInt(window.getComputedStyle(timerProgressBar).width);565timerProgressBar.style.removeProperty('transition');566timerProgressBar.style.width = '100%';567const timerProgressBarFullWidth = parseInt(window.getComputedStyle(timerProgressBar).width);568const timerProgressBarPercent = timerProgressBarWidth / timerProgressBarFullWidth * 100;569timerProgressBar.style.removeProperty('transition');570timerProgressBar.style.width = "".concat(timerProgressBarPercent, "%");571};572
573/**574* Detect Node env
575*
576* @returns {boolean}
577*/
578const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined';579
580const RESTORE_FOCUS_TIMEOUT = 100;581
582const globalState = {};583
584const focusPreviousActiveElement = () => {585if (globalState.previousActiveElement && globalState.previousActiveElement.focus) {586globalState.previousActiveElement.focus();587globalState.previousActiveElement = null;588} else if (document.body) {589document.body.focus();590}591}; // Restore previous active (focused) element592
593
594const restoreActiveElement = returnFocus => {595return new Promise(resolve => {596if (!returnFocus) {597return resolve();598}599
600const x = window.scrollX;601const y = window.scrollY;602globalState.restoreFocusTimeout = setTimeout(() => {603focusPreviousActiveElement();604resolve();605}, RESTORE_FOCUS_TIMEOUT); // issues/900606
607window.scrollTo(x, y);608});609};610
611const sweetHTML = "\n <div aria-labelledby=\"".concat(swalClasses.title, "\" aria-describedby=\"").concat(swalClasses['html-container'], "\" class=\"").concat(swalClasses.popup, "\" tabindex=\"-1\">\n <button type=\"button\" class=\"").concat(swalClasses.close, "\"></button>\n <ul class=\"").concat(swalClasses['progress-steps'], "\"></ul>\n <div class=\"").concat(swalClasses.icon, "\"></div>\n <img class=\"").concat(swalClasses.image, "\" />\n <h2 class=\"").concat(swalClasses.title, "\" id=\"").concat(swalClasses.title, "\"></h2>\n <div class=\"").concat(swalClasses['html-container'], "\" id=\"").concat(swalClasses['html-container'], "\"></div>\n <input class=\"").concat(swalClasses.input, "\" />\n <input type=\"file\" class=\"").concat(swalClasses.file, "\" />\n <div class=\"").concat(swalClasses.range, "\">\n <input type=\"range\" />\n <output></output>\n </div>\n <select class=\"").concat(swalClasses.select, "\"></select>\n <div class=\"").concat(swalClasses.radio, "\"></div>\n <label for=\"").concat(swalClasses.checkbox, "\" class=\"").concat(swalClasses.checkbox, "\">\n <input type=\"checkbox\" />\n <span class=\"").concat(swalClasses.label, "\"></span>\n </label>\n <textarea class=\"").concat(swalClasses.textarea, "\"></textarea>\n <div class=\"").concat(swalClasses['validation-message'], "\" id=\"").concat(swalClasses['validation-message'], "\"></div>\n <div class=\"").concat(swalClasses.actions, "\">\n <div class=\"").concat(swalClasses.loader, "\"></div>\n <button type=\"button\" class=\"").concat(swalClasses.confirm, "\"></button>\n <button type=\"button\" class=\"").concat(swalClasses.deny, "\"></button>\n <button type=\"button\" class=\"").concat(swalClasses.cancel, "\"></button>\n </div>\n <div class=\"").concat(swalClasses.footer, "\"></div>\n <div class=\"").concat(swalClasses['timer-progress-bar-container'], "\">\n <div class=\"").concat(swalClasses['timer-progress-bar'], "\"></div>\n </div>\n </div>\n").replace(/(^|\n)\s*/g, '');612
613const resetOldContainer = () => {614const oldContainer = getContainer();615
616if (!oldContainer) {617return false;618}619
620oldContainer.remove();621removeClass([document.documentElement, document.body], [swalClasses['no-backdrop'], swalClasses['toast-shown'], swalClasses['has-column']]);622return true;623};624
625const resetValidationMessage = () => {626globalState.currentInstance.resetValidationMessage();627};628
629const addInputChangeListeners = () => {630const popup = getPopup();631const input = getDirectChildByClass(popup, swalClasses.input);632const file = getDirectChildByClass(popup, swalClasses.file);633const range = popup.querySelector(".".concat(swalClasses.range, " input"));634const rangeOutput = popup.querySelector(".".concat(swalClasses.range, " output"));635const select = getDirectChildByClass(popup, swalClasses.select);636const checkbox = popup.querySelector(".".concat(swalClasses.checkbox, " input"));637const textarea = getDirectChildByClass(popup, swalClasses.textarea);638input.oninput = resetValidationMessage;639file.onchange = resetValidationMessage;640select.onchange = resetValidationMessage;641checkbox.onchange = resetValidationMessage;642textarea.oninput = resetValidationMessage;643
644range.oninput = () => {645resetValidationMessage();646rangeOutput.value = range.value;647};648
649range.onchange = () => {650resetValidationMessage();651range.nextSibling.value = range.value;652};653};654
655const getTarget = target => typeof target === 'string' ? document.querySelector(target) : target;656
657const setupAccessibility = params => {658const popup = getPopup();659popup.setAttribute('role', params.toast ? 'alert' : 'dialog');660popup.setAttribute('aria-live', params.toast ? 'polite' : 'assertive');661
662if (!params.toast) {663popup.setAttribute('aria-modal', 'true');664}665};666
667const setupRTL = targetElement => {668if (window.getComputedStyle(targetElement).direction === 'rtl') {669addClass(getContainer(), swalClasses.rtl);670}671};672/*673* Add modal + backdrop to DOM
674*/
675
676
677const init = params => {678// Clean up the old popup container if it exists679const oldContainerExisted = resetOldContainer();680/* istanbul ignore if */681
682if (isNodeEnv()) {683error('SweetAlert2 requires document to initialize');684return;685}686
687const container = document.createElement('div');688container.className = swalClasses.container;689
690if (oldContainerExisted) {691addClass(container, swalClasses['no-transition']);692}693
694setInnerHtml(container, sweetHTML);695const targetElement = getTarget(params.target);696targetElement.appendChild(container);697setupAccessibility(params);698setupRTL(targetElement);699addInputChangeListeners();700};701
702/**703* @param {HTMLElement | object | string} param
704* @param {HTMLElement} target
705*/
706
707const parseHtmlToContainer = (param, target) => {708// DOM element709if (param instanceof HTMLElement) {710target.appendChild(param);711} // Object712else if (typeof param === 'object') {713handleObject(param, target);714} // Plain string715else if (param) {716setInnerHtml(target, param);717}718};719/**720* @param {object} param
721* @param {HTMLElement} target
722*/
723
724const handleObject = (param, target) => {725// JQuery element(s)726if (param.jquery) {727handleJqueryElem(target, param);728} // For other objects use their string representation729else {730setInnerHtml(target, param.toString());731}732};733
734const handleJqueryElem = (target, elem) => {735target.textContent = '';736
737if (0 in elem) {738for (let i = 0; (i in elem); i++) {739target.appendChild(elem[i].cloneNode(true));740}741} else {742target.appendChild(elem.cloneNode(true));743}744};745
746const animationEndEvent = (() => {747// Prevent run in Node env748
749/* istanbul ignore if */750if (isNodeEnv()) {751return false;752}753
754const testEl = document.createElement('div');755const transEndEventNames = {756WebkitAnimation: 'webkitAnimationEnd',757// Chrome, Safari and Opera758animation: 'animationend' // Standard syntax759
760};761
762for (const i in transEndEventNames) {763if (Object.prototype.hasOwnProperty.call(transEndEventNames, i) && typeof testEl.style[i] !== 'undefined') {764return transEndEventNames[i];765}766}767
768return false;769})();770
771// https://github.com/twbs/bootstrap/blob/master/js/src/modal.js772
773const measureScrollbar = () => {774const scrollDiv = document.createElement('div');775scrollDiv.className = swalClasses['scrollbar-measure'];776document.body.appendChild(scrollDiv);777const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;778document.body.removeChild(scrollDiv);779return scrollbarWidth;780};781
782const renderActions = (instance, params) => {783const actions = getActions();784const loader = getLoader(); // Actions (buttons) wrapper785
786if (!params.showConfirmButton && !params.showDenyButton && !params.showCancelButton) {787hide(actions);788} else {789show(actions);790} // Custom class791
792
793applyCustomClass(actions, params, 'actions'); // Render all the buttons794
795renderButtons(actions, loader, params); // Loader796
797setInnerHtml(loader, params.loaderHtml);798applyCustomClass(loader, params, 'loader');799};800
801function renderButtons(actions, loader, params) {802const confirmButton = getConfirmButton();803const denyButton = getDenyButton();804const cancelButton = getCancelButton(); // Render buttons805
806renderButton(confirmButton, 'confirm', params);807renderButton(denyButton, 'deny', params);808renderButton(cancelButton, 'cancel', params);809handleButtonsStyling(confirmButton, denyButton, cancelButton, params);810
811if (params.reverseButtons) {812if (params.toast) {813actions.insertBefore(cancelButton, confirmButton);814actions.insertBefore(denyButton, confirmButton);815} else {816actions.insertBefore(cancelButton, loader);817actions.insertBefore(denyButton, loader);818actions.insertBefore(confirmButton, loader);819}820}821}822
823function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) {824if (!params.buttonsStyling) {825return removeClass([confirmButton, denyButton, cancelButton], swalClasses.styled);826}827
828addClass([confirmButton, denyButton, cancelButton], swalClasses.styled); // Buttons background colors829
830if (params.confirmButtonColor) {831confirmButton.style.backgroundColor = params.confirmButtonColor;832addClass(confirmButton, swalClasses['default-outline']);833}834
835if (params.denyButtonColor) {836denyButton.style.backgroundColor = params.denyButtonColor;837addClass(denyButton, swalClasses['default-outline']);838}839
840if (params.cancelButtonColor) {841cancelButton.style.backgroundColor = params.cancelButtonColor;842addClass(cancelButton, swalClasses['default-outline']);843}844}845
846function renderButton(button, buttonType, params) {847toggle(button, params["show".concat(capitalizeFirstLetter(buttonType), "Button")], 'inline-block');848setInnerHtml(button, params["".concat(buttonType, "ButtonText")]); // Set caption text849
850button.setAttribute('aria-label', params["".concat(buttonType, "ButtonAriaLabel")]); // ARIA label851// Add buttons custom classes852
853button.className = swalClasses[buttonType];854applyCustomClass(button, params, "".concat(buttonType, "Button"));855addClass(button, params["".concat(buttonType, "ButtonClass")]);856}857
858function handleBackdropParam(container, backdrop) {859if (typeof backdrop === 'string') {860container.style.background = backdrop;861} else if (!backdrop) {862addClass([document.documentElement, document.body], swalClasses['no-backdrop']);863}864}865
866function handlePositionParam(container, position) {867if (position in swalClasses) {868addClass(container, swalClasses[position]);869} else {870warn('The "position" parameter is not valid, defaulting to "center"');871addClass(container, swalClasses.center);872}873}874
875function handleGrowParam(container, grow) {876if (grow && typeof grow === 'string') {877const growClass = "grow-".concat(grow);878
879if (growClass in swalClasses) {880addClass(container, swalClasses[growClass]);881}882}883}884
885const renderContainer = (instance, params) => {886const container = getContainer();887
888if (!container) {889return;890}891
892handleBackdropParam(container, params.backdrop);893handlePositionParam(container, params.position);894handleGrowParam(container, params.grow); // Custom class895
896applyCustomClass(container, params, 'container');897};898
899/**900* This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
901* For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
902* This is the approach that Babel will probably take to implement private methods/fields
903* https://github.com/tc39/proposal-private-methods
904* https://github.com/babel/babel/pull/7555
905* Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
906* then we can use that language feature.
907*/
908var privateProps = {909awaitingPromise: new WeakMap(),910promise: new WeakMap(),911innerParams: new WeakMap(),912domCache: new WeakMap()913};914
915const inputTypes = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea'];916const renderInput = (instance, params) => {917const popup = getPopup();918const innerParams = privateProps.innerParams.get(instance);919const rerender = !innerParams || params.input !== innerParams.input;920inputTypes.forEach(inputType => {921const inputClass = swalClasses[inputType];922const inputContainer = getDirectChildByClass(popup, inputClass); // set attributes923
924setAttributes(inputType, params.inputAttributes); // set class925
926inputContainer.className = inputClass;927
928if (rerender) {929hide(inputContainer);930}931});932
933if (params.input) {934if (rerender) {935showInput(params);936} // set custom class937
938
939setCustomClass(params);940}941};942
943const showInput = params => {944if (!renderInputType[params.input]) {945return error("Unexpected type of input! Expected \"text\", \"email\", \"password\", \"number\", \"tel\", \"select\", \"radio\", \"checkbox\", \"textarea\", \"file\" or \"url\", got \"".concat(params.input, "\""));946}947
948const inputContainer = getInputContainer(params.input);949const input = renderInputType[params.input](inputContainer, params);950show(input); // input autofocus951
952setTimeout(() => {953focusInput(input);954});955};956
957const removeAttributes = input => {958for (let i = 0; i < input.attributes.length; i++) {959const attrName = input.attributes[i].name;960
961if (!['type', 'value', 'style'].includes(attrName)) {962input.removeAttribute(attrName);963}964}965};966
967const setAttributes = (inputType, inputAttributes) => {968const input = getInput(getPopup(), inputType);969
970if (!input) {971return;972}973
974removeAttributes(input);975
976for (const attr in inputAttributes) {977input.setAttribute(attr, inputAttributes[attr]);978}979};980
981const setCustomClass = params => {982const inputContainer = getInputContainer(params.input);983
984if (params.customClass) {985addClass(inputContainer, params.customClass.input);986}987};988
989const setInputPlaceholder = (input, params) => {990if (!input.placeholder || params.inputPlaceholder) {991input.placeholder = params.inputPlaceholder;992}993};994
995const setInputLabel = (input, prependTo, params) => {996if (params.inputLabel) {997input.id = swalClasses.input;998const label = document.createElement('label');999const labelClass = swalClasses['input-label'];1000label.setAttribute('for', input.id);1001label.className = labelClass;1002addClass(label, params.customClass.inputLabel);1003label.innerText = params.inputLabel;1004prependTo.insertAdjacentElement('beforebegin', label);1005}1006};1007
1008const getInputContainer = inputType => {1009const inputClass = swalClasses[inputType] ? swalClasses[inputType] : swalClasses.input;1010return getDirectChildByClass(getPopup(), inputClass);1011};1012
1013const renderInputType = {};1014
1015renderInputType.text = renderInputType.email = renderInputType.password = renderInputType.number = renderInputType.tel = renderInputType.url = (input, params) => {1016if (typeof params.inputValue === 'string' || typeof params.inputValue === 'number') {1017input.value = params.inputValue;1018} else if (!isPromise(params.inputValue)) {1019warn("Unexpected type of inputValue! Expected \"string\", \"number\" or \"Promise\", got \"".concat(typeof params.inputValue, "\""));1020}1021
1022setInputLabel(input, input, params);1023setInputPlaceholder(input, params);1024input.type = params.input;1025return input;1026};1027
1028renderInputType.file = (input, params) => {1029setInputLabel(input, input, params);1030setInputPlaceholder(input, params);1031return input;1032};1033
1034renderInputType.range = (range, params) => {1035const rangeInput = range.querySelector('input');1036const rangeOutput = range.querySelector('output');1037rangeInput.value = params.inputValue;1038rangeInput.type = params.input;1039rangeOutput.value = params.inputValue;1040setInputLabel(rangeInput, range, params);1041return range;1042};1043
1044renderInputType.select = (select, params) => {1045select.textContent = '';1046
1047if (params.inputPlaceholder) {1048const placeholder = document.createElement('option');1049setInnerHtml(placeholder, params.inputPlaceholder);1050placeholder.value = '';1051placeholder.disabled = true;1052placeholder.selected = true;1053select.appendChild(placeholder);1054}1055
1056setInputLabel(select, select, params);1057return select;1058};1059
1060renderInputType.radio = radio => {1061radio.textContent = '';1062return radio;1063};1064
1065renderInputType.checkbox = (checkboxContainer, params) => {1066/** @type {HTMLInputElement} */1067const checkbox = getInput(getPopup(), 'checkbox');1068checkbox.value = '1';1069checkbox.id = swalClasses.checkbox;1070checkbox.checked = Boolean(params.inputValue);1071const label = checkboxContainer.querySelector('span');1072setInnerHtml(label, params.inputPlaceholder);1073return checkboxContainer;1074};1075
1076renderInputType.textarea = (textarea, params) => {1077textarea.value = params.inputValue;1078setInputPlaceholder(textarea, params);1079setInputLabel(textarea, textarea, params);1080
1081const getMargin = el => parseInt(window.getComputedStyle(el).marginLeft) + parseInt(window.getComputedStyle(el).marginRight); // https://github.com/sweetalert2/sweetalert2/issues/22911082
1083
1084setTimeout(() => {1085// https://github.com/sweetalert2/sweetalert2/issues/16991086if ('MutationObserver' in window) {1087const initialPopupWidth = parseInt(window.getComputedStyle(getPopup()).width);1088
1089const textareaResizeHandler = () => {1090const textareaWidth = textarea.offsetWidth + getMargin(textarea);1091
1092if (textareaWidth > initialPopupWidth) {1093getPopup().style.width = "".concat(textareaWidth, "px");1094} else {1095getPopup().style.width = null;1096}1097};1098
1099new MutationObserver(textareaResizeHandler).observe(textarea, {1100attributes: true,1101attributeFilter: ['style']1102});1103}1104});1105return textarea;1106};1107
1108const renderContent = (instance, params) => {1109const htmlContainer = getHtmlContainer();1110applyCustomClass(htmlContainer, params, 'htmlContainer'); // Content as HTML1111
1112if (params.html) {1113parseHtmlToContainer(params.html, htmlContainer);1114show(htmlContainer, 'block');1115} // Content as plain text1116else if (params.text) {1117htmlContainer.textContent = params.text;1118show(htmlContainer, 'block');1119} // No content1120else {1121hide(htmlContainer);1122}1123
1124renderInput(instance, params);1125};1126
1127const renderFooter = (instance, params) => {1128const footer = getFooter();1129toggle(footer, params.footer);1130
1131if (params.footer) {1132parseHtmlToContainer(params.footer, footer);1133} // Custom class1134
1135
1136applyCustomClass(footer, params, 'footer');1137};1138
1139const renderCloseButton = (instance, params) => {1140const closeButton = getCloseButton();1141setInnerHtml(closeButton, params.closeButtonHtml); // Custom class1142
1143applyCustomClass(closeButton, params, 'closeButton');1144toggle(closeButton, params.showCloseButton);1145closeButton.setAttribute('aria-label', params.closeButtonAriaLabel);1146};1147
1148const renderIcon = (instance, params) => {1149const innerParams = privateProps.innerParams.get(instance);1150const icon = getIcon(); // if the given icon already rendered, apply the styling without re-rendering the icon1151
1152if (innerParams && params.icon === innerParams.icon) {1153// Custom or default content1154setContent(icon, params);1155applyStyles(icon, params);1156return;1157}1158
1159if (!params.icon && !params.iconHtml) {1160return hide(icon);1161}1162
1163if (params.icon && Object.keys(iconTypes).indexOf(params.icon) === -1) {1164error("Unknown icon! Expected \"success\", \"error\", \"warning\", \"info\" or \"question\", got \"".concat(params.icon, "\""));1165return hide(icon);1166}1167
1168show(icon); // Custom or default content1169
1170setContent(icon, params);1171applyStyles(icon, params); // Animate icon1172
1173addClass(icon, params.showClass.icon);1174};1175
1176const applyStyles = (icon, params) => {1177for (const iconType in iconTypes) {1178if (params.icon !== iconType) {1179removeClass(icon, iconTypes[iconType]);1180}1181}1182
1183addClass(icon, iconTypes[params.icon]); // Icon color1184
1185setColor(icon, params); // Success icon background color1186
1187adjustSuccessIconBackgroundColor(); // Custom class1188
1189applyCustomClass(icon, params, 'icon');1190}; // Adjust success icon background color to match the popup background color1191
1192
1193const adjustSuccessIconBackgroundColor = () => {1194const popup = getPopup();1195const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color');1196const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix');1197
1198for (let i = 0; i < successIconParts.length; i++) {1199successIconParts[i].style.backgroundColor = popupBackgroundColor;1200}1201};1202
1203const successIconHtml = "\n <div class=\"swal2-success-circular-line-left\"></div>\n <span class=\"swal2-success-line-tip\"></span> <span class=\"swal2-success-line-long\"></span>\n <div class=\"swal2-success-ring\"></div> <div class=\"swal2-success-fix\"></div>\n <div class=\"swal2-success-circular-line-right\"></div>\n";1204const errorIconHtml = "\n <span class=\"swal2-x-mark\">\n <span class=\"swal2-x-mark-line-left\"></span>\n <span class=\"swal2-x-mark-line-right\"></span>\n </span>\n";1205
1206const setContent = (icon, params) => {1207icon.textContent = '';1208
1209if (params.iconHtml) {1210setInnerHtml(icon, iconContent(params.iconHtml));1211} else if (params.icon === 'success') {1212setInnerHtml(icon, successIconHtml);1213} else if (params.icon === 'error') {1214setInnerHtml(icon, errorIconHtml);1215} else {1216const defaultIconHtml = {1217question: '?',1218warning: '!',1219info: 'i'1220};1221setInnerHtml(icon, iconContent(defaultIconHtml[params.icon]));1222}1223};1224
1225const setColor = (icon, params) => {1226if (!params.iconColor) {1227return;1228}1229
1230icon.style.color = params.iconColor;1231icon.style.borderColor = params.iconColor;1232
1233for (const sel of ['.swal2-success-line-tip', '.swal2-success-line-long', '.swal2-x-mark-line-left', '.swal2-x-mark-line-right']) {1234setStyle(icon, sel, 'backgroundColor', params.iconColor);1235}1236
1237setStyle(icon, '.swal2-success-ring', 'borderColor', params.iconColor);1238};1239
1240const iconContent = content => "<div class=\"".concat(swalClasses['icon-content'], "\">").concat(content, "</div>");1241
1242const renderImage = (instance, params) => {1243const image = getImage();1244
1245if (!params.imageUrl) {1246return hide(image);1247}1248
1249show(image, ''); // Src, alt1250
1251image.setAttribute('src', params.imageUrl);1252image.setAttribute('alt', params.imageAlt); // Width, height1253
1254applyNumericalStyle(image, 'width', params.imageWidth);1255applyNumericalStyle(image, 'height', params.imageHeight); // Class1256
1257image.className = swalClasses.image;1258applyCustomClass(image, params, 'image');1259};1260
1261const createStepElement = step => {1262const stepEl = document.createElement('li');1263addClass(stepEl, swalClasses['progress-step']);1264setInnerHtml(stepEl, step);1265return stepEl;1266};1267
1268const createLineElement = params => {1269const lineEl = document.createElement('li');1270addClass(lineEl, swalClasses['progress-step-line']);1271
1272if (params.progressStepsDistance) {1273lineEl.style.width = params.progressStepsDistance;1274}1275
1276return lineEl;1277};1278
1279const renderProgressSteps = (instance, params) => {1280const progressStepsContainer = getProgressSteps();1281
1282if (!params.progressSteps || params.progressSteps.length === 0) {1283return hide(progressStepsContainer);1284}1285
1286show(progressStepsContainer);1287progressStepsContainer.textContent = '';1288
1289if (params.currentProgressStep >= params.progressSteps.length) {1290warn('Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)');1291}1292
1293params.progressSteps.forEach((step, index) => {1294const stepEl = createStepElement(step);1295progressStepsContainer.appendChild(stepEl);1296
1297if (index === params.currentProgressStep) {1298addClass(stepEl, swalClasses['active-progress-step']);1299}1300
1301if (index !== params.progressSteps.length - 1) {1302const lineEl = createLineElement(params);1303progressStepsContainer.appendChild(lineEl);1304}1305});1306};1307
1308const renderTitle = (instance, params) => {1309const title = getTitle();1310toggle(title, params.title || params.titleText, 'block');1311
1312if (params.title) {1313parseHtmlToContainer(params.title, title);1314}1315
1316if (params.titleText) {1317title.innerText = params.titleText;1318} // Custom class1319
1320
1321applyCustomClass(title, params, 'title');1322};1323
1324const renderPopup = (instance, params) => {1325const container = getContainer();1326const popup = getPopup(); // Width1327// https://github.com/sweetalert2/sweetalert2/issues/21701328
1329if (params.toast) {1330applyNumericalStyle(container, 'width', params.width);1331popup.style.width = '100%';1332popup.insertBefore(getLoader(), getIcon());1333} else {1334applyNumericalStyle(popup, 'width', params.width);1335} // Padding1336
1337
1338applyNumericalStyle(popup, 'padding', params.padding); // Color1339
1340if (params.color) {1341popup.style.color = params.color;1342} // Background1343
1344
1345if (params.background) {1346popup.style.background = params.background;1347}1348
1349hide(getValidationMessage()); // Classes1350
1351addClasses(popup, params);1352};1353
1354const addClasses = (popup, params) => {1355// Default Class + showClass when updating Swal.update({})1356popup.className = "".concat(swalClasses.popup, " ").concat(isVisible(popup) ? params.showClass.popup : '');1357
1358if (params.toast) {1359addClass([document.documentElement, document.body], swalClasses['toast-shown']);1360addClass(popup, swalClasses.toast);1361} else {1362addClass(popup, swalClasses.modal);1363} // Custom class1364
1365
1366applyCustomClass(popup, params, 'popup');1367
1368if (typeof params.customClass === 'string') {1369addClass(popup, params.customClass);1370} // Icon class (#1842)1371
1372
1373if (params.icon) {1374addClass(popup, swalClasses["icon-".concat(params.icon)]);1375}1376};1377
1378const render = (instance, params) => {1379renderPopup(instance, params);1380renderContainer(instance, params);1381renderProgressSteps(instance, params);1382renderIcon(instance, params);1383renderImage(instance, params);1384renderTitle(instance, params);1385renderCloseButton(instance, params);1386renderContent(instance, params);1387renderActions(instance, params);1388renderFooter(instance, params);1389
1390if (typeof params.didRender === 'function') {1391params.didRender(getPopup());1392}1393};1394
1395const DismissReason = Object.freeze({1396cancel: 'cancel',1397backdrop: 'backdrop',1398close: 'close',1399esc: 'esc',1400timer: 'timer'1401});1402
1403// Adding aria-hidden="true" to elements outside of the active modal dialog ensures that1404// elements not within the active modal dialog will not be surfaced if a user opens a screen1405// reader’s list of elements (headings, form controls, landmarks, etc.) in the document.1406
1407const setAriaHidden = () => {1408const bodyChildren = toArray(document.body.children);1409bodyChildren.forEach(el => {1410if (el === getContainer() || el.contains(getContainer())) {1411return;1412}1413
1414if (el.hasAttribute('aria-hidden')) {1415el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden'));1416}1417
1418el.setAttribute('aria-hidden', 'true');1419});1420};1421const unsetAriaHidden = () => {1422const bodyChildren = toArray(document.body.children);1423bodyChildren.forEach(el => {1424if (el.hasAttribute('data-previous-aria-hidden')) {1425el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden'));1426el.removeAttribute('data-previous-aria-hidden');1427} else {1428el.removeAttribute('aria-hidden');1429}1430});1431};1432
1433const swalStringParams = ['swal-title', 'swal-html', 'swal-footer'];1434const getTemplateParams = params => {1435const template = typeof params.template === 'string' ? document.querySelector(params.template) : params.template;1436
1437if (!template) {1438return {};1439}1440/** @type {DocumentFragment} */1441
1442
1443const templateContent = template.content;1444showWarningsForElements(templateContent);1445const result = Object.assign(getSwalParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams));1446return result;1447};1448/**1449* @param {DocumentFragment} templateContent
1450*/
1451
1452const getSwalParams = templateContent => {1453const result = {};1454toArray(templateContent.querySelectorAll('swal-param')).forEach(param => {1455showWarningsForAttributes(param, ['name', 'value']);1456const paramName = param.getAttribute('name');1457const value = param.getAttribute('value');1458
1459if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {1460result[paramName] = false;1461}1462
1463if (typeof defaultParams[paramName] === 'object') {1464result[paramName] = JSON.parse(value);1465}1466});1467return result;1468};1469/**1470* @param {DocumentFragment} templateContent
1471*/
1472
1473
1474const getSwalButtons = templateContent => {1475const result = {};1476toArray(templateContent.querySelectorAll('swal-button')).forEach(button => {1477showWarningsForAttributes(button, ['type', 'color', 'aria-label']);1478const type = button.getAttribute('type');1479result["".concat(type, "ButtonText")] = button.innerHTML;1480result["show".concat(capitalizeFirstLetter(type), "Button")] = true;1481
1482if (button.hasAttribute('color')) {1483result["".concat(type, "ButtonColor")] = button.getAttribute('color');1484}1485
1486if (button.hasAttribute('aria-label')) {1487result["".concat(type, "ButtonAriaLabel")] = button.getAttribute('aria-label');1488}1489});1490return result;1491};1492/**1493* @param {DocumentFragment} templateContent
1494*/
1495
1496
1497const getSwalImage = templateContent => {1498const result = {};1499/** @type {HTMLElement} */1500
1501const image = templateContent.querySelector('swal-image');1502
1503if (image) {1504showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']);1505
1506if (image.hasAttribute('src')) {1507result.imageUrl = image.getAttribute('src');1508}1509
1510if (image.hasAttribute('width')) {1511result.imageWidth = image.getAttribute('width');1512}1513
1514if (image.hasAttribute('height')) {1515result.imageHeight = image.getAttribute('height');1516}1517
1518if (image.hasAttribute('alt')) {1519result.imageAlt = image.getAttribute('alt');1520}1521}1522
1523return result;1524};1525/**1526* @param {DocumentFragment} templateContent
1527*/
1528
1529
1530const getSwalIcon = templateContent => {1531const result = {};1532/** @type {HTMLElement} */1533
1534const icon = templateContent.querySelector('swal-icon');1535
1536if (icon) {1537showWarningsForAttributes(icon, ['type', 'color']);1538
1539if (icon.hasAttribute('type')) {1540result.icon = icon.getAttribute('type');1541}1542
1543if (icon.hasAttribute('color')) {1544result.iconColor = icon.getAttribute('color');1545}1546
1547result.iconHtml = icon.innerHTML;1548}1549
1550return result;1551};1552/**1553* @param {DocumentFragment} templateContent
1554*/
1555
1556
1557const getSwalInput = templateContent => {1558const result = {};1559/** @type {HTMLElement} */1560
1561const input = templateContent.querySelector('swal-input');1562
1563if (input) {1564showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value']);1565result.input = input.getAttribute('type') || 'text';1566
1567if (input.hasAttribute('label')) {1568result.inputLabel = input.getAttribute('label');1569}1570
1571if (input.hasAttribute('placeholder')) {1572result.inputPlaceholder = input.getAttribute('placeholder');1573}1574
1575if (input.hasAttribute('value')) {1576result.inputValue = input.getAttribute('value');1577}1578}1579
1580const inputOptions = templateContent.querySelectorAll('swal-input-option');1581
1582if (inputOptions.length) {1583result.inputOptions = {};1584toArray(inputOptions).forEach(option => {1585showWarningsForAttributes(option, ['value']);1586const optionValue = option.getAttribute('value');1587const optionName = option.innerHTML;1588result.inputOptions[optionValue] = optionName;1589});1590}1591
1592return result;1593};1594/**1595* @param {DocumentFragment} templateContent
1596* @param {string[]} paramNames
1597*/
1598
1599
1600const getSwalStringParams = (templateContent, paramNames) => {1601const result = {};1602
1603for (const i in paramNames) {1604const paramName = paramNames[i];1605/** @type {HTMLElement} */1606
1607const tag = templateContent.querySelector(paramName);1608
1609if (tag) {1610showWarningsForAttributes(tag, []);1611result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim();1612}1613}1614
1615return result;1616};1617/**1618* @param {DocumentFragment} templateContent
1619*/
1620
1621
1622const showWarningsForElements = templateContent => {1623const allowedElements = swalStringParams.concat(['swal-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']);1624toArray(templateContent.children).forEach(el => {1625const tagName = el.tagName.toLowerCase();1626
1627if (allowedElements.indexOf(tagName) === -1) {1628warn("Unrecognized element <".concat(tagName, ">"));1629}1630});1631};1632/**1633* @param {HTMLElement} el
1634* @param {string[]} allowedAttributes
1635*/
1636
1637
1638const showWarningsForAttributes = (el, allowedAttributes) => {1639toArray(el.attributes).forEach(attribute => {1640if (allowedAttributes.indexOf(attribute.name) === -1) {1641warn(["Unrecognized attribute \"".concat(attribute.name, "\" on <").concat(el.tagName.toLowerCase(), ">."), "".concat(allowedAttributes.length ? "Allowed attributes are: ".concat(allowedAttributes.join(', ')) : 'To set the value, use HTML within the element.')]);1642}1643});1644};1645
1646var defaultInputValidators = {1647email: (string, validationMessage) => {1648return /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid email address');1649},1650url: (string, validationMessage) => {1651// taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #20131652return /^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');1653}1654};1655
1656function setDefaultInputValidators(params) {1657// Use default `inputValidator` for supported input types if not provided1658if (!params.inputValidator) {1659Object.keys(defaultInputValidators).forEach(key => {1660if (params.input === key) {1661params.inputValidator = defaultInputValidators[key];1662}1663});1664}1665}1666
1667function validateCustomTargetElement(params) {1668// Determine if the custom target element is valid1669if (!params.target || typeof params.target === 'string' && !document.querySelector(params.target) || typeof params.target !== 'string' && !params.target.appendChild) {1670warn('Target parameter is not valid, defaulting to "body"');1671params.target = 'body';1672}1673}1674/**1675* Set type, text and actions on popup
1676*
1677* @param params
1678*/
1679
1680
1681function setParameters(params) {1682setDefaultInputValidators(params); // showLoaderOnConfirm && preConfirm1683
1684if (params.showLoaderOnConfirm && !params.preConfirm) {1685warn('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');1686}1687
1688validateCustomTargetElement(params); // Replace newlines with <br> in title1689
1690if (typeof params.title === 'string') {1691params.title = params.title.split('\n').join('<br />');1692}1693
1694init(params);1695}1696
1697class Timer {1698constructor(callback, delay) {1699this.callback = callback;1700this.remaining = delay;1701this.running = false;1702this.start();1703}1704
1705start() {1706if (!this.running) {1707this.running = true;1708this.started = new Date();1709this.id = setTimeout(this.callback, this.remaining);1710}1711
1712return this.remaining;1713}1714
1715stop() {1716if (this.running) {1717this.running = false;1718clearTimeout(this.id);1719this.remaining -= new Date().getTime() - this.started.getTime();1720}1721
1722return this.remaining;1723}1724
1725increase(n) {1726const running = this.running;1727
1728if (running) {1729this.stop();1730}1731
1732this.remaining += n;1733
1734if (running) {1735this.start();1736}1737
1738return this.remaining;1739}1740
1741getTimerLeft() {1742if (this.running) {1743this.stop();1744this.start();1745}1746
1747return this.remaining;1748}1749
1750isRunning() {1751return this.running;1752}1753
1754}1755
1756const fixScrollbar = () => {1757// for queues, do not do this more than once1758if (states.previousBodyPadding !== null) {1759return;1760} // if the body has overflow1761
1762
1763if (document.body.scrollHeight > window.innerHeight) {1764// add padding so the content doesn't shift after removal of scrollbar1765states.previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'));1766document.body.style.paddingRight = "".concat(states.previousBodyPadding + measureScrollbar(), "px");1767}1768};1769const undoScrollbar = () => {1770if (states.previousBodyPadding !== null) {1771document.body.style.paddingRight = "".concat(states.previousBodyPadding, "px");1772states.previousBodyPadding = null;1773}1774};1775
1776/* istanbul ignore file */1777
1778const iOSfix = () => {1779const iOS = // @ts-ignore1780/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream || navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;1781
1782if (iOS && !hasClass(document.body, swalClasses.iosfix)) {1783const offset = document.body.scrollTop;1784document.body.style.top = "".concat(offset * -1, "px");1785addClass(document.body, swalClasses.iosfix);1786lockBodyScroll();1787addBottomPaddingForTallPopups();1788}1789};1790/**1791* https://github.com/sweetalert2/sweetalert2/issues/1948
1792*/
1793
1794const addBottomPaddingForTallPopups = () => {1795const ua = navigator.userAgent;1796const iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);1797const webkit = !!ua.match(/WebKit/i);1798const iOSSafari = iOS && webkit && !ua.match(/CriOS/i);1799
1800if (iOSSafari) {1801const bottomPanelHeight = 44;1802
1803if (getPopup().scrollHeight > window.innerHeight - bottomPanelHeight) {1804getContainer().style.paddingBottom = "".concat(bottomPanelHeight, "px");1805}1806}1807};1808/**1809* https://github.com/sweetalert2/sweetalert2/issues/1246
1810*/
1811
1812
1813const lockBodyScroll = () => {1814const container = getContainer();1815let preventTouchMove;1816
1817container.ontouchstart = e => {1818preventTouchMove = shouldPreventTouchMove(e);1819};1820
1821container.ontouchmove = e => {1822if (preventTouchMove) {1823e.preventDefault();1824e.stopPropagation();1825}1826};1827};1828
1829const shouldPreventTouchMove = event => {1830const target = event.target;1831const container = getContainer();1832
1833if (isStylus(event) || isZoom(event)) {1834return false;1835}1836
1837if (target === container) {1838return true;1839}1840
1841if (!isScrollable(container) && target.tagName !== 'INPUT' && // #16031842target.tagName !== 'TEXTAREA' && // #22661843!(isScrollable(getHtmlContainer()) && // #19441844getHtmlContainer().contains(target))) {1845return true;1846}1847
1848return false;1849};1850/**1851* https://github.com/sweetalert2/sweetalert2/issues/1786
1852*
1853* @param {*} event
1854* @returns {boolean}
1855*/
1856
1857
1858const isStylus = event => {1859return event.touches && event.touches.length && event.touches[0].touchType === 'stylus';1860};1861/**1862* https://github.com/sweetalert2/sweetalert2/issues/1891
1863*
1864* @param {TouchEvent} event
1865* @returns {boolean}
1866*/
1867
1868
1869const isZoom = event => {1870return event.touches && event.touches.length > 1;1871};1872
1873const undoIOSfix = () => {1874if (hasClass(document.body, swalClasses.iosfix)) {1875const offset = parseInt(document.body.style.top, 10);1876removeClass(document.body, swalClasses.iosfix);1877document.body.style.top = '';1878document.body.scrollTop = offset * -1;1879}1880};1881
1882const SHOW_CLASS_TIMEOUT = 10;1883/**1884* Open popup, add necessary classes and styles, fix scrollbar
1885*
1886* @param params
1887*/
1888
1889const openPopup = params => {1890const container = getContainer();1891const popup = getPopup();1892
1893if (typeof params.willOpen === 'function') {1894params.willOpen(popup);1895}1896
1897const bodyStyles = window.getComputedStyle(document.body);1898const initialBodyOverflow = bodyStyles.overflowY;1899addClasses$1(container, popup, params); // scrolling is 'hidden' until animation is done, after that 'auto'1900
1901setTimeout(() => {1902setScrollingVisibility(container, popup);1903}, SHOW_CLASS_TIMEOUT);1904
1905if (isModal()) {1906fixScrollContainer(container, params.scrollbarPadding, initialBodyOverflow);1907setAriaHidden();1908}1909
1910if (!isToast() && !globalState.previousActiveElement) {1911globalState.previousActiveElement = document.activeElement;1912}1913
1914if (typeof params.didOpen === 'function') {1915setTimeout(() => params.didOpen(popup));1916}1917
1918removeClass(container, swalClasses['no-transition']);1919};1920
1921const swalOpenAnimationFinished = event => {1922const popup = getPopup();1923
1924if (event.target !== popup) {1925return;1926}1927
1928const container = getContainer();1929popup.removeEventListener(animationEndEvent, swalOpenAnimationFinished);1930container.style.overflowY = 'auto';1931};1932
1933const setScrollingVisibility = (container, popup) => {1934if (animationEndEvent && hasCssAnimation(popup)) {1935container.style.overflowY = 'hidden';1936popup.addEventListener(animationEndEvent, swalOpenAnimationFinished);1937} else {1938container.style.overflowY = 'auto';1939}1940};1941
1942const fixScrollContainer = (container, scrollbarPadding, initialBodyOverflow) => {1943iOSfix();1944
1945if (scrollbarPadding && initialBodyOverflow !== 'hidden') {1946fixScrollbar();1947} // sweetalert2/issues/12471948
1949
1950setTimeout(() => {1951container.scrollTop = 0;1952});1953};1954
1955const addClasses$1 = (container, popup, params) => {1956addClass(container, params.showClass.backdrop); // this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/20591957
1958popup.style.setProperty('opacity', '0', 'important');1959show(popup, 'grid');1960setTimeout(() => {1961// Animate popup right after showing it1962addClass(popup, params.showClass.popup); // and remove the opacity workaround1963
1964popup.style.removeProperty('opacity');1965}, SHOW_CLASS_TIMEOUT); // 10ms in order to fix #20621966
1967addClass([document.documentElement, document.body], swalClasses.shown);1968
1969if (params.heightAuto && params.backdrop && !params.toast) {1970addClass([document.documentElement, document.body], swalClasses['height-auto']);1971}1972};1973
1974/**1975* Shows loader (spinner), this is useful with AJAX requests.
1976* By default the loader be shown instead of the "Confirm" button.
1977*/
1978
1979const showLoading = buttonToReplace => {1980let popup = getPopup();1981
1982if (!popup) {1983new Swal(); // eslint-disable-line no-new1984}1985
1986popup = getPopup();1987const loader = getLoader();1988
1989if (isToast()) {1990hide(getIcon());1991} else {1992replaceButton(popup, buttonToReplace);1993}1994
1995show(loader);1996popup.setAttribute('data-loading', true);1997popup.setAttribute('aria-busy', true);1998popup.focus();1999};2000
2001const replaceButton = (popup, buttonToReplace) => {2002const actions = getActions();2003const loader = getLoader();2004
2005if (!buttonToReplace && isVisible(getConfirmButton())) {2006buttonToReplace = getConfirmButton();2007}2008
2009show(actions);2010
2011if (buttonToReplace) {2012hide(buttonToReplace);2013loader.setAttribute('data-button-to-replace', buttonToReplace.className);2014}2015
2016loader.parentNode.insertBefore(loader, buttonToReplace);2017addClass([popup, actions], swalClasses.loading);2018};2019
2020const handleInputOptionsAndValue = (instance, params) => {2021if (params.input === 'select' || params.input === 'radio') {2022handleInputOptions(instance, params);2023} else if (['text', 'email', 'number', 'tel', 'textarea'].includes(params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {2024showLoading(getConfirmButton());2025handleInputValue(instance, params);2026}2027};2028const getInputValue = (instance, innerParams) => {2029const input = instance.getInput();2030
2031if (!input) {2032return null;2033}2034
2035switch (innerParams.input) {2036case 'checkbox':2037return getCheckboxValue(input);2038
2039case 'radio':2040return getRadioValue(input);2041
2042case 'file':2043return getFileValue(input);2044
2045default:2046return innerParams.inputAutoTrim ? input.value.trim() : input.value;2047}2048};2049
2050const getCheckboxValue = input => input.checked ? 1 : 0;2051
2052const getRadioValue = input => input.checked ? input.value : null;2053
2054const getFileValue = input => input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;2055
2056const handleInputOptions = (instance, params) => {2057const popup = getPopup();2058
2059const processInputOptions = inputOptions => populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params);2060
2061if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {2062showLoading(getConfirmButton());2063asPromise(params.inputOptions).then(inputOptions => {2064instance.hideLoading();2065processInputOptions(inputOptions);2066});2067} else if (typeof params.inputOptions === 'object') {2068processInputOptions(params.inputOptions);2069} else {2070error("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(typeof params.inputOptions));2071}2072};2073
2074const handleInputValue = (instance, params) => {2075const input = instance.getInput();2076hide(input);2077asPromise(params.inputValue).then(inputValue => {2078input.value = params.input === 'number' ? parseFloat(inputValue) || 0 : "".concat(inputValue);2079show(input);2080input.focus();2081instance.hideLoading();2082}).catch(err => {2083error("Error in inputValue promise: ".concat(err));2084input.value = '';2085show(input);2086input.focus();2087instance.hideLoading();2088});2089};2090
2091const populateInputOptions = {2092select: (popup, inputOptions, params) => {2093const select = getDirectChildByClass(popup, swalClasses.select);2094
2095const renderOption = (parent, optionLabel, optionValue) => {2096const option = document.createElement('option');2097option.value = optionValue;2098setInnerHtml(option, optionLabel);2099option.selected = isSelected(optionValue, params.inputValue);2100parent.appendChild(option);2101};2102
2103inputOptions.forEach(inputOption => {2104const optionValue = inputOption[0];2105const optionLabel = inputOption[1]; // <optgroup> spec:2106// https://www.w3.org/TR/html401/interact/forms.html#h-17.62107// "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."2108// check whether this is a <optgroup>2109
2110if (Array.isArray(optionLabel)) {2111// if it is an array, then it is an <optgroup>2112const optgroup = document.createElement('optgroup');2113optgroup.label = optionValue;2114optgroup.disabled = false; // not configurable for now2115
2116select.appendChild(optgroup);2117optionLabel.forEach(o => renderOption(optgroup, o[1], o[0]));2118} else {2119// case of <option>2120renderOption(select, optionLabel, optionValue);2121}2122});2123select.focus();2124},2125radio: (popup, inputOptions, params) => {2126const radio = getDirectChildByClass(popup, swalClasses.radio);2127inputOptions.forEach(inputOption => {2128const radioValue = inputOption[0];2129const radioLabel = inputOption[1];2130const radioInput = document.createElement('input');2131const radioLabelElement = document.createElement('label');2132radioInput.type = 'radio';2133radioInput.name = swalClasses.radio;2134radioInput.value = radioValue;2135
2136if (isSelected(radioValue, params.inputValue)) {2137radioInput.checked = true;2138}2139
2140const label = document.createElement('span');2141setInnerHtml(label, radioLabel);2142label.className = swalClasses.label;2143radioLabelElement.appendChild(radioInput);2144radioLabelElement.appendChild(label);2145radio.appendChild(radioLabelElement);2146});2147const radios = radio.querySelectorAll('input');2148
2149if (radios.length) {2150radios[0].focus();2151}2152}2153};2154/**2155* Converts `inputOptions` into an array of `[value, label]`s
2156* @param inputOptions
2157*/
2158
2159const formatInputOptions = inputOptions => {2160const result = [];2161
2162if (typeof Map !== 'undefined' && inputOptions instanceof Map) {2163inputOptions.forEach((value, key) => {2164let valueFormatted = value;2165
2166if (typeof valueFormatted === 'object') {2167// case of <optgroup>2168valueFormatted = formatInputOptions(valueFormatted);2169}2170
2171result.push([key, valueFormatted]);2172});2173} else {2174Object.keys(inputOptions).forEach(key => {2175let valueFormatted = inputOptions[key];2176
2177if (typeof valueFormatted === 'object') {2178// case of <optgroup>2179valueFormatted = formatInputOptions(valueFormatted);2180}2181
2182result.push([key, valueFormatted]);2183});2184}2185
2186return result;2187};2188
2189const isSelected = (optionValue, inputValue) => {2190return inputValue && inputValue.toString() === optionValue.toString();2191};2192
2193const handleConfirmButtonClick = instance => {2194const innerParams = privateProps.innerParams.get(instance);2195instance.disableButtons();2196
2197if (innerParams.input) {2198handleConfirmOrDenyWithInput(instance, 'confirm');2199} else {2200confirm(instance, true);2201}2202};2203const handleDenyButtonClick = instance => {2204const innerParams = privateProps.innerParams.get(instance);2205instance.disableButtons();2206
2207if (innerParams.returnInputValueOnDeny) {2208handleConfirmOrDenyWithInput(instance, 'deny');2209} else {2210deny(instance, false);2211}2212};2213const handleCancelButtonClick = (instance, dismissWith) => {2214instance.disableButtons();2215dismissWith(DismissReason.cancel);2216};2217
2218const handleConfirmOrDenyWithInput = (instance, type2219/* 'confirm' | 'deny' */2220) => {2221const innerParams = privateProps.innerParams.get(instance);2222
2223if (!innerParams.input) {2224return error("The \"input\" parameter is needed to be set when using returnInputValueOn".concat(capitalizeFirstLetter(type)));2225}2226
2227const inputValue = getInputValue(instance, innerParams);2228
2229if (innerParams.inputValidator) {2230handleInputValidator(instance, inputValue, type);2231} else if (!instance.getInput().checkValidity()) {2232instance.enableButtons();2233instance.showValidationMessage(innerParams.validationMessage);2234} else if (type === 'deny') {2235deny(instance, inputValue);2236} else {2237confirm(instance, inputValue);2238}2239};2240
2241const handleInputValidator = (instance, inputValue, type2242/* 'confirm' | 'deny' */2243) => {2244const innerParams = privateProps.innerParams.get(instance);2245instance.disableInput();2246const validationPromise = Promise.resolve().then(() => asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage)));2247validationPromise.then(validationMessage => {2248instance.enableButtons();2249instance.enableInput();2250
2251if (validationMessage) {2252instance.showValidationMessage(validationMessage);2253} else if (type === 'deny') {2254deny(instance, inputValue);2255} else {2256confirm(instance, inputValue);2257}2258});2259};2260
2261const deny = (instance, value) => {2262const innerParams = privateProps.innerParams.get(instance || undefined);2263
2264if (innerParams.showLoaderOnDeny) {2265showLoading(getDenyButton());2266}2267
2268if (innerParams.preDeny) {2269privateProps.awaitingPromise.set(instance || undefined, 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 received2270
2271const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage)));2272preDenyPromise.then(preDenyValue => {2273if (preDenyValue === false) {2274instance.hideLoading();2275} else {2276instance.closePopup({2277isDenied: true,2278value: typeof preDenyValue === 'undefined' ? value : preDenyValue2279});2280}2281}).catch(error$$1 => rejectWith(instance || undefined, error$$1));2282} else {2283instance.closePopup({2284isDenied: true,2285value
2286});2287}2288};2289
2290const succeedWith = (instance, value) => {2291instance.closePopup({2292isConfirmed: true,2293value
2294});2295};2296
2297const rejectWith = (instance, error$$1) => {2298instance.rejectPromise(error$$1);2299};2300
2301const confirm = (instance, value) => {2302const innerParams = privateProps.innerParams.get(instance || undefined);2303
2304if (innerParams.showLoaderOnConfirm) {2305showLoading();2306}2307
2308if (innerParams.preConfirm) {2309instance.resetValidationMessage();2310privateProps.awaitingPromise.set(instance || undefined, 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 received2311
2312const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));2313preConfirmPromise.then(preConfirmValue => {2314if (isVisible(getValidationMessage()) || preConfirmValue === false) {2315instance.hideLoading();2316} else {2317succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);2318}2319}).catch(error$$1 => rejectWith(instance || undefined, error$$1));2320} else {2321succeedWith(instance, value);2322}2323};2324
2325const handlePopupClick = (instance, domCache, dismissWith) => {2326const innerParams = privateProps.innerParams.get(instance);2327
2328if (innerParams.toast) {2329handleToastClick(instance, domCache, dismissWith);2330} else {2331// Ignore click events that had mousedown on the popup but mouseup on the container2332// This can happen when the user drags a slider2333handleModalMousedown(domCache); // Ignore click events that had mousedown on the container but mouseup on the popup2334
2335handleContainerMousedown(domCache);2336handleModalClick(instance, domCache, dismissWith);2337}2338};2339
2340const handleToastClick = (instance, domCache, dismissWith) => {2341// Closing toast by internal click2342domCache.popup.onclick = () => {2343const innerParams = privateProps.innerParams.get(instance);2344
2345if (innerParams && (isAnyButtonShown(innerParams) || innerParams.timer || innerParams.input)) {2346return;2347}2348
2349dismissWith(DismissReason.close);2350};2351};2352/**2353* @param {*} innerParams
2354* @returns {boolean}
2355*/
2356
2357
2358const isAnyButtonShown = innerParams => {2359return innerParams.showConfirmButton || innerParams.showDenyButton || innerParams.showCancelButton || innerParams.showCloseButton;2360};2361
2362let ignoreOutsideClick = false;2363
2364const handleModalMousedown = domCache => {2365domCache.popup.onmousedown = () => {2366domCache.container.onmouseup = function (e) {2367domCache.container.onmouseup = undefined; // We only check if the mouseup target is the container because usually it doesn't2368// have any other direct children aside of the popup2369
2370if (e.target === domCache.container) {2371ignoreOutsideClick = true;2372}2373};2374};2375};2376
2377const handleContainerMousedown = domCache => {2378domCache.container.onmousedown = () => {2379domCache.popup.onmouseup = function (e) {2380domCache.popup.onmouseup = undefined; // We also need to check if the mouseup target is a child of the popup2381
2382if (e.target === domCache.popup || domCache.popup.contains(e.target)) {2383ignoreOutsideClick = true;2384}2385};2386};2387};2388
2389const handleModalClick = (instance, domCache, dismissWith) => {2390domCache.container.onclick = e => {2391const innerParams = privateProps.innerParams.get(instance);2392
2393if (ignoreOutsideClick) {2394ignoreOutsideClick = false;2395return;2396}2397
2398if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) {2399dismissWith(DismissReason.backdrop);2400}2401};2402};2403
2404/*2405* Global function to determine if SweetAlert2 popup is shown
2406*/
2407
2408const isVisible$1 = () => {2409return isVisible(getPopup());2410};2411/*2412* Global function to click 'Confirm' button
2413*/
2414
2415const clickConfirm = () => getConfirmButton() && getConfirmButton().click();2416/*2417* Global function to click 'Deny' button
2418*/
2419
2420const clickDeny = () => getDenyButton() && getDenyButton().click();2421/*2422* Global function to click 'Cancel' button
2423*/
2424
2425const clickCancel = () => getCancelButton() && getCancelButton().click();2426
2427const addKeydownHandler = (instance, globalState, innerParams, dismissWith) => {2428if (globalState.keydownTarget && globalState.keydownHandlerAdded) {2429globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, {2430capture: globalState.keydownListenerCapture2431});2432globalState.keydownHandlerAdded = false;2433}2434
2435if (!innerParams.toast) {2436globalState.keydownHandler = e => keydownHandler(instance, e, dismissWith);2437
2438globalState.keydownTarget = innerParams.keydownListenerCapture ? window : getPopup();2439globalState.keydownListenerCapture = innerParams.keydownListenerCapture;2440globalState.keydownTarget.addEventListener('keydown', globalState.keydownHandler, {2441capture: globalState.keydownListenerCapture2442});2443globalState.keydownHandlerAdded = true;2444}2445}; // Focus handling2446
2447const setFocus = (innerParams, index, increment) => {2448const focusableElements = getFocusableElements(); // search for visible elements and select the next possible match2449
2450if (focusableElements.length) {2451index = index + increment; // rollover to first item2452
2453if (index === focusableElements.length) {2454index = 0; // go to last item2455} else if (index === -1) {2456index = focusableElements.length - 1;2457}2458
2459return focusableElements[index].focus();2460} // no visible focusable elements, focus the popup2461
2462
2463getPopup().focus();2464};2465const arrowKeysNextButton = ['ArrowRight', 'ArrowDown'];2466const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp'];2467
2468const keydownHandler = (instance, e, dismissWith) => {2469const innerParams = privateProps.innerParams.get(instance);2470
2471if (!innerParams) {2472return; // This instance has already been destroyed2473}2474
2475if (innerParams.stopKeydownPropagation) {2476e.stopPropagation();2477} // ENTER2478
2479
2480if (e.key === 'Enter') {2481handleEnter(instance, e, innerParams);2482} // TAB2483else if (e.key === 'Tab') {2484handleTab(e, innerParams);2485} // ARROWS - switch focus between buttons2486else if ([...arrowKeysNextButton, ...arrowKeysPreviousButton].includes(e.key)) {2487handleArrows(e.key);2488} // ESC2489else if (e.key === 'Escape') {2490handleEsc(e, innerParams, dismissWith);2491}2492};2493
2494const handleEnter = (instance, e, innerParams) => {2495// #2386 #720 #7212496if (!callIfFunction(innerParams.allowEnterKey) || e.isComposing) {2497return;2498}2499
2500if (e.target && instance.getInput() && e.target.outerHTML === instance.getInput().outerHTML) {2501if (['textarea', 'file'].includes(innerParams.input)) {2502return; // do not submit2503}2504
2505clickConfirm();2506e.preventDefault();2507}2508};2509
2510const handleTab = (e, innerParams) => {2511const targetElement = e.target;2512const focusableElements = getFocusableElements();2513let btnIndex = -1;2514
2515for (let i = 0; i < focusableElements.length; i++) {2516if (targetElement === focusableElements[i]) {2517btnIndex = i;2518break;2519}2520} // Cycle to the next button2521
2522
2523if (!e.shiftKey) {2524setFocus(innerParams, btnIndex, 1);2525} // Cycle to the prev button2526else {2527setFocus(innerParams, btnIndex, -1);2528}2529
2530e.stopPropagation();2531e.preventDefault();2532};2533
2534const handleArrows = key => {2535const confirmButton = getConfirmButton();2536const denyButton = getDenyButton();2537const cancelButton = getCancelButton();2538
2539if (![confirmButton, denyButton, cancelButton].includes(document.activeElement)) {2540return;2541}2542
2543const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling';2544const buttonToFocus = document.activeElement[sibling];2545
2546if (buttonToFocus instanceof HTMLElement) {2547buttonToFocus.focus();2548}2549};2550
2551const handleEsc = (e, innerParams, dismissWith) => {2552if (callIfFunction(innerParams.allowEscapeKey)) {2553e.preventDefault();2554dismissWith(DismissReason.esc);2555}2556};2557
2558const isJqueryElement = elem => typeof elem === 'object' && elem.jquery;2559
2560const isElement = elem => elem instanceof Element || isJqueryElement(elem);2561
2562const argsToParams = args => {2563const params = {};2564
2565if (typeof args[0] === 'object' && !isElement(args[0])) {2566Object.assign(params, args[0]);2567} else {2568['title', 'html', 'icon'].forEach((name, index) => {2569const arg = args[index];2570
2571if (typeof arg === 'string' || isElement(arg)) {2572params[name] = arg;2573} else if (arg !== undefined) {2574error("Unexpected type of ".concat(name, "! Expected \"string\" or \"Element\", got ").concat(typeof arg));2575}2576});2577}2578
2579return params;2580};2581
2582function fire() {2583const Swal = this; // eslint-disable-line @typescript-eslint/no-this-alias2584
2585for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {2586args[_key] = arguments[_key];2587}2588
2589return new Swal(...args);2590}2591
2592/**2593* Returns an extended version of `Swal` containing `params` as defaults.
2594* Useful for reusing Swal configuration.
2595*
2596* For example:
2597*
2598* Before:
2599* const textPromptOptions = { input: 'text', showCancelButton: true }
2600* const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' })
2601* const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' })
2602*
2603* After:
2604* const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true })
2605* const {value: firstName} = await TextPrompt('What is your first name?')
2606* const {value: lastName} = await TextPrompt('What is your last name?')
2607*
2608* @param mixinParams
2609*/
2610function mixin(mixinParams) {2611class MixinSwal extends this {2612_main(params, priorityMixinParams) {2613return super._main(params, Object.assign({}, mixinParams, priorityMixinParams));2614}2615
2616}2617
2618return MixinSwal;2619}2620
2621/**2622* If `timer` parameter is set, returns number of milliseconds of timer remained.
2623* Otherwise, returns undefined.
2624*/
2625
2626const getTimerLeft = () => {2627return globalState.timeout && globalState.timeout.getTimerLeft();2628};2629/**2630* Stop timer. Returns number of milliseconds of timer remained.
2631* If `timer` parameter isn't set, returns undefined.
2632*/
2633
2634const stopTimer = () => {2635if (globalState.timeout) {2636stopTimerProgressBar();2637return globalState.timeout.stop();2638}2639};2640/**2641* Resume timer. Returns number of milliseconds of timer remained.
2642* If `timer` parameter isn't set, returns undefined.
2643*/
2644
2645const resumeTimer = () => {2646if (globalState.timeout) {2647const remaining = globalState.timeout.start();2648animateTimerProgressBar(remaining);2649return remaining;2650}2651};2652/**2653* Resume timer. Returns number of milliseconds of timer remained.
2654* If `timer` parameter isn't set, returns undefined.
2655*/
2656
2657const toggleTimer = () => {2658const timer = globalState.timeout;2659return timer && (timer.running ? stopTimer() : resumeTimer());2660};2661/**2662* Increase timer. Returns number of milliseconds of an updated timer.
2663* If `timer` parameter isn't set, returns undefined.
2664*/
2665
2666const increaseTimer = n => {2667if (globalState.timeout) {2668const remaining = globalState.timeout.increase(n);2669animateTimerProgressBar(remaining, true);2670return remaining;2671}2672};2673/**2674* Check if timer is running. Returns true if timer is running
2675* or false if timer is paused or stopped.
2676* If `timer` parameter isn't set, returns undefined
2677*/
2678
2679const isTimerRunning = () => {2680return globalState.timeout && globalState.timeout.isRunning();2681};2682
2683let bodyClickListenerAdded = false;2684const clickHandlers = {};2685function bindClickHandler() {2686let attr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'data-swal-template';2687clickHandlers[attr] = this;2688
2689if (!bodyClickListenerAdded) {2690document.body.addEventListener('click', bodyClickListener);2691bodyClickListenerAdded = true;2692}2693}2694
2695const bodyClickListener = event => {2696for (let el = event.target; el && el !== document; el = el.parentNode) {2697for (const attr in clickHandlers) {2698const template = el.getAttribute(attr);2699
2700if (template) {2701clickHandlers[attr].fire({2702template
2703});2704return;2705}2706}2707}2708};2709
2710
2711
2712var staticMethods = /*#__PURE__*/Object.freeze({2713isValidParameter: isValidParameter,2714isUpdatableParameter: isUpdatableParameter,2715isDeprecatedParameter: isDeprecatedParameter,2716argsToParams: argsToParams,2717isVisible: isVisible$1,2718clickConfirm: clickConfirm,2719clickDeny: clickDeny,2720clickCancel: clickCancel,2721getContainer: getContainer,2722getPopup: getPopup,2723getTitle: getTitle,2724getHtmlContainer: getHtmlContainer,2725getImage: getImage,2726getIcon: getIcon,2727getInputLabel: getInputLabel,2728getCloseButton: getCloseButton,2729getActions: getActions,2730getConfirmButton: getConfirmButton,2731getDenyButton: getDenyButton,2732getCancelButton: getCancelButton,2733getLoader: getLoader,2734getFooter: getFooter,2735getTimerProgressBar: getTimerProgressBar,2736getFocusableElements: getFocusableElements,2737getValidationMessage: getValidationMessage,2738isLoading: isLoading,2739fire: fire,2740mixin: mixin,2741showLoading: showLoading,2742enableLoading: showLoading,2743getTimerLeft: getTimerLeft,2744stopTimer: stopTimer,2745resumeTimer: resumeTimer,2746toggleTimer: toggleTimer,2747increaseTimer: increaseTimer,2748isTimerRunning: isTimerRunning,2749bindClickHandler: bindClickHandler2750});2751
2752/**2753* Hides loader and shows back the button which was hidden by .showLoading()
2754*/
2755
2756function hideLoading() {2757// do nothing if popup is closed2758const innerParams = privateProps.innerParams.get(this);2759
2760if (!innerParams) {2761return;2762}2763
2764const domCache = privateProps.domCache.get(this);2765hide(domCache.loader);2766
2767if (isToast()) {2768if (innerParams.icon) {2769show(getIcon());2770}2771} else {2772showRelatedButton(domCache);2773}2774
2775removeClass([domCache.popup, domCache.actions], swalClasses.loading);2776domCache.popup.removeAttribute('aria-busy');2777domCache.popup.removeAttribute('data-loading');2778domCache.confirmButton.disabled = false;2779domCache.denyButton.disabled = false;2780domCache.cancelButton.disabled = false;2781}2782
2783const showRelatedButton = domCache => {2784const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'));2785
2786if (buttonToReplace.length) {2787show(buttonToReplace[0], 'inline-block');2788} else if (allButtonsAreHidden()) {2789hide(domCache.actions);2790}2791};2792
2793/**2794* Gets the input DOM node, this method works with input parameter.
2795* @returns {HTMLElement | null}
2796*/
2797
2798function getInput$1(instance) {2799const innerParams = privateProps.innerParams.get(instance || this);2800const domCache = privateProps.domCache.get(instance || this);2801
2802if (!domCache) {2803return null;2804}2805
2806return getInput(domCache.popup, innerParams.input);2807}2808
2809/**2810* This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
2811* For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
2812* This is the approach that Babel will probably take to implement private methods/fields
2813* https://github.com/tc39/proposal-private-methods
2814* https://github.com/babel/babel/pull/7555
2815* Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
2816* then we can use that language feature.
2817*/
2818var privateMethods = {2819swalPromiseResolve: new WeakMap(),2820swalPromiseReject: new WeakMap()2821};2822
2823/*2824* Instance method to close sweetAlert
2825*/
2826
2827function removePopupAndResetState(instance, container, returnFocus, didClose) {2828if (isToast()) {2829triggerDidCloseAndDispose(instance, didClose);2830} else {2831restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose));2832globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, {2833capture: globalState.keydownListenerCapture2834});2835globalState.keydownHandlerAdded = false;2836}2837
2838const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); // workaround for #20882839// for some reason removing the container in Safari will scroll the document to bottom2840
2841if (isSafari) {2842container.setAttribute('style', 'display:none !important');2843container.removeAttribute('class');2844container.innerHTML = '';2845} else {2846container.remove();2847}2848
2849if (isModal()) {2850undoScrollbar();2851undoIOSfix();2852unsetAriaHidden();2853}2854
2855removeBodyClasses();2856}2857
2858function removeBodyClasses() {2859removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]);2860}2861
2862function close(resolveValue) {2863resolveValue = prepareResolveValue(resolveValue);2864const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this);2865const didClose = triggerClosePopup(this);2866
2867if (this.isAwaitingPromise()) {2868// A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #23352869if (!resolveValue.isDismissed) {2870handleAwaitingPromise(this);2871swalPromiseResolve(resolveValue);2872}2873} else if (didClose) {2874// Resolve Swal promise2875swalPromiseResolve(resolveValue);2876}2877}2878function isAwaitingPromise() {2879return !!privateProps.awaitingPromise.get(this);2880}2881
2882const triggerClosePopup = instance => {2883const popup = getPopup();2884
2885if (!popup) {2886return false;2887}2888
2889const innerParams = privateProps.innerParams.get(instance);2890
2891if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) {2892return false;2893}2894
2895removeClass(popup, innerParams.showClass.popup);2896addClass(popup, innerParams.hideClass.popup);2897const backdrop = getContainer();2898removeClass(backdrop, innerParams.showClass.backdrop);2899addClass(backdrop, innerParams.hideClass.backdrop);2900handlePopupAnimation(instance, popup, innerParams);2901return true;2902};2903
2904function rejectPromise(error) {2905const rejectPromise = privateMethods.swalPromiseReject.get(this);2906handleAwaitingPromise(this);2907
2908if (rejectPromise) {2909// Reject Swal promise2910rejectPromise(error);2911}2912}2913
2914const handleAwaitingPromise = instance => {2915if (instance.isAwaitingPromise()) {2916privateProps.awaitingPromise.delete(instance); // The instance might have been previously partly destroyed, we must resume the destroy process in this case #23352917
2918if (!privateProps.innerParams.get(instance)) {2919instance._destroy();2920}2921}2922};2923
2924const prepareResolveValue = resolveValue => {2925// When user calls Swal.close()2926if (typeof resolveValue === 'undefined') {2927return {2928isConfirmed: false,2929isDenied: false,2930isDismissed: true2931};2932}2933
2934return Object.assign({2935isConfirmed: false,2936isDenied: false,2937isDismissed: false2938}, resolveValue);2939};2940
2941const handlePopupAnimation = (instance, popup, innerParams) => {2942const container = getContainer(); // If animation is supported, animate2943
2944const animationIsSupported = animationEndEvent && hasCssAnimation(popup);2945
2946if (typeof innerParams.willClose === 'function') {2947innerParams.willClose(popup);2948}2949
2950if (animationIsSupported) {2951animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose);2952} else {2953// Otherwise, remove immediately2954removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose);2955}2956};2957
2958const animatePopup = (instance, popup, container, returnFocus, didClose) => {2959globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose);2960popup.addEventListener(animationEndEvent, function (e) {2961if (e.target === popup) {2962globalState.swalCloseEventFinishedCallback();2963delete globalState.swalCloseEventFinishedCallback;2964}2965});2966};2967
2968const triggerDidCloseAndDispose = (instance, didClose) => {2969setTimeout(() => {2970if (typeof didClose === 'function') {2971didClose.bind(instance.params)();2972}2973
2974instance._destroy();2975});2976};2977
2978function setButtonsDisabled(instance, buttons, disabled) {2979const domCache = privateProps.domCache.get(instance);2980buttons.forEach(button => {2981domCache[button].disabled = disabled;2982});2983}2984
2985function setInputDisabled(input, disabled) {2986if (!input) {2987return false;2988}2989
2990if (input.type === 'radio') {2991const radiosContainer = input.parentNode.parentNode;2992const radios = radiosContainer.querySelectorAll('input');2993
2994for (let i = 0; i < radios.length; i++) {2995radios[i].disabled = disabled;2996}2997} else {2998input.disabled = disabled;2999}3000}3001
3002function enableButtons() {3003setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);3004}3005function disableButtons() {3006setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);3007}3008function enableInput() {3009return setInputDisabled(this.getInput(), false);3010}3011function disableInput() {3012return setInputDisabled(this.getInput(), true);3013}3014
3015function showValidationMessage(error) {3016const domCache = privateProps.domCache.get(this);3017const params = privateProps.innerParams.get(this);3018setInnerHtml(domCache.validationMessage, error);3019domCache.validationMessage.className = swalClasses['validation-message'];3020
3021if (params.customClass && params.customClass.validationMessage) {3022addClass(domCache.validationMessage, params.customClass.validationMessage);3023}3024
3025show(domCache.validationMessage);3026const input = this.getInput();3027
3028if (input) {3029input.setAttribute('aria-invalid', true);3030input.setAttribute('aria-describedby', swalClasses['validation-message']);3031focusInput(input);3032addClass(input, swalClasses.inputerror);3033}3034} // Hide block with validation message3035
3036function resetValidationMessage$1() {3037const domCache = privateProps.domCache.get(this);3038
3039if (domCache.validationMessage) {3040hide(domCache.validationMessage);3041}3042
3043const input = this.getInput();3044
3045if (input) {3046input.removeAttribute('aria-invalid');3047input.removeAttribute('aria-describedby');3048removeClass(input, swalClasses.inputerror);3049}3050}3051
3052function getProgressSteps$1() {3053const domCache = privateProps.domCache.get(this);3054return domCache.progressSteps;3055}3056
3057/**3058* Updates popup parameters.
3059*/
3060
3061function update(params) {3062const popup = getPopup();3063const innerParams = privateProps.innerParams.get(this);3064
3065if (!popup || hasClass(popup, innerParams.hideClass.popup)) {3066return 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.");3067}3068
3069const validUpdatableParams = filterValidParams(params);3070const updatedParams = Object.assign({}, innerParams, validUpdatableParams);3071render(this, updatedParams);3072privateProps.innerParams.set(this, updatedParams);3073Object.defineProperties(this, {3074params: {3075value: Object.assign({}, this.params, params),3076writable: false,3077enumerable: true3078}3079});3080}3081
3082const filterValidParams = params => {3083const validUpdatableParams = {};3084Object.keys(params).forEach(param => {3085if (isUpdatableParameter(param)) {3086validUpdatableParams[param] = params[param];3087} else {3088warn("Invalid parameter to update: \"".concat(param, "\". Updatable params are listed here: https://github.com/sweetalert2/sweetalert2/blob/master/src/utils/params.js\n\nIf you think this parameter should be updatable, request it here: https://github.com/sweetalert2/sweetalert2/issues/new?template=02_feature_request.md"));3089}3090});3091return validUpdatableParams;3092};3093
3094function _destroy() {3095const domCache = privateProps.domCache.get(this);3096const innerParams = privateProps.innerParams.get(this);3097
3098if (!innerParams) {3099disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #23353100
3101return; // This instance has already been destroyed3102} // Check if there is another Swal closing3103
3104
3105if (domCache.popup && globalState.swalCloseEventFinishedCallback) {3106globalState.swalCloseEventFinishedCallback();3107delete globalState.swalCloseEventFinishedCallback;3108} // Check if there is a swal disposal defer timer3109
3110
3111if (globalState.deferDisposalTimer) {3112clearTimeout(globalState.deferDisposalTimer);3113delete globalState.deferDisposalTimer;3114}3115
3116if (typeof innerParams.didDestroy === 'function') {3117innerParams.didDestroy();3118}3119
3120disposeSwal(this);3121}3122
3123const disposeSwal = instance => {3124disposeWeakMaps(instance); // Unset this.params so GC will dispose it (#1569)3125
3126delete instance.params; // Unset globalState props so GC will dispose globalState (#1569)3127
3128delete globalState.keydownHandler;3129delete globalState.keydownTarget; // Unset currentInstance3130
3131delete globalState.currentInstance;3132};3133
3134const disposeWeakMaps = instance => {3135// If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #23353136if (instance.isAwaitingPromise()) {3137unsetWeakMaps(privateProps, instance);3138privateProps.awaitingPromise.set(instance, true);3139} else {3140unsetWeakMaps(privateMethods, instance);3141unsetWeakMaps(privateProps, instance);3142}3143};3144
3145const unsetWeakMaps = (obj, instance) => {3146for (const i in obj) {3147obj[i].delete(instance);3148}3149};3150
3151
3152
3153var instanceMethods = /*#__PURE__*/Object.freeze({3154hideLoading: hideLoading,3155disableLoading: hideLoading,3156getInput: getInput$1,3157close: close,3158isAwaitingPromise: isAwaitingPromise,3159rejectPromise: rejectPromise,3160closePopup: close,3161closeModal: close,3162closeToast: close,3163enableButtons: enableButtons,3164disableButtons: disableButtons,3165enableInput: enableInput,3166disableInput: disableInput,3167showValidationMessage: showValidationMessage,3168resetValidationMessage: resetValidationMessage$1,3169getProgressSteps: getProgressSteps$1,3170update: update,3171_destroy: _destroy3172});3173
3174let currentInstance;3175
3176class SweetAlert {3177constructor() {3178// Prevent run in Node env3179if (typeof window === 'undefined') {3180return;3181}3182
3183currentInstance = this; // @ts-ignore3184
3185for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {3186args[_key] = arguments[_key];3187}3188
3189const outerParams = Object.freeze(this.constructor.argsToParams(args));3190Object.defineProperties(this, {3191params: {3192value: outerParams,3193writable: false,3194enumerable: true,3195configurable: true3196}3197}); // @ts-ignore3198
3199const promise = this._main(this.params);3200
3201privateProps.promise.set(this, promise);3202}3203
3204_main(userParams) {3205let mixinParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};3206showWarningsForParams(Object.assign({}, mixinParams, userParams));3207
3208if (globalState.currentInstance) {3209globalState.currentInstance._destroy();3210
3211if (isModal()) {3212unsetAriaHidden();3213}3214}3215
3216globalState.currentInstance = this;3217const innerParams = prepareParams(userParams, mixinParams);3218setParameters(innerParams);3219Object.freeze(innerParams); // clear the previous timer3220
3221if (globalState.timeout) {3222globalState.timeout.stop();3223delete globalState.timeout;3224} // clear the restore focus timeout3225
3226
3227clearTimeout(globalState.restoreFocusTimeout);3228const domCache = populateDomCache(this);3229render(this, innerParams);3230privateProps.innerParams.set(this, innerParams);3231return swalPromise(this, domCache, innerParams);3232} // `catch` cannot be the name of a module export, so we define our thenable methods here instead3233
3234
3235then(onFulfilled) {3236const promise = privateProps.promise.get(this);3237return promise.then(onFulfilled);3238}3239
3240finally(onFinally) {3241const promise = privateProps.promise.get(this);3242return promise.finally(onFinally);3243}3244
3245}3246
3247const swalPromise = (instance, domCache, innerParams) => {3248return new Promise((resolve, reject) => {3249// functions to handle all closings/dismissals3250const dismissWith = dismiss => {3251instance.closePopup({3252isDismissed: true,3253dismiss
3254});3255};3256
3257privateMethods.swalPromiseResolve.set(instance, resolve);3258privateMethods.swalPromiseReject.set(instance, reject);3259
3260domCache.confirmButton.onclick = () => handleConfirmButtonClick(instance);3261
3262domCache.denyButton.onclick = () => handleDenyButtonClick(instance);3263
3264domCache.cancelButton.onclick = () => handleCancelButtonClick(instance, dismissWith);3265
3266domCache.closeButton.onclick = () => dismissWith(DismissReason.close);3267
3268handlePopupClick(instance, domCache, dismissWith);3269addKeydownHandler(instance, globalState, innerParams, dismissWith);3270handleInputOptionsAndValue(instance, innerParams);3271openPopup(innerParams);3272setupTimer(globalState, innerParams, dismissWith);3273initFocus(domCache, innerParams); // Scroll container to top on open (#1247, #1946)3274
3275setTimeout(() => {3276domCache.container.scrollTop = 0;3277});3278});3279};3280
3281const prepareParams = (userParams, mixinParams) => {3282const templateParams = getTemplateParams(userParams);3283const params = Object.assign({}, defaultParams, mixinParams, templateParams, userParams); // precedence is described in #21313284
3285params.showClass = Object.assign({}, defaultParams.showClass, params.showClass);3286params.hideClass = Object.assign({}, defaultParams.hideClass, params.hideClass);3287return params;3288};3289
3290const populateDomCache = instance => {3291const domCache = {3292popup: getPopup(),3293container: getContainer(),3294actions: getActions(),3295confirmButton: getConfirmButton(),3296denyButton: getDenyButton(),3297cancelButton: getCancelButton(),3298loader: getLoader(),3299closeButton: getCloseButton(),3300validationMessage: getValidationMessage(),3301progressSteps: getProgressSteps()3302};3303privateProps.domCache.set(instance, domCache);3304return domCache;3305};3306
3307const setupTimer = (globalState$$1, innerParams, dismissWith) => {3308const timerProgressBar = getTimerProgressBar();3309hide(timerProgressBar);3310
3311if (innerParams.timer) {3312globalState$$1.timeout = new Timer(() => {3313dismissWith('timer');3314delete globalState$$1.timeout;3315}, innerParams.timer);3316
3317if (innerParams.timerProgressBar) {3318show(timerProgressBar);3319applyCustomClass(timerProgressBar, innerParams, 'timerProgressBar');3320setTimeout(() => {3321if (globalState$$1.timeout && globalState$$1.timeout.running) {3322// timer can be already stopped or unset at this point3323animateTimerProgressBar(innerParams.timer);3324}3325});3326}3327}3328};3329
3330const initFocus = (domCache, innerParams) => {3331if (innerParams.toast) {3332return;3333}3334
3335if (!callIfFunction(innerParams.allowEnterKey)) {3336return blurActiveElement();3337}3338
3339if (!focusButton(domCache, innerParams)) {3340setFocus(innerParams, -1, 1);3341}3342};3343
3344const focusButton = (domCache, innerParams) => {3345if (innerParams.focusDeny && isVisible(domCache.denyButton)) {3346domCache.denyButton.focus();3347return true;3348}3349
3350if (innerParams.focusCancel && isVisible(domCache.cancelButton)) {3351domCache.cancelButton.focus();3352return true;3353}3354
3355if (innerParams.focusConfirm && isVisible(domCache.confirmButton)) {3356domCache.confirmButton.focus();3357return true;3358}3359
3360return false;3361};3362
3363const blurActiveElement = () => {3364if (document.activeElement instanceof HTMLElement && typeof document.activeElement.blur === 'function') {3365document.activeElement.blur();3366}3367}; // Assign instance methods from src/instanceMethods/*.js to prototype3368
3369
3370Object.assign(SweetAlert.prototype, instanceMethods); // Assign static methods from src/staticMethods/*.js to constructor3371
3372Object.assign(SweetAlert, staticMethods); // Proxy to instance methods to constructor, for now, for backwards compatibility3373
3374Object.keys(instanceMethods).forEach(key => {3375SweetAlert[key] = function () {3376if (currentInstance) {3377return currentInstance[key](...arguments);3378}3379};3380});3381SweetAlert.DismissReason = DismissReason;3382SweetAlert.version = '11.4.0';3383
3384const Swal = SweetAlert; // @ts-ignore3385
3386Swal.default = Swal;3387
3388return Swal;3389
3390}));3391if (typeof this !== 'undefined' && this.Sweetalert2){ this.swal = this.sweetAlert = this.Swal = this.SweetAlert = this.Sweetalert2}3392