sweetalert2 11.7.20 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sweetalert2",
3
- "version": "11.7.20",
3
+ "version": "11.7.21",
4
4
  "repository": "sweetalert2/sweetalert2",
5
5
  "homepage": "https://sweetalert2.github.io/",
6
6
  "description": "A beautiful, responsive, customizable and accessible (WAI-ARIA) replacement for JavaScript's popup boxes, supported fork of sweetalert",
@@ -25,7 +25,7 @@
25
25
  "rollup": "^3.2.2",
26
26
  "sass": "^1.55.0",
27
27
  "stylelint": "^15.0.0",
28
- "typescript": "4.0.2",
28
+ "typescript": "4.3.5",
29
29
  "vite": "^4.0.0",
30
30
  "zx": "^7.1.1"
31
31
  },
@@ -58,7 +58,7 @@
58
58
  "accessible"
59
59
  ],
60
60
  "scripts": {
61
- "start": "vite sandbox --open",
61
+ "dev": "vite sandbox --open",
62
62
  "lint": "stylelint src/**/*.scss && eslint src cypress *.js *.ts && prettier --check src/**/*.js cypress/**/*.js *.js",
63
63
  "build": "zx tools/build.mjs",
64
64
  "test": "cypress run --headless",
package/src/SweetAlert.js CHANGED
@@ -319,6 +319,6 @@ Object.keys(instanceMethods).forEach((key) => {
319
319
 
320
320
  SweetAlert.DismissReason = DismissReason
321
321
 
322
- SweetAlert.version = '11.7.20'
322
+ SweetAlert.version = '11.7.21'
323
323
 
324
324
  export default SweetAlert
@@ -52,10 +52,11 @@ const handleConfirmOrDenyWithInput = (instance, type) => {
52
52
  error(`The "input" parameter is needed to be set when using returnInputValueOn${capitalizeFirstLetter(type)}`)
53
53
  return
54
54
  }
55
+ const input = instance.getInput()
55
56
  const inputValue = getInputValue(instance, innerParams)
56
57
  if (innerParams.inputValidator) {
57
58
  handleInputValidator(instance, inputValue, type)
58
- } else if (!instance.getInput().checkValidity()) {
59
+ } else if (input && !input.checkValidity()) {
59
60
  instance.enableButtons()
60
61
  instance.showValidationMessage(innerParams.validationMessage)
61
62
  } else if (type === 'deny') {
@@ -1,4 +1,6 @@
1
+ import * as dom from '../utils/dom/index.js'
1
2
  import privateProps from '../privateProps.js'
3
+ import { swalClasses } from '../utils/classes.js'
2
4
 
3
5
  /**
4
6
  * @param {SweetAlert} instance
@@ -13,16 +15,17 @@ function setButtonsDisabled(instance, buttons, disabled) {
13
15
  }
14
16
 
15
17
  /**
16
- * @param {HTMLInputElement} input
18
+ * @param {HTMLInputElement | null} input
17
19
  * @param {boolean} disabled
18
20
  */
19
21
  function setInputDisabled(input, disabled) {
20
- if (!input) {
22
+ const popup = dom.getPopup()
23
+ if (!popup || !input) {
21
24
  return
22
25
  }
23
26
  if (input.type === 'radio') {
24
- const radiosContainer = input.parentNode.parentNode
25
- const radios = radiosContainer.querySelectorAll('input')
27
+ /** @type {NodeListOf<HTMLInputElement>} */
28
+ const radios = popup.querySelectorAll(`[name="${swalClasses.radio}"]`)
26
29
  for (let i = 0; i < radios.length; i++) {
27
30
  radios[i].disabled = disabled
28
31
  }
@@ -33,6 +36,7 @@ function setInputDisabled(input, disabled) {
33
36
 
34
37
  /**
35
38
  * Enable all the buttons
39
+ * @this {SweetAlert}
36
40
  */
37
41
  export function enableButtons() {
38
42
  setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false)
@@ -40,6 +44,7 @@ export function enableButtons() {
40
44
 
41
45
  /**
42
46
  * Disable all the buttons
47
+ * @this {SweetAlert}
43
48
  */
44
49
  export function disableButtons() {
45
50
  setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true)
@@ -47,6 +52,7 @@ export function disableButtons() {
47
52
 
48
53
  /**
49
54
  * Enable the input field
55
+ * @this {SweetAlert}
50
56
  */
51
57
  export function enableInput() {
52
58
  setInputDisabled(this.getInput(), false)
@@ -54,6 +60,7 @@ export function enableInput() {
54
60
 
55
61
  /**
56
62
  * Disable the input field
63
+ * @this {SweetAlert}
57
64
  */
58
65
  export function disableInput() {
59
66
  setInputDisabled(this.getInput(), true)
@@ -6,7 +6,7 @@ import * as dom from '../utils/dom/index.js'
6
6
  * Shows loader (spinner), this is useful with AJAX requests.
7
7
  * By default the loader be shown instead of the "Confirm" button.
8
8
  *
9
- * @param {HTMLButtonElement} [buttonToReplace]
9
+ * @param {HTMLButtonElement | null} [buttonToReplace]
10
10
  */
11
11
  const showLoading = (buttonToReplace) => {
12
12
  let popup = dom.getPopup()
@@ -14,6 +14,9 @@ const showLoading = (buttonToReplace) => {
14
14
  new Swal() // eslint-disable-line no-new
15
15
  }
16
16
  popup = dom.getPopup()
17
+ if (!popup) {
18
+ return
19
+ }
17
20
  const loader = dom.getLoader()
18
21
 
19
22
  if (dom.isToast()) {
@@ -30,11 +33,14 @@ const showLoading = (buttonToReplace) => {
30
33
 
31
34
  /**
32
35
  * @param {HTMLElement} popup
33
- * @param {HTMLButtonElement} [buttonToReplace]
36
+ * @param {HTMLButtonElement | null} [buttonToReplace]
34
37
  */
35
38
  const replaceButton = (popup, buttonToReplace) => {
36
39
  const actions = dom.getActions()
37
40
  const loader = dom.getLoader()
41
+ if (!actions || !loader) {
42
+ return
43
+ }
38
44
 
39
45
  if (!buttonToReplace && dom.isVisible(dom.getConfirmButton())) {
40
46
  buttonToReplace = dom.getConfirmButton()
@@ -44,8 +50,8 @@ const replaceButton = (popup, buttonToReplace) => {
44
50
  if (buttonToReplace) {
45
51
  dom.hide(buttonToReplace)
46
52
  loader.setAttribute('data-button-to-replace', buttonToReplace.className)
53
+ actions.insertBefore(loader, buttonToReplace)
47
54
  }
48
- loader.parentNode.insertBefore(loader, buttonToReplace)
49
55
  dom.addClass([popup, actions], swalClasses.loading)
50
56
  }
51
57
 
@@ -243,7 +243,7 @@ export const toggle = (elem, condition, display = 'flex') => {
243
243
  /**
244
244
  * borrowed from jquery $(elem).is(':visible') implementation
245
245
  *
246
- * @param {HTMLElement} elem
246
+ * @param {HTMLElement | null} elem
247
247
  * @returns {boolean}
248
248
  */
249
249
  export const isVisible = (elem) => !!(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length))
@@ -281,6 +281,9 @@ export const hasCssAnimation = (elem) => {
281
281
  */
282
282
  export const animateTimerProgressBar = (timer, reset = false) => {
283
283
  const timerProgressBar = getTimerProgressBar()
284
+ if (!timerProgressBar) {
285
+ return
286
+ }
284
287
  if (isVisible(timerProgressBar)) {
285
288
  if (reset) {
286
289
  timerProgressBar.style.transition = 'none'
@@ -295,6 +298,9 @@ export const animateTimerProgressBar = (timer, reset = false) => {
295
298
 
296
299
  export const stopTimerProgressBar = () => {
297
300
  const timerProgressBar = getTimerProgressBar()
301
+ if (!timerProgressBar) {
302
+ return
303
+ }
298
304
  const timerProgressBarWidth = parseInt(window.getComputedStyle(timerProgressBar).width)
299
305
  timerProgressBar.style.removeProperty('transition')
300
306
  timerProgressBar.style.width = '100%'
@@ -5,7 +5,7 @@ import { getDirectChildByClass } from './domUtils.js'
5
5
  import * as dom from './index.js'
6
6
 
7
7
  /**
8
- * @typedef { string | number | boolean } InputValue
8
+ * @typedef { string | number | boolean | undefined } InputValue
9
9
  */
10
10
 
11
11
  /**
@@ -16,7 +16,7 @@ export const handleInputOptionsAndValue = (instance, params) => {
16
16
  if (params.input === 'select' || params.input === 'radio') {
17
17
  handleInputOptions(instance, params)
18
18
  } else if (
19
- ['text', 'email', 'number', 'tel', 'textarea'].includes(params.input) &&
19
+ ['text', 'email', 'number', 'tel', 'textarea'].some((i) => i === params.input) &&
20
20
  (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))
21
21
  ) {
22
22
  showLoading(dom.getConfirmButton())
@@ -63,7 +63,7 @@ const getRadioValue = (input) => (input.checked ? input.value : null)
63
63
  * @returns {FileList | File | null}
64
64
  */
65
65
  const getFileValue = (input) =>
66
- input.files.length ? (input.getAttribute('multiple') !== null ? input.files : input.files[0]) : null
66
+ input.files && input.files.length ? (input.getAttribute('multiple') !== null ? input.files : input.files[0]) : null
67
67
 
68
68
  /**
69
69
  * @param {SweetAlert} instance
@@ -71,11 +71,18 @@ const getFileValue = (input) =>
71
71
  */
72
72
  const handleInputOptions = (instance, params) => {
73
73
  const popup = dom.getPopup()
74
+ if (!popup) {
75
+ return
76
+ }
74
77
  /**
75
78
  * @param {Record<string, any>} inputOptions
76
79
  */
77
80
  const processInputOptions = (inputOptions) => {
78
- populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params)
81
+ if (params.input === 'select') {
82
+ populateSelectOptions(popup, formatInputOptions(inputOptions), params)
83
+ } else if (params.input === 'radio') {
84
+ populateRadioOptions(popup, formatInputOptions(inputOptions), params)
85
+ }
79
86
  }
80
87
  if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
81
88
  showLoading(dom.getConfirmButton())
@@ -96,6 +103,9 @@ const handleInputOptions = (instance, params) => {
96
103
  */
97
104
  const handleInputValue = (instance, params) => {
98
105
  const input = instance.getInput()
106
+ if (!input) {
107
+ return
108
+ }
99
109
  dom.hide(input)
100
110
  asPromise(params.inputValue)
101
111
  .then((inputValue) => {
@@ -113,89 +123,95 @@ const handleInputValue = (instance, params) => {
113
123
  })
114
124
  }
115
125
 
116
- const populateInputOptions = {
126
+ /**
127
+ * @param {HTMLElement} popup
128
+ * @param {InputOptionFlattened[]} inputOptions
129
+ * @param {SweetAlertOptions} params
130
+ */
131
+ function populateSelectOptions(popup, inputOptions, params) {
132
+ const select = getDirectChildByClass(popup, swalClasses.select)
133
+ if (!select) {
134
+ return
135
+ }
117
136
  /**
118
- * @param {HTMLElement} popup
119
- * @param {Record<string, any>} inputOptions
120
- * @param {SweetAlertOptions} params
137
+ * @param {HTMLElement} parent
138
+ * @param {string} optionLabel
139
+ * @param {string} optionValue
121
140
  */
122
- select: (popup, inputOptions, params) => {
123
- const select = getDirectChildByClass(popup, swalClasses.select)
124
- /**
125
- * @param {HTMLElement} parent
126
- * @param {string} optionLabel
127
- * @param {string} optionValue
128
- */
129
- const renderOption = (parent, optionLabel, optionValue) => {
130
- const option = document.createElement('option')
131
- option.value = optionValue
132
- dom.setInnerHtml(option, optionLabel)
133
- option.selected = isSelected(optionValue, params.inputValue)
134
- parent.appendChild(option)
141
+ const renderOption = (parent, optionLabel, optionValue) => {
142
+ const option = document.createElement('option')
143
+ option.value = optionValue
144
+ dom.setInnerHtml(option, optionLabel)
145
+ option.selected = isSelected(optionValue, params.inputValue)
146
+ parent.appendChild(option)
147
+ }
148
+ inputOptions.forEach((inputOption) => {
149
+ const optionValue = inputOption[0]
150
+ const optionLabel = inputOption[1]
151
+ // <optgroup> spec:
152
+ // https://www.w3.org/TR/html401/interact/forms.html#h-17.6
153
+ // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
154
+ // check whether this is a <optgroup>
155
+ if (Array.isArray(optionLabel)) {
156
+ // if it is an array, then it is an <optgroup>
157
+ const optgroup = document.createElement('optgroup')
158
+ optgroup.label = optionValue
159
+ optgroup.disabled = false // not configurable for now
160
+ select.appendChild(optgroup)
161
+ optionLabel.forEach((o) => renderOption(optgroup, o[1], o[0]))
162
+ } else {
163
+ // case of <option>
164
+ renderOption(select, optionLabel, optionValue)
135
165
  }
136
- inputOptions.forEach((inputOption) => {
137
- const optionValue = inputOption[0]
138
- const optionLabel = inputOption[1]
139
- // <optgroup> spec:
140
- // https://www.w3.org/TR/html401/interact/forms.html#h-17.6
141
- // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
142
- // check whether this is a <optgroup>
143
- if (Array.isArray(optionLabel)) {
144
- // if it is an array, then it is an <optgroup>
145
- const optgroup = document.createElement('optgroup')
146
- optgroup.label = optionValue
147
- optgroup.disabled = false // not configurable for now
148
- select.appendChild(optgroup)
149
- optionLabel.forEach((o) => renderOption(optgroup, o[1], o[0]))
150
- } else {
151
- // case of <option>
152
- renderOption(select, optionLabel, optionValue)
153
- }
154
- })
155
- select.focus()
156
- },
166
+ })
167
+ select.focus()
168
+ }
157
169
 
158
- /**
159
- * @param {HTMLElement} popup
160
- * @param {Record<string, any>} inputOptions
161
- * @param {SweetAlertOptions} params
162
- */
163
- radio: (popup, inputOptions, params) => {
164
- const radio = getDirectChildByClass(popup, swalClasses.radio)
165
- inputOptions.forEach((inputOption) => {
166
- const radioValue = inputOption[0]
167
- const radioLabel = inputOption[1]
168
- const radioInput = document.createElement('input')
169
- const radioLabelElement = document.createElement('label')
170
- radioInput.type = 'radio'
171
- radioInput.name = swalClasses.radio
172
- radioInput.value = radioValue
173
- if (isSelected(radioValue, params.inputValue)) {
174
- radioInput.checked = true
175
- }
176
- const label = document.createElement('span')
177
- dom.setInnerHtml(label, radioLabel)
178
- label.className = swalClasses.label
179
- radioLabelElement.appendChild(radioInput)
180
- radioLabelElement.appendChild(label)
181
- radio.appendChild(radioLabelElement)
182
- })
183
- const radios = radio.querySelectorAll('input')
184
- if (radios.length) {
185
- radios[0].focus()
170
+ /**
171
+ * @param {HTMLElement} popup
172
+ * @param {InputOptionFlattened[]} inputOptions
173
+ * @param {SweetAlertOptions} params
174
+ */
175
+ function populateRadioOptions(popup, inputOptions, params) {
176
+ const radio = getDirectChildByClass(popup, swalClasses.radio)
177
+ if (!radio) {
178
+ return
179
+ }
180
+ inputOptions.forEach((inputOption) => {
181
+ const radioValue = inputOption[0]
182
+ const radioLabel = inputOption[1]
183
+ const radioInput = document.createElement('input')
184
+ const radioLabelElement = document.createElement('label')
185
+ radioInput.type = 'radio'
186
+ radioInput.name = swalClasses.radio
187
+ radioInput.value = radioValue
188
+ if (isSelected(radioValue, params.inputValue)) {
189
+ radioInput.checked = true
186
190
  }
187
- },
191
+ const label = document.createElement('span')
192
+ dom.setInnerHtml(label, radioLabel)
193
+ label.className = swalClasses.label
194
+ radioLabelElement.appendChild(radioInput)
195
+ radioLabelElement.appendChild(label)
196
+ radio.appendChild(radioLabelElement)
197
+ })
198
+ const radios = radio.querySelectorAll('input')
199
+ if (radios.length) {
200
+ radios[0].focus()
201
+ }
188
202
  }
189
203
 
190
204
  /**
191
205
  * Converts `inputOptions` into an array of `[value, label]`s
192
206
  *
193
207
  * @param {Record<string, any>} inputOptions
194
- * @returns {Array<Array<string>>}
208
+ * @typedef {string[]} InputOptionFlattened
209
+ * @returns {InputOptionFlattened[]}
195
210
  */
196
211
  const formatInputOptions = (inputOptions) => {
212
+ /** @type {InputOptionFlattened[]} */
197
213
  const result = []
198
- if (typeof Map !== 'undefined' && inputOptions instanceof Map) {
214
+ if (inputOptions instanceof Map) {
199
215
  inputOptions.forEach((value, key) => {
200
216
  let valueFormatted = value
201
217
  if (typeof valueFormatted === 'object') {
@@ -223,5 +239,5 @@ const formatInputOptions = (inputOptions) => {
223
239
  * @returns {boolean}
224
240
  */
225
241
  const isSelected = (optionValue, inputValue) => {
226
- return inputValue && inputValue.toString() === optionValue.toString()
242
+ return !!inputValue && inputValue.toString() === optionValue.toString()
227
243
  }
package/sweetalert2.d.ts CHANGED
@@ -951,7 +951,7 @@ declare module 'sweetalert2' {
951
951
  *
952
952
  * @default undefined
953
953
  */
954
- preConfirm?(inputValue: PreConfirmCallbackValue): PreConfirmResult
954
+ preConfirm?(inputValue: PreConfirmCallbackValue): SyncOrAsync<PreConfirmResult>
955
955
 
956
956
  /**
957
957
  * Function to execute before denying, may be async (Promise-returning) or sync.