sweetalert2 11.2.2 → 11.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * sweetalert2 v11.2.2
2
+ * sweetalert2 v11.3.3
3
3
  * Released under the MIT License.
4
4
  */
5
5
  (function (global, factory) {
@@ -8,14 +8,6 @@
8
8
  (global = global || self, global.Sweetalert2 = factory());
9
9
  }(this, function () { 'use strict';
10
10
 
11
- const DismissReason = Object.freeze({
12
- cancel: 'cancel',
13
- backdrop: 'backdrop',
14
- close: 'close',
15
- esc: 'esc',
16
- timer: 'timer'
17
- });
18
-
19
11
  const consolePrefix = 'SweetAlert2:';
20
12
  /**
21
13
  * Filter the unique values into a new array
@@ -97,28 +89,161 @@
97
89
  const asPromise = arg => hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg);
98
90
  const isPromise = arg => arg && Promise.resolve(arg) === arg;
99
91
 
100
- const isJqueryElement = elem => typeof elem === 'object' && elem.jquery;
92
+ const defaultParams = {
93
+ title: '',
94
+ titleText: '',
95
+ text: '',
96
+ html: '',
97
+ footer: '',
98
+ icon: undefined,
99
+ iconColor: undefined,
100
+ iconHtml: undefined,
101
+ template: undefined,
102
+ toast: false,
103
+ showClass: {
104
+ popup: 'swal2-show',
105
+ backdrop: 'swal2-backdrop-show',
106
+ icon: 'swal2-icon-show'
107
+ },
108
+ hideClass: {
109
+ popup: 'swal2-hide',
110
+ backdrop: 'swal2-backdrop-hide',
111
+ icon: 'swal2-icon-hide'
112
+ },
113
+ customClass: {},
114
+ target: 'body',
115
+ color: undefined,
116
+ backdrop: true,
117
+ heightAuto: true,
118
+ allowOutsideClick: true,
119
+ allowEscapeKey: true,
120
+ allowEnterKey: true,
121
+ stopKeydownPropagation: true,
122
+ keydownListenerCapture: false,
123
+ showConfirmButton: true,
124
+ showDenyButton: false,
125
+ showCancelButton: false,
126
+ preConfirm: undefined,
127
+ preDeny: undefined,
128
+ confirmButtonText: 'OK',
129
+ confirmButtonAriaLabel: '',
130
+ confirmButtonColor: undefined,
131
+ denyButtonText: 'No',
132
+ denyButtonAriaLabel: '',
133
+ denyButtonColor: undefined,
134
+ cancelButtonText: 'Cancel',
135
+ cancelButtonAriaLabel: '',
136
+ cancelButtonColor: undefined,
137
+ buttonsStyling: true,
138
+ reverseButtons: false,
139
+ focusConfirm: true,
140
+ focusDeny: false,
141
+ focusCancel: false,
142
+ returnFocus: true,
143
+ showCloseButton: false,
144
+ closeButtonHtml: '×',
145
+ closeButtonAriaLabel: 'Close this dialog',
146
+ loaderHtml: '',
147
+ showLoaderOnConfirm: false,
148
+ showLoaderOnDeny: false,
149
+ imageUrl: undefined,
150
+ imageWidth: undefined,
151
+ imageHeight: undefined,
152
+ imageAlt: '',
153
+ timer: undefined,
154
+ timerProgressBar: false,
155
+ width: undefined,
156
+ padding: undefined,
157
+ background: undefined,
158
+ input: undefined,
159
+ inputPlaceholder: '',
160
+ inputLabel: '',
161
+ inputValue: '',
162
+ inputOptions: {},
163
+ inputAutoTrim: true,
164
+ inputAttributes: {},
165
+ inputValidator: undefined,
166
+ returnInputValueOnDeny: false,
167
+ validationMessage: undefined,
168
+ grow: false,
169
+ position: 'center',
170
+ progressSteps: [],
171
+ currentProgressStep: undefined,
172
+ progressStepsDistance: undefined,
173
+ willOpen: undefined,
174
+ didOpen: undefined,
175
+ didRender: undefined,
176
+ willClose: undefined,
177
+ didClose: undefined,
178
+ didDestroy: undefined,
179
+ scrollbarPadding: true
180
+ };
181
+ const 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'];
182
+ const deprecatedParams = {};
183
+ const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];
184
+ /**
185
+ * Is valid parameter
186
+ * @param {string} paramName
187
+ */
101
188
 
102
- const isElement = elem => elem instanceof Element || isJqueryElement(elem);
189
+ const isValidParameter = paramName => {
190
+ return Object.prototype.hasOwnProperty.call(defaultParams, paramName);
191
+ };
192
+ /**
193
+ * Is valid parameter for Swal.update() method
194
+ * @param {string} paramName
195
+ */
103
196
 
104
- const argsToParams = args => {
105
- const params = {};
197
+ const isUpdatableParameter = paramName => {
198
+ return updatableParams.indexOf(paramName) !== -1;
199
+ };
200
+ /**
201
+ * Is deprecated parameter
202
+ * @param {string} paramName
203
+ */
106
204
 
107
- if (typeof args[0] === 'object' && !isElement(args[0])) {
108
- Object.assign(params, args[0]);
109
- } else {
110
- ['title', 'html', 'icon'].forEach((name, index) => {
111
- const arg = args[index];
205
+ const isDeprecatedParameter = paramName => {
206
+ return deprecatedParams[paramName];
207
+ };
112
208
 
113
- if (typeof arg === 'string' || isElement(arg)) {
114
- params[name] = arg;
115
- } else if (arg !== undefined) {
116
- error("Unexpected type of ".concat(name, "! Expected \"string\" or \"Element\", got ").concat(typeof arg));
117
- }
118
- });
209
+ const checkIfParamIsValid = param => {
210
+ if (!isValidParameter(param)) {
211
+ warn("Unknown parameter \"".concat(param, "\""));
119
212
  }
213
+ };
120
214
 
121
- return params;
215
+ const checkIfToastParamIsValid = param => {
216
+ if (toastIncompatibleParams.includes(param)) {
217
+ warn("The parameter \"".concat(param, "\" is incompatible with toasts"));
218
+ }
219
+ };
220
+
221
+ const checkIfParamIsDeprecated = param => {
222
+ if (isDeprecatedParameter(param)) {
223
+ warnAboutDeprecation(param, isDeprecatedParameter(param));
224
+ }
225
+ };
226
+ /**
227
+ * Show relevant warnings for given params
228
+ *
229
+ * @param params
230
+ */
231
+
232
+
233
+ const showWarningsForParams = params => {
234
+ if (!params.backdrop && params.allowOutsideClick) {
235
+ warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
236
+ }
237
+
238
+ for (const param in params) {
239
+ checkIfParamIsValid(param);
240
+
241
+ if (params.toast) {
242
+ checkIfToastParamIsValid(param);
243
+ }
244
+
245
+ checkIfParamIsDeprecated(param);
246
+ }
122
247
  };
123
248
 
124
249
  const swalPrefix = 'swal2-';
@@ -134,6 +259,12 @@
134
259
  const 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']);
135
260
  const iconTypes = prefix(['success', 'warning', 'info', 'question', 'error']);
136
261
 
262
+ /**
263
+ * Gets the popup container which contains the backdrop and the popup itself.
264
+ *
265
+ * @returns {HTMLElement | null}
266
+ */
267
+
137
268
  const getContainer = () => document.body.querySelector(".".concat(swalClasses.container));
138
269
  const elementBySelector = selectorString => {
139
270
  const container = getContainer();
@@ -192,8 +323,15 @@
192
323
  const states = {
193
324
  previousBodyPadding: null
194
325
  };
326
+ /**
327
+ * Securely set innerHTML of an element
328
+ * https://github.com/sweetalert2/sweetalert2/issues/1926
329
+ *
330
+ * @param {HTMLElement} elem
331
+ * @param {string} html
332
+ */
333
+
195
334
  const setInnerHtml = (elem, html) => {
196
- // #1926
197
335
  elem.textContent = '';
198
336
 
199
337
  if (html) {
@@ -207,6 +345,12 @@
207
345
  });
208
346
  }
209
347
  };
348
+ /**
349
+ * @param {HTMLElement} elem
350
+ * @param {string} className
351
+ * @returns {boolean}
352
+ */
353
+
210
354
  const hasClass = (elem, className) => {
211
355
  if (!className) {
212
356
  return false;
@@ -242,6 +386,12 @@
242
386
  addClass(elem, params.customClass[className]);
243
387
  }
244
388
  };
389
+ /**
390
+ * @param {HTMLElement} popup
391
+ * @param {string} inputType
392
+ * @returns {HTMLInputElement | null}
393
+ */
394
+
245
395
  const getInput = (popup, inputType) => {
246
396
  if (!inputType) {
247
397
  return null;
@@ -251,21 +401,25 @@
251
401
  case 'select':
252
402
  case 'textarea':
253
403
  case 'file':
254
- return getChildByClass(popup, swalClasses[inputType]);
404
+ return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses[inputType]));
255
405
 
256
406
  case 'checkbox':
257
- return popup.querySelector(".".concat(swalClasses.checkbox, " input"));
407
+ return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.checkbox, " input"));
258
408
 
259
409
  case 'radio':
260
- return popup.querySelector(".".concat(swalClasses.radio, " input:checked")) || popup.querySelector(".".concat(swalClasses.radio, " input:first-child"));
410
+ return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.radio, " input:checked")) || popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.radio, " input:first-child"));
261
411
 
262
412
  case 'range':
263
- return popup.querySelector(".".concat(swalClasses.range, " input"));
413
+ return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.range, " input"));
264
414
 
265
415
  default:
266
- return getChildByClass(popup, swalClasses.input);
416
+ return popup.querySelector(".".concat(swalClasses.popup, " > .").concat(swalClasses.input));
267
417
  }
268
418
  };
419
+ /**
420
+ * @param {HTMLInputElement} input
421
+ */
422
+
269
423
  const focusInput = input => {
270
424
  input.focus(); // place cursor at end of text in text input
271
425
 
@@ -276,6 +430,12 @@
276
430
  input.value = val;
277
431
  }
278
432
  };
433
+ /**
434
+ * @param {HTMLElement | HTMLElement[] | null} target
435
+ * @param {string | string[]} classList
436
+ * @param {boolean} condition
437
+ */
438
+
279
439
  const toggleClass = (target, classList, condition) => {
280
440
  if (!target || !classList) {
281
441
  return;
@@ -286,7 +446,7 @@
286
446
  }
287
447
 
288
448
  classList.forEach(className => {
289
- if (target.forEach) {
449
+ if (Array.isArray(target)) {
290
450
  target.forEach(elem => {
291
451
  condition ? elem.classList.add(className) : elem.classList.remove(className);
292
452
  });
@@ -295,19 +455,45 @@
295
455
  }
296
456
  });
297
457
  };
458
+ /**
459
+ * @param {HTMLElement | HTMLElement[] | null} target
460
+ * @param {string | string[]} classList
461
+ */
462
+
298
463
  const addClass = (target, classList) => {
299
464
  toggleClass(target, classList, true);
300
465
  };
466
+ /**
467
+ * @param {HTMLElement | HTMLElement[] | null} target
468
+ * @param {string | string[]} classList
469
+ */
470
+
301
471
  const removeClass = (target, classList) => {
302
472
  toggleClass(target, classList, false);
303
473
  };
304
- const getChildByClass = (elem, className) => {
305
- for (let i = 0; i < elem.childNodes.length; i++) {
306
- if (hasClass(elem.childNodes[i], className)) {
307
- return elem.childNodes[i];
474
+ /**
475
+ * Get direct child of an element by class name
476
+ *
477
+ * @param {HTMLElement} elem
478
+ * @param {string} className
479
+ * @returns {HTMLElement | null}
480
+ */
481
+
482
+ const getDirectChildByClass = (elem, className) => {
483
+ const childNodes = toArray(elem.childNodes);
484
+
485
+ for (let i = 0; i < childNodes.length; i++) {
486
+ if (hasClass(childNodes[i], className)) {
487
+ return childNodes[i];
308
488
  }
309
489
  }
310
490
  };
491
+ /**
492
+ * @param {HTMLElement} elem
493
+ * @param {string} property
494
+ * @param {*} value
495
+ */
496
+
311
497
  const applyNumericalStyle = (elem, property, value) => {
312
498
  if (value === "".concat(parseInt(value))) {
313
499
  value = parseInt(value);
@@ -319,10 +505,19 @@
319
505
  elem.style.removeProperty(property);
320
506
  }
321
507
  };
508
+ /**
509
+ * @param {HTMLElement} elem
510
+ * @param {string} display
511
+ */
512
+
322
513
  const show = function (elem) {
323
514
  let display = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'flex';
324
515
  elem.style.display = display;
325
516
  };
517
+ /**
518
+ * @param {HTMLElement} elem
519
+ */
520
+
326
521
  const hide = elem => {
327
522
  elem.style.display = 'none';
328
523
  };
@@ -369,7 +564,7 @@
369
564
  timerProgressBar.style.removeProperty('transition');
370
565
  timerProgressBar.style.width = '100%';
371
566
  const timerProgressBarFullWidth = parseInt(window.getComputedStyle(timerProgressBar).width);
372
- const timerProgressBarPercent = parseInt(timerProgressBarWidth / timerProgressBarFullWidth * 100);
567
+ const timerProgressBarPercent = timerProgressBarWidth / timerProgressBarFullWidth * 100;
373
568
  timerProgressBar.style.removeProperty('transition');
374
569
  timerProgressBar.style.width = "".concat(timerProgressBarPercent, "%");
375
570
  };
@@ -377,6 +572,37 @@
377
572
  // Detect Node env
378
573
  const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined';
379
574
 
575
+ const RESTORE_FOCUS_TIMEOUT = 100;
576
+
577
+ const globalState = {};
578
+
579
+ const focusPreviousActiveElement = () => {
580
+ if (globalState.previousActiveElement && globalState.previousActiveElement.focus) {
581
+ globalState.previousActiveElement.focus();
582
+ globalState.previousActiveElement = null;
583
+ } else if (document.body) {
584
+ document.body.focus();
585
+ }
586
+ }; // Restore previous active (focused) element
587
+
588
+
589
+ const restoreActiveElement = returnFocus => {
590
+ return new Promise(resolve => {
591
+ if (!returnFocus) {
592
+ return resolve();
593
+ }
594
+
595
+ const x = window.scrollX;
596
+ const y = window.scrollY;
597
+ globalState.restoreFocusTimeout = setTimeout(() => {
598
+ focusPreviousActiveElement();
599
+ resolve();
600
+ }, RESTORE_FOCUS_TIMEOUT); // issues/900
601
+
602
+ window.scrollTo(x, y);
603
+ });
604
+ };
605
+
380
606
  const 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, '');
381
607
 
382
608
  const resetOldContainer = () => {
@@ -392,20 +618,18 @@
392
618
  };
393
619
 
394
620
  const resetValidationMessage = () => {
395
- if (Swal.isVisible()) {
396
- Swal.resetValidationMessage();
397
- }
621
+ globalState.currentInstance.resetValidationMessage();
398
622
  };
399
623
 
400
624
  const addInputChangeListeners = () => {
401
625
  const popup = getPopup();
402
- const input = getChildByClass(popup, swalClasses.input);
403
- const file = getChildByClass(popup, swalClasses.file);
626
+ const input = getDirectChildByClass(popup, swalClasses.input);
627
+ const file = getDirectChildByClass(popup, swalClasses.file);
404
628
  const range = popup.querySelector(".".concat(swalClasses.range, " input"));
405
629
  const rangeOutput = popup.querySelector(".".concat(swalClasses.range, " output"));
406
- const select = getChildByClass(popup, swalClasses.select);
630
+ const select = getDirectChildByClass(popup, swalClasses.select);
407
631
  const checkbox = popup.querySelector(".".concat(swalClasses.checkbox, " input"));
408
- const textarea = getChildByClass(popup, swalClasses.textarea);
632
+ const textarea = getDirectChildByClass(popup, swalClasses.textarea);
409
633
  input.oninput = resetValidationMessage;
410
634
  file.onchange = resetValidationMessage;
411
635
  select.onchange = resetValidationMessage;
@@ -677,7 +901,7 @@
677
901
  const rerender = !innerParams || params.input !== innerParams.input;
678
902
  inputTypes.forEach(inputType => {
679
903
  const inputClass = swalClasses[inputType];
680
- const inputContainer = getChildByClass(popup, inputClass); // set attributes
904
+ const inputContainer = getDirectChildByClass(popup, inputClass); // set attributes
681
905
 
682
906
  setAttributes(inputType, params.inputAttributes); // set class
683
907
 
@@ -765,7 +989,7 @@
765
989
 
766
990
  const getInputContainer = inputType => {
767
991
  const inputClass = swalClasses[inputType] ? swalClasses[inputType] : swalClasses.input;
768
- return getChildByClass(getPopup(), inputClass);
992
+ return getDirectChildByClass(getPopup(), inputClass);
769
993
  };
770
994
 
771
995
  const renderInputType = {};
@@ -821,8 +1045,9 @@
821
1045
  };
822
1046
 
823
1047
  renderInputType.checkbox = (checkboxContainer, params) => {
1048
+ /** @type {HTMLInputElement} */
824
1049
  const checkbox = getInput(getPopup(), 'checkbox');
825
- checkbox.value = 1;
1050
+ checkbox.value = '1';
826
1051
  checkbox.id = swalClasses.checkbox;
827
1052
  checkbox.checked = Boolean(params.inputValue);
828
1053
  const label = checkboxContainer.querySelector('span');
@@ -1087,7 +1312,12 @@
1087
1312
  } // Padding
1088
1313
 
1089
1314
 
1090
- applyNumericalStyle(popup, 'padding', params.padding); // Background
1315
+ applyNumericalStyle(popup, 'padding', params.padding); // Color
1316
+
1317
+ if (params.color) {
1318
+ popup.style.color = params.color;
1319
+ } // Background
1320
+
1091
1321
 
1092
1322
  if (params.background) {
1093
1323
  popup.style.background = params.background;
@@ -1139,587 +1369,13 @@
1139
1369
  }
1140
1370
  };
1141
1371
 
1142
- /*
1143
- * Global function to determine if SweetAlert2 popup is shown
1144
- */
1145
-
1146
- const isVisible$1 = () => {
1147
- return isVisible(getPopup());
1148
- };
1149
- /*
1150
- * Global function to click 'Confirm' button
1151
- */
1152
-
1153
- const clickConfirm = () => getConfirmButton() && getConfirmButton().click();
1154
- /*
1155
- * Global function to click 'Deny' button
1156
- */
1157
-
1158
- const clickDeny = () => getDenyButton() && getDenyButton().click();
1159
- /*
1160
- * Global function to click 'Cancel' button
1161
- */
1162
-
1163
- const clickCancel = () => getCancelButton() && getCancelButton().click();
1164
-
1165
- function fire() {
1166
- const Swal = this;
1167
-
1168
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1169
- args[_key] = arguments[_key];
1170
- }
1171
-
1172
- return new Swal(...args);
1173
- }
1174
-
1175
- /**
1176
- * Returns an extended version of `Swal` containing `params` as defaults.
1177
- * Useful for reusing Swal configuration.
1178
- *
1179
- * For example:
1180
- *
1181
- * Before:
1182
- * const textPromptOptions = { input: 'text', showCancelButton: true }
1183
- * const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' })
1184
- * const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' })
1185
- *
1186
- * After:
1187
- * const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true })
1188
- * const {value: firstName} = await TextPrompt('What is your first name?')
1189
- * const {value: lastName} = await TextPrompt('What is your last name?')
1190
- *
1191
- * @param mixinParams
1192
- */
1193
- function mixin(mixinParams) {
1194
- class MixinSwal extends this {
1195
- _main(params, priorityMixinParams) {
1196
- return super._main(params, Object.assign({}, mixinParams, priorityMixinParams));
1197
- }
1198
-
1199
- }
1200
-
1201
- return MixinSwal;
1202
- }
1203
-
1204
- /**
1205
- * Shows loader (spinner), this is useful with AJAX requests.
1206
- * By default the loader be shown instead of the "Confirm" button.
1207
- */
1208
-
1209
- const showLoading = buttonToReplace => {
1210
- let popup = getPopup();
1211
-
1212
- if (!popup) {
1213
- Swal.fire();
1214
- }
1215
-
1216
- popup = getPopup();
1217
- const loader = getLoader();
1218
-
1219
- if (isToast()) {
1220
- hide(getIcon());
1221
- } else {
1222
- replaceButton(popup, buttonToReplace);
1223
- }
1224
-
1225
- show(loader);
1226
- popup.setAttribute('data-loading', true);
1227
- popup.setAttribute('aria-busy', true);
1228
- popup.focus();
1229
- };
1230
-
1231
- const replaceButton = (popup, buttonToReplace) => {
1232
- const actions = getActions();
1233
- const loader = getLoader();
1234
-
1235
- if (!buttonToReplace && isVisible(getConfirmButton())) {
1236
- buttonToReplace = getConfirmButton();
1237
- }
1238
-
1239
- show(actions);
1240
-
1241
- if (buttonToReplace) {
1242
- hide(buttonToReplace);
1243
- loader.setAttribute('data-button-to-replace', buttonToReplace.className);
1244
- }
1245
-
1246
- loader.parentNode.insertBefore(loader, buttonToReplace);
1247
- addClass([popup, actions], swalClasses.loading);
1248
- };
1249
-
1250
- const RESTORE_FOCUS_TIMEOUT = 100;
1251
-
1252
- const globalState = {};
1253
-
1254
- const focusPreviousActiveElement = () => {
1255
- if (globalState.previousActiveElement && globalState.previousActiveElement.focus) {
1256
- globalState.previousActiveElement.focus();
1257
- globalState.previousActiveElement = null;
1258
- } else if (document.body) {
1259
- document.body.focus();
1260
- }
1261
- }; // Restore previous active (focused) element
1262
-
1263
-
1264
- const restoreActiveElement = returnFocus => {
1265
- return new Promise(resolve => {
1266
- if (!returnFocus) {
1267
- return resolve();
1268
- }
1269
-
1270
- const x = window.scrollX;
1271
- const y = window.scrollY;
1272
- globalState.restoreFocusTimeout = setTimeout(() => {
1273
- focusPreviousActiveElement();
1274
- resolve();
1275
- }, RESTORE_FOCUS_TIMEOUT); // issues/900
1276
-
1277
- window.scrollTo(x, y);
1278
- });
1279
- };
1280
-
1281
- /**
1282
- * If `timer` parameter is set, returns number of milliseconds of timer remained.
1283
- * Otherwise, returns undefined.
1284
- */
1285
-
1286
- const getTimerLeft = () => {
1287
- return globalState.timeout && globalState.timeout.getTimerLeft();
1288
- };
1289
- /**
1290
- * Stop timer. Returns number of milliseconds of timer remained.
1291
- * If `timer` parameter isn't set, returns undefined.
1292
- */
1293
-
1294
- const stopTimer = () => {
1295
- if (globalState.timeout) {
1296
- stopTimerProgressBar();
1297
- return globalState.timeout.stop();
1298
- }
1299
- };
1300
- /**
1301
- * Resume timer. Returns number of milliseconds of timer remained.
1302
- * If `timer` parameter isn't set, returns undefined.
1303
- */
1304
-
1305
- const resumeTimer = () => {
1306
- if (globalState.timeout) {
1307
- const remaining = globalState.timeout.start();
1308
- animateTimerProgressBar(remaining);
1309
- return remaining;
1310
- }
1311
- };
1312
- /**
1313
- * Resume timer. Returns number of milliseconds of timer remained.
1314
- * If `timer` parameter isn't set, returns undefined.
1315
- */
1316
-
1317
- const toggleTimer = () => {
1318
- const timer = globalState.timeout;
1319
- return timer && (timer.running ? stopTimer() : resumeTimer());
1320
- };
1321
- /**
1322
- * Increase timer. Returns number of milliseconds of an updated timer.
1323
- * If `timer` parameter isn't set, returns undefined.
1324
- */
1325
-
1326
- const increaseTimer = n => {
1327
- if (globalState.timeout) {
1328
- const remaining = globalState.timeout.increase(n);
1329
- animateTimerProgressBar(remaining, true);
1330
- return remaining;
1331
- }
1332
- };
1333
- /**
1334
- * Check if timer is running. Returns true if timer is running
1335
- * or false if timer is paused or stopped.
1336
- * If `timer` parameter isn't set, returns undefined
1337
- */
1338
-
1339
- const isTimerRunning = () => {
1340
- return globalState.timeout && globalState.timeout.isRunning();
1341
- };
1342
-
1343
- let bodyClickListenerAdded = false;
1344
- const clickHandlers = {};
1345
- function bindClickHandler() {
1346
- let attr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'data-swal-template';
1347
- clickHandlers[attr] = this;
1348
-
1349
- if (!bodyClickListenerAdded) {
1350
- document.body.addEventListener('click', bodyClickListener);
1351
- bodyClickListenerAdded = true;
1352
- }
1353
- }
1354
-
1355
- const bodyClickListener = event => {
1356
- for (let el = event.target; el && el !== document; el = el.parentNode) {
1357
- for (const attr in clickHandlers) {
1358
- const template = el.getAttribute(attr);
1359
-
1360
- if (template) {
1361
- clickHandlers[attr].fire({
1362
- template
1363
- });
1364
- return;
1365
- }
1366
- }
1367
- }
1368
- };
1369
-
1370
- const defaultParams = {
1371
- title: '',
1372
- titleText: '',
1373
- text: '',
1374
- html: '',
1375
- footer: '',
1376
- icon: undefined,
1377
- iconColor: undefined,
1378
- iconHtml: undefined,
1379
- template: undefined,
1380
- toast: false,
1381
- showClass: {
1382
- popup: 'swal2-show',
1383
- backdrop: 'swal2-backdrop-show',
1384
- icon: 'swal2-icon-show'
1385
- },
1386
- hideClass: {
1387
- popup: 'swal2-hide',
1388
- backdrop: 'swal2-backdrop-hide',
1389
- icon: 'swal2-icon-hide'
1390
- },
1391
- customClass: {},
1392
- target: 'body',
1393
- backdrop: true,
1394
- heightAuto: true,
1395
- allowOutsideClick: true,
1396
- allowEscapeKey: true,
1397
- allowEnterKey: true,
1398
- stopKeydownPropagation: true,
1399
- keydownListenerCapture: false,
1400
- showConfirmButton: true,
1401
- showDenyButton: false,
1402
- showCancelButton: false,
1403
- preConfirm: undefined,
1404
- preDeny: undefined,
1405
- confirmButtonText: 'OK',
1406
- confirmButtonAriaLabel: '',
1407
- confirmButtonColor: undefined,
1408
- denyButtonText: 'No',
1409
- denyButtonAriaLabel: '',
1410
- denyButtonColor: undefined,
1411
- cancelButtonText: 'Cancel',
1412
- cancelButtonAriaLabel: '',
1413
- cancelButtonColor: undefined,
1414
- buttonsStyling: true,
1415
- reverseButtons: false,
1416
- focusConfirm: true,
1417
- focusDeny: false,
1418
- focusCancel: false,
1419
- returnFocus: true,
1420
- showCloseButton: false,
1421
- closeButtonHtml: '&times;',
1422
- closeButtonAriaLabel: 'Close this dialog',
1423
- loaderHtml: '',
1424
- showLoaderOnConfirm: false,
1425
- showLoaderOnDeny: false,
1426
- imageUrl: undefined,
1427
- imageWidth: undefined,
1428
- imageHeight: undefined,
1429
- imageAlt: '',
1430
- timer: undefined,
1431
- timerProgressBar: false,
1432
- width: undefined,
1433
- padding: undefined,
1434
- background: undefined,
1435
- input: undefined,
1436
- inputPlaceholder: '',
1437
- inputLabel: '',
1438
- inputValue: '',
1439
- inputOptions: {},
1440
- inputAutoTrim: true,
1441
- inputAttributes: {},
1442
- inputValidator: undefined,
1443
- returnInputValueOnDeny: false,
1444
- validationMessage: undefined,
1445
- grow: false,
1446
- position: 'center',
1447
- progressSteps: [],
1448
- currentProgressStep: undefined,
1449
- progressStepsDistance: undefined,
1450
- willOpen: undefined,
1451
- didOpen: undefined,
1452
- didRender: undefined,
1453
- willClose: undefined,
1454
- didClose: undefined,
1455
- didDestroy: undefined,
1456
- scrollbarPadding: true
1457
- };
1458
- const updatableParams = ['allowEscapeKey', 'allowOutsideClick', 'background', 'buttonsStyling', 'cancelButtonAriaLabel', 'cancelButtonColor', 'cancelButtonText', 'closeButtonAriaLabel', 'closeButtonHtml', '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'];
1459
- const deprecatedParams = {};
1460
- const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];
1461
- /**
1462
- * Is valid parameter
1463
- * @param {String} paramName
1464
- */
1465
-
1466
- const isValidParameter = paramName => {
1467
- return Object.prototype.hasOwnProperty.call(defaultParams, paramName);
1468
- };
1469
- /**
1470
- * Is valid parameter for Swal.update() method
1471
- * @param {String} paramName
1472
- */
1473
-
1474
- const isUpdatableParameter = paramName => {
1475
- return updatableParams.indexOf(paramName) !== -1;
1476
- };
1477
- /**
1478
- * Is deprecated parameter
1479
- * @param {String} paramName
1480
- */
1481
-
1482
- const isDeprecatedParameter = paramName => {
1483
- return deprecatedParams[paramName];
1484
- };
1485
-
1486
- const checkIfParamIsValid = param => {
1487
- if (!isValidParameter(param)) {
1488
- warn("Unknown parameter \"".concat(param, "\""));
1489
- }
1490
- };
1491
-
1492
- const checkIfToastParamIsValid = param => {
1493
- if (toastIncompatibleParams.includes(param)) {
1494
- warn("The parameter \"".concat(param, "\" is incompatible with toasts"));
1495
- }
1496
- };
1497
-
1498
- const checkIfParamIsDeprecated = param => {
1499
- if (isDeprecatedParameter(param)) {
1500
- warnAboutDeprecation(param, isDeprecatedParameter(param));
1501
- }
1502
- };
1503
- /**
1504
- * Show relevant warnings for given params
1505
- *
1506
- * @param params
1507
- */
1508
-
1509
-
1510
- const showWarningsForParams = params => {
1511
- if (!params.backdrop && params.allowOutsideClick) {
1512
- warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
1513
- }
1514
-
1515
- for (const param in params) {
1516
- checkIfParamIsValid(param);
1517
-
1518
- if (params.toast) {
1519
- checkIfToastParamIsValid(param);
1520
- }
1521
-
1522
- checkIfParamIsDeprecated(param);
1523
- }
1524
- };
1525
-
1526
-
1527
-
1528
- var staticMethods = /*#__PURE__*/Object.freeze({
1529
- isValidParameter: isValidParameter,
1530
- isUpdatableParameter: isUpdatableParameter,
1531
- isDeprecatedParameter: isDeprecatedParameter,
1532
- argsToParams: argsToParams,
1533
- isVisible: isVisible$1,
1534
- clickConfirm: clickConfirm,
1535
- clickDeny: clickDeny,
1536
- clickCancel: clickCancel,
1537
- getContainer: getContainer,
1538
- getPopup: getPopup,
1539
- getTitle: getTitle,
1540
- getHtmlContainer: getHtmlContainer,
1541
- getImage: getImage,
1542
- getIcon: getIcon,
1543
- getInputLabel: getInputLabel,
1544
- getCloseButton: getCloseButton,
1545
- getActions: getActions,
1546
- getConfirmButton: getConfirmButton,
1547
- getDenyButton: getDenyButton,
1548
- getCancelButton: getCancelButton,
1549
- getLoader: getLoader,
1550
- getFooter: getFooter,
1551
- getTimerProgressBar: getTimerProgressBar,
1552
- getFocusableElements: getFocusableElements,
1553
- getValidationMessage: getValidationMessage,
1554
- isLoading: isLoading,
1555
- fire: fire,
1556
- mixin: mixin,
1557
- showLoading: showLoading,
1558
- enableLoading: showLoading,
1559
- getTimerLeft: getTimerLeft,
1560
- stopTimer: stopTimer,
1561
- resumeTimer: resumeTimer,
1562
- toggleTimer: toggleTimer,
1563
- increaseTimer: increaseTimer,
1564
- isTimerRunning: isTimerRunning,
1565
- bindClickHandler: bindClickHandler
1566
- });
1567
-
1568
- /**
1569
- * Hides loader and shows back the button which was hidden by .showLoading()
1570
- */
1571
-
1572
- function hideLoading() {
1573
- // do nothing if popup is closed
1574
- const innerParams = privateProps.innerParams.get(this);
1575
-
1576
- if (!innerParams) {
1577
- return;
1578
- }
1579
-
1580
- const domCache = privateProps.domCache.get(this);
1581
- hide(domCache.loader);
1582
-
1583
- if (isToast()) {
1584
- if (innerParams.icon) {
1585
- show(getIcon());
1586
- }
1587
- } else {
1588
- showRelatedButton(domCache);
1589
- }
1590
-
1591
- removeClass([domCache.popup, domCache.actions], swalClasses.loading);
1592
- domCache.popup.removeAttribute('aria-busy');
1593
- domCache.popup.removeAttribute('data-loading');
1594
- domCache.confirmButton.disabled = false;
1595
- domCache.denyButton.disabled = false;
1596
- domCache.cancelButton.disabled = false;
1597
- }
1598
-
1599
- const showRelatedButton = domCache => {
1600
- const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'));
1601
-
1602
- if (buttonToReplace.length) {
1603
- show(buttonToReplace[0], 'inline-block');
1604
- } else if (allButtonsAreHidden()) {
1605
- hide(domCache.actions);
1606
- }
1607
- };
1608
-
1609
- function getInput$1(instance) {
1610
- const innerParams = privateProps.innerParams.get(instance || this);
1611
- const domCache = privateProps.domCache.get(instance || this);
1612
-
1613
- if (!domCache) {
1614
- return null;
1615
- }
1616
-
1617
- return getInput(domCache.popup, innerParams.input);
1618
- }
1619
-
1620
- const fixScrollbar = () => {
1621
- // for queues, do not do this more than once
1622
- if (states.previousBodyPadding !== null) {
1623
- return;
1624
- } // if the body has overflow
1625
-
1626
-
1627
- if (document.body.scrollHeight > window.innerHeight) {
1628
- // add padding so the content doesn't shift after removal of scrollbar
1629
- states.previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'));
1630
- document.body.style.paddingRight = "".concat(states.previousBodyPadding + measureScrollbar(), "px");
1631
- }
1632
- };
1633
- const undoScrollbar = () => {
1634
- if (states.previousBodyPadding !== null) {
1635
- document.body.style.paddingRight = "".concat(states.previousBodyPadding, "px");
1636
- states.previousBodyPadding = null;
1637
- }
1638
- };
1639
-
1640
- /* istanbul ignore file */
1641
-
1642
- const iOSfix = () => {
1643
- const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream || navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
1644
-
1645
- if (iOS && !hasClass(document.body, swalClasses.iosfix)) {
1646
- const offset = document.body.scrollTop;
1647
- document.body.style.top = "".concat(offset * -1, "px");
1648
- addClass(document.body, swalClasses.iosfix);
1649
- lockBodyScroll();
1650
- addBottomPaddingForTallPopups(); // #1948
1651
- }
1652
- };
1653
-
1654
- const addBottomPaddingForTallPopups = () => {
1655
- const safari = !navigator.userAgent.match(/(CriOS|FxiOS|EdgiOS|YaBrowser|UCBrowser)/i);
1656
-
1657
- if (safari) {
1658
- const bottomPanelHeight = 44;
1659
-
1660
- if (getPopup().scrollHeight > window.innerHeight - bottomPanelHeight) {
1661
- getContainer().style.paddingBottom = "".concat(bottomPanelHeight, "px");
1662
- }
1663
- }
1664
- };
1665
-
1666
- const lockBodyScroll = () => {
1667
- // #1246
1668
- const container = getContainer();
1669
- let preventTouchMove;
1670
-
1671
- container.ontouchstart = e => {
1672
- preventTouchMove = shouldPreventTouchMove(e);
1673
- };
1674
-
1675
- container.ontouchmove = e => {
1676
- if (preventTouchMove) {
1677
- e.preventDefault();
1678
- e.stopPropagation();
1679
- }
1680
- };
1681
- };
1682
-
1683
- const shouldPreventTouchMove = event => {
1684
- const target = event.target;
1685
- const container = getContainer();
1686
-
1687
- if (isStylys(event) || isZoom(event)) {
1688
- return false;
1689
- }
1690
-
1691
- if (target === container) {
1692
- return true;
1693
- }
1694
-
1695
- if (!isScrollable(container) && target.tagName !== 'INPUT' && // #1603
1696
- target.tagName !== 'TEXTAREA' && // #2266
1697
- !(isScrollable(getHtmlContainer()) && // #1944
1698
- getHtmlContainer().contains(target))) {
1699
- return true;
1700
- }
1701
-
1702
- return false;
1703
- };
1704
-
1705
- const isStylys = event => {
1706
- // #1786
1707
- return event.touches && event.touches.length && event.touches[0].touchType === 'stylus';
1708
- };
1709
-
1710
- const isZoom = event => {
1711
- // #1891
1712
- return event.touches && event.touches.length > 1;
1713
- };
1714
-
1715
- const undoIOSfix = () => {
1716
- if (hasClass(document.body, swalClasses.iosfix)) {
1717
- const offset = parseInt(document.body.style.top, 10);
1718
- removeClass(document.body, swalClasses.iosfix);
1719
- document.body.style.top = '';
1720
- document.body.scrollTop = offset * -1;
1721
- }
1722
- };
1372
+ const DismissReason = Object.freeze({
1373
+ cancel: 'cancel',
1374
+ backdrop: 'backdrop',
1375
+ close: 'close',
1376
+ esc: 'esc',
1377
+ timer: 'timer'
1378
+ });
1723
1379
 
1724
1380
  // Adding aria-hidden="true" to elements outside of the active modal dialog ensures that
1725
1381
  // elements not within the active modal dialog will not be surfaced if a user opens a screen
@@ -1751,312 +1407,177 @@
1751
1407
  });
1752
1408
  };
1753
1409
 
1754
- /**
1755
- * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
1756
- * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
1757
- * This is the approach that Babel will probably take to implement private methods/fields
1758
- * https://github.com/tc39/proposal-private-methods
1759
- * https://github.com/babel/babel/pull/7555
1760
- * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
1761
- * then we can use that language feature.
1762
- */
1763
- var privateMethods = {
1764
- swalPromiseResolve: new WeakMap(),
1765
- swalPromiseReject: new WeakMap()
1766
- };
1767
-
1768
- /*
1769
- * Instance method to close sweetAlert
1770
- */
1771
-
1772
- function removePopupAndResetState(instance, container, returnFocus, didClose) {
1773
- if (isToast()) {
1774
- triggerDidCloseAndDispose(instance, didClose);
1775
- } else {
1776
- restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose));
1777
- globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, {
1778
- capture: globalState.keydownListenerCapture
1779
- });
1780
- globalState.keydownHandlerAdded = false;
1781
- }
1782
-
1783
- const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); // workaround for #2088
1784
- // for some reason removing the container in Safari will scroll the document to bottom
1785
-
1786
- if (isSafari) {
1787
- container.setAttribute('style', 'display:none !important');
1788
- container.removeAttribute('class');
1789
- container.innerHTML = '';
1790
- } else {
1791
- container.remove();
1792
- }
1793
-
1794
- if (isModal()) {
1795
- undoScrollbar();
1796
- undoIOSfix();
1797
- unsetAriaHidden();
1798
- }
1799
-
1800
- removeBodyClasses();
1801
- }
1802
-
1803
- function removeBodyClasses() {
1804
- removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]);
1805
- }
1806
-
1807
- function close(resolveValue) {
1808
- resolveValue = prepareResolveValue(resolveValue);
1809
- const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this);
1810
- const didClose = triggerClosePopup(this);
1811
-
1812
- if (this.isAwaitingPromise()) {
1813
- // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
1814
- if (!resolveValue.isDismissed) {
1815
- handleAwaitingPromise(this);
1816
- swalPromiseResolve(resolveValue);
1817
- }
1818
- } else if (didClose) {
1819
- // Resolve Swal promise
1820
- swalPromiseResolve(resolveValue);
1821
- }
1822
- }
1823
- function isAwaitingPromise() {
1824
- return !!privateProps.awaitingPromise.get(this);
1825
- }
1826
-
1827
- const triggerClosePopup = instance => {
1828
- const popup = getPopup();
1829
-
1830
- if (!popup) {
1831
- return false;
1832
- }
1833
-
1834
- const innerParams = privateProps.innerParams.get(instance);
1410
+ const swalStringParams = ['swal-title', 'swal-html', 'swal-footer'];
1411
+ const getTemplateParams = params => {
1412
+ const template = typeof params.template === 'string' ? document.querySelector(params.template) : params.template;
1835
1413
 
1836
- if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) {
1837
- return false;
1414
+ if (!template) {
1415
+ return {};
1838
1416
  }
1839
1417
 
1840
- removeClass(popup, innerParams.showClass.popup);
1841
- addClass(popup, innerParams.hideClass.popup);
1842
- const backdrop = getContainer();
1843
- removeClass(backdrop, innerParams.showClass.backdrop);
1844
- addClass(backdrop, innerParams.hideClass.backdrop);
1845
- handlePopupAnimation(instance, popup, innerParams);
1846
- return true;
1418
+ const templateContent = template.content;
1419
+ showWarningsForElements(templateContent);
1420
+ const result = Object.assign(getSwalParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams));
1421
+ return result;
1847
1422
  };
1848
1423
 
1849
- function rejectPromise(error) {
1850
- const rejectPromise = privateMethods.swalPromiseReject.get(this);
1851
- handleAwaitingPromise(this);
1852
-
1853
- if (rejectPromise) {
1854
- // Reject Swal promise
1855
- rejectPromise(error);
1856
- }
1857
- }
1858
-
1859
- const handleAwaitingPromise = instance => {
1860
- if (instance.isAwaitingPromise()) {
1861
- privateProps.awaitingPromise.delete(instance); // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
1424
+ const getSwalParams = templateContent => {
1425
+ const result = {};
1426
+ toArray(templateContent.querySelectorAll('swal-param')).forEach(param => {
1427
+ showWarningsForAttributes(param, ['name', 'value']);
1428
+ const paramName = param.getAttribute('name');
1429
+ let value = param.getAttribute('value');
1862
1430
 
1863
- if (!privateProps.innerParams.get(instance)) {
1864
- instance._destroy();
1431
+ if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {
1432
+ value = false;
1865
1433
  }
1866
- }
1867
- };
1868
1434
 
1869
- const prepareResolveValue = resolveValue => {
1870
- // When user calls Swal.close()
1871
- if (typeof resolveValue === 'undefined') {
1872
- return {
1873
- isConfirmed: false,
1874
- isDenied: false,
1875
- isDismissed: true
1876
- };
1877
- }
1435
+ if (typeof defaultParams[paramName] === 'object') {
1436
+ value = JSON.parse(value);
1437
+ }
1878
1438
 
1879
- return Object.assign({
1880
- isConfirmed: false,
1881
- isDenied: false,
1882
- isDismissed: false
1883
- }, resolveValue);
1439
+ result[paramName] = value;
1440
+ });
1441
+ return result;
1884
1442
  };
1885
1443
 
1886
- const handlePopupAnimation = (instance, popup, innerParams) => {
1887
- const container = getContainer(); // If animation is supported, animate
1888
-
1889
- const animationIsSupported = animationEndEvent && hasCssAnimation(popup);
1890
-
1891
- if (typeof innerParams.willClose === 'function') {
1892
- innerParams.willClose(popup);
1893
- }
1894
-
1895
- if (animationIsSupported) {
1896
- animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose);
1897
- } else {
1898
- // Otherwise, remove immediately
1899
- removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose);
1900
- }
1901
- };
1444
+ const getSwalButtons = templateContent => {
1445
+ const result = {};
1446
+ toArray(templateContent.querySelectorAll('swal-button')).forEach(button => {
1447
+ showWarningsForAttributes(button, ['type', 'color', 'aria-label']);
1448
+ const type = button.getAttribute('type');
1449
+ result["".concat(type, "ButtonText")] = button.innerHTML;
1450
+ result["show".concat(capitalizeFirstLetter(type), "Button")] = true;
1902
1451
 
1903
- const animatePopup = (instance, popup, container, returnFocus, didClose) => {
1904
- globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose);
1905
- popup.addEventListener(animationEndEvent, function (e) {
1906
- if (e.target === popup) {
1907
- globalState.swalCloseEventFinishedCallback();
1908
- delete globalState.swalCloseEventFinishedCallback;
1452
+ if (button.hasAttribute('color')) {
1453
+ result["".concat(type, "ButtonColor")] = button.getAttribute('color');
1909
1454
  }
1910
- });
1911
- };
1912
1455
 
1913
- const triggerDidCloseAndDispose = (instance, didClose) => {
1914
- setTimeout(() => {
1915
- if (typeof didClose === 'function') {
1916
- didClose.bind(instance.params)();
1456
+ if (button.hasAttribute('aria-label')) {
1457
+ result["".concat(type, "ButtonAriaLabel")] = button.getAttribute('aria-label');
1917
1458
  }
1918
-
1919
- instance._destroy();
1920
1459
  });
1460
+ return result;
1921
1461
  };
1922
1462
 
1923
- function setButtonsDisabled(instance, buttons, disabled) {
1924
- const domCache = privateProps.domCache.get(instance);
1925
- buttons.forEach(button => {
1926
- domCache[button].disabled = disabled;
1927
- });
1928
- }
1929
-
1930
- function setInputDisabled(input, disabled) {
1931
- if (!input) {
1932
- return false;
1933
- }
1463
+ const getSwalImage = templateContent => {
1464
+ const result = {};
1465
+ const image = templateContent.querySelector('swal-image');
1934
1466
 
1935
- if (input.type === 'radio') {
1936
- const radiosContainer = input.parentNode.parentNode;
1937
- const radios = radiosContainer.querySelectorAll('input');
1467
+ if (image) {
1468
+ showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']);
1938
1469
 
1939
- for (let i = 0; i < radios.length; i++) {
1940
- radios[i].disabled = disabled;
1470
+ if (image.hasAttribute('src')) {
1471
+ result.imageUrl = image.getAttribute('src');
1941
1472
  }
1942
- } else {
1943
- input.disabled = disabled;
1944
- }
1945
- }
1946
1473
 
1947
- function enableButtons() {
1948
- setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
1949
- }
1950
- function disableButtons() {
1951
- setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
1952
- }
1953
- function enableInput() {
1954
- return setInputDisabled(this.getInput(), false);
1955
- }
1956
- function disableInput() {
1957
- return setInputDisabled(this.getInput(), true);
1958
- }
1474
+ if (image.hasAttribute('width')) {
1475
+ result.imageWidth = image.getAttribute('width');
1476
+ }
1959
1477
 
1960
- function showValidationMessage(error) {
1961
- const domCache = privateProps.domCache.get(this);
1962
- const params = privateProps.innerParams.get(this);
1963
- setInnerHtml(domCache.validationMessage, error);
1964
- domCache.validationMessage.className = swalClasses['validation-message'];
1478
+ if (image.hasAttribute('height')) {
1479
+ result.imageHeight = image.getAttribute('height');
1480
+ }
1965
1481
 
1966
- if (params.customClass && params.customClass.validationMessage) {
1967
- addClass(domCache.validationMessage, params.customClass.validationMessage);
1482
+ if (image.hasAttribute('alt')) {
1483
+ result.imageAlt = image.getAttribute('alt');
1484
+ }
1968
1485
  }
1969
1486
 
1970
- show(domCache.validationMessage);
1971
- const input = this.getInput();
1487
+ return result;
1488
+ };
1972
1489
 
1973
- if (input) {
1974
- input.setAttribute('aria-invalid', true);
1975
- input.setAttribute('aria-describedby', swalClasses['validation-message']);
1976
- focusInput(input);
1977
- addClass(input, swalClasses.inputerror);
1978
- }
1979
- } // Hide block with validation message
1490
+ const getSwalIcon = templateContent => {
1491
+ const result = {};
1492
+ const icon = templateContent.querySelector('swal-icon');
1980
1493
 
1981
- function resetValidationMessage$1() {
1982
- const domCache = privateProps.domCache.get(this);
1494
+ if (icon) {
1495
+ showWarningsForAttributes(icon, ['type', 'color']);
1983
1496
 
1984
- if (domCache.validationMessage) {
1985
- hide(domCache.validationMessage);
1986
- }
1497
+ if (icon.hasAttribute('type')) {
1498
+ result.icon = icon.getAttribute('type');
1499
+ }
1987
1500
 
1988
- const input = this.getInput();
1501
+ if (icon.hasAttribute('color')) {
1502
+ result.iconColor = icon.getAttribute('color');
1503
+ }
1989
1504
 
1990
- if (input) {
1991
- input.removeAttribute('aria-invalid');
1992
- input.removeAttribute('aria-describedby');
1993
- removeClass(input, swalClasses.inputerror);
1505
+ result.iconHtml = icon.innerHTML;
1994
1506
  }
1995
- }
1996
1507
 
1997
- function getProgressSteps$1() {
1998
- const domCache = privateProps.domCache.get(this);
1999
- return domCache.progressSteps;
2000
- }
1508
+ return result;
1509
+ };
2001
1510
 
2002
- class Timer {
2003
- constructor(callback, delay) {
2004
- this.callback = callback;
2005
- this.remaining = delay;
2006
- this.running = false;
2007
- this.start();
2008
- }
1511
+ const getSwalInput = templateContent => {
1512
+ const result = {};
1513
+ const input = templateContent.querySelector('swal-input');
2009
1514
 
2010
- start() {
2011
- if (!this.running) {
2012
- this.running = true;
2013
- this.started = new Date();
2014
- this.id = setTimeout(this.callback, this.remaining);
1515
+ if (input) {
1516
+ showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value']);
1517
+ result.input = input.getAttribute('type') || 'text';
1518
+
1519
+ if (input.hasAttribute('label')) {
1520
+ result.inputLabel = input.getAttribute('label');
2015
1521
  }
2016
1522
 
2017
- return this.remaining;
2018
- }
1523
+ if (input.hasAttribute('placeholder')) {
1524
+ result.inputPlaceholder = input.getAttribute('placeholder');
1525
+ }
2019
1526
 
2020
- stop() {
2021
- if (this.running) {
2022
- this.running = false;
2023
- clearTimeout(this.id);
2024
- this.remaining -= new Date() - this.started;
1527
+ if (input.hasAttribute('value')) {
1528
+ result.inputValue = input.getAttribute('value');
2025
1529
  }
1530
+ }
2026
1531
 
2027
- return this.remaining;
1532
+ const inputOptions = templateContent.querySelectorAll('swal-input-option');
1533
+
1534
+ if (inputOptions.length) {
1535
+ result.inputOptions = {};
1536
+ toArray(inputOptions).forEach(option => {
1537
+ showWarningsForAttributes(option, ['value']);
1538
+ const optionValue = option.getAttribute('value');
1539
+ const optionName = option.innerHTML;
1540
+ result.inputOptions[optionValue] = optionName;
1541
+ });
2028
1542
  }
2029
1543
 
2030
- increase(n) {
2031
- const running = this.running;
1544
+ return result;
1545
+ };
2032
1546
 
2033
- if (running) {
2034
- this.stop();
2035
- }
1547
+ const getSwalStringParams = (templateContent, paramNames) => {
1548
+ const result = {};
2036
1549
 
2037
- this.remaining += n;
1550
+ for (const i in paramNames) {
1551
+ const paramName = paramNames[i];
1552
+ const tag = templateContent.querySelector(paramName);
2038
1553
 
2039
- if (running) {
2040
- this.start();
1554
+ if (tag) {
1555
+ showWarningsForAttributes(tag, []);
1556
+ result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim();
2041
1557
  }
2042
-
2043
- return this.remaining;
2044
1558
  }
2045
1559
 
2046
- getTimerLeft() {
2047
- if (this.running) {
2048
- this.stop();
2049
- this.start();
2050
- }
1560
+ return result;
1561
+ };
2051
1562
 
2052
- return this.remaining;
2053
- }
1563
+ const showWarningsForElements = template => {
1564
+ const allowedElements = swalStringParams.concat(['swal-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']);
1565
+ toArray(template.children).forEach(el => {
1566
+ const tagName = el.tagName.toLowerCase();
2054
1567
 
2055
- isRunning() {
2056
- return this.running;
2057
- }
1568
+ if (allowedElements.indexOf(tagName) === -1) {
1569
+ warn("Unrecognized element <".concat(tagName, ">"));
1570
+ }
1571
+ });
1572
+ };
2058
1573
 
2059
- }
1574
+ const showWarningsForAttributes = (el, allowedAttributes) => {
1575
+ toArray(el.attributes).forEach(attribute => {
1576
+ if (allowedAttributes.indexOf(attribute.name) === -1) {
1577
+ warn(["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.')]);
1578
+ }
1579
+ });
1580
+ };
2060
1581
 
2061
1582
  var defaultInputValidators = {
2062
1583
  email: (string, validationMessage) => {
@@ -2090,7 +1611,6 @@
2090
1611
  * Set type, text and actions on popup
2091
1612
  *
2092
1613
  * @param params
2093
- * @returns {boolean}
2094
1614
  */
2095
1615
 
2096
1616
 
@@ -2110,176 +1630,168 @@
2110
1630
  init(params);
2111
1631
  }
2112
1632
 
2113
- const swalStringParams = ['swal-title', 'swal-html', 'swal-footer'];
2114
- const getTemplateParams = params => {
2115
- const template = typeof params.template === 'string' ? document.querySelector(params.template) : params.template;
2116
-
2117
- if (!template) {
2118
- return {};
1633
+ class Timer {
1634
+ constructor(callback, delay) {
1635
+ this.callback = callback;
1636
+ this.remaining = delay;
1637
+ this.running = false;
1638
+ this.start();
2119
1639
  }
2120
1640
 
2121
- const templateContent = template.content;
2122
- showWarningsForElements(templateContent);
2123
- const result = Object.assign(getSwalParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams));
2124
- return result;
2125
- };
1641
+ start() {
1642
+ if (!this.running) {
1643
+ this.running = true;
1644
+ this.started = new Date();
1645
+ this.id = setTimeout(this.callback, this.remaining);
1646
+ }
2126
1647
 
2127
- const getSwalParams = templateContent => {
2128
- const result = {};
2129
- toArray(templateContent.querySelectorAll('swal-param')).forEach(param => {
2130
- showWarningsForAttributes(param, ['name', 'value']);
2131
- const paramName = param.getAttribute('name');
2132
- let value = param.getAttribute('value');
1648
+ return this.remaining;
1649
+ }
2133
1650
 
2134
- if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {
2135
- value = false;
1651
+ stop() {
1652
+ if (this.running) {
1653
+ this.running = false;
1654
+ clearTimeout(this.id);
1655
+ this.remaining -= new Date().getTime() - this.started.getTime();
2136
1656
  }
2137
1657
 
2138
- if (typeof defaultParams[paramName] === 'object') {
2139
- value = JSON.parse(value);
2140
- }
1658
+ return this.remaining;
1659
+ }
2141
1660
 
2142
- result[paramName] = value;
2143
- });
2144
- return result;
2145
- };
1661
+ increase(n) {
1662
+ const running = this.running;
2146
1663
 
2147
- const getSwalButtons = templateContent => {
2148
- const result = {};
2149
- toArray(templateContent.querySelectorAll('swal-button')).forEach(button => {
2150
- showWarningsForAttributes(button, ['type', 'color', 'aria-label']);
2151
- const type = button.getAttribute('type');
2152
- result["".concat(type, "ButtonText")] = button.innerHTML;
2153
- result["show".concat(capitalizeFirstLetter(type), "Button")] = true;
1664
+ if (running) {
1665
+ this.stop();
1666
+ }
2154
1667
 
2155
- if (button.hasAttribute('color')) {
2156
- result["".concat(type, "ButtonColor")] = button.getAttribute('color');
1668
+ this.remaining += n;
1669
+
1670
+ if (running) {
1671
+ this.start();
2157
1672
  }
2158
1673
 
2159
- if (button.hasAttribute('aria-label')) {
2160
- result["".concat(type, "ButtonAriaLabel")] = button.getAttribute('aria-label');
1674
+ return this.remaining;
1675
+ }
1676
+
1677
+ getTimerLeft() {
1678
+ if (this.running) {
1679
+ this.stop();
1680
+ this.start();
2161
1681
  }
2162
- });
2163
- return result;
2164
- };
2165
1682
 
2166
- const getSwalImage = templateContent => {
2167
- const result = {};
2168
- const image = templateContent.querySelector('swal-image');
1683
+ return this.remaining;
1684
+ }
2169
1685
 
2170
- if (image) {
2171
- showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']);
1686
+ isRunning() {
1687
+ return this.running;
1688
+ }
2172
1689
 
2173
- if (image.hasAttribute('src')) {
2174
- result.imageUrl = image.getAttribute('src');
2175
- }
1690
+ }
2176
1691
 
2177
- if (image.hasAttribute('width')) {
2178
- result.imageWidth = image.getAttribute('width');
2179
- }
1692
+ const fixScrollbar = () => {
1693
+ // for queues, do not do this more than once
1694
+ if (states.previousBodyPadding !== null) {
1695
+ return;
1696
+ } // if the body has overflow
2180
1697
 
2181
- if (image.hasAttribute('height')) {
2182
- result.imageHeight = image.getAttribute('height');
2183
- }
2184
1698
 
2185
- if (image.hasAttribute('alt')) {
2186
- result.imageAlt = image.getAttribute('alt');
2187
- }
1699
+ if (document.body.scrollHeight > window.innerHeight) {
1700
+ // add padding so the content doesn't shift after removal of scrollbar
1701
+ states.previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'));
1702
+ document.body.style.paddingRight = "".concat(states.previousBodyPadding + measureScrollbar(), "px");
1703
+ }
1704
+ };
1705
+ const undoScrollbar = () => {
1706
+ if (states.previousBodyPadding !== null) {
1707
+ document.body.style.paddingRight = "".concat(states.previousBodyPadding, "px");
1708
+ states.previousBodyPadding = null;
2188
1709
  }
2189
-
2190
- return result;
2191
1710
  };
2192
1711
 
2193
- const getSwalIcon = templateContent => {
2194
- const result = {};
2195
- const icon = templateContent.querySelector('swal-icon');
1712
+ /* istanbul ignore file */
2196
1713
 
2197
- if (icon) {
2198
- showWarningsForAttributes(icon, ['type', 'color']);
1714
+ const iOSfix = () => {
1715
+ // @ts-ignore
1716
+ const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream || navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
1717
+
1718
+ if (iOS && !hasClass(document.body, swalClasses.iosfix)) {
1719
+ const offset = document.body.scrollTop;
1720
+ document.body.style.top = "".concat(offset * -1, "px");
1721
+ addClass(document.body, swalClasses.iosfix);
1722
+ lockBodyScroll();
1723
+ addBottomPaddingForTallPopups(); // #1948
1724
+ }
1725
+ };
1726
+
1727
+ const addBottomPaddingForTallPopups = () => {
1728
+ const safari = !navigator.userAgent.match(/(CriOS|FxiOS|EdgiOS|YaBrowser|UCBrowser)/i);
2199
1729
 
2200
- if (icon.hasAttribute('type')) {
2201
- result.icon = icon.getAttribute('type');
2202
- }
1730
+ if (safari) {
1731
+ const bottomPanelHeight = 44;
2203
1732
 
2204
- if (icon.hasAttribute('color')) {
2205
- result.iconColor = icon.getAttribute('color');
1733
+ if (getPopup().scrollHeight > window.innerHeight - bottomPanelHeight) {
1734
+ getContainer().style.paddingBottom = "".concat(bottomPanelHeight, "px");
2206
1735
  }
2207
-
2208
- result.iconHtml = icon.innerHTML;
2209
1736
  }
2210
-
2211
- return result;
2212
1737
  };
2213
1738
 
2214
- const getSwalInput = templateContent => {
2215
- const result = {};
2216
- const input = templateContent.querySelector('swal-input');
1739
+ const lockBodyScroll = () => {
1740
+ // #1246
1741
+ const container = getContainer();
1742
+ let preventTouchMove;
2217
1743
 
2218
- if (input) {
2219
- showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value']);
2220
- result.input = input.getAttribute('type') || 'text';
1744
+ container.ontouchstart = e => {
1745
+ preventTouchMove = shouldPreventTouchMove(e);
1746
+ };
2221
1747
 
2222
- if (input.hasAttribute('label')) {
2223
- result.inputLabel = input.getAttribute('label');
1748
+ container.ontouchmove = e => {
1749
+ if (preventTouchMove) {
1750
+ e.preventDefault();
1751
+ e.stopPropagation();
2224
1752
  }
1753
+ };
1754
+ };
2225
1755
 
2226
- if (input.hasAttribute('placeholder')) {
2227
- result.inputPlaceholder = input.getAttribute('placeholder');
2228
- }
1756
+ const shouldPreventTouchMove = event => {
1757
+ const target = event.target;
1758
+ const container = getContainer();
2229
1759
 
2230
- if (input.hasAttribute('value')) {
2231
- result.inputValue = input.getAttribute('value');
2232
- }
1760
+ if (isStylys(event) || isZoom(event)) {
1761
+ return false;
2233
1762
  }
2234
1763
 
2235
- const inputOptions = templateContent.querySelectorAll('swal-input-option');
2236
-
2237
- if (inputOptions.length) {
2238
- result.inputOptions = {};
2239
- toArray(inputOptions).forEach(option => {
2240
- showWarningsForAttributes(option, ['value']);
2241
- const optionValue = option.getAttribute('value');
2242
- const optionName = option.innerHTML;
2243
- result.inputOptions[optionValue] = optionName;
2244
- });
1764
+ if (target === container) {
1765
+ return true;
2245
1766
  }
2246
1767
 
2247
- return result;
2248
- };
2249
-
2250
- const getSwalStringParams = (templateContent, paramNames) => {
2251
- const result = {};
2252
-
2253
- for (const i in paramNames) {
2254
- const paramName = paramNames[i];
2255
- const tag = templateContent.querySelector(paramName);
2256
-
2257
- if (tag) {
2258
- showWarningsForAttributes(tag, []);
2259
- result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim();
2260
- }
1768
+ if (!isScrollable(container) && target.tagName !== 'INPUT' && // #1603
1769
+ target.tagName !== 'TEXTAREA' && // #2266
1770
+ !(isScrollable(getHtmlContainer()) && // #1944
1771
+ getHtmlContainer().contains(target))) {
1772
+ return true;
2261
1773
  }
2262
1774
 
2263
- return result;
1775
+ return false;
2264
1776
  };
2265
1777
 
2266
- const showWarningsForElements = template => {
2267
- const allowedElements = swalStringParams.concat(['swal-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']);
2268
- toArray(template.children).forEach(el => {
2269
- const tagName = el.tagName.toLowerCase();
1778
+ const isStylys = event => {
1779
+ // #1786
1780
+ return event.touches && event.touches.length && event.touches[0].touchType === 'stylus';
1781
+ };
2270
1782
 
2271
- if (allowedElements.indexOf(tagName) === -1) {
2272
- warn("Unrecognized element <".concat(tagName, ">"));
2273
- }
2274
- });
1783
+ const isZoom = event => {
1784
+ // #1891
1785
+ return event.touches && event.touches.length > 1;
2275
1786
  };
2276
1787
 
2277
- const showWarningsForAttributes = (el, allowedAttributes) => {
2278
- toArray(el.attributes).forEach(attribute => {
2279
- if (allowedAttributes.indexOf(attribute.name) === -1) {
2280
- warn(["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.')]);
2281
- }
2282
- });
1788
+ const undoIOSfix = () => {
1789
+ if (hasClass(document.body, swalClasses.iosfix)) {
1790
+ const offset = parseInt(document.body.style.top, 10);
1791
+ removeClass(document.body, swalClasses.iosfix);
1792
+ document.body.style.top = '';
1793
+ document.body.scrollTop = offset * -1;
1794
+ }
2283
1795
  };
2284
1796
 
2285
1797
  const SHOW_CLASS_TIMEOUT = 10;
@@ -2374,6 +1886,52 @@
2374
1886
  }
2375
1887
  };
2376
1888
 
1889
+ /**
1890
+ * Shows loader (spinner), this is useful with AJAX requests.
1891
+ * By default the loader be shown instead of the "Confirm" button.
1892
+ */
1893
+
1894
+ const showLoading = buttonToReplace => {
1895
+ let popup = getPopup();
1896
+
1897
+ if (!popup) {
1898
+ new Swal(); // eslint-disable-line no-new
1899
+ }
1900
+
1901
+ popup = getPopup();
1902
+ const loader = getLoader();
1903
+
1904
+ if (isToast()) {
1905
+ hide(getIcon());
1906
+ } else {
1907
+ replaceButton(popup, buttonToReplace);
1908
+ }
1909
+
1910
+ show(loader);
1911
+ popup.setAttribute('data-loading', true);
1912
+ popup.setAttribute('aria-busy', true);
1913
+ popup.focus();
1914
+ };
1915
+
1916
+ const replaceButton = (popup, buttonToReplace) => {
1917
+ const actions = getActions();
1918
+ const loader = getLoader();
1919
+
1920
+ if (!buttonToReplace && isVisible(getConfirmButton())) {
1921
+ buttonToReplace = getConfirmButton();
1922
+ }
1923
+
1924
+ show(actions);
1925
+
1926
+ if (buttonToReplace) {
1927
+ hide(buttonToReplace);
1928
+ loader.setAttribute('data-button-to-replace', buttonToReplace.className);
1929
+ }
1930
+
1931
+ loader.parentNode.insertBefore(loader, buttonToReplace);
1932
+ addClass([popup, actions], swalClasses.loading);
1933
+ };
1934
+
2377
1935
  const handleInputOptionsAndValue = (instance, params) => {
2378
1936
  if (params.input === 'select' || params.input === 'radio') {
2379
1937
  handleInputOptions(instance, params);
@@ -2447,7 +2005,7 @@
2447
2005
 
2448
2006
  const populateInputOptions = {
2449
2007
  select: (popup, inputOptions, params) => {
2450
- const select = getChildByClass(popup, swalClasses.select);
2008
+ const select = getDirectChildByClass(popup, swalClasses.select);
2451
2009
 
2452
2010
  const renderOption = (parent, optionLabel, optionValue) => {
2453
2011
  const option = document.createElement('option');
@@ -2480,7 +2038,7 @@
2480
2038
  select.focus();
2481
2039
  },
2482
2040
  radio: (popup, inputOptions, params) => {
2483
- const radio = getChildByClass(popup, swalClasses.radio);
2041
+ const radio = getDirectChildByClass(popup, swalClasses.radio);
2484
2042
  inputOptions.forEach(inputOption => {
2485
2043
  const radioValue = inputOption[0];
2486
2044
  const radioLabel = inputOption[1];
@@ -2653,26 +2211,128 @@
2653
2211
  const confirm = (instance, value) => {
2654
2212
  const innerParams = privateProps.innerParams.get(instance || undefined);
2655
2213
 
2656
- if (innerParams.showLoaderOnConfirm) {
2657
- showLoading();
2658
- }
2214
+ if (innerParams.showLoaderOnConfirm) {
2215
+ showLoading();
2216
+ }
2217
+
2218
+ if (innerParams.preConfirm) {
2219
+ instance.resetValidationMessage();
2220
+ privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesnt get destroyed until the result from this preConfirm's promise is received
2221
+
2222
+ const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
2223
+ preConfirmPromise.then(preConfirmValue => {
2224
+ if (isVisible(getValidationMessage()) || preConfirmValue === false) {
2225
+ instance.hideLoading();
2226
+ } else {
2227
+ succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);
2228
+ }
2229
+ }).catch(error$$1 => rejectWith(instance || undefined, error$$1));
2230
+ } else {
2231
+ succeedWith(instance, value);
2232
+ }
2233
+ };
2234
+
2235
+ const handlePopupClick = (instance, domCache, dismissWith) => {
2236
+ const innerParams = privateProps.innerParams.get(instance);
2237
+
2238
+ if (innerParams.toast) {
2239
+ handleToastClick(instance, domCache, dismissWith);
2240
+ } else {
2241
+ // Ignore click events that had mousedown on the popup but mouseup on the container
2242
+ // This can happen when the user drags a slider
2243
+ handleModalMousedown(domCache); // Ignore click events that had mousedown on the container but mouseup on the popup
2244
+
2245
+ handleContainerMousedown(domCache);
2246
+ handleModalClick(instance, domCache, dismissWith);
2247
+ }
2248
+ };
2249
+
2250
+ const handleToastClick = (instance, domCache, dismissWith) => {
2251
+ // Closing toast by internal click
2252
+ domCache.popup.onclick = () => {
2253
+ const innerParams = privateProps.innerParams.get(instance);
2254
+
2255
+ if (innerParams && (isAnyButtonShown(innerParams) || innerParams.timer || innerParams.input)) {
2256
+ return;
2257
+ }
2258
+
2259
+ dismissWith(DismissReason.close);
2260
+ };
2261
+ };
2262
+ /**
2263
+ * @param {*} innerParams
2264
+ * @returns {boolean}
2265
+ */
2266
+
2267
+
2268
+ const isAnyButtonShown = innerParams => {
2269
+ return innerParams.showConfirmButton || innerParams.showDenyButton || innerParams.showCancelButton || innerParams.showCloseButton;
2270
+ };
2271
+
2272
+ let ignoreOutsideClick = false;
2273
+
2274
+ const handleModalMousedown = domCache => {
2275
+ domCache.popup.onmousedown = () => {
2276
+ domCache.container.onmouseup = function (e) {
2277
+ domCache.container.onmouseup = undefined; // We only check if the mouseup target is the container because usually it doesn't
2278
+ // have any other direct children aside of the popup
2279
+
2280
+ if (e.target === domCache.container) {
2281
+ ignoreOutsideClick = true;
2282
+ }
2283
+ };
2284
+ };
2285
+ };
2286
+
2287
+ const handleContainerMousedown = domCache => {
2288
+ domCache.container.onmousedown = () => {
2289
+ domCache.popup.onmouseup = function (e) {
2290
+ domCache.popup.onmouseup = undefined; // We also need to check if the mouseup target is a child of the popup
2291
+
2292
+ if (e.target === domCache.popup || domCache.popup.contains(e.target)) {
2293
+ ignoreOutsideClick = true;
2294
+ }
2295
+ };
2296
+ };
2297
+ };
2298
+
2299
+ const handleModalClick = (instance, domCache, dismissWith) => {
2300
+ domCache.container.onclick = e => {
2301
+ const innerParams = privateProps.innerParams.get(instance);
2302
+
2303
+ if (ignoreOutsideClick) {
2304
+ ignoreOutsideClick = false;
2305
+ return;
2306
+ }
2307
+
2308
+ if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) {
2309
+ dismissWith(DismissReason.backdrop);
2310
+ }
2311
+ };
2312
+ };
2313
+
2314
+ /*
2315
+ * Global function to determine if SweetAlert2 popup is shown
2316
+ */
2317
+
2318
+ const isVisible$1 = () => {
2319
+ return isVisible(getPopup());
2320
+ };
2321
+ /*
2322
+ * Global function to click 'Confirm' button
2323
+ */
2324
+
2325
+ const clickConfirm = () => getConfirmButton() && getConfirmButton().click();
2326
+ /*
2327
+ * Global function to click 'Deny' button
2328
+ */
2659
2329
 
2660
- if (innerParams.preConfirm) {
2661
- instance.resetValidationMessage();
2662
- privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesnt get destroyed until the result from this preConfirm's promise is received
2330
+ const clickDeny = () => getDenyButton() && getDenyButton().click();
2331
+ /*
2332
+ * Global function to click 'Cancel' button
2333
+ */
2663
2334
 
2664
- const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
2665
- preConfirmPromise.then(preConfirmValue => {
2666
- if (isVisible(getValidationMessage()) || preConfirmValue === false) {
2667
- instance.hideLoading();
2668
- } else {
2669
- succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);
2670
- }
2671
- }).catch(error$$1 => rejectWith(instance || undefined, error$$1));
2672
- } else {
2673
- succeedWith(instance, value);
2674
- }
2675
- };
2335
+ const clickCancel = () => getCancelButton() && getCancelButton().click();
2676
2336
 
2677
2337
  const addKeydownHandler = (instance, globalState, innerParams, dismissWith) => {
2678
2338
  if (globalState.keydownTarget && globalState.keydownHandlerAdded) {
@@ -2783,245 +2443,523 @@
2783
2443
  const denyButton = getDenyButton();
2784
2444
  const cancelButton = getCancelButton();
2785
2445
 
2786
- if (![confirmButton, denyButton, cancelButton].includes(document.activeElement)) {
2787
- return;
2446
+ if (![confirmButton, denyButton, cancelButton].includes(document.activeElement)) {
2447
+ return;
2448
+ }
2449
+
2450
+ const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling';
2451
+ const buttonToFocus = document.activeElement[sibling];
2452
+
2453
+ if (buttonToFocus instanceof HTMLElement) {
2454
+ buttonToFocus.focus();
2455
+ }
2456
+ };
2457
+
2458
+ const handleEsc = (e, innerParams, dismissWith) => {
2459
+ if (callIfFunction(innerParams.allowEscapeKey)) {
2460
+ e.preventDefault();
2461
+ dismissWith(DismissReason.esc);
2462
+ }
2463
+ };
2464
+
2465
+ const isJqueryElement = elem => typeof elem === 'object' && elem.jquery;
2466
+
2467
+ const isElement = elem => elem instanceof Element || isJqueryElement(elem);
2468
+
2469
+ const argsToParams = args => {
2470
+ const params = {};
2471
+
2472
+ if (typeof args[0] === 'object' && !isElement(args[0])) {
2473
+ Object.assign(params, args[0]);
2474
+ } else {
2475
+ ['title', 'html', 'icon'].forEach((name, index) => {
2476
+ const arg = args[index];
2477
+
2478
+ if (typeof arg === 'string' || isElement(arg)) {
2479
+ params[name] = arg;
2480
+ } else if (arg !== undefined) {
2481
+ error("Unexpected type of ".concat(name, "! Expected \"string\" or \"Element\", got ").concat(typeof arg));
2482
+ }
2483
+ });
2484
+ }
2485
+
2486
+ return params;
2487
+ };
2488
+
2489
+ function fire() {
2490
+ const Swal = this;
2491
+
2492
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
2493
+ args[_key] = arguments[_key];
2494
+ }
2495
+
2496
+ return new Swal(...args);
2497
+ }
2498
+
2499
+ /**
2500
+ * Returns an extended version of `Swal` containing `params` as defaults.
2501
+ * Useful for reusing Swal configuration.
2502
+ *
2503
+ * For example:
2504
+ *
2505
+ * Before:
2506
+ * const textPromptOptions = { input: 'text', showCancelButton: true }
2507
+ * const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' })
2508
+ * const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' })
2509
+ *
2510
+ * After:
2511
+ * const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true })
2512
+ * const {value: firstName} = await TextPrompt('What is your first name?')
2513
+ * const {value: lastName} = await TextPrompt('What is your last name?')
2514
+ *
2515
+ * @param mixinParams
2516
+ */
2517
+ function mixin(mixinParams) {
2518
+ class MixinSwal extends this {
2519
+ _main(params, priorityMixinParams) {
2520
+ return super._main(params, Object.assign({}, mixinParams, priorityMixinParams));
2521
+ }
2522
+
2523
+ }
2524
+
2525
+ return MixinSwal;
2526
+ }
2527
+
2528
+ /**
2529
+ * If `timer` parameter is set, returns number of milliseconds of timer remained.
2530
+ * Otherwise, returns undefined.
2531
+ */
2532
+
2533
+ const getTimerLeft = () => {
2534
+ return globalState.timeout && globalState.timeout.getTimerLeft();
2535
+ };
2536
+ /**
2537
+ * Stop timer. Returns number of milliseconds of timer remained.
2538
+ * If `timer` parameter isn't set, returns undefined.
2539
+ */
2540
+
2541
+ const stopTimer = () => {
2542
+ if (globalState.timeout) {
2543
+ stopTimerProgressBar();
2544
+ return globalState.timeout.stop();
2545
+ }
2546
+ };
2547
+ /**
2548
+ * Resume timer. Returns number of milliseconds of timer remained.
2549
+ * If `timer` parameter isn't set, returns undefined.
2550
+ */
2551
+
2552
+ const resumeTimer = () => {
2553
+ if (globalState.timeout) {
2554
+ const remaining = globalState.timeout.start();
2555
+ animateTimerProgressBar(remaining);
2556
+ return remaining;
2557
+ }
2558
+ };
2559
+ /**
2560
+ * Resume timer. Returns number of milliseconds of timer remained.
2561
+ * If `timer` parameter isn't set, returns undefined.
2562
+ */
2563
+
2564
+ const toggleTimer = () => {
2565
+ const timer = globalState.timeout;
2566
+ return timer && (timer.running ? stopTimer() : resumeTimer());
2567
+ };
2568
+ /**
2569
+ * Increase timer. Returns number of milliseconds of an updated timer.
2570
+ * If `timer` parameter isn't set, returns undefined.
2571
+ */
2572
+
2573
+ const increaseTimer = n => {
2574
+ if (globalState.timeout) {
2575
+ const remaining = globalState.timeout.increase(n);
2576
+ animateTimerProgressBar(remaining, true);
2577
+ return remaining;
2578
+ }
2579
+ };
2580
+ /**
2581
+ * Check if timer is running. Returns true if timer is running
2582
+ * or false if timer is paused or stopped.
2583
+ * If `timer` parameter isn't set, returns undefined
2584
+ */
2585
+
2586
+ const isTimerRunning = () => {
2587
+ return globalState.timeout && globalState.timeout.isRunning();
2588
+ };
2589
+
2590
+ let bodyClickListenerAdded = false;
2591
+ const clickHandlers = {};
2592
+ function bindClickHandler() {
2593
+ let attr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'data-swal-template';
2594
+ clickHandlers[attr] = this;
2595
+
2596
+ if (!bodyClickListenerAdded) {
2597
+ document.body.addEventListener('click', bodyClickListener);
2598
+ bodyClickListenerAdded = true;
2599
+ }
2600
+ }
2601
+
2602
+ const bodyClickListener = event => {
2603
+ for (let el = event.target; el && el !== document; el = el.parentNode) {
2604
+ for (const attr in clickHandlers) {
2605
+ const template = el.getAttribute(attr);
2606
+
2607
+ if (template) {
2608
+ clickHandlers[attr].fire({
2609
+ template
2610
+ });
2611
+ return;
2612
+ }
2613
+ }
2614
+ }
2615
+ };
2616
+
2617
+
2618
+
2619
+ var staticMethods = /*#__PURE__*/Object.freeze({
2620
+ isValidParameter: isValidParameter,
2621
+ isUpdatableParameter: isUpdatableParameter,
2622
+ isDeprecatedParameter: isDeprecatedParameter,
2623
+ argsToParams: argsToParams,
2624
+ isVisible: isVisible$1,
2625
+ clickConfirm: clickConfirm,
2626
+ clickDeny: clickDeny,
2627
+ clickCancel: clickCancel,
2628
+ getContainer: getContainer,
2629
+ getPopup: getPopup,
2630
+ getTitle: getTitle,
2631
+ getHtmlContainer: getHtmlContainer,
2632
+ getImage: getImage,
2633
+ getIcon: getIcon,
2634
+ getInputLabel: getInputLabel,
2635
+ getCloseButton: getCloseButton,
2636
+ getActions: getActions,
2637
+ getConfirmButton: getConfirmButton,
2638
+ getDenyButton: getDenyButton,
2639
+ getCancelButton: getCancelButton,
2640
+ getLoader: getLoader,
2641
+ getFooter: getFooter,
2642
+ getTimerProgressBar: getTimerProgressBar,
2643
+ getFocusableElements: getFocusableElements,
2644
+ getValidationMessage: getValidationMessage,
2645
+ isLoading: isLoading,
2646
+ fire: fire,
2647
+ mixin: mixin,
2648
+ showLoading: showLoading,
2649
+ enableLoading: showLoading,
2650
+ getTimerLeft: getTimerLeft,
2651
+ stopTimer: stopTimer,
2652
+ resumeTimer: resumeTimer,
2653
+ toggleTimer: toggleTimer,
2654
+ increaseTimer: increaseTimer,
2655
+ isTimerRunning: isTimerRunning,
2656
+ bindClickHandler: bindClickHandler
2657
+ });
2658
+
2659
+ /**
2660
+ * Hides loader and shows back the button which was hidden by .showLoading()
2661
+ */
2662
+
2663
+ function hideLoading() {
2664
+ // do nothing if popup is closed
2665
+ const innerParams = privateProps.innerParams.get(this);
2666
+
2667
+ if (!innerParams) {
2668
+ return;
2669
+ }
2670
+
2671
+ const domCache = privateProps.domCache.get(this);
2672
+ hide(domCache.loader);
2673
+
2674
+ if (isToast()) {
2675
+ if (innerParams.icon) {
2676
+ show(getIcon());
2677
+ }
2678
+ } else {
2679
+ showRelatedButton(domCache);
2788
2680
  }
2789
2681
 
2790
- const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling';
2791
- const buttonToFocus = document.activeElement[sibling];
2682
+ removeClass([domCache.popup, domCache.actions], swalClasses.loading);
2683
+ domCache.popup.removeAttribute('aria-busy');
2684
+ domCache.popup.removeAttribute('data-loading');
2685
+ domCache.confirmButton.disabled = false;
2686
+ domCache.denyButton.disabled = false;
2687
+ domCache.cancelButton.disabled = false;
2688
+ }
2792
2689
 
2793
- if (buttonToFocus) {
2794
- buttonToFocus.focus();
2795
- }
2796
- };
2690
+ const showRelatedButton = domCache => {
2691
+ const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'));
2797
2692
 
2798
- const handleEsc = (e, innerParams, dismissWith) => {
2799
- if (callIfFunction(innerParams.allowEscapeKey)) {
2800
- e.preventDefault();
2801
- dismissWith(DismissReason.esc);
2693
+ if (buttonToReplace.length) {
2694
+ show(buttonToReplace[0], 'inline-block');
2695
+ } else if (allButtonsAreHidden()) {
2696
+ hide(domCache.actions);
2802
2697
  }
2803
2698
  };
2804
2699
 
2805
- const handlePopupClick = (instance, domCache, dismissWith) => {
2806
- const innerParams = privateProps.innerParams.get(instance);
2700
+ /**
2701
+ * Gets the input DOM node, this method works with input parameter.
2702
+ * @returns {HTMLElement | null}
2703
+ */
2807
2704
 
2808
- if (innerParams.toast) {
2809
- handleToastClick(instance, domCache, dismissWith);
2810
- } else {
2811
- // Ignore click events that had mousedown on the popup but mouseup on the container
2812
- // This can happen when the user drags a slider
2813
- handleModalMousedown(domCache); // Ignore click events that had mousedown on the container but mouseup on the popup
2705
+ function getInput$1(instance) {
2706
+ const innerParams = privateProps.innerParams.get(instance || this);
2707
+ const domCache = privateProps.domCache.get(instance || this);
2814
2708
 
2815
- handleContainerMousedown(domCache);
2816
- handleModalClick(instance, domCache, dismissWith);
2709
+ if (!domCache) {
2710
+ return null;
2817
2711
  }
2818
- };
2819
2712
 
2820
- const handleToastClick = (instance, domCache, dismissWith) => {
2821
- // Closing toast by internal click
2822
- domCache.popup.onclick = () => {
2823
- const innerParams = privateProps.innerParams.get(instance);
2824
-
2825
- if (innerParams.showConfirmButton || innerParams.showDenyButton || innerParams.showCancelButton || innerParams.showCloseButton || innerParams.timer || innerParams.input) {
2826
- return;
2827
- }
2713
+ return getInput(domCache.popup, innerParams.input);
2714
+ }
2828
2715
 
2829
- dismissWith(DismissReason.close);
2830
- };
2716
+ /**
2717
+ * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
2718
+ * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
2719
+ * This is the approach that Babel will probably take to implement private methods/fields
2720
+ * https://github.com/tc39/proposal-private-methods
2721
+ * https://github.com/babel/babel/pull/7555
2722
+ * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
2723
+ * then we can use that language feature.
2724
+ */
2725
+ var privateMethods = {
2726
+ swalPromiseResolve: new WeakMap(),
2727
+ swalPromiseReject: new WeakMap()
2831
2728
  };
2832
2729
 
2833
- let ignoreOutsideClick = false;
2730
+ /*
2731
+ * Instance method to close sweetAlert
2732
+ */
2834
2733
 
2835
- const handleModalMousedown = domCache => {
2836
- domCache.popup.onmousedown = () => {
2837
- domCache.container.onmouseup = function (e) {
2838
- domCache.container.onmouseup = undefined; // We only check if the mouseup target is the container because usually it doesn't
2839
- // have any other direct children aside of the popup
2734
+ function removePopupAndResetState(instance, container, returnFocus, didClose) {
2735
+ if (isToast()) {
2736
+ triggerDidCloseAndDispose(instance, didClose);
2737
+ } else {
2738
+ restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose));
2739
+ globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, {
2740
+ capture: globalState.keydownListenerCapture
2741
+ });
2742
+ globalState.keydownHandlerAdded = false;
2743
+ }
2840
2744
 
2841
- if (e.target === domCache.container) {
2842
- ignoreOutsideClick = true;
2843
- }
2844
- };
2845
- };
2846
- };
2745
+ const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); // workaround for #2088
2746
+ // for some reason removing the container in Safari will scroll the document to bottom
2847
2747
 
2848
- const handleContainerMousedown = domCache => {
2849
- domCache.container.onmousedown = () => {
2850
- domCache.popup.onmouseup = function (e) {
2851
- domCache.popup.onmouseup = undefined; // We also need to check if the mouseup target is a child of the popup
2748
+ if (isSafari) {
2749
+ container.setAttribute('style', 'display:none !important');
2750
+ container.removeAttribute('class');
2751
+ container.innerHTML = '';
2752
+ } else {
2753
+ container.remove();
2754
+ }
2852
2755
 
2853
- if (e.target === domCache.popup || domCache.popup.contains(e.target)) {
2854
- ignoreOutsideClick = true;
2855
- }
2856
- };
2857
- };
2858
- };
2756
+ if (isModal()) {
2757
+ undoScrollbar();
2758
+ undoIOSfix();
2759
+ unsetAriaHidden();
2760
+ }
2859
2761
 
2860
- const handleModalClick = (instance, domCache, dismissWith) => {
2861
- domCache.container.onclick = e => {
2862
- const innerParams = privateProps.innerParams.get(instance);
2762
+ removeBodyClasses();
2763
+ }
2863
2764
 
2864
- if (ignoreOutsideClick) {
2865
- ignoreOutsideClick = false;
2866
- return;
2867
- }
2765
+ function removeBodyClasses() {
2766
+ removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]);
2767
+ }
2868
2768
 
2869
- if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) {
2870
- dismissWith(DismissReason.backdrop);
2871
- }
2872
- };
2873
- };
2769
+ function close(resolveValue) {
2770
+ resolveValue = prepareResolveValue(resolveValue);
2771
+ const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this);
2772
+ const didClose = triggerClosePopup(this);
2874
2773
 
2875
- function _main(userParams) {
2876
- let mixinParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2877
- showWarningsForParams(Object.assign({}, mixinParams, userParams));
2774
+ if (this.isAwaitingPromise()) {
2775
+ // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
2776
+ if (!resolveValue.isDismissed) {
2777
+ handleAwaitingPromise(this);
2778
+ swalPromiseResolve(resolveValue);
2779
+ }
2780
+ } else if (didClose) {
2781
+ // Resolve Swal promise
2782
+ swalPromiseResolve(resolveValue);
2783
+ }
2784
+ }
2785
+ function isAwaitingPromise() {
2786
+ return !!privateProps.awaitingPromise.get(this);
2787
+ }
2878
2788
 
2879
- if (globalState.currentInstance) {
2880
- globalState.currentInstance._destroy();
2789
+ const triggerClosePopup = instance => {
2790
+ const popup = getPopup();
2881
2791
 
2882
- if (isModal()) {
2883
- unsetAriaHidden();
2884
- }
2792
+ if (!popup) {
2793
+ return false;
2885
2794
  }
2886
2795
 
2887
- globalState.currentInstance = this;
2888
- const innerParams = prepareParams(userParams, mixinParams);
2889
- setParameters(innerParams);
2890
- Object.freeze(innerParams); // clear the previous timer
2796
+ const innerParams = privateProps.innerParams.get(instance);
2891
2797
 
2892
- if (globalState.timeout) {
2893
- globalState.timeout.stop();
2894
- delete globalState.timeout;
2895
- } // clear the restore focus timeout
2798
+ if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) {
2799
+ return false;
2800
+ }
2801
+
2802
+ removeClass(popup, innerParams.showClass.popup);
2803
+ addClass(popup, innerParams.hideClass.popup);
2804
+ const backdrop = getContainer();
2805
+ removeClass(backdrop, innerParams.showClass.backdrop);
2806
+ addClass(backdrop, innerParams.hideClass.backdrop);
2807
+ handlePopupAnimation(instance, popup, innerParams);
2808
+ return true;
2809
+ };
2896
2810
 
2811
+ function rejectPromise(error) {
2812
+ const rejectPromise = privateMethods.swalPromiseReject.get(this);
2813
+ handleAwaitingPromise(this);
2897
2814
 
2898
- clearTimeout(globalState.restoreFocusTimeout);
2899
- const domCache = populateDomCache(this);
2900
- render(this, innerParams);
2901
- privateProps.innerParams.set(this, innerParams);
2902
- return swalPromise(this, domCache, innerParams);
2815
+ if (rejectPromise) {
2816
+ // Reject Swal promise
2817
+ rejectPromise(error);
2818
+ }
2903
2819
  }
2904
2820
 
2905
- const prepareParams = (userParams, mixinParams) => {
2906
- const templateParams = getTemplateParams(userParams);
2907
- const params = Object.assign({}, defaultParams, mixinParams, templateParams, userParams); // precedence is described in #2131
2821
+ const handleAwaitingPromise = instance => {
2822
+ if (instance.isAwaitingPromise()) {
2823
+ privateProps.awaitingPromise.delete(instance); // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
2908
2824
 
2909
- params.showClass = Object.assign({}, defaultParams.showClass, params.showClass);
2910
- params.hideClass = Object.assign({}, defaultParams.hideClass, params.hideClass);
2911
- return params;
2825
+ if (!privateProps.innerParams.get(instance)) {
2826
+ instance._destroy();
2827
+ }
2828
+ }
2912
2829
  };
2913
2830
 
2914
- const swalPromise = (instance, domCache, innerParams) => {
2915
- return new Promise((resolve, reject) => {
2916
- // functions to handle all closings/dismissals
2917
- const dismissWith = dismiss => {
2918
- instance.closePopup({
2919
- isDismissed: true,
2920
- dismiss
2921
- });
2831
+ const prepareResolveValue = resolveValue => {
2832
+ // When user calls Swal.close()
2833
+ if (typeof resolveValue === 'undefined') {
2834
+ return {
2835
+ isConfirmed: false,
2836
+ isDenied: false,
2837
+ isDismissed: true
2922
2838
  };
2839
+ }
2923
2840
 
2924
- privateMethods.swalPromiseResolve.set(instance, resolve);
2925
- privateMethods.swalPromiseReject.set(instance, reject);
2841
+ return Object.assign({
2842
+ isConfirmed: false,
2843
+ isDenied: false,
2844
+ isDismissed: false
2845
+ }, resolveValue);
2846
+ };
2926
2847
 
2927
- domCache.confirmButton.onclick = () => handleConfirmButtonClick(instance);
2848
+ const handlePopupAnimation = (instance, popup, innerParams) => {
2849
+ const container = getContainer(); // If animation is supported, animate
2928
2850
 
2929
- domCache.denyButton.onclick = () => handleDenyButtonClick(instance);
2851
+ const animationIsSupported = animationEndEvent && hasCssAnimation(popup);
2930
2852
 
2931
- domCache.cancelButton.onclick = () => handleCancelButtonClick(instance, dismissWith);
2853
+ if (typeof innerParams.willClose === 'function') {
2854
+ innerParams.willClose(popup);
2855
+ }
2932
2856
 
2933
- domCache.closeButton.onclick = () => dismissWith(DismissReason.close);
2857
+ if (animationIsSupported) {
2858
+ animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose);
2859
+ } else {
2860
+ // Otherwise, remove immediately
2861
+ removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose);
2862
+ }
2863
+ };
2934
2864
 
2935
- handlePopupClick(instance, domCache, dismissWith);
2936
- addKeydownHandler(instance, globalState, innerParams, dismissWith);
2937
- handleInputOptionsAndValue(instance, innerParams);
2938
- openPopup(innerParams);
2939
- setupTimer(globalState, innerParams, dismissWith);
2940
- initFocus(domCache, innerParams); // Scroll container to top on open (#1247, #1946)
2865
+ const animatePopup = (instance, popup, container, returnFocus, didClose) => {
2866
+ globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose);
2867
+ popup.addEventListener(animationEndEvent, function (e) {
2868
+ if (e.target === popup) {
2869
+ globalState.swalCloseEventFinishedCallback();
2870
+ delete globalState.swalCloseEventFinishedCallback;
2871
+ }
2872
+ });
2873
+ };
2874
+
2875
+ const triggerDidCloseAndDispose = (instance, didClose) => {
2876
+ setTimeout(() => {
2877
+ if (typeof didClose === 'function') {
2878
+ didClose.bind(instance.params)();
2879
+ }
2941
2880
 
2942
- setTimeout(() => {
2943
- domCache.container.scrollTop = 0;
2944
- });
2881
+ instance._destroy();
2945
2882
  });
2946
2883
  };
2947
2884
 
2948
- const populateDomCache = instance => {
2949
- const domCache = {
2950
- popup: getPopup(),
2951
- container: getContainer(),
2952
- actions: getActions(),
2953
- confirmButton: getConfirmButton(),
2954
- denyButton: getDenyButton(),
2955
- cancelButton: getCancelButton(),
2956
- loader: getLoader(),
2957
- closeButton: getCloseButton(),
2958
- validationMessage: getValidationMessage(),
2959
- progressSteps: getProgressSteps()
2960
- };
2961
- privateProps.domCache.set(instance, domCache);
2962
- return domCache;
2963
- };
2885
+ function setButtonsDisabled(instance, buttons, disabled) {
2886
+ const domCache = privateProps.domCache.get(instance);
2887
+ buttons.forEach(button => {
2888
+ domCache[button].disabled = disabled;
2889
+ });
2890
+ }
2964
2891
 
2965
- const setupTimer = (globalState$$1, innerParams, dismissWith) => {
2966
- const timerProgressBar = getTimerProgressBar();
2967
- hide(timerProgressBar);
2892
+ function setInputDisabled(input, disabled) {
2893
+ if (!input) {
2894
+ return false;
2895
+ }
2968
2896
 
2969
- if (innerParams.timer) {
2970
- globalState$$1.timeout = new Timer(() => {
2971
- dismissWith('timer');
2972
- delete globalState$$1.timeout;
2973
- }, innerParams.timer);
2897
+ if (input.type === 'radio') {
2898
+ const radiosContainer = input.parentNode.parentNode;
2899
+ const radios = radiosContainer.querySelectorAll('input');
2974
2900
 
2975
- if (innerParams.timerProgressBar) {
2976
- show(timerProgressBar);
2977
- setTimeout(() => {
2978
- if (globalState$$1.timeout && globalState$$1.timeout.running) {
2979
- // timer can be already stopped or unset at this point
2980
- animateTimerProgressBar(innerParams.timer);
2981
- }
2982
- });
2901
+ for (let i = 0; i < radios.length; i++) {
2902
+ radios[i].disabled = disabled;
2983
2903
  }
2904
+ } else {
2905
+ input.disabled = disabled;
2984
2906
  }
2985
- };
2907
+ }
2986
2908
 
2987
- const initFocus = (domCache, innerParams) => {
2988
- if (innerParams.toast) {
2989
- return;
2990
- }
2909
+ function enableButtons() {
2910
+ setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
2911
+ }
2912
+ function disableButtons() {
2913
+ setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
2914
+ }
2915
+ function enableInput() {
2916
+ return setInputDisabled(this.getInput(), false);
2917
+ }
2918
+ function disableInput() {
2919
+ return setInputDisabled(this.getInput(), true);
2920
+ }
2991
2921
 
2992
- if (!callIfFunction(innerParams.allowEnterKey)) {
2993
- return blurActiveElement();
2994
- }
2922
+ function showValidationMessage(error) {
2923
+ const domCache = privateProps.domCache.get(this);
2924
+ const params = privateProps.innerParams.get(this);
2925
+ setInnerHtml(domCache.validationMessage, error);
2926
+ domCache.validationMessage.className = swalClasses['validation-message'];
2995
2927
 
2996
- if (!focusButton(domCache, innerParams)) {
2997
- setFocus(innerParams, -1, 1);
2928
+ if (params.customClass && params.customClass.validationMessage) {
2929
+ addClass(domCache.validationMessage, params.customClass.validationMessage);
2998
2930
  }
2999
- };
3000
2931
 
3001
- const focusButton = (domCache, innerParams) => {
3002
- if (innerParams.focusDeny && isVisible(domCache.denyButton)) {
3003
- domCache.denyButton.focus();
3004
- return true;
3005
- }
2932
+ show(domCache.validationMessage);
2933
+ const input = this.getInput();
3006
2934
 
3007
- if (innerParams.focusCancel && isVisible(domCache.cancelButton)) {
3008
- domCache.cancelButton.focus();
3009
- return true;
2935
+ if (input) {
2936
+ input.setAttribute('aria-invalid', true);
2937
+ input.setAttribute('aria-describedby', swalClasses['validation-message']);
2938
+ focusInput(input);
2939
+ addClass(input, swalClasses.inputerror);
3010
2940
  }
2941
+ } // Hide block with validation message
3011
2942
 
3012
- if (innerParams.focusConfirm && isVisible(domCache.confirmButton)) {
3013
- domCache.confirmButton.focus();
3014
- return true;
2943
+ function resetValidationMessage$1() {
2944
+ const domCache = privateProps.domCache.get(this);
2945
+
2946
+ if (domCache.validationMessage) {
2947
+ hide(domCache.validationMessage);
3015
2948
  }
3016
2949
 
3017
- return false;
3018
- };
2950
+ const input = this.getInput();
3019
2951
 
3020
- const blurActiveElement = () => {
3021
- if (document.activeElement && typeof document.activeElement.blur === 'function') {
3022
- document.activeElement.blur();
2952
+ if (input) {
2953
+ input.removeAttribute('aria-invalid');
2954
+ input.removeAttribute('aria-describedby');
2955
+ removeClass(input, swalClasses.inputerror);
3023
2956
  }
3024
- };
2957
+ }
2958
+
2959
+ function getProgressSteps$1() {
2960
+ const domCache = privateProps.domCache.get(this);
2961
+ return domCache.progressSteps;
2962
+ }
3025
2963
 
3026
2964
  /**
3027
2965
  * Updates popup parameters.
@@ -3038,7 +2976,7 @@
3038
2976
  const validUpdatableParams = {}; // assign valid params from `params` to `defaults`
3039
2977
 
3040
2978
  Object.keys(params).forEach(param => {
3041
- if (Swal.isUpdatableParameter(param)) {
2979
+ if (isUpdatableParameter(param)) {
3042
2980
  validUpdatableParams[param] = params[param];
3043
2981
  } else {
3044
2982
  warn("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"));
@@ -3132,7 +3070,6 @@
3132
3070
  showValidationMessage: showValidationMessage,
3133
3071
  resetValidationMessage: resetValidationMessage$1,
3134
3072
  getProgressSteps: getProgressSteps$1,
3135
- _main: _main,
3136
3073
  update: update,
3137
3074
  _destroy: _destroy
3138
3075
  });
@@ -3146,7 +3083,7 @@
3146
3083
  return;
3147
3084
  }
3148
3085
 
3149
- currentInstance = this;
3086
+ currentInstance = this; // @ts-ignore
3150
3087
 
3151
3088
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
3152
3089
  args[_key] = arguments[_key];
@@ -3160,11 +3097,41 @@
3160
3097
  enumerable: true,
3161
3098
  configurable: true
3162
3099
  }
3163
- });
3100
+ }); // @ts-ignore
3164
3101
 
3165
3102
  const promise = this._main(this.params);
3166
3103
 
3167
3104
  privateProps.promise.set(this, promise);
3105
+ }
3106
+
3107
+ _main(userParams) {
3108
+ let mixinParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3109
+ showWarningsForParams(Object.assign({}, mixinParams, userParams));
3110
+
3111
+ if (globalState.currentInstance) {
3112
+ globalState.currentInstance._destroy();
3113
+
3114
+ if (isModal()) {
3115
+ unsetAriaHidden();
3116
+ }
3117
+ }
3118
+
3119
+ globalState.currentInstance = this;
3120
+ const innerParams = prepareParams(userParams, mixinParams);
3121
+ setParameters(innerParams);
3122
+ Object.freeze(innerParams); // clear the previous timer
3123
+
3124
+ if (globalState.timeout) {
3125
+ globalState.timeout.stop();
3126
+ delete globalState.timeout;
3127
+ } // clear the restore focus timeout
3128
+
3129
+
3130
+ clearTimeout(globalState.restoreFocusTimeout);
3131
+ const domCache = populateDomCache(this);
3132
+ render(this, innerParams);
3133
+ privateProps.innerParams.set(this, innerParams);
3134
+ return swalPromise(this, domCache, innerParams);
3168
3135
  } // `catch` cannot be the name of a module export, so we define our thenable methods here instead
3169
3136
 
3170
3137
 
@@ -3178,7 +3145,128 @@
3178
3145
  return promise.finally(onFinally);
3179
3146
  }
3180
3147
 
3181
- } // Assign instance methods from src/instanceMethods/*.js to prototype
3148
+ }
3149
+
3150
+ const swalPromise = (instance, domCache, innerParams) => {
3151
+ return new Promise((resolve, reject) => {
3152
+ // functions to handle all closings/dismissals
3153
+ const dismissWith = dismiss => {
3154
+ instance.closePopup({
3155
+ isDismissed: true,
3156
+ dismiss
3157
+ });
3158
+ };
3159
+
3160
+ privateMethods.swalPromiseResolve.set(instance, resolve);
3161
+ privateMethods.swalPromiseReject.set(instance, reject);
3162
+
3163
+ domCache.confirmButton.onclick = () => handleConfirmButtonClick(instance);
3164
+
3165
+ domCache.denyButton.onclick = () => handleDenyButtonClick(instance);
3166
+
3167
+ domCache.cancelButton.onclick = () => handleCancelButtonClick(instance, dismissWith);
3168
+
3169
+ domCache.closeButton.onclick = () => dismissWith(DismissReason.close);
3170
+
3171
+ handlePopupClick(instance, domCache, dismissWith);
3172
+ addKeydownHandler(instance, globalState, innerParams, dismissWith);
3173
+ handleInputOptionsAndValue(instance, innerParams);
3174
+ openPopup(innerParams);
3175
+ setupTimer(globalState, innerParams, dismissWith);
3176
+ initFocus(domCache, innerParams); // Scroll container to top on open (#1247, #1946)
3177
+
3178
+ setTimeout(() => {
3179
+ domCache.container.scrollTop = 0;
3180
+ });
3181
+ });
3182
+ };
3183
+
3184
+ const prepareParams = (userParams, mixinParams) => {
3185
+ const templateParams = getTemplateParams(userParams);
3186
+ const params = Object.assign({}, defaultParams, mixinParams, templateParams, userParams); // precedence is described in #2131
3187
+
3188
+ params.showClass = Object.assign({}, defaultParams.showClass, params.showClass);
3189
+ params.hideClass = Object.assign({}, defaultParams.hideClass, params.hideClass);
3190
+ return params;
3191
+ };
3192
+
3193
+ const populateDomCache = instance => {
3194
+ const domCache = {
3195
+ popup: getPopup(),
3196
+ container: getContainer(),
3197
+ actions: getActions(),
3198
+ confirmButton: getConfirmButton(),
3199
+ denyButton: getDenyButton(),
3200
+ cancelButton: getCancelButton(),
3201
+ loader: getLoader(),
3202
+ closeButton: getCloseButton(),
3203
+ validationMessage: getValidationMessage(),
3204
+ progressSteps: getProgressSteps()
3205
+ };
3206
+ privateProps.domCache.set(instance, domCache);
3207
+ return domCache;
3208
+ };
3209
+
3210
+ const setupTimer = (globalState$$1, innerParams, dismissWith) => {
3211
+ const timerProgressBar = getTimerProgressBar();
3212
+ hide(timerProgressBar);
3213
+
3214
+ if (innerParams.timer) {
3215
+ globalState$$1.timeout = new Timer(() => {
3216
+ dismissWith('timer');
3217
+ delete globalState$$1.timeout;
3218
+ }, innerParams.timer);
3219
+
3220
+ if (innerParams.timerProgressBar) {
3221
+ show(timerProgressBar);
3222
+ setTimeout(() => {
3223
+ if (globalState$$1.timeout && globalState$$1.timeout.running) {
3224
+ // timer can be already stopped or unset at this point
3225
+ animateTimerProgressBar(innerParams.timer);
3226
+ }
3227
+ });
3228
+ }
3229
+ }
3230
+ };
3231
+
3232
+ const initFocus = (domCache, innerParams) => {
3233
+ if (innerParams.toast) {
3234
+ return;
3235
+ }
3236
+
3237
+ if (!callIfFunction(innerParams.allowEnterKey)) {
3238
+ return blurActiveElement();
3239
+ }
3240
+
3241
+ if (!focusButton(domCache, innerParams)) {
3242
+ setFocus(innerParams, -1, 1);
3243
+ }
3244
+ };
3245
+
3246
+ const focusButton = (domCache, innerParams) => {
3247
+ if (innerParams.focusDeny && isVisible(domCache.denyButton)) {
3248
+ domCache.denyButton.focus();
3249
+ return true;
3250
+ }
3251
+
3252
+ if (innerParams.focusCancel && isVisible(domCache.cancelButton)) {
3253
+ domCache.cancelButton.focus();
3254
+ return true;
3255
+ }
3256
+
3257
+ if (innerParams.focusConfirm && isVisible(domCache.confirmButton)) {
3258
+ domCache.confirmButton.focus();
3259
+ return true;
3260
+ }
3261
+
3262
+ return false;
3263
+ };
3264
+
3265
+ const blurActiveElement = () => {
3266
+ if (document.activeElement instanceof HTMLElement && typeof document.activeElement.blur === 'function') {
3267
+ document.activeElement.blur();
3268
+ }
3269
+ }; // Assign instance methods from src/instanceMethods/*.js to prototype
3182
3270
 
3183
3271
 
3184
3272
  Object.assign(SweetAlert.prototype, instanceMethods); // Assign static methods from src/staticMethods/*.js to constructor
@@ -3193,9 +3281,10 @@
3193
3281
  };
3194
3282
  });
3195
3283
  SweetAlert.DismissReason = DismissReason;
3196
- SweetAlert.version = '11.2.2';
3284
+ SweetAlert.version = '11.3.3';
3285
+
3286
+ const Swal = SweetAlert; // @ts-ignore
3197
3287
 
3198
- const Swal = SweetAlert;
3199
3288
  Swal.default = Swal;
3200
3289
 
3201
3290
  return Swal;