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/dist/sweetalert2.all.js +122 -86
- package/dist/sweetalert2.all.min.js +2 -2
- package/dist/sweetalert2.js +122 -86
- package/dist/sweetalert2.min.js +2 -2
- package/package.json +3 -3
- package/src/SweetAlert.js +1 -1
- package/src/buttons-handlers.js +2 -1
- package/src/instanceMethods/enable-disable-elements.js +11 -4
- package/src/staticMethods/showLoading.js +9 -3
- package/src/utils/dom/domUtils.js +7 -1
- package/src/utils/dom/inputUtils.js +90 -74
- package/sweetalert2.d.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sweetalert2",
|
|
3
|
-
"version": "11.7.
|
|
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.
|
|
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
|
-
"
|
|
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
package/src/buttons-handlers.js
CHANGED
|
@@ -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 (!
|
|
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
|
-
|
|
22
|
+
const popup = dom.getPopup()
|
|
23
|
+
if (!popup || !input) {
|
|
21
24
|
return
|
|
22
25
|
}
|
|
23
26
|
if (input.type === 'radio') {
|
|
24
|
-
|
|
25
|
-
const radios =
|
|
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'].
|
|
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
|
-
|
|
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
|
-
|
|
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}
|
|
119
|
-
* @param {
|
|
120
|
-
* @param {
|
|
137
|
+
* @param {HTMLElement} parent
|
|
138
|
+
* @param {string} optionLabel
|
|
139
|
+
* @param {string} optionValue
|
|
121
140
|
*/
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
* @
|
|
208
|
+
* @typedef {string[]} InputOptionFlattened
|
|
209
|
+
* @returns {InputOptionFlattened[]}
|
|
195
210
|
*/
|
|
196
211
|
const formatInputOptions = (inputOptions) => {
|
|
212
|
+
/** @type {InputOptionFlattened[]} */
|
|
197
213
|
const result = []
|
|
198
|
-
if (
|
|
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.
|