sweetalert2 11.7.5 → 11.7.7

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.7.5
2
+ * sweetalert2 v11.7.7
3
3
  * Released under the MIT License.
4
4
  */
5
5
  (function (global, factory) {
@@ -8,6 +8,41 @@
8
8
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Sweetalert2 = factory());
9
9
  })(this, (function () { 'use strict';
10
10
 
11
+ const RESTORE_FOCUS_TIMEOUT = 100;
12
+
13
+ /** @type {GlobalState} */
14
+ const globalState = {};
15
+ const focusPreviousActiveElement = () => {
16
+ if (globalState.previousActiveElement instanceof HTMLElement) {
17
+ globalState.previousActiveElement.focus();
18
+ globalState.previousActiveElement = null;
19
+ } else if (document.body) {
20
+ document.body.focus();
21
+ }
22
+ };
23
+
24
+ /**
25
+ * Restore previous active (focused) element
26
+ *
27
+ * @param {boolean} returnFocus
28
+ * @returns {Promise}
29
+ */
30
+ const restoreActiveElement = returnFocus => {
31
+ return new Promise(resolve => {
32
+ if (!returnFocus) {
33
+ return resolve();
34
+ }
35
+ const x = window.scrollX;
36
+ const y = window.scrollY;
37
+ globalState.restoreFocusTimeout = setTimeout(() => {
38
+ focusPreviousActiveElement();
39
+ resolve();
40
+ }, RESTORE_FOCUS_TIMEOUT); // issues/900
41
+
42
+ window.scrollTo(x, y);
43
+ });
44
+ };
45
+
11
46
  /**
12
47
  * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
13
48
  * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
@@ -19,7 +54,6 @@
19
54
  */
20
55
 
21
56
  var privateProps = {
22
- awaitingPromise: new WeakMap(),
23
57
  promise: new WeakMap(),
24
58
  innerParams: new WeakMap(),
25
59
  domCache: new WeakMap()
@@ -597,41 +631,6 @@
597
631
  timerProgressBar.style.width = `${timerProgressBarPercent}%`;
598
632
  };
599
633
 
600
- const RESTORE_FOCUS_TIMEOUT = 100;
601
-
602
- /** @type {GlobalState} */
603
- const globalState = {};
604
- const focusPreviousActiveElement = () => {
605
- if (globalState.previousActiveElement instanceof HTMLElement) {
606
- globalState.previousActiveElement.focus();
607
- globalState.previousActiveElement = null;
608
- } else if (document.body) {
609
- document.body.focus();
610
- }
611
- };
612
-
613
- /**
614
- * Restore previous active (focused) element
615
- *
616
- * @param {boolean} returnFocus
617
- * @returns {Promise}
618
- */
619
- const restoreActiveElement = returnFocus => {
620
- return new Promise(resolve => {
621
- if (!returnFocus) {
622
- return resolve();
623
- }
624
- const x = window.scrollX;
625
- const y = window.scrollY;
626
- globalState.restoreFocusTimeout = setTimeout(() => {
627
- focusPreviousActiveElement();
628
- resolve();
629
- }, RESTORE_FOCUS_TIMEOUT); // issues/900
630
-
631
- window.scrollTo(x, y);
632
- });
633
- };
634
-
635
634
  /**
636
635
  * Detect Node env
637
636
  *
@@ -862,7 +861,7 @@
862
861
  };
863
862
 
864
863
  /**
865
- * @param {SweetAlert2} instance
864
+ * @param {SweetAlert} instance
866
865
  * @param {SweetAlertOptions} params
867
866
  */
868
867
  const renderActions = (instance, params) => {
@@ -959,7 +958,7 @@
959
958
  }
960
959
 
961
960
  /**
962
- * @param {SweetAlert2} instance
961
+ * @param {SweetAlert} instance
963
962
  * @param {SweetAlertOptions} params
964
963
  */
965
964
  const renderCloseButton = (instance, params) => {
@@ -973,7 +972,7 @@
973
972
  };
974
973
 
975
974
  /**
976
- * @param {SweetAlert2} instance
975
+ * @param {SweetAlert} instance
977
976
  * @param {SweetAlertOptions} params
978
977
  */
979
978
  const renderContainer = (instance, params) => {
@@ -1029,11 +1028,12 @@
1029
1028
 
1030
1029
  /// <reference path="../../../../sweetalert2.d.ts"/>
1031
1030
 
1031
+
1032
1032
  /** @type {InputClass[]} */
1033
1033
  const inputClasses = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea'];
1034
1034
 
1035
1035
  /**
1036
- * @param {SweetAlert2} instance
1036
+ * @param {SweetAlert} instance
1037
1037
  * @param {SweetAlertOptions} params
1038
1038
  */
1039
1039
  const renderInput = (instance, params) => {
@@ -1292,7 +1292,7 @@
1292
1292
  };
1293
1293
 
1294
1294
  /**
1295
- * @param {SweetAlert2} instance
1295
+ * @param {SweetAlert} instance
1296
1296
  * @param {SweetAlertOptions} params
1297
1297
  */
1298
1298
  const renderContent = (instance, params) => {
@@ -1319,7 +1319,7 @@
1319
1319
  };
1320
1320
 
1321
1321
  /**
1322
- * @param {SweetAlert2} instance
1322
+ * @param {SweetAlert} instance
1323
1323
  * @param {SweetAlertOptions} params
1324
1324
  */
1325
1325
  const renderFooter = (instance, params) => {
@@ -1334,7 +1334,7 @@
1334
1334
  };
1335
1335
 
1336
1336
  /**
1337
- * @param {SweetAlert2} instance
1337
+ * @param {SweetAlert} instance
1338
1338
  * @param {SweetAlertOptions} params
1339
1339
  */
1340
1340
  const renderIcon = (instance, params) => {
@@ -1462,7 +1462,7 @@
1462
1462
  const iconContent = content => `<div class="${swalClasses['icon-content']}">${content}</div>`;
1463
1463
 
1464
1464
  /**
1465
- * @param {SweetAlert2} instance
1465
+ * @param {SweetAlert} instance
1466
1466
  * @param {SweetAlertOptions} params
1467
1467
  */
1468
1468
  const renderImage = (instance, params) => {
@@ -1487,7 +1487,7 @@
1487
1487
  };
1488
1488
 
1489
1489
  /**
1490
- * @param {SweetAlert2} instance
1490
+ * @param {SweetAlert} instance
1491
1491
  * @param {SweetAlertOptions} params
1492
1492
  */
1493
1493
  const renderPopup = (instance, params) => {
@@ -1549,7 +1549,7 @@
1549
1549
  };
1550
1550
 
1551
1551
  /**
1552
- * @param {SweetAlert2} instance
1552
+ * @param {SweetAlert} instance
1553
1553
  * @param {SweetAlertOptions} params
1554
1554
  */
1555
1555
  const renderProgressSteps = (instance, params) => {
@@ -1601,7 +1601,7 @@
1601
1601
  };
1602
1602
 
1603
1603
  /**
1604
- * @param {SweetAlert2} instance
1604
+ * @param {SweetAlert} instance
1605
1605
  * @param {SweetAlertOptions} params
1606
1606
  */
1607
1607
  const renderTitle = (instance, params) => {
@@ -1619,7 +1619,7 @@
1619
1619
  };
1620
1620
 
1621
1621
  /**
1622
- * @param {SweetAlert2} instance
1622
+ * @param {SweetAlert} instance
1623
1623
  * @param {SweetAlertOptions} params
1624
1624
  */
1625
1625
  const render = (instance, params) => {
@@ -1638,55 +1638,6 @@
1638
1638
  }
1639
1639
  };
1640
1640
 
1641
- /**
1642
- * Hides loader and shows back the button which was hidden by .showLoading()
1643
- */
1644
- function hideLoading() {
1645
- // do nothing if popup is closed
1646
- const innerParams = privateProps.innerParams.get(this);
1647
- if (!innerParams) {
1648
- return;
1649
- }
1650
- const domCache = privateProps.domCache.get(this);
1651
- hide(domCache.loader);
1652
- if (isToast()) {
1653
- if (innerParams.icon) {
1654
- show(getIcon());
1655
- }
1656
- } else {
1657
- showRelatedButton(domCache);
1658
- }
1659
- removeClass([domCache.popup, domCache.actions], swalClasses.loading);
1660
- domCache.popup.removeAttribute('aria-busy');
1661
- domCache.popup.removeAttribute('data-loading');
1662
- domCache.confirmButton.disabled = false;
1663
- domCache.denyButton.disabled = false;
1664
- domCache.cancelButton.disabled = false;
1665
- }
1666
- const showRelatedButton = domCache => {
1667
- const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'));
1668
- if (buttonToReplace.length) {
1669
- show(buttonToReplace[0], 'inline-block');
1670
- } else if (allButtonsAreHidden()) {
1671
- hide(domCache.actions);
1672
- }
1673
- };
1674
-
1675
- /**
1676
- * Gets the input DOM node, this method works with input parameter.
1677
- *
1678
- * @param {SweetAlert2} instance
1679
- * @returns {HTMLElement | null}
1680
- */
1681
- function getInput(instance) {
1682
- const innerParams = privateProps.innerParams.get(instance || this);
1683
- const domCache = privateProps.domCache.get(instance || this);
1684
- if (!domCache) {
1685
- return null;
1686
- }
1687
- return getInput$1(domCache.popup, innerParams.input);
1688
- }
1689
-
1690
1641
  /*
1691
1642
  * Global function to determine if SweetAlert2 popup is shown
1692
1643
  */
@@ -1730,7 +1681,7 @@
1730
1681
  };
1731
1682
 
1732
1683
  /**
1733
- * @param {SweetAlert2} instance
1684
+ * @param {SweetAlert} instance
1734
1685
  * @param {GlobalState} globalState
1735
1686
  * @param {SweetAlertOptions} innerParams
1736
1687
  * @param {*} dismissWith
@@ -1776,7 +1727,7 @@
1776
1727
  const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp'];
1777
1728
 
1778
1729
  /**
1779
- * @param {SweetAlert2} instance
1730
+ * @param {SweetAlert} instance
1780
1731
  * @param {KeyboardEvent} event
1781
1732
  * @param {Function} dismissWith
1782
1733
  */
@@ -1819,7 +1770,7 @@
1819
1770
  };
1820
1771
 
1821
1772
  /**
1822
- * @param {SweetAlert2} instance
1773
+ * @param {SweetAlert} instance
1823
1774
  * @param {KeyboardEvent} event
1824
1775
  * @param {SweetAlertOptions} innerParams
1825
1776
  */
@@ -2078,7 +2029,7 @@
2078
2029
  };
2079
2030
 
2080
2031
  /**
2081
- * @param {SweetAlert2} instance
2032
+ * @param {SweetAlert} instance
2082
2033
  * @param {HTMLElement} container
2083
2034
  * @param {boolean} returnFocus
2084
2035
  * @param {Function} didClose
@@ -2124,7 +2075,7 @@
2124
2075
  resolveValue = prepareResolveValue(resolveValue);
2125
2076
  const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this);
2126
2077
  const didClose = triggerClosePopup(this);
2127
- if (this.isAwaitingPromise()) {
2078
+ if (this.isAwaitingPromise) {
2128
2079
  // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
2129
2080
  if (!resolveValue.isDismissed) {
2130
2081
  handleAwaitingPromise(this);
@@ -2135,13 +2086,6 @@
2135
2086
  swalPromiseResolve(resolveValue);
2136
2087
  }
2137
2088
  }
2138
-
2139
- /**
2140
- * @returns {boolean}
2141
- */
2142
- function isAwaitingPromise() {
2143
- return !!privateProps.awaitingPromise.get(this);
2144
- }
2145
2089
  const triggerClosePopup = instance => {
2146
2090
  const popup = getPopup();
2147
2091
  if (!popup) {
@@ -2173,15 +2117,13 @@
2173
2117
  }
2174
2118
 
2175
2119
  /**
2176
- * @param {SweetAlert2} instance
2120
+ * @param {SweetAlert} instance
2177
2121
  */
2178
2122
  const handleAwaitingPromise = instance => {
2179
- // @ts-ignore
2180
- if (instance.isAwaitingPromise()) {
2181
- privateProps.awaitingPromise.delete(instance);
2123
+ if (instance.isAwaitingPromise) {
2124
+ delete instance.isAwaitingPromise;
2182
2125
  // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
2183
2126
  if (!privateProps.innerParams.get(instance)) {
2184
- // @ts-ignore
2185
2127
  instance._destroy();
2186
2128
  }
2187
2129
  }
@@ -2208,7 +2150,7 @@
2208
2150
  };
2209
2151
 
2210
2152
  /**
2211
- * @param {SweetAlert2} instance
2153
+ * @param {SweetAlert} instance
2212
2154
  * @param {HTMLElement} popup
2213
2155
  * @param {SweetAlertOptions} innerParams
2214
2156
  */
@@ -2228,7 +2170,7 @@
2228
2170
  };
2229
2171
 
2230
2172
  /**
2231
- * @param {SweetAlert2} instance
2173
+ * @param {SweetAlert} instance
2232
2174
  * @param {HTMLElement} popup
2233
2175
  * @param {HTMLElement} container
2234
2176
  * @param {boolean} returnFocus
@@ -2245,7 +2187,7 @@
2245
2187
  };
2246
2188
 
2247
2189
  /**
2248
- * @param {SweetAlert2} instance
2190
+ * @param {SweetAlert} instance
2249
2191
  * @param {Function} didClose
2250
2192
  */
2251
2193
  const triggerDidCloseAndDispose = (instance, didClose) => {
@@ -2254,820 +2196,885 @@
2254
2196
  // @ts-ignore
2255
2197
  didClose.bind(instance.params)();
2256
2198
  }
2257
- // @ts-ignore
2258
- instance._destroy();
2199
+ // instance might have been destroyed already
2200
+ if (instance._destroy) {
2201
+ instance._destroy();
2202
+ }
2259
2203
  });
2260
2204
  };
2261
2205
 
2262
2206
  /**
2263
- * @param {SweetAlert2} instance
2264
- * @param {string[]} buttons
2265
- * @param {boolean} disabled
2207
+ * Shows loader (spinner), this is useful with AJAX requests.
2208
+ * By default the loader be shown instead of the "Confirm" button.
2209
+ *
2210
+ * @param {HTMLButtonElement} [buttonToReplace]
2266
2211
  */
2267
- function setButtonsDisabled(instance, buttons, disabled) {
2268
- const domCache = privateProps.domCache.get(instance);
2269
- buttons.forEach(button => {
2270
- domCache[button].disabled = disabled;
2271
- });
2272
- }
2212
+ const showLoading = buttonToReplace => {
2213
+ let popup = getPopup();
2214
+ if (!popup) {
2215
+ new Swal(); // eslint-disable-line no-new
2216
+ }
2217
+
2218
+ popup = getPopup();
2219
+ const loader = getLoader();
2220
+ if (isToast()) {
2221
+ hide(getIcon());
2222
+ } else {
2223
+ replaceButton(popup, buttonToReplace);
2224
+ }
2225
+ show(loader);
2226
+ popup.setAttribute('data-loading', 'true');
2227
+ popup.setAttribute('aria-busy', 'true');
2228
+ popup.focus();
2229
+ };
2273
2230
 
2274
2231
  /**
2275
- * @param {HTMLInputElement} input
2276
- * @param {boolean} disabled
2232
+ * @param {HTMLElement} popup
2233
+ * @param {HTMLButtonElement} [buttonToReplace]
2277
2234
  */
2278
- function setInputDisabled(input, disabled) {
2279
- if (!input) {
2280
- return;
2235
+ const replaceButton = (popup, buttonToReplace) => {
2236
+ const actions = getActions();
2237
+ const loader = getLoader();
2238
+ if (!buttonToReplace && isVisible$1(getConfirmButton())) {
2239
+ buttonToReplace = getConfirmButton();
2281
2240
  }
2282
- if (input.type === 'radio') {
2283
- const radiosContainer = input.parentNode.parentNode;
2284
- const radios = radiosContainer.querySelectorAll('input');
2285
- for (let i = 0; i < radios.length; i++) {
2286
- radios[i].disabled = disabled;
2287
- }
2288
- } else {
2289
- input.disabled = disabled;
2241
+ show(actions);
2242
+ if (buttonToReplace) {
2243
+ hide(buttonToReplace);
2244
+ loader.setAttribute('data-button-to-replace', buttonToReplace.className);
2290
2245
  }
2291
- }
2246
+ loader.parentNode.insertBefore(loader, buttonToReplace);
2247
+ addClass([popup, actions], swalClasses.loading);
2248
+ };
2292
2249
 
2293
2250
  /**
2294
- * Enable all the buttons
2251
+ * @typedef { string | number | boolean } InputValue
2295
2252
  */
2296
- function enableButtons() {
2297
- setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
2298
- }
2299
2253
 
2300
2254
  /**
2301
- * Disable all the buttons
2255
+ * @param {SweetAlert} instance
2256
+ * @param {SweetAlertOptions} params
2302
2257
  */
2303
- function disableButtons() {
2304
- setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
2305
- }
2258
+ const handleInputOptionsAndValue = (instance, params) => {
2259
+ if (params.input === 'select' || params.input === 'radio') {
2260
+ handleInputOptions(instance, params);
2261
+ } else if (['text', 'email', 'number', 'tel', 'textarea'].includes(params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {
2262
+ showLoading(getConfirmButton());
2263
+ handleInputValue(instance, params);
2264
+ }
2265
+ };
2306
2266
 
2307
2267
  /**
2308
- * Enable the input field
2268
+ * @param {SweetAlert} instance
2269
+ * @param {SweetAlertOptions} innerParams
2270
+ * @returns {string | number | File | FileList | null}
2309
2271
  */
2310
- function enableInput() {
2311
- setInputDisabled(this.getInput(), false);
2312
- }
2272
+ const getInputValue = (instance, innerParams) => {
2273
+ const input = instance.getInput();
2274
+ if (!input) {
2275
+ return null;
2276
+ }
2277
+ switch (innerParams.input) {
2278
+ case 'checkbox':
2279
+ return getCheckboxValue(input);
2280
+ case 'radio':
2281
+ return getRadioValue(input);
2282
+ case 'file':
2283
+ return getFileValue(input);
2284
+ default:
2285
+ return innerParams.inputAutoTrim ? input.value.trim() : input.value;
2286
+ }
2287
+ };
2313
2288
 
2314
2289
  /**
2315
- * Disable the input field
2290
+ * @param {HTMLInputElement} input
2291
+ * @returns {number}
2316
2292
  */
2317
- function disableInput() {
2318
- setInputDisabled(this.getInput(), true);
2319
- }
2293
+ const getCheckboxValue = input => input.checked ? 1 : 0;
2320
2294
 
2321
2295
  /**
2322
- * Show block with validation message
2323
- *
2324
- * @param {string} error
2296
+ * @param {HTMLInputElement} input
2297
+ * @returns {string | null}
2325
2298
  */
2326
- function showValidationMessage(error) {
2327
- const domCache = privateProps.domCache.get(this);
2328
- const params = privateProps.innerParams.get(this);
2329
- setInnerHtml(domCache.validationMessage, error);
2330
- domCache.validationMessage.className = swalClasses['validation-message'];
2331
- if (params.customClass && params.customClass.validationMessage) {
2332
- addClass(domCache.validationMessage, params.customClass.validationMessage);
2333
- }
2334
- show(domCache.validationMessage);
2335
- const input = this.getInput();
2336
- if (input) {
2337
- input.setAttribute('aria-invalid', true);
2338
- input.setAttribute('aria-describedby', swalClasses['validation-message']);
2339
- focusInput(input);
2340
- addClass(input, swalClasses.inputerror);
2341
- }
2342
- }
2299
+ const getRadioValue = input => input.checked ? input.value : null;
2343
2300
 
2344
2301
  /**
2345
- * Hide block with validation message
2346
- */
2347
- function resetValidationMessage() {
2348
- const domCache = privateProps.domCache.get(this);
2349
- if (domCache.validationMessage) {
2350
- hide(domCache.validationMessage);
2351
- }
2352
- const input = this.getInput();
2353
- if (input) {
2354
- input.removeAttribute('aria-invalid');
2355
- input.removeAttribute('aria-describedby');
2356
- removeClass(input, swalClasses.inputerror);
2357
- }
2358
- }
2359
-
2360
- const defaultParams = {
2361
- title: '',
2362
- titleText: '',
2363
- text: '',
2364
- html: '',
2365
- footer: '',
2366
- icon: undefined,
2367
- iconColor: undefined,
2368
- iconHtml: undefined,
2369
- template: undefined,
2370
- toast: false,
2371
- showClass: {
2372
- popup: 'swal2-show',
2373
- backdrop: 'swal2-backdrop-show',
2374
- icon: 'swal2-icon-show'
2375
- },
2376
- hideClass: {
2377
- popup: 'swal2-hide',
2378
- backdrop: 'swal2-backdrop-hide',
2379
- icon: 'swal2-icon-hide'
2380
- },
2381
- customClass: {},
2382
- target: 'body',
2383
- color: undefined,
2384
- backdrop: true,
2385
- heightAuto: true,
2386
- allowOutsideClick: true,
2387
- allowEscapeKey: true,
2388
- allowEnterKey: true,
2389
- stopKeydownPropagation: true,
2390
- keydownListenerCapture: false,
2391
- showConfirmButton: true,
2392
- showDenyButton: false,
2393
- showCancelButton: false,
2394
- preConfirm: undefined,
2395
- preDeny: undefined,
2396
- confirmButtonText: 'OK',
2397
- confirmButtonAriaLabel: '',
2398
- confirmButtonColor: undefined,
2399
- denyButtonText: 'No',
2400
- denyButtonAriaLabel: '',
2401
- denyButtonColor: undefined,
2402
- cancelButtonText: 'Cancel',
2403
- cancelButtonAriaLabel: '',
2404
- cancelButtonColor: undefined,
2405
- buttonsStyling: true,
2406
- reverseButtons: false,
2407
- focusConfirm: true,
2408
- focusDeny: false,
2409
- focusCancel: false,
2410
- returnFocus: true,
2411
- showCloseButton: false,
2412
- closeButtonHtml: '&times;',
2413
- closeButtonAriaLabel: 'Close this dialog',
2414
- loaderHtml: '',
2415
- showLoaderOnConfirm: false,
2416
- showLoaderOnDeny: false,
2417
- imageUrl: undefined,
2418
- imageWidth: undefined,
2419
- imageHeight: undefined,
2420
- imageAlt: '',
2421
- timer: undefined,
2422
- timerProgressBar: false,
2423
- width: undefined,
2424
- padding: undefined,
2425
- background: undefined,
2426
- input: undefined,
2427
- inputPlaceholder: '',
2428
- inputLabel: '',
2429
- inputValue: '',
2430
- inputOptions: {},
2431
- inputAutoFocus: true,
2432
- inputAutoTrim: true,
2433
- inputAttributes: {},
2434
- inputValidator: undefined,
2435
- returnInputValueOnDeny: false,
2436
- validationMessage: undefined,
2437
- grow: false,
2438
- position: 'center',
2439
- progressSteps: [],
2440
- currentProgressStep: undefined,
2441
- progressStepsDistance: undefined,
2442
- willOpen: undefined,
2443
- didOpen: undefined,
2444
- didRender: undefined,
2445
- willClose: undefined,
2446
- didClose: undefined,
2447
- didDestroy: undefined,
2448
- scrollbarPadding: true
2449
- };
2450
- 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'];
2451
- const deprecatedParams = {};
2452
- const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];
2453
-
2454
- /**
2455
- * Is valid parameter
2456
- *
2457
- * @param {string} paramName
2458
- * @returns {boolean}
2302
+ * @param {HTMLInputElement} input
2303
+ * @returns {FileList | File | null}
2459
2304
  */
2460
- const isValidParameter = paramName => {
2461
- return Object.prototype.hasOwnProperty.call(defaultParams, paramName);
2462
- };
2305
+ const getFileValue = input => input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;
2463
2306
 
2464
2307
  /**
2465
- * Is valid parameter for Swal.update() method
2466
- *
2467
- * @param {string} paramName
2468
- * @returns {boolean}
2308
+ * @param {SweetAlert} instance
2309
+ * @param {SweetAlertOptions} params
2469
2310
  */
2470
- const isUpdatableParameter = paramName => {
2471
- return updatableParams.indexOf(paramName) !== -1;
2311
+ const handleInputOptions = (instance, params) => {
2312
+ const popup = getPopup();
2313
+ /**
2314
+ * @param {Record<string, any>} inputOptions
2315
+ */
2316
+ const processInputOptions = inputOptions => {
2317
+ populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params);
2318
+ };
2319
+ if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
2320
+ showLoading(getConfirmButton());
2321
+ asPromise(params.inputOptions).then(inputOptions => {
2322
+ instance.hideLoading();
2323
+ processInputOptions(inputOptions);
2324
+ });
2325
+ } else if (typeof params.inputOptions === 'object') {
2326
+ processInputOptions(params.inputOptions);
2327
+ } else {
2328
+ error(`Unexpected type of inputOptions! Expected object, Map or Promise, got ${typeof params.inputOptions}`);
2329
+ }
2472
2330
  };
2473
2331
 
2474
2332
  /**
2475
- * Is deprecated parameter
2476
- *
2477
- * @param {string} paramName
2478
- * @returns {string | undefined}
2333
+ * @param {SweetAlert} instance
2334
+ * @param {SweetAlertOptions} params
2479
2335
  */
2480
- const isDeprecatedParameter = paramName => {
2481
- return deprecatedParams[paramName];
2336
+ const handleInputValue = (instance, params) => {
2337
+ const input = instance.getInput();
2338
+ hide(input);
2339
+ asPromise(params.inputValue).then(inputValue => {
2340
+ input.value = params.input === 'number' ? `${parseFloat(inputValue) || 0}` : `${inputValue}`;
2341
+ show(input);
2342
+ input.focus();
2343
+ instance.hideLoading();
2344
+ }).catch(err => {
2345
+ error(`Error in inputValue promise: ${err}`);
2346
+ input.value = '';
2347
+ show(input);
2348
+ input.focus();
2349
+ instance.hideLoading();
2350
+ });
2482
2351
  };
2483
-
2484
- /**
2485
- * @param {string} param
2486
- */
2487
- const checkIfParamIsValid = param => {
2488
- if (!isValidParameter(param)) {
2489
- warn(`Unknown parameter "${param}"`);
2352
+ const populateInputOptions = {
2353
+ /**
2354
+ * @param {HTMLElement} popup
2355
+ * @param {Record<string, any>} inputOptions
2356
+ * @param {SweetAlertOptions} params
2357
+ */
2358
+ select: (popup, inputOptions, params) => {
2359
+ const select = getDirectChildByClass(popup, swalClasses.select);
2360
+ /**
2361
+ * @param {HTMLElement} parent
2362
+ * @param {string} optionLabel
2363
+ * @param {string} optionValue
2364
+ */
2365
+ const renderOption = (parent, optionLabel, optionValue) => {
2366
+ const option = document.createElement('option');
2367
+ option.value = optionValue;
2368
+ setInnerHtml(option, optionLabel);
2369
+ option.selected = isSelected(optionValue, params.inputValue);
2370
+ parent.appendChild(option);
2371
+ };
2372
+ inputOptions.forEach(inputOption => {
2373
+ const optionValue = inputOption[0];
2374
+ const optionLabel = inputOption[1];
2375
+ // <optgroup> spec:
2376
+ // https://www.w3.org/TR/html401/interact/forms.html#h-17.6
2377
+ // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
2378
+ // check whether this is a <optgroup>
2379
+ if (Array.isArray(optionLabel)) {
2380
+ // if it is an array, then it is an <optgroup>
2381
+ const optgroup = document.createElement('optgroup');
2382
+ optgroup.label = optionValue;
2383
+ optgroup.disabled = false; // not configurable for now
2384
+ select.appendChild(optgroup);
2385
+ optionLabel.forEach(o => renderOption(optgroup, o[1], o[0]));
2386
+ } else {
2387
+ // case of <option>
2388
+ renderOption(select, optionLabel, optionValue);
2389
+ }
2390
+ });
2391
+ select.focus();
2392
+ },
2393
+ /**
2394
+ * @param {HTMLElement} popup
2395
+ * @param {Record<string, any>} inputOptions
2396
+ * @param {SweetAlertOptions} params
2397
+ */
2398
+ radio: (popup, inputOptions, params) => {
2399
+ const radio = getDirectChildByClass(popup, swalClasses.radio);
2400
+ inputOptions.forEach(inputOption => {
2401
+ const radioValue = inputOption[0];
2402
+ const radioLabel = inputOption[1];
2403
+ const radioInput = document.createElement('input');
2404
+ const radioLabelElement = document.createElement('label');
2405
+ radioInput.type = 'radio';
2406
+ radioInput.name = swalClasses.radio;
2407
+ radioInput.value = radioValue;
2408
+ if (isSelected(radioValue, params.inputValue)) {
2409
+ radioInput.checked = true;
2410
+ }
2411
+ const label = document.createElement('span');
2412
+ setInnerHtml(label, radioLabel);
2413
+ label.className = swalClasses.label;
2414
+ radioLabelElement.appendChild(radioInput);
2415
+ radioLabelElement.appendChild(label);
2416
+ radio.appendChild(radioLabelElement);
2417
+ });
2418
+ const radios = radio.querySelectorAll('input');
2419
+ if (radios.length) {
2420
+ radios[0].focus();
2421
+ }
2490
2422
  }
2491
2423
  };
2492
2424
 
2493
2425
  /**
2494
- * @param {string} param
2426
+ * Converts `inputOptions` into an array of `[value, label]`s
2427
+ *
2428
+ * @param {Record<string, any>} inputOptions
2429
+ * @returns {Array<Array<string>>}
2495
2430
  */
2496
- const checkIfToastParamIsValid = param => {
2497
- if (toastIncompatibleParams.includes(param)) {
2498
- warn(`The parameter "${param}" is incompatible with toasts`);
2499
- }
2500
- };
2501
-
2502
- /**
2503
- * @param {string} param
2504
- */
2505
- const checkIfParamIsDeprecated = param => {
2506
- if (isDeprecatedParameter(param)) {
2507
- warnAboutDeprecation(param, isDeprecatedParameter(param));
2431
+ const formatInputOptions = inputOptions => {
2432
+ const result = [];
2433
+ if (typeof Map !== 'undefined' && inputOptions instanceof Map) {
2434
+ inputOptions.forEach((value, key) => {
2435
+ let valueFormatted = value;
2436
+ if (typeof valueFormatted === 'object') {
2437
+ // case of <optgroup>
2438
+ valueFormatted = formatInputOptions(valueFormatted);
2439
+ }
2440
+ result.push([key, valueFormatted]);
2441
+ });
2442
+ } else {
2443
+ Object.keys(inputOptions).forEach(key => {
2444
+ let valueFormatted = inputOptions[key];
2445
+ if (typeof valueFormatted === 'object') {
2446
+ // case of <optgroup>
2447
+ valueFormatted = formatInputOptions(valueFormatted);
2448
+ }
2449
+ result.push([key, valueFormatted]);
2450
+ });
2508
2451
  }
2452
+ return result;
2509
2453
  };
2510
2454
 
2511
2455
  /**
2512
- * Show relevant warnings for given params
2513
- *
2514
- * @param {SweetAlertOptions} params
2456
+ * @param {string} optionValue
2457
+ * @param {InputValue | Promise<InputValue> | { toPromise: () => InputValue }} inputValue
2458
+ * @returns {boolean}
2515
2459
  */
2516
- const showWarningsForParams = params => {
2517
- if (params.backdrop === false && params.allowOutsideClick) {
2518
- warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
2519
- }
2520
- for (const param in params) {
2521
- checkIfParamIsValid(param);
2522
- if (params.toast) {
2523
- checkIfToastParamIsValid(param);
2524
- }
2525
- checkIfParamIsDeprecated(param);
2526
- }
2460
+ const isSelected = (optionValue, inputValue) => {
2461
+ return inputValue && inputValue.toString() === optionValue.toString();
2527
2462
  };
2528
2463
 
2529
2464
  /**
2530
- * Updates popup parameters.
2531
- *
2532
- * @param {SweetAlertOptions} params
2465
+ * @param {SweetAlert} instance
2533
2466
  */
2534
- function update(params) {
2535
- const popup = getPopup();
2536
- const innerParams = privateProps.innerParams.get(this);
2537
- if (!popup || hasClass(popup, innerParams.hideClass.popup)) {
2538
- 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.`);
2539
- return;
2467
+ const handleConfirmButtonClick = instance => {
2468
+ const innerParams = privateProps.innerParams.get(instance);
2469
+ instance.disableButtons();
2470
+ if (innerParams.input) {
2471
+ handleConfirmOrDenyWithInput(instance, 'confirm');
2472
+ } else {
2473
+ confirm(instance, true);
2540
2474
  }
2541
- const validUpdatableParams = filterValidParams(params);
2542
- const updatedParams = Object.assign({}, innerParams, validUpdatableParams);
2543
- render(this, updatedParams);
2544
- privateProps.innerParams.set(this, updatedParams);
2545
- Object.defineProperties(this, {
2546
- params: {
2547
- value: Object.assign({}, this.params, params),
2548
- writable: false,
2549
- enumerable: true
2550
- }
2551
- });
2552
- }
2553
-
2554
- /**
2555
- * @param {SweetAlertOptions} params
2556
- * @returns {SweetAlertOptions}
2557
- */
2558
- const filterValidParams = params => {
2559
- const validUpdatableParams = {};
2560
- Object.keys(params).forEach(param => {
2561
- if (isUpdatableParameter(param)) {
2562
- validUpdatableParams[param] = params[param];
2563
- } else {
2564
- warn(`Invalid parameter to update: ${param}`);
2565
- }
2566
- });
2567
- return validUpdatableParams;
2568
2475
  };
2569
2476
 
2570
2477
  /**
2571
- * Dispose the current SweetAlert2 instance
2478
+ * @param {SweetAlert} instance
2572
2479
  */
2573
- function _destroy() {
2574
- const domCache = privateProps.domCache.get(this);
2575
- const innerParams = privateProps.innerParams.get(this);
2576
- if (!innerParams) {
2577
- disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
2578
- return; // This instance has already been destroyed
2579
- }
2580
-
2581
- // Check if there is another Swal closing
2582
- if (domCache.popup && globalState.swalCloseEventFinishedCallback) {
2583
- globalState.swalCloseEventFinishedCallback();
2584
- delete globalState.swalCloseEventFinishedCallback;
2585
- }
2586
- if (typeof innerParams.didDestroy === 'function') {
2587
- innerParams.didDestroy();
2480
+ const handleDenyButtonClick = instance => {
2481
+ const innerParams = privateProps.innerParams.get(instance);
2482
+ instance.disableButtons();
2483
+ if (innerParams.returnInputValueOnDeny) {
2484
+ handleConfirmOrDenyWithInput(instance, 'deny');
2485
+ } else {
2486
+ deny(instance, false);
2588
2487
  }
2589
- disposeSwal(this);
2590
- }
2488
+ };
2591
2489
 
2592
2490
  /**
2593
- * @param {SweetAlert2} instance
2491
+ * @param {SweetAlert} instance
2492
+ * @param {Function} dismissWith
2594
2493
  */
2595
- const disposeSwal = instance => {
2596
- disposeWeakMaps(instance);
2597
- // Unset this.params so GC will dispose it (#1569)
2598
- // @ts-ignore
2599
- delete instance.params;
2600
- // Unset globalState props so GC will dispose globalState (#1569)
2601
- delete globalState.keydownHandler;
2602
- delete globalState.keydownTarget;
2603
- // Unset currentInstance
2604
- delete globalState.currentInstance;
2494
+ const handleCancelButtonClick = (instance, dismissWith) => {
2495
+ instance.disableButtons();
2496
+ dismissWith(DismissReason.cancel);
2605
2497
  };
2606
2498
 
2607
2499
  /**
2608
- * @param {SweetAlert2} instance
2500
+ * @param {SweetAlert} instance
2501
+ * @param {'confirm' | 'deny'} type
2609
2502
  */
2610
- const disposeWeakMaps = instance => {
2611
- // If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335
2612
- // @ts-ignore
2613
- if (instance.isAwaitingPromise()) {
2614
- unsetWeakMaps(privateProps, instance);
2615
- privateProps.awaitingPromise.set(instance, true);
2503
+ const handleConfirmOrDenyWithInput = (instance, type) => {
2504
+ const innerParams = privateProps.innerParams.get(instance);
2505
+ if (!innerParams.input) {
2506
+ error(`The "input" parameter is needed to be set when using returnInputValueOn${capitalizeFirstLetter(type)}`);
2507
+ return;
2508
+ }
2509
+ const inputValue = getInputValue(instance, innerParams);
2510
+ if (innerParams.inputValidator) {
2511
+ handleInputValidator(instance, inputValue, type);
2512
+ } else if (!instance.getInput().checkValidity()) {
2513
+ instance.enableButtons();
2514
+ instance.showValidationMessage(innerParams.validationMessage);
2515
+ } else if (type === 'deny') {
2516
+ deny(instance, inputValue);
2616
2517
  } else {
2617
- unsetWeakMaps(privateMethods, instance);
2618
- unsetWeakMaps(privateProps, instance);
2518
+ confirm(instance, inputValue);
2619
2519
  }
2620
2520
  };
2621
2521
 
2622
2522
  /**
2623
- * @param {object} obj
2624
- * @param {SweetAlert2} instance
2523
+ * @param {SweetAlert} instance
2524
+ * @param {string | number | File | FileList | null} inputValue
2525
+ * @param {'confirm' | 'deny'} type
2625
2526
  */
2626
- const unsetWeakMaps = (obj, instance) => {
2627
- for (const i in obj) {
2628
- obj[i].delete(instance);
2629
- }
2527
+ const handleInputValidator = (instance, inputValue, type) => {
2528
+ const innerParams = privateProps.innerParams.get(instance);
2529
+ instance.disableInput();
2530
+ const validationPromise = Promise.resolve().then(() => asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage)));
2531
+ validationPromise.then(validationMessage => {
2532
+ instance.enableButtons();
2533
+ instance.enableInput();
2534
+ if (validationMessage) {
2535
+ instance.showValidationMessage(validationMessage);
2536
+ } else if (type === 'deny') {
2537
+ deny(instance, inputValue);
2538
+ } else {
2539
+ confirm(instance, inputValue);
2540
+ }
2541
+ });
2630
2542
  };
2631
2543
 
2632
- var instanceMethods = /*#__PURE__*/Object.freeze({
2633
- __proto__: null,
2634
- _destroy: _destroy,
2635
- close: close,
2636
- closeModal: close,
2637
- closePopup: close,
2638
- closeToast: close,
2639
- disableButtons: disableButtons,
2640
- disableInput: disableInput,
2641
- disableLoading: hideLoading,
2642
- enableButtons: enableButtons,
2643
- enableInput: enableInput,
2644
- getInput: getInput,
2645
- handleAwaitingPromise: handleAwaitingPromise,
2646
- hideLoading: hideLoading,
2647
- isAwaitingPromise: isAwaitingPromise,
2648
- rejectPromise: rejectPromise,
2649
- resetValidationMessage: resetValidationMessage,
2650
- showValidationMessage: showValidationMessage,
2651
- update: update
2652
- });
2653
-
2654
2544
  /**
2655
- * Shows loader (spinner), this is useful with AJAX requests.
2656
- * By default the loader be shown instead of the "Confirm" button.
2657
- *
2658
- * @param {HTMLButtonElement} [buttonToReplace]
2545
+ * @param {SweetAlert} instance
2546
+ * @param {any} value
2659
2547
  */
2660
- const showLoading = buttonToReplace => {
2661
- let popup = getPopup();
2662
- if (!popup) {
2663
- new Swal(); // eslint-disable-line no-new
2548
+ const deny = (instance, value) => {
2549
+ const innerParams = privateProps.innerParams.get(instance || undefined);
2550
+ if (innerParams.showLoaderOnDeny) {
2551
+ showLoading(getDenyButton());
2664
2552
  }
2665
-
2666
- popup = getPopup();
2667
- const loader = getLoader();
2668
- if (isToast()) {
2669
- hide(getIcon());
2553
+ if (innerParams.preDeny) {
2554
+ instance.isAwaitingPromise = true; // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preDeny's promise is received
2555
+ const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage)));
2556
+ preDenyPromise.then(preDenyValue => {
2557
+ if (preDenyValue === false) {
2558
+ instance.hideLoading();
2559
+ handleAwaitingPromise(instance);
2560
+ } else {
2561
+ instance.close({
2562
+ isDenied: true,
2563
+ value: typeof preDenyValue === 'undefined' ? value : preDenyValue
2564
+ });
2565
+ }
2566
+ }).catch(error => rejectWith(instance || undefined, error));
2670
2567
  } else {
2671
- replaceButton(popup, buttonToReplace);
2568
+ instance.close({
2569
+ isDenied: true,
2570
+ value
2571
+ });
2672
2572
  }
2673
- show(loader);
2674
- popup.setAttribute('data-loading', 'true');
2675
- popup.setAttribute('aria-busy', 'true');
2676
- popup.focus();
2677
2573
  };
2678
2574
 
2679
2575
  /**
2680
- * @param {HTMLElement} popup
2681
- * @param {HTMLButtonElement} [buttonToReplace]
2576
+ * @param {SweetAlert} instance
2577
+ * @param {any} value
2682
2578
  */
2683
- const replaceButton = (popup, buttonToReplace) => {
2684
- const actions = getActions();
2685
- const loader = getLoader();
2686
- if (!buttonToReplace && isVisible$1(getConfirmButton())) {
2687
- buttonToReplace = getConfirmButton();
2688
- }
2689
- show(actions);
2690
- if (buttonToReplace) {
2691
- hide(buttonToReplace);
2692
- loader.setAttribute('data-button-to-replace', buttonToReplace.className);
2693
- }
2694
- loader.parentNode.insertBefore(loader, buttonToReplace);
2695
- addClass([popup, actions], swalClasses.loading);
2579
+ const succeedWith = (instance, value) => {
2580
+ instance.close({
2581
+ isConfirmed: true,
2582
+ value
2583
+ });
2696
2584
  };
2697
2585
 
2698
2586
  /**
2699
- * @typedef { string | number | boolean } InputValue
2587
+ *
2588
+ * @param {SweetAlert} instance
2589
+ * @param {string} error
2700
2590
  */
2591
+ const rejectWith = (instance, error) => {
2592
+ instance.rejectPromise(error);
2593
+ };
2701
2594
 
2702
2595
  /**
2703
- * @param {SweetAlert2} instance
2704
- * @param {SweetAlertOptions} params
2596
+ *
2597
+ * @param {SweetAlert} instance
2598
+ * @param {any} value
2705
2599
  */
2706
- const handleInputOptionsAndValue = (instance, params) => {
2707
- if (params.input === 'select' || params.input === 'radio') {
2708
- handleInputOptions(instance, params);
2709
- } else if (['text', 'email', 'number', 'tel', 'textarea'].includes(params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {
2710
- showLoading(getConfirmButton());
2711
- handleInputValue(instance, params);
2600
+ const confirm = (instance, value) => {
2601
+ const innerParams = privateProps.innerParams.get(instance || undefined);
2602
+ if (innerParams.showLoaderOnConfirm) {
2603
+ showLoading();
2604
+ }
2605
+ if (innerParams.preConfirm) {
2606
+ instance.resetValidationMessage();
2607
+ instance.isAwaitingPromise = true; // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preConfirm's promise is received
2608
+ const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
2609
+ preConfirmPromise.then(preConfirmValue => {
2610
+ if (isVisible$1(getValidationMessage()) || preConfirmValue === false) {
2611
+ instance.hideLoading();
2612
+ handleAwaitingPromise(instance);
2613
+ } else {
2614
+ succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);
2615
+ }
2616
+ }).catch(error => rejectWith(instance || undefined, error));
2617
+ } else {
2618
+ succeedWith(instance, value);
2712
2619
  }
2713
2620
  };
2714
2621
 
2715
2622
  /**
2716
- * @param {SweetAlert2} instance
2717
- * @param {SweetAlertOptions} innerParams
2718
- * @returns {string | number | File | FileList | null}
2623
+ * Hides loader and shows back the button which was hidden by .showLoading()
2719
2624
  */
2720
- const getInputValue = (instance, innerParams) => {
2721
- const input = instance.getInput();
2722
- if (!input) {
2723
- return null;
2625
+ function hideLoading() {
2626
+ // do nothing if popup is closed
2627
+ const innerParams = privateProps.innerParams.get(this);
2628
+ if (!innerParams) {
2629
+ return;
2724
2630
  }
2725
- switch (innerParams.input) {
2726
- case 'checkbox':
2727
- return getCheckboxValue(input);
2728
- case 'radio':
2729
- return getRadioValue(input);
2730
- case 'file':
2731
- return getFileValue(input);
2732
- default:
2733
- return innerParams.inputAutoTrim ? input.value.trim() : input.value;
2631
+ const domCache = privateProps.domCache.get(this);
2632
+ hide(domCache.loader);
2633
+ if (isToast()) {
2634
+ if (innerParams.icon) {
2635
+ show(getIcon());
2636
+ }
2637
+ } else {
2638
+ showRelatedButton(domCache);
2639
+ }
2640
+ removeClass([domCache.popup, domCache.actions], swalClasses.loading);
2641
+ domCache.popup.removeAttribute('aria-busy');
2642
+ domCache.popup.removeAttribute('data-loading');
2643
+ domCache.confirmButton.disabled = false;
2644
+ domCache.denyButton.disabled = false;
2645
+ domCache.cancelButton.disabled = false;
2646
+ }
2647
+ const showRelatedButton = domCache => {
2648
+ const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'));
2649
+ if (buttonToReplace.length) {
2650
+ show(buttonToReplace[0], 'inline-block');
2651
+ } else if (allButtonsAreHidden()) {
2652
+ hide(domCache.actions);
2734
2653
  }
2735
2654
  };
2736
2655
 
2737
2656
  /**
2738
- * @param {HTMLInputElement} input
2739
- * @returns {number}
2657
+ * Gets the input DOM node, this method works with input parameter.
2658
+ *
2659
+ * @returns {HTMLInputElement | null}
2740
2660
  */
2741
- const getCheckboxValue = input => input.checked ? 1 : 0;
2661
+ function getInput() {
2662
+ const innerParams = privateProps.innerParams.get(this);
2663
+ const domCache = privateProps.domCache.get(this);
2664
+ if (!domCache) {
2665
+ return null;
2666
+ }
2667
+ return getInput$1(domCache.popup, innerParams.input);
2668
+ }
2742
2669
 
2743
2670
  /**
2744
- * @param {HTMLInputElement} input
2745
- * @returns {string | null}
2671
+ * @param {SweetAlert} instance
2672
+ * @param {string[]} buttons
2673
+ * @param {boolean} disabled
2746
2674
  */
2747
- const getRadioValue = input => input.checked ? input.value : null;
2675
+ function setButtonsDisabled(instance, buttons, disabled) {
2676
+ const domCache = privateProps.domCache.get(instance);
2677
+ buttons.forEach(button => {
2678
+ domCache[button].disabled = disabled;
2679
+ });
2680
+ }
2748
2681
 
2749
2682
  /**
2750
2683
  * @param {HTMLInputElement} input
2751
- * @returns {FileList | File | null}
2684
+ * @param {boolean} disabled
2752
2685
  */
2753
- const getFileValue = input => input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;
2686
+ function setInputDisabled(input, disabled) {
2687
+ if (!input) {
2688
+ return;
2689
+ }
2690
+ if (input.type === 'radio') {
2691
+ const radiosContainer = input.parentNode.parentNode;
2692
+ const radios = radiosContainer.querySelectorAll('input');
2693
+ for (let i = 0; i < radios.length; i++) {
2694
+ radios[i].disabled = disabled;
2695
+ }
2696
+ } else {
2697
+ input.disabled = disabled;
2698
+ }
2699
+ }
2754
2700
 
2755
2701
  /**
2756
- * @param {SweetAlert2} instance
2757
- * @param {SweetAlertOptions} params
2702
+ * Enable all the buttons
2758
2703
  */
2759
- const handleInputOptions = (instance, params) => {
2760
- const popup = getPopup();
2761
- /**
2762
- * @param {Record<string, any>} inputOptions
2763
- */
2764
- const processInputOptions = inputOptions => {
2765
- populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params);
2766
- };
2767
- if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
2768
- showLoading(getConfirmButton());
2769
- asPromise(params.inputOptions).then(inputOptions => {
2770
- instance.hideLoading();
2771
- processInputOptions(inputOptions);
2772
- });
2773
- } else if (typeof params.inputOptions === 'object') {
2774
- processInputOptions(params.inputOptions);
2775
- } else {
2776
- error(`Unexpected type of inputOptions! Expected object, Map or Promise, got ${typeof params.inputOptions}`);
2777
- }
2778
- };
2704
+ function enableButtons() {
2705
+ setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
2706
+ }
2779
2707
 
2780
2708
  /**
2781
- * @param {SweetAlert2} instance
2782
- * @param {SweetAlertOptions} params
2709
+ * Disable all the buttons
2783
2710
  */
2784
- const handleInputValue = (instance, params) => {
2785
- const input = instance.getInput();
2786
- hide(input);
2787
- asPromise(params.inputValue).then(inputValue => {
2788
- input.value = params.input === 'number' ? `${parseFloat(inputValue) || 0}` : `${inputValue}`;
2789
- show(input);
2790
- input.focus();
2791
- instance.hideLoading();
2792
- }).catch(err => {
2793
- error(`Error in inputValue promise: ${err}`);
2794
- input.value = '';
2795
- show(input);
2796
- input.focus();
2797
- instance.hideLoading();
2798
- });
2799
- };
2800
- const populateInputOptions = {
2801
- /**
2802
- * @param {HTMLElement} popup
2803
- * @param {Record<string, any>} inputOptions
2804
- * @param {SweetAlertOptions} params
2805
- */
2806
- select: (popup, inputOptions, params) => {
2807
- const select = getDirectChildByClass(popup, swalClasses.select);
2808
- /**
2809
- * @param {HTMLElement} parent
2810
- * @param {string} optionLabel
2811
- * @param {string} optionValue
2812
- */
2813
- const renderOption = (parent, optionLabel, optionValue) => {
2814
- const option = document.createElement('option');
2815
- option.value = optionValue;
2816
- setInnerHtml(option, optionLabel);
2817
- option.selected = isSelected(optionValue, params.inputValue);
2818
- parent.appendChild(option);
2819
- };
2820
- inputOptions.forEach(inputOption => {
2821
- const optionValue = inputOption[0];
2822
- const optionLabel = inputOption[1];
2823
- // <optgroup> spec:
2824
- // https://www.w3.org/TR/html401/interact/forms.html#h-17.6
2825
- // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
2826
- // check whether this is a <optgroup>
2827
- if (Array.isArray(optionLabel)) {
2828
- // if it is an array, then it is an <optgroup>
2829
- const optgroup = document.createElement('optgroup');
2830
- optgroup.label = optionValue;
2831
- optgroup.disabled = false; // not configurable for now
2832
- select.appendChild(optgroup);
2833
- optionLabel.forEach(o => renderOption(optgroup, o[1], o[0]));
2834
- } else {
2835
- // case of <option>
2836
- renderOption(select, optionLabel, optionValue);
2837
- }
2838
- });
2839
- select.focus();
2840
- },
2841
- /**
2842
- * @param {HTMLElement} popup
2843
- * @param {Record<string, any>} inputOptions
2844
- * @param {SweetAlertOptions} params
2845
- */
2846
- radio: (popup, inputOptions, params) => {
2847
- const radio = getDirectChildByClass(popup, swalClasses.radio);
2848
- inputOptions.forEach(inputOption => {
2849
- const radioValue = inputOption[0];
2850
- const radioLabel = inputOption[1];
2851
- const radioInput = document.createElement('input');
2852
- const radioLabelElement = document.createElement('label');
2853
- radioInput.type = 'radio';
2854
- radioInput.name = swalClasses.radio;
2855
- radioInput.value = radioValue;
2856
- if (isSelected(radioValue, params.inputValue)) {
2857
- radioInput.checked = true;
2858
- }
2859
- const label = document.createElement('span');
2860
- setInnerHtml(label, radioLabel);
2861
- label.className = swalClasses.label;
2862
- radioLabelElement.appendChild(radioInput);
2863
- radioLabelElement.appendChild(label);
2864
- radio.appendChild(radioLabelElement);
2865
- });
2866
- const radios = radio.querySelectorAll('input');
2867
- if (radios.length) {
2868
- radios[0].focus();
2869
- }
2870
- }
2871
- };
2711
+ function disableButtons() {
2712
+ setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
2713
+ }
2872
2714
 
2873
2715
  /**
2874
- * Converts `inputOptions` into an array of `[value, label]`s
2716
+ * Enable the input field
2717
+ */
2718
+ function enableInput() {
2719
+ setInputDisabled(this.getInput(), false);
2720
+ }
2721
+
2722
+ /**
2723
+ * Disable the input field
2724
+ */
2725
+ function disableInput() {
2726
+ setInputDisabled(this.getInput(), true);
2727
+ }
2728
+
2729
+ /**
2730
+ * Show block with validation message
2875
2731
  *
2876
- * @param {Record<string, any>} inputOptions
2877
- * @returns {Array<Array<string>>}
2732
+ * @param {string} error
2878
2733
  */
2879
- const formatInputOptions = inputOptions => {
2880
- const result = [];
2881
- if (typeof Map !== 'undefined' && inputOptions instanceof Map) {
2882
- inputOptions.forEach((value, key) => {
2883
- let valueFormatted = value;
2884
- if (typeof valueFormatted === 'object') {
2885
- // case of <optgroup>
2886
- valueFormatted = formatInputOptions(valueFormatted);
2887
- }
2888
- result.push([key, valueFormatted]);
2889
- });
2890
- } else {
2891
- Object.keys(inputOptions).forEach(key => {
2892
- let valueFormatted = inputOptions[key];
2893
- if (typeof valueFormatted === 'object') {
2894
- // case of <optgroup>
2895
- valueFormatted = formatInputOptions(valueFormatted);
2896
- }
2897
- result.push([key, valueFormatted]);
2898
- });
2734
+ function showValidationMessage(error) {
2735
+ const domCache = privateProps.domCache.get(this);
2736
+ const params = privateProps.innerParams.get(this);
2737
+ setInnerHtml(domCache.validationMessage, error);
2738
+ domCache.validationMessage.className = swalClasses['validation-message'];
2739
+ if (params.customClass && params.customClass.validationMessage) {
2740
+ addClass(domCache.validationMessage, params.customClass.validationMessage);
2899
2741
  }
2900
- return result;
2742
+ show(domCache.validationMessage);
2743
+ const input = this.getInput();
2744
+ if (input) {
2745
+ input.setAttribute('aria-invalid', true);
2746
+ input.setAttribute('aria-describedby', swalClasses['validation-message']);
2747
+ focusInput(input);
2748
+ addClass(input, swalClasses.inputerror);
2749
+ }
2750
+ }
2751
+
2752
+ /**
2753
+ * Hide block with validation message
2754
+ */
2755
+ function resetValidationMessage() {
2756
+ const domCache = privateProps.domCache.get(this);
2757
+ if (domCache.validationMessage) {
2758
+ hide(domCache.validationMessage);
2759
+ }
2760
+ const input = this.getInput();
2761
+ if (input) {
2762
+ input.removeAttribute('aria-invalid');
2763
+ input.removeAttribute('aria-describedby');
2764
+ removeClass(input, swalClasses.inputerror);
2765
+ }
2766
+ }
2767
+
2768
+ const defaultParams = {
2769
+ title: '',
2770
+ titleText: '',
2771
+ text: '',
2772
+ html: '',
2773
+ footer: '',
2774
+ icon: undefined,
2775
+ iconColor: undefined,
2776
+ iconHtml: undefined,
2777
+ template: undefined,
2778
+ toast: false,
2779
+ showClass: {
2780
+ popup: 'swal2-show',
2781
+ backdrop: 'swal2-backdrop-show',
2782
+ icon: 'swal2-icon-show'
2783
+ },
2784
+ hideClass: {
2785
+ popup: 'swal2-hide',
2786
+ backdrop: 'swal2-backdrop-hide',
2787
+ icon: 'swal2-icon-hide'
2788
+ },
2789
+ customClass: {},
2790
+ target: 'body',
2791
+ color: undefined,
2792
+ backdrop: true,
2793
+ heightAuto: true,
2794
+ allowOutsideClick: true,
2795
+ allowEscapeKey: true,
2796
+ allowEnterKey: true,
2797
+ stopKeydownPropagation: true,
2798
+ keydownListenerCapture: false,
2799
+ showConfirmButton: true,
2800
+ showDenyButton: false,
2801
+ showCancelButton: false,
2802
+ preConfirm: undefined,
2803
+ preDeny: undefined,
2804
+ confirmButtonText: 'OK',
2805
+ confirmButtonAriaLabel: '',
2806
+ confirmButtonColor: undefined,
2807
+ denyButtonText: 'No',
2808
+ denyButtonAriaLabel: '',
2809
+ denyButtonColor: undefined,
2810
+ cancelButtonText: 'Cancel',
2811
+ cancelButtonAriaLabel: '',
2812
+ cancelButtonColor: undefined,
2813
+ buttonsStyling: true,
2814
+ reverseButtons: false,
2815
+ focusConfirm: true,
2816
+ focusDeny: false,
2817
+ focusCancel: false,
2818
+ returnFocus: true,
2819
+ showCloseButton: false,
2820
+ closeButtonHtml: '&times;',
2821
+ closeButtonAriaLabel: 'Close this dialog',
2822
+ loaderHtml: '',
2823
+ showLoaderOnConfirm: false,
2824
+ showLoaderOnDeny: false,
2825
+ imageUrl: undefined,
2826
+ imageWidth: undefined,
2827
+ imageHeight: undefined,
2828
+ imageAlt: '',
2829
+ timer: undefined,
2830
+ timerProgressBar: false,
2831
+ width: undefined,
2832
+ padding: undefined,
2833
+ background: undefined,
2834
+ input: undefined,
2835
+ inputPlaceholder: '',
2836
+ inputLabel: '',
2837
+ inputValue: '',
2838
+ inputOptions: {},
2839
+ inputAutoFocus: true,
2840
+ inputAutoTrim: true,
2841
+ inputAttributes: {},
2842
+ inputValidator: undefined,
2843
+ returnInputValueOnDeny: false,
2844
+ validationMessage: undefined,
2845
+ grow: false,
2846
+ position: 'center',
2847
+ progressSteps: [],
2848
+ currentProgressStep: undefined,
2849
+ progressStepsDistance: undefined,
2850
+ willOpen: undefined,
2851
+ didOpen: undefined,
2852
+ didRender: undefined,
2853
+ willClose: undefined,
2854
+ didClose: undefined,
2855
+ didDestroy: undefined,
2856
+ scrollbarPadding: true
2857
+ };
2858
+ 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'];
2859
+ const deprecatedParams = {};
2860
+ const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture'];
2861
+
2862
+ /**
2863
+ * Is valid parameter
2864
+ *
2865
+ * @param {string} paramName
2866
+ * @returns {boolean}
2867
+ */
2868
+ const isValidParameter = paramName => {
2869
+ return Object.prototype.hasOwnProperty.call(defaultParams, paramName);
2901
2870
  };
2902
2871
 
2903
2872
  /**
2904
- * @param {string} optionValue
2905
- * @param {InputValue | Promise<InputValue> | { toPromise: () => InputValue }} inputValue
2873
+ * Is valid parameter for Swal.update() method
2874
+ *
2875
+ * @param {string} paramName
2906
2876
  * @returns {boolean}
2907
2877
  */
2908
- const isSelected = (optionValue, inputValue) => {
2909
- return inputValue && inputValue.toString() === optionValue.toString();
2878
+ const isUpdatableParameter = paramName => {
2879
+ return updatableParams.indexOf(paramName) !== -1;
2910
2880
  };
2911
2881
 
2912
2882
  /**
2913
- * @param {SweetAlert2} instance
2883
+ * Is deprecated parameter
2884
+ *
2885
+ * @param {string} paramName
2886
+ * @returns {string | undefined}
2914
2887
  */
2915
- const handleConfirmButtonClick = instance => {
2916
- const innerParams = privateProps.innerParams.get(instance);
2917
- instance.disableButtons();
2918
- if (innerParams.input) {
2919
- handleConfirmOrDenyWithInput(instance, 'confirm');
2920
- } else {
2921
- confirm(instance, true);
2888
+ const isDeprecatedParameter = paramName => {
2889
+ return deprecatedParams[paramName];
2890
+ };
2891
+
2892
+ /**
2893
+ * @param {string} param
2894
+ */
2895
+ const checkIfParamIsValid = param => {
2896
+ if (!isValidParameter(param)) {
2897
+ warn(`Unknown parameter "${param}"`);
2922
2898
  }
2923
2899
  };
2924
2900
 
2925
2901
  /**
2926
- * @param {SweetAlert2} instance
2902
+ * @param {string} param
2927
2903
  */
2928
- const handleDenyButtonClick = instance => {
2929
- const innerParams = privateProps.innerParams.get(instance);
2930
- instance.disableButtons();
2931
- if (innerParams.returnInputValueOnDeny) {
2932
- handleConfirmOrDenyWithInput(instance, 'deny');
2933
- } else {
2934
- deny(instance, false);
2904
+ const checkIfToastParamIsValid = param => {
2905
+ if (toastIncompatibleParams.includes(param)) {
2906
+ warn(`The parameter "${param}" is incompatible with toasts`);
2935
2907
  }
2936
2908
  };
2937
2909
 
2938
2910
  /**
2939
- * @param {SweetAlert2} instance
2940
- * @param {Function} dismissWith
2911
+ * @param {string} param
2941
2912
  */
2942
- const handleCancelButtonClick = (instance, dismissWith) => {
2943
- instance.disableButtons();
2944
- dismissWith(DismissReason.cancel);
2913
+ const checkIfParamIsDeprecated = param => {
2914
+ if (isDeprecatedParameter(param)) {
2915
+ warnAboutDeprecation(param, isDeprecatedParameter(param));
2916
+ }
2945
2917
  };
2946
2918
 
2947
2919
  /**
2948
- * @param {SweetAlert2} instance
2949
- * @param {'confirm' | 'deny'} type
2920
+ * Show relevant warnings for given params
2921
+ *
2922
+ * @param {SweetAlertOptions} params
2950
2923
  */
2951
- const handleConfirmOrDenyWithInput = (instance, type) => {
2952
- const innerParams = privateProps.innerParams.get(instance);
2953
- if (!innerParams.input) {
2954
- error(`The "input" parameter is needed to be set when using returnInputValueOn${capitalizeFirstLetter(type)}`);
2955
- return;
2924
+ const showWarningsForParams = params => {
2925
+ if (params.backdrop === false && params.allowOutsideClick) {
2926
+ warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');
2956
2927
  }
2957
- const inputValue = getInputValue(instance, innerParams);
2958
- if (innerParams.inputValidator) {
2959
- handleInputValidator(instance, inputValue, type);
2960
- } else if (!instance.getInput().checkValidity()) {
2961
- instance.enableButtons();
2962
- instance.showValidationMessage(innerParams.validationMessage);
2963
- } else if (type === 'deny') {
2964
- deny(instance, inputValue);
2965
- } else {
2966
- confirm(instance, inputValue);
2928
+ for (const param in params) {
2929
+ checkIfParamIsValid(param);
2930
+ if (params.toast) {
2931
+ checkIfToastParamIsValid(param);
2932
+ }
2933
+ checkIfParamIsDeprecated(param);
2967
2934
  }
2968
2935
  };
2969
2936
 
2970
2937
  /**
2971
- * @param {SweetAlert2} instance
2972
- * @param {string | number | File | FileList | null} inputValue
2973
- * @param {'confirm' | 'deny'} type
2938
+ * Updates popup parameters.
2939
+ *
2940
+ * @param {SweetAlertOptions} params
2974
2941
  */
2975
- const handleInputValidator = (instance, inputValue, type) => {
2976
- const innerParams = privateProps.innerParams.get(instance);
2977
- instance.disableInput();
2978
- const validationPromise = Promise.resolve().then(() => asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage)));
2979
- validationPromise.then(validationMessage => {
2980
- instance.enableButtons();
2981
- instance.enableInput();
2982
- if (validationMessage) {
2983
- instance.showValidationMessage(validationMessage);
2984
- } else if (type === 'deny') {
2985
- deny(instance, inputValue);
2942
+ function update(params) {
2943
+ const popup = getPopup();
2944
+ const innerParams = privateProps.innerParams.get(this);
2945
+ if (!popup || hasClass(popup, innerParams.hideClass.popup)) {
2946
+ 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.`);
2947
+ return;
2948
+ }
2949
+ const validUpdatableParams = filterValidParams(params);
2950
+ const updatedParams = Object.assign({}, innerParams, validUpdatableParams);
2951
+ render(this, updatedParams);
2952
+ privateProps.innerParams.set(this, updatedParams);
2953
+ Object.defineProperties(this, {
2954
+ params: {
2955
+ value: Object.assign({}, this.params, params),
2956
+ writable: false,
2957
+ enumerable: true
2958
+ }
2959
+ });
2960
+ }
2961
+
2962
+ /**
2963
+ * @param {SweetAlertOptions} params
2964
+ * @returns {SweetAlertOptions}
2965
+ */
2966
+ const filterValidParams = params => {
2967
+ const validUpdatableParams = {};
2968
+ Object.keys(params).forEach(param => {
2969
+ if (isUpdatableParameter(param)) {
2970
+ validUpdatableParams[param] = params[param];
2986
2971
  } else {
2987
- confirm(instance, inputValue);
2972
+ warn(`Invalid parameter to update: ${param}`);
2988
2973
  }
2989
2974
  });
2975
+ return validUpdatableParams;
2990
2976
  };
2991
2977
 
2992
2978
  /**
2993
- * @param {SweetAlert2} instance
2994
- * @param {any} value
2979
+ * Dispose the current SweetAlert2 instance
2995
2980
  */
2996
- const deny = (instance, value) => {
2997
- const innerParams = privateProps.innerParams.get(instance || undefined);
2998
- if (innerParams.showLoaderOnDeny) {
2999
- showLoading(getDenyButton());
2981
+ function _destroy() {
2982
+ const domCache = privateProps.domCache.get(this);
2983
+ const innerParams = privateProps.innerParams.get(this);
2984
+ if (!innerParams) {
2985
+ disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
2986
+ return; // This instance has already been destroyed
3000
2987
  }
3001
- if (innerParams.preDeny) {
3002
- 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
3003
- const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage)));
3004
- preDenyPromise.then(preDenyValue => {
3005
- if (preDenyValue === false) {
3006
- instance.hideLoading();
3007
- handleAwaitingPromise(instance);
3008
- } else {
3009
- instance.close({
3010
- isDenied: true,
3011
- value: typeof preDenyValue === 'undefined' ? value : preDenyValue
3012
- });
3013
- }
3014
- }).catch(error => rejectWith(instance || undefined, error));
3015
- } else {
3016
- instance.close({
3017
- isDenied: true,
3018
- value
3019
- });
2988
+
2989
+ // Check if there is another Swal closing
2990
+ if (domCache.popup && globalState.swalCloseEventFinishedCallback) {
2991
+ globalState.swalCloseEventFinishedCallback();
2992
+ delete globalState.swalCloseEventFinishedCallback;
3020
2993
  }
3021
- };
2994
+ if (typeof innerParams.didDestroy === 'function') {
2995
+ innerParams.didDestroy();
2996
+ }
2997
+ disposeSwal(this);
2998
+ }
3022
2999
 
3023
3000
  /**
3024
- * @param {SweetAlert2} instance
3025
- * @param {any} value
3001
+ * @param {SweetAlert} instance
3026
3002
  */
3027
- const succeedWith = (instance, value) => {
3028
- instance.close({
3029
- isConfirmed: true,
3030
- value
3031
- });
3003
+ const disposeSwal = instance => {
3004
+ disposeWeakMaps(instance);
3005
+ // Unset this.params so GC will dispose it (#1569)
3006
+ // @ts-ignore
3007
+ delete instance.params;
3008
+ // Unset globalState props so GC will dispose globalState (#1569)
3009
+ delete globalState.keydownHandler;
3010
+ delete globalState.keydownTarget;
3011
+ // Unset currentInstance
3012
+ delete globalState.currentInstance;
3032
3013
  };
3033
3014
 
3034
3015
  /**
3035
- *
3036
- * @param {SweetAlert2} instance
3037
- * @param {string} error
3016
+ * @param {SweetAlert} instance
3038
3017
  */
3039
- const rejectWith = (instance, error) => {
3040
- // @ts-ignore
3041
- instance.rejectPromise(error);
3018
+ const disposeWeakMaps = instance => {
3019
+ // If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335
3020
+ if (instance.isAwaitingPromise) {
3021
+ unsetWeakMaps(privateProps, instance);
3022
+ instance.isAwaitingPromise = true;
3023
+ } else {
3024
+ unsetWeakMaps(privateMethods, instance);
3025
+ unsetWeakMaps(privateProps, instance);
3026
+ delete instance.isAwaitingPromise;
3027
+ // Unset instance methods
3028
+ delete instance.disableButtons;
3029
+ delete instance.enableButtons;
3030
+ delete instance.getInput;
3031
+ delete instance.disableInput;
3032
+ delete instance.enableInput;
3033
+ delete instance.hideLoading;
3034
+ delete instance.disableLoading;
3035
+ delete instance.showValidationMessage;
3036
+ delete instance.resetValidationMessage;
3037
+ delete instance.close;
3038
+ delete instance.closePopup;
3039
+ delete instance.closeModal;
3040
+ delete instance.closeToast;
3041
+ delete instance.rejectPromise;
3042
+ delete instance.update;
3043
+ delete instance._destroy;
3044
+ }
3042
3045
  };
3043
3046
 
3044
3047
  /**
3045
- *
3046
- * @param {SweetAlert2} instance
3047
- * @param {any} value
3048
+ * @param {object} obj
3049
+ * @param {SweetAlert} instance
3048
3050
  */
3049
- const confirm = (instance, value) => {
3050
- const innerParams = privateProps.innerParams.get(instance || undefined);
3051
- if (innerParams.showLoaderOnConfirm) {
3052
- showLoading();
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
3057
- const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
3058
- preConfirmPromise.then(preConfirmValue => {
3059
- if (isVisible$1(getValidationMessage()) || preConfirmValue === false) {
3060
- instance.hideLoading();
3061
- handleAwaitingPromise(instance);
3062
- } else {
3063
- succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue);
3064
- }
3065
- }).catch(error => rejectWith(instance || undefined, error));
3066
- } else {
3067
- succeedWith(instance, value);
3051
+ const unsetWeakMaps = (obj, instance) => {
3052
+ for (const i in obj) {
3053
+ obj[i].delete(instance);
3068
3054
  }
3069
3055
  };
3070
3056
 
3057
+ var instanceMethods = /*#__PURE__*/Object.freeze({
3058
+ __proto__: null,
3059
+ _destroy: _destroy,
3060
+ close: close,
3061
+ closeModal: close,
3062
+ closePopup: close,
3063
+ closeToast: close,
3064
+ disableButtons: disableButtons,
3065
+ disableInput: disableInput,
3066
+ disableLoading: hideLoading,
3067
+ enableButtons: enableButtons,
3068
+ enableInput: enableInput,
3069
+ getInput: getInput,
3070
+ handleAwaitingPromise: handleAwaitingPromise,
3071
+ hideLoading: hideLoading,
3072
+ rejectPromise: rejectPromise,
3073
+ resetValidationMessage: resetValidationMessage,
3074
+ showValidationMessage: showValidationMessage,
3075
+ update: update
3076
+ });
3077
+
3071
3078
  const handlePopupClick = (instance, domCache, dismissWith) => {
3072
3079
  const innerParams = privateProps.innerParams.get(instance);
3073
3080
  if (innerParams.toast) {
@@ -3187,7 +3194,7 @@
3187
3194
  * const {value: lastName} = await TextPrompt('What is your last name?')
3188
3195
  *
3189
3196
  * @param {SweetAlertOptions} mixinParams
3190
- * @returns {SweetAlert2}
3197
+ * @returns {SweetAlert}
3191
3198
  */
3192
3199
  function mixin(mixinParams) {
3193
3200
  class MixinSwal extends this {
@@ -3771,8 +3778,13 @@
3771
3778
  init(params);
3772
3779
  }
3773
3780
 
3781
+ /** @type {SweetAlert} */
3774
3782
  let currentInstance;
3775
3783
  class SweetAlert {
3784
+ /**
3785
+ * @param {...any} args
3786
+ * @this {SweetAlert}
3787
+ */
3776
3788
  constructor() {
3777
3789
  // Prevent run in Node env
3778
3790
  if (typeof window === 'undefined') {
@@ -3794,6 +3806,9 @@
3794
3806
  }
3795
3807
  });
3796
3808
 
3809
+ /** @type {boolean} */
3810
+ this.isAwaitingPromise = false;
3811
+
3797
3812
  // @ts-ignore
3798
3813
  const promise = currentInstance._main(currentInstance.params);
3799
3814
  privateProps.promise.set(this, promise);
@@ -3802,7 +3817,6 @@
3802
3817
  let mixinParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3803
3818
  showWarningsForParams(Object.assign({}, mixinParams, userParams));
3804
3819
  if (globalState.currentInstance) {
3805
- // @ts-ignore
3806
3820
  globalState.currentInstance._destroy();
3807
3821
  if (isModal()) {
3808
3822
  unsetAriaHidden();
@@ -3839,7 +3853,7 @@
3839
3853
  }
3840
3854
 
3841
3855
  /**
3842
- * @param {SweetAlert2} instance
3856
+ * @param {SweetAlert} instance
3843
3857
  * @param {DomCache} domCache
3844
3858
  * @param {SweetAlertOptions} innerParams
3845
3859
  * @returns {Promise}
@@ -3851,7 +3865,6 @@
3851
3865
  * @param {DismissReason} dismiss
3852
3866
  */
3853
3867
  const dismissWith = dismiss => {
3854
- // @ts-ignore
3855
3868
  instance.close({
3856
3869
  isDismissed: true,
3857
3870
  dismiss
@@ -3900,7 +3913,7 @@
3900
3913
  };
3901
3914
 
3902
3915
  /**
3903
- * @param {SweetAlert2} instance
3916
+ * @param {SweetAlert} instance
3904
3917
  * @returns {DomCache}
3905
3918
  */
3906
3919
  const populateDomCache = instance => {
@@ -4012,7 +4025,22 @@
4012
4025
  }
4013
4026
 
4014
4027
  // Assign instance methods from src/instanceMethods/*.js to prototype
4015
- Object.assign(SweetAlert.prototype, instanceMethods);
4028
+ SweetAlert.prototype.disableButtons = disableButtons;
4029
+ SweetAlert.prototype.enableButtons = enableButtons;
4030
+ SweetAlert.prototype.getInput = getInput;
4031
+ SweetAlert.prototype.disableInput = disableInput;
4032
+ SweetAlert.prototype.enableInput = enableInput;
4033
+ SweetAlert.prototype.hideLoading = hideLoading;
4034
+ SweetAlert.prototype.disableLoading = hideLoading;
4035
+ SweetAlert.prototype.showValidationMessage = showValidationMessage;
4036
+ SweetAlert.prototype.resetValidationMessage = resetValidationMessage;
4037
+ SweetAlert.prototype.close = close;
4038
+ SweetAlert.prototype.closePopup = close;
4039
+ SweetAlert.prototype.closeModal = close;
4040
+ SweetAlert.prototype.closeToast = close;
4041
+ SweetAlert.prototype.rejectPromise = rejectPromise;
4042
+ SweetAlert.prototype.update = update;
4043
+ SweetAlert.prototype._destroy = _destroy;
4016
4044
 
4017
4045
  // Assign static methods from src/staticMethods/*.js to constructor
4018
4046
  Object.assign(SweetAlert, staticMethods);
@@ -4024,13 +4052,14 @@
4024
4052
  * @returns {any | undefined}
4025
4053
  */
4026
4054
  SweetAlert[key] = function () {
4027
- if (currentInstance) {
4055
+ if (currentInstance && currentInstance[key]) {
4028
4056
  return currentInstance[key](...arguments);
4029
4057
  }
4058
+ return null;
4030
4059
  };
4031
4060
  });
4032
4061
  SweetAlert.DismissReason = DismissReason;
4033
- SweetAlert.version = '11.7.5';
4062
+ SweetAlert.version = '11.7.7';
4034
4063
 
4035
4064
  const Swal = SweetAlert;
4036
4065
  // @ts-ignore