bootstrap 5.0.0.beta3 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/assets/javascripts/bootstrap-sprockets.js +1 -1
  4. data/assets/javascripts/bootstrap.js +509 -459
  5. data/assets/javascripts/bootstrap.min.js +2 -2
  6. data/assets/javascripts/bootstrap/alert.js +4 -4
  7. data/assets/javascripts/bootstrap/base-component.js +9 -7
  8. data/assets/javascripts/bootstrap/button.js +3 -3
  9. data/assets/javascripts/bootstrap/carousel.js +11 -12
  10. data/assets/javascripts/bootstrap/collapse.js +5 -5
  11. data/assets/javascripts/bootstrap/dom/data.js +2 -2
  12. data/assets/javascripts/bootstrap/dom/event-handler.js +32 -14
  13. data/assets/javascripts/bootstrap/dom/manipulator.js +2 -2
  14. data/assets/javascripts/bootstrap/dom/selector-engine.js +2 -2
  15. data/assets/javascripts/bootstrap/dropdown.js +109 -94
  16. data/assets/javascripts/bootstrap/modal.js +262 -177
  17. data/assets/javascripts/bootstrap/offcanvas.js +219 -56
  18. data/assets/javascripts/bootstrap/popover.js +3 -3
  19. data/assets/javascripts/bootstrap/scrollspy.js +18 -22
  20. data/assets/javascripts/bootstrap/tab.js +21 -8
  21. data/assets/javascripts/bootstrap/toast.js +4 -5
  22. data/assets/javascripts/bootstrap/tooltip.js +7 -9
  23. data/assets/stylesheets/_bootstrap-grid.scss +1 -1
  24. data/assets/stylesheets/_bootstrap-reboot.scss +1 -1
  25. data/assets/stylesheets/_bootstrap.scss +1 -1
  26. data/assets/stylesheets/bootstrap/_accordion.scss +4 -2
  27. data/assets/stylesheets/bootstrap/_dropdown.scss +7 -13
  28. data/assets/stylesheets/bootstrap/_list-group.scss +1 -1
  29. data/assets/stylesheets/bootstrap/_mixins.scss +1 -0
  30. data/assets/stylesheets/bootstrap/_modal.scss +0 -9
  31. data/assets/stylesheets/bootstrap/_offcanvas.scss +11 -11
  32. data/assets/stylesheets/bootstrap/_spinners.scss +2 -2
  33. data/assets/stylesheets/bootstrap/_variables.scss +7 -7
  34. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +1 -1
  35. data/assets/stylesheets/bootstrap/forms/_form-control.scss +5 -5
  36. data/assets/stylesheets/bootstrap/mixins/_color-scheme.scss +7 -0
  37. data/assets/stylesheets/bootstrap/mixins/_forms.scss +7 -4
  38. data/assets/stylesheets/bootstrap/mixins/_grid.scss +8 -3
  39. data/bootstrap.gemspec +1 -1
  40. data/lib/bootstrap/version.rb +2 -2
  41. data/tasks/updater/js.rb +1 -1
  42. metadata +7 -6
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Bootstrap offcanvas.js v5.0.0-beta3 (https://getbootstrap.com/)
2
+ * Bootstrap offcanvas.js v5.0.0 (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
  */
@@ -19,11 +19,12 @@
19
19
 
20
20
  /**
21
21
  * --------------------------------------------------------------------------
22
- * Bootstrap (v5.0.0-beta3): util/index.js
22
+ * Bootstrap (v5.0.0): util/index.js
23
23
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
24
24
  * --------------------------------------------------------------------------
25
25
  */
26
26
  const MILLISECONDS_MULTIPLIER = 1000;
27
+ const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
27
28
 
28
29
  const toType = obj => {
29
30
  if (obj === null || obj === undefined) {
@@ -48,7 +49,7 @@
48
49
 
49
50
 
50
51
  if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
51
- hrefAttr = '#' + hrefAttr.split('#')[1];
52
+ hrefAttr = `#${hrefAttr.split('#')[1]}`;
52
53
  }
53
54
 
54
55
  selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
@@ -57,16 +58,6 @@
57
58
  return selector;
58
59
  };
59
60
 
60
- const getSelectorFromElement = element => {
61
- const selector = getSelector(element);
62
-
63
- if (selector) {
64
- return document.querySelector(selector) ? selector : null;
65
- }
66
-
67
- return null;
68
- };
69
-
70
61
  const getElementFromSelector = element => {
71
62
  const selector = getSelector(element);
72
63
  return selector ? document.querySelector(selector) : null;
@@ -95,8 +86,30 @@
95
86
  return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
96
87
  };
97
88
 
89
+ const triggerTransitionEnd = element => {
90
+ element.dispatchEvent(new Event(TRANSITION_END));
91
+ };
92
+
98
93
  const isElement = obj => (obj[0] || obj).nodeType;
99
94
 
95
+ const emulateTransitionEnd = (element, duration) => {
96
+ let called = false;
97
+ const durationPadding = 5;
98
+ const emulatedDuration = duration + durationPadding;
99
+
100
+ function listener() {
101
+ called = true;
102
+ element.removeEventListener(TRANSITION_END, listener);
103
+ }
104
+
105
+ element.addEventListener(TRANSITION_END, listener);
106
+ setTimeout(() => {
107
+ if (!called) {
108
+ triggerTransitionEnd(element);
109
+ }
110
+ }, emulatedDuration);
111
+ };
112
+
100
113
  const typeCheckConfig = (componentName, config, configTypes) => {
101
114
  Object.keys(configTypes).forEach(property => {
102
115
  const expectedTypes = configTypes[property];
@@ -104,7 +117,7 @@
104
117
  const valueType = value && isElement(value) ? 'element' : toType(value);
105
118
 
106
119
  if (!new RegExp(expectedTypes).test(valueType)) {
107
- throw new TypeError(`${componentName.toUpperCase()}: ` + `Option "${property}" provided type "${valueType}" ` + `but expected type "${expectedTypes}".`);
120
+ throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
108
121
  }
109
122
  });
110
123
  };
@@ -139,6 +152,8 @@
139
152
  return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
140
153
  };
141
154
 
155
+ const reflow = element => element.offsetHeight;
156
+
142
157
  const getjQuery = () => {
143
158
  const {
144
159
  jQuery
@@ -177,13 +192,19 @@
177
192
  });
178
193
  };
179
194
 
195
+ const execute = callback => {
196
+ if (typeof callback === 'function') {
197
+ callback();
198
+ }
199
+ };
200
+
180
201
  /**
181
202
  * --------------------------------------------------------------------------
182
- * Bootstrap (v5.0.0-beta3): util/scrollBar.js
203
+ * Bootstrap (v5.0.0): util/scrollBar.js
183
204
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
184
205
  * --------------------------------------------------------------------------
185
206
  */
186
- const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed';
207
+ const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
187
208
  const SELECTOR_STICKY_CONTENT = '.sticky-top';
188
209
 
189
210
  const getWidth = () => {
@@ -193,13 +214,25 @@
193
214
  };
194
215
 
195
216
  const hide = (width = getWidth()) => {
196
- document.body.style.overflow = 'hidden';
217
+ _disableOverFlow(); // give padding to element to balances the hidden scrollbar width
218
+
219
+
220
+ _setElementAttributes('body', 'paddingRight', calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements, to keep shown fullwidth
221
+
197
222
 
198
223
  _setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width);
199
224
 
200
225
  _setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);
226
+ };
201
227
 
202
- _setElementAttributes('body', 'paddingRight', calculatedValue => calculatedValue + width);
228
+ const _disableOverFlow = () => {
229
+ const actualValue = document.body.style.overflow;
230
+
231
+ if (actualValue) {
232
+ Manipulator__default['default'].setDataAttribute(document.body, 'overflow', actualValue);
233
+ }
234
+
235
+ document.body.style.overflow = 'hidden';
203
236
  };
204
237
 
205
238
  const _setElementAttributes = (selector, styleProp, callback) => {
@@ -212,25 +245,25 @@
212
245
  const actualValue = element.style[styleProp];
213
246
  const calculatedValue = window.getComputedStyle(element)[styleProp];
214
247
  Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue);
215
- element.style[styleProp] = callback(Number.parseFloat(calculatedValue)) + 'px';
248
+ element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
216
249
  });
217
250
  };
218
251
 
219
252
  const reset = () => {
220
- document.body.style.overflow = 'auto';
253
+ _resetElementAttributes('body', 'overflow');
254
+
255
+ _resetElementAttributes('body', 'paddingRight');
221
256
 
222
257
  _resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
223
258
 
224
259
  _resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
225
-
226
- _resetElementAttributes('body', 'paddingRight');
227
260
  };
228
261
 
229
262
  const _resetElementAttributes = (selector, styleProp) => {
230
263
  SelectorEngine__default['default'].find(selector).forEach(element => {
231
264
  const value = Manipulator__default['default'].getDataAttribute(element, styleProp);
232
265
 
233
- if (typeof value === 'undefined' && element === document.body) {
266
+ if (typeof value === 'undefined') {
234
267
  element.style.removeProperty(styleProp);
235
268
  } else {
236
269
  Manipulator__default['default'].removeDataAttribute(element, styleProp);
@@ -241,7 +274,135 @@
241
274
 
242
275
  /**
243
276
  * --------------------------------------------------------------------------
244
- * Bootstrap (v5.0.0-beta3): offcanvas.js
277
+ * Bootstrap (v5.0.0): util/backdrop.js
278
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
279
+ * --------------------------------------------------------------------------
280
+ */
281
+ const Default$1 = {
282
+ isVisible: true,
283
+ // if false, we use the backdrop helper without adding any element to the dom
284
+ isAnimated: false,
285
+ rootElement: document.body,
286
+ // give the choice to place backdrop under different elements
287
+ clickCallback: null
288
+ };
289
+ const DefaultType$1 = {
290
+ isVisible: 'boolean',
291
+ isAnimated: 'boolean',
292
+ rootElement: 'element',
293
+ clickCallback: '(function|null)'
294
+ };
295
+ const NAME$1 = 'backdrop';
296
+ const CLASS_NAME_BACKDROP = 'modal-backdrop';
297
+ const CLASS_NAME_FADE = 'fade';
298
+ const CLASS_NAME_SHOW$1 = 'show';
299
+ const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$1}`;
300
+
301
+ class Backdrop {
302
+ constructor(config) {
303
+ this._config = this._getConfig(config);
304
+ this._isAppended = false;
305
+ this._element = null;
306
+ }
307
+
308
+ show(callback) {
309
+ if (!this._config.isVisible) {
310
+ execute(callback);
311
+ return;
312
+ }
313
+
314
+ this._append();
315
+
316
+ if (this._config.isAnimated) {
317
+ reflow(this._getElement());
318
+ }
319
+
320
+ this._getElement().classList.add(CLASS_NAME_SHOW$1);
321
+
322
+ this._emulateAnimation(() => {
323
+ execute(callback);
324
+ });
325
+ }
326
+
327
+ hide(callback) {
328
+ if (!this._config.isVisible) {
329
+ execute(callback);
330
+ return;
331
+ }
332
+
333
+ this._getElement().classList.remove(CLASS_NAME_SHOW$1);
334
+
335
+ this._emulateAnimation(() => {
336
+ this.dispose();
337
+ execute(callback);
338
+ });
339
+ } // Private
340
+
341
+
342
+ _getElement() {
343
+ if (!this._element) {
344
+ const backdrop = document.createElement('div');
345
+ backdrop.className = CLASS_NAME_BACKDROP;
346
+
347
+ if (this._config.isAnimated) {
348
+ backdrop.classList.add(CLASS_NAME_FADE);
349
+ }
350
+
351
+ this._element = backdrop;
352
+ }
353
+
354
+ return this._element;
355
+ }
356
+
357
+ _getConfig(config) {
358
+ config = { ...Default$1,
359
+ ...(typeof config === 'object' ? config : {})
360
+ };
361
+ typeCheckConfig(NAME$1, config, DefaultType$1);
362
+ return config;
363
+ }
364
+
365
+ _append() {
366
+ if (this._isAppended) {
367
+ return;
368
+ }
369
+
370
+ this._config.rootElement.appendChild(this._getElement());
371
+
372
+ EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => {
373
+ execute(this._config.clickCallback);
374
+ });
375
+ this._isAppended = true;
376
+ }
377
+
378
+ dispose() {
379
+ if (!this._isAppended) {
380
+ return;
381
+ }
382
+
383
+ EventHandler__default['default'].off(this._element, EVENT_MOUSEDOWN);
384
+
385
+ this._getElement().parentNode.removeChild(this._element);
386
+
387
+ this._isAppended = false;
388
+ }
389
+
390
+ _emulateAnimation(callback) {
391
+ if (!this._config.isAnimated) {
392
+ execute(callback);
393
+ return;
394
+ }
395
+
396
+ const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement());
397
+ EventHandler__default['default'].one(this._getElement(), 'transitionend', () => execute(callback));
398
+ emulateTransitionEnd(this._getElement(), backdropTransitionDuration);
399
+ }
400
+
401
+ }
402
+
403
+ /**
404
+ * --------------------------------------------------------------------------
405
+ * Bootstrap (v5.0.0): offcanvas.js
245
406
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
246
407
  * --------------------------------------------------------------------------
247
408
  */
@@ -267,11 +428,8 @@
267
428
  keyboard: 'boolean',
268
429
  scroll: 'boolean'
269
430
  };
270
- const CLASS_NAME_BACKDROP_BODY = 'offcanvas-backdrop';
271
431
  const CLASS_NAME_SHOW = 'show';
272
- const CLASS_NAME_TOGGLING = 'offcanvas-toggling';
273
432
  const OPEN_SELECTOR = '.offcanvas.show';
274
- const ACTIVE_SELECTOR = `${OPEN_SELECTOR}, .${CLASS_NAME_TOGGLING}`;
275
433
  const EVENT_SHOW = `show${EVENT_KEY}`;
276
434
  const EVENT_SHOWN = `shown${EVENT_KEY}`;
277
435
  const EVENT_HIDE = `hide${EVENT_KEY}`;
@@ -279,6 +437,7 @@
279
437
  const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
280
438
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
281
439
  const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
440
+ const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
282
441
  const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]';
283
442
  const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]';
284
443
  /**
@@ -292,6 +451,7 @@
292
451
  super(element);
293
452
  this._config = this._getConfig(config);
294
453
  this._isShown = false;
454
+ this._backdrop = this._initializeBackDrop();
295
455
 
296
456
  this._addEventListeners();
297
457
  } // Getters
@@ -326,15 +486,13 @@
326
486
  this._isShown = true;
327
487
  this._element.style.visibility = 'visible';
328
488
 
329
- if (this._config.backdrop) {
330
- document.body.classList.add(CLASS_NAME_BACKDROP_BODY);
331
- }
489
+ this._backdrop.show();
332
490
 
333
491
  if (!this._config.scroll) {
334
492
  hide();
335
- }
336
493
 
337
- this._element.classList.add(CLASS_NAME_TOGGLING);
494
+ this._enforceFocusOnElement(this._element);
495
+ }
338
496
 
339
497
  this._element.removeAttribute('aria-hidden');
340
498
 
@@ -345,16 +503,14 @@
345
503
  this._element.classList.add(CLASS_NAME_SHOW);
346
504
 
347
505
  const completeCallBack = () => {
348
- this._element.classList.remove(CLASS_NAME_TOGGLING);
349
-
350
506
  EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, {
351
507
  relatedTarget
352
508
  });
353
-
354
- this._enforceFocusOnElement(this._element);
355
509
  };
356
510
 
357
- setTimeout(completeCallBack, getTransitionDurationFromElement(this._element));
511
+ const transitionDuration = getTransitionDurationFromElement(this._element);
512
+ EventHandler__default['default'].one(this._element, 'transitionend', completeCallBack);
513
+ emulateTransitionEnd(this._element, transitionDuration);
358
514
  }
359
515
 
360
516
  hide() {
@@ -368,8 +524,6 @@
368
524
  return;
369
525
  }
370
526
 
371
- this._element.classList.add(CLASS_NAME_TOGGLING);
372
-
373
527
  EventHandler__default['default'].off(document, EVENT_FOCUSIN);
374
528
 
375
529
  this._element.blur();
@@ -378,6 +532,8 @@
378
532
 
379
533
  this._element.classList.remove(CLASS_NAME_SHOW);
380
534
 
535
+ this._backdrop.hide();
536
+
381
537
  const completeCallback = () => {
382
538
  this._element.setAttribute('aria-hidden', true);
383
539
 
@@ -387,20 +543,25 @@
387
543
 
388
544
  this._element.style.visibility = 'hidden';
389
545
 
390
- if (this._config.backdrop) {
391
- document.body.classList.remove(CLASS_NAME_BACKDROP_BODY);
392
- }
393
-
394
546
  if (!this._config.scroll) {
395
547
  reset();
396
548
  }
397
549
 
398
550
  EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN);
399
-
400
- this._element.classList.remove(CLASS_NAME_TOGGLING);
401
551
  };
402
552
 
403
- setTimeout(completeCallback, getTransitionDurationFromElement(this._element));
553
+ const transitionDuration = getTransitionDurationFromElement(this._element);
554
+ EventHandler__default['default'].one(this._element, 'transitionend', completeCallback);
555
+ emulateTransitionEnd(this._element, transitionDuration);
556
+ }
557
+
558
+ dispose() {
559
+ this._backdrop.dispose();
560
+
561
+ super.dispose();
562
+ EventHandler__default['default'].off(document, EVENT_FOCUSIN);
563
+ this._config = null;
564
+ this._backdrop = null;
404
565
  } // Private
405
566
 
406
567
 
@@ -413,6 +574,15 @@
413
574
  return config;
414
575
  }
415
576
 
577
+ _initializeBackDrop() {
578
+ return new Backdrop({
579
+ isVisible: this._config.backdrop,
580
+ isAnimated: true,
581
+ rootElement: this._element.parentNode,
582
+ clickCallback: () => this.hide()
583
+ });
584
+ }
585
+
416
586
  _enforceFocusOnElement(element) {
417
587
  EventHandler__default['default'].off(document, EVENT_FOCUSIN); // guard against infinite focus loop
418
588
 
@@ -426,18 +596,11 @@
426
596
 
427
597
  _addEventListeners() {
428
598
  EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
429
- EventHandler__default['default'].on(document, 'keydown', event => {
599
+ EventHandler__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, event => {
430
600
  if (this._config.keyboard && event.key === ESCAPE_KEY) {
431
601
  this.hide();
432
602
  }
433
603
  });
434
- EventHandler__default['default'].on(document, EVENT_CLICK_DATA_API, event => {
435
- const target = SelectorEngine__default['default'].findOne(getSelectorFromElement(event.target));
436
-
437
- if (!this._element.contains(event.target) && target !== this._element) {
438
- this.hide();
439
- }
440
- });
441
604
  } // Static
442
605
 
443
606
 
@@ -483,10 +646,10 @@
483
646
  }
484
647
  }); // avoid conflict when clicking a toggler of an offcanvas, while another is open
485
648
 
486
- const allReadyOpen = SelectorEngine__default['default'].findOne(ACTIVE_SELECTOR);
649
+ const allReadyOpen = SelectorEngine__default['default'].findOne(OPEN_SELECTOR);
487
650
 
488
651
  if (allReadyOpen && allReadyOpen !== target) {
489
- return;
652
+ Offcanvas.getInstance(allReadyOpen).hide();
490
653
  }
491
654
 
492
655
  const data = Data__default['default'].get(target, DATA_KEY) || new Offcanvas(target);