sweetalert2 11.7.11 → 11.7.13

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.
@@ -0,0 +1,235 @@
1
+ // https://stackoverflow.com/a/12335841/1331425
2
+ @function strip-units($number) {
3
+ @return math.div($number, ($number * 0 + 1));
4
+ }
5
+ $icon-zoom: math.div(strip-units($swal2-icon-size), 5);
6
+
7
+ div:where(.swal2-icon) {
8
+ position: relative;
9
+ box-sizing: content-box;
10
+ justify-content: center;
11
+ width: $swal2-icon-size;
12
+ height: $swal2-icon-size;
13
+ margin: $swal2-icon-margin;
14
+ zoom: $swal2-icon-zoom;
15
+ border: #{0.25em * $icon-zoom} solid transparent;
16
+ border-radius: 50%;
17
+ border-color: $swal2-icon-border-color;
18
+ font-family: $swal2-icon-font-family;
19
+ line-height: $swal2-icon-size;
20
+ cursor: default;
21
+ user-select: none;
22
+
23
+ .swal2-icon-content {
24
+ display: flex;
25
+ align-items: center;
26
+ font-size: $swal2-icon-font-size;
27
+ }
28
+
29
+ &.swal2-error {
30
+ border-color: $swal2-error;
31
+ color: $swal2-error;
32
+
33
+ .swal2-x-mark {
34
+ position: relative;
35
+ flex-grow: 1;
36
+
37
+ @if $icon-zoom != 1 {
38
+ zoom: $icon-zoom;
39
+ }
40
+ }
41
+
42
+ [class^='swal2-x-mark-line'] {
43
+ display: block;
44
+ position: absolute;
45
+ top: 2.3125em;
46
+ width: 2.9375em;
47
+ height: 0.3125em;
48
+ border-radius: 0.125em;
49
+ background-color: $swal2-error;
50
+
51
+ &[class$='left'] {
52
+ left: 1.0625em;
53
+ transform: rotate(45deg);
54
+ }
55
+
56
+ &[class$='right'] {
57
+ right: 1em;
58
+ transform: rotate(-45deg);
59
+ }
60
+ }
61
+
62
+ // Error icon animation
63
+ &.swal2-icon-show {
64
+ @if $swal2-icon-animations {
65
+ animation: swal2-animate-error-icon 0.5s;
66
+
67
+ .swal2-x-mark {
68
+ animation: swal2-animate-error-x-mark 0.5s;
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ &.swal2-warning {
75
+ border-color: lighten($swal2-warning, 7);
76
+ color: $swal2-warning;
77
+
78
+ // Warning icon animation
79
+ &.swal2-icon-show {
80
+ @if $swal2-icon-animations {
81
+ animation: swal2-animate-error-icon 0.5s;
82
+
83
+ .swal2-icon-content {
84
+ animation: swal2-animate-i-mark 0.5s;
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ &.swal2-info {
91
+ border-color: lighten($swal2-info, 20);
92
+ color: $swal2-info;
93
+
94
+ // Info icon animation
95
+ &.swal2-icon-show {
96
+ @if $swal2-icon-animations {
97
+ animation: swal2-animate-error-icon 0.5s;
98
+
99
+ .swal2-icon-content {
100
+ animation: swal2-animate-i-mark 0.8s;
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ &.swal2-question {
107
+ border-color: lighten($swal2-question, 20);
108
+ color: $swal2-question;
109
+
110
+ // Question icon animation
111
+ &.swal2-icon-show {
112
+ @if $swal2-icon-animations {
113
+ animation: swal2-animate-error-icon 0.5s;
114
+
115
+ .swal2-icon-content {
116
+ animation: swal2-animate-question-mark 0.8s;
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ &.swal2-success {
123
+ border-color: $swal2-success;
124
+ color: $swal2-success;
125
+
126
+ [class^='swal2-success-circular-line'] {
127
+ // Emulate moving circular line
128
+ position: absolute;
129
+ width: 3.75em;
130
+ height: 7.5em;
131
+ transform: rotate(45deg);
132
+ border-radius: 50%;
133
+
134
+ &[class$='left'] {
135
+ top: -0.4375em;
136
+ left: -2.0635em;
137
+ transform: rotate(-45deg);
138
+ transform-origin: 3.75em 3.75em;
139
+ border-radius: 7.5em 0 0 7.5em;
140
+
141
+ @if $icon-zoom != 1 {
142
+ zoom: $icon-zoom;
143
+ }
144
+ }
145
+
146
+ &[class$='right'] {
147
+ top: -0.6875em;
148
+ left: 1.875em;
149
+ transform: rotate(-45deg);
150
+ transform-origin: 0 3.75em;
151
+ border-radius: 0 7.5em 7.5em 0;
152
+
153
+ @if $icon-zoom != 1 {
154
+ zoom: $icon-zoom;
155
+ }
156
+ }
157
+ }
158
+
159
+ .swal2-success-ring {
160
+ // Ring
161
+ position: absolute;
162
+ z-index: 2;
163
+ top: -0.25em;
164
+ left: -0.25em;
165
+ box-sizing: content-box;
166
+ width: 100%;
167
+ height: 100%;
168
+ border: 0.25em solid $swal2-success-border;
169
+ border-radius: 50%;
170
+
171
+ @if $icon-zoom != 1 {
172
+ zoom: $icon-zoom;
173
+ }
174
+ }
175
+
176
+ .swal2-success-fix {
177
+ // Hide corners left from animation
178
+ position: absolute;
179
+ z-index: 1;
180
+ top: 0.5em;
181
+ left: 1.625em;
182
+ width: 0.4375em;
183
+ height: 5.625em;
184
+ transform: rotate(-45deg);
185
+
186
+ @if $icon-zoom != 1 {
187
+ zoom: $icon-zoom;
188
+ }
189
+ }
190
+
191
+ [class^='swal2-success-line'] {
192
+ display: block;
193
+ position: absolute;
194
+ z-index: 2;
195
+ height: 0.3125em;
196
+ border-radius: 0.125em;
197
+ background-color: $swal2-success;
198
+
199
+ &[class$='tip'] {
200
+ top: 2.875em;
201
+ left: 0.8125em;
202
+ width: 1.5625em;
203
+ transform: rotate(45deg);
204
+ }
205
+
206
+ &[class$='long'] {
207
+ top: 2.375em;
208
+ right: 0.5em;
209
+ width: 2.9375em;
210
+ transform: rotate(-45deg);
211
+ }
212
+
213
+ @if $icon-zoom != 1 {
214
+ zoom: $icon-zoom;
215
+ }
216
+ }
217
+
218
+ // Success icon animation
219
+ &.swal2-icon-show {
220
+ @if $swal2-icon-animations {
221
+ .swal2-success-line-tip {
222
+ animation: swal2-animate-success-line-tip 0.75s;
223
+ }
224
+
225
+ .swal2-success-line-long {
226
+ animation: swal2-animate-success-line-long 0.75s;
227
+ }
228
+
229
+ .swal2-success-circular-line-right {
230
+ animation: swal2-rotate-success-circular-line 4.25s ease-in;
231
+ }
232
+ }
233
+ }
234
+ }
235
+ }
@@ -72,5 +72,5 @@ export const increaseTimer = (n) => {
72
72
  * @returns {boolean}
73
73
  */
74
74
  export const isTimerRunning = () => {
75
- return globalState.timeout && globalState.timeout.isRunning()
75
+ return !!(globalState.timeout && globalState.timeout.isRunning())
76
76
  }
package/src/utils/aria.js CHANGED
@@ -13,7 +13,7 @@ export const setAriaHidden = () => {
13
13
  }
14
14
 
15
15
  if (el.hasAttribute('aria-hidden')) {
16
- el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden'))
16
+ el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden') || '')
17
17
  }
18
18
  el.setAttribute('aria-hidden', 'true')
19
19
  })
@@ -23,7 +23,7 @@ export const unsetAriaHidden = () => {
23
23
  const bodyChildren = Array.from(document.body.children)
24
24
  bodyChildren.forEach((el) => {
25
25
  if (el.hasAttribute('data-previous-aria-hidden')) {
26
- el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden'))
26
+ el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden') || '')
27
27
  el.removeAttribute('data-previous-aria-hidden')
28
28
  } else {
29
29
  el.removeAttribute('aria-hidden')
@@ -128,7 +128,7 @@ export const focusInput = (input) => {
128
128
 
129
129
  /**
130
130
  * @param {HTMLElement | HTMLElement[] | null} target
131
- * @param {string | string[] | readonly string[]} classList
131
+ * @param {string | string[] | readonly string[] | undefined} classList
132
132
  * @param {boolean} condition
133
133
  */
134
134
  export const toggleClass = (target, classList, condition) => {
@@ -151,7 +151,7 @@ export const toggleClass = (target, classList, condition) => {
151
151
 
152
152
  /**
153
153
  * @param {HTMLElement | HTMLElement[] | null} target
154
- * @param {string | string[] | readonly string[]} classList
154
+ * @param {string | string[] | readonly string[] | undefined} classList
155
155
  */
156
156
  export const addClass = (target, classList) => {
157
157
  toggleClass(target, classList, true)
@@ -159,7 +159,7 @@ export const addClass = (target, classList) => {
159
159
 
160
160
  /**
161
161
  * @param {HTMLElement | HTMLElement[] | null} target
162
- * @param {string | string[] | readonly string[]} classList
162
+ * @param {string | string[] | readonly string[] | undefined} classList
163
163
  */
164
164
  export const removeClass = (target, classList) => {
165
165
  toggleClass(target, classList, false)
@@ -134,15 +134,17 @@ const focusable = `
134
134
  * @returns {HTMLElement[]}
135
135
  */
136
136
  export const getFocusableElements = () => {
137
+ const popup = getPopup()
138
+ if (!popup) {
139
+ return []
140
+ }
137
141
  /** @type {NodeListOf<HTMLElement>} */
138
- const focusableElementsWithTabindex = getPopup().querySelectorAll(
139
- '[tabindex]:not([tabindex="-1"]):not([tabindex="0"])'
140
- )
142
+ const focusableElementsWithTabindex = popup.querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')
141
143
  const focusableElementsWithTabindexSorted = Array.from(focusableElementsWithTabindex)
142
144
  // sort according to tabindex
143
145
  .sort((a, b) => {
144
- const tabindexA = parseInt(a.getAttribute('tabindex'))
145
- const tabindexB = parseInt(b.getAttribute('tabindex'))
146
+ const tabindexA = parseInt(a.getAttribute('tabindex') || '0')
147
+ const tabindexB = parseInt(b.getAttribute('tabindex') || '0')
146
148
  if (tabindexA > tabindexB) {
147
149
  return 1
148
150
  } else if (tabindexA < tabindexB) {
@@ -152,7 +154,7 @@ export const getFocusableElements = () => {
152
154
  })
153
155
 
154
156
  /** @type {NodeListOf<HTMLElement>} */
155
- const otherFocusableElements = getPopup().querySelectorAll(focusable)
157
+ const otherFocusableElements = popup.querySelectorAll(focusable)
156
158
  const otherFocusableElementsFiltered = Array.from(otherFocusableElements).filter(
157
159
  (el) => el.getAttribute('tabindex') !== '-1'
158
160
  )
@@ -177,12 +179,20 @@ export const isModal = () => {
177
179
  * @returns {boolean}
178
180
  */
179
181
  export const isToast = () => {
180
- return getPopup() && hasClass(getPopup(), swalClasses.toast)
182
+ const popup = getPopup()
183
+ if (!popup) {
184
+ return false
185
+ }
186
+ return hasClass(popup, swalClasses.toast)
181
187
  }
182
188
 
183
189
  /**
184
190
  * @returns {boolean}
185
191
  */
186
192
  export const isLoading = () => {
187
- return getPopup().hasAttribute('data-loading')
193
+ const popup = getPopup()
194
+ if (!popup) {
195
+ return false
196
+ }
197
+ return popup.hasAttribute('data-loading')
188
198
  }
@@ -13,19 +13,19 @@ const sweetHTML = `
13
13
  <img class="${swalClasses.image}" />
14
14
  <h2 class="${swalClasses.title}" id="${swalClasses.title}"></h2>
15
15
  <div class="${swalClasses['html-container']}" id="${swalClasses['html-container']}"></div>
16
- <input class="${swalClasses.input}" />
16
+ <input class="${swalClasses.input}" id="${swalClasses.input}" />
17
17
  <input type="file" class="${swalClasses.file}" />
18
18
  <div class="${swalClasses.range}">
19
19
  <input type="range" />
20
20
  <output></output>
21
21
  </div>
22
- <select class="${swalClasses.select}"></select>
22
+ <select class="${swalClasses.select}" id="${swalClasses.select}"></select>
23
23
  <div class="${swalClasses.radio}"></div>
24
- <label for="${swalClasses.checkbox}" class="${swalClasses.checkbox}">
25
- <input type="checkbox" />
24
+ <label class="${swalClasses.checkbox}">
25
+ <input type="checkbox" id="${swalClasses.checkbox}" />
26
26
  <span class="${swalClasses.label}"></span>
27
27
  </label>
28
- <textarea class="${swalClasses.textarea}"></textarea>
28
+ <textarea class="${swalClasses.textarea}" id="${swalClasses.textarea}"></textarea>
29
29
  <div class="${swalClasses['validation-message']}" id="${swalClasses['validation-message']}"></div>
30
30
  <div class="${swalClasses.actions}">
31
31
  <div class="${swalClasses.loader}"></div>
@@ -22,7 +22,7 @@ export const parseHtmlToContainer = (param, target) => {
22
22
  }
23
23
 
24
24
  /**
25
- * @param {object} param
25
+ * @param {any} param
26
26
  * @param {HTMLElement} target
27
27
  */
28
28
  const handleObject = (param, target) => {
@@ -39,7 +39,7 @@ const handleObject = (param, target) => {
39
39
 
40
40
  /**
41
41
  * @param {HTMLElement} target
42
- * @param {HTMLElement} elem
42
+ * @param {any} elem
43
43
  */
44
44
  const handleJqueryElem = (target, elem) => {
45
45
  target.textContent = ''
@@ -28,7 +28,8 @@ export const render = (instance, params) => {
28
28
  renderActions(instance, params)
29
29
  renderFooter(instance, params)
30
30
 
31
- if (typeof params.didRender === 'function') {
32
- params.didRender(getPopup())
31
+ const popup = getPopup()
32
+ if (typeof params.didRender === 'function' && popup) {
33
+ params.didRender(popup)
33
34
  }
34
35
  }
@@ -9,6 +9,9 @@ import { capitalizeFirstLetter } from '../../utils.js'
9
9
  export const renderActions = (instance, params) => {
10
10
  const actions = dom.getActions()
11
11
  const loader = dom.getLoader()
12
+ if (!actions || !loader) {
13
+ return
14
+ }
12
15
 
13
16
  // Actions (buttons) wrapper
14
17
  if (!params.showConfirmButton && !params.showDenyButton && !params.showCancelButton) {
@@ -24,7 +27,7 @@ export const renderActions = (instance, params) => {
24
27
  renderButtons(actions, loader, params)
25
28
 
26
29
  // Loader
27
- dom.setInnerHtml(loader, params.loaderHtml)
30
+ dom.setInnerHtml(loader, params.loaderHtml || '')
28
31
  dom.applyCustomClass(loader, params, 'loader')
29
32
  }
30
33
 
@@ -37,6 +40,9 @@ function renderButtons(actions, loader, params) {
37
40
  const confirmButton = dom.getConfirmButton()
38
41
  const denyButton = dom.getDenyButton()
39
42
  const cancelButton = dom.getCancelButton()
43
+ if (!confirmButton || !denyButton || !cancelButton) {
44
+ return
45
+ }
40
46
 
41
47
  // Render buttons
42
48
  renderButton(confirmButton, 'confirm', params)
@@ -91,12 +97,13 @@ function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) {
91
97
  * @param {SweetAlertOptions} params
92
98
  */
93
99
  function renderButton(button, buttonType, params) {
94
- dom.toggle(button, params[`show${capitalizeFirstLetter(buttonType)}Button`], 'inline-block')
95
- dom.setInnerHtml(button, params[`${buttonType}ButtonText`]) // Set caption text
96
- button.setAttribute('aria-label', params[`${buttonType}ButtonAriaLabel`]) // ARIA label
100
+ const buttonName = /** @type {'Confirm' | 'Deny' | 'Cancel'} */ (capitalizeFirstLetter(buttonType))
101
+
102
+ dom.toggle(button, params[`show${buttonName}Button`], 'inline-block')
103
+ dom.setInnerHtml(button, params[`${buttonType}ButtonText`] || '') // Set caption text
104
+ button.setAttribute('aria-label', params[`${buttonType}ButtonAriaLabel`] || '') // ARIA label
97
105
 
98
106
  // Add buttons custom classes
99
107
  button.className = swalClasses[buttonType]
100
108
  dom.applyCustomClass(button, params, `${buttonType}Button`)
101
- dom.addClass(button, params[`${buttonType}ButtonClass`])
102
109
  }
@@ -39,6 +39,9 @@ function handleBackdropParam(container, backdrop) {
39
39
  * @param {SweetAlertOptions['position']} position
40
40
  */
41
41
  function handlePositionParam(container, position) {
42
+ if (!position) {
43
+ return
44
+ }
42
45
  if (position in swalClasses) {
43
46
  dom.addClass(container, swalClasses[position])
44
47
  } else {
@@ -52,10 +55,8 @@ function handlePositionParam(container, position) {
52
55
  * @param {SweetAlertOptions['grow']} grow
53
56
  */
54
57
  function handleGrowParam(container, grow) {
55
- if (grow && typeof grow === 'string') {
56
- const growClass = `grow-${grow}`
57
- if (growClass in swalClasses) {
58
- dom.addClass(container, swalClasses[growClass])
59
- }
58
+ if (!grow) {
59
+ return
60
60
  }
61
+ dom.addClass(container, swalClasses[`grow-${grow}`])
61
62
  }
@@ -10,6 +10,9 @@ import { error } from '../../utils.js'
10
10
  export const renderIcon = (instance, params) => {
11
11
  const innerParams = privateProps.innerParams.get(instance)
12
12
  const icon = dom.getIcon()
13
+ if (!icon) {
14
+ return
15
+ }
13
16
 
14
17
  // if the given icon already rendered, apply the styling without re-rendering the icon
15
18
  if (innerParams && params.icon === innerParams.icon) {
@@ -39,7 +42,7 @@ export const renderIcon = (instance, params) => {
39
42
  applyStyles(icon, params)
40
43
 
41
44
  // Animate icon
42
- dom.addClass(icon, params.showClass.icon)
45
+ dom.addClass(icon, params.showClass && params.showClass.icon)
43
46
  }
44
47
 
45
48
  /**
@@ -47,12 +50,12 @@ export const renderIcon = (instance, params) => {
47
50
  * @param {SweetAlertOptions} params
48
51
  */
49
52
  const applyStyles = (icon, params) => {
50
- for (const iconType in iconTypes) {
53
+ for (const [iconType, iconClassName] of Object.entries(iconTypes)) {
51
54
  if (params.icon !== iconType) {
52
- dom.removeClass(icon, iconTypes[iconType])
55
+ dom.removeClass(icon, iconClassName)
53
56
  }
54
57
  }
55
- dom.addClass(icon, iconTypes[params.icon])
58
+ dom.addClass(icon, params.icon && iconTypes[params.icon])
56
59
 
57
60
  // Icon color
58
61
  setColor(icon, params)
@@ -67,6 +70,9 @@ const applyStyles = (icon, params) => {
67
70
  // Adjust success icon background color to match the popup background color
68
71
  const adjustSuccessIconBackgroundColor = () => {
69
72
  const popup = dom.getPopup()
73
+ if (!popup) {
74
+ return
75
+ }
70
76
  const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color')
71
77
  /** @type {NodeListOf<HTMLElement>} */
72
78
  const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix')
@@ -94,6 +100,9 @@ const errorIconHtml = `
94
100
  * @param {SweetAlertOptions} params
95
101
  */
96
102
  const setContent = (icon, params) => {
103
+ if (!params.icon) {
104
+ return
105
+ }
97
106
  let oldContent = icon.innerHTML
98
107
  let newContent
99
108
  if (params.iconHtml) {
package/sweetalert2.d.ts CHANGED
@@ -668,6 +668,7 @@ declare module 'sweetalert2' {
668
668
  * closeButton: '...',
669
669
  * icon: '...',
670
670
  * image: '...',
671
+ * htmlContainer: '...',
671
672
  * input: '...',
672
673
  * inputLabel: '...',
673
674
  * validationMessage: '...',