bootstrap 5.0.1 → 5.1.2

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 +89 -58
  4. data/assets/javascripts/bootstrap/base-component.js +53 -39
  5. data/assets/javascripts/bootstrap/button.js +31 -25
  6. data/assets/javascripts/bootstrap/carousel.js +126 -89
  7. data/assets/javascripts/bootstrap/collapse.js +125 -133
  8. data/assets/javascripts/bootstrap/dom/data.js +5 -5
  9. data/assets/javascripts/bootstrap/dom/event-handler.js +11 -5
  10. data/assets/javascripts/bootstrap/dom/manipulator.js +6 -6
  11. data/assets/javascripts/bootstrap/dom/selector-engine.js +49 -7
  12. data/assets/javascripts/bootstrap/dropdown.js +147 -140
  13. data/assets/javascripts/bootstrap/modal.js +397 -180
  14. data/assets/javascripts/bootstrap/offcanvas.js +333 -138
  15. data/assets/javascripts/bootstrap/popover.js +36 -54
  16. data/assets/javascripts/bootstrap/scrollspy.js +58 -68
  17. data/assets/javascripts/bootstrap/tab.js +53 -26
  18. data/assets/javascripts/bootstrap/toast.js +138 -41
  19. data/assets/javascripts/bootstrap/tooltip.js +137 -120
  20. data/assets/javascripts/bootstrap-sprockets.js +8 -8
  21. data/assets/javascripts/bootstrap.js +937 -886
  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/_buttons.scss +1 -0
  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 +4 -4
  30. data/assets/stylesheets/bootstrap/_functions.scss +100 -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/_mixins.scss +1 -0
  35. data/assets/stylesheets/bootstrap/_modal.scss +5 -15
  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 +9 -5
  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 +206 -29
  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 +1 -1
  52. data/assets/stylesheets/bootstrap/forms/_form-range.scss +1 -1
  53. data/assets/stylesheets/bootstrap/forms/_form-select.scss +5 -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/_grid.scss +35 -9
  59. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +27 -6
  60. data/assets/stylesheets/bootstrap/mixins/_visually-hidden.scss +1 -1
  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,22 +1,27 @@
1
1
  /*!
2
- * Bootstrap offcanvas.js v5.0.1 (https://getbootstrap.com/)
2
+ * Bootstrap offcanvas.js v5.1.2 (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
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
+ const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
13
 
14
- var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
15
- var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
16
- var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
17
- var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
18
- var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
14
+ const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
15
+ const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
16
+ const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
17
+ const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
19
18
 
19
+ /**
20
+ * --------------------------------------------------------------------------
21
+ * Bootstrap (v5.1.2): util/index.js
22
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
23
+ * --------------------------------------------------------------------------
24
+ */
20
25
  const MILLISECONDS_MULTIPLIER = 1000;
21
26
  const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
22
27
 
@@ -96,22 +101,17 @@
96
101
  return typeof obj.nodeType !== 'undefined';
97
102
  };
98
103
 
99
- const emulateTransitionEnd = (element, duration) => {
100
- let called = false;
101
- const durationPadding = 5;
102
- const emulatedDuration = duration + durationPadding;
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
+ }
103
109
 
104
- function listener() {
105
- called = true;
106
- element.removeEventListener(TRANSITION_END, listener);
110
+ if (typeof obj === 'string' && obj.length > 0) {
111
+ return document.querySelector(obj);
107
112
  }
108
113
 
109
- element.addEventListener(TRANSITION_END, listener);
110
- setTimeout(() => {
111
- if (!called) {
112
- triggerTransitionEnd(element);
113
- }
114
- }, emulatedDuration);
114
+ return null;
115
115
  };
116
116
 
117
117
  const typeCheckConfig = (componentName, config, configTypes) => {
@@ -127,17 +127,11 @@
127
127
  };
128
128
 
129
129
  const isVisible = element => {
130
- if (!element) {
130
+ if (!isElement(element) || element.getClientRects().length === 0) {
131
131
  return false;
132
132
  }
133
133
 
134
- if (element.style && element.parentNode && element.parentNode.style) {
135
- const elementStyle = getComputedStyle(element);
136
- const parentNodeStyle = getComputedStyle(element.parentNode);
137
- return elementStyle.display !== 'none' && parentNodeStyle.display !== 'none' && elementStyle.visibility !== 'hidden';
138
- }
139
-
140
- return false;
134
+ return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
141
135
  };
142
136
 
143
137
  const isDisabled = element => {
@@ -155,8 +149,20 @@
155
149
 
156
150
  return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
157
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
+ */
158
160
 
159
- const reflow = element => element.offsetHeight;
161
+
162
+ const reflow = element => {
163
+ // eslint-disable-next-line no-unused-expressions
164
+ element.offsetHeight;
165
+ };
160
166
 
161
167
  const getjQuery = () => {
162
168
  const {
@@ -170,9 +176,18 @@
170
176
  return null;
171
177
  };
172
178
 
179
+ const DOMContentLoadedCallbacks = [];
180
+
173
181
  const onDOMContentLoaded = callback => {
174
182
  if (document.readyState === 'loading') {
175
- 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);
176
191
  } else {
177
192
  callback();
178
193
  }
@@ -203,105 +218,166 @@
203
218
  }
204
219
  };
205
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
+
206
251
  /**
207
252
  * --------------------------------------------------------------------------
208
- * Bootstrap (v5.0.1): util/scrollBar.js
253
+ * Bootstrap (v5.1.2): util/scrollBar.js
209
254
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
210
255
  * --------------------------------------------------------------------------
211
256
  */
212
257
  const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
213
258
  const SELECTOR_STICKY_CONTENT = '.sticky-top';
214
259
 
215
- const getWidth = () => {
216
- // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
217
- const documentWidth = document.documentElement.clientWidth;
218
- return Math.abs(window.innerWidth - documentWidth);
219
- };
260
+ class ScrollBarHelper {
261
+ constructor() {
262
+ this._element = document.body;
263
+ }
220
264
 
221
- const hide = (width = getWidth()) => {
222
- _disableOverFlow(); // give padding to element to balances the hidden scrollbar width
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
+ }
223
270
 
271
+ hide() {
272
+ const width = this.getWidth();
224
273
 
225
- _setElementAttributes('body', 'paddingRight', calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements, to keep shown fullwidth
274
+ this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width
226
275
 
227
276
 
228
- _setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', 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
229
278
 
230
- _setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);
231
- };
232
279
 
233
- const _disableOverFlow = () => {
234
- const actualValue = document.body.style.overflow;
280
+ this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width);
235
281
 
236
- if (actualValue) {
237
- Manipulator__default['default'].setDataAttribute(document.body, 'overflow', actualValue);
282
+ this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);
238
283
  }
239
284
 
240
- document.body.style.overflow = 'hidden';
241
- };
285
+ _disableOverFlow() {
286
+ this._saveInitialAttribute(this._element, 'overflow');
242
287
 
243
- const _setElementAttributes = (selector, styleProp, callback) => {
244
- const scrollbarWidth = getWidth();
245
- SelectorEngine__default['default'].find(selector).forEach(element => {
246
- if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) {
247
- return;
248
- }
288
+ this._element.style.overflow = 'hidden';
289
+ }
249
290
 
250
- const actualValue = element.style[styleProp];
251
- const calculatedValue = window.getComputedStyle(element)[styleProp];
252
- Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue);
253
- element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
254
- });
255
- };
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
+ }
256
298
 
257
- const reset = () => {
258
- _resetElementAttributes('body', 'overflow');
299
+ this._saveInitialAttribute(element, styleProp);
259
300
 
260
- _resetElementAttributes('body', 'paddingRight');
301
+ const calculatedValue = window.getComputedStyle(element)[styleProp];
302
+ element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
303
+ };
261
304
 
262
- _resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
305
+ this._applyManipulationCallback(selector, manipulationCallBack);
306
+ }
263
307
 
264
- _resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
265
- };
308
+ reset() {
309
+ this._resetElementAttributes(this._element, 'overflow');
310
+
311
+ this._resetElementAttributes(this._element, 'paddingRight');
266
312
 
267
- const _resetElementAttributes = (selector, styleProp) => {
268
- SelectorEngine__default['default'].find(selector).forEach(element => {
269
- const value = Manipulator__default['default'].getDataAttribute(element, styleProp);
313
+ this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
270
314
 
271
- if (typeof value === 'undefined') {
272
- element.style.removeProperty(styleProp);
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);
273
344
  } else {
274
- Manipulator__default['default'].removeDataAttribute(element, styleProp);
275
- element.style[styleProp] = value;
345
+ SelectorEngine__default.default.find(selector, this._element).forEach(callBack);
276
346
  }
277
- });
278
- };
347
+ }
348
+
349
+ isOverflowing() {
350
+ return this.getWidth() > 0;
351
+ }
352
+
353
+ }
279
354
 
280
355
  /**
281
356
  * --------------------------------------------------------------------------
282
- * Bootstrap (v5.0.1): util/backdrop.js
283
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
357
+ * Bootstrap (v5.1.2): util/backdrop.js
358
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
284
359
  * --------------------------------------------------------------------------
285
360
  */
286
- const Default$1 = {
361
+ const Default$2 = {
362
+ className: 'modal-backdrop',
287
363
  isVisible: true,
288
364
  // if false, we use the backdrop helper without adding any element to the dom
289
365
  isAnimated: false,
290
- rootElement: document.body,
366
+ rootElement: 'body',
291
367
  // give the choice to place backdrop under different elements
292
368
  clickCallback: null
293
369
  };
294
- const DefaultType$1 = {
370
+ const DefaultType$2 = {
371
+ className: 'string',
295
372
  isVisible: 'boolean',
296
373
  isAnimated: 'boolean',
297
- rootElement: 'element',
374
+ rootElement: '(element|string)',
298
375
  clickCallback: '(function|null)'
299
376
  };
300
- const NAME$1 = 'backdrop';
301
- const CLASS_NAME_BACKDROP = 'modal-backdrop';
377
+ const NAME$2 = 'backdrop';
302
378
  const CLASS_NAME_FADE = 'fade';
303
379
  const CLASS_NAME_SHOW$1 = 'show';
304
- const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$1}`;
380
+ const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$2}`;
305
381
 
306
382
  class Backdrop {
307
383
  constructor(config) {
@@ -347,7 +423,7 @@
347
423
  _getElement() {
348
424
  if (!this._element) {
349
425
  const backdrop = document.createElement('div');
350
- backdrop.className = CLASS_NAME_BACKDROP;
426
+ backdrop.className = this._config.className;
351
427
 
352
428
  if (this._config.isAnimated) {
353
429
  backdrop.classList.add(CLASS_NAME_FADE);
@@ -360,11 +436,12 @@
360
436
  }
361
437
 
362
438
  _getConfig(config) {
363
- config = { ...Default$1,
439
+ config = { ...Default$2,
364
440
  ...(typeof config === 'object' ? config : {})
365
- };
366
- config.rootElement = config.rootElement || document.body;
367
- typeCheckConfig(NAME$1, config, DefaultType$1);
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);
368
445
  return config;
369
446
  }
370
447
 
@@ -373,9 +450,9 @@
373
450
  return;
374
451
  }
375
452
 
376
- this._config.rootElement.appendChild(this._getElement());
453
+ this._config.rootElement.append(this._getElement());
377
454
 
378
- EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => {
455
+ EventHandler__default.default.on(this._getElement(), EVENT_MOUSEDOWN, () => {
379
456
  execute(this._config.clickCallback);
380
457
  });
381
458
  this._isAppended = true;
@@ -386,30 +463,152 @@
386
463
  return;
387
464
  }
388
465
 
389
- EventHandler__default['default'].off(this._element, EVENT_MOUSEDOWN);
466
+ EventHandler__default.default.off(this._element, EVENT_MOUSEDOWN);
390
467
 
391
- this._getElement().parentNode.removeChild(this._element);
468
+ this._element.remove();
392
469
 
393
470
  this._isAppended = false;
394
471
  }
395
472
 
396
473
  _emulateAnimation(callback) {
397
- if (!this._config.isAnimated) {
398
- execute(callback);
474
+ executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
475
+ }
476
+
477
+ }
478
+
479
+ /**
480
+ * --------------------------------------------------------------------------
481
+ * Bootstrap (v5.1.2): util/focustrap.js
482
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
483
+ * --------------------------------------------------------------------------
484
+ */
485
+ const Default$1 = {
486
+ trapElement: null,
487
+ // The element to trap focus inside of
488
+ autofocus: true
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
+ }
509
+
510
+ activate() {
511
+ const {
512
+ trapElement,
513
+ autofocus
514
+ } = this._config;
515
+
516
+ if (this._isActive) {
399
517
  return;
400
518
  }
401
519
 
402
- const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement());
403
- EventHandler__default['default'].one(this._getElement(), 'transitionend', () => execute(callback));
404
- emulateTransitionEnd(this._getElement(), backdropTransitionDuration);
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();
559
+ } else {
560
+ elements[0].focus();
561
+ }
562
+ }
563
+
564
+ _handleKeydown(event) {
565
+ if (event.key !== TAB_KEY) {
566
+ return;
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;
405
578
  }
406
579
 
407
580
  }
408
581
 
409
582
  /**
410
583
  * --------------------------------------------------------------------------
411
- * Bootstrap (v5.0.1): offcanvas.js
412
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
584
+ * Bootstrap (v5.1.2): 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]();
605
+ });
606
+ };
607
+
608
+ /**
609
+ * --------------------------------------------------------------------------
610
+ * Bootstrap (v5.1.2): offcanvas.js
611
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
413
612
  * --------------------------------------------------------------------------
414
613
  */
415
614
  /**
@@ -435,16 +634,14 @@
435
634
  scroll: 'boolean'
436
635
  };
437
636
  const CLASS_NAME_SHOW = 'show';
637
+ const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
438
638
  const OPEN_SELECTOR = '.offcanvas.show';
439
639
  const EVENT_SHOW = `show${EVENT_KEY}`;
440
640
  const EVENT_SHOWN = `shown${EVENT_KEY}`;
441
641
  const EVENT_HIDE = `hide${EVENT_KEY}`;
442
642
  const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
443
- const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
444
643
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
445
- const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
446
644
  const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
447
- const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]';
448
645
  const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]';
449
646
  /**
450
647
  * ------------------------------------------------------------------------
@@ -452,12 +649,13 @@
452
649
  * ------------------------------------------------------------------------
453
650
  */
454
651
 
455
- class Offcanvas extends BaseComponent__default['default'] {
652
+ class Offcanvas extends BaseComponent__default.default {
456
653
  constructor(element, config) {
457
654
  super(element);
458
655
  this._config = this._getConfig(config);
459
656
  this._isShown = false;
460
657
  this._backdrop = this._initializeBackDrop();
658
+ this._focustrap = this._initializeFocusTrap();
461
659
 
462
660
  this._addEventListeners();
463
661
  } // Getters
@@ -481,7 +679,7 @@
481
679
  return;
482
680
  }
483
681
 
484
- const showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW, {
682
+ const showEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW, {
485
683
  relatedTarget
486
684
  });
487
685
 
@@ -495,9 +693,7 @@
495
693
  this._backdrop.show();
496
694
 
497
695
  if (!this._config.scroll) {
498
- hide();
499
-
500
- this._enforceFocusOnElement(this._element);
696
+ new ScrollBarHelper().hide();
501
697
  }
502
698
 
503
699
  this._element.removeAttribute('aria-hidden');
@@ -509,7 +705,11 @@
509
705
  this._element.classList.add(CLASS_NAME_SHOW);
510
706
 
511
707
  const completeCallBack = () => {
512
- EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, {
708
+ if (!this._config.scroll) {
709
+ this._focustrap.activate();
710
+ }
711
+
712
+ EventHandler__default.default.trigger(this._element, EVENT_SHOWN, {
513
713
  relatedTarget
514
714
  });
515
715
  };
@@ -522,13 +722,13 @@
522
722
  return;
523
723
  }
524
724
 
525
- const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE);
725
+ const hideEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE);
526
726
 
527
727
  if (hideEvent.defaultPrevented) {
528
728
  return;
529
729
  }
530
730
 
531
- EventHandler__default['default'].off(document, EVENT_FOCUSIN);
731
+ this._focustrap.deactivate();
532
732
 
533
733
  this._element.blur();
534
734
 
@@ -548,10 +748,10 @@
548
748
  this._element.style.visibility = 'hidden';
549
749
 
550
750
  if (!this._config.scroll) {
551
- reset();
751
+ new ScrollBarHelper().reset();
552
752
  }
553
753
 
554
- EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN);
754
+ EventHandler__default.default.trigger(this._element, EVENT_HIDDEN);
555
755
  };
556
756
 
557
757
  this._queueCallback(completeCallback, this._element, true);
@@ -560,14 +760,15 @@
560
760
  dispose() {
561
761
  this._backdrop.dispose();
562
762
 
763
+ this._focustrap.deactivate();
764
+
563
765
  super.dispose();
564
- EventHandler__default['default'].off(document, EVENT_FOCUSIN);
565
766
  } // Private
566
767
 
567
768
 
568
769
  _getConfig(config) {
569
770
  config = { ...Default,
570
- ...Manipulator__default['default'].getDataAttributes(this._element),
771
+ ...Manipulator__default.default.getDataAttributes(this._element),
571
772
  ...(typeof config === 'object' ? config : {})
572
773
  };
573
774
  typeCheckConfig(NAME, config, DefaultType);
@@ -576,6 +777,7 @@
576
777
 
577
778
  _initializeBackDrop() {
578
779
  return new Backdrop({
780
+ className: CLASS_NAME_BACKDROP,
579
781
  isVisible: this._config.backdrop,
580
782
  isAnimated: true,
581
783
  rootElement: this._element.parentNode,
@@ -583,20 +785,14 @@
583
785
  });
584
786
  }
585
787
 
586
- _enforceFocusOnElement(element) {
587
- EventHandler__default['default'].off(document, EVENT_FOCUSIN); // guard against infinite focus loop
588
-
589
- EventHandler__default['default'].on(document, EVENT_FOCUSIN, event => {
590
- if (document !== event.target && element !== event.target && !element.contains(event.target)) {
591
- element.focus();
592
- }
788
+ _initializeFocusTrap() {
789
+ return new FocusTrap({
790
+ trapElement: this._element
593
791
  });
594
- element.focus();
595
792
  }
596
793
 
597
794
  _addEventListeners() {
598
- EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide());
599
- EventHandler__default['default'].on(this._element, EVENT_KEYDOWN_DISMISS, event => {
795
+ EventHandler__default.default.on(this._element, EVENT_KEYDOWN_DISMISS, event => {
600
796
  if (this._config.keyboard && event.key === ESCAPE_KEY) {
601
797
  this.hide();
602
798
  }
@@ -606,7 +802,7 @@
606
802
 
607
803
  static jQueryInterface(config) {
608
804
  return this.each(function () {
609
- const data = Data__default['default'].get(this, DATA_KEY) || new Offcanvas(this, typeof config === 'object' ? config : {});
805
+ const data = Offcanvas.getOrCreateInstance(this, config);
610
806
 
611
807
  if (typeof config !== 'string') {
612
808
  return;
@@ -628,7 +824,7 @@
628
824
  */
629
825
 
630
826
 
631
- EventHandler__default['default'].on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
827
+ EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
632
828
  const target = getElementFromSelector(this);
633
829
 
634
830
  if (['A', 'AREA'].includes(this.tagName)) {
@@ -639,25 +835,24 @@
639
835
  return;
640
836
  }
641
837
 
642
- EventHandler__default['default'].one(target, EVENT_HIDDEN, () => {
838
+ EventHandler__default.default.one(target, EVENT_HIDDEN, () => {
643
839
  // focus on trigger when it is closed
644
840
  if (isVisible(this)) {
645
841
  this.focus();
646
842
  }
647
843
  }); // avoid conflict when clicking a toggler of an offcanvas, while another is open
648
844
 
649
- const allReadyOpen = SelectorEngine__default['default'].findOne(OPEN_SELECTOR);
845
+ const allReadyOpen = SelectorEngine__default.default.findOne(OPEN_SELECTOR);
650
846
 
651
847
  if (allReadyOpen && allReadyOpen !== target) {
652
848
  Offcanvas.getInstance(allReadyOpen).hide();
653
849
  }
654
850
 
655
- const data = Data__default['default'].get(target, DATA_KEY) || new Offcanvas(target);
851
+ const data = Offcanvas.getOrCreateInstance(target);
656
852
  data.toggle(this);
657
853
  });
658
- EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, () => {
659
- SelectorEngine__default['default'].find(OPEN_SELECTOR).forEach(el => (Data__default['default'].get(el, DATA_KEY) || new Offcanvas(el)).show());
660
- });
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);
661
856
  /**
662
857
  * ------------------------------------------------------------------------
663
858
  * jQuery
@@ -668,4 +863,4 @@
668
863
 
669
864
  return Offcanvas;
670
865
 
671
- })));
866
+ }));