@openeuropa/bcl-bootstrap 0.25.1 → 0.26.0

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.
Files changed (142) hide show
  1. package/bootstrap-icons.svg +1 -1
  2. package/icons/apple.svg +2 -2
  3. package/icons/boombox-fill.svg +2 -2
  4. package/icons/cup-fill.svg +1 -1
  5. package/icons/cup.svg +1 -1
  6. package/js/dist/alert.js +3 -12
  7. package/js/dist/alert.js.map +1 -1
  8. package/js/dist/base-component.js +32 -18
  9. package/js/dist/base-component.js.map +1 -1
  10. package/js/dist/button.js +3 -12
  11. package/js/dist/button.js.map +1 -1
  12. package/js/dist/carousel.js +207 -307
  13. package/js/dist/carousel.js.map +1 -1
  14. package/js/dist/collapse.js +57 -88
  15. package/js/dist/collapse.js.map +1 -1
  16. package/js/dist/dom/data.js +1 -3
  17. package/js/dist/dom/data.js.map +1 -1
  18. package/js/dist/dom/event-handler.js +87 -106
  19. package/js/dist/dom/event-handler.js.map +1 -1
  20. package/js/dist/dom/manipulator.js +21 -25
  21. package/js/dist/dom/manipulator.js.map +1 -1
  22. package/js/dist/dom/selector-engine.js +11 -10
  23. package/js/dist/dom/selector-engine.js.map +1 -1
  24. package/js/dist/dropdown.js +83 -115
  25. package/js/dist/dropdown.js.map +1 -1
  26. package/js/dist/modal.js +95 -152
  27. package/js/dist/modal.js.map +1 -1
  28. package/js/dist/offcanvas.js +75 -58
  29. package/js/dist/offcanvas.js.map +1 -1
  30. package/js/dist/popover.js +29 -56
  31. package/js/dist/popover.js.map +1 -1
  32. package/js/dist/scrollspy.js +176 -125
  33. package/js/dist/scrollspy.js.map +1 -1
  34. package/js/dist/tab.js +207 -92
  35. package/js/dist/tab.js.map +1 -1
  36. package/js/dist/toast.js +23 -37
  37. package/js/dist/toast.js.map +1 -1
  38. package/js/dist/tooltip.js +259 -348
  39. package/js/dist/tooltip.js.map +1 -1
  40. package/js/dist/util/backdrop.js +62 -39
  41. package/js/dist/util/backdrop.js.map +1 -1
  42. package/js/dist/util/component-functions.js +1 -1
  43. package/js/dist/util/component-functions.js.map +1 -1
  44. package/js/dist/util/config.js +75 -0
  45. package/js/dist/util/config.js.map +1 -0
  46. package/js/dist/util/focustrap.js +41 -34
  47. package/js/dist/util/focustrap.js.map +1 -1
  48. package/js/dist/util/index.js +56 -52
  49. package/js/dist/util/index.js.map +1 -1
  50. package/js/dist/util/sanitizer.js +12 -19
  51. package/js/dist/util/sanitizer.js.map +1 -1
  52. package/js/dist/util/scrollbar.js +49 -34
  53. package/js/dist/util/scrollbar.js.map +1 -1
  54. package/js/dist/util/swipe.js +151 -0
  55. package/js/dist/util/swipe.js.map +1 -0
  56. package/js/dist/util/template-factory.js +173 -0
  57. package/js/dist/util/template-factory.js.map +1 -0
  58. package/js/src/alert.js +3 -15
  59. package/js/src/base-component.js +28 -18
  60. package/js/src/button.js +3 -17
  61. package/js/src/carousel.js +203 -319
  62. package/js/src/collapse.js +61 -94
  63. package/js/src/dom/data.js +1 -3
  64. package/js/src/dom/event-handler.js +80 -108
  65. package/js/src/dom/manipulator.js +22 -31
  66. package/js/src/dom/selector-engine.js +10 -19
  67. package/js/src/dropdown.js +84 -138
  68. package/js/src/modal.js +94 -158
  69. package/js/src/offcanvas.js +72 -61
  70. package/js/src/popover.js +31 -62
  71. package/js/src/scrollspy.js +166 -171
  72. package/js/src/tab.js +193 -110
  73. package/js/src/toast.js +19 -41
  74. package/js/src/tooltip.js +259 -371
  75. package/js/src/util/backdrop.js +55 -36
  76. package/js/src/util/component-functions.js +1 -1
  77. package/js/src/util/config.js +66 -0
  78. package/js/src/util/focustrap.js +38 -28
  79. package/js/src/util/index.js +67 -64
  80. package/js/src/util/sanitizer.js +11 -19
  81. package/js/src/util/scrollbar.js +47 -30
  82. package/js/src/util/swipe.js +146 -0
  83. package/js/src/util/template-factory.js +160 -0
  84. package/package.json +4 -4
  85. package/scss/_accordion.scss +52 -24
  86. package/scss/_alert.scss +18 -4
  87. package/scss/_badge.scss +14 -5
  88. package/scss/_breadcrumb.scss +22 -10
  89. package/scss/_button-group.scss +3 -0
  90. package/scss/_buttons.scss +97 -22
  91. package/scss/_card.scss +55 -37
  92. package/scss/_close.scss +1 -1
  93. package/scss/_containers.scss +1 -1
  94. package/scss/_dropdown.scss +83 -75
  95. package/scss/_functions.scss +7 -7
  96. package/scss/_grid.scss +3 -3
  97. package/scss/_helpers.scss +1 -0
  98. package/scss/_list-group.scss +44 -27
  99. package/scss/_maps.scss +54 -0
  100. package/scss/_modal.scss +71 -43
  101. package/scss/_nav.scss +53 -20
  102. package/scss/_navbar.scss +91 -150
  103. package/scss/_offcanvas.scss +119 -59
  104. package/scss/_pagination.scss +66 -21
  105. package/scss/_placeholders.scss +1 -1
  106. package/scss/_popover.scss +90 -52
  107. package/scss/_progress.scss +20 -9
  108. package/scss/_reboot.scss +25 -40
  109. package/scss/_root.scss +40 -21
  110. package/scss/_spinners.scss +38 -22
  111. package/scss/_tables.scss +32 -23
  112. package/scss/_toasts.scss +35 -16
  113. package/scss/_tooltip.scss +61 -56
  114. package/scss/_type.scss +2 -0
  115. package/scss/_utilities.scss +43 -26
  116. package/scss/_variables.scss +113 -121
  117. package/scss/bootstrap-grid.scss +3 -6
  118. package/scss/bootstrap-reboot.scss +3 -7
  119. package/scss/bootstrap-utilities.scss +3 -6
  120. package/scss/bootstrap.scss +4 -6
  121. package/scss/forms/_floating-labels.scss +14 -3
  122. package/scss/forms/_form-check.scss +28 -5
  123. package/scss/forms/_form-control.scss +12 -37
  124. package/scss/forms/_form-select.scss +0 -1
  125. package/scss/forms/_input-group.scss +15 -7
  126. package/scss/helpers/_color-bg.scss +10 -0
  127. package/scss/helpers/_colored-links.scss +2 -2
  128. package/scss/helpers/_position.scss +7 -1
  129. package/scss/helpers/_ratio.scss +2 -2
  130. package/scss/helpers/_vr.scss +1 -1
  131. package/scss/mixins/_alert.scss +7 -3
  132. package/scss/mixins/_banner.scss +9 -0
  133. package/scss/mixins/_breakpoints.scss +8 -8
  134. package/scss/mixins/_buttons.scss +32 -95
  135. package/scss/mixins/_container.scss +4 -2
  136. package/scss/mixins/_forms.scss +8 -0
  137. package/scss/mixins/_gradients.scss +1 -1
  138. package/scss/mixins/_grid.scss +12 -12
  139. package/scss/mixins/_pagination.scss +4 -25
  140. package/scss/mixins/_reset-text.scss +1 -1
  141. package/scss/mixins/_table-variants.scss +12 -9
  142. package/scss/mixins/_utilities.scss +12 -4
@@ -1,41 +1,65 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * Bootstrap (v5.1.3): util/backdrop.js
3
+ * Bootstrap (v5.2.0): util/backdrop.js
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  * --------------------------------------------------------------------------
6
6
  */
7
7
 
8
8
  import EventHandler from '../dom/event-handler'
9
- import { execute, executeAfterTransition, getElement, reflow, typeCheckConfig } from './index'
9
+ import { execute, executeAfterTransition, getElement, reflow } from './index'
10
+ import Config from './config'
11
+
12
+ /**
13
+ * Constants
14
+ */
15
+
16
+ const NAME = 'backdrop'
17
+ const CLASS_NAME_FADE = 'fade'
18
+ const CLASS_NAME_SHOW = 'show'
19
+ const EVENT_MOUSEDOWN = `mousedown.bs.${NAME}`
10
20
 
11
21
  const Default = {
12
22
  className: 'modal-backdrop',
13
- isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
23
+ clickCallback: null,
14
24
  isAnimated: false,
15
- rootElement: 'body', // give the choice to place backdrop under different elements
16
- clickCallback: null
25
+ isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
26
+ rootElement: 'body' // give the choice to place backdrop under different elements
17
27
  }
18
28
 
19
29
  const DefaultType = {
20
30
  className: 'string',
21
- isVisible: 'boolean',
31
+ clickCallback: '(function|null)',
22
32
  isAnimated: 'boolean',
23
- rootElement: '(element|string)',
24
- clickCallback: '(function|null)'
33
+ isVisible: 'boolean',
34
+ rootElement: '(element|string)'
25
35
  }
26
- const NAME = 'backdrop'
27
- const CLASS_NAME_FADE = 'fade'
28
- const CLASS_NAME_SHOW = 'show'
29
36
 
30
- const EVENT_MOUSEDOWN = `mousedown.bs.${NAME}`
37
+ /**
38
+ * Class definition
39
+ */
31
40
 
32
- class Backdrop {
41
+ class Backdrop extends Config {
33
42
  constructor(config) {
43
+ super()
34
44
  this._config = this._getConfig(config)
35
45
  this._isAppended = false
36
46
  this._element = null
37
47
  }
38
48
 
49
+ // Getters
50
+ static get Default() {
51
+ return Default
52
+ }
53
+
54
+ static get DefaultType() {
55
+ return DefaultType
56
+ }
57
+
58
+ static get NAME() {
59
+ return NAME
60
+ }
61
+
62
+ // Public
39
63
  show(callback) {
40
64
  if (!this._config.isVisible) {
41
65
  execute(callback)
@@ -44,11 +68,12 @@ class Backdrop {
44
68
 
45
69
  this._append()
46
70
 
71
+ const element = this._getElement()
47
72
  if (this._config.isAnimated) {
48
- reflow(this._getElement())
73
+ reflow(element)
49
74
  }
50
75
 
51
- this._getElement().classList.add(CLASS_NAME_SHOW)
76
+ element.classList.add(CLASS_NAME_SHOW)
52
77
 
53
78
  this._emulateAnimation(() => {
54
79
  execute(callback)
@@ -69,8 +94,18 @@ class Backdrop {
69
94
  })
70
95
  }
71
96
 
72
- // Private
97
+ dispose() {
98
+ if (!this._isAppended) {
99
+ return
100
+ }
101
+
102
+ EventHandler.off(this._element, EVENT_MOUSEDOWN)
73
103
 
104
+ this._element.remove()
105
+ this._isAppended = false
106
+ }
107
+
108
+ // Private
74
109
  _getElement() {
75
110
  if (!this._element) {
76
111
  const backdrop = document.createElement('div')
@@ -85,15 +120,9 @@ class Backdrop {
85
120
  return this._element
86
121
  }
87
122
 
88
- _getConfig(config) {
89
- config = {
90
- ...Default,
91
- ...(typeof config === 'object' ? config : {})
92
- }
93
-
123
+ _configAfterMerge(config) {
94
124
  // use getElement() with the default "body" to get a fresh Element on each instantiation
95
125
  config.rootElement = getElement(config.rootElement)
96
- typeCheckConfig(NAME, config, DefaultType)
97
126
  return config
98
127
  }
99
128
 
@@ -102,26 +131,16 @@ class Backdrop {
102
131
  return
103
132
  }
104
133
 
105
- this._config.rootElement.append(this._getElement())
134
+ const element = this._getElement()
135
+ this._config.rootElement.append(element)
106
136
 
107
- EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => {
137
+ EventHandler.on(element, EVENT_MOUSEDOWN, () => {
108
138
  execute(this._config.clickCallback)
109
139
  })
110
140
 
111
141
  this._isAppended = true
112
142
  }
113
143
 
114
- dispose() {
115
- if (!this._isAppended) {
116
- return
117
- }
118
-
119
- EventHandler.off(this._element, EVENT_MOUSEDOWN)
120
-
121
- this._element.remove()
122
- this._isAppended = false
123
- }
124
-
125
144
  _emulateAnimation(callback) {
126
145
  executeAfterTransition(callback, this._getElement(), this._config.isAnimated)
127
146
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * Bootstrap (v5.1.3): util/component-functions.js
3
+ * Bootstrap (v5.2.0): util/component-functions.js
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  * --------------------------------------------------------------------------
6
6
  */
@@ -0,0 +1,66 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * Bootstrap (v5.2.0): util/config.js
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import { isElement, toType } from './index'
9
+ import Manipulator from '../dom/manipulator'
10
+
11
+ /**
12
+ * Class definition
13
+ */
14
+
15
+ class Config {
16
+ // Getters
17
+ static get Default() {
18
+ return {}
19
+ }
20
+
21
+ static get DefaultType() {
22
+ return {}
23
+ }
24
+
25
+ static get NAME() {
26
+ throw new Error('You have to implement the static method "NAME", for each component!')
27
+ }
28
+
29
+ _getConfig(config) {
30
+ config = this._mergeConfigObj(config)
31
+ config = this._configAfterMerge(config)
32
+ this._typeCheckConfig(config)
33
+ return config
34
+ }
35
+
36
+ _configAfterMerge(config) {
37
+ return config
38
+ }
39
+
40
+ _mergeConfigObj(config, element) {
41
+ const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {} // try to parse
42
+
43
+ return {
44
+ ...this.constructor.Default,
45
+ ...(typeof jsonConfig === 'object' ? jsonConfig : {}),
46
+ ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),
47
+ ...(typeof config === 'object' ? config : {})
48
+ }
49
+ }
50
+
51
+ _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {
52
+ for (const property of Object.keys(configTypes)) {
53
+ const expectedTypes = configTypes[property]
54
+ const value = config[property]
55
+ const valueType = isElement(value) ? 'element' : toType(value)
56
+
57
+ if (!new RegExp(expectedTypes).test(valueType)) {
58
+ throw new TypeError(
59
+ `${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
60
+ )
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ export default Config
@@ -1,23 +1,17 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * Bootstrap (v5.1.3): util/focustrap.js
3
+ * Bootstrap (v5.2.0): util/focustrap.js
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  * --------------------------------------------------------------------------
6
6
  */
7
7
 
8
8
  import EventHandler from '../dom/event-handler'
9
9
  import SelectorEngine from '../dom/selector-engine'
10
- import { typeCheckConfig } from './index'
10
+ import Config from './config'
11
11
 
12
- const Default = {
13
- trapElement: null, // The element to trap focus inside of
14
- autofocus: true
15
- }
16
-
17
- const DefaultType = {
18
- trapElement: 'element',
19
- autofocus: 'boolean'
20
- }
12
+ /**
13
+ * Constants
14
+ */
21
15
 
22
16
  const NAME = 'focustrap'
23
17
  const DATA_KEY = 'bs.focustrap'
@@ -29,22 +23,49 @@ const TAB_KEY = 'Tab'
29
23
  const TAB_NAV_FORWARD = 'forward'
30
24
  const TAB_NAV_BACKWARD = 'backward'
31
25
 
32
- class FocusTrap {
26
+ const Default = {
27
+ autofocus: true,
28
+ trapElement: null // The element to trap focus inside of
29
+ }
30
+
31
+ const DefaultType = {
32
+ autofocus: 'boolean',
33
+ trapElement: 'element'
34
+ }
35
+
36
+ /**
37
+ * Class definition
38
+ */
39
+
40
+ class FocusTrap extends Config {
33
41
  constructor(config) {
42
+ super()
34
43
  this._config = this._getConfig(config)
35
44
  this._isActive = false
36
45
  this._lastTabNavDirection = null
37
46
  }
38
47
 
39
- activate() {
40
- const { trapElement, autofocus } = this._config
48
+ // Getters
49
+ static get Default() {
50
+ return Default
51
+ }
52
+
53
+ static get DefaultType() {
54
+ return DefaultType
55
+ }
56
+
57
+ static get NAME() {
58
+ return NAME
59
+ }
41
60
 
61
+ // Public
62
+ activate() {
42
63
  if (this._isActive) {
43
64
  return
44
65
  }
45
66
 
46
- if (autofocus) {
47
- trapElement.focus()
67
+ if (this._config.autofocus) {
68
+ this._config.trapElement.focus()
48
69
  }
49
70
 
50
71
  EventHandler.off(document, EVENT_KEY) // guard against infinite focus loop
@@ -64,12 +85,10 @@ class FocusTrap {
64
85
  }
65
86
 
66
87
  // Private
67
-
68
88
  _handleFocusin(event) {
69
- const { target } = event
70
89
  const { trapElement } = this._config
71
90
 
72
- if (target === document || target === trapElement || trapElement.contains(target)) {
91
+ if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) {
73
92
  return
74
93
  }
75
94
 
@@ -91,15 +110,6 @@ class FocusTrap {
91
110
 
92
111
  this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD
93
112
  }
94
-
95
- _getConfig(config) {
96
- config = {
97
- ...Default,
98
- ...(typeof config === 'object' ? config : {})
99
- }
100
- typeCheckConfig(NAME, config, DefaultType)
101
- return config
102
- }
103
113
  }
104
114
 
105
115
  export default FocusTrap
@@ -1,27 +1,25 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * Bootstrap (v5.1.3): util/index.js
3
+ * Bootstrap (v5.2.0): util/index.js
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  * --------------------------------------------------------------------------
6
6
  */
7
7
 
8
- const MAX_UID = 1000000
8
+ const MAX_UID = 1_000_000
9
9
  const MILLISECONDS_MULTIPLIER = 1000
10
10
  const TRANSITION_END = 'transitionend'
11
11
 
12
- // Shoutout AngusCroll (https://goo.gl/pxwQGp)
13
- const toType = obj => {
14
- if (obj === null || obj === undefined) {
15
- return `${obj}`
12
+ // Shout-out Angus Croll (https://goo.gl/pxwQGp)
13
+ const toType = object => {
14
+ if (object === null || object === undefined) {
15
+ return `${object}`
16
16
  }
17
17
 
18
- return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase()
18
+ return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase()
19
19
  }
20
20
 
21
21
  /**
22
- * --------------------------------------------------------------------------
23
- * Public Util Api
24
- * --------------------------------------------------------------------------
22
+ * Public Util API
25
23
  */
26
24
 
27
25
  const getUID = prefix => {
@@ -36,22 +34,22 @@ const getSelector = element => {
36
34
  let selector = element.getAttribute('data-bs-target')
37
35
 
38
36
  if (!selector || selector === '#') {
39
- let hrefAttr = element.getAttribute('href')
37
+ let hrefAttribute = element.getAttribute('href')
40
38
 
41
39
  // The only valid content that could double as a selector are IDs or classes,
42
40
  // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
43
41
  // `document.querySelector` will rightfully complain it is invalid.
44
42
  // See https://github.com/twbs/bootstrap/issues/32273
45
- if (!hrefAttr || (!hrefAttr.includes('#') && !hrefAttr.startsWith('.'))) {
43
+ if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
46
44
  return null
47
45
  }
48
46
 
49
47
  // Just in case some CMS puts out a full URL with the anchor appended
50
- if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
51
- hrefAttr = `#${hrefAttr.split('#')[1]}`
48
+ if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
49
+ hrefAttribute = `#${hrefAttribute.split('#')[1]}`
52
50
  }
53
51
 
54
- selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null
52
+ selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
55
53
  }
56
54
 
57
55
  return selector
@@ -100,50 +98,56 @@ const triggerTransitionEnd = element => {
100
98
  element.dispatchEvent(new Event(TRANSITION_END))
101
99
  }
102
100
 
103
- const isElement = obj => {
104
- if (!obj || typeof obj !== 'object') {
101
+ const isElement = object => {
102
+ if (!object || typeof object !== 'object') {
105
103
  return false
106
104
  }
107
105
 
108
- if (typeof obj.jquery !== 'undefined') {
109
- obj = obj[0]
106
+ if (typeof object.jquery !== 'undefined') {
107
+ object = object[0]
110
108
  }
111
109
 
112
- return typeof obj.nodeType !== 'undefined'
110
+ return typeof object.nodeType !== 'undefined'
113
111
  }
114
112
 
115
- const getElement = obj => {
116
- if (isElement(obj)) { // it's a jQuery object or a node element
117
- return obj.jquery ? obj[0] : obj
113
+ const getElement = object => {
114
+ // it's a jQuery object or a node element
115
+ if (isElement(object)) {
116
+ return object.jquery ? object[0] : object
118
117
  }
119
118
 
120
- if (typeof obj === 'string' && obj.length > 0) {
121
- return document.querySelector(obj)
119
+ if (typeof object === 'string' && object.length > 0) {
120
+ return document.querySelector(object)
122
121
  }
123
122
 
124
123
  return null
125
124
  }
126
125
 
127
- const typeCheckConfig = (componentName, config, configTypes) => {
128
- Object.keys(configTypes).forEach(property => {
129
- const expectedTypes = configTypes[property]
130
- const value = config[property]
131
- const valueType = value && isElement(value) ? 'element' : toType(value)
132
-
133
- if (!new RegExp(expectedTypes).test(valueType)) {
134
- throw new TypeError(
135
- `${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
136
- )
137
- }
138
- })
139
- }
140
-
141
126
  const isVisible = element => {
142
127
  if (!isElement(element) || element.getClientRects().length === 0) {
143
128
  return false
144
129
  }
145
130
 
146
- return getComputedStyle(element).getPropertyValue('visibility') === 'visible'
131
+ const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'
132
+ // Handle `details` element as its content may falsie appear visible when it is closed
133
+ const closedDetails = element.closest('details:not([open])')
134
+
135
+ if (!closedDetails) {
136
+ return elementIsVisible
137
+ }
138
+
139
+ if (closedDetails !== element) {
140
+ const summary = element.closest('summary')
141
+ if (summary && summary.parentNode !== closedDetails) {
142
+ return false
143
+ }
144
+
145
+ if (summary === null) {
146
+ return false
147
+ }
148
+ }
149
+
150
+ return elementIsVisible
147
151
  }
148
152
 
149
153
  const isDisabled = element => {
@@ -196,15 +200,12 @@ const noop = () => {}
196
200
  * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
197
201
  */
198
202
  const reflow = element => {
199
- // eslint-disable-next-line no-unused-expressions
200
- element.offsetHeight
203
+ element.offsetHeight // eslint-disable-line no-unused-expressions
201
204
  }
202
205
 
203
206
  const getjQuery = () => {
204
- const { jQuery } = window
205
-
206
- if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
207
- return jQuery
207
+ if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
208
+ return window.jQuery
208
209
  }
209
210
 
210
211
  return null
@@ -217,7 +218,9 @@ const onDOMContentLoaded = callback => {
217
218
  // add listener on the first call when the document is in loading state
218
219
  if (!DOMContentLoadedCallbacks.length) {
219
220
  document.addEventListener('DOMContentLoaded', () => {
220
- DOMContentLoadedCallbacks.forEach(callback => callback())
221
+ for (const callback of DOMContentLoadedCallbacks) {
222
+ callback()
223
+ }
221
224
  })
222
225
  }
223
226
 
@@ -291,15 +294,15 @@ const executeAfterTransition = (callback, transitionElement, waitForTransition =
291
294
  * @return {Element|elem} The proper element
292
295
  */
293
296
  const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
297
+ const listLength = list.length
294
298
  let index = list.indexOf(activeElement)
295
299
 
296
- // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
300
+ // if the element does not exist in the list return an element
301
+ // depending on the direction and if cycle is allowed
297
302
  if (index === -1) {
298
- return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0]
303
+ return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]
299
304
  }
300
305
 
301
- const listLength = list.length
302
-
303
306
  index += shouldGetNext ? 1 : -1
304
307
 
305
308
  if (isCycleAllowed) {
@@ -310,24 +313,24 @@ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed
310
313
  }
311
314
 
312
315
  export {
316
+ defineJQueryPlugin,
317
+ execute,
318
+ executeAfterTransition,
319
+ findShadowRoot,
313
320
  getElement,
314
- getUID,
315
- getSelectorFromElement,
316
321
  getElementFromSelector,
322
+ getjQuery,
323
+ getNextActiveElement,
324
+ getSelectorFromElement,
317
325
  getTransitionDurationFromElement,
318
- triggerTransitionEnd,
326
+ getUID,
327
+ isDisabled,
319
328
  isElement,
320
- typeCheckConfig,
329
+ isRTL,
321
330
  isVisible,
322
- isDisabled,
323
- findShadowRoot,
324
331
  noop,
325
- getNextActiveElement,
326
- reflow,
327
- getjQuery,
328
332
  onDOMContentLoaded,
329
- isRTL,
330
- defineJQueryPlugin,
331
- execute,
332
- executeAfterTransition
333
+ reflow,
334
+ triggerTransitionEnd,
335
+ toType
333
336
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * Bootstrap (v5.1.3): util/sanitizer.js
3
+ * Bootstrap (v5.2.0): util/sanitizer.js
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  * --------------------------------------------------------------------------
6
6
  */
@@ -21,14 +21,14 @@ const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
21
21
  /**
22
22
  * A pattern that recognizes a commonly useful subset of URLs that are safe.
23
23
  *
24
- * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
24
+ * Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
25
25
  */
26
26
  const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i
27
27
 
28
28
  /**
29
29
  * A pattern that matches safe data URLs. Only matches image, video and audio types.
30
30
  *
31
- * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
31
+ * Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
32
32
  */
33
33
  const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i
34
34
 
@@ -43,16 +43,9 @@ const allowedAttribute = (attribute, allowedAttributeList) => {
43
43
  return true
44
44
  }
45
45
 
46
- const regExp = allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp)
47
-
48
46
  // Check if a regular expression validates the attribute.
49
- for (let i = 0, len = regExp.length; i < len; i++) {
50
- if (regExp[i].test(attributeName)) {
51
- return true
52
- }
53
- }
54
-
55
- return false
47
+ return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp)
48
+ .some(regex => regex.test(attributeName))
56
49
  }
57
50
 
58
51
  export const DefaultAllowlist = {
@@ -89,21 +82,20 @@ export const DefaultAllowlist = {
89
82
  ul: []
90
83
  }
91
84
 
92
- export function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
85
+ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
93
86
  if (!unsafeHtml.length) {
94
87
  return unsafeHtml
95
88
  }
96
89
 
97
- if (sanitizeFn && typeof sanitizeFn === 'function') {
98
- return sanitizeFn(unsafeHtml)
90
+ if (sanitizeFunction && typeof sanitizeFunction === 'function') {
91
+ return sanitizeFunction(unsafeHtml)
99
92
  }
100
93
 
101
94
  const domParser = new window.DOMParser()
102
95
  const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')
103
96
  const elements = [].concat(...createdDocument.body.querySelectorAll('*'))
104
97
 
105
- for (let i = 0, len = elements.length; i < len; i++) {
106
- const element = elements[i]
98
+ for (const element of elements) {
107
99
  const elementName = element.nodeName.toLowerCase()
108
100
 
109
101
  if (!Object.keys(allowList).includes(elementName)) {
@@ -115,11 +107,11 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
115
107
  const attributeList = [].concat(...element.attributes)
116
108
  const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || [])
117
109
 
118
- attributeList.forEach(attribute => {
110
+ for (const attribute of attributeList) {
119
111
  if (!allowedAttribute(attribute, allowedAttributes)) {
120
112
  element.removeAttribute(attribute.nodeName)
121
113
  }
122
- })
114
+ }
123
115
  }
124
116
 
125
117
  return createdDocument.body.innerHTML