bootstrap 5.0.0.beta3 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/assets/javascripts/bootstrap-sprockets.js +1 -1
  4. data/assets/javascripts/bootstrap.js +1310 -1277
  5. data/assets/javascripts/bootstrap.min.js +2 -2
  6. data/assets/javascripts/bootstrap/alert.js +78 -107
  7. data/assets/javascripts/bootstrap/base-component.js +131 -10
  8. data/assets/javascripts/bootstrap/button.js +24 -24
  9. data/assets/javascripts/bootstrap/carousel.js +115 -133
  10. data/assets/javascripts/bootstrap/collapse.js +120 -177
  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 +4 -4
  14. data/assets/javascripts/bootstrap/dom/selector-engine.js +47 -5
  15. data/assets/javascripts/bootstrap/dropdown.js +218 -191
  16. data/assets/javascripts/bootstrap/modal.js +553 -271
  17. data/assets/javascripts/bootstrap/offcanvas.js +478 -120
  18. data/assets/javascripts/bootstrap/popover.js +27 -59
  19. data/assets/javascripts/bootstrap/scrollspy.js +65 -74
  20. data/assets/javascripts/bootstrap/tab.js +57 -71
  21. data/assets/javascripts/bootstrap/toast.js +176 -88
  22. data/assets/javascripts/bootstrap/tooltip.js +125 -182
  23. data/assets/stylesheets/_bootstrap-grid.scss +1 -1
  24. data/assets/stylesheets/_bootstrap-reboot.scss +1 -1
  25. data/assets/stylesheets/_bootstrap.scss +2 -1
  26. data/assets/stylesheets/bootstrap/_accordion.scss +4 -2
  27. data/assets/stylesheets/bootstrap/_card.scss +7 -6
  28. data/assets/stylesheets/bootstrap/_carousel.scss +2 -2
  29. data/assets/stylesheets/bootstrap/_dropdown.scss +11 -17
  30. data/assets/stylesheets/bootstrap/_functions.scss +94 -3
  31. data/assets/stylesheets/bootstrap/_grid.scss +11 -0
  32. data/assets/stylesheets/bootstrap/_helpers.scss +2 -0
  33. data/assets/stylesheets/bootstrap/_images.scss +1 -1
  34. data/assets/stylesheets/bootstrap/_list-group.scss +5 -5
  35. data/assets/stylesheets/bootstrap/_mixins.scss +2 -0
  36. data/assets/stylesheets/bootstrap/_modal.scss +7 -35
  37. data/assets/stylesheets/bootstrap/_navbar.scss +30 -1
  38. data/assets/stylesheets/bootstrap/_offcanvas.scss +19 -13
  39. data/assets/stylesheets/bootstrap/_placeholders.scss +51 -0
  40. data/assets/stylesheets/bootstrap/_popover.scss +10 -10
  41. data/assets/stylesheets/bootstrap/_reboot.scss +12 -8
  42. data/assets/stylesheets/bootstrap/_root.scss +39 -2
  43. data/assets/stylesheets/bootstrap/_spinners.scss +2 -2
  44. data/assets/stylesheets/bootstrap/_tables.scss +1 -0
  45. data/assets/stylesheets/bootstrap/_toasts.scss +3 -3
  46. data/assets/stylesheets/bootstrap/_tooltip.scss +4 -4
  47. data/assets/stylesheets/bootstrap/_transitions.scss +6 -0
  48. data/assets/stylesheets/bootstrap/_utilities.scss +44 -8
  49. data/assets/stylesheets/bootstrap/_variables.scss +193 -28
  50. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +1 -1
  51. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +3 -1
  52. data/assets/stylesheets/bootstrap/forms/_form-check.scss +1 -1
  53. data/assets/stylesheets/bootstrap/forms/_form-control.scss +1 -1
  54. data/assets/stylesheets/bootstrap/forms/_form-range.scss +1 -1
  55. data/assets/stylesheets/bootstrap/forms/_form-select.scss +3 -0
  56. data/assets/stylesheets/bootstrap/helpers/_stacks.scss +15 -0
  57. data/assets/stylesheets/bootstrap/helpers/_vr.scss +8 -0
  58. data/assets/stylesheets/bootstrap/mixins/_backdrop.scss +14 -0
  59. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +1 -1
  60. data/assets/stylesheets/bootstrap/mixins/_color-scheme.scss +7 -0
  61. data/assets/stylesheets/bootstrap/mixins/_forms.scss +15 -5
  62. data/assets/stylesheets/bootstrap/mixins/_grid.scss +40 -10
  63. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +27 -6
  64. data/assets/stylesheets/bootstrap/vendor/_rfs.scss +55 -13
  65. data/bootstrap.gemspec +3 -3
  66. data/lib/bootstrap/version.rb +2 -2
  67. data/tasks/updater/js.rb +6 -2
  68. metadata +15 -10
@@ -1,29 +1,29 @@
1
1
  /*!
2
- * Bootstrap offcanvas.js v5.0.0-beta3 (https://getbootstrap.com/)
2
+ * Bootstrap offcanvas.js v5.1.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
  */
6
6
  (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/selector-engine.js'), require('./dom/manipulator.js'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./base-component.js')) :
8
- typeof define === 'function' && define.amd ? define(['./dom/selector-engine', './dom/manipulator', './dom/data', './dom/event-handler', './base-component'], factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Offcanvas = factory(global.SelectorEngine, global.Manipulator, global.Data, global.EventHandler, global.Base));
10
- }(this, (function (SelectorEngine, Manipulator, Data, EventHandler, BaseComponent) { 'use strict';
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/selector-engine.js'), require('./dom/manipulator.js'), require('./dom/event-handler.js'), require('./base-component.js')) :
8
+ typeof define === 'function' && define.amd ? define(['./dom/selector-engine', './dom/manipulator', './dom/event-handler', './base-component'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Offcanvas = factory(global.SelectorEngine, global.Manipulator, global.EventHandler, global.Base));
10
+ }(this, (function (SelectorEngine, Manipulator, EventHandler, BaseComponent) { 'use strict';
11
11
 
12
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
13
 
14
14
  var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
15
15
  var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
16
- var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
17
16
  var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
18
17
  var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
19
18
 
20
19
  /**
21
20
  * --------------------------------------------------------------------------
22
- * Bootstrap (v5.0.0-beta3): util/index.js
21
+ * Bootstrap (v5.1.0): util/index.js
23
22
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
24
23
  * --------------------------------------------------------------------------
25
24
  */
26
25
  const MILLISECONDS_MULTIPLIER = 1000;
26
+ const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
27
27
 
28
28
  const toType = obj => {
29
29
  if (obj === null || obj === undefined) {
@@ -48,7 +48,7 @@
48
48
 
49
49
 
50
50
  if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
51
- hrefAttr = '#' + hrefAttr.split('#')[1];
51
+ hrefAttr = `#${hrefAttr.split('#')[1]}`;
52
52
  }
53
53
 
54
54
  selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
@@ -57,16 +57,6 @@
57
57
  return selector;
58
58
  };
59
59
 
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
60
  const getElementFromSelector = element => {
71
61
  const selector = getSelector(element);
72
62
  return selector ? document.querySelector(selector) : null;
@@ -95,7 +85,34 @@
95
85
  return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
96
86
  };
97
87
 
98
- const isElement = obj => (obj[0] || obj).nodeType;
88
+ const triggerTransitionEnd = element => {
89
+ element.dispatchEvent(new Event(TRANSITION_END));
90
+ };
91
+
92
+ const isElement = obj => {
93
+ if (!obj || typeof obj !== 'object') {
94
+ return false;
95
+ }
96
+
97
+ if (typeof obj.jquery !== 'undefined') {
98
+ obj = obj[0];
99
+ }
100
+
101
+ return typeof obj.nodeType !== 'undefined';
102
+ };
103
+
104
+ const getElement = obj => {
105
+ if (isElement(obj)) {
106
+ // it's a jQuery object or a node element
107
+ return obj.jquery ? obj[0] : obj;
108
+ }
109
+
110
+ if (typeof obj === 'string' && obj.length > 0) {
111
+ return document.querySelector(obj);
112
+ }
113
+
114
+ return null;
115
+ };
99
116
 
100
117
  const typeCheckConfig = (componentName, config, configTypes) => {
101
118
  Object.keys(configTypes).forEach(property => {
@@ -104,23 +121,17 @@
104
121
  const valueType = value && isElement(value) ? 'element' : toType(value);
105
122
 
106
123
  if (!new RegExp(expectedTypes).test(valueType)) {
107
- throw new TypeError(`${componentName.toUpperCase()}: ` + `Option "${property}" provided type "${valueType}" ` + `but expected type "${expectedTypes}".`);
124
+ throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
108
125
  }
109
126
  });
110
127
  };
111
128
 
112
129
  const isVisible = element => {
113
- if (!element) {
130
+ if (!isElement(element) || element.getClientRects().length === 0) {
114
131
  return false;
115
132
  }
116
133
 
117
- if (element.style && element.parentNode && element.parentNode.style) {
118
- const elementStyle = getComputedStyle(element);
119
- const parentNodeStyle = getComputedStyle(element.parentNode);
120
- return elementStyle.display !== 'none' && parentNodeStyle.display !== 'none' && elementStyle.visibility !== 'hidden';
121
- }
122
-
123
- return false;
134
+ return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
124
135
  };
125
136
 
126
137
  const isDisabled = element => {
@@ -138,6 +149,20 @@
138
149
 
139
150
  return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
140
151
  };
152
+ /**
153
+ * Trick to restart an element's animation
154
+ *
155
+ * @param {HTMLElement} element
156
+ * @return void
157
+ *
158
+ * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
159
+ */
160
+
161
+
162
+ const reflow = element => {
163
+ // eslint-disable-next-line no-unused-expressions
164
+ element.offsetHeight;
165
+ };
141
166
 
142
167
  const getjQuery = () => {
143
168
  const {
@@ -151,20 +176,30 @@
151
176
  return null;
152
177
  };
153
178
 
179
+ const DOMContentLoadedCallbacks = [];
180
+
154
181
  const onDOMContentLoaded = callback => {
155
182
  if (document.readyState === 'loading') {
156
- document.addEventListener('DOMContentLoaded', callback);
183
+ // add listener on the first call when the document is in loading state
184
+ if (!DOMContentLoadedCallbacks.length) {
185
+ document.addEventListener('DOMContentLoaded', () => {
186
+ DOMContentLoadedCallbacks.forEach(callback => callback());
187
+ });
188
+ }
189
+
190
+ DOMContentLoadedCallbacks.push(callback);
157
191
  } else {
158
192
  callback();
159
193
  }
160
194
  };
161
195
 
162
- const defineJQueryPlugin = (name, plugin) => {
196
+ const defineJQueryPlugin = plugin => {
163
197
  onDOMContentLoaded(() => {
164
198
  const $ = getjQuery();
165
199
  /* istanbul ignore if */
166
200
 
167
201
  if ($) {
202
+ const name = plugin.NAME;
168
203
  const JQUERY_NO_CONFLICT = $.fn[name];
169
204
  $.fn[name] = plugin.jQueryInterface;
170
205
  $.fn[name].Constructor = plugin;
@@ -177,71 +212,402 @@
177
212
  });
178
213
  };
179
214
 
215
+ const execute = callback => {
216
+ if (typeof callback === 'function') {
217
+ callback();
218
+ }
219
+ };
220
+
221
+ const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
222
+ if (!waitForTransition) {
223
+ execute(callback);
224
+ return;
225
+ }
226
+
227
+ const durationPadding = 5;
228
+ const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
229
+ let called = false;
230
+
231
+ const handler = ({
232
+ target
233
+ }) => {
234
+ if (target !== transitionElement) {
235
+ return;
236
+ }
237
+
238
+ called = true;
239
+ transitionElement.removeEventListener(TRANSITION_END, handler);
240
+ execute(callback);
241
+ };
242
+
243
+ transitionElement.addEventListener(TRANSITION_END, handler);
244
+ setTimeout(() => {
245
+ if (!called) {
246
+ triggerTransitionEnd(transitionElement);
247
+ }
248
+ }, emulatedDuration);
249
+ };
250
+
180
251
  /**
181
252
  * --------------------------------------------------------------------------
182
- * Bootstrap (v5.0.0-beta3): util/scrollBar.js
253
+ * Bootstrap (v5.1.0): util/scrollBar.js
183
254
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
184
255
  * --------------------------------------------------------------------------
185
256
  */
186
- const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed';
257
+ const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
187
258
  const SELECTOR_STICKY_CONTENT = '.sticky-top';
188
259
 
189
- const getWidth = () => {
190
- // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
191
- const documentWidth = document.documentElement.clientWidth;
192
- return Math.abs(window.innerWidth - documentWidth);
193
- };
260
+ class ScrollBarHelper {
261
+ constructor() {
262
+ this._element = document.body;
263
+ }
194
264
 
195
- const hide = (width = getWidth()) => {
196
- document.body.style.overflow = 'hidden';
265
+ getWidth() {
266
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
267
+ const documentWidth = document.documentElement.clientWidth;
268
+ return Math.abs(window.innerWidth - documentWidth);
269
+ }
270
+
271
+ hide() {
272
+ const width = this.getWidth();
273
+
274
+ this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width
197
275
 
198
- _setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width);
199
276
 
200
- _setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);
277
+ this._setElementAttributes(this._element, 'paddingRight', calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth
201
278
 
202
- _setElementAttributes('body', 'paddingRight', calculatedValue => calculatedValue + width);
279
+
280
+ this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width);
281
+
282
+ this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);
283
+ }
284
+
285
+ _disableOverFlow() {
286
+ this._saveInitialAttribute(this._element, 'overflow');
287
+
288
+ this._element.style.overflow = 'hidden';
289
+ }
290
+
291
+ _setElementAttributes(selector, styleProp, callback) {
292
+ const scrollbarWidth = this.getWidth();
293
+
294
+ const manipulationCallBack = element => {
295
+ if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
296
+ return;
297
+ }
298
+
299
+ this._saveInitialAttribute(element, styleProp);
300
+
301
+ const calculatedValue = window.getComputedStyle(element)[styleProp];
302
+ element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
303
+ };
304
+
305
+ this._applyManipulationCallback(selector, manipulationCallBack);
306
+ }
307
+
308
+ reset() {
309
+ this._resetElementAttributes(this._element, 'overflow');
310
+
311
+ this._resetElementAttributes(this._element, 'paddingRight');
312
+
313
+ this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
314
+
315
+ this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
316
+ }
317
+
318
+ _saveInitialAttribute(element, styleProp) {
319
+ const actualValue = element.style[styleProp];
320
+
321
+ if (actualValue) {
322
+ Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue);
323
+ }
324
+ }
325
+
326
+ _resetElementAttributes(selector, styleProp) {
327
+ const manipulationCallBack = element => {
328
+ const value = Manipulator__default['default'].getDataAttribute(element, styleProp);
329
+
330
+ if (typeof value === 'undefined') {
331
+ element.style.removeProperty(styleProp);
332
+ } else {
333
+ Manipulator__default['default'].removeDataAttribute(element, styleProp);
334
+ element.style[styleProp] = value;
335
+ }
336
+ };
337
+
338
+ this._applyManipulationCallback(selector, manipulationCallBack);
339
+ }
340
+
341
+ _applyManipulationCallback(selector, callBack) {
342
+ if (isElement(selector)) {
343
+ callBack(selector);
344
+ } else {
345
+ SelectorEngine__default['default'].find(selector, this._element).forEach(callBack);
346
+ }
347
+ }
348
+
349
+ isOverflowing() {
350
+ return this.getWidth() > 0;
351
+ }
352
+
353
+ }
354
+
355
+ /**
356
+ * --------------------------------------------------------------------------
357
+ * Bootstrap (v5.1.0): util/backdrop.js
358
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
359
+ * --------------------------------------------------------------------------
360
+ */
361
+ const Default$2 = {
362
+ className: 'modal-backdrop',
363
+ isVisible: true,
364
+ // if false, we use the backdrop helper without adding any element to the dom
365
+ isAnimated: false,
366
+ rootElement: 'body',
367
+ // give the choice to place backdrop under different elements
368
+ clickCallback: null
369
+ };
370
+ const DefaultType$2 = {
371
+ className: 'string',
372
+ isVisible: 'boolean',
373
+ isAnimated: 'boolean',
374
+ rootElement: '(element|string)',
375
+ clickCallback: '(function|null)'
203
376
  };
377
+ const NAME$2 = 'backdrop';
378
+ const CLASS_NAME_FADE = 'fade';
379
+ const CLASS_NAME_SHOW$1 = 'show';
380
+ const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$2}`;
204
381
 
205
- const _setElementAttributes = (selector, styleProp, callback) => {
206
- const scrollbarWidth = getWidth();
207
- SelectorEngine__default['default'].find(selector).forEach(element => {
208
- if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) {
382
+ class Backdrop {
383
+ constructor(config) {
384
+ this._config = this._getConfig(config);
385
+ this._isAppended = false;
386
+ this._element = null;
387
+ }
388
+
389
+ show(callback) {
390
+ if (!this._config.isVisible) {
391
+ execute(callback);
209
392
  return;
210
393
  }
211
394
 
212
- const actualValue = element.style[styleProp];
213
- const calculatedValue = window.getComputedStyle(element)[styleProp];
214
- Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue);
215
- element.style[styleProp] = callback(Number.parseFloat(calculatedValue)) + 'px';
216
- });
217
- };
395
+ this._append();
396
+
397
+ if (this._config.isAnimated) {
398
+ reflow(this._getElement());
399
+ }
400
+
401
+ this._getElement().classList.add(CLASS_NAME_SHOW$1);
402
+
403
+ this._emulateAnimation(() => {
404
+ execute(callback);
405
+ });
406
+ }
407
+
408
+ hide(callback) {
409
+ if (!this._config.isVisible) {
410
+ execute(callback);
411
+ return;
412
+ }
413
+
414
+ this._getElement().classList.remove(CLASS_NAME_SHOW$1);
415
+
416
+ this._emulateAnimation(() => {
417
+ this.dispose();
418
+ execute(callback);
419
+ });
420
+ } // Private
421
+
422
+
423
+ _getElement() {
424
+ if (!this._element) {
425
+ const backdrop = document.createElement('div');
426
+ backdrop.className = this._config.className;
427
+
428
+ if (this._config.isAnimated) {
429
+ backdrop.classList.add(CLASS_NAME_FADE);
430
+ }
431
+
432
+ this._element = backdrop;
433
+ }
434
+
435
+ return this._element;
436
+ }
437
+
438
+ _getConfig(config) {
439
+ config = { ...Default$2,
440
+ ...(typeof config === 'object' ? config : {})
441
+ }; // use getElement() with the default "body" to get a fresh Element on each instantiation
442
+
443
+ config.rootElement = getElement(config.rootElement);
444
+ typeCheckConfig(NAME$2, config, DefaultType$2);
445
+ return config;
446
+ }
447
+
448
+ _append() {
449
+ if (this._isAppended) {
450
+ return;
451
+ }
452
+
453
+ this._config.rootElement.append(this._getElement());
454
+
455
+ EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => {
456
+ execute(this._config.clickCallback);
457
+ });
458
+ this._isAppended = true;
459
+ }
460
+
461
+ dispose() {
462
+ if (!this._isAppended) {
463
+ return;
464
+ }
218
465
 
219
- const reset = () => {
220
- document.body.style.overflow = 'auto';
466
+ EventHandler__default['default'].off(this._element, EVENT_MOUSEDOWN);
221
467
 
222
- _resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
468
+ this._element.remove();
223
469
 
224
- _resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
470
+ this._isAppended = false;
471
+ }
472
+
473
+ _emulateAnimation(callback) {
474
+ executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
475
+ }
476
+
477
+ }
225
478
 
226
- _resetElementAttributes('body', 'paddingRight');
479
+ /**
480
+ * --------------------------------------------------------------------------
481
+ * Bootstrap (v5.1.0): util/focustrap.js
482
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
483
+ * --------------------------------------------------------------------------
484
+ */
485
+ const Default$1 = {
486
+ trapElement: null,
487
+ // The element to trap focus inside of
488
+ autofocus: true
227
489
  };
490
+ const DefaultType$1 = {
491
+ trapElement: 'element',
492
+ autofocus: 'boolean'
493
+ };
494
+ const NAME$1 = 'focustrap';
495
+ const DATA_KEY$1 = 'bs.focustrap';
496
+ const EVENT_KEY$1 = `.${DATA_KEY$1}`;
497
+ const EVENT_FOCUSIN = `focusin${EVENT_KEY$1}`;
498
+ const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$1}`;
499
+ const TAB_KEY = 'Tab';
500
+ const TAB_NAV_FORWARD = 'forward';
501
+ const TAB_NAV_BACKWARD = 'backward';
502
+
503
+ class FocusTrap {
504
+ constructor(config) {
505
+ this._config = this._getConfig(config);
506
+ this._isActive = false;
507
+ this._lastTabNavDirection = null;
508
+ }
228
509
 
229
- const _resetElementAttributes = (selector, styleProp) => {
230
- SelectorEngine__default['default'].find(selector).forEach(element => {
231
- const value = Manipulator__default['default'].getDataAttribute(element, styleProp);
510
+ activate() {
511
+ const {
512
+ trapElement,
513
+ autofocus
514
+ } = this._config;
232
515
 
233
- if (typeof value === 'undefined' && element === document.body) {
234
- element.style.removeProperty(styleProp);
516
+ if (this._isActive) {
517
+ return;
518
+ }
519
+
520
+ if (autofocus) {
521
+ trapElement.focus();
522
+ }
523
+
524
+ EventHandler__default['default'].off(document, EVENT_KEY$1); // guard against infinite focus loop
525
+
526
+ EventHandler__default['default'].on(document, EVENT_FOCUSIN, event => this._handleFocusin(event));
527
+ EventHandler__default['default'].on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event));
528
+ this._isActive = true;
529
+ }
530
+
531
+ deactivate() {
532
+ if (!this._isActive) {
533
+ return;
534
+ }
535
+
536
+ this._isActive = false;
537
+ EventHandler__default['default'].off(document, EVENT_KEY$1);
538
+ } // Private
539
+
540
+
541
+ _handleFocusin(event) {
542
+ const {
543
+ target
544
+ } = event;
545
+ const {
546
+ trapElement
547
+ } = this._config;
548
+
549
+ if (target === document || target === trapElement || trapElement.contains(target)) {
550
+ return;
551
+ }
552
+
553
+ const elements = SelectorEngine__default['default'].focusableChildren(trapElement);
554
+
555
+ if (elements.length === 0) {
556
+ trapElement.focus();
557
+ } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) {
558
+ elements[elements.length - 1].focus();
235
559
  } else {
236
- Manipulator__default['default'].removeDataAttribute(element, styleProp);
237
- element.style[styleProp] = value;
560
+ elements[0].focus();
561
+ }
562
+ }
563
+
564
+ _handleKeydown(event) {
565
+ if (event.key !== TAB_KEY) {
566
+ return;
238
567
  }
568
+
569
+ this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD;
570
+ }
571
+
572
+ _getConfig(config) {
573
+ config = { ...Default$1,
574
+ ...(typeof config === 'object' ? config : {})
575
+ };
576
+ typeCheckConfig(NAME$1, config, DefaultType$1);
577
+ return config;
578
+ }
579
+
580
+ }
581
+
582
+ /**
583
+ * --------------------------------------------------------------------------
584
+ * Bootstrap (v5.1.0): util/component-functions.js
585
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
586
+ * --------------------------------------------------------------------------
587
+ */
588
+
589
+ const enableDismissTrigger = (component, method = 'hide') => {
590
+ const clickEvent = `click.dismiss${component.EVENT_KEY}`;
591
+ const name = component.NAME;
592
+ EventHandler__default['default'].on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
593
+ if (['A', 'AREA'].includes(this.tagName)) {
594
+ event.preventDefault();
595
+ }
596
+
597
+ if (isDisabled(this)) {
598
+ return;
599
+ }
600
+
601
+ const target = getElementFromSelector(this) || this.closest(`.${name}`);
602
+ const instance = component.getOrCreateInstance(target); // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
603
+
604
+ instance[method]();
239
605
  });
240
606
  };
241
607
 
242
608
  /**
243
609
  * --------------------------------------------------------------------------
244
- * Bootstrap (v5.0.0-beta3): offcanvas.js
610
+ * Bootstrap (v5.1.0): offcanvas.js
245
611
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
246
612
  * --------------------------------------------------------------------------
247
613
  */
@@ -267,19 +633,15 @@
267
633
  keyboard: 'boolean',
268
634
  scroll: 'boolean'
269
635
  };
270
- const CLASS_NAME_BACKDROP_BODY = 'offcanvas-backdrop';
271
636
  const CLASS_NAME_SHOW = 'show';
272
- const CLASS_NAME_TOGGLING = 'offcanvas-toggling';
637
+ const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
273
638
  const OPEN_SELECTOR = '.offcanvas.show';
274
- const ACTIVE_SELECTOR = `${OPEN_SELECTOR}, .${CLASS_NAME_TOGGLING}`;
275
639
  const EVENT_SHOW = `show${EVENT_KEY}`;
276
640
  const EVENT_SHOWN = `shown${EVENT_KEY}`;
277
641
  const EVENT_HIDE = `hide${EVENT_KEY}`;
278
642
  const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
279
- const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
280
643
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
281
- const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
282
- const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]';
644
+ const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
283
645
  const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]';
284
646
  /**
285
647
  * ------------------------------------------------------------------------
@@ -292,17 +654,19 @@
292
654
  super(element);
293
655
  this._config = this._getConfig(config);
294
656
  this._isShown = false;
657
+ this._backdrop = this._initializeBackDrop();
658
+ this._focustrap = this._initializeFocusTrap();
295
659
 
296
660
  this._addEventListeners();
297
661
  } // Getters
298
662
 
299
663
 
300
- static get Default() {
301
- return Default;
664
+ static get NAME() {
665
+ return NAME;
302
666
  }
303
667
 
304
- static get DATA_KEY() {
305
- return DATA_KEY;
668
+ static get Default() {
669
+ return Default;
306
670
  } // Public
307
671
 
308
672
 
@@ -326,16 +690,12 @@
326
690
  this._isShown = true;
327
691
  this._element.style.visibility = 'visible';
328
692
 
329
- if (this._config.backdrop) {
330
- document.body.classList.add(CLASS_NAME_BACKDROP_BODY);
331
- }
693
+ this._backdrop.show();
332
694
 
333
695
  if (!this._config.scroll) {
334
- hide();
696
+ new ScrollBarHelper().hide();
335
697
  }
336
698
 
337
- this._element.classList.add(CLASS_NAME_TOGGLING);
338
-
339
699
  this._element.removeAttribute('aria-hidden');
340
700
 
341
701
  this._element.setAttribute('aria-modal', true);
@@ -345,16 +705,16 @@
345
705
  this._element.classList.add(CLASS_NAME_SHOW);
346
706
 
347
707
  const completeCallBack = () => {
348
- this._element.classList.remove(CLASS_NAME_TOGGLING);
708
+ if (!this._config.scroll) {
709
+ this._focustrap.activate();
710
+ }
349
711
 
350
712
  EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, {
351
713
  relatedTarget
352
714
  });
353
-
354
- this._enforceFocusOnElement(this._element);
355
715
  };
356
716
 
357
- setTimeout(completeCallBack, getTransitionDurationFromElement(this._element));
717
+ this._queueCallback(completeCallBack, this._element, true);
358
718
  }
359
719
 
360
720
  hide() {
@@ -368,9 +728,7 @@
368
728
  return;
369
729
  }
370
730
 
371
- this._element.classList.add(CLASS_NAME_TOGGLING);
372
-
373
- EventHandler__default['default'].off(document, EVENT_FOCUSIN);
731
+ this._focustrap.deactivate();
374
732
 
375
733
  this._element.blur();
376
734
 
@@ -378,6 +736,8 @@
378
736
 
379
737
  this._element.classList.remove(CLASS_NAME_SHOW);
380
738
 
739
+ this._backdrop.hide();
740
+
381
741
  const completeCallback = () => {
382
742
  this._element.setAttribute('aria-hidden', true);
383
743
 
@@ -387,20 +747,22 @@
387
747
 
388
748
  this._element.style.visibility = 'hidden';
389
749
 
390
- if (this._config.backdrop) {
391
- document.body.classList.remove(CLASS_NAME_BACKDROP_BODY);
392
- }
393
-
394
750
  if (!this._config.scroll) {
395
- reset();
751
+ new ScrollBarHelper().reset();
396
752
  }
397
753
 
398
754
  EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN);
399
-
400
- this._element.classList.remove(CLASS_NAME_TOGGLING);
401
755
  };
402
756
 
403
- setTimeout(completeCallback, getTransitionDurationFromElement(this._element));
757
+ this._queueCallback(completeCallback, this._element, true);
758
+ }
759
+
760
+ dispose() {
761
+ this._backdrop.dispose();
762
+
763
+ this._focustrap.deactivate();
764
+
765
+ super.dispose();
404
766
  } // Private
405
767
 
406
768
 
@@ -413,37 +775,34 @@
413
775
  return config;
414
776
  }
415
777
 
416
- _enforceFocusOnElement(element) {
417
- EventHandler__default['default'].off(document, EVENT_FOCUSIN); // guard against infinite focus loop
778
+ _initializeBackDrop() {
779
+ return new Backdrop({
780
+ className: CLASS_NAME_BACKDROP,
781
+ isVisible: this._config.backdrop,
782
+ isAnimated: true,
783
+ rootElement: this._element.parentNode,
784
+ clickCallback: () => this.hide()
785
+ });
786
+ }
418
787
 
419
- EventHandler__default['default'].on(document, EVENT_FOCUSIN, event => {
420
- if (document !== event.target && element !== event.target && !element.contains(event.target)) {
421
- element.focus();
422
- }
788
+ _initializeFocusTrap() {
789
+ return new FocusTrap({
790
+ trapElement: this._element
423
791
  });
424
- element.focus();
425
792
  }
426
793
 
427
794
  _addEventListeners() {
428
- EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
429
- EventHandler__default['default'].on(document, 'keydown', event => {
795
+ EventHandler__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, event => {
430
796
  if (this._config.keyboard && event.key === ESCAPE_KEY) {
431
797
  this.hide();
432
798
  }
433
799
  });
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
800
  } // Static
442
801
 
443
802
 
444
803
  static jQueryInterface(config) {
445
804
  return this.each(function () {
446
- const data = Data__default['default'].get(this, DATA_KEY) || new Offcanvas(this, typeof config === 'object' ? config : {});
805
+ const data = Offcanvas.getOrCreateInstance(this, config);
447
806
 
448
807
  if (typeof config !== 'string') {
449
808
  return;
@@ -483,25 +842,24 @@
483
842
  }
484
843
  }); // avoid conflict when clicking a toggler of an offcanvas, while another is open
485
844
 
486
- const allReadyOpen = SelectorEngine__default['default'].findOne(ACTIVE_SELECTOR);
845
+ const allReadyOpen = SelectorEngine__default['default'].findOne(OPEN_SELECTOR);
487
846
 
488
847
  if (allReadyOpen && allReadyOpen !== target) {
489
- return;
848
+ Offcanvas.getInstance(allReadyOpen).hide();
490
849
  }
491
850
 
492
- const data = Data__default['default'].get(target, DATA_KEY) || new Offcanvas(target);
851
+ const data = Offcanvas.getOrCreateInstance(target);
493
852
  data.toggle(this);
494
853
  });
495
- EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, () => {
496
- SelectorEngine__default['default'].find(OPEN_SELECTOR).forEach(el => (Data__default['default'].get(el, DATA_KEY) || new Offcanvas(el)).show());
497
- });
854
+ EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, () => SelectorEngine__default['default'].find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show()));
855
+ enableDismissTrigger(Offcanvas);
498
856
  /**
499
857
  * ------------------------------------------------------------------------
500
858
  * jQuery
501
859
  * ------------------------------------------------------------------------
502
860
  */
503
861
 
504
- defineJQueryPlugin(NAME, Offcanvas);
862
+ defineJQueryPlugin(Offcanvas);
505
863
 
506
864
  return Offcanvas;
507
865