sweetalert2 11.26.13 → 11.26.15

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/src/SweetAlert.js CHANGED
@@ -24,7 +24,7 @@ export class SweetAlert {
24
24
  /**
25
25
  * @type {Promise<SweetAlertResult>}
26
26
  */
27
- #promise
27
+ #promise = /** @type {Promise<SweetAlertResult>} */ (Promise.resolve({ isConfirmed: false, isDenied: false, isDismissed: true }))
28
28
 
29
29
  /**
30
30
  * @param {...(SweetAlertOptions | string)} args
@@ -50,6 +50,10 @@ export class SweetAlert {
50
50
  this.#promise = this._main(currentInstance.params)
51
51
  }
52
52
 
53
+ /**
54
+ * @param {any} userParams
55
+ * @param {any} mixinParams
56
+ */
53
57
  _main(userParams, mixinParams = {}) {
54
58
  showWarningsForParams(Object.assign({}, mixinParams, userParams))
55
59
 
@@ -90,10 +94,16 @@ export class SweetAlert {
90
94
  }
91
95
 
92
96
  // `catch` cannot be the name of a module export, so we define our thenable methods here instead
97
+ /**
98
+ * @param {any} onFulfilled
99
+ */
93
100
  then(onFulfilled) {
94
101
  return this.#promise.then(onFulfilled)
95
102
  }
96
103
 
104
+ /**
105
+ * @param {any} onFinally
106
+ */
97
107
  finally(onFinally) {
98
108
  return this.#promise.finally(onFinally)
99
109
  }
@@ -103,7 +113,7 @@ export class SweetAlert {
103
113
  * @param {SweetAlert} instance
104
114
  * @param {DomCache} domCache
105
115
  * @param {SweetAlertOptions} innerParams
106
- * @returns {Promise}
116
+ * @returns {Promise<SweetAlertResult>}
107
117
  */
108
118
  const swalPromise = (instance, domCache, innerParams) => {
109
119
  return new Promise((resolve, reject) => {
@@ -177,18 +187,18 @@ const prepareParams = (userParams, mixinParams) => {
177
187
  * @returns {DomCache}
178
188
  */
179
189
  const populateDomCache = (instance) => {
180
- const domCache = {
181
- popup: dom.getPopup(),
182
- container: dom.getContainer(),
183
- actions: dom.getActions(),
184
- confirmButton: dom.getConfirmButton(),
185
- denyButton: dom.getDenyButton(),
186
- cancelButton: dom.getCancelButton(),
187
- loader: dom.getLoader(),
188
- closeButton: dom.getCloseButton(),
189
- validationMessage: dom.getValidationMessage(),
190
- progressSteps: dom.getProgressSteps(),
191
- }
190
+ const domCache = /** @type {DomCache} */ ({
191
+ popup: /** @type {HTMLElement} */ (dom.getPopup()),
192
+ container: /** @type {HTMLElement} */ (dom.getContainer()),
193
+ actions: /** @type {HTMLElement} */ (dom.getActions()),
194
+ confirmButton: /** @type {HTMLElement} */ (dom.getConfirmButton()),
195
+ denyButton: /** @type {HTMLElement} */ (dom.getDenyButton()),
196
+ cancelButton: /** @type {HTMLElement} */ (dom.getCancelButton()),
197
+ loader: /** @type {HTMLElement} */ (dom.getLoader()),
198
+ closeButton: /** @type {HTMLElement} */ (dom.getCloseButton()),
199
+ validationMessage: /** @type {HTMLElement} */ (dom.getValidationMessage()),
200
+ progressSteps: /** @type {HTMLElement} */ (dom.getProgressSteps()),
201
+ })
192
202
  privateProps.domCache.set(instance, domCache)
193
203
 
194
204
  return domCache
@@ -207,13 +217,13 @@ const setupTimer = (globalState, innerParams, dismissWith) => {
207
217
  dismissWith('timer')
208
218
  delete globalState.timeout
209
219
  }, innerParams.timer)
210
- if (innerParams.timerProgressBar) {
220
+ if (innerParams.timerProgressBar && timerProgressBar) {
211
221
  dom.show(timerProgressBar)
212
222
  dom.applyCustomClass(timerProgressBar, innerParams, 'timerProgressBar')
213
223
  setTimeout(() => {
214
224
  if (globalState.timeout && globalState.timeout.running) {
215
225
  // timer can be already stopped or unset at this point
216
- dom.animateTimerProgressBar(innerParams.timer)
226
+ dom.animateTimerProgressBar(/** @type {number} */ (innerParams.timer))
217
227
  }
218
228
  })
219
229
  }
@@ -327,16 +337,19 @@ Object.keys(instanceMethods).forEach((key) => {
327
337
  * @param {...(SweetAlertOptions | string | undefined)} args
328
338
  * @returns {SweetAlertResult | Promise<SweetAlertResult> | undefined}
329
339
  */
340
+ // @ts-ignore: Dynamic property assignment for backwards compatibility
330
341
  SweetAlert[key] = function (...args) {
342
+ // @ts-ignore
331
343
  if (currentInstance && currentInstance[key]) {
344
+ // @ts-ignore
332
345
  return currentInstance[key](...args)
333
346
  }
334
- return null
347
+ return undefined
335
348
  }
336
349
  })
337
350
 
338
351
  SweetAlert.DismissReason = DismissReason
339
352
 
340
- SweetAlert.version = '11.26.13'
353
+ SweetAlert.version = '11.26.15'
341
354
 
342
355
  export default SweetAlert
@@ -16,9 +16,15 @@
16
16
  *
17
17
  * @param {SweetAlertOptions} mixinParams
18
18
  * @returns {SweetAlert}
19
+ * @this {typeof import('../SweetAlert.js').SweetAlert}
19
20
  */
20
21
  export function mixin(mixinParams) {
22
+ // @ts-ignore: 'this' refers to the SweetAlert constructor
21
23
  class MixinSwal extends this {
24
+ /**
25
+ * @param {any} params
26
+ * @param {any} priorityMixinParams
27
+ */
22
28
  _main(params, priorityMixinParams) {
23
29
  return super._main(params, Object.assign({}, mixinParams, priorityMixinParams))
24
30
  }
@@ -210,7 +210,7 @@ export const applyNumericalStyle = (elem, property, value) => {
210
210
  value = parseInt(value)
211
211
  }
212
212
  if (value || parseInt(`${value}`) === 0) {
213
- elem.style.setProperty(property, typeof value === 'number' ? `${value}px` : value)
213
+ elem.style.setProperty(property, typeof value === 'number' ? `${value}px` : /** @type {string} */ (value))
214
214
  } else {
215
215
  elem.style.removeProperty(property)
216
216
  }
@@ -305,7 +305,7 @@ export const isScrollable = (elem) => Boolean(elem.scrollHeight > elem.clientHei
305
305
  * @returns {boolean}
306
306
  */
307
307
  export const selfOrParentIsScrollable = (element, stopElement) => {
308
- let parent = element
308
+ let parent = /** @type {HTMLElement | null} */ (element)
309
309
  while (parent && parent !== stopElement) {
310
310
  if (isScrollable(parent)) {
311
311
  return true
@@ -52,44 +52,66 @@ const resetOldContainer = () => {
52
52
  oldContainer.remove()
53
53
  removeClass(
54
54
  [document.documentElement, document.body],
55
- [swalClasses['no-backdrop'], swalClasses['toast-shown'], swalClasses['has-column']]
55
+ [
56
+ swalClasses['no-backdrop'],
57
+ swalClasses['toast-shown'],
58
+ // @ts-ignore: 'has-column' is not defined in swalClasses but may be set dynamically
59
+ swalClasses['has-column'],
60
+ ]
56
61
  )
57
62
 
58
63
  return true
59
64
  }
60
65
 
61
66
  const resetValidationMessage = () => {
62
- globalState.currentInstance.resetValidationMessage()
67
+ if (globalState.currentInstance) {
68
+ globalState.currentInstance.resetValidationMessage()
69
+ }
63
70
  }
64
71
 
65
72
  const addInputChangeListeners = () => {
66
73
  const popup = getPopup()
74
+ if (!popup) {
75
+ return
76
+ }
67
77
 
68
78
  const input = getDirectChildByClass(popup, swalClasses.input)
69
79
  const file = getDirectChildByClass(popup, swalClasses.file)
70
- /** @type {HTMLInputElement} */
80
+ /** @type {HTMLInputElement | null} */
71
81
  const range = popup.querySelector(`.${swalClasses.range} input`)
72
- /** @type {HTMLOutputElement} */
82
+ /** @type {HTMLOutputElement | null} */
73
83
  const rangeOutput = popup.querySelector(`.${swalClasses.range} output`)
74
84
  const select = getDirectChildByClass(popup, swalClasses.select)
75
- /** @type {HTMLInputElement} */
85
+ /** @type {HTMLInputElement | null} */
76
86
  const checkbox = popup.querySelector(`.${swalClasses.checkbox} input`)
77
87
  const textarea = getDirectChildByClass(popup, swalClasses.textarea)
78
88
 
79
- input.oninput = resetValidationMessage
80
- file.onchange = resetValidationMessage
81
- select.onchange = resetValidationMessage
82
- checkbox.onchange = resetValidationMessage
83
- textarea.oninput = resetValidationMessage
84
-
85
- range.oninput = () => {
86
- resetValidationMessage()
87
- rangeOutput.value = range.value
89
+ if (input) {
90
+ input.oninput = resetValidationMessage
91
+ }
92
+ if (file) {
93
+ file.onchange = resetValidationMessage
94
+ }
95
+ if (select) {
96
+ select.onchange = resetValidationMessage
97
+ }
98
+ if (checkbox) {
99
+ checkbox.onchange = resetValidationMessage
88
100
  }
101
+ if (textarea) {
102
+ textarea.oninput = resetValidationMessage
103
+ }
104
+
105
+ if (range && rangeOutput) {
106
+ range.oninput = () => {
107
+ resetValidationMessage()
108
+ rangeOutput.value = range.value
109
+ }
89
110
 
90
- range.onchange = () => {
91
- resetValidationMessage()
92
- rangeOutput.value = range.value
111
+ range.onchange = () => {
112
+ resetValidationMessage()
113
+ rangeOutput.value = range.value
114
+ }
93
115
  }
94
116
  }
95
117
 
@@ -97,13 +119,25 @@ const addInputChangeListeners = () => {
97
119
  * @param {string | HTMLElement} target
98
120
  * @returns {HTMLElement}
99
121
  */
100
- const getTarget = (target) => (typeof target === 'string' ? document.querySelector(target) : target)
122
+ const getTarget = (target) => {
123
+ if (typeof target === 'string') {
124
+ const element = document.querySelector(target)
125
+ if (!element) {
126
+ throw new Error(`Target element "${target}" not found`)
127
+ }
128
+ return /** @type {HTMLElement} */ (element)
129
+ }
130
+ return target
131
+ }
101
132
 
102
133
  /**
103
134
  * @param {SweetAlertOptions} params
104
135
  */
105
136
  const setupAccessibility = (params) => {
106
137
  const popup = getPopup()
138
+ if (!popup) {
139
+ return
140
+ }
107
141
 
108
142
  popup.setAttribute('role', params.toast ? 'alert' : 'dialog')
109
143
  popup.setAttribute('aria-live', params.toast ? 'polite' : 'assertive')
@@ -145,7 +179,7 @@ export const init = (params) => {
145
179
 
146
180
  container.dataset['swal2Theme'] = params.theme
147
181
 
148
- const targetElement = getTarget(params.target)
182
+ const targetElement = getTarget(params.target || 'body')
149
183
  targetElement.appendChild(container)
150
184
 
151
185
  if (params.topLayer) {
@@ -235,5 +235,5 @@ const formatInputOptions = (inputOptions) => {
235
235
  * @returns {boolean}
236
236
  */
237
237
  const isSelected = (optionValue, inputValue) => {
238
- return Boolean(inputValue) && inputValue.toString() === optionValue.toString()
238
+ return Boolean(inputValue) && (inputValue !== null && inputValue !== undefined) && inputValue.toString() === optionValue.toString()
239
239
  }
@@ -27,7 +27,7 @@ export const parseHtmlToContainer = (param, target) => {
27
27
  */
28
28
  const handleObject = (param, target) => {
29
29
  // JQuery element(s)
30
- if (param.jquery) {
30
+ if ('jquery' in param) {
31
31
  handleJqueryElem(target, param)
32
32
  }
33
33
 
@@ -39,7 +39,7 @@ const handleObject = (param, target) => {
39
39
 
40
40
  /**
41
41
  * @param {HTMLElement} target
42
- * @param {object} elem
42
+ * @param {any} elem
43
43
  */
44
44
  const handleJqueryElem = (target, elem) => {
45
45
  target.textContent = ''
@@ -33,5 +33,5 @@ export const render = (instance, params) => {
33
33
  if (typeof params.didRender === 'function' && popup) {
34
34
  params.didRender(popup)
35
35
  }
36
- globalState.eventEmitter.emit('didRender', popup)
36
+ globalState.eventEmitter?.emit('didRender', popup)
37
37
  }
@@ -48,9 +48,15 @@ const getSwalParams = (templateContent) => {
48
48
  if (!paramName || !value) {
49
49
  return
50
50
  }
51
- if (typeof defaultParams[paramName] === 'boolean') {
51
+ if (
52
+ paramName in defaultParams &&
53
+ typeof defaultParams[/** @type {keyof typeof defaultParams} */ (paramName)] === 'boolean'
54
+ ) {
52
55
  result[paramName] = value !== 'false'
53
- } else if (typeof defaultParams[paramName] === 'object') {
56
+ } else if (
57
+ paramName in defaultParams &&
58
+ typeof defaultParams[/** @type {keyof typeof defaultParams} */ (paramName)] === 'object'
59
+ ) {
54
60
  result[paramName] = JSON.parse(value)
55
61
  } else {
56
62
  result[paramName] = value
@@ -97,10 +103,16 @@ const getSwalButtons = (templateContent) => {
97
103
  result[`${type}ButtonText`] = button.innerHTML
98
104
  result[`show${capitalizeFirstLetter(type)}Button`] = true
99
105
  if (button.hasAttribute('color')) {
100
- result[`${type}ButtonColor`] = button.getAttribute('color')
106
+ const color = button.getAttribute('color')
107
+ if (color !== null) {
108
+ result[`${type}ButtonColor`] = color
109
+ }
101
110
  }
102
111
  if (button.hasAttribute('aria-label')) {
103
- result[`${type}ButtonAriaLabel`] = button.getAttribute('aria-label')
112
+ const ariaLabel = button.getAttribute('aria-label')
113
+ if (ariaLabel !== null) {
114
+ result[`${type}ButtonAriaLabel`] = ariaLabel
115
+ }
104
116
  }
105
117
  })
106
118
  return result
@@ -158,7 +170,7 @@ const getSwalIcon = (templateContent) => {
158
170
  * @returns {object}
159
171
  */
160
172
  const getSwalInput = (templateContent) => {
161
- /** @type {object} */
173
+ /** @type {Record<string, any>} */
162
174
  const result = {}
163
175
  /** @type {HTMLElement | null} */
164
176
  const input = templateContent.querySelector('swal-input')