bootstrap 5.1.3 → 5.2.1

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 +24 -4
  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 +103 -317
  13. data/assets/javascripts/bootstrap/modal.js +107 -749
  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 +183 -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 +272 -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 +2077 -1859
  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 +56 -25
  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 +4 -1
  41. data/assets/stylesheets/bootstrap/_buttons.scss +120 -30
  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 +85 -76
  46. data/assets/stylesheets/bootstrap/_functions.scss +8 -8
  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 +48 -30
  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 +93 -150
  54. data/assets/stylesheets/bootstrap/_offcanvas.scss +120 -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 +36 -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 +128 -135
  68. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +3 -6
  69. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +15 -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 +19 -8
  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 +18 -10
  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 +13 -5
  91. data/bootstrap.gemspec +1 -1
  92. data/lib/bootstrap/version.rb +2 -2
  93. data/tasks/updater/js.rb +10 -5
  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.1 (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
41
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
42
- * --------------------------------------------------------------------------
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
- /**
223
- * --------------------------------------------------------------------------
224
- * Bootstrap (v5.1.3): dropdown.js
40
+ * Bootstrap (v5.2.1): dropdown.js
225
41
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
226
42
  * --------------------------------------------------------------------------
227
43
  */
228
44
  /**
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,50 @@
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
+ // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/
111
+
112
+ this._menu = SelectorEngine__default.default.next(this._element, SELECTOR_MENU)[0] || SelectorEngine__default.default.prev(this._element, SELECTOR_MENU)[0];
296
113
  this._inNavbar = this._detectNavbar();
297
114
  } // Getters
298
115
 
@@ -315,7 +132,7 @@
315
132
  }
316
133
 
317
134
  show() {
318
- if (isDisabled(this._element) || this._isShown(this._menu)) {
135
+ if (index.isDisabled(this._element) || this._isShown()) {
319
136
  return;
320
137
  }
321
138
 
@@ -328,20 +145,16 @@
328
145
  return;
329
146
  }
330
147
 
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
148
+ this._createPopper(); // If this is a touch-enabled device we add extra
338
149
  // empty mouseover listeners to the body's immediate children;
339
150
  // only needed because of broken event delegation on iOS
340
151
  // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
341
152
 
342
153
 
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));
154
+ if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
155
+ for (const element of [].concat(...document.body.children)) {
156
+ EventHandler__default.default.on(element, 'mouseover', index.noop);
157
+ }
345
158
  }
346
159
 
347
160
  this._element.focus();
@@ -356,7 +169,7 @@
356
169
  }
357
170
 
358
171
  hide() {
359
- if (isDisabled(this._element) || !this._isShown(this._menu)) {
172
+ if (index.isDisabled(this._element) || !this._isShown()) {
360
173
  return;
361
174
  }
362
175
 
@@ -394,7 +207,9 @@
394
207
 
395
208
 
396
209
  if ('ontouchstart' in document.documentElement) {
397
- [].concat(...document.body.children).forEach(elem => EventHandler__default.default.off(elem, 'mouseover', noop));
210
+ for (const element of [].concat(...document.body.children)) {
211
+ EventHandler__default.default.off(element, 'mouseover', index.noop);
212
+ }
398
213
  }
399
214
 
400
215
  if (this._popper) {
@@ -412,13 +227,9 @@
412
227
  }
413
228
 
414
229
  _getConfig(config) {
415
- config = { ...this.constructor.Default,
416
- ...Manipulator__default.default.getDataAttributes(this._element),
417
- ...config
418
- };
419
- typeCheckConfig(NAME, config, this.constructor.DefaultType);
230
+ config = super._getConfig(config);
420
231
 
421
- if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {
232
+ if (typeof config.reference === 'object' && !index.isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {
422
233
  // Popper virtual elements require a getBoundingClientRect method
423
234
  throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);
424
235
  }
@@ -426,7 +237,7 @@
426
237
  return config;
427
238
  }
428
239
 
429
- _createPopper(parent) {
240
+ _createPopper() {
430
241
  if (typeof Popper__namespace === 'undefined') {
431
242
  throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
432
243
  }
@@ -434,33 +245,24 @@
434
245
  let referenceElement = this._element;
435
246
 
436
247
  if (this._config.reference === 'parent') {
437
- referenceElement = parent;
438
- } else if (isElement(this._config.reference)) {
439
- referenceElement = getElement(this._config.reference);
248
+ referenceElement = this._parent;
249
+ } else if (index.isElement(this._config.reference)) {
250
+ referenceElement = index.getElement(this._config.reference);
440
251
  } else if (typeof this._config.reference === 'object') {
441
252
  referenceElement = this._config.reference;
442
253
  }
443
254
 
444
255
  const popperConfig = this._getPopperConfig();
445
256
 
446
- const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false);
447
257
  this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig);
448
-
449
- if (isDisplayStatic) {
450
- Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'static');
451
- }
452
258
  }
453
259
 
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];
260
+ _isShown() {
261
+ return this._menu.classList.contains(CLASS_NAME_SHOW);
460
262
  }
461
263
 
462
264
  _getPlacement() {
463
- const parentDropdown = this._element.parentNode;
265
+ const parentDropdown = this._parent;
464
266
 
465
267
  if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
466
268
  return PLACEMENT_RIGHT;
@@ -468,6 +270,14 @@
468
270
 
469
271
  if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
470
272
  return PLACEMENT_LEFT;
273
+ }
274
+
275
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {
276
+ return PLACEMENT_TOPCENTER;
277
+ }
278
+
279
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {
280
+ return PLACEMENT_BOTTOMCENTER;
471
281
  } // We need to trim the value because custom properties can also include spaces
472
282
 
473
283
 
@@ -481,7 +291,7 @@
481
291
  }
482
292
 
483
293
  _detectNavbar() {
484
- return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null;
294
+ return this._element.closest(SELECTOR_NAVBAR) !== null;
485
295
  }
486
296
 
487
297
  _getOffset() {
@@ -490,7 +300,7 @@
490
300
  } = this._config;
491
301
 
492
302
  if (typeof offset === 'string') {
493
- return offset.split(',').map(val => Number.parseInt(val, 10));
303
+ return offset.split(',').map(value => Number.parseInt(value, 10));
494
304
  }
495
305
 
496
306
  if (typeof offset === 'function') {
@@ -514,9 +324,11 @@
514
324
  offset: this._getOffset()
515
325
  }
516
326
  }]
517
- }; // Disable Popper if we have a static display
327
+ }; // Disable Popper if we have a static display or Dropdown is in Navbar
328
+
329
+ if (this._inNavbar || this._config.display === 'static') {
330
+ Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'static'); // todo:v6 remove
518
331
 
519
- if (this._config.display === 'static') {
520
332
  defaultBsPopperConfig.modifiers = [{
521
333
  name: 'applyStyles',
522
334
  enabled: false
@@ -532,7 +344,7 @@
532
344
  key,
533
345
  target
534
346
  }) {
535
- const items = SelectorEngine__default.default.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible);
347
+ const items = SelectorEngine__default.default.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => index.isVisible(element));
536
348
 
537
349
  if (!items.length) {
538
350
  return;
@@ -540,7 +352,7 @@
540
352
  // allow cycling to get the last item in case key equals ARROW_UP_KEY
541
353
 
542
354
 
543
- getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
355
+ index.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
544
356
  } // Static
545
357
 
546
358
 
@@ -561,20 +373,28 @@
561
373
  }
562
374
 
563
375
  static clearMenus(event) {
564
- if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) {
376
+ if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY) {
565
377
  return;
566
378
  }
567
379
 
568
- const toggles = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE);
380
+ const openToggles = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE_SHOWN);
569
381
 
570
- for (let i = 0, len = toggles.length; i < len; i++) {
571
- const context = Dropdown.getInstance(toggles[i]);
382
+ for (const toggle of openToggles) {
383
+ const context = Dropdown.getInstance(toggle);
572
384
 
573
385
  if (!context || context._config.autoClose === false) {
574
386
  continue;
575
387
  }
576
388
 
577
- if (!context._isShown()) {
389
+ const composedPath = event.composedPath();
390
+ const isMenuTarget = composedPath.includes(context._menu);
391
+
392
+ if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {
393
+ continue;
394
+ } // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
395
+
396
+
397
+ if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY || /input|select|option|textarea|form/i.test(event.target.tagName))) {
578
398
  continue;
579
399
  }
580
400
 
@@ -582,85 +402,54 @@
582
402
  relatedTarget: context._element
583
403
  };
584
404
 
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
- }
405
+ if (event.type === 'click') {
406
+ relatedTarget.clickEvent = event;
601
407
  }
602
408
 
603
409
  context._completeHide(relatedTarget);
604
410
  }
605
411
  }
606
412
 
607
- static getParentFromElement(element) {
608
- return getElementFromSelector(element) || element.parentNode;
609
- }
610
-
611
413
  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
- }
414
+ // If not an UP | DOWN | ESCAPE key => not a dropdown command
415
+ // If input/textarea && if key is other than ESCAPE => not a dropdown command
416
+ const isInput = /input|textarea/i.test(event.target.tagName);
417
+ const isEscapeEvent = event.key === ESCAPE_KEY;
418
+ const isUpOrDownEvent = [ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key);
622
419
 
623
- const isActive = this.classList.contains(CLASS_NAME_SHOW);
624
-
625
- if (!isActive && event.key === ESCAPE_KEY) {
420
+ if (!isUpOrDownEvent && !isEscapeEvent) {
626
421
  return;
627
422
  }
628
423
 
629
- event.preventDefault();
630
- event.stopPropagation();
631
-
632
- if (isDisabled(this)) {
424
+ if (isInput && !isEscapeEvent) {
633
425
  return;
634
426
  }
635
427
 
636
- const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine__default.default.prev(this, SELECTOR_DATA_TOGGLE)[0];
637
- const instance = Dropdown.getOrCreateInstance(getToggleButton);
428
+ event.preventDefault(); // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/
638
429
 
639
- if (event.key === ESCAPE_KEY) {
640
- instance.hide();
641
- return;
642
- }
430
+ const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine__default.default.prev(this, SELECTOR_DATA_TOGGLE)[0] || SelectorEngine__default.default.next(this, SELECTOR_DATA_TOGGLE)[0];
431
+ const instance = Dropdown.getOrCreateInstance(getToggleButton);
643
432
 
644
- if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) {
645
- if (!isActive) {
646
- instance.show();
647
- }
433
+ if (isUpOrDownEvent) {
434
+ event.stopPropagation();
435
+ instance.show();
648
436
 
649
437
  instance._selectMenuItem(event);
650
438
 
651
439
  return;
652
440
  }
653
441
 
654
- if (!isActive || event.key === SPACE_KEY) {
655
- Dropdown.clearMenus();
442
+ if (instance._isShown()) {
443
+ // else is escape and we check if it is shown
444
+ event.stopPropagation();
445
+ instance.hide();
446
+ getToggleButton.focus();
656
447
  }
657
448
  }
658
449
 
659
450
  }
660
451
  /**
661
- * ------------------------------------------------------------------------
662
- * Data Api implementation
663
- * ------------------------------------------------------------------------
452
+ * Data API implementation
664
453
  */
665
454
 
666
455
 
@@ -673,13 +462,10 @@
673
462
  Dropdown.getOrCreateInstance(this).toggle();
674
463
  });
675
464
  /**
676
- * ------------------------------------------------------------------------
677
465
  * jQuery
678
- * ------------------------------------------------------------------------
679
- * add .Dropdown to jQuery only if jQuery is present
680
466
  */
681
467
 
682
- defineJQueryPlugin(Dropdown);
468
+ index.defineJQueryPlugin(Dropdown);
683
469
 
684
470
  return Dropdown;
685
471