bootstrap 5.0.0 → 5.1.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/assets/javascripts/bootstrap/alert.js +77 -106
  4. data/assets/javascripts/bootstrap/base-component.js +126 -7
  5. data/assets/javascripts/bootstrap/button.js +24 -24
  6. data/assets/javascripts/bootstrap/carousel.js +115 -128
  7. data/assets/javascripts/bootstrap/collapse.js +119 -176
  8. data/assets/javascripts/bootstrap/dom/data.js +2 -2
  9. data/assets/javascripts/bootstrap/dom/event-handler.js +3 -4
  10. data/assets/javascripts/bootstrap/dom/manipulator.js +4 -4
  11. data/assets/javascripts/bootstrap/dom/selector-engine.js +47 -5
  12. data/assets/javascripts/bootstrap/dropdown.js +142 -130
  13. data/assets/javascripts/bootstrap/modal.js +376 -171
  14. data/assets/javascripts/bootstrap/offcanvas.js +328 -133
  15. data/assets/javascripts/bootstrap/popover.js +27 -59
  16. data/assets/javascripts/bootstrap/scrollspy.js +51 -56
  17. data/assets/javascripts/bootstrap/tab.js +39 -66
  18. data/assets/javascripts/bootstrap/toast.js +175 -86
  19. data/assets/javascripts/bootstrap/tooltip.js +141 -185
  20. data/assets/javascripts/bootstrap-sprockets.js +6 -6
  21. data/assets/javascripts/bootstrap.js +1031 -1026
  22. data/assets/javascripts/bootstrap.min.js +2 -2
  23. data/assets/stylesheets/_bootstrap-grid.scss +3 -1
  24. data/assets/stylesheets/_bootstrap-reboot.scss +2 -4
  25. data/assets/stylesheets/_bootstrap.scss +2 -1
  26. data/assets/stylesheets/bootstrap/_card.scss +7 -6
  27. data/assets/stylesheets/bootstrap/_carousel.scss +2 -2
  28. data/assets/stylesheets/bootstrap/_dropdown.scss +4 -4
  29. data/assets/stylesheets/bootstrap/_functions.scss +100 -3
  30. data/assets/stylesheets/bootstrap/_grid.scss +11 -0
  31. data/assets/stylesheets/bootstrap/_helpers.scss +2 -0
  32. data/assets/stylesheets/bootstrap/_images.scss +1 -1
  33. data/assets/stylesheets/bootstrap/_list-group.scss +5 -5
  34. data/assets/stylesheets/bootstrap/_mixins.scss +1 -0
  35. data/assets/stylesheets/bootstrap/_modal.scss +7 -26
  36. data/assets/stylesheets/bootstrap/_navbar.scss +30 -1
  37. data/assets/stylesheets/bootstrap/_offcanvas.scss +8 -2
  38. data/assets/stylesheets/bootstrap/_placeholders.scss +51 -0
  39. data/assets/stylesheets/bootstrap/_popover.scss +10 -10
  40. data/assets/stylesheets/bootstrap/_reboot.scss +12 -8
  41. data/assets/stylesheets/bootstrap/_root.scss +40 -2
  42. data/assets/stylesheets/bootstrap/_tables.scss +1 -0
  43. data/assets/stylesheets/bootstrap/_toasts.scss +3 -3
  44. data/assets/stylesheets/bootstrap/_tooltip.scss +4 -4
  45. data/assets/stylesheets/bootstrap/_transitions.scss +6 -0
  46. data/assets/stylesheets/bootstrap/_utilities.scss +44 -8
  47. data/assets/stylesheets/bootstrap/_variables.scss +200 -25
  48. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +1 -1
  49. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +3 -1
  50. data/assets/stylesheets/bootstrap/forms/_form-check.scss +1 -1
  51. data/assets/stylesheets/bootstrap/forms/_form-control.scss +6 -6
  52. data/assets/stylesheets/bootstrap/forms/_form-range.scss +1 -1
  53. data/assets/stylesheets/bootstrap/forms/_form-select.scss +3 -0
  54. data/assets/stylesheets/bootstrap/helpers/_stacks.scss +15 -0
  55. data/assets/stylesheets/bootstrap/helpers/_vr.scss +8 -0
  56. data/assets/stylesheets/bootstrap/mixins/_backdrop.scss +14 -0
  57. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +1 -1
  58. data/assets/stylesheets/bootstrap/mixins/_forms.scss +8 -1
  59. data/assets/stylesheets/bootstrap/mixins/_grid.scss +33 -8
  60. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +27 -6
  61. data/assets/stylesheets/bootstrap/vendor/_rfs.scss +55 -13
  62. data/bootstrap.gemspec +3 -3
  63. data/lib/bootstrap/version.rb +2 -2
  64. data/tasks/updater/js.rb +6 -2
  65. metadata +12 -8
@@ -1,29 +1,26 @@
1
1
  /*!
2
- * Bootstrap toast.js v5.0.0 (https://getbootstrap.com/)
2
+ * Bootstrap toast.js v5.1.1 (https://getbootstrap.com/)
3
3
  * Copyright 2011-2021 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('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./base-component.js')) :
8
- typeof define === 'function' && define.amd ? define(['./dom/data', './dom/event-handler', './dom/manipulator', './base-component'], factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Toast = factory(global.Data, global.EventHandler, global.Manipulator, global.Base));
10
- }(this, (function (Data, EventHandler, Manipulator, BaseComponent) { 'use strict';
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./base-component.js')) :
8
+ typeof define === 'function' && define.amd ? define(['./dom/event-handler', './dom/manipulator', './base-component'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Toast = factory(global.EventHandler, global.Manipulator, global.Base));
10
+ }(this, (function (EventHandler, Manipulator, BaseComponent) { 'use strict';
11
11
 
12
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
13
 
14
- var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
15
14
  var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
16
15
  var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
17
16
  var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
18
17
 
19
18
  /**
20
19
  * --------------------------------------------------------------------------
21
- * Bootstrap (v5.0.0): util/index.js
20
+ * Bootstrap (v5.1.1): util/index.js
22
21
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
23
22
  * --------------------------------------------------------------------------
24
23
  */
25
- const MILLISECONDS_MULTIPLIER = 1000;
26
- const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
27
24
 
28
25
  const toType = obj => {
29
26
  if (obj === null || obj === undefined) {
@@ -33,51 +30,45 @@
33
30
  return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
34
31
  };
35
32
 
36
- const getTransitionDurationFromElement = element => {
37
- if (!element) {
38
- return 0;
39
- } // Get transition-duration of the element
33
+ const getSelector = element => {
34
+ let selector = element.getAttribute('data-bs-target');
40
35
 
36
+ if (!selector || selector === '#') {
37
+ let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,
38
+ // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
39
+ // `document.querySelector` will rightfully complain it is invalid.
40
+ // See https://github.com/twbs/bootstrap/issues/32273
41
41
 
42
- let {
43
- transitionDuration,
44
- transitionDelay
45
- } = window.getComputedStyle(element);
46
- const floatTransitionDuration = Number.parseFloat(transitionDuration);
47
- const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found
42
+ if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) {
43
+ return null;
44
+ } // Just in case some CMS puts out a full URL with the anchor appended
48
45
 
49
- if (!floatTransitionDuration && !floatTransitionDelay) {
50
- return 0;
51
- } // If multiple durations are defined, take the first
52
46
 
47
+ if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
48
+ hrefAttr = `#${hrefAttr.split('#')[1]}`;
49
+ }
53
50
 
54
- transitionDuration = transitionDuration.split(',')[0];
55
- transitionDelay = transitionDelay.split(',')[0];
56
- return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
57
- };
51
+ selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
52
+ }
58
53
 
59
- const triggerTransitionEnd = element => {
60
- element.dispatchEvent(new Event(TRANSITION_END));
54
+ return selector;
61
55
  };
62
56
 
63
- const isElement = obj => (obj[0] || obj).nodeType;
57
+ const getElementFromSelector = element => {
58
+ const selector = getSelector(element);
59
+ return selector ? document.querySelector(selector) : null;
60
+ };
64
61
 
65
- const emulateTransitionEnd = (element, duration) => {
66
- let called = false;
67
- const durationPadding = 5;
68
- const emulatedDuration = duration + durationPadding;
62
+ const isElement = obj => {
63
+ if (!obj || typeof obj !== 'object') {
64
+ return false;
65
+ }
69
66
 
70
- function listener() {
71
- called = true;
72
- element.removeEventListener(TRANSITION_END, listener);
67
+ if (typeof obj.jquery !== 'undefined') {
68
+ obj = obj[0];
73
69
  }
74
70
 
75
- element.addEventListener(TRANSITION_END, listener);
76
- setTimeout(() => {
77
- if (!called) {
78
- triggerTransitionEnd(element);
79
- }
80
- }, emulatedDuration);
71
+ return typeof obj.nodeType !== 'undefined';
81
72
  };
82
73
 
83
74
  const typeCheckConfig = (componentName, config, configTypes) => {
@@ -92,7 +83,35 @@
92
83
  });
93
84
  };
94
85
 
95
- const reflow = element => element.offsetHeight;
86
+ const isDisabled = element => {
87
+ if (!element || element.nodeType !== Node.ELEMENT_NODE) {
88
+ return true;
89
+ }
90
+
91
+ if (element.classList.contains('disabled')) {
92
+ return true;
93
+ }
94
+
95
+ if (typeof element.disabled !== 'undefined') {
96
+ return element.disabled;
97
+ }
98
+
99
+ return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
100
+ };
101
+ /**
102
+ * Trick to restart an element's animation
103
+ *
104
+ * @param {HTMLElement} element
105
+ * @return void
106
+ *
107
+ * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
108
+ */
109
+
110
+
111
+ const reflow = element => {
112
+ // eslint-disable-next-line no-unused-expressions
113
+ element.offsetHeight;
114
+ };
96
115
 
97
116
  const getjQuery = () => {
98
117
  const {
@@ -106,20 +125,30 @@
106
125
  return null;
107
126
  };
108
127
 
128
+ const DOMContentLoadedCallbacks = [];
129
+
109
130
  const onDOMContentLoaded = callback => {
110
131
  if (document.readyState === 'loading') {
111
- document.addEventListener('DOMContentLoaded', callback);
132
+ // add listener on the first call when the document is in loading state
133
+ if (!DOMContentLoadedCallbacks.length) {
134
+ document.addEventListener('DOMContentLoaded', () => {
135
+ DOMContentLoadedCallbacks.forEach(callback => callback());
136
+ });
137
+ }
138
+
139
+ DOMContentLoadedCallbacks.push(callback);
112
140
  } else {
113
141
  callback();
114
142
  }
115
143
  };
116
144
 
117
- const defineJQueryPlugin = (name, plugin) => {
145
+ const defineJQueryPlugin = plugin => {
118
146
  onDOMContentLoaded(() => {
119
147
  const $ = getjQuery();
120
148
  /* istanbul ignore if */
121
149
 
122
150
  if ($) {
151
+ const name = plugin.NAME;
123
152
  const JQUERY_NO_CONFLICT = $.fn[name];
124
153
  $.fn[name] = plugin.jQueryInterface;
125
154
  $.fn[name].Constructor = plugin;
@@ -134,7 +163,33 @@
134
163
 
135
164
  /**
136
165
  * --------------------------------------------------------------------------
137
- * Bootstrap (v5.0.0): toast.js
166
+ * Bootstrap (v5.1.1): util/component-functions.js
167
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
168
+ * --------------------------------------------------------------------------
169
+ */
170
+
171
+ const enableDismissTrigger = (component, method = 'hide') => {
172
+ const clickEvent = `click.dismiss${component.EVENT_KEY}`;
173
+ const name = component.NAME;
174
+ EventHandler__default['default'].on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
175
+ if (['A', 'AREA'].includes(this.tagName)) {
176
+ event.preventDefault();
177
+ }
178
+
179
+ if (isDisabled(this)) {
180
+ return;
181
+ }
182
+
183
+ const target = getElementFromSelector(this) || this.closest(`.${name}`);
184
+ const instance = component.getOrCreateInstance(target); // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
185
+
186
+ instance[method]();
187
+ });
188
+ };
189
+
190
+ /**
191
+ * --------------------------------------------------------------------------
192
+ * Bootstrap (v5.1.1): toast.js
138
193
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
139
194
  * --------------------------------------------------------------------------
140
195
  */
@@ -147,13 +202,17 @@
147
202
  const NAME = 'toast';
148
203
  const DATA_KEY = 'bs.toast';
149
204
  const EVENT_KEY = `.${DATA_KEY}`;
150
- const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
205
+ const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;
206
+ const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;
207
+ const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
208
+ const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`;
151
209
  const EVENT_HIDE = `hide${EVENT_KEY}`;
152
210
  const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
153
211
  const EVENT_SHOW = `show${EVENT_KEY}`;
154
212
  const EVENT_SHOWN = `shown${EVENT_KEY}`;
155
213
  const CLASS_NAME_FADE = 'fade';
156
- const CLASS_NAME_HIDE = 'hide';
214
+ const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility
215
+
157
216
  const CLASS_NAME_SHOW = 'show';
158
217
  const CLASS_NAME_SHOWING = 'showing';
159
218
  const DefaultType = {
@@ -166,7 +225,6 @@
166
225
  autohide: true,
167
226
  delay: 5000
168
227
  };
169
- const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="toast"]';
170
228
  /**
171
229
  * ------------------------------------------------------------------------
172
230
  * Class Definition
@@ -178,6 +236,8 @@
178
236
  super(element);
179
237
  this._config = this._getConfig(config);
180
238
  this._timeout = null;
239
+ this._hasMouseInteraction = false;
240
+ this._hasKeyboardInteraction = false;
181
241
 
182
242
  this._setListeners();
183
243
  } // Getters
@@ -191,8 +251,8 @@
191
251
  return Default;
192
252
  }
193
253
 
194
- static get DATA_KEY() {
195
- return DATA_KEY;
254
+ static get NAME() {
255
+ return NAME;
196
256
  } // Public
197
257
 
198
258
 
@@ -212,30 +272,21 @@
212
272
  const complete = () => {
213
273
  this._element.classList.remove(CLASS_NAME_SHOWING);
214
274
 
215
- this._element.classList.add(CLASS_NAME_SHOW);
216
-
217
275
  EventHandler__default['default'].trigger(this._element, EVENT_SHOWN);
218
276
 
219
- if (this._config.autohide) {
220
- this._timeout = setTimeout(() => {
221
- this.hide();
222
- }, this._config.delay);
223
- }
277
+ this._maybeScheduleHide();
224
278
  };
225
279
 
226
- this._element.classList.remove(CLASS_NAME_HIDE);
280
+ this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated
281
+
227
282
 
228
283
  reflow(this._element);
229
284
 
285
+ this._element.classList.add(CLASS_NAME_SHOW);
286
+
230
287
  this._element.classList.add(CLASS_NAME_SHOWING);
231
288
 
232
- if (this._config.animation) {
233
- const transitionDuration = getTransitionDurationFromElement(this._element);
234
- EventHandler__default['default'].one(this._element, 'transitionend', complete);
235
- emulateTransitionEnd(this._element, transitionDuration);
236
- } else {
237
- complete();
238
- }
289
+ this._queueCallback(complete, this._element, this._config.animation);
239
290
  }
240
291
 
241
292
  hide() {
@@ -250,20 +301,19 @@
250
301
  }
251
302
 
252
303
  const complete = () => {
253
- this._element.classList.add(CLASS_NAME_HIDE);
304
+ this._element.classList.add(CLASS_NAME_HIDE); // @deprecated
305
+
306
+
307
+ this._element.classList.remove(CLASS_NAME_SHOWING);
308
+
309
+ this._element.classList.remove(CLASS_NAME_SHOW);
254
310
 
255
311
  EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN);
256
312
  };
257
313
 
258
- this._element.classList.remove(CLASS_NAME_SHOW);
314
+ this._element.classList.add(CLASS_NAME_SHOWING);
259
315
 
260
- if (this._config.animation) {
261
- const transitionDuration = getTransitionDurationFromElement(this._element);
262
- EventHandler__default['default'].one(this._element, 'transitionend', complete);
263
- emulateTransitionEnd(this._element, transitionDuration);
264
- } else {
265
- complete();
266
- }
316
+ this._queueCallback(complete, this._element, this._config.animation);
267
317
  }
268
318
 
269
319
  dispose() {
@@ -274,7 +324,6 @@
274
324
  }
275
325
 
276
326
  super.dispose();
277
- this._config = null;
278
327
  } // Private
279
328
 
280
329
 
@@ -287,8 +336,53 @@
287
336
  return config;
288
337
  }
289
338
 
339
+ _maybeScheduleHide() {
340
+ if (!this._config.autohide) {
341
+ return;
342
+ }
343
+
344
+ if (this._hasMouseInteraction || this._hasKeyboardInteraction) {
345
+ return;
346
+ }
347
+
348
+ this._timeout = setTimeout(() => {
349
+ this.hide();
350
+ }, this._config.delay);
351
+ }
352
+
353
+ _onInteraction(event, isInteracting) {
354
+ switch (event.type) {
355
+ case 'mouseover':
356
+ case 'mouseout':
357
+ this._hasMouseInteraction = isInteracting;
358
+ break;
359
+
360
+ case 'focusin':
361
+ case 'focusout':
362
+ this._hasKeyboardInteraction = isInteracting;
363
+ break;
364
+ }
365
+
366
+ if (isInteracting) {
367
+ this._clearTimeout();
368
+
369
+ return;
370
+ }
371
+
372
+ const nextElement = event.relatedTarget;
373
+
374
+ if (this._element === nextElement || this._element.contains(nextElement)) {
375
+ return;
376
+ }
377
+
378
+ this._maybeScheduleHide();
379
+ }
380
+
290
381
  _setListeners() {
291
- EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
382
+ EventHandler__default['default'].on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true));
383
+ EventHandler__default['default'].on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false));
384
+ EventHandler__default['default'].on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true));
385
+ EventHandler__default['default'].on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false));
292
386
  }
293
387
 
294
388
  _clearTimeout() {
@@ -299,13 +393,7 @@
299
393
 
300
394
  static jQueryInterface(config) {
301
395
  return this.each(function () {
302
- let data = Data__default['default'].get(this, DATA_KEY);
303
-
304
- const _config = typeof config === 'object' && config;
305
-
306
- if (!data) {
307
- data = new Toast(this, _config);
308
- }
396
+ const data = Toast.getOrCreateInstance(this, config);
309
397
 
310
398
  if (typeof config === 'string') {
311
399
  if (typeof data[config] === 'undefined') {
@@ -318,6 +406,8 @@
318
406
  }
319
407
 
320
408
  }
409
+
410
+ enableDismissTrigger(Toast);
321
411
  /**
322
412
  * ------------------------------------------------------------------------
323
413
  * jQuery
@@ -325,8 +415,7 @@
325
415
  * add .Toast to jQuery only if jQuery is present
326
416
  */
327
417
 
328
-
329
- defineJQueryPlugin(NAME, Toast);
418
+ defineJQueryPlugin(Toast);
330
419
 
331
420
  return Toast;
332
421