bootstrap 5.0.0 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
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,25 +1,24 @@
1
1
  /*!
2
- * Bootstrap offcanvas.js v5.0.0 (https://getbootstrap.com/)
2
+ * Bootstrap offcanvas.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/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): util/index.js
21
+ * Bootstrap (v5.1.1): util/index.js
23
22
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
24
23
  * --------------------------------------------------------------------------
25
24
  */
@@ -90,24 +89,29 @@
90
89
  element.dispatchEvent(new Event(TRANSITION_END));
91
90
  };
92
91
 
93
- const isElement = obj => (obj[0] || obj).nodeType;
92
+ const isElement = obj => {
93
+ if (!obj || typeof obj !== 'object') {
94
+ return false;
95
+ }
94
96
 
95
- const emulateTransitionEnd = (element, duration) => {
96
- let called = false;
97
- const durationPadding = 5;
98
- const emulatedDuration = duration + durationPadding;
97
+ if (typeof obj.jquery !== 'undefined') {
98
+ obj = obj[0];
99
+ }
99
100
 
100
- function listener() {
101
- called = true;
102
- element.removeEventListener(TRANSITION_END, listener);
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;
103
108
  }
104
109
 
105
- element.addEventListener(TRANSITION_END, listener);
106
- setTimeout(() => {
107
- if (!called) {
108
- triggerTransitionEnd(element);
109
- }
110
- }, emulatedDuration);
110
+ if (typeof obj === 'string' && obj.length > 0) {
111
+ return document.querySelector(obj);
112
+ }
113
+
114
+ return null;
111
115
  };
112
116
 
113
117
  const typeCheckConfig = (componentName, config, configTypes) => {
@@ -123,17 +127,11 @@
123
127
  };
124
128
 
125
129
  const isVisible = element => {
126
- if (!element) {
130
+ if (!isElement(element) || element.getClientRects().length === 0) {
127
131
  return false;
128
132
  }
129
133
 
130
- if (element.style && element.parentNode && element.parentNode.style) {
131
- const elementStyle = getComputedStyle(element);
132
- const parentNodeStyle = getComputedStyle(element.parentNode);
133
- return elementStyle.display !== 'none' && parentNodeStyle.display !== 'none' && elementStyle.visibility !== 'hidden';
134
- }
135
-
136
- return false;
134
+ return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
137
135
  };
138
136
 
139
137
  const isDisabled = element => {
@@ -151,8 +149,20 @@
151
149
 
152
150
  return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
153
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
+
154
161
 
155
- const reflow = element => element.offsetHeight;
162
+ const reflow = element => {
163
+ // eslint-disable-next-line no-unused-expressions
164
+ element.offsetHeight;
165
+ };
156
166
 
157
167
  const getjQuery = () => {
158
168
  const {
@@ -166,20 +176,30 @@
166
176
  return null;
167
177
  };
168
178
 
179
+ const DOMContentLoadedCallbacks = [];
180
+
169
181
  const onDOMContentLoaded = callback => {
170
182
  if (document.readyState === 'loading') {
171
- 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);
172
191
  } else {
173
192
  callback();
174
193
  }
175
194
  };
176
195
 
177
- const defineJQueryPlugin = (name, plugin) => {
196
+ const defineJQueryPlugin = plugin => {
178
197
  onDOMContentLoaded(() => {
179
198
  const $ = getjQuery();
180
199
  /* istanbul ignore if */
181
200
 
182
201
  if ($) {
202
+ const name = plugin.NAME;
183
203
  const JQUERY_NO_CONFLICT = $.fn[name];
184
204
  $.fn[name] = plugin.jQueryInterface;
185
205
  $.fn[name].Constructor = plugin;
@@ -198,105 +218,166 @@
198
218
  }
199
219
  };
200
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
+
201
251
  /**
202
252
  * --------------------------------------------------------------------------
203
- * Bootstrap (v5.0.0): util/scrollBar.js
253
+ * Bootstrap (v5.1.1): util/scrollBar.js
204
254
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
205
255
  * --------------------------------------------------------------------------
206
256
  */
207
257
  const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
208
258
  const SELECTOR_STICKY_CONTENT = '.sticky-top';
209
259
 
210
- const getWidth = () => {
211
- // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
212
- const documentWidth = document.documentElement.clientWidth;
213
- return Math.abs(window.innerWidth - documentWidth);
214
- };
260
+ class ScrollBarHelper {
261
+ constructor() {
262
+ this._element = document.body;
263
+ }
215
264
 
216
- const hide = (width = getWidth()) => {
217
- _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
+ }
218
270
 
271
+ hide() {
272
+ const width = this.getWidth();
219
273
 
220
- _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
221
275
 
222
276
 
223
- _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
224
278
 
225
- _setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);
226
- };
227
279
 
228
- const _disableOverFlow = () => {
229
- const actualValue = document.body.style.overflow;
280
+ this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width);
230
281
 
231
- if (actualValue) {
232
- Manipulator__default['default'].setDataAttribute(document.body, 'overflow', actualValue);
282
+ this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width);
233
283
  }
234
284
 
235
- document.body.style.overflow = 'hidden';
236
- };
285
+ _disableOverFlow() {
286
+ this._saveInitialAttribute(this._element, 'overflow');
237
287
 
238
- const _setElementAttributes = (selector, styleProp, callback) => {
239
- const scrollbarWidth = getWidth();
240
- SelectorEngine__default['default'].find(selector).forEach(element => {
241
- if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) {
242
- return;
243
- }
288
+ this._element.style.overflow = 'hidden';
289
+ }
244
290
 
245
- const actualValue = element.style[styleProp];
246
- const calculatedValue = window.getComputedStyle(element)[styleProp];
247
- Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue);
248
- element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
249
- });
250
- };
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
+ }
251
298
 
252
- const reset = () => {
253
- _resetElementAttributes('body', 'overflow');
299
+ this._saveInitialAttribute(element, styleProp);
254
300
 
255
- _resetElementAttributes('body', 'paddingRight');
301
+ const calculatedValue = window.getComputedStyle(element)[styleProp];
302
+ element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`;
303
+ };
256
304
 
257
- _resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight');
305
+ this._applyManipulationCallback(selector, manipulationCallBack);
306
+ }
258
307
 
259
- _resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight');
260
- };
308
+ reset() {
309
+ this._resetElementAttributes(this._element, 'overflow');
261
310
 
262
- const _resetElementAttributes = (selector, styleProp) => {
263
- SelectorEngine__default['default'].find(selector).forEach(element => {
264
- const value = Manipulator__default['default'].getDataAttribute(element, styleProp);
311
+ this._resetElementAttributes(this._element, 'paddingRight');
265
312
 
266
- if (typeof value === 'undefined') {
267
- element.style.removeProperty(styleProp);
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);
268
344
  } else {
269
- Manipulator__default['default'].removeDataAttribute(element, styleProp);
270
- element.style[styleProp] = value;
345
+ SelectorEngine__default['default'].find(selector, this._element).forEach(callBack);
271
346
  }
272
- });
273
- };
347
+ }
348
+
349
+ isOverflowing() {
350
+ return this.getWidth() > 0;
351
+ }
352
+
353
+ }
274
354
 
275
355
  /**
276
356
  * --------------------------------------------------------------------------
277
- * Bootstrap (v5.0.0): util/backdrop.js
357
+ * Bootstrap (v5.1.1): util/backdrop.js
278
358
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
279
359
  * --------------------------------------------------------------------------
280
360
  */
281
- const Default$1 = {
361
+ const Default$2 = {
362
+ className: 'modal-backdrop',
282
363
  isVisible: true,
283
364
  // if false, we use the backdrop helper without adding any element to the dom
284
365
  isAnimated: false,
285
- rootElement: document.body,
366
+ rootElement: 'body',
286
367
  // give the choice to place backdrop under different elements
287
368
  clickCallback: null
288
369
  };
289
- const DefaultType$1 = {
370
+ const DefaultType$2 = {
371
+ className: 'string',
290
372
  isVisible: 'boolean',
291
373
  isAnimated: 'boolean',
292
- rootElement: 'element',
374
+ rootElement: '(element|string)',
293
375
  clickCallback: '(function|null)'
294
376
  };
295
- const NAME$1 = 'backdrop';
296
- const CLASS_NAME_BACKDROP = 'modal-backdrop';
377
+ const NAME$2 = 'backdrop';
297
378
  const CLASS_NAME_FADE = 'fade';
298
379
  const CLASS_NAME_SHOW$1 = 'show';
299
- const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$1}`;
380
+ const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$2}`;
300
381
 
301
382
  class Backdrop {
302
383
  constructor(config) {
@@ -342,7 +423,7 @@
342
423
  _getElement() {
343
424
  if (!this._element) {
344
425
  const backdrop = document.createElement('div');
345
- backdrop.className = CLASS_NAME_BACKDROP;
426
+ backdrop.className = this._config.className;
346
427
 
347
428
  if (this._config.isAnimated) {
348
429
  backdrop.classList.add(CLASS_NAME_FADE);
@@ -355,10 +436,12 @@
355
436
  }
356
437
 
357
438
  _getConfig(config) {
358
- config = { ...Default$1,
439
+ config = { ...Default$2,
359
440
  ...(typeof config === 'object' ? config : {})
360
- };
361
- 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);
362
445
  return config;
363
446
  }
364
447
 
@@ -367,7 +450,7 @@
367
450
  return;
368
451
  }
369
452
 
370
- this._config.rootElement.appendChild(this._getElement());
453
+ this._config.rootElement.append(this._getElement());
371
454
 
372
455
  EventHandler__default['default'].on(this._getElement(), EVENT_MOUSEDOWN, () => {
373
456
  execute(this._config.clickCallback);
@@ -382,27 +465,149 @@
382
465
 
383
466
  EventHandler__default['default'].off(this._element, EVENT_MOUSEDOWN);
384
467
 
385
- this._getElement().parentNode.removeChild(this._element);
468
+ this._element.remove();
386
469
 
387
470
  this._isAppended = false;
388
471
  }
389
472
 
390
473
  _emulateAnimation(callback) {
391
- if (!this._config.isAnimated) {
392
- execute(callback);
474
+ executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
475
+ }
476
+
477
+ }
478
+
479
+ /**
480
+ * --------------------------------------------------------------------------
481
+ * Bootstrap (v5.1.1): 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
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) {
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();
559
+ } else {
560
+ elements[0].focus();
561
+ }
562
+ }
563
+
564
+ _handleKeydown(event) {
565
+ if (event.key !== TAB_KEY) {
393
566
  return;
394
567
  }
395
568
 
396
- const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement());
397
- EventHandler__default['default'].one(this._getElement(), 'transitionend', () => execute(callback));
398
- emulateTransitionEnd(this._getElement(), backdropTransitionDuration);
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;
399
578
  }
400
579
 
401
580
  }
402
581
 
403
582
  /**
404
583
  * --------------------------------------------------------------------------
405
- * Bootstrap (v5.0.0): offcanvas.js
584
+ * Bootstrap (v5.1.1): 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.1): offcanvas.js
406
611
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
407
612
  * --------------------------------------------------------------------------
408
613
  */
@@ -429,16 +634,14 @@
429
634
  scroll: 'boolean'
430
635
  };
431
636
  const CLASS_NAME_SHOW = 'show';
637
+ const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
432
638
  const OPEN_SELECTOR = '.offcanvas.show';
433
639
  const EVENT_SHOW = `show${EVENT_KEY}`;
434
640
  const EVENT_SHOWN = `shown${EVENT_KEY}`;
435
641
  const EVENT_HIDE = `hide${EVENT_KEY}`;
436
642
  const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
437
- const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
438
643
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
439
- const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`;
440
644
  const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`;
441
- const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]';
442
645
  const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]';
443
646
  /**
444
647
  * ------------------------------------------------------------------------
@@ -452,17 +655,18 @@
452
655
  this._config = this._getConfig(config);
453
656
  this._isShown = false;
454
657
  this._backdrop = this._initializeBackDrop();
658
+ this._focustrap = this._initializeFocusTrap();
455
659
 
456
660
  this._addEventListeners();
457
661
  } // Getters
458
662
 
459
663
 
460
- static get Default() {
461
- return Default;
664
+ static get NAME() {
665
+ return NAME;
462
666
  }
463
667
 
464
- static get DATA_KEY() {
465
- return DATA_KEY;
668
+ static get Default() {
669
+ return Default;
466
670
  } // Public
467
671
 
468
672
 
@@ -489,9 +693,7 @@
489
693
  this._backdrop.show();
490
694
 
491
695
  if (!this._config.scroll) {
492
- hide();
493
-
494
- this._enforceFocusOnElement(this._element);
696
+ new ScrollBarHelper().hide();
495
697
  }
496
698
 
497
699
  this._element.removeAttribute('aria-hidden');
@@ -503,14 +705,16 @@
503
705
  this._element.classList.add(CLASS_NAME_SHOW);
504
706
 
505
707
  const completeCallBack = () => {
708
+ if (!this._config.scroll) {
709
+ this._focustrap.activate();
710
+ }
711
+
506
712
  EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, {
507
713
  relatedTarget
508
714
  });
509
715
  };
510
716
 
511
- const transitionDuration = getTransitionDurationFromElement(this._element);
512
- EventHandler__default['default'].one(this._element, 'transitionend', completeCallBack);
513
- emulateTransitionEnd(this._element, transitionDuration);
717
+ this._queueCallback(completeCallBack, this._element, true);
514
718
  }
515
719
 
516
720
  hide() {
@@ -524,7 +728,7 @@
524
728
  return;
525
729
  }
526
730
 
527
- EventHandler__default['default'].off(document, EVENT_FOCUSIN);
731
+ this._focustrap.deactivate();
528
732
 
529
733
  this._element.blur();
530
734
 
@@ -544,24 +748,21 @@
544
748
  this._element.style.visibility = 'hidden';
545
749
 
546
750
  if (!this._config.scroll) {
547
- reset();
751
+ new ScrollBarHelper().reset();
548
752
  }
549
753
 
550
754
  EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN);
551
755
  };
552
756
 
553
- const transitionDuration = getTransitionDurationFromElement(this._element);
554
- EventHandler__default['default'].one(this._element, 'transitionend', completeCallback);
555
- emulateTransitionEnd(this._element, transitionDuration);
757
+ this._queueCallback(completeCallback, this._element, true);
556
758
  }
557
759
 
558
760
  dispose() {
559
761
  this._backdrop.dispose();
560
762
 
763
+ this._focustrap.deactivate();
764
+
561
765
  super.dispose();
562
- EventHandler__default['default'].off(document, EVENT_FOCUSIN);
563
- this._config = null;
564
- this._backdrop = null;
565
766
  } // Private
566
767
 
567
768
 
@@ -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,19 +785,13 @@
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
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();
@@ -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;
@@ -652,19 +848,18 @@
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
664
859
  * ------------------------------------------------------------------------
665
860
  */
666
861
 
667
- defineJQueryPlugin(NAME, Offcanvas);
862
+ defineJQueryPlugin(Offcanvas);
668
863
 
669
864
  return Offcanvas;
670
865