bootstrap 5.3.0 → 5.3.8

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +22 -21
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile +1 -0
  5. data/README.md +11 -10
  6. data/Rakefile +16 -5
  7. data/assets/javascripts/bootstrap/alert.js +2 -2
  8. data/assets/javascripts/bootstrap/base-component.js +5 -3
  9. data/assets/javascripts/bootstrap/button.js +2 -2
  10. data/assets/javascripts/bootstrap/carousel.js +2 -2
  11. data/assets/javascripts/bootstrap/collapse.js +4 -4
  12. data/assets/javascripts/bootstrap/dom/data.js +2 -2
  13. data/assets/javascripts/bootstrap/dom/event-handler.js +2 -2
  14. data/assets/javascripts/bootstrap/dom/manipulator.js +3 -3
  15. data/assets/javascripts/bootstrap/dom/selector-engine.js +3 -3
  16. data/assets/javascripts/bootstrap/dropdown.js +4 -4
  17. data/assets/javascripts/bootstrap/modal.js +2 -2
  18. data/assets/javascripts/bootstrap/offcanvas.js +2 -2
  19. data/assets/javascripts/bootstrap/popover.js +2 -2
  20. data/assets/javascripts/bootstrap/scrollspy.js +2 -2
  21. data/assets/javascripts/bootstrap/tab.js +14 -6
  22. data/assets/javascripts/bootstrap/toast.js +2 -3
  23. data/assets/javascripts/bootstrap/tooltip.js +6 -6
  24. data/assets/javascripts/bootstrap/util/backdrop.js +2 -3
  25. data/assets/javascripts/bootstrap/util/component-functions.js +2 -2
  26. data/assets/javascripts/bootstrap/util/config.js +2 -2
  27. data/assets/javascripts/bootstrap/util/focustrap.js +2 -3
  28. data/assets/javascripts/bootstrap/util/index.js +4 -5
  29. data/assets/javascripts/bootstrap/util/sanitizer.js +5 -3
  30. data/assets/javascripts/bootstrap/util/scrollbar.js +2 -2
  31. data/assets/javascripts/bootstrap/util/swipe.js +2 -2
  32. data/assets/javascripts/bootstrap/util/template-factory.js +3 -3
  33. data/assets/javascripts/bootstrap-sprockets.js +13 -13
  34. data/assets/javascripts/bootstrap.js +33 -25
  35. data/assets/javascripts/bootstrap.min.js +3 -3
  36. data/assets/stylesheets/_bootstrap-utilities.scss +19 -0
  37. data/assets/stylesheets/bootstrap/_accordion.scss +10 -15
  38. data/assets/stylesheets/bootstrap/_button-group.scss +8 -3
  39. data/assets/stylesheets/bootstrap/_buttons.scss +10 -1
  40. data/assets/stylesheets/bootstrap/_card.scss +9 -10
  41. data/assets/stylesheets/bootstrap/_carousel.scss +17 -35
  42. data/assets/stylesheets/bootstrap/_close.scss +9 -6
  43. data/assets/stylesheets/bootstrap/_functions.scss +2 -2
  44. data/assets/stylesheets/bootstrap/_list-group.scss +27 -25
  45. data/assets/stylesheets/bootstrap/_modal.scss +6 -3
  46. data/assets/stylesheets/bootstrap/_nav.scss +3 -15
  47. data/assets/stylesheets/bootstrap/_navbar.scss +1 -1
  48. data/assets/stylesheets/bootstrap/_offcanvas.scss +2 -1
  49. data/assets/stylesheets/bootstrap/_pagination.scss +1 -1
  50. data/assets/stylesheets/bootstrap/_progress.scss +1 -1
  51. data/assets/stylesheets/bootstrap/_reboot.scss +12 -5
  52. data/assets/stylesheets/bootstrap/_root.scss +3 -0
  53. data/assets/stylesheets/bootstrap/_spinners.scss +1 -0
  54. data/assets/stylesheets/bootstrap/_tables.scss +1 -1
  55. data/assets/stylesheets/bootstrap/_type.scss +1 -1
  56. data/assets/stylesheets/bootstrap/_utilities.scss +3 -3
  57. data/assets/stylesheets/bootstrap/_variables-dark.scss +20 -3
  58. data/assets/stylesheets/bootstrap/_variables.scss +42 -32
  59. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +20 -17
  60. data/assets/stylesheets/bootstrap/forms/_form-check.scss +3 -2
  61. data/assets/stylesheets/bootstrap/forms/_form-control.scss +1 -1
  62. data/assets/stylesheets/bootstrap/forms/_form-range.scss +3 -3
  63. data/assets/stylesheets/bootstrap/forms/_form-select.scss +1 -1
  64. data/assets/stylesheets/bootstrap/forms/_input-group.scss +1 -1
  65. data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +1 -2
  66. data/assets/stylesheets/bootstrap/helpers/_vr.scss +1 -1
  67. data/assets/stylesheets/bootstrap/mixins/_banner.scss +2 -2
  68. data/assets/stylesheets/bootstrap/mixins/_box-shadow.scss +11 -5
  69. data/assets/stylesheets/bootstrap/mixins/_forms.scss +12 -2
  70. data/assets/stylesheets/bootstrap/mixins/_grid.scss +3 -3
  71. data/assets/stylesheets/bootstrap/mixins/_visually-hidden.scss +6 -1
  72. data/bootstrap.gemspec +4 -4
  73. data/lib/bootstrap/engine.rb +17 -2
  74. data/lib/bootstrap/version.rb +2 -2
  75. data/tasks/updater/scss.rb +1 -1
  76. data/test/dummy_rails/config/application.rb +0 -2
  77. data/test/dummy_rails/public/favicon.ico +0 -0
  78. data/test/gemfiles/rails_4_2.gemfile +2 -1
  79. data/test/gemfiles/rails_5_0.gemfile +1 -2
  80. data/test/gemfiles/rails_5_1.gemfile +1 -2
  81. data/test/gemfiles/rails_5_2.gemfile +1 -2
  82. data/test/gemfiles/rails_6_0.gemfile +9 -1
  83. data/test/gemfiles/rails_6_1.gemfile +9 -1
  84. data/test/gemfiles/rails_7_0_dartsass.gemfile +15 -0
  85. data/test/gemfiles/rails_7_0_sassc.gemfile +15 -0
  86. data/test/rails_test.rb +0 -5
  87. data/test/test_helper.rb +6 -4
  88. metadata +42 -32
  89. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +0 -19
  90. data/test/gemfiles/rails_7_0.gemfile +0 -7
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * Bootstrap scrollbar.js v5.3.0 (https://getbootstrap.com/)
3
- * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap scrollbar.js v5.3.8 (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) {
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * Bootstrap swipe.js v5.3.0 (https://getbootstrap.com/)
3
- * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap swipe.js v5.3.8 (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) {
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * Bootstrap template-factory.js v5.3.0 (https://getbootstrap.com/)
3
- * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap template-factory.js v5.3.8 (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) {
@@ -133,7 +133,7 @@
133
133
  return this._config.sanitize ? sanitizer_js.sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg;
134
134
  }
135
135
  _resolvePossibleFunction(arg) {
136
- return index_js.execute(arg, [this]);
136
+ return index_js.execute(arg, [undefined, this]);
137
137
  }
138
138
  _putElementInTemplate(element, templateElement) {
139
139
  if (this._config.html) {
@@ -1,28 +1,28 @@
1
1
  //= require ./bootstrap-global-this-define
2
- //= require ./bootstrap/dom/manipulator
3
2
  //= require ./bootstrap/dom/data
4
3
  //= require ./bootstrap/util/index
5
4
  //= require ./bootstrap/dom/event-handler
5
+ //= require ./bootstrap/dom/manipulator
6
6
  //= require ./bootstrap/util/config
7
7
  //= require ./bootstrap/base-component
8
+ //= require ./bootstrap/util/sanitizer
8
9
  //= require ./bootstrap/dom/selector-engine
10
+ //= require ./bootstrap/util/template-factory
11
+ //= require ./bootstrap/tooltip
12
+ //= require ./bootstrap/popover
9
13
  //= require ./bootstrap/util/component-functions
14
+ //= require ./bootstrap/alert
10
15
  //= require ./bootstrap/toast
11
16
  //= require ./bootstrap/button
12
- //= require ./bootstrap/alert
13
- //= require ./bootstrap/util/sanitizer
14
- //= require ./bootstrap/util/template-factory
15
- //= require ./bootstrap/util/swipe
16
- //= require ./bootstrap/carousel
17
- //= require ./bootstrap/tooltip
17
+ //= require ./bootstrap/collapse
18
+ //= require ./bootstrap/util/scrollbar
19
+ //= require ./bootstrap/tab
18
20
  //= require ./bootstrap/util/focustrap
19
21
  //= require ./bootstrap/util/backdrop
20
- //= require ./bootstrap/util/scrollbar
21
- //= require ./bootstrap/offcanvas
22
- //= require ./bootstrap/popover
22
+ //= require ./bootstrap/scrollspy
23
23
  //= require ./bootstrap/modal
24
- //= require ./bootstrap/tab
24
+ //= require ./bootstrap/offcanvas
25
+ //= require ./bootstrap/util/swipe
26
+ //= require ./bootstrap/carousel
25
27
  //= require ./bootstrap/dropdown
26
- //= require ./bootstrap/collapse
27
- //= require ./bootstrap/scrollspy
28
28
  //= require ./bootstrap-global-this-undefine
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * Bootstrap v5.3.0 (https://getbootstrap.com/)
3
- * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap v5.3.8 (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) {
@@ -224,12 +224,11 @@
224
224
  * @param {HTMLElement} element
225
225
  * @return void
226
226
  *
227
- * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
227
+ * @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
228
228
  */
229
229
  const reflow = element => {
230
230
  element.offsetHeight; // eslint-disable-line no-unused-expressions
231
231
  };
232
-
233
232
  const getjQuery = () => {
234
233
  if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
235
234
  return window.jQuery;
@@ -270,7 +269,7 @@
270
269
  });
271
270
  };
272
271
  const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
273
- return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue;
272
+ return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
274
273
  };
275
274
  const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
276
275
  if (!waitForTransition) {
@@ -592,7 +591,7 @@
592
591
  const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'));
593
592
  for (const key of bsKeys) {
594
593
  let pureKey = key.replace(/^bs/, '');
595
- pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);
594
+ pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1);
596
595
  attributes[pureKey] = normalizeData(element.dataset[key]);
597
596
  }
598
597
  return attributes;
@@ -667,7 +666,7 @@
667
666
  * Constants
668
667
  */
669
668
 
670
- const VERSION = '5.3.0';
669
+ const VERSION = '5.3.8';
671
670
 
672
671
  /**
673
672
  * Class definition
@@ -693,6 +692,8 @@
693
692
  this[propertyName] = null;
694
693
  }
695
694
  }
695
+
696
+ // Private
696
697
  _queueCallback(callback, element, isAnimated = true) {
697
698
  executeAfterTransition(callback, element, isAnimated);
698
699
  }
@@ -750,7 +751,7 @@
750
751
  }
751
752
  selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null;
752
753
  }
753
- return parseSelector(selector);
754
+ return selector ? selector.split(',').map(sel => parseSelector(sel)).join(',') : null;
754
755
  };
755
756
  const SelectorEngine = {
756
757
  find(selector, element = document.documentElement) {
@@ -1624,11 +1625,11 @@
1624
1625
  this._element.style[dimension] = '';
1625
1626
  this._queueCallback(complete, this._element, true);
1626
1627
  }
1628
+
1629
+ // Private
1627
1630
  _isShown(element = this._element) {
1628
1631
  return element.classList.contains(CLASS_NAME_SHOW$7);
1629
1632
  }
1630
-
1631
- // Private
1632
1633
  _configAfterMerge(config) {
1633
1634
  config.toggle = Boolean(config.toggle); // Coerce string values
1634
1635
  config.parent = getElement(config.parent);
@@ -1882,7 +1883,7 @@
1882
1883
  }
1883
1884
  _createPopper() {
1884
1885
  if (typeof Popper__namespace === 'undefined') {
1885
- throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
1886
+ throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)');
1886
1887
  }
1887
1888
  let referenceElement = this._element;
1888
1889
  if (this._config.reference === 'parent') {
@@ -1961,7 +1962,7 @@
1961
1962
  }
1962
1963
  return {
1963
1964
  ...defaultBsPopperConfig,
1964
- ...execute(this._config.popperConfig, [defaultBsPopperConfig])
1965
+ ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
1965
1966
  };
1966
1967
  }
1967
1968
  _selectMenuItem({
@@ -2096,7 +2097,6 @@
2096
2097
  // if false, we use the backdrop helper without adding any element to the dom
2097
2098
  rootElement: 'body' // give the choice to place backdrop under different elements
2098
2099
  };
2099
-
2100
2100
  const DefaultType$8 = {
2101
2101
  className: 'string',
2102
2102
  clickCallback: '(function|null)',
@@ -2221,7 +2221,6 @@
2221
2221
  autofocus: true,
2222
2222
  trapElement: null // The element to trap focus inside of
2223
2223
  };
2224
-
2225
2224
  const DefaultType$7 = {
2226
2225
  autofocus: 'boolean',
2227
2226
  trapElement: 'element'
@@ -2948,7 +2947,10 @@
2948
2947
  br: [],
2949
2948
  col: [],
2950
2949
  code: [],
2950
+ dd: [],
2951
2951
  div: [],
2952
+ dl: [],
2953
+ dt: [],
2952
2954
  em: [],
2953
2955
  hr: [],
2954
2956
  h1: [],
@@ -2982,7 +2984,6 @@
2982
2984
  *
2983
2985
  * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38
2984
2986
  */
2985
- // eslint-disable-next-line unicorn/better-regex
2986
2987
  const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i;
2987
2988
  const allowedAttribute = (attribute, allowedAttributeList) => {
2988
2989
  const attributeName = attribute.nodeName.toLowerCase();
@@ -3147,7 +3148,7 @@
3147
3148
  return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg;
3148
3149
  }
3149
3150
  _resolvePossibleFunction(arg) {
3150
- return execute(arg, [this]);
3151
+ return execute(arg, [undefined, this]);
3151
3152
  }
3152
3153
  _putElementInTemplate(element, templateElement) {
3153
3154
  if (this._config.html) {
@@ -3246,7 +3247,7 @@
3246
3247
  class Tooltip extends BaseComponent {
3247
3248
  constructor(element, config) {
3248
3249
  if (typeof Popper__namespace === 'undefined') {
3249
- throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
3250
+ throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org/docs/v2/)');
3250
3251
  }
3251
3252
  super(element, config);
3252
3253
 
@@ -3292,7 +3293,6 @@
3292
3293
  if (!this._isEnabled) {
3293
3294
  return;
3294
3295
  }
3295
- this._activeTrigger.click = !this._activeTrigger.click;
3296
3296
  if (this._isShown()) {
3297
3297
  this._leave();
3298
3298
  return;
@@ -3480,7 +3480,7 @@
3480
3480
  return offset;
3481
3481
  }
3482
3482
  _resolvePossibleFunction(arg) {
3483
- return execute(arg, [this._element]);
3483
+ return execute(arg, [this._element, this._element]);
3484
3484
  }
3485
3485
  _getPopperConfig(attachment) {
3486
3486
  const defaultBsPopperConfig = {
@@ -3518,7 +3518,7 @@
3518
3518
  };
3519
3519
  return {
3520
3520
  ...defaultBsPopperConfig,
3521
- ...execute(this._config.popperConfig, [defaultBsPopperConfig])
3521
+ ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
3522
3522
  };
3523
3523
  }
3524
3524
  _setListeners() {
@@ -3527,6 +3527,7 @@
3527
3527
  if (trigger === 'click') {
3528
3528
  EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => {
3529
3529
  const context = this._initializeOnDelegatedTarget(event);
3530
+ context._activeTrigger[TRIGGER_CLICK] = !(context._isShown() && context._activeTrigger[TRIGGER_CLICK]);
3530
3531
  context.toggle();
3531
3532
  });
3532
3533
  } else if (trigger !== TRIGGER_MANUAL) {
@@ -4038,13 +4039,15 @@
4038
4039
  const ARROW_RIGHT_KEY = 'ArrowRight';
4039
4040
  const ARROW_UP_KEY = 'ArrowUp';
4040
4041
  const ARROW_DOWN_KEY = 'ArrowDown';
4042
+ const HOME_KEY = 'Home';
4043
+ const END_KEY = 'End';
4041
4044
  const CLASS_NAME_ACTIVE = 'active';
4042
4045
  const CLASS_NAME_FADE$1 = 'fade';
4043
4046
  const CLASS_NAME_SHOW$1 = 'show';
4044
4047
  const CLASS_DROPDOWN = 'dropdown';
4045
4048
  const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
4046
4049
  const SELECTOR_DROPDOWN_MENU = '.dropdown-menu';
4047
- const NOT_SELECTOR_DROPDOWN_TOGGLE = ':not(.dropdown-toggle)';
4050
+ const NOT_SELECTOR_DROPDOWN_TOGGLE = `:not(${SELECTOR_DROPDOWN_TOGGLE})`;
4048
4051
  const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]';
4049
4052
  const SELECTOR_OUTER = '.nav-item, .list-group-item';
4050
4053
  const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`;
@@ -4144,13 +4147,19 @@
4144
4147
  this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE$1));
4145
4148
  }
4146
4149
  _keydown(event) {
4147
- if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) {
4150
+ if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY, HOME_KEY, END_KEY].includes(event.key)) {
4148
4151
  return;
4149
4152
  }
4150
4153
  event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page
4151
4154
  event.preventDefault();
4152
- const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key);
4153
- const nextActiveElement = getNextActiveElement(this._getChildren().filter(element => !isDisabled(element)), event.target, isNext, true);
4155
+ const children = this._getChildren().filter(element => !isDisabled(element));
4156
+ let nextActiveElement;
4157
+ if ([HOME_KEY, END_KEY].includes(event.key)) {
4158
+ nextActiveElement = children[event.key === HOME_KEY ? 0 : children.length - 1];
4159
+ } else {
4160
+ const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key);
4161
+ nextActiveElement = getNextActiveElement(children, event.target, isNext, true);
4162
+ }
4154
4163
  if (nextActiveElement) {
4155
4164
  nextActiveElement.focus({
4156
4165
  preventScroll: true
@@ -4384,7 +4393,6 @@
4384
4393
  }
4385
4394
 
4386
4395
  // Private
4387
-
4388
4396
  _maybeScheduleHide() {
4389
4397
  if (!this._config.autohide) {
4390
4398
  return;