@coreui/coreui 4.0.5 → 4.1.2

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 (143) hide show
  1. package/README.md +4 -7
  2. package/dist/css/coreui-grid.css +254 -205
  3. package/dist/css/coreui-grid.css.map +1 -1
  4. package/dist/css/coreui-grid.min.css +2 -2
  5. package/dist/css/coreui-grid.min.css.map +1 -1
  6. package/dist/css/coreui-grid.rtl.css +255 -206
  7. package/dist/css/coreui-grid.rtl.css.map +1 -1
  8. package/dist/css/coreui-grid.rtl.min.css +3 -3
  9. package/dist/css/coreui-grid.rtl.min.css.map +1 -1
  10. package/dist/css/coreui-reboot.css +63 -8
  11. package/dist/css/coreui-reboot.css.map +1 -1
  12. package/dist/css/coreui-reboot.min.css +2 -2
  13. package/dist/css/coreui-reboot.min.css.map +1 -1
  14. package/dist/css/coreui-reboot.rtl.css +64 -9
  15. package/dist/css/coreui-reboot.rtl.css.map +1 -1
  16. package/dist/css/coreui-reboot.rtl.min.css +3 -3
  17. package/dist/css/coreui-reboot.rtl.min.css.map +1 -1
  18. package/dist/css/coreui-utilities.css +181 -81
  19. package/dist/css/coreui-utilities.css.map +1 -1
  20. package/dist/css/coreui-utilities.min.css +2 -2
  21. package/dist/css/coreui-utilities.min.css.map +1 -1
  22. package/dist/css/coreui-utilities.rtl.css +182 -82
  23. package/dist/css/coreui-utilities.rtl.css.map +1 -1
  24. package/dist/css/coreui-utilities.rtl.min.css +3 -3
  25. package/dist/css/coreui-utilities.rtl.min.css.map +1 -1
  26. package/dist/css/coreui.css +713 -346
  27. package/dist/css/coreui.css.map +1 -1
  28. package/dist/css/coreui.min.css +2 -2
  29. package/dist/css/coreui.min.css.map +1 -1
  30. package/dist/css/coreui.rtl.css +699 -347
  31. package/dist/css/coreui.rtl.css.map +1 -1
  32. package/dist/css/coreui.rtl.min.css +3 -3
  33. package/dist/css/coreui.rtl.min.css.map +1 -1
  34. package/dist/js/coreui.bundle.js +851 -746
  35. package/dist/js/coreui.bundle.js.map +1 -1
  36. package/dist/js/coreui.bundle.min.js +3 -3
  37. package/dist/js/coreui.bundle.min.js.map +1 -1
  38. package/dist/js/coreui.esm.js +704 -644
  39. package/dist/js/coreui.esm.js.map +1 -1
  40. package/dist/js/coreui.esm.min.js +3 -3
  41. package/dist/js/coreui.esm.min.js.map +1 -1
  42. package/dist/js/coreui.js +714 -656
  43. package/dist/js/coreui.js.map +1 -1
  44. package/dist/js/coreui.min.js +3 -3
  45. package/dist/js/coreui.min.js.map +1 -1
  46. package/js/dist/alert.js +82 -49
  47. package/js/dist/alert.js.map +1 -1
  48. package/js/dist/base-component.js +26 -18
  49. package/js/dist/base-component.js.map +1 -1
  50. package/js/dist/button.js +23 -13
  51. package/js/dist/button.js.map +1 -1
  52. package/js/dist/carousel.js +95 -50
  53. package/js/dist/carousel.js.map +1 -1
  54. package/js/dist/collapse.js +125 -139
  55. package/js/dist/collapse.js.map +1 -1
  56. package/js/dist/dom/data.js +6 -6
  57. package/js/dist/dom/data.js.map +1 -1
  58. package/js/dist/dom/event-handler.js +15 -6
  59. package/js/dist/dom/event-handler.js.map +1 -1
  60. package/js/dist/dom/manipulator.js +7 -7
  61. package/js/dist/dom/manipulator.js.map +1 -1
  62. package/js/dist/dom/selector-engine.js +74 -9
  63. package/js/dist/dom/selector-engine.js.map +1 -1
  64. package/js/dist/dropdown.js +125 -112
  65. package/js/dist/dropdown.js.map +1 -1
  66. package/js/dist/modal.js +270 -93
  67. package/js/dist/modal.js.map +1 -1
  68. package/js/dist/offcanvas.js +231 -62
  69. package/js/dist/offcanvas.js.map +1 -1
  70. package/js/dist/popover.js +29 -59
  71. package/js/dist/popover.js.map +1 -1
  72. package/js/dist/scrollspy.js +45 -35
  73. package/js/dist/scrollspy.js.map +1 -1
  74. package/js/dist/tab.js +45 -23
  75. package/js/dist/tab.js.map +1 -1
  76. package/js/dist/toast.js +132 -34
  77. package/js/dist/toast.js.map +1 -1
  78. package/js/dist/tooltip.js +127 -109
  79. package/js/dist/tooltip.js.map +1 -1
  80. package/js/src/alert.js +21 -47
  81. package/js/src/base-component.js +3 -3
  82. package/js/src/button.js +1 -1
  83. package/js/src/carousel.js +10 -4
  84. package/js/src/collapse.js +66 -119
  85. package/js/src/dom/data.js +1 -1
  86. package/js/src/dom/event-handler.js +1 -2
  87. package/js/src/dom/manipulator.js +3 -3
  88. package/js/src/dom/selector-engine.js +18 -1
  89. package/js/src/dropdown.js +53 -68
  90. package/js/src/modal.js +24 -35
  91. package/js/src/navigation.js +1 -1
  92. package/js/src/offcanvas.js +16 -18
  93. package/js/src/popover.js +7 -49
  94. package/js/src/scrollspy.js +1 -1
  95. package/js/src/sidebar.js +21 -27
  96. package/js/src/tab.js +1 -1
  97. package/js/src/toast.js +11 -11
  98. package/js/src/tooltip.js +66 -50
  99. package/js/src/util/backdrop.js +6 -5
  100. package/js/src/util/component-functions.js +34 -0
  101. package/js/src/util/focustrap.js +105 -0
  102. package/js/src/util/index.js +39 -11
  103. package/js/src/util/sanitizer.js +21 -22
  104. package/js/src/util/scrollbar.js +1 -1
  105. package/package.json +54 -55
  106. package/scss/_buttons.scss +1 -2
  107. package/scss/_card.scss +2 -1
  108. package/scss/_dropdown.scss +1 -1
  109. package/scss/_functions.scss +51 -12
  110. package/scss/_grid.scss +0 -23
  111. package/scss/_helpers.scss +2 -0
  112. package/scss/_mixins.scss +1 -0
  113. package/scss/_modal.scss +2 -12
  114. package/scss/_nav.scss +1 -2
  115. package/scss/_navbar.scss +30 -1
  116. package/scss/_offcanvas.scss +6 -2
  117. package/scss/_placeholders.scss +51 -0
  118. package/scss/_reboot.scss +12 -8
  119. package/scss/_root.scss +36 -7
  120. package/scss/_tables.scss +9 -5
  121. package/scss/_toasts.scss +2 -2
  122. package/scss/_transitions.scss +6 -0
  123. package/scss/_utilities.scss +31 -8
  124. package/scss/_variables.scss +188 -13
  125. package/scss/coreui-grid.rtl.scss +1 -1
  126. package/scss/coreui-grid.scss +3 -1
  127. package/scss/coreui-reboot.rtl.scss +1 -1
  128. package/scss/coreui-reboot.scss +2 -4
  129. package/scss/coreui-utilities.rtl.scss +1 -1
  130. package/scss/coreui-utilities.scss +1 -1
  131. package/scss/coreui.rtl.scss +1 -1
  132. package/scss/coreui.scss +2 -1
  133. package/scss/forms/_form-control.scss +1 -1
  134. package/scss/forms/_form-select.scss +2 -0
  135. package/scss/helpers/_stacks.scss +15 -0
  136. package/scss/helpers/_vr.scss +8 -0
  137. package/scss/mixins/_backdrop.scss +14 -0
  138. package/scss/mixins/_grid.scss +26 -7
  139. package/scss/mixins/_ltr-rtl.scss +21 -0
  140. package/scss/mixins/_reset-text.scss +1 -1
  141. package/scss/mixins/_utilities.scss +28 -33
  142. package/scss/mixins/_visually-hidden.scss +1 -1
  143. package/scss/sidebar/_sidebar-nav.scss +1 -0
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * CoreUI (v4.0.5): collapse.js
3
+ * CoreUI (v4.1.2): collapse.js
4
4
  * Licensed under MIT (https://coreui.io/license)
5
5
  *
6
6
  * This component is a modified version of the Bootstrap's collapse.js
@@ -35,12 +35,12 @@ const DATA_API_KEY = '.data-api'
35
35
 
36
36
  const Default = {
37
37
  toggle: true,
38
- parent: ''
38
+ parent: null
39
39
  }
40
40
 
41
41
  const DefaultType = {
42
42
  toggle: 'boolean',
43
- parent: '(string|element)'
43
+ parent: '(null|element)'
44
44
  }
45
45
 
46
46
  const EVENT_SHOW = `show${EVENT_KEY}`
@@ -53,11 +53,13 @@ const CLASS_NAME_SHOW = 'show'
53
53
  const CLASS_NAME_COLLAPSE = 'collapse'
54
54
  const CLASS_NAME_COLLAPSING = 'collapsing'
55
55
  const CLASS_NAME_COLLAPSED = 'collapsed'
56
+ const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`
57
+ const CLASS_NAME_HORIZONTAL = 'collapse-horizontal'
56
58
 
57
59
  const WIDTH = 'width'
58
60
  const HEIGHT = 'height'
59
61
 
60
- const SELECTOR_ACTIVES = '.show, .collapsing'
62
+ const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing'
61
63
  const SELECTOR_DATA_TOGGLE = '[data-coreui-toggle="collapse"]'
62
64
 
63
65
  /**
@@ -72,10 +74,7 @@ class Collapse extends BaseComponent {
72
74
 
73
75
  this._isTransitioning = false
74
76
  this._config = this._getConfig(config)
75
- this._triggerArray = SelectorEngine.find(
76
- `${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` +
77
- `${SELECTOR_DATA_TOGGLE}[data-coreui-target="#${this._element.id}"]`
78
- )
77
+ this._triggerArray = []
79
78
 
80
79
  const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
81
80
 
@@ -91,10 +90,10 @@ class Collapse extends BaseComponent {
91
90
  }
92
91
  }
93
92
 
94
- this._parent = this._config.parent ? this._getParent() : null
93
+ this._initializeChildren()
95
94
 
96
95
  if (!this._config.parent) {
97
- this._addAriaAndCollapsedClass(this._element, this._triggerArray)
96
+ this._addAriaAndCollapsedClass(this._triggerArray, this._isShown())
98
97
  }
99
98
 
100
99
  if (this._config.toggle) {
@@ -115,7 +114,7 @@ class Collapse extends BaseComponent {
115
114
  // Public
116
115
 
117
116
  toggle() {
118
- if (this._element.classList.contains(CLASS_NAME_SHOW)) {
117
+ if (this._isShown()) {
119
118
  this.hide()
120
119
  } else {
121
120
  this.show()
@@ -123,30 +122,20 @@ class Collapse extends BaseComponent {
123
122
  }
124
123
 
125
124
  show() {
126
- if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) {
125
+ if (this._isTransitioning || this._isShown()) {
127
126
  return
128
127
  }
129
128
 
130
- let actives
129
+ let actives = []
131
130
  let activesData
132
131
 
133
- if (this._parent) {
134
- actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent)
135
- .filter(elem => {
136
- if (typeof this._config.parent === 'string') {
137
- return elem.getAttribute('data-coreui-parent') === this._config.parent
138
- }
139
-
140
- return elem.classList.contains(CLASS_NAME_COLLAPSE)
141
- })
142
-
143
- if (actives.length === 0) {
144
- actives = null
145
- }
132
+ if (this._config.parent) {
133
+ const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent)
134
+ actives = SelectorEngine.find(SELECTOR_ACTIVES, this._config.parent).filter(elem => !children.includes(elem)) // remove children if greater depth
146
135
  }
147
136
 
148
137
  const container = SelectorEngine.findOne(this._selector)
149
- if (actives) {
138
+ if (actives.length) {
150
139
  const tempActiveData = actives.find(elem => container !== elem)
151
140
  activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null
152
141
 
@@ -160,17 +149,15 @@ class Collapse extends BaseComponent {
160
149
  return
161
150
  }
162
151
 
163
- if (actives) {
164
- actives.forEach(elemActive => {
165
- if (container !== elemActive) {
166
- Collapse.collapseInterface(elemActive, 'hide')
167
- }
152
+ actives.forEach(elemActive => {
153
+ if (container !== elemActive) {
154
+ Collapse.getOrCreateInstance(elemActive, { toggle: false }).hide()
155
+ }
168
156
 
169
- if (!activesData) {
170
- Data.set(elemActive, DATA_KEY, null)
171
- }
172
- })
173
- }
157
+ if (!activesData) {
158
+ Data.set(elemActive, DATA_KEY, null)
159
+ }
160
+ })
174
161
 
175
162
  const dimension = this._getDimension()
176
163
 
@@ -179,23 +166,17 @@ class Collapse extends BaseComponent {
179
166
 
180
167
  this._element.style[dimension] = 0
181
168
 
182
- if (this._triggerArray.length) {
183
- this._triggerArray.forEach(element => {
184
- element.classList.remove(CLASS_NAME_COLLAPSED)
185
- element.setAttribute('aria-expanded', true)
186
- })
187
- }
188
-
189
- this.setTransitioning(true)
169
+ this._addAriaAndCollapsedClass(this._triggerArray, true)
170
+ this._isTransitioning = true
190
171
 
191
172
  const complete = () => {
173
+ this._isTransitioning = false
174
+
192
175
  this._element.classList.remove(CLASS_NAME_COLLAPSING)
193
176
  this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)
194
177
 
195
178
  this._element.style[dimension] = ''
196
179
 
197
- this.setTransitioning(false)
198
-
199
180
  EventHandler.trigger(this._element, EVENT_SHOWN)
200
181
  }
201
182
 
@@ -207,7 +188,7 @@ class Collapse extends BaseComponent {
207
188
  }
208
189
 
209
190
  hide() {
210
- if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) {
191
+ if (this._isTransitioning || !this._isShown()) {
211
192
  return
212
193
  }
213
194
 
@@ -226,22 +207,19 @@ class Collapse extends BaseComponent {
226
207
  this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)
227
208
 
228
209
  const triggerArrayLength = this._triggerArray.length
229
- if (triggerArrayLength > 0) {
230
- for (let i = 0; i < triggerArrayLength; i++) {
231
- const trigger = this._triggerArray[i]
232
- const elem = getElementFromSelector(trigger)
233
-
234
- if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) {
235
- trigger.classList.add(CLASS_NAME_COLLAPSED)
236
- trigger.setAttribute('aria-expanded', false)
237
- }
210
+ for (let i = 0; i < triggerArrayLength; i++) {
211
+ const trigger = this._triggerArray[i]
212
+ const elem = getElementFromSelector(trigger)
213
+
214
+ if (elem && !this._isShown(elem)) {
215
+ this._addAriaAndCollapsedClass([trigger], false)
238
216
  }
239
217
  }
240
218
 
241
- this.setTransitioning(true)
219
+ this._isTransitioning = true
242
220
 
243
221
  const complete = () => {
244
- this.setTransitioning(false)
222
+ this._isTransitioning = false
245
223
  this._element.classList.remove(CLASS_NAME_COLLAPSING)
246
224
  this._element.classList.add(CLASS_NAME_COLLAPSE)
247
225
  EventHandler.trigger(this._element, EVENT_HIDDEN)
@@ -252,8 +230,8 @@ class Collapse extends BaseComponent {
252
230
  this._queueCallback(complete, this._element, true)
253
231
  }
254
232
 
255
- setTransitioning(isTransitioning) {
256
- this._isTransitioning = isTransitioning
233
+ _isShown(element = this._element) {
234
+ return element.classList.contains(CLASS_NAME_SHOW)
257
235
  }
258
236
 
259
237
  // Private
@@ -261,44 +239,40 @@ class Collapse extends BaseComponent {
261
239
  _getConfig(config) {
262
240
  config = {
263
241
  ...Default,
242
+ ...Manipulator.getDataAttributes(this._element),
264
243
  ...config
265
244
  }
266
245
  config.toggle = Boolean(config.toggle) // Coerce string values
246
+ config.parent = getElement(config.parent)
267
247
  typeCheckConfig(NAME, config, DefaultType)
268
248
  return config
269
249
  }
270
250
 
271
251
  _getDimension() {
272
- return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT
252
+ return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT
273
253
  }
274
254
 
275
- _getParent() {
276
- let { parent } = this._config
277
-
278
- parent = getElement(parent)
279
-
280
- const selector = `${SELECTOR_DATA_TOGGLE}[data-coreui-parent="${parent}"]`
255
+ _initializeChildren() {
256
+ if (!this._config.parent) {
257
+ return
258
+ }
281
259
 
282
- SelectorEngine.find(selector, parent)
260
+ const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent)
261
+ SelectorEngine.find(SELECTOR_DATA_TOGGLE, this._config.parent).filter(elem => !children.includes(elem))
283
262
  .forEach(element => {
284
263
  const selected = getElementFromSelector(element)
285
264
 
286
- this._addAriaAndCollapsedClass(
287
- selected,
288
- [element]
289
- )
265
+ if (selected) {
266
+ this._addAriaAndCollapsedClass([element], this._isShown(selected))
267
+ }
290
268
  })
291
-
292
- return parent
293
269
  }
294
270
 
295
- _addAriaAndCollapsedClass(element, triggerArray) {
296
- if (!element || !triggerArray.length) {
271
+ _addAriaAndCollapsedClass(triggerArray, isOpen) {
272
+ if (!triggerArray.length) {
297
273
  return
298
274
  }
299
275
 
300
- const isOpen = element.classList.contains(CLASS_NAME_SHOW)
301
-
302
276
  triggerArray.forEach(elem => {
303
277
  if (isOpen) {
304
278
  elem.classList.remove(CLASS_NAME_COLLAPSED)
@@ -312,34 +286,22 @@ class Collapse extends BaseComponent {
312
286
 
313
287
  // Static
314
288
 
315
- static collapseInterface(element, config) {
316
- let data = Collapse.getInstance(element)
317
- const _config = {
318
- ...Default,
319
- ...Manipulator.getDataAttributes(element),
320
- ...(typeof config === 'object' && config ? config : {})
321
- }
289
+ static jQueryInterface(config) {
290
+ return this.each(function () {
291
+ const _config = {}
292
+ if (typeof config === 'string' && /show|hide/.test(config)) {
293
+ _config.toggle = false
294
+ }
322
295
 
323
- if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
324
- _config.toggle = false
325
- }
296
+ const data = Collapse.getOrCreateInstance(this, _config)
326
297
 
327
- if (!data) {
328
- data = new Collapse(element, _config)
329
- }
298
+ if (typeof config === 'string') {
299
+ if (typeof data[config] === 'undefined') {
300
+ throw new TypeError(`No method named "${config}"`)
301
+ }
330
302
 
331
- if (typeof config === 'string') {
332
- if (typeof data[config] === 'undefined') {
333
- throw new TypeError(`No method named "${config}"`)
303
+ data[config]()
334
304
  }
335
-
336
- data[config]()
337
- }
338
- }
339
-
340
- static jQueryInterface(config) {
341
- return this.each(function () {
342
- Collapse.collapseInterface(this, config)
343
305
  })
344
306
  }
345
307
  }
@@ -356,26 +318,11 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
356
318
  event.preventDefault()
357
319
  }
358
320
 
359
- const triggerData = Manipulator.getDataAttributes(this)
360
321
  const selector = getSelectorFromElement(this)
361
322
  const selectorElements = SelectorEngine.find(selector)
362
323
 
363
324
  selectorElements.forEach(element => {
364
- const data = Collapse.getInstance(element)
365
- let config
366
- if (data) {
367
- // update parent attribute
368
- if (data._parent === null && typeof triggerData.parent === 'string') {
369
- data._config.parent = triggerData.parent
370
- data._parent = data._getParent()
371
- }
372
-
373
- config = 'toggle'
374
- } else {
375
- config = triggerData
376
- }
377
-
378
- Collapse.collapseInterface(element, config)
325
+ Collapse.getOrCreateInstance(element, { toggle: false }).toggle()
379
326
  })
380
327
  })
381
328
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * CoreUI (v4.0.5): dom/data.js
3
+ * CoreUI (v4.1.2): dom/data.js
4
4
  * Licensed under MIT (https://coreui.io/license)
5
5
  *
6
6
  * This component is a modified version of the Bootstrap's dom/data.js
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * CoreUI (v4.0.5): dom/event-handler.js
3
+ * CoreUI (v4.1.2): dom/event-handler.js
4
4
  * Licensed under MIT (https://coreui.io/license)
5
5
  *
6
6
  * This component is a modified version of the Bootstrap's dom/event-handler.js
@@ -116,7 +116,6 @@ function bootstrapDelegationHandler(element, selector, fn) {
116
116
  event.delegateTarget = target
117
117
 
118
118
  if (handler.oneOff) {
119
- // eslint-disable-next-line unicorn/consistent-destructuring
120
119
  EventHandler.off(element, event.type, selector, fn)
121
120
  }
122
121
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * CoreUI (v4.0.5): dom/manipulator.js
3
+ * CoreUI (v4.1.2): dom/manipulator.js
4
4
  * Licensed under MIT (https://coreui.io/license)
5
5
  *
6
6
  * This component is a modified version of the Bootstrap's dom/manipulator.js
@@ -67,8 +67,8 @@ const Manipulator = {
67
67
  const rect = element.getBoundingClientRect()
68
68
 
69
69
  return {
70
- top: rect.top + document.body.scrollTop,
71
- left: rect.left + document.body.scrollLeft
70
+ top: rect.top + window.pageYOffset,
71
+ left: rect.left + window.pageXOffset
72
72
  }
73
73
  },
74
74
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * CoreUI (v4.0.5): dom/selector-engine.js
3
+ * CoreUI (v4.1.2): dom/selector-engine.js
4
4
  * Licensed under MIT (https://coreui.io/license)
5
5
  *
6
6
  * This component is a modified version of the Bootstrap's dom/selector-engine.js
@@ -14,6 +14,8 @@
14
14
  * ------------------------------------------------------------------------
15
15
  */
16
16
 
17
+ import { isDisabled, isVisible } from '../util/index'
18
+
17
19
  const NODE_TEXT = 3
18
20
 
19
21
  const SelectorEngine = {
@@ -72,6 +74,21 @@ const SelectorEngine = {
72
74
  }
73
75
 
74
76
  return []
77
+ },
78
+
79
+ focusableChildren(element) {
80
+ const focusables = [
81
+ 'a',
82
+ 'button',
83
+ 'input',
84
+ 'textarea',
85
+ 'select',
86
+ 'details',
87
+ '[tabindex]',
88
+ '[contenteditable="true"]'
89
+ ].map(selector => `${selector}:not([tabindex^="-"])`).join(', ')
90
+
91
+ return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))
75
92
  }
76
93
  }
77
94
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * --------------------------------------------------------------------------
3
- * CoreUI (v4.0.5): dropdown.js
3
+ * CoreUI (v4.1.2): dropdown.js
4
4
  * Licensed under MIT (https://coreui.io/license)
5
5
  *
6
6
  * This component is a modified version of the Bootstrap's dropdown.js
@@ -14,12 +14,12 @@ import {
14
14
  defineJQueryPlugin,
15
15
  getElement,
16
16
  getElementFromSelector,
17
+ getNextActiveElement,
17
18
  isDisabled,
18
19
  isElement,
19
- isVisible,
20
20
  isRTL,
21
+ isVisible,
21
22
  noop,
22
- getNextActiveElement,
23
23
  typeCheckConfig
24
24
  } from './util/index'
25
25
  import EventHandler from './dom/event-handler'
@@ -51,7 +51,6 @@ const EVENT_HIDE = `hide${EVENT_KEY}`
51
51
  const EVENT_HIDDEN = `hidden${EVENT_KEY}`
52
52
  const EVENT_SHOW = `show${EVENT_KEY}`
53
53
  const EVENT_SHOWN = `shown${EVENT_KEY}`
54
- const EVENT_CLICK = `click${EVENT_KEY}`
55
54
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
56
55
  const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`
57
56
  const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`
@@ -106,8 +105,6 @@ class Dropdown extends BaseComponent {
106
105
  this._config = this._getConfig(config)
107
106
  this._menu = this._getMenuElement()
108
107
  this._inNavbar = this._detectNavbar()
109
-
110
- this._addEventListeners()
111
108
  }
112
109
 
113
110
  // Getters
@@ -127,26 +124,14 @@ class Dropdown extends BaseComponent {
127
124
  // Public
128
125
 
129
126
  toggle() {
130
- if (isDisabled(this._element)) {
131
- return
132
- }
133
-
134
- const isActive = this._element.classList.contains(CLASS_NAME_SHOW)
135
-
136
- if (isActive) {
137
- this.hide()
138
- return
139
- }
140
-
141
- this.show()
127
+ return this._isShown() ? this.hide() : this.show()
142
128
  }
143
129
 
144
130
  show() {
145
- if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW)) {
131
+ if (isDisabled(this._element) || this._isShown(this._menu)) {
146
132
  return
147
133
  }
148
134
 
149
- const parent = Dropdown.getParentFromElement(this._element)
150
135
  const relatedTarget = {
151
136
  relatedTarget: this._element
152
137
  }
@@ -157,32 +142,12 @@ class Dropdown extends BaseComponent {
157
142
  return
158
143
  }
159
144
 
145
+ const parent = Dropdown.getParentFromElement(this._element)
160
146
  // Totally disable Popper for Dropdowns in Navbar
161
147
  if (this._inNavbar) {
162
148
  Manipulator.setDataAttribute(this._menu, 'popper', 'none')
163
149
  } else {
164
- if (typeof Popper === 'undefined') {
165
- throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)')
166
- }
167
-
168
- let referenceElement = this._element
169
-
170
- if (this._config.reference === 'parent') {
171
- referenceElement = parent
172
- } else if (isElement(this._config.reference)) {
173
- referenceElement = getElement(this._config.reference)
174
- } else if (typeof this._config.reference === 'object') {
175
- referenceElement = this._config.reference
176
- }
177
-
178
- const popperConfig = this._getPopperConfig()
179
- const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false)
180
-
181
- this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)
182
-
183
- if (isDisplayStatic) {
184
- Manipulator.setDataAttribute(this._menu, 'popper', 'static')
185
- }
150
+ this._createPopper(parent)
186
151
  }
187
152
 
188
153
  // If this is a touch-enabled device we add extra
@@ -198,13 +163,13 @@ class Dropdown extends BaseComponent {
198
163
  this._element.focus()
199
164
  this._element.setAttribute('aria-expanded', true)
200
165
 
201
- this._menu.classList.toggle(CLASS_NAME_SHOW)
202
- this._element.classList.toggle(CLASS_NAME_SHOW)
166
+ this._menu.classList.add(CLASS_NAME_SHOW)
167
+ this._element.classList.add(CLASS_NAME_SHOW)
203
168
  EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget)
204
169
  }
205
170
 
206
171
  hide() {
207
- if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW)) {
172
+ if (isDisabled(this._element) || !this._isShown(this._menu)) {
208
173
  return
209
174
  }
210
175
 
@@ -232,13 +197,6 @@ class Dropdown extends BaseComponent {
232
197
 
233
198
  // Private
234
199
 
235
- _addEventListeners() {
236
- EventHandler.on(this._element, EVENT_CLICK, event => {
237
- event.preventDefault()
238
- this.toggle()
239
- })
240
- }
241
-
242
200
  _completeHide(relatedTarget) {
243
201
  const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget)
244
202
  if (hideEvent.defaultPrevented) {
@@ -282,6 +240,35 @@ class Dropdown extends BaseComponent {
282
240
  return config
283
241
  }
284
242
 
243
+ _createPopper(parent) {
244
+ if (typeof Popper === 'undefined') {
245
+ throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)')
246
+ }
247
+
248
+ let referenceElement = this._element
249
+
250
+ if (this._config.reference === 'parent') {
251
+ referenceElement = parent
252
+ } else if (isElement(this._config.reference)) {
253
+ referenceElement = getElement(this._config.reference)
254
+ } else if (typeof this._config.reference === 'object') {
255
+ referenceElement = this._config.reference
256
+ }
257
+
258
+ const popperConfig = this._getPopperConfig()
259
+ const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false)
260
+
261
+ this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)
262
+
263
+ if (isDisplayStatic) {
264
+ Manipulator.setDataAttribute(this._menu, 'popper', 'static')
265
+ }
266
+ }
267
+
268
+ _isShown(element = this._element) {
269
+ return element.classList.contains(CLASS_NAME_SHOW)
270
+ }
271
+
285
272
  _getMenuElement() {
286
273
  return SelectorEngine.next(this._element, SELECTOR_MENU)[0]
287
274
  }
@@ -370,21 +357,19 @@ class Dropdown extends BaseComponent {
370
357
 
371
358
  // Static
372
359
 
373
- static dropdownInterface(element, config) {
374
- const data = Dropdown.getOrCreateInstance(element, config)
360
+ static jQueryInterface(config) {
361
+ return this.each(function () {
362
+ const data = Dropdown.getOrCreateInstance(this, config)
363
+
364
+ if (typeof config !== 'string') {
365
+ return
366
+ }
375
367
 
376
- if (typeof config === 'string') {
377
368
  if (typeof data[config] === 'undefined') {
378
369
  throw new TypeError(`No method named "${config}"`)
379
370
  }
380
371
 
381
372
  data[config]()
382
- }
383
- }
384
-
385
- static jQueryInterface(config) {
386
- return this.each(function () {
387
- Dropdown.dropdownInterface(this, config)
388
373
  })
389
374
  }
390
375
 
@@ -401,7 +386,7 @@ class Dropdown extends BaseComponent {
401
386
  continue
402
387
  }
403
388
 
404
- if (!context._element.classList.contains(CLASS_NAME_SHOW)) {
389
+ if (!context._isShown()) {
405
390
  continue
406
391
  }
407
392
 
@@ -467,20 +452,20 @@ class Dropdown extends BaseComponent {
467
452
  return
468
453
  }
469
454
 
470
- const getToggleButton = () => this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0]
455
+ const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0]
456
+ const instance = Dropdown.getOrCreateInstance(getToggleButton)
471
457
 
472
458
  if (event.key === ESCAPE_KEY) {
473
- getToggleButton().focus()
474
- Dropdown.clearMenus()
459
+ instance.hide()
475
460
  return
476
461
  }
477
462
 
478
463
  if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {
479
464
  if (!isActive) {
480
- getToggleButton().click()
465
+ instance.show()
481
466
  }
482
467
 
483
- Dropdown.getInstance(getToggleButton())._selectMenuItem(event)
468
+ instance._selectMenuItem(event)
484
469
  return
485
470
  }
486
471
 
@@ -502,7 +487,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus)
502
487
  EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)
503
488
  EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
504
489
  event.preventDefault()
505
- Dropdown.dropdownInterface(this)
490
+ Dropdown.getOrCreateInstance(this).toggle()
506
491
  })
507
492
 
508
493
  /**