sweetalert2 11.7.19 → 11.7.21

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.
package/README.md CHANGED
@@ -10,23 +10,23 @@ A beautiful, responsive, customizable, accessible (WAI-ARIA) replacement <br> fo
10
10
 
11
11
  ---
12
12
 
13
- :moneybag: [Get $100 in free credits with DigitalOcean!](https://m.do.co/c/12907f2ba0bf)
13
+ :moneybag: [Get $200 in free credits with DigitalOcean!](https://m.do.co/c/12907f2ba0bf)
14
14
 
15
15
  ---
16
16
 
17
- Important notice about usage of this software for `.ru`, `.su`, `.by`, and `.рф` domain zones
17
+ Important notice about the usage of this software for `.ru`, `.su`, `.by`, and `.рф` domain zones
18
18
  --------------------------------------------------------------------------------------
19
19
 
20
20
  As a consequence of the illegal war in Ukraine, the behavior of this repository and related npm package [sweetalert2](https://www.npmjs.com/package/sweetalert2) is different for `.ru`, `.su`, `.by`, and `.рф` domain zones.
21
21
 
22
- Including this software in any domain in `.ru`, `.su`, `.by`, and `.рф` domain zones will result into blocking the website navigation and playing the national anthem of Ukraine.
22
+ Including this software in any domain in `.ru`, `.su`, `.by`, and `.рф` domain zones will block the website navigation and play the national anthem of Ukraine.
23
23
 
24
- This behavior is classified as [protestware](https://snyk.io/blog/protestware-open-source-types-impact/) and this project is listed in [GitHub Advisory Database](https://github.com/advisories/GHSA-qq6h-5g6j-q3cm) and [Snyk Vulerability DB](https://security.snyk.io/package/npm/sweetalert2/11.5.2).
24
+ This behavior is classified as [protestware](https://snyk.io/blog/protestware-open-source-types-impact/) and this project is listed in [GitHub Advisory Database](https://github.com/advisories/GHSA-mrr8-v49w-3333) and [Snyk Vulnerability DB](https://security.snyk.io/package/npm/sweetalert2/11.5.2).
25
25
 
26
26
  Sponsors
27
27
  --------
28
28
 
29
- For all questions related to sponsorship please contact me via email sweetalert2@gmail.com
29
+ For all questions related to sponsorship please get in touch with me via email sweetalert2@gmail.com
30
30
 
31
31
  <table>
32
32
  <tr>
@@ -134,4 +134,4 @@ NSFW Sponsors
134
134
  Support and Donations
135
135
  ---------------------
136
136
 
137
- Has SweetAlert2 helped you create an amazing application? You can show your support via [GitHub Sponsors](https://github.com/sponsors/limonte)
137
+ Has SweetAlert2 helped you create a fantastic application? You can show your support via [GitHub Sponsors](https://github.com/sponsors/limonte)
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * sweetalert2 v11.7.19
2
+ * sweetalert2 v11.7.21
3
3
  * Released under the MIT License.
4
4
  */
5
5
  (function (global, factory) {
@@ -436,10 +436,12 @@
436
436
  if (html) {
437
437
  const parser = new DOMParser();
438
438
  const parsed = parser.parseFromString(html, `text/html`);
439
- Array.from(parsed.querySelector('head').childNodes).forEach(child => {
439
+ const head = parsed.querySelector('head');
440
+ head && Array.from(head.childNodes).forEach(child => {
440
441
  elem.appendChild(child);
441
442
  });
442
- Array.from(parsed.querySelector('body').childNodes).forEach(child => {
443
+ const body = parsed.querySelector('body');
444
+ body && Array.from(body.childNodes).forEach(child => {
443
445
  if (child instanceof HTMLVideoElement || child instanceof HTMLAudioElement) {
444
446
  elem.appendChild(child.cloneNode(true)); // https://github.com/sweetalert2/sweetalert2/issues/2507
445
447
  } else {
@@ -473,7 +475,7 @@
473
475
  */
474
476
  const removeCustomClasses = (elem, params) => {
475
477
  Array.from(elem.classList).forEach(className => {
476
- if (!Object.values(swalClasses).includes(className) && !Object.values(iconTypes).includes(className) && !Object.values(params.showClass).includes(className)) {
478
+ if (!Object.values(swalClasses).includes(className) && !Object.values(iconTypes).includes(className) && !Object.values(params.showClass || {}).includes(className)) {
477
479
  elem.classList.remove(className);
478
480
  }
479
481
  });
@@ -650,7 +652,7 @@
650
652
  /**
651
653
  * borrowed from jquery $(elem).is(':visible') implementation
652
654
  *
653
- * @param {HTMLElement} elem
655
+ * @param {HTMLElement | null} elem
654
656
  * @returns {boolean}
655
657
  */
656
658
  const isVisible$1 = elem => !!(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length));
@@ -686,6 +688,9 @@
686
688
  const animateTimerProgressBar = function (timer) {
687
689
  let reset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
688
690
  const timerProgressBar = getTimerProgressBar();
691
+ if (!timerProgressBar) {
692
+ return;
693
+ }
689
694
  if (isVisible$1(timerProgressBar)) {
690
695
  if (reset) {
691
696
  timerProgressBar.style.transition = 'none';
@@ -699,6 +704,9 @@
699
704
  };
700
705
  const stopTimerProgressBar = () => {
701
706
  const timerProgressBar = getTimerProgressBar();
707
+ if (!timerProgressBar) {
708
+ return;
709
+ }
702
710
  const timerProgressBarWidth = parseInt(window.getComputedStyle(timerProgressBar).width);
703
711
  timerProgressBar.style.removeProperty('transition');
704
712
  timerProgressBar.style.width = '100%';
@@ -2319,7 +2327,7 @@
2319
2327
  * Shows loader (spinner), this is useful with AJAX requests.
2320
2328
  * By default the loader be shown instead of the "Confirm" button.
2321
2329
  *
2322
- * @param {HTMLButtonElement} [buttonToReplace]
2330
+ * @param {HTMLButtonElement | null} [buttonToReplace]
2323
2331
  */
2324
2332
  const showLoading = buttonToReplace => {
2325
2333
  let popup = getPopup();
@@ -2328,6 +2336,9 @@
2328
2336
  }
2329
2337
 
2330
2338
  popup = getPopup();
2339
+ if (!popup) {
2340
+ return;
2341
+ }
2331
2342
  const loader = getLoader();
2332
2343
  if (isToast()) {
2333
2344
  hide(getIcon());
@@ -2342,11 +2353,14 @@
2342
2353
 
2343
2354
  /**
2344
2355
  * @param {HTMLElement} popup
2345
- * @param {HTMLButtonElement} [buttonToReplace]
2356
+ * @param {HTMLButtonElement | null} [buttonToReplace]
2346
2357
  */
2347
2358
  const replaceButton = (popup, buttonToReplace) => {
2348
2359
  const actions = getActions();
2349
2360
  const loader = getLoader();
2361
+ if (!actions || !loader) {
2362
+ return;
2363
+ }
2350
2364
  if (!buttonToReplace && isVisible$1(getConfirmButton())) {
2351
2365
  buttonToReplace = getConfirmButton();
2352
2366
  }
@@ -2354,13 +2368,13 @@
2354
2368
  if (buttonToReplace) {
2355
2369
  hide(buttonToReplace);
2356
2370
  loader.setAttribute('data-button-to-replace', buttonToReplace.className);
2371
+ actions.insertBefore(loader, buttonToReplace);
2357
2372
  }
2358
- loader.parentNode.insertBefore(loader, buttonToReplace);
2359
2373
  addClass([popup, actions], swalClasses.loading);
2360
2374
  };
2361
2375
 
2362
2376
  /**
2363
- * @typedef { string | number | boolean } InputValue
2377
+ * @typedef { string | number | boolean | undefined } InputValue
2364
2378
  */
2365
2379
 
2366
2380
  /**
@@ -2370,7 +2384,7 @@
2370
2384
  const handleInputOptionsAndValue = (instance, params) => {
2371
2385
  if (params.input === 'select' || params.input === 'radio') {
2372
2386
  handleInputOptions(instance, params);
2373
- } else if (['text', 'email', 'number', 'tel', 'textarea'].includes(params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {
2387
+ } else if (['text', 'email', 'number', 'tel', 'textarea'].some(i => i === params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) {
2374
2388
  showLoading(getConfirmButton());
2375
2389
  handleInputValue(instance, params);
2376
2390
  }
@@ -2414,7 +2428,7 @@
2414
2428
  * @param {HTMLInputElement} input
2415
2429
  * @returns {FileList | File | null}
2416
2430
  */
2417
- const getFileValue = input => input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;
2431
+ const getFileValue = input => input.files && input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null;
2418
2432
 
2419
2433
  /**
2420
2434
  * @param {SweetAlert} instance
@@ -2422,11 +2436,18 @@
2422
2436
  */
2423
2437
  const handleInputOptions = (instance, params) => {
2424
2438
  const popup = getPopup();
2439
+ if (!popup) {
2440
+ return;
2441
+ }
2425
2442
  /**
2426
2443
  * @param {Record<string, any>} inputOptions
2427
2444
  */
2428
2445
  const processInputOptions = inputOptions => {
2429
- populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params);
2446
+ if (params.input === 'select') {
2447
+ populateSelectOptions(popup, formatInputOptions(inputOptions), params);
2448
+ } else if (params.input === 'radio') {
2449
+ populateRadioOptions(popup, formatInputOptions(inputOptions), params);
2450
+ }
2430
2451
  };
2431
2452
  if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
2432
2453
  showLoading(getConfirmButton());
@@ -2447,6 +2468,9 @@
2447
2468
  */
2448
2469
  const handleInputValue = (instance, params) => {
2449
2470
  const input = instance.getInput();
2471
+ if (!input) {
2472
+ return;
2473
+ }
2450
2474
  hide(input);
2451
2475
  asPromise(params.inputValue).then(inputValue => {
2452
2476
  input.value = params.input === 'number' ? `${parseFloat(inputValue) || 0}` : `${inputValue}`;
@@ -2461,88 +2485,96 @@
2461
2485
  instance.hideLoading();
2462
2486
  });
2463
2487
  };
2464
- const populateInputOptions = {
2465
- /**
2466
- * @param {HTMLElement} popup
2467
- * @param {Record<string, any>} inputOptions
2468
- * @param {SweetAlertOptions} params
2469
- */
2470
- select: (popup, inputOptions, params) => {
2471
- const select = getDirectChildByClass(popup, swalClasses.select);
2472
- /**
2473
- * @param {HTMLElement} parent
2474
- * @param {string} optionLabel
2475
- * @param {string} optionValue
2476
- */
2477
- const renderOption = (parent, optionLabel, optionValue) => {
2478
- const option = document.createElement('option');
2479
- option.value = optionValue;
2480
- setInnerHtml(option, optionLabel);
2481
- option.selected = isSelected(optionValue, params.inputValue);
2482
- parent.appendChild(option);
2483
- };
2484
- inputOptions.forEach(inputOption => {
2485
- const optionValue = inputOption[0];
2486
- const optionLabel = inputOption[1];
2487
- // <optgroup> spec:
2488
- // https://www.w3.org/TR/html401/interact/forms.html#h-17.6
2489
- // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
2490
- // check whether this is a <optgroup>
2491
- if (Array.isArray(optionLabel)) {
2492
- // if it is an array, then it is an <optgroup>
2493
- const optgroup = document.createElement('optgroup');
2494
- optgroup.label = optionValue;
2495
- optgroup.disabled = false; // not configurable for now
2496
- select.appendChild(optgroup);
2497
- optionLabel.forEach(o => renderOption(optgroup, o[1], o[0]));
2498
- } else {
2499
- // case of <option>
2500
- renderOption(select, optionLabel, optionValue);
2501
- }
2502
- });
2503
- select.focus();
2504
- },
2488
+
2489
+ /**
2490
+ * @param {HTMLElement} popup
2491
+ * @param {InputOptionFlattened[]} inputOptions
2492
+ * @param {SweetAlertOptions} params
2493
+ */
2494
+ function populateSelectOptions(popup, inputOptions, params) {
2495
+ const select = getDirectChildByClass(popup, swalClasses.select);
2496
+ if (!select) {
2497
+ return;
2498
+ }
2505
2499
  /**
2506
- * @param {HTMLElement} popup
2507
- * @param {Record<string, any>} inputOptions
2508
- * @param {SweetAlertOptions} params
2500
+ * @param {HTMLElement} parent
2501
+ * @param {string} optionLabel
2502
+ * @param {string} optionValue
2509
2503
  */
2510
- radio: (popup, inputOptions, params) => {
2511
- const radio = getDirectChildByClass(popup, swalClasses.radio);
2512
- inputOptions.forEach(inputOption => {
2513
- const radioValue = inputOption[0];
2514
- const radioLabel = inputOption[1];
2515
- const radioInput = document.createElement('input');
2516
- const radioLabelElement = document.createElement('label');
2517
- radioInput.type = 'radio';
2518
- radioInput.name = swalClasses.radio;
2519
- radioInput.value = radioValue;
2520
- if (isSelected(radioValue, params.inputValue)) {
2521
- radioInput.checked = true;
2522
- }
2523
- const label = document.createElement('span');
2524
- setInnerHtml(label, radioLabel);
2525
- label.className = swalClasses.label;
2526
- radioLabelElement.appendChild(radioInput);
2527
- radioLabelElement.appendChild(label);
2528
- radio.appendChild(radioLabelElement);
2529
- });
2530
- const radios = radio.querySelectorAll('input');
2531
- if (radios.length) {
2532
- radios[0].focus();
2504
+ const renderOption = (parent, optionLabel, optionValue) => {
2505
+ const option = document.createElement('option');
2506
+ option.value = optionValue;
2507
+ setInnerHtml(option, optionLabel);
2508
+ option.selected = isSelected(optionValue, params.inputValue);
2509
+ parent.appendChild(option);
2510
+ };
2511
+ inputOptions.forEach(inputOption => {
2512
+ const optionValue = inputOption[0];
2513
+ const optionLabel = inputOption[1];
2514
+ // <optgroup> spec:
2515
+ // https://www.w3.org/TR/html401/interact/forms.html#h-17.6
2516
+ // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
2517
+ // check whether this is a <optgroup>
2518
+ if (Array.isArray(optionLabel)) {
2519
+ // if it is an array, then it is an <optgroup>
2520
+ const optgroup = document.createElement('optgroup');
2521
+ optgroup.label = optionValue;
2522
+ optgroup.disabled = false; // not configurable for now
2523
+ select.appendChild(optgroup);
2524
+ optionLabel.forEach(o => renderOption(optgroup, o[1], o[0]));
2525
+ } else {
2526
+ // case of <option>
2527
+ renderOption(select, optionLabel, optionValue);
2528
+ }
2529
+ });
2530
+ select.focus();
2531
+ }
2532
+
2533
+ /**
2534
+ * @param {HTMLElement} popup
2535
+ * @param {InputOptionFlattened[]} inputOptions
2536
+ * @param {SweetAlertOptions} params
2537
+ */
2538
+ function populateRadioOptions(popup, inputOptions, params) {
2539
+ const radio = getDirectChildByClass(popup, swalClasses.radio);
2540
+ if (!radio) {
2541
+ return;
2542
+ }
2543
+ inputOptions.forEach(inputOption => {
2544
+ const radioValue = inputOption[0];
2545
+ const radioLabel = inputOption[1];
2546
+ const radioInput = document.createElement('input');
2547
+ const radioLabelElement = document.createElement('label');
2548
+ radioInput.type = 'radio';
2549
+ radioInput.name = swalClasses.radio;
2550
+ radioInput.value = radioValue;
2551
+ if (isSelected(radioValue, params.inputValue)) {
2552
+ radioInput.checked = true;
2533
2553
  }
2554
+ const label = document.createElement('span');
2555
+ setInnerHtml(label, radioLabel);
2556
+ label.className = swalClasses.label;
2557
+ radioLabelElement.appendChild(radioInput);
2558
+ radioLabelElement.appendChild(label);
2559
+ radio.appendChild(radioLabelElement);
2560
+ });
2561
+ const radios = radio.querySelectorAll('input');
2562
+ if (radios.length) {
2563
+ radios[0].focus();
2534
2564
  }
2535
- };
2565
+ }
2536
2566
 
2537
2567
  /**
2538
2568
  * Converts `inputOptions` into an array of `[value, label]`s
2539
2569
  *
2540
2570
  * @param {Record<string, any>} inputOptions
2541
- * @returns {Array<Array<string>>}
2571
+ * @typedef {string[]} InputOptionFlattened
2572
+ * @returns {InputOptionFlattened[]}
2542
2573
  */
2543
2574
  const formatInputOptions = inputOptions => {
2575
+ /** @type {InputOptionFlattened[]} */
2544
2576
  const result = [];
2545
- if (typeof Map !== 'undefined' && inputOptions instanceof Map) {
2577
+ if (inputOptions instanceof Map) {
2546
2578
  inputOptions.forEach((value, key) => {
2547
2579
  let valueFormatted = value;
2548
2580
  if (typeof valueFormatted === 'object') {
@@ -2570,7 +2602,7 @@
2570
2602
  * @returns {boolean}
2571
2603
  */
2572
2604
  const isSelected = (optionValue, inputValue) => {
2573
- return inputValue && inputValue.toString() === optionValue.toString();
2605
+ return !!inputValue && inputValue.toString() === optionValue.toString();
2574
2606
  };
2575
2607
 
2576
2608
  /**
@@ -2618,10 +2650,11 @@
2618
2650
  error(`The "input" parameter is needed to be set when using returnInputValueOn${capitalizeFirstLetter(type)}`);
2619
2651
  return;
2620
2652
  }
2653
+ const input = instance.getInput();
2621
2654
  const inputValue = getInputValue(instance, innerParams);
2622
2655
  if (innerParams.inputValidator) {
2623
2656
  handleInputValidator(instance, inputValue, type);
2624
- } else if (!instance.getInput().checkValidity()) {
2657
+ } else if (input && !input.checkValidity()) {
2625
2658
  instance.enableButtons();
2626
2659
  instance.showValidationMessage(innerParams.validationMessage);
2627
2660
  } else if (type === 'deny') {
@@ -2792,16 +2825,17 @@
2792
2825
  }
2793
2826
 
2794
2827
  /**
2795
- * @param {HTMLInputElement} input
2828
+ * @param {HTMLInputElement | null} input
2796
2829
  * @param {boolean} disabled
2797
2830
  */
2798
2831
  function setInputDisabled(input, disabled) {
2799
- if (!input) {
2832
+ const popup = getPopup();
2833
+ if (!popup || !input) {
2800
2834
  return;
2801
2835
  }
2802
2836
  if (input.type === 'radio') {
2803
- const radiosContainer = input.parentNode.parentNode;
2804
- const radios = radiosContainer.querySelectorAll('input');
2837
+ /** @type {NodeListOf<HTMLInputElement>} */
2838
+ const radios = popup.querySelectorAll(`[name="${swalClasses.radio}"]`);
2805
2839
  for (let i = 0; i < radios.length; i++) {
2806
2840
  radios[i].disabled = disabled;
2807
2841
  }
@@ -2812,6 +2846,7 @@
2812
2846
 
2813
2847
  /**
2814
2848
  * Enable all the buttons
2849
+ * @this {SweetAlert}
2815
2850
  */
2816
2851
  function enableButtons() {
2817
2852
  setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false);
@@ -2819,6 +2854,7 @@
2819
2854
 
2820
2855
  /**
2821
2856
  * Disable all the buttons
2857
+ * @this {SweetAlert}
2822
2858
  */
2823
2859
  function disableButtons() {
2824
2860
  setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true);
@@ -2826,6 +2862,7 @@
2826
2862
 
2827
2863
  /**
2828
2864
  * Enable the input field
2865
+ * @this {SweetAlert}
2829
2866
  */
2830
2867
  function enableInput() {
2831
2868
  setInputDisabled(this.getInput(), false);
@@ -2833,6 +2870,7 @@
2833
2870
 
2834
2871
  /**
2835
2872
  * Disable the input field
2873
+ * @this {SweetAlert}
2836
2874
  */
2837
2875
  function disableInput() {
2838
2876
  setInputDisabled(this.getInput(), true);
@@ -3850,16 +3888,16 @@
3850
3888
  var defaultInputValidators = {
3851
3889
  /**
3852
3890
  * @param {string} string
3853
- * @param {string} validationMessage
3854
- * @returns {Promise<void | string>}
3891
+ * @param {string} [validationMessage]
3892
+ * @returns {Promise<string | void>}
3855
3893
  */
3856
3894
  email: (string, validationMessage) => {
3857
3895
  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');
3858
3896
  },
3859
3897
  /**
3860
3898
  * @param {string} string
3861
- * @param {string} validationMessage
3862
- * @returns {Promise<void | string>}
3899
+ * @param {string} [validationMessage]
3900
+ * @returns {Promise<string | void>}
3863
3901
  */
3864
3902
  url: (string, validationMessage) => {
3865
3903
  // taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #2013
@@ -3872,12 +3910,14 @@
3872
3910
  */
3873
3911
  function setDefaultInputValidators(params) {
3874
3912
  // Use default `inputValidator` for supported input types if not provided
3875
- if (!params.inputValidator) {
3876
- Object.keys(defaultInputValidators).forEach(key => {
3877
- if (params.input === key) {
3878
- params.inputValidator = defaultInputValidators[key];
3879
- }
3880
- });
3913
+ if (params.inputValidator) {
3914
+ return;
3915
+ }
3916
+ if (params.input === 'email') {
3917
+ params.inputValidator = defaultInputValidators['email'];
3918
+ }
3919
+ if (params.input === 'url') {
3920
+ params.inputValidator = defaultInputValidators['url'];
3881
3921
  }
3882
3922
  }
3883
3923
 
@@ -4186,7 +4226,7 @@
4186
4226
  };
4187
4227
  });
4188
4228
  SweetAlert.DismissReason = DismissReason;
4189
- SweetAlert.version = '11.7.19';
4229
+ SweetAlert.version = '11.7.21';
4190
4230
 
4191
4231
  const Swal = SweetAlert;
4192
4232
  // @ts-ignore