@coreui/coreui 4.0.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 (203) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +183 -0
  3. package/dist/css/coreui-grid.css +5004 -0
  4. package/dist/css/coreui-grid.css.map +1 -0
  5. package/dist/css/coreui-grid.min.css +8 -0
  6. package/dist/css/coreui-grid.min.css.map +1 -0
  7. package/dist/css/coreui-grid.rtl.css +5011 -0
  8. package/dist/css/coreui-grid.rtl.css.map +1 -0
  9. package/dist/css/coreui-grid.rtl.min.css +14 -0
  10. package/dist/css/coreui-grid.rtl.min.css.map +1 -0
  11. package/dist/css/coreui-reboot.css +440 -0
  12. package/dist/css/coreui-reboot.css.map +1 -0
  13. package/dist/css/coreui-reboot.min.css +8 -0
  14. package/dist/css/coreui-reboot.min.css.map +1 -0
  15. package/dist/css/coreui-reboot.rtl.css +441 -0
  16. package/dist/css/coreui-reboot.rtl.css.map +1 -0
  17. package/dist/css/coreui-reboot.rtl.min.css +14 -0
  18. package/dist/css/coreui-reboot.rtl.min.css.map +1 -0
  19. package/dist/css/coreui-utilities.css +5030 -0
  20. package/dist/css/coreui-utilities.css.map +1 -0
  21. package/dist/css/coreui-utilities.min.css +8 -0
  22. package/dist/css/coreui-utilities.min.css.map +1 -0
  23. package/dist/css/coreui-utilities.rtl.css +5024 -0
  24. package/dist/css/coreui-utilities.rtl.css.map +1 -0
  25. package/dist/css/coreui-utilities.rtl.min.css +14 -0
  26. package/dist/css/coreui-utilities.rtl.min.css.map +1 -0
  27. package/dist/css/coreui.css +12152 -0
  28. package/dist/css/coreui.css.map +1 -0
  29. package/dist/css/coreui.min.css +8 -0
  30. package/dist/css/coreui.min.css.map +1 -0
  31. package/dist/css/coreui.rtl.css +12041 -0
  32. package/dist/css/coreui.rtl.css.map +1 -0
  33. package/dist/css/coreui.rtl.min.css +14 -0
  34. package/dist/css/coreui.rtl.min.css.map +1 -0
  35. package/dist/js/coreui.bundle.js +7437 -0
  36. package/dist/js/coreui.bundle.js.map +1 -0
  37. package/dist/js/coreui.bundle.min.js +7 -0
  38. package/dist/js/coreui.bundle.min.js.map +1 -0
  39. package/dist/js/coreui.esm.js +5622 -0
  40. package/dist/js/coreui.esm.js.map +1 -0
  41. package/dist/js/coreui.esm.min.js +7 -0
  42. package/dist/js/coreui.esm.min.js.map +1 -0
  43. package/dist/js/coreui.js +5673 -0
  44. package/dist/js/coreui.js.map +1 -0
  45. package/dist/js/coreui.min.js +7 -0
  46. package/dist/js/coreui.min.js.map +1 -0
  47. package/js/dist/alert.js +208 -0
  48. package/js/dist/alert.js.map +1 -0
  49. package/js/dist/base-component.js +181 -0
  50. package/js/dist/base-component.js.map +1 -0
  51. package/js/dist/button.js +142 -0
  52. package/js/dist/button.js.map +1 -0
  53. package/js/dist/carousel.js +724 -0
  54. package/js/dist/carousel.js.map +1 -0
  55. package/js/dist/collapse.js +515 -0
  56. package/js/dist/collapse.js.map +1 -0
  57. package/js/dist/dom/data.js +72 -0
  58. package/js/dist/dom/data.js.map +1 -0
  59. package/js/dist/dom/event-handler.js +319 -0
  60. package/js/dist/dom/event-handler.js.map +1 -0
  61. package/js/dist/dom/manipulator.js +92 -0
  62. package/js/dist/dom/manipulator.js.map +1 -0
  63. package/js/dist/dom/selector-engine.js +89 -0
  64. package/js/dist/dom/selector-engine.js.map +1 -0
  65. package/js/dist/dropdown.js +700 -0
  66. package/js/dist/dropdown.js.map +1 -0
  67. package/js/dist/modal.js +891 -0
  68. package/js/dist/modal.js.map +1 -0
  69. package/js/dist/offcanvas.js +724 -0
  70. package/js/dist/offcanvas.js.map +1 -0
  71. package/js/dist/popover.js +220 -0
  72. package/js/dist/popover.js.map +1 -0
  73. package/js/dist/scrollspy.js +387 -0
  74. package/js/dist/scrollspy.js.map +1 -0
  75. package/js/dist/tab.js +317 -0
  76. package/js/dist/tab.js.map +1 -0
  77. package/js/dist/toast.js +331 -0
  78. package/js/dist/toast.js.map +1 -0
  79. package/js/dist/tooltip.js +997 -0
  80. package/js/dist/tooltip.js.map +1 -0
  81. package/js/src/alert.js +128 -0
  82. package/js/src/base-component.js +78 -0
  83. package/js/src/button.js +89 -0
  84. package/js/src/carousel.js +589 -0
  85. package/js/src/collapse.js +391 -0
  86. package/js/src/dom/data.js +60 -0
  87. package/js/src/dom/event-handler.js +352 -0
  88. package/js/src/dom/manipulator.js +83 -0
  89. package/js/src/dom/selector-engine.js +78 -0
  90. package/js/src/dropdown.js +517 -0
  91. package/js/src/modal.js +451 -0
  92. package/js/src/navigation.js +298 -0
  93. package/js/src/offcanvas.js +277 -0
  94. package/js/src/popover.js +173 -0
  95. package/js/src/scrollspy.js +298 -0
  96. package/js/src/sidebar.js +347 -0
  97. package/js/src/tab.js +227 -0
  98. package/js/src/toast.js +245 -0
  99. package/js/src/tooltip.js +750 -0
  100. package/js/src/util/backdrop.js +129 -0
  101. package/js/src/util/index.js +327 -0
  102. package/js/src/util/sanitizer.js +130 -0
  103. package/js/src/util/scrollbar.js +97 -0
  104. package/package.json +166 -0
  105. package/scss/_accordion.scss +118 -0
  106. package/scss/_alert.scss +52 -0
  107. package/scss/_avatar.scss +49 -0
  108. package/scss/_badge.scss +38 -0
  109. package/scss/_breadcrumb.scss +33 -0
  110. package/scss/_button-group.scss +139 -0
  111. package/scss/_buttons.scss +143 -0
  112. package/scss/_callout.scss +16 -0
  113. package/scss/_card.scss +215 -0
  114. package/scss/_carousel.scss +231 -0
  115. package/scss/_close.scss +40 -0
  116. package/scss/_containers.scss +41 -0
  117. package/scss/_dropdown.scss +227 -0
  118. package/scss/_footer.scss +25 -0
  119. package/scss/_forms.scss +9 -0
  120. package/scss/_functions.scss +356 -0
  121. package/scss/_grid.scss +56 -0
  122. package/scss/_header.scss +170 -0
  123. package/scss/_helpers.scss +7 -0
  124. package/scss/_icon.scss +32 -0
  125. package/scss/_images.scss +42 -0
  126. package/scss/_list-group.scss +169 -0
  127. package/scss/_mixins.scss +50 -0
  128. package/scss/_modal.scss +219 -0
  129. package/scss/_nav.scss +140 -0
  130. package/scss/_navbar.scss +254 -0
  131. package/scss/_offcanvas.scss +79 -0
  132. package/scss/_pagination.scss +64 -0
  133. package/scss/_popover.scss +158 -0
  134. package/scss/_progress.scss +91 -0
  135. package/scss/_reboot.scss +632 -0
  136. package/scss/_root.scss +25 -0
  137. package/scss/_sidebar.scss +3 -0
  138. package/scss/_spinners.scss +69 -0
  139. package/scss/_subheader.scss +72 -0
  140. package/scss/_tables.scss +166 -0
  141. package/scss/_toasts.scss +52 -0
  142. package/scss/_tooltip.scss +115 -0
  143. package/scss/_transitions.scss +21 -0
  144. package/scss/_type.scss +104 -0
  145. package/scss/_utilities.scss +678 -0
  146. package/scss/_variables.scss +1801 -0
  147. package/scss/coreui-grid.rtl.scss +12 -0
  148. package/scss/coreui-grid.scss +67 -0
  149. package/scss/coreui-reboot.rtl.scss +12 -0
  150. package/scss/coreui-reboot.scss +15 -0
  151. package/scss/coreui-utilities.rtl.scss +12 -0
  152. package/scss/coreui-utilities.scss +19 -0
  153. package/scss/coreui.rtl.scss +12 -0
  154. package/scss/coreui.scss +61 -0
  155. package/scss/forms/_floating-labels.scss +63 -0
  156. package/scss/forms/_form-check.scss +188 -0
  157. package/scss/forms/_form-control.scss +219 -0
  158. package/scss/forms/_form-range.scss +91 -0
  159. package/scss/forms/_form-select.scss +70 -0
  160. package/scss/forms/_form-text.scss +11 -0
  161. package/scss/forms/_input-group.scss +121 -0
  162. package/scss/forms/_labels.scss +36 -0
  163. package/scss/forms/_validation.scss +12 -0
  164. package/scss/helpers/_clearfix.scss +3 -0
  165. package/scss/helpers/_colored-links.scss +12 -0
  166. package/scss/helpers/_position.scss +30 -0
  167. package/scss/helpers/_ratio.scss +26 -0
  168. package/scss/helpers/_stretched-link.scss +15 -0
  169. package/scss/helpers/_text-truncation.scss +7 -0
  170. package/scss/helpers/_visually-hidden.scss +8 -0
  171. package/scss/mixins/_alert.scss +15 -0
  172. package/scss/mixins/_avatar.scss +10 -0
  173. package/scss/mixins/_border-radius.scss +78 -0
  174. package/scss/mixins/_box-shadow.scss +18 -0
  175. package/scss/mixins/_breakpoints.scss +140 -0
  176. package/scss/mixins/_buttons.scss +101 -0
  177. package/scss/mixins/_caret.scss +64 -0
  178. package/scss/mixins/_clearfix.scss +9 -0
  179. package/scss/mixins/_color-scheme.scss +7 -0
  180. package/scss/mixins/_container.scss +9 -0
  181. package/scss/mixins/_css-vars.scss +87 -0
  182. package/scss/mixins/_deprecate.scss +10 -0
  183. package/scss/mixins/_forms.scss +144 -0
  184. package/scss/mixins/_gradients.scss +47 -0
  185. package/scss/mixins/_grid.scss +132 -0
  186. package/scss/mixins/_icon.scss +6 -0
  187. package/scss/mixins/_image.scss +16 -0
  188. package/scss/mixins/_list-group.scss +18 -0
  189. package/scss/mixins/_lists.scss +7 -0
  190. package/scss/mixins/_ltr-rtl.scss +60 -0
  191. package/scss/mixins/_pagination.scss +31 -0
  192. package/scss/mixins/_reset-text.scss +17 -0
  193. package/scss/mixins/_resize.scss +6 -0
  194. package/scss/mixins/_table-variants.scss +16 -0
  195. package/scss/mixins/_text-truncate.scss +8 -0
  196. package/scss/mixins/_transition.scss +26 -0
  197. package/scss/mixins/_utilities.scss +104 -0
  198. package/scss/mixins/_visually-hidden.scss +29 -0
  199. package/scss/sidebar/_sidebar-narrow.scss +106 -0
  200. package/scss/sidebar/_sidebar-nav.scss +165 -0
  201. package/scss/sidebar/_sidebar.scss +261 -0
  202. package/scss/utilities/_api.scss +47 -0
  203. package/scss/vendor/_rfs.scss +354 -0
@@ -0,0 +1,517 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * CoreUI (v4.0.2): dropdown.js
4
+ * Licensed under MIT (https://coreui.io/license)
5
+ *
6
+ * This component is a modified version of the Bootstrap's dropdown.js
7
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
8
+ * --------------------------------------------------------------------------
9
+ */
10
+
11
+ import * as Popper from '@popperjs/core'
12
+
13
+ import {
14
+ defineJQueryPlugin,
15
+ getElement,
16
+ getElementFromSelector,
17
+ isDisabled,
18
+ isElement,
19
+ isVisible,
20
+ isRTL,
21
+ noop,
22
+ getNextActiveElement,
23
+ typeCheckConfig
24
+ } from './util/index'
25
+ import EventHandler from './dom/event-handler'
26
+ import Manipulator from './dom/manipulator'
27
+ import SelectorEngine from './dom/selector-engine'
28
+ import BaseComponent from './base-component'
29
+
30
+ /**
31
+ * ------------------------------------------------------------------------
32
+ * Constants
33
+ * ------------------------------------------------------------------------
34
+ */
35
+
36
+ const NAME = 'dropdown'
37
+ const DATA_KEY = 'coreui.dropdown'
38
+ const EVENT_KEY = `.${DATA_KEY}`
39
+ const DATA_API_KEY = '.data-api'
40
+
41
+ const ESCAPE_KEY = 'Escape'
42
+ const SPACE_KEY = 'Space'
43
+ const TAB_KEY = 'Tab'
44
+ const ARROW_UP_KEY = 'ArrowUp'
45
+ const ARROW_DOWN_KEY = 'ArrowDown'
46
+ const RIGHT_MOUSE_BUTTON = 2 // MouseEvent.button value for the secondary button, usually the right button
47
+
48
+ const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEY}|${ARROW_DOWN_KEY}|${ESCAPE_KEY}`)
49
+
50
+ const EVENT_HIDE = `hide${EVENT_KEY}`
51
+ const EVENT_HIDDEN = `hidden${EVENT_KEY}`
52
+ const EVENT_SHOW = `show${EVENT_KEY}`
53
+ const EVENT_SHOWN = `shown${EVENT_KEY}`
54
+ const EVENT_CLICK = `click${EVENT_KEY}`
55
+ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
56
+ const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`
57
+ const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`
58
+
59
+ const CLASS_NAME_SHOW = 'show'
60
+ const CLASS_NAME_DROPUP = 'dropup'
61
+ const CLASS_NAME_DROPEND = 'dropend'
62
+ const CLASS_NAME_DROPSTART = 'dropstart'
63
+ const CLASS_NAME_NAVBAR = 'navbar'
64
+
65
+ const SELECTOR_DATA_TOGGLE = '[data-coreui-toggle="dropdown"]'
66
+ const SELECTOR_MENU = '.dropdown-menu'
67
+ const SELECTOR_NAVBAR_NAV = '.navbar-nav'
68
+ const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
69
+
70
+ const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'
71
+ const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'
72
+ const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'
73
+ const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'
74
+ const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'
75
+ const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'
76
+
77
+ const Default = {
78
+ offset: [0, 2],
79
+ boundary: 'clippingParents',
80
+ reference: 'toggle',
81
+ display: 'dynamic',
82
+ popperConfig: null,
83
+ autoClose: true
84
+ }
85
+
86
+ const DefaultType = {
87
+ offset: '(array|string|function)',
88
+ boundary: '(string|element)',
89
+ reference: '(string|element|object)',
90
+ display: 'string',
91
+ popperConfig: '(null|object|function)',
92
+ autoClose: '(boolean|string)'
93
+ }
94
+
95
+ /**
96
+ * ------------------------------------------------------------------------
97
+ * Class Definition
98
+ * ------------------------------------------------------------------------
99
+ */
100
+
101
+ class Dropdown extends BaseComponent {
102
+ constructor(element, config) {
103
+ super(element)
104
+
105
+ this._popper = null
106
+ this._config = this._getConfig(config)
107
+ this._menu = this._getMenuElement()
108
+ this._inNavbar = this._detectNavbar()
109
+
110
+ this._addEventListeners()
111
+ }
112
+
113
+ // Getters
114
+
115
+ static get Default() {
116
+ return Default
117
+ }
118
+
119
+ static get DefaultType() {
120
+ return DefaultType
121
+ }
122
+
123
+ static get NAME() {
124
+ return NAME
125
+ }
126
+
127
+ // Public
128
+
129
+ 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()
142
+ }
143
+
144
+ show() {
145
+ if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW)) {
146
+ return
147
+ }
148
+
149
+ const parent = Dropdown.getParentFromElement(this._element)
150
+ const relatedTarget = {
151
+ relatedTarget: this._element
152
+ }
153
+
154
+ const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, relatedTarget)
155
+
156
+ if (showEvent.defaultPrevented) {
157
+ return
158
+ }
159
+
160
+ // Totally disable Popper for Dropdowns in Navbar
161
+ if (this._inNavbar) {
162
+ Manipulator.setDataAttribute(this._menu, 'popper', 'none')
163
+ } 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
+ }
186
+ }
187
+
188
+ // If this is a touch-enabled device we add extra
189
+ // empty mouseover listeners to the body's immediate children;
190
+ // only needed because of broken event delegation on iOS
191
+ // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
192
+ if ('ontouchstart' in document.documentElement &&
193
+ !parent.closest(SELECTOR_NAVBAR_NAV)) {
194
+ [].concat(...document.body.children)
195
+ .forEach(elem => EventHandler.on(elem, 'mouseover', noop))
196
+ }
197
+
198
+ this._element.focus()
199
+ this._element.setAttribute('aria-expanded', true)
200
+
201
+ this._menu.classList.toggle(CLASS_NAME_SHOW)
202
+ this._element.classList.toggle(CLASS_NAME_SHOW)
203
+ EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget)
204
+ }
205
+
206
+ hide() {
207
+ if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW)) {
208
+ return
209
+ }
210
+
211
+ const relatedTarget = {
212
+ relatedTarget: this._element
213
+ }
214
+
215
+ this._completeHide(relatedTarget)
216
+ }
217
+
218
+ dispose() {
219
+ if (this._popper) {
220
+ this._popper.destroy()
221
+ }
222
+
223
+ super.dispose()
224
+ }
225
+
226
+ update() {
227
+ this._inNavbar = this._detectNavbar()
228
+ if (this._popper) {
229
+ this._popper.update()
230
+ }
231
+ }
232
+
233
+ // Private
234
+
235
+ _addEventListeners() {
236
+ EventHandler.on(this._element, EVENT_CLICK, event => {
237
+ event.preventDefault()
238
+ this.toggle()
239
+ })
240
+ }
241
+
242
+ _completeHide(relatedTarget) {
243
+ const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget)
244
+ if (hideEvent.defaultPrevented) {
245
+ return
246
+ }
247
+
248
+ // If this is a touch-enabled device we remove the extra
249
+ // empty mouseover listeners we added for iOS support
250
+ if ('ontouchstart' in document.documentElement) {
251
+ [].concat(...document.body.children)
252
+ .forEach(elem => EventHandler.off(elem, 'mouseover', noop))
253
+ }
254
+
255
+ if (this._popper) {
256
+ this._popper.destroy()
257
+ }
258
+
259
+ this._menu.classList.remove(CLASS_NAME_SHOW)
260
+ this._element.classList.remove(CLASS_NAME_SHOW)
261
+ this._element.setAttribute('aria-expanded', 'false')
262
+ Manipulator.removeDataAttribute(this._menu, 'popper')
263
+ EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)
264
+ }
265
+
266
+ _getConfig(config) {
267
+ config = {
268
+ ...this.constructor.Default,
269
+ ...Manipulator.getDataAttributes(this._element),
270
+ ...config
271
+ }
272
+
273
+ typeCheckConfig(NAME, config, this.constructor.DefaultType)
274
+
275
+ if (typeof config.reference === 'object' && !isElement(config.reference) &&
276
+ typeof config.reference.getBoundingClientRect !== 'function'
277
+ ) {
278
+ // Popper virtual elements require a getBoundingClientRect method
279
+ throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
280
+ }
281
+
282
+ return config
283
+ }
284
+
285
+ _getMenuElement() {
286
+ return SelectorEngine.next(this._element, SELECTOR_MENU)[0]
287
+ }
288
+
289
+ _getPlacement() {
290
+ const parentDropdown = this._element.parentNode
291
+
292
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
293
+ return PLACEMENT_RIGHT
294
+ }
295
+
296
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
297
+ return PLACEMENT_LEFT
298
+ }
299
+
300
+ // We need to trim the value because custom properties can also include spaces
301
+ const isEnd = getComputedStyle(this._menu).getPropertyValue('--cui-position').trim() === 'end'
302
+
303
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {
304
+ return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP
305
+ }
306
+
307
+ return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM
308
+ }
309
+
310
+ _detectNavbar() {
311
+ return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null
312
+ }
313
+
314
+ _getOffset() {
315
+ const { offset } = this._config
316
+
317
+ if (typeof offset === 'string') {
318
+ return offset.split(',').map(val => Number.parseInt(val, 10))
319
+ }
320
+
321
+ if (typeof offset === 'function') {
322
+ return popperData => offset(popperData, this._element)
323
+ }
324
+
325
+ return offset
326
+ }
327
+
328
+ _getPopperConfig() {
329
+ const defaultBsPopperConfig = {
330
+ placement: this._getPlacement(),
331
+ modifiers: [{
332
+ name: 'preventOverflow',
333
+ options: {
334
+ boundary: this._config.boundary
335
+ }
336
+ },
337
+ {
338
+ name: 'offset',
339
+ options: {
340
+ offset: this._getOffset()
341
+ }
342
+ }]
343
+ }
344
+
345
+ // Disable Popper if we have a static display
346
+ if (this._config.display === 'static') {
347
+ defaultBsPopperConfig.modifiers = [{
348
+ name: 'applyStyles',
349
+ enabled: false
350
+ }]
351
+ }
352
+
353
+ return {
354
+ ...defaultBsPopperConfig,
355
+ ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
356
+ }
357
+ }
358
+
359
+ _selectMenuItem({ key, target }) {
360
+ const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible)
361
+
362
+ if (!items.length) {
363
+ return
364
+ }
365
+
366
+ // if target isn't included in items (e.g. when expanding the dropdown)
367
+ // allow cycling to get the last item in case key equals ARROW_UP_KEY
368
+ getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()
369
+ }
370
+
371
+ // Static
372
+
373
+ static dropdownInterface(element, config) {
374
+ const data = Dropdown.getOrCreateInstance(element, config)
375
+
376
+ if (typeof config === 'string') {
377
+ if (typeof data[config] === 'undefined') {
378
+ throw new TypeError(`No method named "${config}"`)
379
+ }
380
+
381
+ data[config]()
382
+ }
383
+ }
384
+
385
+ static jQueryInterface(config) {
386
+ return this.each(function () {
387
+ Dropdown.dropdownInterface(this, config)
388
+ })
389
+ }
390
+
391
+ static clearMenus(event) {
392
+ if (event && (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY))) {
393
+ return
394
+ }
395
+
396
+ const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
397
+
398
+ for (let i = 0, len = toggles.length; i < len; i++) {
399
+ const context = Dropdown.getInstance(toggles[i])
400
+ if (!context || context._config.autoClose === false) {
401
+ continue
402
+ }
403
+
404
+ if (!context._element.classList.contains(CLASS_NAME_SHOW)) {
405
+ continue
406
+ }
407
+
408
+ const relatedTarget = {
409
+ relatedTarget: context._element
410
+ }
411
+
412
+ if (event) {
413
+ const composedPath = event.composedPath()
414
+ const isMenuTarget = composedPath.includes(context._menu)
415
+ if (
416
+ composedPath.includes(context._element) ||
417
+ (context._config.autoClose === 'inside' && !isMenuTarget) ||
418
+ (context._config.autoClose === 'outside' && isMenuTarget)
419
+ ) {
420
+ continue
421
+ }
422
+
423
+ // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
424
+ if (context._menu.contains(event.target) && ((event.type === 'keyup' && event.key === TAB_KEY) || /input|select|option|textarea|form/i.test(event.target.tagName))) {
425
+ continue
426
+ }
427
+
428
+ if (event.type === 'click') {
429
+ relatedTarget.clickEvent = event
430
+ }
431
+ }
432
+
433
+ context._completeHide(relatedTarget)
434
+ }
435
+ }
436
+
437
+ static getParentFromElement(element) {
438
+ return getElementFromSelector(element) || element.parentNode
439
+ }
440
+
441
+ static dataApiKeydownHandler(event) {
442
+ // If not input/textarea:
443
+ // - And not a key in REGEXP_KEYDOWN => not a dropdown command
444
+ // If input/textarea:
445
+ // - If space key => not a dropdown command
446
+ // - If key is other than escape
447
+ // - If key is not up or down => not a dropdown command
448
+ // - If trigger inside the menu => not a dropdown command
449
+ if (/input|textarea/i.test(event.target.tagName) ?
450
+ event.key === SPACE_KEY || (event.key !== ESCAPE_KEY &&
451
+ ((event.key !== ARROW_DOWN_KEY && event.key !== ARROW_UP_KEY) ||
452
+ event.target.closest(SELECTOR_MENU))) :
453
+ !REGEXP_KEYDOWN.test(event.key)) {
454
+ return
455
+ }
456
+
457
+ const isActive = this.classList.contains(CLASS_NAME_SHOW)
458
+
459
+ if (!isActive && event.key === ESCAPE_KEY) {
460
+ return
461
+ }
462
+
463
+ event.preventDefault()
464
+ event.stopPropagation()
465
+
466
+ if (isDisabled(this)) {
467
+ return
468
+ }
469
+
470
+ const getToggleButton = () => this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0]
471
+
472
+ if (event.key === ESCAPE_KEY) {
473
+ getToggleButton().focus()
474
+ Dropdown.clearMenus()
475
+ return
476
+ }
477
+
478
+ if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {
479
+ if (!isActive) {
480
+ getToggleButton().click()
481
+ }
482
+
483
+ Dropdown.getInstance(getToggleButton())._selectMenuItem(event)
484
+ return
485
+ }
486
+
487
+ if (!isActive || event.key === SPACE_KEY) {
488
+ Dropdown.clearMenus()
489
+ }
490
+ }
491
+ }
492
+
493
+ /**
494
+ * ------------------------------------------------------------------------
495
+ * Data Api implementation
496
+ * ------------------------------------------------------------------------
497
+ */
498
+
499
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)
500
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)
501
+ EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus)
502
+ EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)
503
+ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
504
+ event.preventDefault()
505
+ Dropdown.dropdownInterface(this)
506
+ })
507
+
508
+ /**
509
+ * ------------------------------------------------------------------------
510
+ * jQuery
511
+ * ------------------------------------------------------------------------
512
+ * add .Dropdown to jQuery only if jQuery is present
513
+ */
514
+
515
+ defineJQueryPlugin(Dropdown)
516
+
517
+ export default Dropdown