bootstrap 5.1.3 → 5.3.5

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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +61 -0
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile +1 -0
  5. data/README.md +35 -14
  6. data/Rakefile +16 -5
  7. data/assets/javascripts/bootstrap/alert.js +22 -167
  8. data/assets/javascripts/bootstrap/base-component.js +34 -133
  9. data/assets/javascripts/bootstrap/button.js +19 -86
  10. data/assets/javascripts/bootstrap/carousel.js +209 -564
  11. data/assets/javascripts/bootstrap/collapse.js +78 -324
  12. data/assets/javascripts/bootstrap/dom/data.js +8 -14
  13. data/assets/javascripts/bootstrap/dom/event-handler.js +89 -174
  14. data/assets/javascripts/bootstrap/dom/manipulator.js +22 -39
  15. data/assets/javascripts/bootstrap/dom/selector-engine.js +47 -71
  16. data/assets/javascripts/bootstrap/dropdown.js +135 -420
  17. data/assets/javascripts/bootstrap/modal.js +115 -837
  18. data/assets/javascripts/bootstrap/offcanvas.js +93 -714
  19. data/assets/javascripts/bootstrap/popover.js +42 -130
  20. data/assets/javascripts/bootstrap/scrollspy.js +180 -296
  21. data/assets/javascripts/bootstrap/tab.js +197 -245
  22. data/assets/javascripts/bootstrap/toast.js +52 -276
  23. data/assets/javascripts/bootstrap/tooltip.js +283 -744
  24. data/assets/javascripts/bootstrap/util/backdrop.js +138 -0
  25. data/assets/javascripts/bootstrap/util/component-functions.js +41 -0
  26. data/assets/javascripts/bootstrap/util/config.js +67 -0
  27. data/assets/javascripts/bootstrap/util/focustrap.js +112 -0
  28. data/assets/javascripts/bootstrap/util/index.js +280 -0
  29. data/assets/javascripts/bootstrap/util/sanitizer.js +113 -0
  30. data/assets/javascripts/bootstrap/util/scrollbar.js +112 -0
  31. data/assets/javascripts/bootstrap/util/swipe.js +134 -0
  32. data/assets/javascripts/bootstrap/util/template-factory.js +150 -0
  33. data/assets/javascripts/bootstrap-global-this-define.js +1 -1
  34. data/assets/javascripts/bootstrap-sprockets.js +15 -6
  35. data/assets/javascripts/bootstrap.js +2278 -2831
  36. data/assets/javascripts/bootstrap.min.js +3 -3
  37. data/assets/stylesheets/_bootstrap-grid.scss +4 -9
  38. data/assets/stylesheets/_bootstrap-reboot.scss +4 -7
  39. data/assets/stylesheets/_bootstrap-utilities.scss +19 -0
  40. data/assets/stylesheets/_bootstrap.scss +5 -6
  41. data/assets/stylesheets/bootstrap/_accordion.scss +68 -33
  42. data/assets/stylesheets/bootstrap/_alert.scss +25 -14
  43. data/assets/stylesheets/bootstrap/_badge.scss +14 -5
  44. data/assets/stylesheets/bootstrap/_breadcrumb.scss +22 -10
  45. data/assets/stylesheets/bootstrap/_button-group.scss +12 -4
  46. data/assets/stylesheets/bootstrap/_buttons.scss +133 -28
  47. data/assets/stylesheets/bootstrap/_card.scss +61 -39
  48. data/assets/stylesheets/bootstrap/_carousel.scss +22 -25
  49. data/assets/stylesheets/bootstrap/_close.scss +36 -10
  50. data/assets/stylesheets/bootstrap/_containers.scss +1 -1
  51. data/assets/stylesheets/bootstrap/_dropdown.scss +86 -76
  52. data/assets/stylesheets/bootstrap/_functions.scss +10 -10
  53. data/assets/stylesheets/bootstrap/_grid.scss +9 -3
  54. data/assets/stylesheets/bootstrap/_helpers.scss +3 -0
  55. data/assets/stylesheets/bootstrap/_list-group.scss +81 -56
  56. data/assets/stylesheets/bootstrap/_maps.scss +174 -0
  57. data/assets/stylesheets/bootstrap/_mixins.scss +1 -2
  58. data/assets/stylesheets/bootstrap/_modal.scss +76 -45
  59. data/assets/stylesheets/bootstrap/_nav.scss +87 -29
  60. data/assets/stylesheets/bootstrap/_navbar.scss +102 -148
  61. data/assets/stylesheets/bootstrap/_offcanvas.scss +125 -61
  62. data/assets/stylesheets/bootstrap/_pagination.scss +66 -21
  63. data/assets/stylesheets/bootstrap/_placeholders.scss +1 -1
  64. data/assets/stylesheets/bootstrap/_popover.scss +90 -52
  65. data/assets/stylesheets/bootstrap/_progress.scss +31 -11
  66. data/assets/stylesheets/bootstrap/_reboot.scss +32 -46
  67. data/assets/stylesheets/bootstrap/_root.scss +155 -22
  68. data/assets/stylesheets/bootstrap/_spinners.scss +38 -22
  69. data/assets/stylesheets/bootstrap/_tables.scss +40 -24
  70. data/assets/stylesheets/bootstrap/_toasts.scss +38 -16
  71. data/assets/stylesheets/bootstrap/_tooltip.scss +60 -56
  72. data/assets/stylesheets/bootstrap/_type.scss +3 -1
  73. data/assets/stylesheets/bootstrap/_utilities.scss +209 -33
  74. data/assets/stylesheets/bootstrap/_variables-dark.scss +102 -0
  75. data/assets/stylesheets/bootstrap/_variables.scss +415 -303
  76. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +39 -5
  77. data/assets/stylesheets/bootstrap/forms/_form-check.scss +51 -14
  78. data/assets/stylesheets/bootstrap/forms/_form-control.scss +36 -41
  79. data/assets/stylesheets/bootstrap/forms/_form-range.scss +3 -3
  80. data/assets/stylesheets/bootstrap/forms/_form-select.scss +12 -4
  81. data/assets/stylesheets/bootstrap/forms/_input-group.scss +20 -9
  82. data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +7 -0
  83. data/assets/stylesheets/bootstrap/helpers/_colored-links.scss +20 -2
  84. data/assets/stylesheets/bootstrap/helpers/_focus-ring.scss +5 -0
  85. data/assets/stylesheets/bootstrap/helpers/_icon-link.scss +25 -0
  86. data/assets/stylesheets/bootstrap/helpers/_position.scss +7 -1
  87. data/assets/stylesheets/bootstrap/helpers/_ratio.scss +2 -2
  88. data/assets/stylesheets/bootstrap/helpers/_vr.scss +2 -2
  89. data/assets/stylesheets/bootstrap/mixins/_alert.scss +11 -4
  90. data/assets/stylesheets/bootstrap/mixins/_banner.scss +7 -0
  91. data/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +8 -8
  92. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +32 -95
  93. data/assets/stylesheets/bootstrap/mixins/_caret.scss +30 -25
  94. data/assets/stylesheets/bootstrap/mixins/_color-mode.scss +21 -0
  95. data/assets/stylesheets/bootstrap/mixins/_container.scss +4 -2
  96. data/assets/stylesheets/bootstrap/mixins/_forms.scss +38 -19
  97. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +1 -1
  98. data/assets/stylesheets/bootstrap/mixins/_grid.scss +15 -15
  99. data/assets/stylesheets/bootstrap/mixins/_list-group.scss +2 -0
  100. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +4 -25
  101. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +1 -1
  102. data/assets/stylesheets/bootstrap/mixins/_table-variants.scss +12 -9
  103. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +14 -6
  104. data/assets/stylesheets/bootstrap/mixins/_visually-hidden.scss +6 -2
  105. data/assets/stylesheets/bootstrap/vendor/_rfs.scss +23 -29
  106. data/bootstrap.gemspec +3 -3
  107. data/lib/bootstrap/engine.rb +17 -2
  108. data/lib/bootstrap/version.rb +2 -2
  109. data/tasks/updater/js.rb +10 -5
  110. data/tasks/updater/network.rb +2 -2
  111. data/tasks/updater/scss.rb +2 -2
  112. data/tasks/updater.rb +2 -2
  113. data/test/dummy_rails/config/application.rb +0 -2
  114. data/test/dummy_rails/public/favicon.ico +0 -0
  115. data/test/gemfiles/rails_4_2.gemfile +2 -1
  116. data/test/gemfiles/rails_5_0.gemfile +1 -2
  117. data/test/gemfiles/rails_5_1.gemfile +1 -2
  118. data/test/gemfiles/rails_5_2.gemfile +7 -0
  119. data/test/gemfiles/rails_6_0.gemfile +1 -1
  120. data/test/gemfiles/rails_6_1.gemfile +1 -1
  121. data/test/gemfiles/rails_7_0_dartsass.gemfile +7 -0
  122. data/test/gemfiles/rails_7_0_sassc.gemfile +7 -0
  123. data/test/rails_test.rb +0 -5
  124. data/test/test_helper.rb +3 -2
  125. metadata +49 -29
  126. data/.travis.yml +0 -32
  127. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +0 -18
@@ -1,19 +1,16 @@
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.3.5 (https://getbootstrap.com/)
3
+ * Copyright 2011-2025 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('./base-component.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./util/index.js')) :
8
+ typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './util/index'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Dropdown = factory(global["@popperjs/core"], global.BaseComponent, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Index));
10
+ })(this, (function (Popper, BaseComponent, EventHandler, Manipulator, SelectorEngine, index_js) { 'use strict';
11
11
 
12
- const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
-
14
- function _interopNamespace(e) {
15
- if (e && e.__esModule) return e;
16
- const n = Object.create(null);
12
+ function _interopNamespaceDefault(e) {
13
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
17
14
  if (e) {
18
15
  for (const k in e) {
19
16
  if (k !== 'default') {
@@ -29,206 +26,18 @@
29
26
  return Object.freeze(n);
30
27
  }
31
28
 
32
- const Popper__namespace = /*#__PURE__*/_interopNamespace(Popper);
33
- const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
34
- const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
35
- const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
36
- const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
29
+ const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper);
37
30
 
38
31
  /**
39
32
  * --------------------------------------------------------------------------
40
- * Bootstrap (v5.1.3): util/index.js
33
+ * Bootstrap dropdown.js
41
34
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
42
35
  * --------------------------------------------------------------------------
43
36
  */
44
37
 
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
38
 
222
39
  /**
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
40
  * Constants
231
- * ------------------------------------------------------------------------
232
41
  */
233
42
 
234
43
  const NAME = 'dropdown';
@@ -236,13 +45,11 @@
236
45
  const EVENT_KEY = `.${DATA_KEY}`;
237
46
  const DATA_API_KEY = '.data-api';
238
47
  const ESCAPE_KEY = 'Escape';
239
- const SPACE_KEY = 'Space';
240
48
  const TAB_KEY = 'Tab';
241
49
  const ARROW_UP_KEY = 'ArrowUp';
242
50
  const ARROW_DOWN_KEY = 'ArrowDown';
243
51
  const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button
244
52
 
245
- const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEY}|${ARROW_DOWN_KEY}|${ESCAPE_KEY}`);
246
53
  const EVENT_HIDE = `hide${EVENT_KEY}`;
247
54
  const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
248
55
  const EVENT_SHOW = `show${EVENT_KEY}`;
@@ -254,252 +61,204 @@
254
61
  const CLASS_NAME_DROPUP = 'dropup';
255
62
  const CLASS_NAME_DROPEND = 'dropend';
256
63
  const CLASS_NAME_DROPSTART = 'dropstart';
257
- const CLASS_NAME_NAVBAR = 'navbar';
258
- const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]';
64
+ const CLASS_NAME_DROPUP_CENTER = 'dropup-center';
65
+ const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center';
66
+ const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)';
67
+ const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}`;
259
68
  const SELECTOR_MENU = '.dropdown-menu';
69
+ const SELECTOR_NAVBAR = '.navbar';
260
70
  const SELECTOR_NAVBAR_NAV = '.navbar-nav';
261
71
  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';
72
+ const PLACEMENT_TOP = index_js.isRTL() ? 'top-end' : 'top-start';
73
+ const PLACEMENT_TOPEND = index_js.isRTL() ? 'top-start' : 'top-end';
74
+ const PLACEMENT_BOTTOM = index_js.isRTL() ? 'bottom-end' : 'bottom-start';
75
+ const PLACEMENT_BOTTOMEND = index_js.isRTL() ? 'bottom-start' : 'bottom-end';
76
+ const PLACEMENT_RIGHT = index_js.isRTL() ? 'left-start' : 'right-start';
77
+ const PLACEMENT_LEFT = index_js.isRTL() ? 'right-start' : 'left-start';
78
+ const PLACEMENT_TOPCENTER = 'top';
79
+ const PLACEMENT_BOTTOMCENTER = 'bottom';
268
80
  const Default = {
269
- offset: [0, 2],
81
+ autoClose: true,
270
82
  boundary: 'clippingParents',
271
- reference: 'toggle',
272
83
  display: 'dynamic',
84
+ offset: [0, 2],
273
85
  popperConfig: null,
274
- autoClose: true
86
+ reference: 'toggle'
275
87
  };
276
88
  const DefaultType = {
277
- offset: '(array|string|function)',
89
+ autoClose: '(boolean|string)',
278
90
  boundary: '(string|element)',
279
- reference: '(string|element|object)',
280
91
  display: 'string',
92
+ offset: '(array|string|function)',
281
93
  popperConfig: '(null|object|function)',
282
- autoClose: '(boolean|string)'
94
+ reference: '(string|element|object)'
283
95
  };
96
+
284
97
  /**
285
- * ------------------------------------------------------------------------
286
- * Class Definition
287
- * ------------------------------------------------------------------------
98
+ * Class definition
288
99
  */
289
100
 
290
- class Dropdown extends BaseComponent__default.default {
101
+ class Dropdown extends BaseComponent {
291
102
  constructor(element, config) {
292
- super(element);
103
+ super(element, config);
293
104
  this._popper = null;
294
- this._config = this._getConfig(config);
295
- this._menu = this._getMenuElement();
105
+ this._parent = this._element.parentNode; // dropdown wrapper
106
+ // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
107
+ this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent);
296
108
  this._inNavbar = this._detectNavbar();
297
- } // Getters
298
-
109
+ }
299
110
 
111
+ // Getters
300
112
  static get Default() {
301
113
  return Default;
302
114
  }
303
-
304
115
  static get DefaultType() {
305
116
  return DefaultType;
306
117
  }
307
-
308
118
  static get NAME() {
309
119
  return NAME;
310
- } // Public
311
-
120
+ }
312
121
 
122
+ // Public
313
123
  toggle() {
314
124
  return this._isShown() ? this.hide() : this.show();
315
125
  }
316
-
317
126
  show() {
318
- if (isDisabled(this._element) || this._isShown(this._menu)) {
127
+ if (index_js.isDisabled(this._element) || this._isShown()) {
319
128
  return;
320
129
  }
321
-
322
130
  const relatedTarget = {
323
131
  relatedTarget: this._element
324
132
  };
325
- const showEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW, relatedTarget);
326
-
133
+ const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, relatedTarget);
327
134
  if (showEvent.defaultPrevented) {
328
135
  return;
329
136
  }
137
+ this._createPopper();
330
138
 
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
139
+ // If this is a touch-enabled device we add extra
338
140
  // empty mouseover listeners to the body's immediate children;
339
141
  // only needed because of broken event delegation on iOS
340
142
  // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
341
-
342
-
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));
143
+ if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
144
+ for (const element of [].concat(...document.body.children)) {
145
+ EventHandler.on(element, 'mouseover', index_js.noop);
146
+ }
345
147
  }
346
-
347
148
  this._element.focus();
348
-
349
149
  this._element.setAttribute('aria-expanded', true);
350
-
351
150
  this._menu.classList.add(CLASS_NAME_SHOW);
352
-
353
151
  this._element.classList.add(CLASS_NAME_SHOW);
354
-
355
- EventHandler__default.default.trigger(this._element, EVENT_SHOWN, relatedTarget);
152
+ EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget);
356
153
  }
357
-
358
154
  hide() {
359
- if (isDisabled(this._element) || !this._isShown(this._menu)) {
155
+ if (index_js.isDisabled(this._element) || !this._isShown()) {
360
156
  return;
361
157
  }
362
-
363
158
  const relatedTarget = {
364
159
  relatedTarget: this._element
365
160
  };
366
-
367
161
  this._completeHide(relatedTarget);
368
162
  }
369
-
370
163
  dispose() {
371
164
  if (this._popper) {
372
165
  this._popper.destroy();
373
166
  }
374
-
375
167
  super.dispose();
376
168
  }
377
-
378
169
  update() {
379
170
  this._inNavbar = this._detectNavbar();
380
-
381
171
  if (this._popper) {
382
172
  this._popper.update();
383
173
  }
384
- } // Private
385
-
174
+ }
386
175
 
176
+ // Private
387
177
  _completeHide(relatedTarget) {
388
- const hideEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE, relatedTarget);
389
-
178
+ const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget);
390
179
  if (hideEvent.defaultPrevented) {
391
180
  return;
392
- } // If this is a touch-enabled device we remove the extra
393
- // empty mouseover listeners we added for iOS support
394
-
181
+ }
395
182
 
183
+ // If this is a touch-enabled device we remove the extra
184
+ // empty mouseover listeners we added for iOS support
396
185
  if ('ontouchstart' in document.documentElement) {
397
- [].concat(...document.body.children).forEach(elem => EventHandler__default.default.off(elem, 'mouseover', noop));
186
+ for (const element of [].concat(...document.body.children)) {
187
+ EventHandler.off(element, 'mouseover', index_js.noop);
188
+ }
398
189
  }
399
-
400
190
  if (this._popper) {
401
191
  this._popper.destroy();
402
192
  }
403
-
404
193
  this._menu.classList.remove(CLASS_NAME_SHOW);
405
-
406
194
  this._element.classList.remove(CLASS_NAME_SHOW);
407
-
408
195
  this._element.setAttribute('aria-expanded', 'false');
409
-
410
- Manipulator__default.default.removeDataAttribute(this._menu, 'popper');
411
- EventHandler__default.default.trigger(this._element, EVENT_HIDDEN, relatedTarget);
196
+ Manipulator.removeDataAttribute(this._menu, 'popper');
197
+ EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget);
412
198
  }
413
-
414
199
  _getConfig(config) {
415
- config = { ...this.constructor.Default,
416
- ...Manipulator__default.default.getDataAttributes(this._element),
417
- ...config
418
- };
419
- typeCheckConfig(NAME, config, this.constructor.DefaultType);
420
-
421
- if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {
200
+ config = super._getConfig(config);
201
+ if (typeof config.reference === 'object' && !index_js.isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {
422
202
  // Popper virtual elements require a getBoundingClientRect method
423
203
  throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);
424
204
  }
425
-
426
205
  return config;
427
206
  }
428
-
429
- _createPopper(parent) {
207
+ _createPopper() {
430
208
  if (typeof Popper__namespace === 'undefined') {
431
- throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
209
+ throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)');
432
210
  }
433
-
434
211
  let referenceElement = this._element;
435
-
436
212
  if (this._config.reference === 'parent') {
437
- referenceElement = parent;
438
- } else if (isElement(this._config.reference)) {
439
- referenceElement = getElement(this._config.reference);
213
+ referenceElement = this._parent;
214
+ } else if (index_js.isElement(this._config.reference)) {
215
+ referenceElement = index_js.getElement(this._config.reference);
440
216
  } else if (typeof this._config.reference === 'object') {
441
217
  referenceElement = this._config.reference;
442
218
  }
443
-
444
219
  const popperConfig = this._getPopperConfig();
445
-
446
- const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false);
447
220
  this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig);
448
-
449
- if (isDisplayStatic) {
450
- Manipulator__default.default.setDataAttribute(this._menu, 'popper', 'static');
451
- }
452
221
  }
453
-
454
- _isShown(element = this._element) {
455
- return element.classList.contains(CLASS_NAME_SHOW);
222
+ _isShown() {
223
+ return this._menu.classList.contains(CLASS_NAME_SHOW);
456
224
  }
457
-
458
- _getMenuElement() {
459
- return SelectorEngine__default.default.next(this._element, SELECTOR_MENU)[0];
460
- }
461
-
462
225
  _getPlacement() {
463
- const parentDropdown = this._element.parentNode;
464
-
226
+ const parentDropdown = this._parent;
465
227
  if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
466
228
  return PLACEMENT_RIGHT;
467
229
  }
468
-
469
230
  if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
470
231
  return PLACEMENT_LEFT;
471
- } // We need to trim the value because custom properties can also include spaces
472
-
232
+ }
233
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {
234
+ return PLACEMENT_TOPCENTER;
235
+ }
236
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {
237
+ return PLACEMENT_BOTTOMCENTER;
238
+ }
473
239
 
240
+ // We need to trim the value because custom properties can also include spaces
474
241
  const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end';
475
-
476
242
  if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {
477
243
  return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP;
478
244
  }
479
-
480
245
  return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM;
481
246
  }
482
-
483
247
  _detectNavbar() {
484
- return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null;
248
+ return this._element.closest(SELECTOR_NAVBAR) !== null;
485
249
  }
486
-
487
250
  _getOffset() {
488
251
  const {
489
252
  offset
490
253
  } = this._config;
491
-
492
254
  if (typeof offset === 'string') {
493
- return offset.split(',').map(val => Number.parseInt(val, 10));
255
+ return offset.split(',').map(value => Number.parseInt(value, 10));
494
256
  }
495
-
496
257
  if (typeof offset === 'function') {
497
258
  return popperData => offset(popperData, this._element);
498
259
  }
499
-
500
260
  return offset;
501
261
  }
502
-
503
262
  _getPopperConfig() {
504
263
  const defaultBsPopperConfig = {
505
264
  placement: this._getPlacement(),
@@ -514,172 +273,128 @@
514
273
  offset: this._getOffset()
515
274
  }
516
275
  }]
517
- }; // Disable Popper if we have a static display
276
+ };
518
277
 
519
- if (this._config.display === 'static') {
278
+ // Disable Popper if we have a static display or Dropdown is in Navbar
279
+ if (this._inNavbar || this._config.display === 'static') {
280
+ Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // TODO: v6 remove
520
281
  defaultBsPopperConfig.modifiers = [{
521
282
  name: 'applyStyles',
522
283
  enabled: false
523
284
  }];
524
285
  }
525
-
526
- return { ...defaultBsPopperConfig,
527
- ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
286
+ return {
287
+ ...defaultBsPopperConfig,
288
+ ...index_js.execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
528
289
  };
529
290
  }
530
-
531
291
  _selectMenuItem({
532
292
  key,
533
293
  target
534
294
  }) {
535
- const items = SelectorEngine__default.default.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible);
536
-
295
+ const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => index_js.isVisible(element));
537
296
  if (!items.length) {
538
297
  return;
539
- } // if target isn't included in items (e.g. when expanding the dropdown)
540
- // allow cycling to get the last item in case key equals ARROW_UP_KEY
541
-
542
-
543
- getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
544
- } // Static
298
+ }
545
299
 
300
+ // if target isn't included in items (e.g. when expanding the dropdown)
301
+ // allow cycling to get the last item in case key equals ARROW_UP_KEY
302
+ index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
303
+ }
546
304
 
305
+ // Static
547
306
  static jQueryInterface(config) {
548
307
  return this.each(function () {
549
308
  const data = Dropdown.getOrCreateInstance(this, config);
550
-
551
309
  if (typeof config !== 'string') {
552
310
  return;
553
311
  }
554
-
555
312
  if (typeof data[config] === 'undefined') {
556
313
  throw new TypeError(`No method named "${config}"`);
557
314
  }
558
-
559
315
  data[config]();
560
316
  });
561
317
  }
562
-
563
318
  static clearMenus(event) {
564
- if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) {
319
+ if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY) {
565
320
  return;
566
321
  }
567
-
568
- const toggles = SelectorEngine__default.default.find(SELECTOR_DATA_TOGGLE);
569
-
570
- for (let i = 0, len = toggles.length; i < len; i++) {
571
- const context = Dropdown.getInstance(toggles[i]);
572
-
322
+ const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN);
323
+ for (const toggle of openToggles) {
324
+ const context = Dropdown.getInstance(toggle);
573
325
  if (!context || context._config.autoClose === false) {
574
326
  continue;
575
327
  }
576
-
577
- if (!context._isShown()) {
328
+ const composedPath = event.composedPath();
329
+ const isMenuTarget = composedPath.includes(context._menu);
330
+ if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {
578
331
  continue;
579
332
  }
580
333
 
334
+ // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
335
+ if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY || /input|select|option|textarea|form/i.test(event.target.tagName))) {
336
+ continue;
337
+ }
581
338
  const relatedTarget = {
582
339
  relatedTarget: context._element
583
340
  };
584
-
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
- }
341
+ if (event.type === 'click') {
342
+ relatedTarget.clickEvent = event;
601
343
  }
602
-
603
344
  context._completeHide(relatedTarget);
604
345
  }
605
346
  }
606
-
607
- static getParentFromElement(element) {
608
- return getElementFromSelector(element) || element.parentNode;
609
- }
610
-
611
347
  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);
348
+ // If not an UP | DOWN | ESCAPE key => not a dropdown command
349
+ // If input/textarea && if key is other than ESCAPE => not a dropdown command
624
350
 
625
- if (!isActive && event.key === ESCAPE_KEY) {
351
+ const isInput = /input|textarea/i.test(event.target.tagName);
352
+ const isEscapeEvent = event.key === ESCAPE_KEY;
353
+ const isUpOrDownEvent = [ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key);
354
+ if (!isUpOrDownEvent && !isEscapeEvent) {
626
355
  return;
627
356
  }
628
-
629
- event.preventDefault();
630
- event.stopPropagation();
631
-
632
- if (isDisabled(this)) {
357
+ if (isInput && !isEscapeEvent) {
633
358
  return;
634
359
  }
360
+ event.preventDefault();
635
361
 
636
- const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine__default.default.prev(this, SELECTOR_DATA_TOGGLE)[0];
362
+ // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
363
+ const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode);
637
364
  const instance = Dropdown.getOrCreateInstance(getToggleButton);
638
-
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
- }
648
-
365
+ if (isUpOrDownEvent) {
366
+ event.stopPropagation();
367
+ instance.show();
649
368
  instance._selectMenuItem(event);
650
-
651
369
  return;
652
370
  }
653
-
654
- if (!isActive || event.key === SPACE_KEY) {
655
- Dropdown.clearMenus();
371
+ if (instance._isShown()) {
372
+ // else is escape and we check if it is shown
373
+ event.stopPropagation();
374
+ instance.hide();
375
+ getToggleButton.focus();
656
376
  }
657
377
  }
658
-
659
378
  }
379
+
660
380
  /**
661
- * ------------------------------------------------------------------------
662
- * Data Api implementation
663
- * ------------------------------------------------------------------------
381
+ * Data API implementation
664
382
  */
665
383
 
666
-
667
- EventHandler__default.default.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler);
668
- EventHandler__default.default.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);
669
- EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus);
670
- EventHandler__default.default.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
671
- EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
384
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler);
385
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);
386
+ EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus);
387
+ EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
388
+ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
672
389
  event.preventDefault();
673
390
  Dropdown.getOrCreateInstance(this).toggle();
674
391
  });
392
+
675
393
  /**
676
- * ------------------------------------------------------------------------
677
394
  * jQuery
678
- * ------------------------------------------------------------------------
679
- * add .Dropdown to jQuery only if jQuery is present
680
395
  */
681
396
 
682
- defineJQueryPlugin(Dropdown);
397
+ index_js.defineJQueryPlugin(Dropdown);
683
398
 
684
399
  return Dropdown;
685
400