sweetalert2 11.4.30 → 11.4.31

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.4.30
2
+ * sweetalert2 v11.4.31
3
3
  * Released under the MIT License.
4
4
  */
5
5
  (function (global, factory) {
@@ -8,6 +8,40 @@
8
8
  (global = global || self, global.Sweetalert2 = factory());
9
9
  }(this, function () { 'use strict';
10
10
 
11
+ /**
12
+ * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
13
+ * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
14
+ * This is the approach that Babel will probably take to implement private methods/fields
15
+ * https://github.com/tc39/proposal-private-methods
16
+ * https://github.com/babel/babel/pull/7555
17
+ * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
18
+ * then we can use that language feature.
19
+ */
20
+ var privateProps = {
21
+ awaitingPromise: new WeakMap(),
22
+ promise: new WeakMap(),
23
+ innerParams: new WeakMap(),
24
+ domCache: new WeakMap()
25
+ };
26
+
27
+ const swalPrefix = 'swal2-';
28
+ /**
29
+ * @param {string[]} items
30
+ * @returns {object}
31
+ */
32
+
33
+ const prefix = items => {
34
+ const result = {};
35
+
36
+ for (const i in items) {
37
+ result[items[i]] = swalPrefix + items[i];
38
+ }
39
+
40
+ return result;
41
+ };
42
+ 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', 'no-war']);
43
+ const iconTypes = prefix(['success', 'warning', 'info', 'question', 'error']);
44
+
11
45
  const consolePrefix = 'SweetAlert2:';
12
46
  /**
13
47
  * Filter the unique values into a new array
@@ -117,198 +151,6 @@
117
151
 
118
152
  const getRandomElement = arr => arr[Math.floor(Math.random() * arr.length)];
119
153
 
120
- const defaultParams = {
121
- title: '',
122
- titleText: '',
123
- text: '',
124
- html: '',
125
- footer: '',
126
- icon: undefined,
127
- iconColor: undefined,
128
- iconHtml: undefined,
129
- template: undefined,
130
- toast: false,
131
- showClass: {
132
- popup: 'swal2-show',
133
- backdrop: 'swal2-backdrop-show',
134
- icon: 'swal2-icon-show'
135
- },
136
- hideClass: {
137
- popup: 'swal2-hide',
138
- backdrop: 'swal2-backdrop-hide',
139
- icon: 'swal2-icon-hide'
140
- },
141
- customClass: {},
142
- target: 'body',
143
- color: undefined,
144
- backdrop: true,
145
- heightAuto: true,
146
- allowOutsideClick: true,
147
- allowEscapeKey: true,
148
- allowEnterKey: true,
149
- stopKeydownPropagation: true,
150
- keydownListenerCapture: false,
151
- showConfirmButton: true,
152
- showDenyButton: false,
153
- showCancelButton: false,
154
- preConfirm: undefined,
155
- preDeny: undefined,
156
- confirmButtonText: 'OK',
157
- confirmButtonAriaLabel: '',
158
- confirmButtonColor: undefined,
159
- denyButtonText: 'No',
160
- denyButtonAriaLabel: '',
161
- denyButtonColor: undefined,
162
- cancelButtonText: 'Cancel',
163
- cancelButtonAriaLabel: '',
164
- cancelButtonColor: undefined,
165
- buttonsStyling: true,
166
- reverseButtons: false,
167
- focusConfirm: true,
168
- focusDeny: false,
169
- focusCancel: false,
170
- returnFocus: true,
171
- showCloseButton: false,
172
- closeButtonHtml: '×',
173
- closeButtonAriaLabel: 'Close this dialog',
174
- loaderHtml: '',
175
- showLoaderOnConfirm: false,
176
- showLoaderOnDeny: false,
177
- imageUrl: undefined,
178
- imageWidth: undefined,
179
- imageHeight: undefined,
180
- imageAlt: '',
181
- timer: undefined,
182
- timerProgressBar: false,
183
- width: undefined,
184
- padding: undefined,
185
- background: undefined,
186
- input: undefined,
187
- inputPlaceholder: '',
188
- inputLabel: '',
189
- inputValue: '',
190
- inputOptions: {},
191
- inputAutoTrim: true,
192
- inputAttributes: {},
193
- inputValidator: undefined,
194
- returnInputValueOnDeny: false,
195
- validationMessage: undefined,
196
- grow: false,
197
- position: 'center',
198
- progressSteps: [],
199
- currentProgressStep: undefined,
200
- progressStepsDistance: undefined,
201
- willOpen: undefined,
202
- didOpen: undefined,
203
- didRender: undefined,
204
- willClose: undefined,
205
- didClose: undefined,
206
- didDestroy: undefined,
207
- scrollbarPadding: true
208
- };
209
- 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'];
210
- const deprecatedParams = {};
211
- const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];
212
- /**
213
- * Is valid parameter
214
- *
215
- * @param {string} paramName
216
- * @returns {boolean}
217
- */
218
-
219
- const isValidParameter = paramName => {
220
- return Object.prototype.hasOwnProperty.call(defaultParams, paramName);
221
- };
222
- /**
223
- * Is valid parameter for Swal.update() method
224
- *
225
- * @param {string} paramName
226
- * @returns {boolean}
227
- */
228
-
229
- const isUpdatableParameter = paramName => {
230
- return updatableParams.indexOf(paramName) !== -1;
231
- };
232
- /**
233
- * Is deprecated parameter
234
- *
235
- * @param {string} paramName
236
- * @returns {string | undefined}
237
- */
238
-
239
- const isDeprecatedParameter = paramName => {
240
- return deprecatedParams[paramName];
241
- };
242
- /**
243
- * @param {string} param
244
- */
245
-
246
- const checkIfParamIsValid = param => {
247
- if (!isValidParameter(param)) {
248
- warn("Unknown parameter \"".concat(param, "\""));
249
- }
250
- };
251
- /**
252
- * @param {string} param
253
- */
254
-
255
-
256
- const checkIfToastParamIsValid = param => {
257
- if (toastIncompatibleParams.includes(param)) {
258
- warn("The parameter \"".concat(param, "\" is incompatible with toasts"));
259
- }
260
- };
261
- /**
262
- * @param {string} param
263
- */
264
-
265
-
266
- const checkIfParamIsDeprecated = param => {
267
- if (isDeprecatedParameter(param)) {
268
- warnAboutDeprecation(param, isDeprecatedParameter(param));
269
- }
270
- };
271
- /**
272
- * Show relevant warnings for given params
273
- *
274
- * @param {SweetAlertOptions} params
275
- */
276
-
277
-
278
- const showWarningsForParams = params => {
279
- if (!params.backdrop && params.allowOutsideClick) {
280
- warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
281
- }
282
-
283
- for (const param in params) {
284
- checkIfParamIsValid(param);
285
-
286
- if (params.toast) {
287
- checkIfToastParamIsValid(param);
288
- }
289
-
290
- checkIfParamIsDeprecated(param);
291
- }
292
- };
293
-
294
- const swalPrefix = 'swal2-';
295
- /**
296
- * @param {string[]} items
297
- * @returns {object}
298
- */
299
-
300
- const prefix = items => {
301
- const result = {};
302
-
303
- for (const i in items) {
304
- result[items[i]] = swalPrefix + items[i];
305
- }
306
-
307
- return result;
308
- };
309
- 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', 'no-war']);
310
- const iconTypes = prefix(['success', 'warning', 'info', 'question', 'error']);
311
-
312
154
  /**
313
155
  * Gets the popup container which contains the backdrop and the popup itself.
314
156
  *
@@ -760,13 +602,6 @@
760
602
  timerProgressBar.style.width = "".concat(timerProgressBarPercent, "%");
761
603
  };
762
604
 
763
- /**
764
- * Detect Node env
765
- *
766
- * @returns {boolean}
767
- */
768
- const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined';
769
-
770
605
  const RESTORE_FOCUS_TIMEOUT = 100;
771
606
 
772
607
  /** @type {GlobalState} */
@@ -806,6 +641,13 @@
806
641
  });
807
642
  };
808
643
 
644
+ /**
645
+ * Detect Node env
646
+ *
647
+ * @returns {boolean}
648
+ */
649
+ const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined';
650
+
809
651
  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, '');
810
652
  /**
811
653
  * @returns {boolean}
@@ -1114,6 +956,20 @@
1114
956
  addClass(button, params["".concat(buttonType, "ButtonClass")]);
1115
957
  }
1116
958
 
959
+ /**
960
+ * @param {SweetAlert2} instance
961
+ * @param {SweetAlertOptions} params
962
+ */
963
+
964
+ const renderCloseButton = (instance, params) => {
965
+ const closeButton = getCloseButton();
966
+ setInnerHtml(closeButton, params.closeButtonHtml); // Custom class
967
+
968
+ applyCustomClass(closeButton, params, 'closeButton');
969
+ toggle(closeButton, params.showCloseButton);
970
+ closeButton.setAttribute('aria-label', params.closeButtonAriaLabel);
971
+ };
972
+
1117
973
  /**
1118
974
  * @param {SweetAlert2} instance
1119
975
  * @param {SweetAlertOptions} params
@@ -1174,22 +1030,6 @@
1174
1030
  }
1175
1031
  }
1176
1032
 
1177
- /**
1178
- * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
1179
- * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
1180
- * This is the approach that Babel will probably take to implement private methods/fields
1181
- * https://github.com/tc39/proposal-private-methods
1182
- * https://github.com/babel/babel/pull/7555
1183
- * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
1184
- * then we can use that language feature.
1185
- */
1186
- var privateProps = {
1187
- awaitingPromise: new WeakMap(),
1188
- promise: new WeakMap(),
1189
- innerParams: new WeakMap(),
1190
- domCache: new WeakMap()
1191
- };
1192
-
1193
1033
  /// <reference path="../../../../sweetalert2.d.ts"/>
1194
1034
  /** @type {InputClass[]} */
1195
1035
 
@@ -1519,20 +1359,6 @@
1519
1359
  applyCustomClass(footer, params, 'footer');
1520
1360
  };
1521
1361
 
1522
- /**
1523
- * @param {SweetAlert2} instance
1524
- * @param {SweetAlertOptions} params
1525
- */
1526
-
1527
- const renderCloseButton = (instance, params) => {
1528
- const closeButton = getCloseButton();
1529
- setInnerHtml(closeButton, params.closeButtonHtml); // Custom class
1530
-
1531
- applyCustomClass(closeButton, params, 'closeButton');
1532
- toggle(closeButton, params.showCloseButton);
1533
- closeButton.setAttribute('aria-label', params.closeButtonAriaLabel);
1534
- };
1535
-
1536
1362
  /**
1537
1363
  * @param {SweetAlert2} instance
1538
1364
  * @param {SweetAlertOptions} params
@@ -1684,6 +1510,69 @@
1684
1510
  applyCustomClass(image, params, 'image');
1685
1511
  };
1686
1512
 
1513
+ /**
1514
+ * @param {SweetAlert2} instance
1515
+ * @param {SweetAlertOptions} params
1516
+ */
1517
+
1518
+ const renderPopup = (instance, params) => {
1519
+ const container = getContainer();
1520
+ const popup = getPopup(); // Width
1521
+ // https://github.com/sweetalert2/sweetalert2/issues/2170
1522
+
1523
+ if (params.toast) {
1524
+ applyNumericalStyle(container, 'width', params.width);
1525
+ popup.style.width = '100%';
1526
+ popup.insertBefore(getLoader(), getIcon());
1527
+ } else {
1528
+ applyNumericalStyle(popup, 'width', params.width);
1529
+ } // Padding
1530
+
1531
+
1532
+ applyNumericalStyle(popup, 'padding', params.padding); // Color
1533
+
1534
+ if (params.color) {
1535
+ popup.style.color = params.color;
1536
+ } // Background
1537
+
1538
+
1539
+ if (params.background) {
1540
+ popup.style.background = params.background;
1541
+ }
1542
+
1543
+ hide(getValidationMessage()); // Classes
1544
+
1545
+ addClasses(popup, params);
1546
+ };
1547
+ /**
1548
+ * @param {HTMLElement} popup
1549
+ * @param {SweetAlertOptions} params
1550
+ */
1551
+
1552
+ const addClasses = (popup, params) => {
1553
+ // Default Class + showClass when updating Swal.update({})
1554
+ popup.className = "".concat(swalClasses.popup, " ").concat(isVisible(popup) ? params.showClass.popup : '');
1555
+
1556
+ if (params.toast) {
1557
+ addClass([document.documentElement, document.body], swalClasses['toast-shown']);
1558
+ addClass(popup, swalClasses.toast);
1559
+ } else {
1560
+ addClass(popup, swalClasses.modal);
1561
+ } // Custom class
1562
+
1563
+
1564
+ applyCustomClass(popup, params, 'popup');
1565
+
1566
+ if (typeof params.customClass === 'string') {
1567
+ addClass(popup, params.customClass);
1568
+ } // Icon class (#1842)
1569
+
1570
+
1571
+ if (params.icon) {
1572
+ addClass(popup, swalClasses["icon-".concat(params.icon)]);
1573
+ }
1574
+ };
1575
+
1687
1576
  /**
1688
1577
  * @param {SweetAlert2} instance
1689
1578
  * @param {SweetAlertOptions} params
@@ -1771,85 +1660,102 @@
1771
1660
  * @param {SweetAlertOptions} params
1772
1661
  */
1773
1662
 
1774
- const renderPopup = (instance, params) => {
1775
- const container = getContainer();
1776
- const popup = getPopup(); // Width
1777
- // https://github.com/sweetalert2/sweetalert2/issues/2170
1663
+ const render = (instance, params) => {
1664
+ renderPopup(instance, params);
1665
+ renderContainer(instance, params);
1666
+ renderProgressSteps(instance, params);
1667
+ renderIcon(instance, params);
1668
+ renderImage(instance, params);
1669
+ renderTitle(instance, params);
1670
+ renderCloseButton(instance, params);
1671
+ renderContent(instance, params);
1672
+ renderActions(instance, params);
1673
+ renderFooter(instance, params);
1778
1674
 
1779
- if (params.toast) {
1780
- applyNumericalStyle(container, 'width', params.width);
1781
- popup.style.width = '100%';
1782
- popup.insertBefore(getLoader(), getIcon());
1783
- } else {
1784
- applyNumericalStyle(popup, 'width', params.width);
1785
- } // Padding
1675
+ if (typeof params.didRender === 'function') {
1676
+ params.didRender(getPopup());
1677
+ }
1678
+ };
1786
1679
 
1680
+ /**
1681
+ * Hides loader and shows back the button which was hidden by .showLoading()
1682
+ */
1787
1683
 
1788
- applyNumericalStyle(popup, 'padding', params.padding); // Color
1684
+ function hideLoading() {
1685
+ // do nothing if popup is closed
1686
+ const innerParams = privateProps.innerParams.get(this);
1789
1687
 
1790
- if (params.color) {
1791
- popup.style.color = params.color;
1792
- } // Background
1688
+ if (!innerParams) {
1689
+ return;
1690
+ }
1793
1691
 
1692
+ const domCache = privateProps.domCache.get(this);
1693
+ hide(domCache.loader);
1794
1694
 
1795
- if (params.background) {
1796
- popup.style.background = params.background;
1695
+ if (isToast()) {
1696
+ if (innerParams.icon) {
1697
+ show(getIcon());
1698
+ }
1699
+ } else {
1700
+ showRelatedButton(domCache);
1797
1701
  }
1798
1702
 
1799
- hide(getValidationMessage()); // Classes
1703
+ removeClass([domCache.popup, domCache.actions], swalClasses.loading);
1704
+ domCache.popup.removeAttribute('aria-busy');
1705
+ domCache.popup.removeAttribute('data-loading');
1706
+ domCache.confirmButton.disabled = false;
1707
+ domCache.denyButton.disabled = false;
1708
+ domCache.cancelButton.disabled = false;
1709
+ }
1800
1710
 
1801
- addClasses(popup, params);
1711
+ const showRelatedButton = domCache => {
1712
+ const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'));
1713
+
1714
+ if (buttonToReplace.length) {
1715
+ show(buttonToReplace[0], 'inline-block');
1716
+ } else if (allButtonsAreHidden()) {
1717
+ hide(domCache.actions);
1718
+ }
1802
1719
  };
1720
+
1803
1721
  /**
1804
- * @param {HTMLElement} popup
1805
- * @param {SweetAlertOptions} params
1722
+ * Gets the input DOM node, this method works with input parameter.
1723
+ * @returns {HTMLElement | null}
1806
1724
  */
1807
1725
 
1808
- const addClasses = (popup, params) => {
1809
- // Default Class + showClass when updating Swal.update({})
1810
- popup.className = "".concat(swalClasses.popup, " ").concat(isVisible(popup) ? params.showClass.popup : '');
1811
-
1812
- if (params.toast) {
1813
- addClass([document.documentElement, document.body], swalClasses['toast-shown']);
1814
- addClass(popup, swalClasses.toast);
1815
- } else {
1816
- addClass(popup, swalClasses.modal);
1817
- } // Custom class
1818
-
1726
+ function getInput$1(instance) {
1727
+ const innerParams = privateProps.innerParams.get(instance || this);
1728
+ const domCache = privateProps.domCache.get(instance || this);
1819
1729
 
1820
- applyCustomClass(popup, params, 'popup');
1730
+ if (!domCache) {
1731
+ return null;
1732
+ }
1821
1733
 
1822
- if (typeof params.customClass === 'string') {
1823
- addClass(popup, params.customClass);
1824
- } // Icon class (#1842)
1734
+ return getInput(domCache.popup, innerParams.input);
1735
+ }
1825
1736
 
1737
+ /*
1738
+ * Global function to determine if SweetAlert2 popup is shown
1739
+ */
1826
1740
 
1827
- if (params.icon) {
1828
- addClass(popup, swalClasses["icon-".concat(params.icon)]);
1829
- }
1741
+ const isVisible$1 = () => {
1742
+ return isVisible(getPopup());
1830
1743
  };
1744
+ /*
1745
+ * Global function to click 'Confirm' button
1746
+ */
1831
1747
 
1832
- /**
1833
- * @param {SweetAlert2} instance
1834
- * @param {SweetAlertOptions} params
1748
+ const clickConfirm = () => getConfirmButton() && getConfirmButton().click();
1749
+ /*
1750
+ * Global function to click 'Deny' button
1835
1751
  */
1836
1752
 
1837
- const render = (instance, params) => {
1838
- renderPopup(instance, params);
1839
- renderContainer(instance, params);
1840
- renderProgressSteps(instance, params);
1841
- renderIcon(instance, params);
1842
- renderImage(instance, params);
1843
- renderTitle(instance, params);
1844
- renderCloseButton(instance, params);
1845
- renderContent(instance, params);
1846
- renderActions(instance, params);
1847
- renderFooter(instance, params);
1753
+ const clickDeny = () => getDenyButton() && getDenyButton().click();
1754
+ /*
1755
+ * Global function to click 'Cancel' button
1756
+ */
1848
1757
 
1849
- if (typeof params.didRender === 'function') {
1850
- params.didRender(getPopup());
1851
- }
1852
- };
1758
+ const clickCancel = () => getCancelButton() && getCancelButton().click();
1853
1759
 
1854
1760
  const DismissReason = Object.freeze({
1855
1761
  cancel: 'cancel',
@@ -1859,408 +1765,244 @@
1859
1765
  timer: 'timer'
1860
1766
  });
1861
1767
 
1862
- // Adding aria-hidden="true" to elements outside of the active modal dialog ensures that
1863
- // elements not within the active modal dialog will not be surfaced if a user opens a screen
1864
- // reader’s list of elements (headings, form controls, landmarks, etc.) in the document.
1768
+ /**
1769
+ * @param {GlobalState} globalState
1770
+ */
1865
1771
 
1866
- const setAriaHidden = () => {
1867
- const bodyChildren = Array.from(document.body.children);
1868
- bodyChildren.forEach(el => {
1869
- if (el === getContainer() || el.contains(getContainer())) {
1870
- return;
1871
- }
1772
+ const removeKeydownHandler = globalState => {
1773
+ if (globalState.keydownTarget && globalState.keydownHandlerAdded) {
1774
+ globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, {
1775
+ capture: globalState.keydownListenerCapture
1776
+ });
1777
+ globalState.keydownHandlerAdded = false;
1778
+ }
1779
+ };
1780
+ /**
1781
+ * @param {SweetAlert2} instance
1782
+ * @param {GlobalState} globalState
1783
+ * @param {SweetAlertOptions} innerParams
1784
+ * @param {*} dismissWith
1785
+ */
1872
1786
 
1873
- if (el.hasAttribute('aria-hidden')) {
1874
- el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden'));
1875
- }
1787
+ const addKeydownHandler = (instance, globalState, innerParams, dismissWith) => {
1788
+ removeKeydownHandler(globalState);
1876
1789
 
1877
- el.setAttribute('aria-hidden', 'true');
1878
- });
1879
- };
1880
- const unsetAriaHidden = () => {
1881
- const bodyChildren = Array.from(document.body.children);
1882
- bodyChildren.forEach(el => {
1883
- if (el.hasAttribute('data-previous-aria-hidden')) {
1884
- el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden'));
1885
- el.removeAttribute('data-previous-aria-hidden');
1886
- } else {
1887
- el.removeAttribute('aria-hidden');
1888
- }
1889
- });
1890
- };
1891
-
1892
- const swalStringParams = ['swal-title', 'swal-html', 'swal-footer'];
1893
- const getTemplateParams = params => {
1894
- const template = typeof params.template === 'string' ? document.querySelector(params.template) : params.template;
1790
+ if (!innerParams.toast) {
1791
+ globalState.keydownHandler = e => keydownHandler(instance, e, dismissWith);
1895
1792
 
1896
- if (!template) {
1897
- return {};
1793
+ globalState.keydownTarget = innerParams.keydownListenerCapture ? window : getPopup();
1794
+ globalState.keydownListenerCapture = innerParams.keydownListenerCapture;
1795
+ globalState.keydownTarget.addEventListener('keydown', globalState.keydownHandler, {
1796
+ capture: globalState.keydownListenerCapture
1797
+ });
1798
+ globalState.keydownHandlerAdded = true;
1898
1799
  }
1899
- /** @type {DocumentFragment} */
1900
-
1901
-
1902
- const templateContent = template.content;
1903
- showWarningsForElements(templateContent);
1904
- const result = Object.assign(getSwalParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams));
1905
- return result;
1906
1800
  };
1907
1801
  /**
1908
- * @param {DocumentFragment} templateContent
1802
+ * @param {SweetAlertOptions} innerParams
1803
+ * @param {number} index
1804
+ * @param {number} increment
1909
1805
  */
1910
1806
 
1911
- const getSwalParams = templateContent => {
1912
- const result = {};
1913
- /** @type {HTMLElement[]} */
1807
+ const setFocus = (innerParams, index, increment) => {
1808
+ const focusableElements = getFocusableElements(); // search for visible elements and select the next possible match
1914
1809
 
1915
- const swalParams = Array.from(templateContent.querySelectorAll('swal-param'));
1916
- swalParams.forEach(param => {
1917
- showWarningsForAttributes(param, ['name', 'value']);
1918
- const paramName = param.getAttribute('name');
1919
- const value = param.getAttribute('value');
1810
+ if (focusableElements.length) {
1811
+ index = index + increment; // rollover to first item
1920
1812
 
1921
- if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {
1922
- result[paramName] = false;
1813
+ if (index === focusableElements.length) {
1814
+ index = 0; // go to last item
1815
+ } else if (index === -1) {
1816
+ index = focusableElements.length - 1;
1923
1817
  }
1924
1818
 
1925
- if (typeof defaultParams[paramName] === 'object') {
1926
- result[paramName] = JSON.parse(value);
1927
- }
1928
- });
1929
- return result;
1819
+ return focusableElements[index].focus();
1820
+ } // no visible focusable elements, focus the popup
1821
+
1822
+
1823
+ getPopup().focus();
1930
1824
  };
1825
+ const arrowKeysNextButton = ['ArrowRight', 'ArrowDown'];
1826
+ const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp'];
1931
1827
  /**
1932
- * @param {DocumentFragment} templateContent
1828
+ * @param {SweetAlert2} instance
1829
+ * @param {KeyboardEvent} e
1830
+ * @param {function} dismissWith
1933
1831
  */
1934
1832
 
1833
+ const keydownHandler = (instance, e, dismissWith) => {
1834
+ const innerParams = privateProps.innerParams.get(instance);
1935
1835
 
1936
- const getSwalButtons = templateContent => {
1937
- const result = {};
1938
- /** @type {HTMLElement[]} */
1836
+ if (!innerParams) {
1837
+ return; // This instance has already been destroyed
1838
+ } // Ignore keydown during IME composition
1839
+ // https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event#ignoring_keydown_during_ime_composition
1840
+ // https://github.com/sweetalert2/sweetalert2/issues/720
1841
+ // https://github.com/sweetalert2/sweetalert2/issues/2406
1939
1842
 
1940
- const swalButtons = Array.from(templateContent.querySelectorAll('swal-button'));
1941
- swalButtons.forEach(button => {
1942
- showWarningsForAttributes(button, ['type', 'color', 'aria-label']);
1943
- const type = button.getAttribute('type');
1944
- result["".concat(type, "ButtonText")] = button.innerHTML;
1945
- result["show".concat(capitalizeFirstLetter(type), "Button")] = true;
1946
1843
 
1947
- if (button.hasAttribute('color')) {
1948
- result["".concat(type, "ButtonColor")] = button.getAttribute('color');
1949
- }
1844
+ if (e.isComposing || e.keyCode === 229) {
1845
+ return;
1846
+ }
1950
1847
 
1951
- if (button.hasAttribute('aria-label')) {
1952
- result["".concat(type, "ButtonAriaLabel")] = button.getAttribute('aria-label');
1953
- }
1954
- });
1955
- return result;
1848
+ if (innerParams.stopKeydownPropagation) {
1849
+ e.stopPropagation();
1850
+ } // ENTER
1851
+
1852
+
1853
+ if (e.key === 'Enter') {
1854
+ handleEnter(instance, e, innerParams);
1855
+ } // TAB
1856
+ else if (e.key === 'Tab') {
1857
+ handleTab(e, innerParams);
1858
+ } // ARROWS - switch focus between buttons
1859
+ else if ([...arrowKeysNextButton, ...arrowKeysPreviousButton].includes(e.key)) {
1860
+ handleArrows(e.key);
1861
+ } // ESC
1862
+ else if (e.key === 'Escape') {
1863
+ handleEsc(e, innerParams, dismissWith);
1864
+ }
1956
1865
  };
1957
1866
  /**
1958
- * @param {DocumentFragment} templateContent
1867
+ * @param {SweetAlert2} instance
1868
+ * @param {KeyboardEvent} e
1869
+ * @param {SweetAlertOptions} innerParams
1959
1870
  */
1960
1871
 
1961
1872
 
1962
- const getSwalImage = templateContent => {
1963
- const result = {};
1964
- /** @type {HTMLElement} */
1965
-
1966
- const image = templateContent.querySelector('swal-image');
1967
-
1968
- if (image) {
1969
- showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']);
1970
-
1971
- if (image.hasAttribute('src')) {
1972
- result.imageUrl = image.getAttribute('src');
1973
- }
1974
-
1975
- if (image.hasAttribute('width')) {
1976
- result.imageWidth = image.getAttribute('width');
1977
- }
1873
+ const handleEnter = (instance, e, innerParams) => {
1874
+ // https://github.com/sweetalert2/sweetalert2/issues/2386
1875
+ if (!callIfFunction(innerParams.allowEnterKey)) {
1876
+ return;
1877
+ }
1978
1878
 
1979
- if (image.hasAttribute('height')) {
1980
- result.imageHeight = image.getAttribute('height');
1879
+ if (e.target && instance.getInput() && e.target instanceof HTMLElement && e.target.outerHTML === instance.getInput().outerHTML) {
1880
+ if (['textarea', 'file'].includes(innerParams.input)) {
1881
+ return; // do not submit
1981
1882
  }
1982
1883
 
1983
- if (image.hasAttribute('alt')) {
1984
- result.imageAlt = image.getAttribute('alt');
1985
- }
1884
+ clickConfirm();
1885
+ e.preventDefault();
1986
1886
  }
1987
-
1988
- return result;
1989
1887
  };
1990
1888
  /**
1991
- * @param {DocumentFragment} templateContent
1889
+ * @param {KeyboardEvent} e
1890
+ * @param {SweetAlertOptions} innerParams
1992
1891
  */
1993
1892
 
1994
1893
 
1995
- const getSwalIcon = templateContent => {
1996
- const result = {};
1997
- /** @type {HTMLElement} */
1998
-
1999
- const icon = templateContent.querySelector('swal-icon');
2000
-
2001
- if (icon) {
2002
- showWarningsForAttributes(icon, ['type', 'color']);
1894
+ const handleTab = (e, innerParams) => {
1895
+ const targetElement = e.target;
1896
+ const focusableElements = getFocusableElements();
1897
+ let btnIndex = -1;
2003
1898
 
2004
- if (icon.hasAttribute('type')) {
2005
- result.icon = icon.getAttribute('type');
1899
+ for (let i = 0; i < focusableElements.length; i++) {
1900
+ if (targetElement === focusableElements[i]) {
1901
+ btnIndex = i;
1902
+ break;
2006
1903
  }
1904
+ } // Cycle to the next button
2007
1905
 
2008
- if (icon.hasAttribute('color')) {
2009
- result.iconColor = icon.getAttribute('color');
2010
- }
2011
1906
 
2012
- result.iconHtml = icon.innerHTML;
1907
+ if (!e.shiftKey) {
1908
+ setFocus(innerParams, btnIndex, 1);
1909
+ } // Cycle to the prev button
1910
+ else {
1911
+ setFocus(innerParams, btnIndex, -1);
2013
1912
  }
2014
1913
 
2015
- return result;
1914
+ e.stopPropagation();
1915
+ e.preventDefault();
2016
1916
  };
2017
1917
  /**
2018
- * @param {DocumentFragment} templateContent
1918
+ * @param {string} key
2019
1919
  */
2020
1920
 
2021
1921
 
2022
- const getSwalInput = templateContent => {
2023
- const result = {};
2024
- /** @type {HTMLElement} */
1922
+ const handleArrows = key => {
1923
+ const confirmButton = getConfirmButton();
1924
+ const denyButton = getDenyButton();
1925
+ const cancelButton = getCancelButton();
2025
1926
 
2026
- const input = templateContent.querySelector('swal-input');
1927
+ if (document.activeElement instanceof HTMLElement && ![confirmButton, denyButton, cancelButton].includes(document.activeElement)) {
1928
+ return;
1929
+ }
2027
1930
 
2028
- if (input) {
2029
- showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value']);
2030
- result.input = input.getAttribute('type') || 'text';
1931
+ const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling';
1932
+ let buttonToFocus = document.activeElement;
2031
1933
 
2032
- if (input.hasAttribute('label')) {
2033
- result.inputLabel = input.getAttribute('label');
2034
- }
1934
+ for (let i = 0; i < getActions().children.length; i++) {
1935
+ buttonToFocus = buttonToFocus[sibling];
2035
1936
 
2036
- if (input.hasAttribute('placeholder')) {
2037
- result.inputPlaceholder = input.getAttribute('placeholder');
1937
+ if (!buttonToFocus) {
1938
+ return;
2038
1939
  }
2039
1940
 
2040
- if (input.hasAttribute('value')) {
2041
- result.inputValue = input.getAttribute('value');
1941
+ if (buttonToFocus instanceof HTMLButtonElement && isVisible(buttonToFocus)) {
1942
+ break;
2042
1943
  }
2043
1944
  }
2044
- /** @type {HTMLElement[]} */
2045
-
2046
-
2047
- const inputOptions = Array.from(templateContent.querySelectorAll('swal-input-option'));
2048
1945
 
2049
- if (inputOptions.length) {
2050
- result.inputOptions = {};
2051
- inputOptions.forEach(option => {
2052
- showWarningsForAttributes(option, ['value']);
2053
- const optionValue = option.getAttribute('value');
2054
- const optionName = option.innerHTML;
2055
- result.inputOptions[optionValue] = optionName;
2056
- });
1946
+ if (buttonToFocus instanceof HTMLButtonElement) {
1947
+ buttonToFocus.focus();
2057
1948
  }
2058
-
2059
- return result;
2060
1949
  };
2061
1950
  /**
2062
- * @param {DocumentFragment} templateContent
2063
- * @param {string[]} paramNames
1951
+ * @param {KeyboardEvent} e
1952
+ * @param {SweetAlertOptions} innerParams
1953
+ * @param {function} dismissWith
2064
1954
  */
2065
1955
 
2066
1956
 
2067
- const getSwalStringParams = (templateContent, paramNames) => {
2068
- const result = {};
2069
-
2070
- for (const i in paramNames) {
2071
- const paramName = paramNames[i];
2072
- /** @type {HTMLElement} */
2073
-
2074
- const tag = templateContent.querySelector(paramName);
2075
-
2076
- if (tag) {
2077
- showWarningsForAttributes(tag, []);
2078
- result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim();
2079
- }
1957
+ const handleEsc = (e, innerParams, dismissWith) => {
1958
+ if (callIfFunction(innerParams.allowEscapeKey)) {
1959
+ e.preventDefault();
1960
+ dismissWith(DismissReason.esc);
2080
1961
  }
1962
+ };
2081
1963
 
2082
- return result;
2083
- };
2084
- /**
2085
- * @param {DocumentFragment} templateContent
2086
- */
2087
-
2088
-
2089
- const showWarningsForElements = templateContent => {
2090
- const allowedElements = swalStringParams.concat(['swal-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']);
2091
- Array.from(templateContent.children).forEach(el => {
2092
- const tagName = el.tagName.toLowerCase();
2093
-
2094
- if (allowedElements.indexOf(tagName) === -1) {
2095
- warn("Unrecognized element <".concat(tagName, ">"));
2096
- }
2097
- });
2098
- };
2099
1964
  /**
2100
- * @param {HTMLElement} el
2101
- * @param {string[]} allowedAttributes
1965
+ * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
1966
+ * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
1967
+ * This is the approach that Babel will probably take to implement private methods/fields
1968
+ * https://github.com/tc39/proposal-private-methods
1969
+ * https://github.com/babel/babel/pull/7555
1970
+ * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
1971
+ * then we can use that language feature.
2102
1972
  */
2103
-
2104
-
2105
- const showWarningsForAttributes = (el, allowedAttributes) => {
2106
- Array.from(el.attributes).forEach(attribute => {
2107
- if (allowedAttributes.indexOf(attribute.name) === -1) {
2108
- 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.')]);
2109
- }
2110
- });
2111
- };
2112
-
2113
- var defaultInputValidators = {
2114
- /**
2115
- * @param {string} string
2116
- * @param {string} validationMessage
2117
- * @returns {Promise<void | string>}
2118
- */
2119
- email: (string, validationMessage) => {
2120
- return /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid email address');
2121
- },
2122
-
2123
- /**
2124
- * @param {string} string
2125
- * @param {string} validationMessage
2126
- * @returns {Promise<void | string>}
2127
- */
2128
- url: (string, validationMessage) => {
2129
- // taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #2013
2130
- return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid URL');
2131
- }
1973
+ var privateMethods = {
1974
+ swalPromiseResolve: new WeakMap(),
1975
+ swalPromiseReject: new WeakMap()
2132
1976
  };
2133
1977
 
2134
- /**
2135
- * @param {SweetAlertOptions} params
2136
- */
2137
-
2138
- function setDefaultInputValidators(params) {
2139
- // Use default `inputValidator` for supported input types if not provided
2140
- if (!params.inputValidator) {
2141
- Object.keys(defaultInputValidators).forEach(key => {
2142
- if (params.input === key) {
2143
- params.inputValidator = defaultInputValidators[key];
2144
- }
2145
- });
2146
- }
2147
- }
2148
- /**
2149
- * @param {SweetAlertOptions} params
2150
- */
2151
-
2152
-
2153
- function validateCustomTargetElement(params) {
2154
- // Determine if the custom target element is valid
2155
- if (!params.target || typeof params.target === 'string' && !document.querySelector(params.target) || typeof params.target !== 'string' && !params.target.appendChild) {
2156
- warn('Target parameter is not valid, defaulting to "body"');
2157
- params.target = 'body';
2158
- }
2159
- }
2160
- /**
2161
- * Set type, text and actions on popup
2162
- *
2163
- * @param {SweetAlertOptions} params
2164
- */
2165
-
2166
-
2167
- function setParameters(params) {
2168
- setDefaultInputValidators(params); // showLoaderOnConfirm && preConfirm
2169
-
2170
- if (params.showLoaderOnConfirm && !params.preConfirm) {
2171
- warn('showLoaderOnConfirm is set to true, but preConfirm is not defined.\n' + 'showLoaderOnConfirm should be used together with preConfirm, see usage example:\n' + 'https://sweetalert2.github.io/#ajax-request');
2172
- }
2173
-
2174
- validateCustomTargetElement(params); // Replace newlines with <br> in title
2175
-
2176
- if (typeof params.title === 'string') {
2177
- params.title = params.title.split('\n').join('<br />');
2178
- }
2179
-
2180
- init(params);
2181
- }
2182
-
2183
- class Timer {
2184
- /**
2185
- * @param {Function} callback
2186
- * @param {number} delay
2187
- */
2188
- constructor(callback, delay) {
2189
- this.callback = callback;
2190
- this.remaining = delay;
2191
- this.running = false;
2192
- this.start();
2193
- }
2194
-
2195
- start() {
2196
- if (!this.running) {
2197
- this.running = true;
2198
- this.started = new Date();
2199
- this.id = setTimeout(this.callback, this.remaining);
2200
- }
2201
-
2202
- return this.remaining;
2203
- }
2204
-
2205
- stop() {
2206
- if (this.running) {
2207
- this.running = false;
2208
- clearTimeout(this.id);
2209
- this.remaining -= new Date().getTime() - this.started.getTime();
2210
- }
2211
-
2212
- return this.remaining;
2213
- }
2214
-
2215
- increase(n) {
2216
- const running = this.running;
2217
-
2218
- if (running) {
2219
- this.stop();
2220
- }
2221
-
2222
- this.remaining += n;
1978
+ // Adding aria-hidden="true" to elements outside of the active modal dialog ensures that
1979
+ // elements not within the active modal dialog will not be surfaced if a user opens a screen
1980
+ // reader’s list of elements (headings, form controls, landmarks, etc.) in the document.
2223
1981
 
2224
- if (running) {
2225
- this.start();
1982
+ const setAriaHidden = () => {
1983
+ const bodyChildren = Array.from(document.body.children);
1984
+ bodyChildren.forEach(el => {
1985
+ if (el === getContainer() || el.contains(getContainer())) {
1986
+ return;
2226
1987
  }
2227
1988
 
2228
- return this.remaining;
2229
- }
2230
-
2231
- getTimerLeft() {
2232
- if (this.running) {
2233
- this.stop();
2234
- this.start();
1989
+ if (el.hasAttribute('aria-hidden')) {
1990
+ el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden'));
2235
1991
  }
2236
1992
 
2237
- return this.remaining;
2238
- }
2239
-
2240
- isRunning() {
2241
- return this.running;
2242
- }
2243
-
2244
- }
2245
-
2246
- const fixScrollbar = () => {
2247
- // for queues, do not do this more than once
2248
- if (states.previousBodyPadding !== null) {
2249
- return;
2250
- } // if the body has overflow
2251
-
2252
-
2253
- if (document.body.scrollHeight > window.innerHeight) {
2254
- // add padding so the content doesn't shift after removal of scrollbar
2255
- states.previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'));
2256
- document.body.style.paddingRight = "".concat(states.previousBodyPadding + measureScrollbar(), "px");
2257
- }
1993
+ el.setAttribute('aria-hidden', 'true');
1994
+ });
2258
1995
  };
2259
- const undoScrollbar = () => {
2260
- if (states.previousBodyPadding !== null) {
2261
- document.body.style.paddingRight = "".concat(states.previousBodyPadding, "px");
2262
- states.previousBodyPadding = null;
2263
- }
1996
+ const unsetAriaHidden = () => {
1997
+ const bodyChildren = Array.from(document.body.children);
1998
+ bodyChildren.forEach(el => {
1999
+ if (el.hasAttribute('data-previous-aria-hidden')) {
2000
+ el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden'));
2001
+ el.removeAttribute('data-previous-aria-hidden');
2002
+ } else {
2003
+ el.removeAttribute('aria-hidden');
2004
+ }
2005
+ });
2264
2006
  };
2265
2007
 
2266
2008
  /* istanbul ignore file */
@@ -2381,220 +2123,658 @@
2381
2123
  }
2382
2124
  };
2383
2125
 
2384
- const SHOW_CLASS_TIMEOUT = 10;
2385
- /**
2386
- * Open popup, add necessary classes and styles, fix scrollbar
2387
- *
2388
- * @param {SweetAlertOptions} params
2389
- */
2126
+ const fixScrollbar = () => {
2127
+ // for queues, do not do this more than once
2128
+ if (states.previousBodyPadding !== null) {
2129
+ return;
2130
+ } // if the body has overflow
2390
2131
 
2391
- const openPopup = params => {
2392
- const container = getContainer();
2393
- const popup = getPopup();
2394
2132
 
2395
- if (typeof params.willOpen === 'function') {
2396
- params.willOpen(popup);
2133
+ if (document.body.scrollHeight > window.innerHeight) {
2134
+ // add padding so the content doesn't shift after removal of scrollbar
2135
+ states.previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'));
2136
+ document.body.style.paddingRight = "".concat(states.previousBodyPadding + measureScrollbar(), "px");
2397
2137
  }
2398
-
2399
- const bodyStyles = window.getComputedStyle(document.body);
2400
- const initialBodyOverflow = bodyStyles.overflowY;
2401
- addClasses$1(container, popup, params); // scrolling is 'hidden' until animation is done, after that 'auto'
2402
-
2403
- setTimeout(() => {
2404
- setScrollingVisibility(container, popup);
2405
- }, SHOW_CLASS_TIMEOUT);
2406
-
2407
- if (isModal()) {
2408
- fixScrollContainer(container, params.scrollbarPadding, initialBodyOverflow);
2409
- setAriaHidden();
2138
+ };
2139
+ const undoScrollbar = () => {
2140
+ if (states.previousBodyPadding !== null) {
2141
+ document.body.style.paddingRight = "".concat(states.previousBodyPadding, "px");
2142
+ states.previousBodyPadding = null;
2410
2143
  }
2144
+ };
2411
2145
 
2412
- if (!isToast() && !globalState.previousActiveElement) {
2413
- globalState.previousActiveElement = document.activeElement;
2414
- }
2146
+ /*
2147
+ * Instance method to close sweetAlert
2148
+ */
2415
2149
 
2416
- if (typeof params.didOpen === 'function') {
2417
- setTimeout(() => params.didOpen(popup));
2150
+ function removePopupAndResetState(instance, container, returnFocus, didClose) {
2151
+ if (isToast()) {
2152
+ triggerDidCloseAndDispose(instance, didClose);
2153
+ } else {
2154
+ restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose));
2155
+ removeKeydownHandler(globalState);
2418
2156
  }
2419
2157
 
2420
- removeClass(container, swalClasses['no-transition']);
2421
- };
2422
- /**
2423
- * @param {AnimationEvent} event
2424
- */
2425
-
2426
- const swalOpenAnimationFinished = event => {
2427
- const popup = getPopup();
2428
-
2429
- if (event.target !== popup) {
2430
- return;
2431
- }
2432
-
2433
- const container = getContainer();
2434
- popup.removeEventListener(animationEndEvent, swalOpenAnimationFinished);
2435
- container.style.overflowY = 'auto';
2436
- };
2437
- /**
2438
- * @param {HTMLElement} container
2439
- * @param {HTMLElement} popup
2440
- */
2441
-
2158
+ const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); // workaround for #2088
2159
+ // for some reason removing the container in Safari will scroll the document to bottom
2442
2160
 
2443
- const setScrollingVisibility = (container, popup) => {
2444
- if (animationEndEvent && hasCssAnimation(popup)) {
2445
- container.style.overflowY = 'hidden';
2446
- popup.addEventListener(animationEndEvent, swalOpenAnimationFinished);
2161
+ if (isSafari) {
2162
+ container.setAttribute('style', 'display:none !important');
2163
+ container.removeAttribute('class');
2164
+ container.innerHTML = '';
2447
2165
  } else {
2448
- container.style.overflowY = 'auto';
2166
+ container.remove();
2449
2167
  }
2450
- };
2451
- /**
2452
- * @param {HTMLElement} container
2453
- * @param {boolean} scrollbarPadding
2454
- * @param {string} initialBodyOverflow
2455
- */
2456
-
2457
-
2458
- const fixScrollContainer = (container, scrollbarPadding, initialBodyOverflow) => {
2459
- iOSfix();
2460
-
2461
- if (scrollbarPadding && initialBodyOverflow !== 'hidden') {
2462
- fixScrollbar();
2463
- } // sweetalert2/issues/1247
2464
-
2465
2168
 
2466
- setTimeout(() => {
2467
- container.scrollTop = 0;
2468
- });
2469
- };
2470
- /**
2471
- * @param {HTMLElement} container
2472
- * @param {HTMLElement} popup
2473
- * @param {SweetAlertOptions} params
2474
- */
2475
-
2476
-
2477
- const addClasses$1 = (container, popup, params) => {
2478
- addClass(container, params.showClass.backdrop); // this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059
2169
+ if (isModal()) {
2170
+ undoScrollbar();
2171
+ undoIOSfix();
2172
+ unsetAriaHidden();
2173
+ }
2479
2174
 
2480
- popup.style.setProperty('opacity', '0', 'important');
2481
- show(popup, 'grid');
2482
- setTimeout(() => {
2483
- // Animate popup right after showing it
2484
- addClass(popup, params.showClass.popup); // and remove the opacity workaround
2175
+ removeBodyClasses();
2176
+ }
2485
2177
 
2486
- popup.style.removeProperty('opacity');
2487
- }, SHOW_CLASS_TIMEOUT); // 10ms in order to fix #2062
2178
+ function removeBodyClasses() {
2179
+ removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]);
2180
+ }
2488
2181
 
2489
- addClass([document.documentElement, document.body], swalClasses.shown);
2182
+ function close(resolveValue) {
2183
+ resolveValue = prepareResolveValue(resolveValue);
2184
+ const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this);
2185
+ const didClose = triggerClosePopup(this);
2490
2186
 
2491
- if (params.heightAuto && params.backdrop && !params.toast) {
2492
- addClass([document.documentElement, document.body], swalClasses['height-auto']);
2187
+ if (this.isAwaitingPromise()) {
2188
+ // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
2189
+ if (!resolveValue.isDismissed) {
2190
+ handleAwaitingPromise(this);
2191
+ swalPromiseResolve(resolveValue);
2192
+ }
2193
+ } else if (didClose) {
2194
+ // Resolve Swal promise
2195
+ swalPromiseResolve(resolveValue);
2493
2196
  }
2494
- };
2495
-
2496
- /**
2497
- * Shows loader (spinner), this is useful with AJAX requests.
2498
- * By default the loader be shown instead of the "Confirm" button.
2499
- */
2197
+ }
2198
+ function isAwaitingPromise() {
2199
+ return !!privateProps.awaitingPromise.get(this);
2200
+ }
2500
2201
 
2501
- const showLoading = buttonToReplace => {
2502
- let popup = getPopup();
2202
+ const triggerClosePopup = instance => {
2203
+ const popup = getPopup();
2503
2204
 
2504
2205
  if (!popup) {
2505
- new Swal(); // eslint-disable-line no-new
2206
+ return false;
2506
2207
  }
2507
2208
 
2508
- popup = getPopup();
2509
- const loader = getLoader();
2209
+ const innerParams = privateProps.innerParams.get(instance);
2510
2210
 
2511
- if (isToast()) {
2512
- hide(getIcon());
2513
- } else {
2514
- replaceButton(popup, buttonToReplace);
2211
+ if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) {
2212
+ return false;
2515
2213
  }
2516
2214
 
2517
- show(loader);
2518
- popup.setAttribute('data-loading', 'true');
2519
- popup.setAttribute('aria-busy', 'true');
2520
- popup.focus();
2215
+ removeClass(popup, innerParams.showClass.popup);
2216
+ addClass(popup, innerParams.hideClass.popup);
2217
+ const backdrop = getContainer();
2218
+ removeClass(backdrop, innerParams.showClass.backdrop);
2219
+ addClass(backdrop, innerParams.hideClass.backdrop);
2220
+ handlePopupAnimation(instance, popup, innerParams);
2221
+ return true;
2521
2222
  };
2522
2223
 
2523
- const replaceButton = (popup, buttonToReplace) => {
2524
- const actions = getActions();
2525
- const loader = getLoader();
2224
+ function rejectPromise(error) {
2225
+ const rejectPromise = privateMethods.swalPromiseReject.get(this);
2226
+ handleAwaitingPromise(this);
2526
2227
 
2527
- if (!buttonToReplace && isVisible(getConfirmButton())) {
2528
- buttonToReplace = getConfirmButton();
2228
+ if (rejectPromise) {
2229
+ // Reject Swal promise
2230
+ rejectPromise(error);
2529
2231
  }
2232
+ }
2233
+ const handleAwaitingPromise = instance => {
2234
+ if (instance.isAwaitingPromise()) {
2235
+ privateProps.awaitingPromise.delete(instance); // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
2530
2236
 
2531
- show(actions);
2532
-
2533
- if (buttonToReplace) {
2534
- hide(buttonToReplace);
2535
- loader.setAttribute('data-button-to-replace', buttonToReplace.className);
2237
+ if (!privateProps.innerParams.get(instance)) {
2238
+ instance._destroy();
2239
+ }
2536
2240
  }
2537
-
2538
- loader.parentNode.insertBefore(loader, buttonToReplace);
2539
- addClass([popup, actions], swalClasses.loading);
2540
2241
  };
2541
2242
 
2542
- const handleInputOptionsAndValue = (instance, params) => {
2543
- if (params.input === 'select' || params.input === 'radio') {
2544
- handleInputOptions(instance, params);
2545
- } else if (['text', 'email', 'number', 'tel', 'textarea'].includes(params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {
2546
- showLoading(getConfirmButton());
2547
- handleInputValue(instance, params);
2243
+ const prepareResolveValue = resolveValue => {
2244
+ // When user calls Swal.close()
2245
+ if (typeof resolveValue === 'undefined') {
2246
+ return {
2247
+ isConfirmed: false,
2248
+ isDenied: false,
2249
+ isDismissed: true
2250
+ };
2548
2251
  }
2549
- };
2550
- const getInputValue = (instance, innerParams) => {
2551
- const input = instance.getInput();
2552
2252
 
2553
- if (!input) {
2554
- return null;
2555
- }
2253
+ return Object.assign({
2254
+ isConfirmed: false,
2255
+ isDenied: false,
2256
+ isDismissed: false
2257
+ }, resolveValue);
2258
+ };
2556
2259
 
2557
- switch (innerParams.input) {
2558
- case 'checkbox':
2559
- return getCheckboxValue(input);
2260
+ const handlePopupAnimation = (instance, popup, innerParams) => {
2261
+ const container = getContainer(); // If animation is supported, animate
2560
2262
 
2561
- case 'radio':
2562
- return getRadioValue(input);
2263
+ const animationIsSupported = animationEndEvent && hasCssAnimation(popup);
2563
2264
 
2564
- case 'file':
2565
- return getFileValue(input);
2265
+ if (typeof innerParams.willClose === 'function') {
2266
+ innerParams.willClose(popup);
2267
+ }
2566
2268
 
2567
- default:
2568
- return innerParams.inputAutoTrim ? input.value.trim() : input.value;
2269
+ if (animationIsSupported) {
2270
+ animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose);
2271
+ } else {
2272
+ // Otherwise, remove immediately
2273
+ removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose);
2569
2274
  }
2570
2275
  };
2571
2276
 
2572
- const getCheckboxValue = input => input.checked ? 1 : 0;
2277
+ const animatePopup = (instance, popup, container, returnFocus, didClose) => {
2278
+ globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose);
2279
+ popup.addEventListener(animationEndEvent, function (e) {
2280
+ if (e.target === popup) {
2281
+ globalState.swalCloseEventFinishedCallback();
2282
+ delete globalState.swalCloseEventFinishedCallback;
2283
+ }
2284
+ });
2285
+ };
2573
2286
 
2574
- const getRadioValue = input => input.checked ? input.value : null;
2287
+ const triggerDidCloseAndDispose = (instance, didClose) => {
2288
+ setTimeout(() => {
2289
+ if (typeof didClose === 'function') {
2290
+ didClose.bind(instance.params)();
2291
+ }
2575
2292
 
2576
- const getFileValue = input => input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;
2293
+ instance._destroy();
2294
+ });
2295
+ };
2577
2296
 
2578
- const handleInputOptions = (instance, params) => {
2579
- const popup = getPopup();
2297
+ function setButtonsDisabled(instance, buttons, disabled) {
2298
+ const domCache = privateProps.domCache.get(instance);
2299
+ buttons.forEach(button => {
2300
+ domCache[button].disabled = disabled;
2301
+ });
2302
+ }
2580
2303
 
2581
- const processInputOptions = inputOptions => populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params);
2304
+ function setInputDisabled(input, disabled) {
2305
+ if (!input) {
2306
+ return false;
2307
+ }
2582
2308
 
2583
- if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
2584
- showLoading(getConfirmButton());
2585
- asPromise(params.inputOptions).then(inputOptions => {
2586
- instance.hideLoading();
2587
- processInputOptions(inputOptions);
2588
- });
2589
- } else if (typeof params.inputOptions === 'object') {
2590
- processInputOptions(params.inputOptions);
2309
+ if (input.type === 'radio') {
2310
+ const radiosContainer = input.parentNode.parentNode;
2311
+ const radios = radiosContainer.querySelectorAll('input');
2312
+
2313
+ for (let i = 0; i < radios.length; i++) {
2314
+ radios[i].disabled = disabled;
2315
+ }
2591
2316
  } else {
2592
- error("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(typeof params.inputOptions));
2317
+ input.disabled = disabled;
2593
2318
  }
2594
- };
2319
+ }
2595
2320
 
2596
- const handleInputValue = (instance, params) => {
2597
- const input = instance.getInput();
2321
+ function enableButtons() {
2322
+ setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
2323
+ }
2324
+ function disableButtons() {
2325
+ setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
2326
+ }
2327
+ function enableInput() {
2328
+ return setInputDisabled(this.getInput(), false);
2329
+ }
2330
+ function disableInput() {
2331
+ return setInputDisabled(this.getInput(), true);
2332
+ }
2333
+
2334
+ function showValidationMessage(error) {
2335
+ const domCache = privateProps.domCache.get(this);
2336
+ const params = privateProps.innerParams.get(this);
2337
+ setInnerHtml(domCache.validationMessage, error);
2338
+ domCache.validationMessage.className = swalClasses['validation-message'];
2339
+
2340
+ if (params.customClass && params.customClass.validationMessage) {
2341
+ addClass(domCache.validationMessage, params.customClass.validationMessage);
2342
+ }
2343
+
2344
+ show(domCache.validationMessage);
2345
+ const input = this.getInput();
2346
+
2347
+ if (input) {
2348
+ input.setAttribute('aria-invalid', true);
2349
+ input.setAttribute('aria-describedby', swalClasses['validation-message']);
2350
+ focusInput(input);
2351
+ addClass(input, swalClasses.inputerror);
2352
+ }
2353
+ } // Hide block with validation message
2354
+
2355
+ function resetValidationMessage$1() {
2356
+ const domCache = privateProps.domCache.get(this);
2357
+
2358
+ if (domCache.validationMessage) {
2359
+ hide(domCache.validationMessage);
2360
+ }
2361
+
2362
+ const input = this.getInput();
2363
+
2364
+ if (input) {
2365
+ input.removeAttribute('aria-invalid');
2366
+ input.removeAttribute('aria-describedby');
2367
+ removeClass(input, swalClasses.inputerror);
2368
+ }
2369
+ }
2370
+
2371
+ function getProgressSteps$1() {
2372
+ const domCache = privateProps.domCache.get(this);
2373
+ return domCache.progressSteps;
2374
+ }
2375
+
2376
+ const defaultParams = {
2377
+ title: '',
2378
+ titleText: '',
2379
+ text: '',
2380
+ html: '',
2381
+ footer: '',
2382
+ icon: undefined,
2383
+ iconColor: undefined,
2384
+ iconHtml: undefined,
2385
+ template: undefined,
2386
+ toast: false,
2387
+ showClass: {
2388
+ popup: 'swal2-show',
2389
+ backdrop: 'swal2-backdrop-show',
2390
+ icon: 'swal2-icon-show'
2391
+ },
2392
+ hideClass: {
2393
+ popup: 'swal2-hide',
2394
+ backdrop: 'swal2-backdrop-hide',
2395
+ icon: 'swal2-icon-hide'
2396
+ },
2397
+ customClass: {},
2398
+ target: 'body',
2399
+ color: undefined,
2400
+ backdrop: true,
2401
+ heightAuto: true,
2402
+ allowOutsideClick: true,
2403
+ allowEscapeKey: true,
2404
+ allowEnterKey: true,
2405
+ stopKeydownPropagation: true,
2406
+ keydownListenerCapture: false,
2407
+ showConfirmButton: true,
2408
+ showDenyButton: false,
2409
+ showCancelButton: false,
2410
+ preConfirm: undefined,
2411
+ preDeny: undefined,
2412
+ confirmButtonText: 'OK',
2413
+ confirmButtonAriaLabel: '',
2414
+ confirmButtonColor: undefined,
2415
+ denyButtonText: 'No',
2416
+ denyButtonAriaLabel: '',
2417
+ denyButtonColor: undefined,
2418
+ cancelButtonText: 'Cancel',
2419
+ cancelButtonAriaLabel: '',
2420
+ cancelButtonColor: undefined,
2421
+ buttonsStyling: true,
2422
+ reverseButtons: false,
2423
+ focusConfirm: true,
2424
+ focusDeny: false,
2425
+ focusCancel: false,
2426
+ returnFocus: true,
2427
+ showCloseButton: false,
2428
+ closeButtonHtml: '&times;',
2429
+ closeButtonAriaLabel: 'Close this dialog',
2430
+ loaderHtml: '',
2431
+ showLoaderOnConfirm: false,
2432
+ showLoaderOnDeny: false,
2433
+ imageUrl: undefined,
2434
+ imageWidth: undefined,
2435
+ imageHeight: undefined,
2436
+ imageAlt: '',
2437
+ timer: undefined,
2438
+ timerProgressBar: false,
2439
+ width: undefined,
2440
+ padding: undefined,
2441
+ background: undefined,
2442
+ input: undefined,
2443
+ inputPlaceholder: '',
2444
+ inputLabel: '',
2445
+ inputValue: '',
2446
+ inputOptions: {},
2447
+ inputAutoTrim: true,
2448
+ inputAttributes: {},
2449
+ inputValidator: undefined,
2450
+ returnInputValueOnDeny: false,
2451
+ validationMessage: undefined,
2452
+ grow: false,
2453
+ position: 'center',
2454
+ progressSteps: [],
2455
+ currentProgressStep: undefined,
2456
+ progressStepsDistance: undefined,
2457
+ willOpen: undefined,
2458
+ didOpen: undefined,
2459
+ didRender: undefined,
2460
+ willClose: undefined,
2461
+ didClose: undefined,
2462
+ didDestroy: undefined,
2463
+ scrollbarPadding: true
2464
+ };
2465
+ 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'];
2466
+ const deprecatedParams = {};
2467
+ const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];
2468
+ /**
2469
+ * Is valid parameter
2470
+ *
2471
+ * @param {string} paramName
2472
+ * @returns {boolean}
2473
+ */
2474
+
2475
+ const isValidParameter = paramName => {
2476
+ return Object.prototype.hasOwnProperty.call(defaultParams, paramName);
2477
+ };
2478
+ /**
2479
+ * Is valid parameter for Swal.update() method
2480
+ *
2481
+ * @param {string} paramName
2482
+ * @returns {boolean}
2483
+ */
2484
+
2485
+ const isUpdatableParameter = paramName => {
2486
+ return updatableParams.indexOf(paramName) !== -1;
2487
+ };
2488
+ /**
2489
+ * Is deprecated parameter
2490
+ *
2491
+ * @param {string} paramName
2492
+ * @returns {string | undefined}
2493
+ */
2494
+
2495
+ const isDeprecatedParameter = paramName => {
2496
+ return deprecatedParams[paramName];
2497
+ };
2498
+ /**
2499
+ * @param {string} param
2500
+ */
2501
+
2502
+ const checkIfParamIsValid = param => {
2503
+ if (!isValidParameter(param)) {
2504
+ warn("Unknown parameter \"".concat(param, "\""));
2505
+ }
2506
+ };
2507
+ /**
2508
+ * @param {string} param
2509
+ */
2510
+
2511
+
2512
+ const checkIfToastParamIsValid = param => {
2513
+ if (toastIncompatibleParams.includes(param)) {
2514
+ warn("The parameter \"".concat(param, "\" is incompatible with toasts"));
2515
+ }
2516
+ };
2517
+ /**
2518
+ * @param {string} param
2519
+ */
2520
+
2521
+
2522
+ const checkIfParamIsDeprecated = param => {
2523
+ if (isDeprecatedParameter(param)) {
2524
+ warnAboutDeprecation(param, isDeprecatedParameter(param));
2525
+ }
2526
+ };
2527
+ /**
2528
+ * Show relevant warnings for given params
2529
+ *
2530
+ * @param {SweetAlertOptions} params
2531
+ */
2532
+
2533
+
2534
+ const showWarningsForParams = params => {
2535
+ if (!params.backdrop && params.allowOutsideClick) {
2536
+ warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
2537
+ }
2538
+
2539
+ for (const param in params) {
2540
+ checkIfParamIsValid(param);
2541
+
2542
+ if (params.toast) {
2543
+ checkIfToastParamIsValid(param);
2544
+ }
2545
+
2546
+ checkIfParamIsDeprecated(param);
2547
+ }
2548
+ };
2549
+
2550
+ /**
2551
+ * Updates popup parameters.
2552
+ */
2553
+
2554
+ function update(params) {
2555
+ const popup = getPopup();
2556
+ const innerParams = privateProps.innerParams.get(this);
2557
+
2558
+ if (!popup || hasClass(popup, innerParams.hideClass.popup)) {
2559
+ return warn("You're trying to update the closed or closing popup, that won't work. Use the update() method in preConfirm parameter or show a new popup.");
2560
+ }
2561
+
2562
+ const validUpdatableParams = filterValidParams(params);
2563
+ const updatedParams = Object.assign({}, innerParams, validUpdatableParams);
2564
+ render(this, updatedParams);
2565
+ privateProps.innerParams.set(this, updatedParams);
2566
+ Object.defineProperties(this, {
2567
+ params: {
2568
+ value: Object.assign({}, this.params, params),
2569
+ writable: false,
2570
+ enumerable: true
2571
+ }
2572
+ });
2573
+ }
2574
+
2575
+ const filterValidParams = params => {
2576
+ const validUpdatableParams = {};
2577
+ Object.keys(params).forEach(param => {
2578
+ if (isUpdatableParameter(param)) {
2579
+ validUpdatableParams[param] = params[param];
2580
+ } else {
2581
+ warn("Invalid parameter to update: ".concat(param));
2582
+ }
2583
+ });
2584
+ return validUpdatableParams;
2585
+ };
2586
+
2587
+ function _destroy() {
2588
+ const domCache = privateProps.domCache.get(this);
2589
+ const innerParams = privateProps.innerParams.get(this);
2590
+
2591
+ if (!innerParams) {
2592
+ disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
2593
+
2594
+ return; // This instance has already been destroyed
2595
+ } // Check if there is another Swal closing
2596
+
2597
+
2598
+ if (domCache.popup && globalState.swalCloseEventFinishedCallback) {
2599
+ globalState.swalCloseEventFinishedCallback();
2600
+ delete globalState.swalCloseEventFinishedCallback;
2601
+ }
2602
+
2603
+ if (typeof innerParams.didDestroy === 'function') {
2604
+ innerParams.didDestroy();
2605
+ }
2606
+
2607
+ disposeSwal(this);
2608
+ }
2609
+ /**
2610
+ * @param {SweetAlert2} instance
2611
+ */
2612
+
2613
+ const disposeSwal = instance => {
2614
+ disposeWeakMaps(instance); // Unset this.params so GC will dispose it (#1569)
2615
+ // @ts-ignore
2616
+
2617
+ delete instance.params; // Unset globalState props so GC will dispose globalState (#1569)
2618
+
2619
+ delete globalState.keydownHandler;
2620
+ delete globalState.keydownTarget; // Unset currentInstance
2621
+
2622
+ delete globalState.currentInstance;
2623
+ };
2624
+ /**
2625
+ * @param {SweetAlert2} instance
2626
+ */
2627
+
2628
+
2629
+ const disposeWeakMaps = instance => {
2630
+ // If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335
2631
+ // @ts-ignore
2632
+ if (instance.isAwaitingPromise()) {
2633
+ unsetWeakMaps(privateProps, instance);
2634
+ privateProps.awaitingPromise.set(instance, true);
2635
+ } else {
2636
+ unsetWeakMaps(privateMethods, instance);
2637
+ unsetWeakMaps(privateProps, instance);
2638
+ }
2639
+ };
2640
+ /**
2641
+ * @param {object} obj
2642
+ * @param {SweetAlert2} instance
2643
+ */
2644
+
2645
+
2646
+ const unsetWeakMaps = (obj, instance) => {
2647
+ for (const i in obj) {
2648
+ obj[i].delete(instance);
2649
+ }
2650
+ };
2651
+
2652
+
2653
+
2654
+ var instanceMethods = /*#__PURE__*/Object.freeze({
2655
+ hideLoading: hideLoading,
2656
+ disableLoading: hideLoading,
2657
+ getInput: getInput$1,
2658
+ close: close,
2659
+ isAwaitingPromise: isAwaitingPromise,
2660
+ rejectPromise: rejectPromise,
2661
+ handleAwaitingPromise: handleAwaitingPromise,
2662
+ closePopup: close,
2663
+ closeModal: close,
2664
+ closeToast: close,
2665
+ enableButtons: enableButtons,
2666
+ disableButtons: disableButtons,
2667
+ enableInput: enableInput,
2668
+ disableInput: disableInput,
2669
+ showValidationMessage: showValidationMessage,
2670
+ resetValidationMessage: resetValidationMessage$1,
2671
+ getProgressSteps: getProgressSteps$1,
2672
+ update: update,
2673
+ _destroy: _destroy
2674
+ });
2675
+
2676
+ /**
2677
+ * Shows loader (spinner), this is useful with AJAX requests.
2678
+ * By default the loader be shown instead of the "Confirm" button.
2679
+ */
2680
+
2681
+ const showLoading = buttonToReplace => {
2682
+ let popup = getPopup();
2683
+
2684
+ if (!popup) {
2685
+ new Swal(); // eslint-disable-line no-new
2686
+ }
2687
+
2688
+ popup = getPopup();
2689
+ const loader = getLoader();
2690
+
2691
+ if (isToast()) {
2692
+ hide(getIcon());
2693
+ } else {
2694
+ replaceButton(popup, buttonToReplace);
2695
+ }
2696
+
2697
+ show(loader);
2698
+ popup.setAttribute('data-loading', 'true');
2699
+ popup.setAttribute('aria-busy', 'true');
2700
+ popup.focus();
2701
+ };
2702
+
2703
+ const replaceButton = (popup, buttonToReplace) => {
2704
+ const actions = getActions();
2705
+ const loader = getLoader();
2706
+
2707
+ if (!buttonToReplace && isVisible(getConfirmButton())) {
2708
+ buttonToReplace = getConfirmButton();
2709
+ }
2710
+
2711
+ show(actions);
2712
+
2713
+ if (buttonToReplace) {
2714
+ hide(buttonToReplace);
2715
+ loader.setAttribute('data-button-to-replace', buttonToReplace.className);
2716
+ }
2717
+
2718
+ loader.parentNode.insertBefore(loader, buttonToReplace);
2719
+ addClass([popup, actions], swalClasses.loading);
2720
+ };
2721
+
2722
+ const handleInputOptionsAndValue = (instance, params) => {
2723
+ if (params.input === 'select' || params.input === 'radio') {
2724
+ handleInputOptions(instance, params);
2725
+ } else if (['text', 'email', 'number', 'tel', 'textarea'].includes(params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {
2726
+ showLoading(getConfirmButton());
2727
+ handleInputValue(instance, params);
2728
+ }
2729
+ };
2730
+ const getInputValue = (instance, innerParams) => {
2731
+ const input = instance.getInput();
2732
+
2733
+ if (!input) {
2734
+ return null;
2735
+ }
2736
+
2737
+ switch (innerParams.input) {
2738
+ case 'checkbox':
2739
+ return getCheckboxValue(input);
2740
+
2741
+ case 'radio':
2742
+ return getRadioValue(input);
2743
+
2744
+ case 'file':
2745
+ return getFileValue(input);
2746
+
2747
+ default:
2748
+ return innerParams.inputAutoTrim ? input.value.trim() : input.value;
2749
+ }
2750
+ };
2751
+
2752
+ const getCheckboxValue = input => input.checked ? 1 : 0;
2753
+
2754
+ const getRadioValue = input => input.checked ? input.value : null;
2755
+
2756
+ const getFileValue = input => input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;
2757
+
2758
+ const handleInputOptions = (instance, params) => {
2759
+ const popup = getPopup();
2760
+
2761
+ const processInputOptions = inputOptions => populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params);
2762
+
2763
+ if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
2764
+ showLoading(getConfirmButton());
2765
+ asPromise(params.inputOptions).then(inputOptions => {
2766
+ instance.hideLoading();
2767
+ processInputOptions(inputOptions);
2768
+ });
2769
+ } else if (typeof params.inputOptions === 'object') {
2770
+ processInputOptions(params.inputOptions);
2771
+ } else {
2772
+ error("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(typeof params.inputOptions));
2773
+ }
2774
+ };
2775
+
2776
+ const handleInputValue = (instance, params) => {
2777
+ const input = instance.getInput();
2598
2778
  hide(input);
2599
2779
  asPromise(params.inputValue).then(inputValue => {
2600
2780
  input.value = params.input === 'number' ? parseFloat(inputValue) || 0 : "".concat(inputValue);
@@ -2713,1100 +2893,937 @@
2713
2893
  };
2714
2894
 
2715
2895
  /**
2716
- * Hides loader and shows back the button which was hidden by .showLoading()
2896
+ * @param {SweetAlert2} instance
2717
2897
  */
2718
2898
 
2719
- function hideLoading() {
2720
- // do nothing if popup is closed
2721
- const innerParams = privateProps.innerParams.get(this);
2722
-
2723
- if (!innerParams) {
2724
- return;
2725
- }
2726
-
2727
- const domCache = privateProps.domCache.get(this);
2728
- hide(domCache.loader);
2899
+ const handleConfirmButtonClick = instance => {
2900
+ const innerParams = privateProps.innerParams.get(instance);
2901
+ instance.disableButtons();
2729
2902
 
2730
- if (isToast()) {
2731
- if (innerParams.icon) {
2732
- show(getIcon());
2733
- }
2903
+ if (innerParams.input) {
2904
+ handleConfirmOrDenyWithInput(instance, 'confirm');
2734
2905
  } else {
2735
- showRelatedButton(domCache);
2736
- }
2737
-
2738
- removeClass([domCache.popup, domCache.actions], swalClasses.loading);
2739
- domCache.popup.removeAttribute('aria-busy');
2740
- domCache.popup.removeAttribute('data-loading');
2741
- domCache.confirmButton.disabled = false;
2742
- domCache.denyButton.disabled = false;
2743
- domCache.cancelButton.disabled = false;
2744
- }
2745
-
2746
- const showRelatedButton = domCache => {
2747
- const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'));
2748
-
2749
- if (buttonToReplace.length) {
2750
- show(buttonToReplace[0], 'inline-block');
2751
- } else if (allButtonsAreHidden()) {
2752
- hide(domCache.actions);
2906
+ confirm(instance, true);
2753
2907
  }
2754
2908
  };
2755
-
2756
2909
  /**
2757
- * Gets the input DOM node, this method works with input parameter.
2758
- * @returns {HTMLElement | null}
2910
+ * @param {SweetAlert2} instance
2759
2911
  */
2760
2912
 
2761
- function getInput$1(instance) {
2762
- const innerParams = privateProps.innerParams.get(instance || this);
2763
- const domCache = privateProps.domCache.get(instance || this);
2913
+ const handleDenyButtonClick = instance => {
2914
+ const innerParams = privateProps.innerParams.get(instance);
2915
+ instance.disableButtons();
2764
2916
 
2765
- if (!domCache) {
2766
- return null;
2917
+ if (innerParams.returnInputValueOnDeny) {
2918
+ handleConfirmOrDenyWithInput(instance, 'deny');
2919
+ } else {
2920
+ deny(instance, false);
2767
2921
  }
2768
-
2769
- return getInput(domCache.popup, innerParams.input);
2770
- }
2771
-
2772
- /**
2773
- * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
2774
- * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
2775
- * This is the approach that Babel will probably take to implement private methods/fields
2776
- * https://github.com/tc39/proposal-private-methods
2777
- * https://github.com/babel/babel/pull/7555
2778
- * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
2779
- * then we can use that language feature.
2780
- */
2781
- var privateMethods = {
2782
- swalPromiseResolve: new WeakMap(),
2783
- swalPromiseReject: new WeakMap()
2784
- };
2785
-
2786
- /*
2787
- * Global function to determine if SweetAlert2 popup is shown
2788
- */
2789
-
2790
- const isVisible$1 = () => {
2791
- return isVisible(getPopup());
2792
2922
  };
2793
- /*
2794
- * Global function to click 'Confirm' button
2795
- */
2796
-
2797
- const clickConfirm = () => getConfirmButton() && getConfirmButton().click();
2798
- /*
2799
- * Global function to click 'Deny' button
2800
- */
2801
-
2802
- const clickDeny = () => getDenyButton() && getDenyButton().click();
2803
- /*
2804
- * Global function to click 'Cancel' button
2805
- */
2806
-
2807
- const clickCancel = () => getCancelButton() && getCancelButton().click();
2808
-
2809
2923
  /**
2810
- * @param {GlobalState} globalState
2924
+ * @param {SweetAlert2} instance
2925
+ * @param {Function} dismissWith
2811
2926
  */
2812
2927
 
2813
- const removeKeydownHandler = globalState => {
2814
- if (globalState.keydownTarget && globalState.keydownHandlerAdded) {
2815
- globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, {
2816
- capture: globalState.keydownListenerCapture
2817
- });
2818
- globalState.keydownHandlerAdded = false;
2819
- }
2928
+ const handleCancelButtonClick = (instance, dismissWith) => {
2929
+ instance.disableButtons();
2930
+ dismissWith(DismissReason.cancel);
2820
2931
  };
2821
2932
  /**
2822
2933
  * @param {SweetAlert2} instance
2823
- * @param {GlobalState} globalState
2824
- * @param {SweetAlertOptions} innerParams
2825
- * @param {*} dismissWith
2934
+ * @param {'confirm' | 'deny'} type
2826
2935
  */
2827
2936
 
2828
- const addKeydownHandler = (instance, globalState, innerParams, dismissWith) => {
2829
- removeKeydownHandler(globalState);
2937
+ const handleConfirmOrDenyWithInput = (instance, type) => {
2938
+ const innerParams = privateProps.innerParams.get(instance);
2830
2939
 
2831
- if (!innerParams.toast) {
2832
- globalState.keydownHandler = e => keydownHandler(instance, e, dismissWith);
2940
+ if (!innerParams.input) {
2941
+ error("The \"input\" parameter is needed to be set when using returnInputValueOn".concat(capitalizeFirstLetter(type)));
2942
+ return;
2943
+ }
2833
2944
 
2834
- globalState.keydownTarget = innerParams.keydownListenerCapture ? window : getPopup();
2835
- globalState.keydownListenerCapture = innerParams.keydownListenerCapture;
2836
- globalState.keydownTarget.addEventListener('keydown', globalState.keydownHandler, {
2837
- capture: globalState.keydownListenerCapture
2838
- });
2839
- globalState.keydownHandlerAdded = true;
2945
+ const inputValue = getInputValue(instance, innerParams);
2946
+
2947
+ if (innerParams.inputValidator) {
2948
+ handleInputValidator(instance, inputValue, type);
2949
+ } else if (!instance.getInput().checkValidity()) {
2950
+ instance.enableButtons();
2951
+ instance.showValidationMessage(innerParams.validationMessage);
2952
+ } else if (type === 'deny') {
2953
+ deny(instance, inputValue);
2954
+ } else {
2955
+ confirm(instance, inputValue);
2840
2956
  }
2841
2957
  };
2842
2958
  /**
2843
- * @param {SweetAlertOptions} innerParams
2844
- * @param {number} index
2845
- * @param {number} increment
2959
+ * @param {SweetAlert2} instance
2960
+ * @param {string} inputValue
2961
+ * @param {'confirm' | 'deny'} type
2846
2962
  */
2847
2963
 
2848
- const setFocus = (innerParams, index, increment) => {
2849
- const focusableElements = getFocusableElements(); // search for visible elements and select the next possible match
2850
2964
 
2851
- if (focusableElements.length) {
2852
- index = index + increment; // rollover to first item
2965
+ const handleInputValidator = (instance, inputValue, type) => {
2966
+ const innerParams = privateProps.innerParams.get(instance);
2967
+ instance.disableInput();
2968
+ const validationPromise = Promise.resolve().then(() => asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage)));
2969
+ validationPromise.then(validationMessage => {
2970
+ instance.enableButtons();
2971
+ instance.enableInput();
2853
2972
 
2854
- if (index === focusableElements.length) {
2855
- index = 0; // go to last item
2856
- } else if (index === -1) {
2857
- index = focusableElements.length - 1;
2973
+ if (validationMessage) {
2974
+ instance.showValidationMessage(validationMessage);
2975
+ } else if (type === 'deny') {
2976
+ deny(instance, inputValue);
2977
+ } else {
2978
+ confirm(instance, inputValue);
2858
2979
  }
2859
-
2860
- return focusableElements[index].focus();
2861
- } // no visible focusable elements, focus the popup
2862
-
2863
-
2864
- getPopup().focus();
2980
+ });
2865
2981
  };
2866
- const arrowKeysNextButton = ['ArrowRight', 'ArrowDown'];
2867
- const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp'];
2868
2982
  /**
2869
2983
  * @param {SweetAlert2} instance
2870
- * @param {KeyboardEvent} e
2871
- * @param {function} dismissWith
2984
+ * @param {any} value
2872
2985
  */
2873
2986
 
2874
- const keydownHandler = (instance, e, dismissWith) => {
2875
- const innerParams = privateProps.innerParams.get(instance);
2876
-
2877
- if (!innerParams) {
2878
- return; // This instance has already been destroyed
2879
- } // Ignore keydown during IME composition
2880
- // https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event#ignoring_keydown_during_ime_composition
2881
- // https://github.com/sweetalert2/sweetalert2/issues/720
2882
- // https://github.com/sweetalert2/sweetalert2/issues/2406
2883
2987
 
2988
+ const deny = (instance, value) => {
2989
+ const innerParams = privateProps.innerParams.get(instance || undefined);
2884
2990
 
2885
- if (e.isComposing || e.keyCode === 229) {
2886
- return;
2991
+ if (innerParams.showLoaderOnDeny) {
2992
+ showLoading(getDenyButton());
2887
2993
  }
2888
2994
 
2889
- if (innerParams.stopKeydownPropagation) {
2890
- e.stopPropagation();
2891
- } // ENTER
2892
-
2995
+ if (innerParams.preDeny) {
2996
+ privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preDeny's promise is received
2893
2997
 
2894
- if (e.key === 'Enter') {
2895
- handleEnter(instance, e, innerParams);
2896
- } // TAB
2897
- else if (e.key === 'Tab') {
2898
- handleTab(e, innerParams);
2899
- } // ARROWS - switch focus between buttons
2900
- else if ([...arrowKeysNextButton, ...arrowKeysPreviousButton].includes(e.key)) {
2901
- handleArrows(e.key);
2902
- } // ESC
2903
- else if (e.key === 'Escape') {
2904
- handleEsc(e, innerParams, dismissWith);
2998
+ const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage)));
2999
+ preDenyPromise.then(preDenyValue => {
3000
+ if (preDenyValue === false) {
3001
+ instance.hideLoading();
3002
+ handleAwaitingPromise(instance);
3003
+ } else {
3004
+ instance.close({
3005
+ isDenied: true,
3006
+ value: typeof preDenyValue === 'undefined' ? value : preDenyValue
3007
+ });
3008
+ }
3009
+ }).catch(error$$1 => rejectWith(instance || undefined, error$$1));
3010
+ } else {
3011
+ instance.close({
3012
+ isDenied: true,
3013
+ value
3014
+ });
2905
3015
  }
2906
3016
  };
2907
3017
  /**
2908
3018
  * @param {SweetAlert2} instance
2909
- * @param {KeyboardEvent} e
2910
- * @param {SweetAlertOptions} innerParams
3019
+ * @param {any} value
2911
3020
  */
2912
3021
 
2913
3022
 
2914
- const handleEnter = (instance, e, innerParams) => {
2915
- // https://github.com/sweetalert2/sweetalert2/issues/2386
2916
- if (!callIfFunction(innerParams.allowEnterKey)) {
2917
- return;
2918
- }
3023
+ const succeedWith = (instance, value) => {
3024
+ instance.close({
3025
+ isConfirmed: true,
3026
+ value
3027
+ });
3028
+ };
3029
+ /**
3030
+ *
3031
+ * @param {SweetAlert2} instance
3032
+ * @param {string} error
3033
+ */
2919
3034
 
2920
- if (e.target && instance.getInput() && e.target instanceof HTMLElement && e.target.outerHTML === instance.getInput().outerHTML) {
2921
- if (['textarea', 'file'].includes(innerParams.input)) {
2922
- return; // do not submit
2923
- }
2924
3035
 
2925
- clickConfirm();
2926
- e.preventDefault();
2927
- }
3036
+ const rejectWith = (instance, error$$1) => {
3037
+ // @ts-ignore
3038
+ instance.rejectPromise(error$$1);
2928
3039
  };
2929
3040
  /**
2930
- * @param {KeyboardEvent} e
2931
- * @param {SweetAlertOptions} innerParams
3041
+ *
3042
+ * @param {SweetAlert2} instance
3043
+ * @param {any} value
2932
3044
  */
2933
3045
 
2934
3046
 
2935
- const handleTab = (e, innerParams) => {
2936
- const targetElement = e.target;
2937
- const focusableElements = getFocusableElements();
2938
- let btnIndex = -1;
3047
+ const confirm = (instance, value) => {
3048
+ const innerParams = privateProps.innerParams.get(instance || undefined);
2939
3049
 
2940
- for (let i = 0; i < focusableElements.length; i++) {
2941
- if (targetElement === focusableElements[i]) {
2942
- btnIndex = i;
2943
- break;
2944
- }
2945
- } // Cycle to the next button
3050
+ if (innerParams.showLoaderOnConfirm) {
3051
+ showLoading();
3052
+ }
2946
3053
 
3054
+ if (innerParams.preConfirm) {
3055
+ instance.resetValidationMessage();
3056
+ privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preConfirm's promise is received
2947
3057
 
2948
- if (!e.shiftKey) {
2949
- setFocus(innerParams, btnIndex, 1);
2950
- } // Cycle to the prev button
2951
- else {
2952
- setFocus(innerParams, btnIndex, -1);
3058
+ const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
3059
+ preConfirmPromise.then(preConfirmValue => {
3060
+ if (isVisible(getValidationMessage()) || preConfirmValue === false) {
3061
+ instance.hideLoading();
3062
+ handleAwaitingPromise(instance);
3063
+ } else {
3064
+ succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);
3065
+ }
3066
+ }).catch(error$$1 => rejectWith(instance || undefined, error$$1));
3067
+ } else {
3068
+ succeedWith(instance, value);
2953
3069
  }
2954
-
2955
- e.stopPropagation();
2956
- e.preventDefault();
2957
3070
  };
2958
- /**
2959
- * @param {string} key
2960
- */
2961
3071
 
3072
+ const handlePopupClick = (instance, domCache, dismissWith) => {
3073
+ const innerParams = privateProps.innerParams.get(instance);
2962
3074
 
2963
- const handleArrows = key => {
2964
- const confirmButton = getConfirmButton();
2965
- const denyButton = getDenyButton();
2966
- const cancelButton = getCancelButton();
3075
+ if (innerParams.toast) {
3076
+ handleToastClick(instance, domCache, dismissWith);
3077
+ } else {
3078
+ // Ignore click events that had mousedown on the popup but mouseup on the container
3079
+ // This can happen when the user drags a slider
3080
+ handleModalMousedown(domCache); // Ignore click events that had mousedown on the container but mouseup on the popup
2967
3081
 
2968
- if (document.activeElement instanceof HTMLElement && ![confirmButton, denyButton, cancelButton].includes(document.activeElement)) {
2969
- return;
3082
+ handleContainerMousedown(domCache);
3083
+ handleModalClick(instance, domCache, dismissWith);
2970
3084
  }
3085
+ };
2971
3086
 
2972
- const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling';
2973
- let buttonToFocus = document.activeElement;
2974
-
2975
- for (let i = 0; i < getActions().children.length; i++) {
2976
- buttonToFocus = buttonToFocus[sibling];
3087
+ const handleToastClick = (instance, domCache, dismissWith) => {
3088
+ // Closing toast by internal click
3089
+ domCache.popup.onclick = () => {
3090
+ const innerParams = privateProps.innerParams.get(instance);
2977
3091
 
2978
- if (!buttonToFocus) {
3092
+ if (innerParams && (isAnyButtonShown(innerParams) || innerParams.timer || innerParams.input)) {
2979
3093
  return;
2980
3094
  }
2981
3095
 
2982
- if (buttonToFocus instanceof HTMLButtonElement && isVisible(buttonToFocus)) {
2983
- break;
2984
- }
2985
- }
2986
-
2987
- if (buttonToFocus instanceof HTMLButtonElement) {
2988
- buttonToFocus.focus();
2989
- }
3096
+ dismissWith(DismissReason.close);
3097
+ };
2990
3098
  };
2991
3099
  /**
2992
- * @param {KeyboardEvent} e
2993
- * @param {SweetAlertOptions} innerParams
2994
- * @param {function} dismissWith
3100
+ * @param {*} innerParams
3101
+ * @returns {boolean}
2995
3102
  */
2996
3103
 
2997
3104
 
2998
- const handleEsc = (e, innerParams, dismissWith) => {
2999
- if (callIfFunction(innerParams.allowEscapeKey)) {
3000
- e.preventDefault();
3001
- dismissWith(DismissReason.esc);
3002
- }
3105
+ const isAnyButtonShown = innerParams => {
3106
+ return innerParams.showConfirmButton || innerParams.showDenyButton || innerParams.showCancelButton || innerParams.showCloseButton;
3003
3107
  };
3004
3108
 
3005
- /*
3006
- * Instance method to close sweetAlert
3007
- */
3008
-
3009
- function removePopupAndResetState(instance, container, returnFocus, didClose) {
3010
- if (isToast()) {
3011
- triggerDidCloseAndDispose(instance, didClose);
3012
- } else {
3013
- restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose));
3014
- removeKeydownHandler(globalState);
3015
- }
3109
+ let ignoreOutsideClick = false;
3016
3110
 
3017
- const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); // workaround for #2088
3018
- // for some reason removing the container in Safari will scroll the document to bottom
3111
+ const handleModalMousedown = domCache => {
3112
+ domCache.popup.onmousedown = () => {
3113
+ domCache.container.onmouseup = function (e) {
3114
+ domCache.container.onmouseup = undefined; // We only check if the mouseup target is the container because usually it doesn't
3115
+ // have any other direct children aside of the popup
3019
3116
 
3020
- if (isSafari) {
3021
- container.setAttribute('style', 'display:none !important');
3022
- container.removeAttribute('class');
3023
- container.innerHTML = '';
3024
- } else {
3025
- container.remove();
3026
- }
3117
+ if (e.target === domCache.container) {
3118
+ ignoreOutsideClick = true;
3119
+ }
3120
+ };
3121
+ };
3122
+ };
3027
3123
 
3028
- if (isModal()) {
3029
- undoScrollbar();
3030
- undoIOSfix();
3031
- unsetAriaHidden();
3032
- }
3124
+ const handleContainerMousedown = domCache => {
3125
+ domCache.container.onmousedown = () => {
3126
+ domCache.popup.onmouseup = function (e) {
3127
+ domCache.popup.onmouseup = undefined; // We also need to check if the mouseup target is a child of the popup
3033
3128
 
3034
- removeBodyClasses();
3035
- }
3129
+ if (e.target === domCache.popup || domCache.popup.contains(e.target)) {
3130
+ ignoreOutsideClick = true;
3131
+ }
3132
+ };
3133
+ };
3134
+ };
3036
3135
 
3037
- function removeBodyClasses() {
3038
- removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]);
3039
- }
3136
+ const handleModalClick = (instance, domCache, dismissWith) => {
3137
+ domCache.container.onclick = e => {
3138
+ const innerParams = privateProps.innerParams.get(instance);
3040
3139
 
3041
- function close(resolveValue) {
3042
- resolveValue = prepareResolveValue(resolveValue);
3043
- const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this);
3044
- const didClose = triggerClosePopup(this);
3140
+ if (ignoreOutsideClick) {
3141
+ ignoreOutsideClick = false;
3142
+ return;
3143
+ }
3045
3144
 
3046
- if (this.isAwaitingPromise()) {
3047
- // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
3048
- if (!resolveValue.isDismissed) {
3049
- handleAwaitingPromise(this);
3050
- swalPromiseResolve(resolveValue);
3145
+ if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) {
3146
+ dismissWith(DismissReason.backdrop);
3051
3147
  }
3052
- } else if (didClose) {
3053
- // Resolve Swal promise
3054
- swalPromiseResolve(resolveValue);
3055
- }
3056
- }
3057
- function isAwaitingPromise() {
3058
- return !!privateProps.awaitingPromise.get(this);
3059
- }
3148
+ };
3149
+ };
3060
3150
 
3061
- const triggerClosePopup = instance => {
3062
- const popup = getPopup();
3151
+ const isJqueryElement = elem => typeof elem === 'object' && elem.jquery;
3063
3152
 
3064
- if (!popup) {
3065
- return false;
3066
- }
3153
+ const isElement = elem => elem instanceof Element || isJqueryElement(elem);
3067
3154
 
3068
- const innerParams = privateProps.innerParams.get(instance);
3155
+ const argsToParams = args => {
3156
+ const params = {};
3069
3157
 
3070
- if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) {
3071
- return false;
3158
+ if (typeof args[0] === 'object' && !isElement(args[0])) {
3159
+ Object.assign(params, args[0]);
3160
+ } else {
3161
+ ['title', 'html', 'icon'].forEach((name, index) => {
3162
+ const arg = args[index];
3163
+
3164
+ if (typeof arg === 'string' || isElement(arg)) {
3165
+ params[name] = arg;
3166
+ } else if (arg !== undefined) {
3167
+ error("Unexpected type of ".concat(name, "! Expected \"string\" or \"Element\", got ").concat(typeof arg));
3168
+ }
3169
+ });
3072
3170
  }
3073
3171
 
3074
- removeClass(popup, innerParams.showClass.popup);
3075
- addClass(popup, innerParams.hideClass.popup);
3076
- const backdrop = getContainer();
3077
- removeClass(backdrop, innerParams.showClass.backdrop);
3078
- addClass(backdrop, innerParams.hideClass.backdrop);
3079
- handlePopupAnimation(instance, popup, innerParams);
3080
- return true;
3172
+ return params;
3081
3173
  };
3082
3174
 
3083
- function rejectPromise(error) {
3084
- const rejectPromise = privateMethods.swalPromiseReject.get(this);
3085
- handleAwaitingPromise(this);
3175
+ function fire() {
3176
+ const Swal = this; // eslint-disable-line @typescript-eslint/no-this-alias
3086
3177
 
3087
- if (rejectPromise) {
3088
- // Reject Swal promise
3089
- rejectPromise(error);
3178
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
3179
+ args[_key] = arguments[_key];
3090
3180
  }
3181
+
3182
+ return new Swal(...args);
3091
3183
  }
3092
- const handleAwaitingPromise = instance => {
3093
- if (instance.isAwaitingPromise()) {
3094
- privateProps.awaitingPromise.delete(instance); // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
3095
3184
 
3096
- if (!privateProps.innerParams.get(instance)) {
3097
- instance._destroy();
3185
+ /**
3186
+ * Returns an extended version of `Swal` containing `params` as defaults.
3187
+ * Useful for reusing Swal configuration.
3188
+ *
3189
+ * For example:
3190
+ *
3191
+ * Before:
3192
+ * const textPromptOptions = { input: 'text', showCancelButton: true }
3193
+ * const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' })
3194
+ * const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' })
3195
+ *
3196
+ * After:
3197
+ * const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true })
3198
+ * const {value: firstName} = await TextPrompt('What is your first name?')
3199
+ * const {value: lastName} = await TextPrompt('What is your last name?')
3200
+ *
3201
+ * @param mixinParams
3202
+ */
3203
+ function mixin(mixinParams) {
3204
+ class MixinSwal extends this {
3205
+ _main(params, priorityMixinParams) {
3206
+ return super._main(params, Object.assign({}, mixinParams, priorityMixinParams));
3098
3207
  }
3099
- }
3100
- };
3101
3208
 
3102
- const prepareResolveValue = resolveValue => {
3103
- // When user calls Swal.close()
3104
- if (typeof resolveValue === 'undefined') {
3105
- return {
3106
- isConfirmed: false,
3107
- isDenied: false,
3108
- isDismissed: true
3109
- };
3110
3209
  }
3111
3210
 
3112
- return Object.assign({
3113
- isConfirmed: false,
3114
- isDenied: false,
3115
- isDismissed: false
3116
- }, resolveValue);
3117
- };
3211
+ return MixinSwal;
3212
+ }
3118
3213
 
3119
- const handlePopupAnimation = (instance, popup, innerParams) => {
3120
- const container = getContainer(); // If animation is supported, animate
3214
+ /**
3215
+ * If `timer` parameter is set, returns number of milliseconds of timer remained.
3216
+ * Otherwise, returns undefined.
3217
+ */
3121
3218
 
3122
- const animationIsSupported = animationEndEvent && hasCssAnimation(popup);
3219
+ const getTimerLeft = () => {
3220
+ return globalState.timeout && globalState.timeout.getTimerLeft();
3221
+ };
3222
+ /**
3223
+ * Stop timer. Returns number of milliseconds of timer remained.
3224
+ * If `timer` parameter isn't set, returns undefined.
3225
+ */
3123
3226
 
3124
- if (typeof innerParams.willClose === 'function') {
3125
- innerParams.willClose(popup);
3227
+ const stopTimer = () => {
3228
+ if (globalState.timeout) {
3229
+ stopTimerProgressBar();
3230
+ return globalState.timeout.stop();
3126
3231
  }
3232
+ };
3233
+ /**
3234
+ * Resume timer. Returns number of milliseconds of timer remained.
3235
+ * If `timer` parameter isn't set, returns undefined.
3236
+ */
3127
3237
 
3128
- if (animationIsSupported) {
3129
- animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose);
3130
- } else {
3131
- // Otherwise, remove immediately
3132
- removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose);
3238
+ const resumeTimer = () => {
3239
+ if (globalState.timeout) {
3240
+ const remaining = globalState.timeout.start();
3241
+ animateTimerProgressBar(remaining);
3242
+ return remaining;
3133
3243
  }
3134
3244
  };
3245
+ /**
3246
+ * Resume timer. Returns number of milliseconds of timer remained.
3247
+ * If `timer` parameter isn't set, returns undefined.
3248
+ */
3135
3249
 
3136
- const animatePopup = (instance, popup, container, returnFocus, didClose) => {
3137
- globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose);
3138
- popup.addEventListener(animationEndEvent, function (e) {
3139
- if (e.target === popup) {
3140
- globalState.swalCloseEventFinishedCallback();
3141
- delete globalState.swalCloseEventFinishedCallback;
3142
- }
3143
- });
3250
+ const toggleTimer = () => {
3251
+ const timer = globalState.timeout;
3252
+ return timer && (timer.running ? stopTimer() : resumeTimer());
3144
3253
  };
3254
+ /**
3255
+ * Increase timer. Returns number of milliseconds of an updated timer.
3256
+ * If `timer` parameter isn't set, returns undefined.
3257
+ */
3145
3258
 
3146
- const triggerDidCloseAndDispose = (instance, didClose) => {
3147
- setTimeout(() => {
3148
- if (typeof didClose === 'function') {
3149
- didClose.bind(instance.params)();
3150
- }
3151
-
3152
- instance._destroy();
3153
- });
3259
+ const increaseTimer = n => {
3260
+ if (globalState.timeout) {
3261
+ const remaining = globalState.timeout.increase(n);
3262
+ animateTimerProgressBar(remaining, true);
3263
+ return remaining;
3264
+ }
3154
3265
  };
3266
+ /**
3267
+ * Check if timer is running. Returns true if timer is running
3268
+ * or false if timer is paused or stopped.
3269
+ * If `timer` parameter isn't set, returns undefined
3270
+ */
3155
3271
 
3156
- function setButtonsDisabled(instance, buttons, disabled) {
3157
- const domCache = privateProps.domCache.get(instance);
3158
- buttons.forEach(button => {
3159
- domCache[button].disabled = disabled;
3160
- });
3161
- }
3162
-
3163
- function setInputDisabled(input, disabled) {
3164
- if (!input) {
3165
- return false;
3166
- }
3272
+ const isTimerRunning = () => {
3273
+ return globalState.timeout && globalState.timeout.isRunning();
3274
+ };
3167
3275
 
3168
- if (input.type === 'radio') {
3169
- const radiosContainer = input.parentNode.parentNode;
3170
- const radios = radiosContainer.querySelectorAll('input');
3276
+ let bodyClickListenerAdded = false;
3277
+ const clickHandlers = {};
3278
+ function bindClickHandler() {
3279
+ let attr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'data-swal-template';
3280
+ clickHandlers[attr] = this;
3171
3281
 
3172
- for (let i = 0; i < radios.length; i++) {
3173
- radios[i].disabled = disabled;
3174
- }
3175
- } else {
3176
- input.disabled = disabled;
3282
+ if (!bodyClickListenerAdded) {
3283
+ document.body.addEventListener('click', bodyClickListener);
3284
+ bodyClickListenerAdded = true;
3177
3285
  }
3178
3286
  }
3179
3287
 
3180
- function enableButtons() {
3181
- setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
3182
- }
3183
- function disableButtons() {
3184
- setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
3185
- }
3186
- function enableInput() {
3187
- return setInputDisabled(this.getInput(), false);
3188
- }
3189
- function disableInput() {
3190
- return setInputDisabled(this.getInput(), true);
3191
- }
3192
-
3193
- function showValidationMessage(error) {
3194
- const domCache = privateProps.domCache.get(this);
3195
- const params = privateProps.innerParams.get(this);
3196
- setInnerHtml(domCache.validationMessage, error);
3197
- domCache.validationMessage.className = swalClasses['validation-message'];
3198
-
3199
- if (params.customClass && params.customClass.validationMessage) {
3200
- addClass(domCache.validationMessage, params.customClass.validationMessage);
3201
- }
3202
-
3203
- show(domCache.validationMessage);
3204
- const input = this.getInput();
3288
+ const bodyClickListener = event => {
3289
+ for (let el = event.target; el && el !== document; el = el.parentNode) {
3290
+ for (const attr in clickHandlers) {
3291
+ const template = el.getAttribute(attr);
3205
3292
 
3206
- if (input) {
3207
- input.setAttribute('aria-invalid', true);
3208
- input.setAttribute('aria-describedby', swalClasses['validation-message']);
3209
- focusInput(input);
3210
- addClass(input, swalClasses.inputerror);
3293
+ if (template) {
3294
+ clickHandlers[attr].fire({
3295
+ template
3296
+ });
3297
+ return;
3298
+ }
3299
+ }
3211
3300
  }
3212
- } // Hide block with validation message
3301
+ };
3213
3302
 
3214
- function resetValidationMessage$1() {
3215
- const domCache = privateProps.domCache.get(this);
3216
3303
 
3217
- if (domCache.validationMessage) {
3218
- hide(domCache.validationMessage);
3219
- }
3220
3304
 
3221
- const input = this.getInput();
3305
+ var staticMethods = /*#__PURE__*/Object.freeze({
3306
+ isValidParameter: isValidParameter,
3307
+ isUpdatableParameter: isUpdatableParameter,
3308
+ isDeprecatedParameter: isDeprecatedParameter,
3309
+ argsToParams: argsToParams,
3310
+ isVisible: isVisible$1,
3311
+ clickConfirm: clickConfirm,
3312
+ clickDeny: clickDeny,
3313
+ clickCancel: clickCancel,
3314
+ getContainer: getContainer,
3315
+ getPopup: getPopup,
3316
+ getTitle: getTitle,
3317
+ getHtmlContainer: getHtmlContainer,
3318
+ getImage: getImage,
3319
+ getIcon: getIcon,
3320
+ getInputLabel: getInputLabel,
3321
+ getCloseButton: getCloseButton,
3322
+ getActions: getActions,
3323
+ getConfirmButton: getConfirmButton,
3324
+ getDenyButton: getDenyButton,
3325
+ getCancelButton: getCancelButton,
3326
+ getLoader: getLoader,
3327
+ getFooter: getFooter,
3328
+ getTimerProgressBar: getTimerProgressBar,
3329
+ getFocusableElements: getFocusableElements,
3330
+ getValidationMessage: getValidationMessage,
3331
+ isLoading: isLoading,
3332
+ fire: fire,
3333
+ mixin: mixin,
3334
+ showLoading: showLoading,
3335
+ enableLoading: showLoading,
3336
+ getTimerLeft: getTimerLeft,
3337
+ stopTimer: stopTimer,
3338
+ resumeTimer: resumeTimer,
3339
+ toggleTimer: toggleTimer,
3340
+ increaseTimer: increaseTimer,
3341
+ isTimerRunning: isTimerRunning,
3342
+ bindClickHandler: bindClickHandler
3343
+ });
3222
3344
 
3223
- if (input) {
3224
- input.removeAttribute('aria-invalid');
3225
- input.removeAttribute('aria-describedby');
3226
- removeClass(input, swalClasses.inputerror);
3345
+ class Timer {
3346
+ /**
3347
+ * @param {Function} callback
3348
+ * @param {number} delay
3349
+ */
3350
+ constructor(callback, delay) {
3351
+ this.callback = callback;
3352
+ this.remaining = delay;
3353
+ this.running = false;
3354
+ this.start();
3227
3355
  }
3228
- }
3229
3356
 
3230
- function getProgressSteps$1() {
3231
- const domCache = privateProps.domCache.get(this);
3232
- return domCache.progressSteps;
3233
- }
3357
+ start() {
3358
+ if (!this.running) {
3359
+ this.running = true;
3360
+ this.started = new Date();
3361
+ this.id = setTimeout(this.callback, this.remaining);
3362
+ }
3234
3363
 
3235
- /**
3236
- * Updates popup parameters.
3237
- */
3364
+ return this.remaining;
3365
+ }
3238
3366
 
3239
- function update(params) {
3240
- const popup = getPopup();
3241
- const innerParams = privateProps.innerParams.get(this);
3367
+ stop() {
3368
+ if (this.running) {
3369
+ this.running = false;
3370
+ clearTimeout(this.id);
3371
+ this.remaining -= new Date().getTime() - this.started.getTime();
3372
+ }
3242
3373
 
3243
- if (!popup || hasClass(popup, innerParams.hideClass.popup)) {
3244
- return warn("You're trying to update the closed or closing popup, that won't work. Use the update() method in preConfirm parameter or show a new popup.");
3374
+ return this.remaining;
3245
3375
  }
3246
3376
 
3247
- const validUpdatableParams = filterValidParams(params);
3248
- const updatedParams = Object.assign({}, innerParams, validUpdatableParams);
3249
- render(this, updatedParams);
3250
- privateProps.innerParams.set(this, updatedParams);
3251
- Object.defineProperties(this, {
3252
- params: {
3253
- value: Object.assign({}, this.params, params),
3254
- writable: false,
3255
- enumerable: true
3256
- }
3257
- });
3258
- }
3377
+ increase(n) {
3378
+ const running = this.running;
3259
3379
 
3260
- const filterValidParams = params => {
3261
- const validUpdatableParams = {};
3262
- Object.keys(params).forEach(param => {
3263
- if (isUpdatableParameter(param)) {
3264
- validUpdatableParams[param] = params[param];
3265
- } else {
3266
- warn("Invalid parameter to update: ".concat(param));
3380
+ if (running) {
3381
+ this.stop();
3267
3382
  }
3268
- });
3269
- return validUpdatableParams;
3270
- };
3271
3383
 
3272
- function _destroy() {
3273
- const domCache = privateProps.domCache.get(this);
3274
- const innerParams = privateProps.innerParams.get(this);
3384
+ this.remaining += n;
3275
3385
 
3276
- if (!innerParams) {
3277
- disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
3386
+ if (running) {
3387
+ this.start();
3388
+ }
3278
3389
 
3279
- return; // This instance has already been destroyed
3280
- } // Check if there is another Swal closing
3390
+ return this.remaining;
3391
+ }
3281
3392
 
3393
+ getTimerLeft() {
3394
+ if (this.running) {
3395
+ this.stop();
3396
+ this.start();
3397
+ }
3282
3398
 
3283
- if (domCache.popup && globalState.swalCloseEventFinishedCallback) {
3284
- globalState.swalCloseEventFinishedCallback();
3285
- delete globalState.swalCloseEventFinishedCallback;
3399
+ return this.remaining;
3286
3400
  }
3287
3401
 
3288
- if (typeof innerParams.didDestroy === 'function') {
3289
- innerParams.didDestroy();
3402
+ isRunning() {
3403
+ return this.running;
3290
3404
  }
3291
3405
 
3292
- disposeSwal(this);
3293
3406
  }
3294
- /**
3295
- * @param {SweetAlert2} instance
3296
- */
3297
-
3298
- const disposeSwal = instance => {
3299
- disposeWeakMaps(instance); // Unset this.params so GC will dispose it (#1569)
3300
- // @ts-ignore
3301
-
3302
- delete instance.params; // Unset globalState props so GC will dispose globalState (#1569)
3303
-
3304
- delete globalState.keydownHandler;
3305
- delete globalState.keydownTarget; // Unset currentInstance
3306
3407
 
3307
- delete globalState.currentInstance;
3308
- };
3408
+ const swalStringParams = ['swal-title', 'swal-html', 'swal-footer'];
3309
3409
  /**
3310
- * @param {SweetAlert2} instance
3410
+ * @param {SweetAlertOptions} params
3411
+ * @returns {SweetAlertOptions}
3311
3412
  */
3312
3413
 
3414
+ const getTemplateParams = params => {
3415
+ /** @type {HTMLTemplateElement} */
3416
+ const template = typeof params.template === 'string' ? document.querySelector(params.template) : params.template;
3313
3417
 
3314
- const disposeWeakMaps = instance => {
3315
- // If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335
3316
- // @ts-ignore
3317
- if (instance.isAwaitingPromise()) {
3318
- unsetWeakMaps(privateProps, instance);
3319
- privateProps.awaitingPromise.set(instance, true);
3320
- } else {
3321
- unsetWeakMaps(privateMethods, instance);
3322
- unsetWeakMaps(privateProps, instance);
3418
+ if (!template) {
3419
+ return {};
3323
3420
  }
3324
- };
3325
- /**
3326
- * @param {object} obj
3327
- * @param {SweetAlert2} instance
3328
- */
3421
+ /** @type {DocumentFragment} */
3329
3422
 
3330
3423
 
3331
- const unsetWeakMaps = (obj, instance) => {
3332
- for (const i in obj) {
3333
- obj[i].delete(instance);
3334
- }
3424
+ const templateContent = template.content;
3425
+ showWarningsForElements(templateContent);
3426
+ const result = Object.assign(getSwalParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams));
3427
+ return result;
3335
3428
  };
3336
-
3337
-
3338
-
3339
- var instanceMethods = /*#__PURE__*/Object.freeze({
3340
- hideLoading: hideLoading,
3341
- disableLoading: hideLoading,
3342
- getInput: getInput$1,
3343
- close: close,
3344
- isAwaitingPromise: isAwaitingPromise,
3345
- rejectPromise: rejectPromise,
3346
- handleAwaitingPromise: handleAwaitingPromise,
3347
- closePopup: close,
3348
- closeModal: close,
3349
- closeToast: close,
3350
- enableButtons: enableButtons,
3351
- disableButtons: disableButtons,
3352
- enableInput: enableInput,
3353
- disableInput: disableInput,
3354
- showValidationMessage: showValidationMessage,
3355
- resetValidationMessage: resetValidationMessage$1,
3356
- getProgressSteps: getProgressSteps$1,
3357
- update: update,
3358
- _destroy: _destroy
3359
- });
3360
-
3361
3429
  /**
3362
- * @param {SweetAlert2} instance
3430
+ * @param {DocumentFragment} templateContent
3431
+ * @returns {SweetAlertOptions}
3363
3432
  */
3364
3433
 
3365
- const handleConfirmButtonClick = instance => {
3366
- const innerParams = privateProps.innerParams.get(instance);
3367
- instance.disableButtons();
3368
-
3369
- if (innerParams.input) {
3370
- handleConfirmOrDenyWithInput(instance, 'confirm');
3371
- } else {
3372
- confirm(instance, true);
3373
- }
3374
- };
3375
- /**
3376
- * @param {SweetAlert2} instance
3377
- */
3434
+ const getSwalParams = templateContent => {
3435
+ const result = {};
3436
+ /** @type {HTMLElement[]} */
3378
3437
 
3379
- const handleDenyButtonClick = instance => {
3380
- const innerParams = privateProps.innerParams.get(instance);
3381
- instance.disableButtons();
3438
+ const swalParams = Array.from(templateContent.querySelectorAll('swal-param'));
3439
+ swalParams.forEach(param => {
3440
+ showWarningsForAttributes(param, ['name', 'value']);
3441
+ const paramName = param.getAttribute('name');
3442
+ const value = param.getAttribute('value');
3382
3443
 
3383
- if (innerParams.returnInputValueOnDeny) {
3384
- handleConfirmOrDenyWithInput(instance, 'deny');
3385
- } else {
3386
- deny(instance, false);
3387
- }
3388
- };
3389
- /**
3390
- * @param {SweetAlert2} instance
3391
- * @param {Function} dismissWith
3392
- */
3444
+ if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {
3445
+ result[paramName] = false;
3446
+ }
3393
3447
 
3394
- const handleCancelButtonClick = (instance, dismissWith) => {
3395
- instance.disableButtons();
3396
- dismissWith(DismissReason.cancel);
3448
+ if (typeof defaultParams[paramName] === 'object') {
3449
+ result[paramName] = JSON.parse(value);
3450
+ }
3451
+ });
3452
+ return result;
3397
3453
  };
3398
3454
  /**
3399
- * @param {SweetAlert2} instance
3400
- * @param {'confirm' | 'deny'} type
3455
+ * @param {DocumentFragment} templateContent
3456
+ * @returns {SweetAlertOptions}
3401
3457
  */
3402
3458
 
3403
- const handleConfirmOrDenyWithInput = (instance, type) => {
3404
- const innerParams = privateProps.innerParams.get(instance);
3405
-
3406
- if (!innerParams.input) {
3407
- error("The \"input\" parameter is needed to be set when using returnInputValueOn".concat(capitalizeFirstLetter(type)));
3408
- return;
3409
- }
3410
-
3411
- const inputValue = getInputValue(instance, innerParams);
3412
3459
 
3413
- if (innerParams.inputValidator) {
3414
- handleInputValidator(instance, inputValue, type);
3415
- } else if (!instance.getInput().checkValidity()) {
3416
- instance.enableButtons();
3417
- instance.showValidationMessage(innerParams.validationMessage);
3418
- } else if (type === 'deny') {
3419
- deny(instance, inputValue);
3420
- } else {
3421
- confirm(instance, inputValue);
3422
- }
3423
- };
3424
- /**
3425
- * @param {SweetAlert2} instance
3426
- * @param {string} inputValue
3427
- * @param {'confirm' | 'deny'} type
3428
- */
3460
+ const getSwalButtons = templateContent => {
3461
+ const result = {};
3462
+ /** @type {HTMLElement[]} */
3429
3463
 
3464
+ const swalButtons = Array.from(templateContent.querySelectorAll('swal-button'));
3465
+ swalButtons.forEach(button => {
3466
+ showWarningsForAttributes(button, ['type', 'color', 'aria-label']);
3467
+ const type = button.getAttribute('type');
3468
+ result["".concat(type, "ButtonText")] = button.innerHTML;
3469
+ result["show".concat(capitalizeFirstLetter(type), "Button")] = true;
3430
3470
 
3431
- const handleInputValidator = (instance, inputValue, type) => {
3432
- const innerParams = privateProps.innerParams.get(instance);
3433
- instance.disableInput();
3434
- const validationPromise = Promise.resolve().then(() => asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage)));
3435
- validationPromise.then(validationMessage => {
3436
- instance.enableButtons();
3437
- instance.enableInput();
3471
+ if (button.hasAttribute('color')) {
3472
+ result["".concat(type, "ButtonColor")] = button.getAttribute('color');
3473
+ }
3438
3474
 
3439
- if (validationMessage) {
3440
- instance.showValidationMessage(validationMessage);
3441
- } else if (type === 'deny') {
3442
- deny(instance, inputValue);
3443
- } else {
3444
- confirm(instance, inputValue);
3475
+ if (button.hasAttribute('aria-label')) {
3476
+ result["".concat(type, "ButtonAriaLabel")] = button.getAttribute('aria-label');
3445
3477
  }
3446
3478
  });
3479
+ return result;
3447
3480
  };
3448
3481
  /**
3449
- * @param {SweetAlert2} instance
3450
- * @param {any} value
3482
+ * @param {DocumentFragment} templateContent
3483
+ * @returns {SweetAlertOptions}
3451
3484
  */
3452
3485
 
3453
3486
 
3454
- const deny = (instance, value) => {
3455
- const innerParams = privateProps.innerParams.get(instance || undefined);
3487
+ const getSwalImage = templateContent => {
3488
+ const result = {};
3489
+ /** @type {HTMLElement} */
3456
3490
 
3457
- if (innerParams.showLoaderOnDeny) {
3458
- showLoading(getDenyButton());
3459
- }
3491
+ const image = templateContent.querySelector('swal-image');
3460
3492
 
3461
- if (innerParams.preDeny) {
3462
- privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preDeny's promise is received
3493
+ if (image) {
3494
+ showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']);
3463
3495
 
3464
- const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage)));
3465
- preDenyPromise.then(preDenyValue => {
3466
- if (preDenyValue === false) {
3467
- instance.hideLoading();
3468
- handleAwaitingPromise(instance);
3469
- } else {
3470
- instance.close({
3471
- isDenied: true,
3472
- value: typeof preDenyValue === 'undefined' ? value : preDenyValue
3473
- });
3474
- }
3475
- }).catch(error$$1 => rejectWith(instance || undefined, error$$1));
3476
- } else {
3477
- instance.close({
3478
- isDenied: true,
3479
- value
3480
- });
3496
+ if (image.hasAttribute('src')) {
3497
+ result.imageUrl = image.getAttribute('src');
3498
+ }
3499
+
3500
+ if (image.hasAttribute('width')) {
3501
+ result.imageWidth = image.getAttribute('width');
3502
+ }
3503
+
3504
+ if (image.hasAttribute('height')) {
3505
+ result.imageHeight = image.getAttribute('height');
3506
+ }
3507
+
3508
+ if (image.hasAttribute('alt')) {
3509
+ result.imageAlt = image.getAttribute('alt');
3510
+ }
3481
3511
  }
3512
+
3513
+ return result;
3482
3514
  };
3483
3515
  /**
3484
- * @param {SweetAlert2} instance
3485
- * @param {any} value
3516
+ * @param {DocumentFragment} templateContent
3517
+ * @returns {SweetAlertOptions}
3486
3518
  */
3487
3519
 
3488
3520
 
3489
- const succeedWith = (instance, value) => {
3490
- instance.close({
3491
- isConfirmed: true,
3492
- value
3493
- });
3494
- };
3495
- /**
3496
- *
3497
- * @param {SweetAlert2} instance
3498
- * @param {string} error
3499
- */
3521
+ const getSwalIcon = templateContent => {
3522
+ const result = {};
3523
+ /** @type {HTMLElement} */
3500
3524
 
3525
+ const icon = templateContent.querySelector('swal-icon');
3501
3526
 
3502
- const rejectWith = (instance, error$$1) => {
3503
- // @ts-ignore
3504
- instance.rejectPromise(error$$1);
3527
+ if (icon) {
3528
+ showWarningsForAttributes(icon, ['type', 'color']);
3529
+
3530
+ if (icon.hasAttribute('type')) {
3531
+ /** @type {SweetAlertIcon} */
3532
+ // @ts-ignore
3533
+ result.icon = icon.getAttribute('type');
3534
+ }
3535
+
3536
+ if (icon.hasAttribute('color')) {
3537
+ result.iconColor = icon.getAttribute('color');
3538
+ }
3539
+
3540
+ result.iconHtml = icon.innerHTML;
3541
+ }
3542
+
3543
+ return result;
3505
3544
  };
3506
3545
  /**
3507
- *
3508
- * @param {SweetAlert2} instance
3509
- * @param {any} value
3546
+ * @param {DocumentFragment} templateContent
3547
+ * @returns {SweetAlertOptions}
3510
3548
  */
3511
3549
 
3512
3550
 
3513
- const confirm = (instance, value) => {
3514
- const innerParams = privateProps.innerParams.get(instance || undefined);
3551
+ const getSwalInput = templateContent => {
3552
+ const result = {};
3553
+ /** @type {HTMLElement} */
3515
3554
 
3516
- if (innerParams.showLoaderOnConfirm) {
3517
- showLoading();
3518
- }
3555
+ const input = templateContent.querySelector('swal-input');
3519
3556
 
3520
- if (innerParams.preConfirm) {
3521
- instance.resetValidationMessage();
3522
- privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preConfirm's promise is received
3557
+ if (input) {
3558
+ showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value']);
3559
+ /** @type {SweetAlertInput} */
3560
+ // @ts-ignore
3523
3561
 
3524
- const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
3525
- preConfirmPromise.then(preConfirmValue => {
3526
- if (isVisible(getValidationMessage()) || preConfirmValue === false) {
3527
- instance.hideLoading();
3528
- handleAwaitingPromise(instance);
3529
- } else {
3530
- succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);
3531
- }
3532
- }).catch(error$$1 => rejectWith(instance || undefined, error$$1));
3533
- } else {
3534
- succeedWith(instance, value);
3535
- }
3536
- };
3562
+ result.input = input.getAttribute('type') || 'text';
3537
3563
 
3538
- const handlePopupClick = (instance, domCache, dismissWith) => {
3539
- const innerParams = privateProps.innerParams.get(instance);
3564
+ if (input.hasAttribute('label')) {
3565
+ result.inputLabel = input.getAttribute('label');
3566
+ }
3540
3567
 
3541
- if (innerParams.toast) {
3542
- handleToastClick(instance, domCache, dismissWith);
3543
- } else {
3544
- // Ignore click events that had mousedown on the popup but mouseup on the container
3545
- // This can happen when the user drags a slider
3546
- handleModalMousedown(domCache); // Ignore click events that had mousedown on the container but mouseup on the popup
3568
+ if (input.hasAttribute('placeholder')) {
3569
+ result.inputPlaceholder = input.getAttribute('placeholder');
3570
+ }
3547
3571
 
3548
- handleContainerMousedown(domCache);
3549
- handleModalClick(instance, domCache, dismissWith);
3572
+ if (input.hasAttribute('value')) {
3573
+ result.inputValue = input.getAttribute('value');
3574
+ }
3550
3575
  }
3551
- };
3576
+ /** @type {HTMLElement[]} */
3552
3577
 
3553
- const handleToastClick = (instance, domCache, dismissWith) => {
3554
- // Closing toast by internal click
3555
- domCache.popup.onclick = () => {
3556
- const innerParams = privateProps.innerParams.get(instance);
3557
3578
 
3558
- if (innerParams && (isAnyButtonShown(innerParams) || innerParams.timer || innerParams.input)) {
3559
- return;
3560
- }
3579
+ const inputOptions = Array.from(templateContent.querySelectorAll('swal-input-option'));
3561
3580
 
3562
- dismissWith(DismissReason.close);
3563
- };
3581
+ if (inputOptions.length) {
3582
+ result.inputOptions = {};
3583
+ inputOptions.forEach(option => {
3584
+ showWarningsForAttributes(option, ['value']);
3585
+ const optionValue = option.getAttribute('value');
3586
+ const optionName = option.innerHTML;
3587
+ result.inputOptions[optionValue] = optionName;
3588
+ });
3589
+ }
3590
+
3591
+ return result;
3564
3592
  };
3565
3593
  /**
3566
- * @param {*} innerParams
3567
- * @returns {boolean}
3594
+ * @param {DocumentFragment} templateContent
3595
+ * @param {string[]} paramNames
3596
+ * @returns {SweetAlertOptions}
3568
3597
  */
3569
3598
 
3570
3599
 
3571
- const isAnyButtonShown = innerParams => {
3572
- return innerParams.showConfirmButton || innerParams.showDenyButton || innerParams.showCancelButton || innerParams.showCloseButton;
3573
- };
3574
-
3575
- let ignoreOutsideClick = false;
3600
+ const getSwalStringParams = (templateContent, paramNames) => {
3601
+ const result = {};
3576
3602
 
3577
- const handleModalMousedown = domCache => {
3578
- domCache.popup.onmousedown = () => {
3579
- domCache.container.onmouseup = function (e) {
3580
- domCache.container.onmouseup = undefined; // We only check if the mouseup target is the container because usually it doesn't
3581
- // have any other direct children aside of the popup
3603
+ for (const i in paramNames) {
3604
+ const paramName = paramNames[i];
3605
+ /** @type {HTMLElement} */
3582
3606
 
3583
- if (e.target === domCache.container) {
3584
- ignoreOutsideClick = true;
3585
- }
3586
- };
3587
- };
3588
- };
3607
+ const tag = templateContent.querySelector(paramName);
3589
3608
 
3590
- const handleContainerMousedown = domCache => {
3591
- domCache.container.onmousedown = () => {
3592
- domCache.popup.onmouseup = function (e) {
3593
- domCache.popup.onmouseup = undefined; // We also need to check if the mouseup target is a child of the popup
3609
+ if (tag) {
3610
+ showWarningsForAttributes(tag, []);
3611
+ result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim();
3612
+ }
3613
+ }
3594
3614
 
3595
- if (e.target === domCache.popup || domCache.popup.contains(e.target)) {
3596
- ignoreOutsideClick = true;
3597
- }
3598
- };
3599
- };
3615
+ return result;
3600
3616
  };
3617
+ /**
3618
+ * @param {DocumentFragment} templateContent
3619
+ */
3601
3620
 
3602
- const handleModalClick = (instance, domCache, dismissWith) => {
3603
- domCache.container.onclick = e => {
3604
- const innerParams = privateProps.innerParams.get(instance);
3605
3621
 
3606
- if (ignoreOutsideClick) {
3607
- ignoreOutsideClick = false;
3608
- return;
3609
- }
3622
+ const showWarningsForElements = templateContent => {
3623
+ const allowedElements = swalStringParams.concat(['swal-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']);
3624
+ Array.from(templateContent.children).forEach(el => {
3625
+ const tagName = el.tagName.toLowerCase();
3610
3626
 
3611
- if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) {
3612
- dismissWith(DismissReason.backdrop);
3627
+ if (!allowedElements.includes(tagName)) {
3628
+ warn("Unrecognized element <".concat(tagName, ">"));
3613
3629
  }
3614
- };
3630
+ });
3615
3631
  };
3632
+ /**
3633
+ * @param {HTMLElement} el
3634
+ * @param {string[]} allowedAttributes
3635
+ */
3616
3636
 
3617
- const isJqueryElement = elem => typeof elem === 'object' && elem.jquery;
3618
3637
 
3619
- const isElement = elem => elem instanceof Element || isJqueryElement(elem);
3638
+ const showWarningsForAttributes = (el, allowedAttributes) => {
3639
+ Array.from(el.attributes).forEach(attribute => {
3640
+ if (allowedAttributes.indexOf(attribute.name) === -1) {
3641
+ 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.')]);
3642
+ }
3643
+ });
3644
+ };
3620
3645
 
3621
- const argsToParams = args => {
3622
- const params = {};
3646
+ const SHOW_CLASS_TIMEOUT = 10;
3647
+ /**
3648
+ * Open popup, add necessary classes and styles, fix scrollbar
3649
+ *
3650
+ * @param {SweetAlertOptions} params
3651
+ */
3623
3652
 
3624
- if (typeof args[0] === 'object' && !isElement(args[0])) {
3625
- Object.assign(params, args[0]);
3626
- } else {
3627
- ['title', 'html', 'icon'].forEach((name, index) => {
3628
- const arg = args[index];
3653
+ const openPopup = params => {
3654
+ const container = getContainer();
3655
+ const popup = getPopup();
3629
3656
 
3630
- if (typeof arg === 'string' || isElement(arg)) {
3631
- params[name] = arg;
3632
- } else if (arg !== undefined) {
3633
- error("Unexpected type of ".concat(name, "! Expected \"string\" or \"Element\", got ").concat(typeof arg));
3634
- }
3635
- });
3657
+ if (typeof params.willOpen === 'function') {
3658
+ params.willOpen(popup);
3636
3659
  }
3637
3660
 
3638
- return params;
3639
- };
3661
+ const bodyStyles = window.getComputedStyle(document.body);
3662
+ const initialBodyOverflow = bodyStyles.overflowY;
3663
+ addClasses$1(container, popup, params); // scrolling is 'hidden' until animation is done, after that 'auto'
3640
3664
 
3641
- function fire() {
3642
- const Swal = this; // eslint-disable-line @typescript-eslint/no-this-alias
3665
+ setTimeout(() => {
3666
+ setScrollingVisibility(container, popup);
3667
+ }, SHOW_CLASS_TIMEOUT);
3643
3668
 
3644
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
3645
- args[_key] = arguments[_key];
3669
+ if (isModal()) {
3670
+ fixScrollContainer(container, params.scrollbarPadding, initialBodyOverflow);
3671
+ setAriaHidden();
3646
3672
  }
3647
3673
 
3648
- return new Swal(...args);
3649
- }
3674
+ if (!isToast() && !globalState.previousActiveElement) {
3675
+ globalState.previousActiveElement = document.activeElement;
3676
+ }
3677
+
3678
+ if (typeof params.didOpen === 'function') {
3679
+ setTimeout(() => params.didOpen(popup));
3680
+ }
3650
3681
 
3682
+ removeClass(container, swalClasses['no-transition']);
3683
+ };
3651
3684
  /**
3652
- * Returns an extended version of `Swal` containing `params` as defaults.
3653
- * Useful for reusing Swal configuration.
3654
- *
3655
- * For example:
3656
- *
3657
- * Before:
3658
- * const textPromptOptions = { input: 'text', showCancelButton: true }
3659
- * const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' })
3660
- * const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' })
3661
- *
3662
- * After:
3663
- * const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true })
3664
- * const {value: firstName} = await TextPrompt('What is your first name?')
3665
- * const {value: lastName} = await TextPrompt('What is your last name?')
3666
- *
3667
- * @param mixinParams
3685
+ * @param {AnimationEvent} event
3668
3686
  */
3669
- function mixin(mixinParams) {
3670
- class MixinSwal extends this {
3671
- _main(params, priorityMixinParams) {
3672
- return super._main(params, Object.assign({}, mixinParams, priorityMixinParams));
3673
- }
3674
3687
 
3675
- }
3688
+ const swalOpenAnimationFinished = event => {
3689
+ const popup = getPopup();
3676
3690
 
3677
- return MixinSwal;
3678
- }
3691
+ if (event.target !== popup) {
3692
+ return;
3693
+ }
3679
3694
 
3695
+ const container = getContainer();
3696
+ popup.removeEventListener(animationEndEvent, swalOpenAnimationFinished);
3697
+ container.style.overflowY = 'auto';
3698
+ };
3680
3699
  /**
3681
- * If `timer` parameter is set, returns number of milliseconds of timer remained.
3682
- * Otherwise, returns undefined.
3700
+ * @param {HTMLElement} container
3701
+ * @param {HTMLElement} popup
3683
3702
  */
3684
3703
 
3685
- const getTimerLeft = () => {
3686
- return globalState.timeout && globalState.timeout.getTimerLeft();
3704
+
3705
+ const setScrollingVisibility = (container, popup) => {
3706
+ if (animationEndEvent && hasCssAnimation(popup)) {
3707
+ container.style.overflowY = 'hidden';
3708
+ popup.addEventListener(animationEndEvent, swalOpenAnimationFinished);
3709
+ } else {
3710
+ container.style.overflowY = 'auto';
3711
+ }
3687
3712
  };
3688
3713
  /**
3689
- * Stop timer. Returns number of milliseconds of timer remained.
3690
- * If `timer` parameter isn't set, returns undefined.
3714
+ * @param {HTMLElement} container
3715
+ * @param {boolean} scrollbarPadding
3716
+ * @param {string} initialBodyOverflow
3691
3717
  */
3692
3718
 
3693
- const stopTimer = () => {
3694
- if (globalState.timeout) {
3695
- stopTimerProgressBar();
3696
- return globalState.timeout.stop();
3697
- }
3719
+
3720
+ const fixScrollContainer = (container, scrollbarPadding, initialBodyOverflow) => {
3721
+ iOSfix();
3722
+
3723
+ if (scrollbarPadding && initialBodyOverflow !== 'hidden') {
3724
+ fixScrollbar();
3725
+ } // sweetalert2/issues/1247
3726
+
3727
+
3728
+ setTimeout(() => {
3729
+ container.scrollTop = 0;
3730
+ });
3698
3731
  };
3699
3732
  /**
3700
- * Resume timer. Returns number of milliseconds of timer remained.
3701
- * If `timer` parameter isn't set, returns undefined.
3733
+ * @param {HTMLElement} container
3734
+ * @param {HTMLElement} popup
3735
+ * @param {SweetAlertOptions} params
3702
3736
  */
3703
3737
 
3704
- const resumeTimer = () => {
3705
- if (globalState.timeout) {
3706
- const remaining = globalState.timeout.start();
3707
- animateTimerProgressBar(remaining);
3708
- return remaining;
3738
+
3739
+ const addClasses$1 = (container, popup, params) => {
3740
+ addClass(container, params.showClass.backdrop); // this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059
3741
+
3742
+ popup.style.setProperty('opacity', '0', 'important');
3743
+ show(popup, 'grid');
3744
+ setTimeout(() => {
3745
+ // Animate popup right after showing it
3746
+ addClass(popup, params.showClass.popup); // and remove the opacity workaround
3747
+
3748
+ popup.style.removeProperty('opacity');
3749
+ }, SHOW_CLASS_TIMEOUT); // 10ms in order to fix #2062
3750
+
3751
+ addClass([document.documentElement, document.body], swalClasses.shown);
3752
+
3753
+ if (params.heightAuto && params.backdrop && !params.toast) {
3754
+ addClass([document.documentElement, document.body], swalClasses['height-auto']);
3709
3755
  }
3710
3756
  };
3711
- /**
3712
- * Resume timer. Returns number of milliseconds of timer remained.
3713
- * If `timer` parameter isn't set, returns undefined.
3714
- */
3715
3757
 
3716
- const toggleTimer = () => {
3717
- const timer = globalState.timeout;
3718
- return timer && (timer.running ? stopTimer() : resumeTimer());
3758
+ var defaultInputValidators = {
3759
+ /**
3760
+ * @param {string} string
3761
+ * @param {string} validationMessage
3762
+ * @returns {Promise<void | string>}
3763
+ */
3764
+ email: (string, validationMessage) => {
3765
+ return /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid email address');
3766
+ },
3767
+
3768
+ /**
3769
+ * @param {string} string
3770
+ * @param {string} validationMessage
3771
+ * @returns {Promise<void | string>}
3772
+ */
3773
+ url: (string, validationMessage) => {
3774
+ // taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #2013
3775
+ return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid URL');
3776
+ }
3719
3777
  };
3778
+
3720
3779
  /**
3721
- * Increase timer. Returns number of milliseconds of an updated timer.
3722
- * If `timer` parameter isn't set, returns undefined.
3780
+ * @param {SweetAlertOptions} params
3723
3781
  */
3724
3782
 
3725
- const increaseTimer = n => {
3726
- if (globalState.timeout) {
3727
- const remaining = globalState.timeout.increase(n);
3728
- animateTimerProgressBar(remaining, true);
3729
- return remaining;
3783
+ function setDefaultInputValidators(params) {
3784
+ // Use default `inputValidator` for supported input types if not provided
3785
+ if (!params.inputValidator) {
3786
+ Object.keys(defaultInputValidators).forEach(key => {
3787
+ if (params.input === key) {
3788
+ params.inputValidator = defaultInputValidators[key];
3789
+ }
3790
+ });
3730
3791
  }
3731
- };
3792
+ }
3732
3793
  /**
3733
- * Check if timer is running. Returns true if timer is running
3734
- * or false if timer is paused or stopped.
3735
- * If `timer` parameter isn't set, returns undefined
3794
+ * @param {SweetAlertOptions} params
3736
3795
  */
3737
3796
 
3738
- const isTimerRunning = () => {
3739
- return globalState.timeout && globalState.timeout.isRunning();
3740
- };
3741
-
3742
- let bodyClickListenerAdded = false;
3743
- const clickHandlers = {};
3744
- function bindClickHandler() {
3745
- let attr = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'data-swal-template';
3746
- clickHandlers[attr] = this;
3747
3797
 
3748
- if (!bodyClickListenerAdded) {
3749
- document.body.addEventListener('click', bodyClickListener);
3750
- bodyClickListenerAdded = true;
3798
+ function validateCustomTargetElement(params) {
3799
+ // Determine if the custom target element is valid
3800
+ if (!params.target || typeof params.target === 'string' && !document.querySelector(params.target) || typeof params.target !== 'string' && !params.target.appendChild) {
3801
+ warn('Target parameter is not valid, defaulting to "body"');
3802
+ params.target = 'body';
3751
3803
  }
3752
3804
  }
3805
+ /**
3806
+ * Set type, text and actions on popup
3807
+ *
3808
+ * @param {SweetAlertOptions} params
3809
+ */
3753
3810
 
3754
- const bodyClickListener = event => {
3755
- for (let el = event.target; el && el !== document; el = el.parentNode) {
3756
- for (const attr in clickHandlers) {
3757
- const template = el.getAttribute(attr);
3758
3811
 
3759
- if (template) {
3760
- clickHandlers[attr].fire({
3761
- template
3762
- });
3763
- return;
3764
- }
3765
- }
3812
+ function setParameters(params) {
3813
+ setDefaultInputValidators(params); // showLoaderOnConfirm && preConfirm
3814
+
3815
+ if (params.showLoaderOnConfirm && !params.preConfirm) {
3816
+ warn('showLoaderOnConfirm is set to true, but preConfirm is not defined.\n' + 'showLoaderOnConfirm should be used together with preConfirm, see usage example:\n' + 'https://sweetalert2.github.io/#ajax-request');
3766
3817
  }
3767
- };
3768
3818
 
3819
+ validateCustomTargetElement(params); // Replace newlines with <br> in title
3769
3820
 
3821
+ if (typeof params.title === 'string') {
3822
+ params.title = params.title.split('\n').join('<br />');
3823
+ }
3770
3824
 
3771
- var staticMethods = /*#__PURE__*/Object.freeze({
3772
- isValidParameter: isValidParameter,
3773
- isUpdatableParameter: isUpdatableParameter,
3774
- isDeprecatedParameter: isDeprecatedParameter,
3775
- argsToParams: argsToParams,
3776
- isVisible: isVisible$1,
3777
- clickConfirm: clickConfirm,
3778
- clickDeny: clickDeny,
3779
- clickCancel: clickCancel,
3780
- getContainer: getContainer,
3781
- getPopup: getPopup,
3782
- getTitle: getTitle,
3783
- getHtmlContainer: getHtmlContainer,
3784
- getImage: getImage,
3785
- getIcon: getIcon,
3786
- getInputLabel: getInputLabel,
3787
- getCloseButton: getCloseButton,
3788
- getActions: getActions,
3789
- getConfirmButton: getConfirmButton,
3790
- getDenyButton: getDenyButton,
3791
- getCancelButton: getCancelButton,
3792
- getLoader: getLoader,
3793
- getFooter: getFooter,
3794
- getTimerProgressBar: getTimerProgressBar,
3795
- getFocusableElements: getFocusableElements,
3796
- getValidationMessage: getValidationMessage,
3797
- isLoading: isLoading,
3798
- fire: fire,
3799
- mixin: mixin,
3800
- showLoading: showLoading,
3801
- enableLoading: showLoading,
3802
- getTimerLeft: getTimerLeft,
3803
- stopTimer: stopTimer,
3804
- resumeTimer: resumeTimer,
3805
- toggleTimer: toggleTimer,
3806
- increaseTimer: increaseTimer,
3807
- isTimerRunning: isTimerRunning,
3808
- bindClickHandler: bindClickHandler
3809
- });
3825
+ init(params);
3826
+ }
3810
3827
 
3811
3828
  let currentInstance;
3812
3829
 
@@ -4066,7 +4083,7 @@
4066
4083
  };
4067
4084
  });
4068
4085
  SweetAlert.DismissReason = DismissReason;
4069
- SweetAlert.version = '11.4.30';
4086
+ SweetAlert.version = '11.4.31';
4070
4087
 
4071
4088
  const Swal = SweetAlert; // @ts-ignore
4072
4089