bootstrap 5.1.3 → 5.2.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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/javascripts/bootstrap/alert.js +11 -146
  4. data/assets/javascripts/bootstrap/base-component.js +37 -120
  5. data/assets/javascripts/bootstrap/button.js +10 -74
  6. data/assets/javascripts/bootstrap/carousel.js +213 -485
  7. data/assets/javascripts/bootstrap/collapse.js +65 -249
  8. data/assets/javascripts/bootstrap/dom/data.js +3 -5
  9. data/assets/javascripts/bootstrap/dom/event-handler.js +94 -132
  10. data/assets/javascripts/bootstrap/dom/manipulator.js +23 -27
  11. data/assets/javascripts/bootstrap/dom/selector-engine.js +16 -58
  12. data/assets/javascripts/bootstrap/dropdown.js +101 -317
  13. data/assets/javascripts/bootstrap/modal.js +107 -752
  14. data/assets/javascripts/bootstrap/offcanvas.js +90 -659
  15. data/assets/javascripts/bootstrap/popover.js +36 -118
  16. data/assets/javascripts/bootstrap/scrollspy.js +179 -262
  17. data/assets/javascripts/bootstrap/tab.js +215 -214
  18. data/assets/javascripts/bootstrap/toast.js +28 -214
  19. data/assets/javascripts/bootstrap/tooltip.js +268 -611
  20. data/assets/javascripts/bootstrap/util/backdrop.js +165 -0
  21. data/assets/javascripts/bootstrap/util/component-functions.js +46 -0
  22. data/assets/javascripts/bootstrap/util/config.js +79 -0
  23. data/assets/javascripts/bootstrap/util/focustrap.js +129 -0
  24. data/assets/javascripts/bootstrap/util/index.js +350 -0
  25. data/assets/javascripts/bootstrap/util/sanitizer.js +122 -0
  26. data/assets/javascripts/bootstrap/util/scrollbar.js +138 -0
  27. data/assets/javascripts/bootstrap/util/swipe.js +155 -0
  28. data/assets/javascripts/bootstrap/util/template-factory.js +177 -0
  29. data/assets/javascripts/bootstrap-global-this-define.js +1 -1
  30. data/assets/javascripts/bootstrap-sprockets.js +10 -1
  31. data/assets/javascripts/bootstrap.js +2065 -1860
  32. data/assets/javascripts/bootstrap.min.js +3 -3
  33. data/assets/stylesheets/_bootstrap-grid.scss +3 -6
  34. data/assets/stylesheets/_bootstrap-reboot.scss +3 -7
  35. data/assets/stylesheets/_bootstrap.scss +4 -6
  36. data/assets/stylesheets/bootstrap/_accordion.scss +52 -24
  37. data/assets/stylesheets/bootstrap/_alert.scss +18 -4
  38. data/assets/stylesheets/bootstrap/_badge.scss +14 -5
  39. data/assets/stylesheets/bootstrap/_breadcrumb.scss +22 -10
  40. data/assets/stylesheets/bootstrap/_button-group.scss +3 -0
  41. data/assets/stylesheets/bootstrap/_buttons.scss +97 -22
  42. data/assets/stylesheets/bootstrap/_card.scss +55 -37
  43. data/assets/stylesheets/bootstrap/_close.scss +1 -1
  44. data/assets/stylesheets/bootstrap/_containers.scss +1 -1
  45. data/assets/stylesheets/bootstrap/_dropdown.scss +83 -75
  46. data/assets/stylesheets/bootstrap/_functions.scss +7 -7
  47. data/assets/stylesheets/bootstrap/_grid.scss +3 -3
  48. data/assets/stylesheets/bootstrap/_helpers.scss +1 -0
  49. data/assets/stylesheets/bootstrap/_list-group.scss +44 -27
  50. data/assets/stylesheets/bootstrap/_maps.scss +54 -0
  51. data/assets/stylesheets/bootstrap/_modal.scss +71 -43
  52. data/assets/stylesheets/bootstrap/_nav.scss +53 -20
  53. data/assets/stylesheets/bootstrap/_navbar.scss +91 -150
  54. data/assets/stylesheets/bootstrap/_offcanvas.scss +119 -59
  55. data/assets/stylesheets/bootstrap/_pagination.scss +66 -21
  56. data/assets/stylesheets/bootstrap/_placeholders.scss +1 -1
  57. data/assets/stylesheets/bootstrap/_popover.scss +90 -52
  58. data/assets/stylesheets/bootstrap/_progress.scss +20 -9
  59. data/assets/stylesheets/bootstrap/_reboot.scss +25 -40
  60. data/assets/stylesheets/bootstrap/_root.scss +40 -21
  61. data/assets/stylesheets/bootstrap/_spinners.scss +38 -22
  62. data/assets/stylesheets/bootstrap/_tables.scss +32 -23
  63. data/assets/stylesheets/bootstrap/_toasts.scss +35 -16
  64. data/assets/stylesheets/bootstrap/_tooltip.scss +61 -56
  65. data/assets/stylesheets/bootstrap/_type.scss +2 -0
  66. data/assets/stylesheets/bootstrap/_utilities.scss +43 -26
  67. data/assets/stylesheets/bootstrap/_variables.scss +113 -121
  68. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +3 -6
  69. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +14 -3
  70. data/assets/stylesheets/bootstrap/forms/_form-check.scss +28 -5
  71. data/assets/stylesheets/bootstrap/forms/_form-control.scss +12 -37
  72. data/assets/stylesheets/bootstrap/forms/_form-select.scss +0 -1
  73. data/assets/stylesheets/bootstrap/forms/_input-group.scss +15 -7
  74. data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +10 -0
  75. data/assets/stylesheets/bootstrap/helpers/_colored-links.scss +2 -2
  76. data/assets/stylesheets/bootstrap/helpers/_position.scss +7 -1
  77. data/assets/stylesheets/bootstrap/helpers/_ratio.scss +2 -2
  78. data/assets/stylesheets/bootstrap/helpers/_vr.scss +1 -1
  79. data/assets/stylesheets/bootstrap/mixins/_alert.scss +7 -3
  80. data/assets/stylesheets/bootstrap/mixins/_banner.scss +9 -0
  81. data/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +8 -8
  82. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +32 -95
  83. data/assets/stylesheets/bootstrap/mixins/_container.scss +4 -2
  84. data/assets/stylesheets/bootstrap/mixins/_forms.scss +8 -0
  85. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +1 -1
  86. data/assets/stylesheets/bootstrap/mixins/_grid.scss +12 -12
  87. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +4 -25
  88. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +1 -1
  89. data/assets/stylesheets/bootstrap/mixins/_table-variants.scss +12 -9
  90. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +12 -4
  91. data/bootstrap.gemspec +1 -1
  92. data/lib/bootstrap/version.rb +2 -2
  93. data/tasks/updater/js.rb +9 -4
  94. metadata +16 -4
@@ -1,19 +1,19 @@
1
1
  /*!
2
- * Bootstrap dropdown.js v5.1.3 (https://getbootstrap.com/)
3
- * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap dropdown.js v5.2.0 (https://getbootstrap.com/)
3
+ * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  */
6
6
  (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) :
8
- typeof define === 'function' && define.amd ? define(['@popperjs/core', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Dropdown = factory(global.Popper, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base));
10
- })(this, (function (Popper, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./util/index'), require('./dom/event-handler'), require('./dom/manipulator'), require('./dom/selector-engine'), require('./base-component')) :
8
+ typeof define === 'function' && define.amd ? define(['@popperjs/core', './util/index', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Dropdown = factory(global["@popperjs/core"], global.Index, global.EventHandler, global.Manipulator, global.SelectorEngine, global.BaseComponent));
10
+ })(this, (function (Popper, index, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
11
11
 
12
12
  const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
13
 
14
14
  function _interopNamespace(e) {
15
15
  if (e && e.__esModule) return e;
16
- const n = Object.create(null);
16
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
17
17
  if (e) {
18
18
  for (const k in e) {
19
19
  if (k !== 'default') {
@@ -37,198 +37,12 @@
37
37
 
38
38
  /**
39
39
  * --------------------------------------------------------------------------
40
- * Bootstrap (v5.1.3): util/index.js
40
+ * Bootstrap (v5.2.0): dropdown.js
41
41
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
42
42
  * --------------------------------------------------------------------------
43
43
  */
44
-
45
- const toType = obj => {
46
- if (obj === null || obj === undefined) {
47
- return `${obj}`;
48
- }
49
-
50
- return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
51
- };
52
-
53
- const getSelector = element => {
54
- let selector = element.getAttribute('data-bs-target');
55
-
56
- if (!selector || selector === '#') {
57
- let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,
58
- // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
59
- // `document.querySelector` will rightfully complain it is invalid.
60
- // See https://github.com/twbs/bootstrap/issues/32273
61
-
62
- if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) {
63
- return null;
64
- } // Just in case some CMS puts out a full URL with the anchor appended
65
-
66
-
67
- if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
68
- hrefAttr = `#${hrefAttr.split('#')[1]}`;
69
- }
70
-
71
- selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
72
- }
73
-
74
- return selector;
75
- };
76
-
77
- const getElementFromSelector = element => {
78
- const selector = getSelector(element);
79
- return selector ? document.querySelector(selector) : null;
80
- };
81
-
82
- const isElement = obj => {
83
- if (!obj || typeof obj !== 'object') {
84
- return false;
85
- }
86
-
87
- if (typeof obj.jquery !== 'undefined') {
88
- obj = obj[0];
89
- }
90
-
91
- return typeof obj.nodeType !== 'undefined';
92
- };
93
-
94
- const getElement = obj => {
95
- if (isElement(obj)) {
96
- // it's a jQuery object or a node element
97
- return obj.jquery ? obj[0] : obj;
98
- }
99
-
100
- if (typeof obj === 'string' && obj.length > 0) {
101
- return document.querySelector(obj);
102
- }
103
-
104
- return null;
105
- };
106
-
107
- const typeCheckConfig = (componentName, config, configTypes) => {
108
- Object.keys(configTypes).forEach(property => {
109
- const expectedTypes = configTypes[property];
110
- const value = config[property];
111
- const valueType = value && isElement(value) ? 'element' : toType(value);
112
-
113
- if (!new RegExp(expectedTypes).test(valueType)) {
114
- throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
115
- }
116
- });
117
- };
118
-
119
- const isVisible = element => {
120
- if (!isElement(element) || element.getClientRects().length === 0) {
121
- return false;
122
- }
123
-
124
- return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
125
- };
126
-
127
- const isDisabled = element => {
128
- if (!element || element.nodeType !== Node.ELEMENT_NODE) {
129
- return true;
130
- }
131
-
132
- if (element.classList.contains('disabled')) {
133
- return true;
134
- }
135
-
136
- if (typeof element.disabled !== 'undefined') {
137
- return element.disabled;
138
- }
139
-
140
- return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
141
- };
142
-
143
- const noop = () => {};
144
-
145
- const getjQuery = () => {
146
- const {
147
- jQuery
148
- } = window;
149
-
150
- if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
151
- return jQuery;
152
- }
153
-
154
- return null;
155
- };
156
-
157
- const DOMContentLoadedCallbacks = [];
158
-
159
- const onDOMContentLoaded = callback => {
160
- if (document.readyState === 'loading') {
161
- // add listener on the first call when the document is in loading state
162
- if (!DOMContentLoadedCallbacks.length) {
163
- document.addEventListener('DOMContentLoaded', () => {
164
- DOMContentLoadedCallbacks.forEach(callback => callback());
165
- });
166
- }
167
-
168
- DOMContentLoadedCallbacks.push(callback);
169
- } else {
170
- callback();
171
- }
172
- };
173
-
174
- const isRTL = () => document.documentElement.dir === 'rtl';
175
-
176
- const defineJQueryPlugin = plugin => {
177
- onDOMContentLoaded(() => {
178
- const $ = getjQuery();
179
- /* istanbul ignore if */
180
-
181
- if ($) {
182
- const name = plugin.NAME;
183
- const JQUERY_NO_CONFLICT = $.fn[name];
184
- $.fn[name] = plugin.jQueryInterface;
185
- $.fn[name].Constructor = plugin;
186
-
187
- $.fn[name].noConflict = () => {
188
- $.fn[name] = JQUERY_NO_CONFLICT;
189
- return plugin.jQueryInterface;
190
- };
191
- }
192
- });
193
- };
194
- /**
195
- * Return the previous/next element of a list.
196
- *
197
- * @param {array} list The list of elements
198
- * @param activeElement The active element
199
- * @param shouldGetNext Choose to get next or previous element
200
- * @param isCycleAllowed
201
- * @return {Element|elem} The proper element
202
- */
203
-
204
-
205
- const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
206
- let index = list.indexOf(activeElement); // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
207
-
208
- if (index === -1) {
209
- return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];
210
- }
211
-
212
- const listLength = list.length;
213
- index += shouldGetNext ? 1 : -1;
214
-
215
- if (isCycleAllowed) {
216
- index = (index + listLength) % listLength;
217
- }
218
-
219
- return list[Math.max(0, Math.min(index, listLength - 1))];
220
- };
221
-
222
44
  /**
223
- * --------------------------------------------------------------------------
224
- * Bootstrap (v5.1.3): dropdown.js
225
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
226
- * --------------------------------------------------------------------------
227
- */
228
- /**
229
- * ------------------------------------------------------------------------
230
45
  * Constants
231
- * ------------------------------------------------------------------------
232
46
  */
233
47
 
234
48
  const NAME = 'dropdown';
@@ -236,13 +50,11 @@
236
50
  const EVENT_KEY = `.${DATA_KEY}`;
237
51
  const DATA_API_KEY = '.data-api';
238
52
  const ESCAPE_KEY = 'Escape';
239
- const SPACE_KEY = 'Space';
240
53
  const TAB_KEY = 'Tab';
241
54
  const ARROW_UP_KEY = 'ArrowUp';
242
55
  const ARROW_DOWN_KEY = 'ArrowDown';
243
56
  const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button
244
57
 
245
- const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEY}|${ARROW_DOWN_KEY}|${ESCAPE_KEY}`);
246
58
  const EVENT_HIDE = `hide${EVENT_KEY}`;
247
59
  const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
248
60
  const EVENT_SHOW = `show${EVENT_KEY}`;
@@ -254,45 +66,49 @@
254
66
  const CLASS_NAME_DROPUP = 'dropup';
255
67
  const CLASS_NAME_DROPEND = 'dropend';
256
68
  const CLASS_NAME_DROPSTART = 'dropstart';
257
- const CLASS_NAME_NAVBAR = 'navbar';
258
- const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]';
69
+ const CLASS_NAME_DROPUP_CENTER = 'dropup-center';
70
+ const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center';
71
+ const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)';
72
+ const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}`;
259
73
  const SELECTOR_MENU = '.dropdown-menu';
74
+ const SELECTOR_NAVBAR = '.navbar';
260
75
  const SELECTOR_NAVBAR_NAV = '.navbar-nav';
261
76
  const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';
262
- const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start';
263
- const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end';
264
- const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start';
265
- const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end';
266
- const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start';
267
- const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start';
77
+ const PLACEMENT_TOP = index.isRTL() ? 'top-end' : 'top-start';
78
+ const PLACEMENT_TOPEND = index.isRTL() ? 'top-start' : 'top-end';
79
+ const PLACEMENT_BOTTOM = index.isRTL() ? 'bottom-end' : 'bottom-start';
80
+ const PLACEMENT_BOTTOMEND = index.isRTL() ? 'bottom-start' : 'bottom-end';
81
+ const PLACEMENT_RIGHT = index.isRTL() ? 'left-start' : 'right-start';
82
+ const PLACEMENT_LEFT = index.isRTL() ? 'right-start' : 'left-start';
83
+ const PLACEMENT_TOPCENTER = 'top';
84
+ const PLACEMENT_BOTTOMCENTER = 'bottom';
268
85
  const Default = {
269
- offset: [0, 2],
86
+ autoClose: true,
270
87
  boundary: 'clippingParents',
271
- reference: 'toggle',
272
88
  display: 'dynamic',
89
+ offset: [0, 2],
273
90
  popperConfig: null,
274
- autoClose: true
91
+ reference: 'toggle'
275
92
  };
276
93
  const DefaultType = {
277
- offset: '(array|string|function)',
94
+ autoClose: '(boolean|string)',
278
95
  boundary: '(string|element)',
279
- reference: '(string|element|object)',
280
96
  display: 'string',
97
+ offset: '(array|string|function)',
281
98
  popperConfig: '(null|object|function)',
282
- autoClose: '(boolean|string)'
99
+ reference: '(string|element|object)'
283
100
  };
284
101
  /**
285
- * ------------------------------------------------------------------------
286
- * Class Definition
287
- * ------------------------------------------------------------------------
102
+ * Class definition
288
103
  */
289
104
 
290
105
  class Dropdown extends BaseComponent__default.default {
291
106
  constructor(element, config) {
292
- super(element);
107
+ super(element, config);
293
108
  this._popper = null;
294
- this._config = this._getConfig(config);
295
- this._menu = this._getMenuElement();
109
+ this._parent = this._element.parentNode; // dropdown wrapper
110
+
111
+ this._menu = SelectorEngine__default.default.findOne(SELECTOR_MENU, this._parent);
296
112
  this._inNavbar = this._detectNavbar();
297
113
  } // Getters
298
114
 
@@ -315,7 +131,7 @@
315
131
  }
316
132
 
317
133
  show() {
318
- if (isDisabled(this._element) || this._isShown(this._menu)) {
134
+ if (index.isDisabled(this._element) || this._isShown()) {
319
135
  return;
320
136
  }
321
137
 
@@ -328,20 +144,16 @@
328
144
  return;
329
145
  }
330
146
 
331
- const parent = Dropdown.getParentFromElement(this._element); // Totally disable Popper for Dropdowns in Navbar
332
-
333
- if (this._inNavbar) {
334
- Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'none');
335
- } else {
336
- this._createPopper(parent);
337
- } // If this is a touch-enabled device we add extra
147
+ this._createPopper(); // If this is a touch-enabled device we add extra
338
148
  // empty mouseover listeners to the body's immediate children;
339
149
  // only needed because of broken event delegation on iOS
340
150
  // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
341
151
 
342
152
 
343
- if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) {
344
- [].concat(...document.body.children).forEach(elem => EventHandler__default.default.on(elem, 'mouseover', noop));
153
+ if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
154
+ for (const element of [].concat(...document.body.children)) {
155
+ EventHandler__default.default.on(element, 'mouseover', index.noop);
156
+ }
345
157
  }
346
158
 
347
159
  this._element.focus();
@@ -356,7 +168,7 @@
356
168
  }
357
169
 
358
170
  hide() {
359
- if (isDisabled(this._element) || !this._isShown(this._menu)) {
171
+ if (index.isDisabled(this._element) || !this._isShown()) {
360
172
  return;
361
173
  }
362
174
 
@@ -394,7 +206,9 @@
394
206
 
395
207
 
396
208
  if ('ontouchstart' in document.documentElement) {
397
- [].concat(...document.body.children).forEach(elem => EventHandler__default.default.off(elem, 'mouseover', noop));
209
+ for (const element of [].concat(...document.body.children)) {
210
+ EventHandler__default.default.off(element, 'mouseover', index.noop);
211
+ }
398
212
  }
399
213
 
400
214
  if (this._popper) {
@@ -412,13 +226,9 @@
412
226
  }
413
227
 
414
228
  _getConfig(config) {
415
- config = { ...this.constructor.Default,
416
- ...Manipulator__default.default.getDataAttributes(this._element),
417
- ...config
418
- };
419
- typeCheckConfig(NAME, config, this.constructor.DefaultType);
229
+ config = super._getConfig(config);
420
230
 
421
- if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {
231
+ if (typeof config.reference === 'object' && !index.isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {
422
232
  // Popper virtual elements require a getBoundingClientRect method
423
233
  throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);
424
234
  }
@@ -426,7 +236,7 @@
426
236
  return config;
427
237
  }
428
238
 
429
- _createPopper(parent) {
239
+ _createPopper() {
430
240
  if (typeof Popper__namespace === 'undefined') {
431
241
  throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
432
242
  }
@@ -434,33 +244,24 @@
434
244
  let referenceElement = this._element;
435
245
 
436
246
  if (this._config.reference === 'parent') {
437
- referenceElement = parent;
438
- } else if (isElement(this._config.reference)) {
439
- referenceElement = getElement(this._config.reference);
247
+ referenceElement = this._parent;
248
+ } else if (index.isElement(this._config.reference)) {
249
+ referenceElement = index.getElement(this._config.reference);
440
250
  } else if (typeof this._config.reference === 'object') {
441
251
  referenceElement = this._config.reference;
442
252
  }
443
253
 
444
254
  const popperConfig = this._getPopperConfig();
445
255
 
446
- const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false);
447
256
  this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig);
448
-
449
- if (isDisplayStatic) {
450
- Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'static');
451
- }
452
257
  }
453
258
 
454
- _isShown(element = this._element) {
455
- return element.classList.contains(CLASS_NAME_SHOW);
456
- }
457
-
458
- _getMenuElement() {
459
- return SelectorEngine__default.default.next(this._element, SELECTOR_MENU)[0];
259
+ _isShown() {
260
+ return this._menu.classList.contains(CLASS_NAME_SHOW);
460
261
  }
461
262
 
462
263
  _getPlacement() {
463
- const parentDropdown = this._element.parentNode;
264
+ const parentDropdown = this._parent;
464
265
 
465
266
  if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
466
267
  return PLACEMENT_RIGHT;
@@ -468,6 +269,14 @@
468
269
 
469
270
  if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
470
271
  return PLACEMENT_LEFT;
272
+ }
273
+
274
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {
275
+ return PLACEMENT_TOPCENTER;
276
+ }
277
+
278
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {
279
+ return PLACEMENT_BOTTOMCENTER;
471
280
  } // We need to trim the value because custom properties can also include spaces
472
281
 
473
282
 
@@ -481,7 +290,7 @@
481
290
  }
482
291
 
483
292
  _detectNavbar() {
484
- return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null;
293
+ return this._element.closest(SELECTOR_NAVBAR) !== null;
485
294
  }
486
295
 
487
296
  _getOffset() {
@@ -490,7 +299,7 @@
490
299
  } = this._config;
491
300
 
492
301
  if (typeof offset === 'string') {
493
- return offset.split(',').map(val => Number.parseInt(val, 10));
302
+ return offset.split(',').map(value => Number.parseInt(value, 10));
494
303
  }
495
304
 
496
305
  if (typeof offset === 'function') {
@@ -514,9 +323,11 @@
514
323
  offset: this._getOffset()
515
324
  }
516
325
  }]
517
- }; // Disable Popper if we have a static display
326
+ }; // Disable Popper if we have a static display or Dropdown is in Navbar
327
+
328
+ if (this._inNavbar || this._config.display === 'static') {
329
+ Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'static'); // todo:v6 remove
518
330
 
519
- if (this._config.display === 'static') {
520
331
  defaultBsPopperConfig.modifiers = [{
521
332
  name: 'applyStyles',
522
333
  enabled: false
@@ -532,7 +343,7 @@
532
343
  key,
533
344
  target
534
345
  }) {
535
- const items = SelectorEngine__default.default.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible);
346
+ const items = SelectorEngine__default.default.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => index.isVisible(element));
536
347
 
537
348
  if (!items.length) {
538
349
  return;
@@ -540,7 +351,7 @@
540
351
  // allow cycling to get the last item in case key equals ARROW_UP_KEY
541
352
 
542
353
 
543
- getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
354
+ index.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
544
355
  } // Static
545
356
 
546
357
 
@@ -561,20 +372,28 @@
561
372
  }
562
373
 
563
374
  static clearMenus(event) {
564
- if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) {
375
+ if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY) {
565
376
  return;
566
377
  }
567
378
 
568
- const toggles = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE);
379
+ const openToggles = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE_SHOWN);
569
380
 
570
- for (let i = 0, len = toggles.length; i < len; i++) {
571
- const context = Dropdown.getInstance(toggles[i]);
381
+ for (const toggle of openToggles) {
382
+ const context = Dropdown.getInstance(toggle);
572
383
 
573
384
  if (!context || context._config.autoClose === false) {
574
385
  continue;
575
386
  }
576
387
 
577
- if (!context._isShown()) {
388
+ const composedPath = event.composedPath();
389
+ const isMenuTarget = composedPath.includes(context._menu);
390
+
391
+ if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {
392
+ continue;
393
+ } // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
394
+
395
+
396
+ if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY || /input|select|option|textarea|form/i.test(event.target.tagName))) {
578
397
  continue;
579
398
  }
580
399
 
@@ -582,85 +401,53 @@
582
401
  relatedTarget: context._element
583
402
  };
584
403
 
585
- if (event) {
586
- const composedPath = event.composedPath();
587
- const isMenuTarget = composedPath.includes(context._menu);
588
-
589
- if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {
590
- continue;
591
- } // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
592
-
593
-
594
- if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY || /input|select|option|textarea|form/i.test(event.target.tagName))) {
595
- continue;
596
- }
597
-
598
- if (event.type === 'click') {
599
- relatedTarget.clickEvent = event;
600
- }
404
+ if (event.type === 'click') {
405
+ relatedTarget.clickEvent = event;
601
406
  }
602
407
 
603
408
  context._completeHide(relatedTarget);
604
409
  }
605
410
  }
606
411
 
607
- static getParentFromElement(element) {
608
- return getElementFromSelector(element) || element.parentNode;
609
- }
610
-
611
412
  static dataApiKeydownHandler(event) {
612
- // If not input/textarea:
613
- // - And not a key in REGEXP_KEYDOWN => not a dropdown command
614
- // If input/textarea:
615
- // - If space key => not a dropdown command
616
- // - If key is other than escape
617
- // - If key is not up or down => not a dropdown command
618
- // - If trigger inside the menu => not a dropdown command
619
- if (/input|textarea/i.test(event.target.tagName) ? event.key === SPACE_KEY || event.key !== ESCAPE_KEY && (event.key !== ARROW_DOWN_KEY && event.key !== ARROW_UP_KEY || event.target.closest(SELECTOR_MENU)) : !REGEXP_KEYDOWN.test(event.key)) {
620
- return;
621
- }
622
-
623
- const isActive = this.classList.contains(CLASS_NAME_SHOW);
413
+ // If not an UP | DOWN | ESCAPE key => not a dropdown command
414
+ // If input/textarea && if key is other than ESCAPE => not a dropdown command
415
+ const isInput = /input|textarea/i.test(event.target.tagName);
416
+ const isEscapeEvent = event.key === ESCAPE_KEY;
417
+ const isUpOrDownEvent = [ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key);
624
418
 
625
- if (!isActive && event.key === ESCAPE_KEY) {
419
+ if (!isUpOrDownEvent && !isEscapeEvent) {
626
420
  return;
627
421
  }
628
422
 
629
- event.preventDefault();
630
- event.stopPropagation();
631
-
632
- if (isDisabled(this)) {
423
+ if (isInput && !isEscapeEvent) {
633
424
  return;
634
425
  }
635
426
 
636
- const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine__default.default.prev(this, SELECTOR_DATA_TOGGLE)[0];
427
+ event.preventDefault();
428
+ const getToggleButton = SelectorEngine__default.default.findOne(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode);
637
429
  const instance = Dropdown.getOrCreateInstance(getToggleButton);
638
430
 
639
- if (event.key === ESCAPE_KEY) {
640
- instance.hide();
641
- return;
642
- }
643
-
644
- if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {
645
- if (!isActive) {
646
- instance.show();
647
- }
431
+ if (isUpOrDownEvent) {
432
+ event.stopPropagation();
433
+ instance.show();
648
434
 
649
435
  instance._selectMenuItem(event);
650
436
 
651
437
  return;
652
438
  }
653
439
 
654
- if (!isActive || event.key === SPACE_KEY) {
655
- Dropdown.clearMenus();
440
+ if (instance._isShown()) {
441
+ // else is escape and we check if it is shown
442
+ event.stopPropagation();
443
+ instance.hide();
444
+ getToggleButton.focus();
656
445
  }
657
446
  }
658
447
 
659
448
  }
660
449
  /**
661
- * ------------------------------------------------------------------------
662
- * Data Api implementation
663
- * ------------------------------------------------------------------------
450
+ * Data API implementation
664
451
  */
665
452
 
666
453
 
@@ -673,13 +460,10 @@
673
460
  Dropdown.getOrCreateInstance(this).toggle();
674
461
  });
675
462
  /**
676
- * ------------------------------------------------------------------------
677
463
  * jQuery
678
- * ------------------------------------------------------------------------
679
- * add .Dropdown to jQuery only if jQuery is present
680
464
  */
681
465
 
682
- defineJQueryPlugin(Dropdown);
466
+ index.defineJQueryPlugin(Dropdown);
683
467
 
684
468
  return Dropdown;
685
469