bootstrap 5.1.3 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/javascripts/bootstrap/alert.js +11 -146
  4. data/assets/javascripts/bootstrap/base-component.js +37 -120
  5. data/assets/javascripts/bootstrap/button.js +10 -74
  6. data/assets/javascripts/bootstrap/carousel.js +213 -485
  7. data/assets/javascripts/bootstrap/collapse.js +65 -249
  8. data/assets/javascripts/bootstrap/dom/data.js +3 -5
  9. data/assets/javascripts/bootstrap/dom/event-handler.js +94 -132
  10. data/assets/javascripts/bootstrap/dom/manipulator.js +23 -27
  11. data/assets/javascripts/bootstrap/dom/selector-engine.js +16 -58
  12. data/assets/javascripts/bootstrap/dropdown.js +101 -317
  13. data/assets/javascripts/bootstrap/modal.js +107 -752
  14. data/assets/javascripts/bootstrap/offcanvas.js +90 -659
  15. data/assets/javascripts/bootstrap/popover.js +36 -118
  16. data/assets/javascripts/bootstrap/scrollspy.js +179 -262
  17. data/assets/javascripts/bootstrap/tab.js +215 -214
  18. data/assets/javascripts/bootstrap/toast.js +28 -214
  19. data/assets/javascripts/bootstrap/tooltip.js +268 -611
  20. data/assets/javascripts/bootstrap/util/backdrop.js +165 -0
  21. data/assets/javascripts/bootstrap/util/component-functions.js +46 -0
  22. data/assets/javascripts/bootstrap/util/config.js +79 -0
  23. data/assets/javascripts/bootstrap/util/focustrap.js +129 -0
  24. data/assets/javascripts/bootstrap/util/index.js +350 -0
  25. data/assets/javascripts/bootstrap/util/sanitizer.js +122 -0
  26. data/assets/javascripts/bootstrap/util/scrollbar.js +138 -0
  27. data/assets/javascripts/bootstrap/util/swipe.js +155 -0
  28. data/assets/javascripts/bootstrap/util/template-factory.js +177 -0
  29. data/assets/javascripts/bootstrap-global-this-define.js +1 -1
  30. data/assets/javascripts/bootstrap-sprockets.js +10 -1
  31. data/assets/javascripts/bootstrap.js +2065 -1860
  32. data/assets/javascripts/bootstrap.min.js +3 -3
  33. data/assets/stylesheets/_bootstrap-grid.scss +3 -6
  34. data/assets/stylesheets/_bootstrap-reboot.scss +3 -7
  35. data/assets/stylesheets/_bootstrap.scss +4 -6
  36. data/assets/stylesheets/bootstrap/_accordion.scss +52 -24
  37. data/assets/stylesheets/bootstrap/_alert.scss +18 -4
  38. data/assets/stylesheets/bootstrap/_badge.scss +14 -5
  39. data/assets/stylesheets/bootstrap/_breadcrumb.scss +22 -10
  40. data/assets/stylesheets/bootstrap/_button-group.scss +3 -0
  41. data/assets/stylesheets/bootstrap/_buttons.scss +97 -22
  42. data/assets/stylesheets/bootstrap/_card.scss +55 -37
  43. data/assets/stylesheets/bootstrap/_close.scss +1 -1
  44. data/assets/stylesheets/bootstrap/_containers.scss +1 -1
  45. data/assets/stylesheets/bootstrap/_dropdown.scss +83 -75
  46. data/assets/stylesheets/bootstrap/_functions.scss +7 -7
  47. data/assets/stylesheets/bootstrap/_grid.scss +3 -3
  48. data/assets/stylesheets/bootstrap/_helpers.scss +1 -0
  49. data/assets/stylesheets/bootstrap/_list-group.scss +44 -27
  50. data/assets/stylesheets/bootstrap/_maps.scss +54 -0
  51. data/assets/stylesheets/bootstrap/_modal.scss +71 -43
  52. data/assets/stylesheets/bootstrap/_nav.scss +53 -20
  53. data/assets/stylesheets/bootstrap/_navbar.scss +91 -150
  54. data/assets/stylesheets/bootstrap/_offcanvas.scss +119 -59
  55. data/assets/stylesheets/bootstrap/_pagination.scss +66 -21
  56. data/assets/stylesheets/bootstrap/_placeholders.scss +1 -1
  57. data/assets/stylesheets/bootstrap/_popover.scss +90 -52
  58. data/assets/stylesheets/bootstrap/_progress.scss +20 -9
  59. data/assets/stylesheets/bootstrap/_reboot.scss +25 -40
  60. data/assets/stylesheets/bootstrap/_root.scss +40 -21
  61. data/assets/stylesheets/bootstrap/_spinners.scss +38 -22
  62. data/assets/stylesheets/bootstrap/_tables.scss +32 -23
  63. data/assets/stylesheets/bootstrap/_toasts.scss +35 -16
  64. data/assets/stylesheets/bootstrap/_tooltip.scss +61 -56
  65. data/assets/stylesheets/bootstrap/_type.scss +2 -0
  66. data/assets/stylesheets/bootstrap/_utilities.scss +43 -26
  67. data/assets/stylesheets/bootstrap/_variables.scss +113 -121
  68. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +3 -6
  69. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +14 -3
  70. data/assets/stylesheets/bootstrap/forms/_form-check.scss +28 -5
  71. data/assets/stylesheets/bootstrap/forms/_form-control.scss +12 -37
  72. data/assets/stylesheets/bootstrap/forms/_form-select.scss +0 -1
  73. data/assets/stylesheets/bootstrap/forms/_input-group.scss +15 -7
  74. data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +10 -0
  75. data/assets/stylesheets/bootstrap/helpers/_colored-links.scss +2 -2
  76. data/assets/stylesheets/bootstrap/helpers/_position.scss +7 -1
  77. data/assets/stylesheets/bootstrap/helpers/_ratio.scss +2 -2
  78. data/assets/stylesheets/bootstrap/helpers/_vr.scss +1 -1
  79. data/assets/stylesheets/bootstrap/mixins/_alert.scss +7 -3
  80. data/assets/stylesheets/bootstrap/mixins/_banner.scss +9 -0
  81. data/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +8 -8
  82. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +32 -95
  83. data/assets/stylesheets/bootstrap/mixins/_container.scss +4 -2
  84. data/assets/stylesheets/bootstrap/mixins/_forms.scss +8 -0
  85. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +1 -1
  86. data/assets/stylesheets/bootstrap/mixins/_grid.scss +12 -12
  87. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +4 -25
  88. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +1 -1
  89. data/assets/stylesheets/bootstrap/mixins/_table-variants.scss +12 -9
  90. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +12 -4
  91. data/bootstrap.gemspec +1 -1
  92. data/lib/bootstrap/version.rb +2 -2
  93. data/tasks/updater/js.rb +9 -4
  94. metadata +16 -4
@@ -1,203 +1,30 @@
1
1
  /*!
2
- * Bootstrap carousel.js v5.1.3 (https://getbootstrap.com/)
3
- * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap carousel.js v5.2.0 (https://getbootstrap.com/)
3
+ * Copyright 2011-2022 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/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) :
8
- typeof define === 'function' && define.amd ? define(['./dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Carousel = factory(global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base));
10
- })(this, (function (EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./util/index'), require('./dom/event-handler'), require('./dom/manipulator'), require('./dom/selector-engine'), require('./util/swipe'), require('./base-component')) :
8
+ typeof define === 'function' && define.amd ? define(['./util/index', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './util/swipe', './base-component'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Carousel = factory(global.Index, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Swipe, global.BaseComponent));
10
+ })(this, (function (index, EventHandler, Manipulator, SelectorEngine, Swipe, BaseComponent) { 'use strict';
11
11
 
12
12
  const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
13
 
14
14
  const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
15
15
  const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
16
16
  const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
17
+ const Swipe__default = /*#__PURE__*/_interopDefaultLegacy(Swipe);
17
18
  const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
18
19
 
19
20
  /**
20
21
  * --------------------------------------------------------------------------
21
- * Bootstrap (v5.1.3): util/index.js
22
+ * Bootstrap (v5.2.0): carousel.js
22
23
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
23
24
  * --------------------------------------------------------------------------
24
25
  */
25
- const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
26
-
27
- const toType = obj => {
28
- if (obj === null || obj === undefined) {
29
- return `${obj}`;
30
- }
31
-
32
- return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
33
- };
34
-
35
- const getSelector = element => {
36
- let selector = element.getAttribute('data-bs-target');
37
-
38
- if (!selector || selector === '#') {
39
- let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,
40
- // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
41
- // `document.querySelector` will rightfully complain it is invalid.
42
- // See https://github.com/twbs/bootstrap/issues/32273
43
-
44
- if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) {
45
- return null;
46
- } // Just in case some CMS puts out a full URL with the anchor appended
47
-
48
-
49
- if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
50
- hrefAttr = `#${hrefAttr.split('#')[1]}`;
51
- }
52
-
53
- selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
54
- }
55
-
56
- return selector;
57
- };
58
-
59
- const getElementFromSelector = element => {
60
- const selector = getSelector(element);
61
- return selector ? document.querySelector(selector) : null;
62
- };
63
-
64
- const triggerTransitionEnd = element => {
65
- element.dispatchEvent(new Event(TRANSITION_END));
66
- };
67
-
68
- const isElement = obj => {
69
- if (!obj || typeof obj !== 'object') {
70
- return false;
71
- }
72
-
73
- if (typeof obj.jquery !== 'undefined') {
74
- obj = obj[0];
75
- }
76
-
77
- return typeof obj.nodeType !== 'undefined';
78
- };
79
-
80
- const typeCheckConfig = (componentName, config, configTypes) => {
81
- Object.keys(configTypes).forEach(property => {
82
- const expectedTypes = configTypes[property];
83
- const value = config[property];
84
- const valueType = value && isElement(value) ? 'element' : toType(value);
85
-
86
- if (!new RegExp(expectedTypes).test(valueType)) {
87
- throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
88
- }
89
- });
90
- };
91
-
92
- const isVisible = element => {
93
- if (!isElement(element) || element.getClientRects().length === 0) {
94
- return false;
95
- }
96
-
97
- return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
98
- };
99
- /**
100
- * Trick to restart an element's animation
101
- *
102
- * @param {HTMLElement} element
103
- * @return void
104
- *
105
- * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
106
- */
107
-
108
-
109
- const reflow = element => {
110
- // eslint-disable-next-line no-unused-expressions
111
- element.offsetHeight;
112
- };
113
-
114
- const getjQuery = () => {
115
- const {
116
- jQuery
117
- } = window;
118
-
119
- if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
120
- return jQuery;
121
- }
122
-
123
- return null;
124
- };
125
-
126
- const DOMContentLoadedCallbacks = [];
127
-
128
- const onDOMContentLoaded = callback => {
129
- if (document.readyState === 'loading') {
130
- // add listener on the first call when the document is in loading state
131
- if (!DOMContentLoadedCallbacks.length) {
132
- document.addEventListener('DOMContentLoaded', () => {
133
- DOMContentLoadedCallbacks.forEach(callback => callback());
134
- });
135
- }
136
-
137
- DOMContentLoadedCallbacks.push(callback);
138
- } else {
139
- callback();
140
- }
141
- };
142
-
143
- const isRTL = () => document.documentElement.dir === 'rtl';
144
-
145
- const defineJQueryPlugin = plugin => {
146
- onDOMContentLoaded(() => {
147
- const $ = getjQuery();
148
- /* istanbul ignore if */
149
-
150
- if ($) {
151
- const name = plugin.NAME;
152
- const JQUERY_NO_CONFLICT = $.fn[name];
153
- $.fn[name] = plugin.jQueryInterface;
154
- $.fn[name].Constructor = plugin;
155
-
156
- $.fn[name].noConflict = () => {
157
- $.fn[name] = JQUERY_NO_CONFLICT;
158
- return plugin.jQueryInterface;
159
- };
160
- }
161
- });
162
- };
163
26
  /**
164
- * Return the previous/next element of a list.
165
- *
166
- * @param {array} list The list of elements
167
- * @param activeElement The active element
168
- * @param shouldGetNext Choose to get next or previous element
169
- * @param isCycleAllowed
170
- * @return {Element|elem} The proper element
171
- */
172
-
173
-
174
- const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
175
- let index = list.indexOf(activeElement); // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
176
-
177
- if (index === -1) {
178
- return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];
179
- }
180
-
181
- const listLength = list.length;
182
- index += shouldGetNext ? 1 : -1;
183
-
184
- if (isCycleAllowed) {
185
- index = (index + listLength) % listLength;
186
- }
187
-
188
- return list[Math.max(0, Math.min(index, listLength - 1))];
189
- };
190
-
191
- /**
192
- * --------------------------------------------------------------------------
193
- * Bootstrap (v5.1.3): carousel.js
194
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
195
- * --------------------------------------------------------------------------
196
- */
197
- /**
198
- * ------------------------------------------------------------------------
199
27
  * Constants
200
- * ------------------------------------------------------------------------
201
28
  */
202
29
 
203
30
  const NAME = 'carousel';
@@ -208,41 +35,15 @@
208
35
  const ARROW_RIGHT_KEY = 'ArrowRight';
209
36
  const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
210
37
 
211
- const SWIPE_THRESHOLD = 40;
212
- const Default = {
213
- interval: 5000,
214
- keyboard: true,
215
- slide: false,
216
- pause: 'hover',
217
- wrap: true,
218
- touch: true
219
- };
220
- const DefaultType = {
221
- interval: '(number|boolean)',
222
- keyboard: 'boolean',
223
- slide: '(boolean|string)',
224
- pause: '(string|boolean)',
225
- wrap: 'boolean',
226
- touch: 'boolean'
227
- };
228
38
  const ORDER_NEXT = 'next';
229
39
  const ORDER_PREV = 'prev';
230
40
  const DIRECTION_LEFT = 'left';
231
41
  const DIRECTION_RIGHT = 'right';
232
- const KEY_TO_DIRECTION = {
233
- [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
234
- [ARROW_RIGHT_KEY]: DIRECTION_LEFT
235
- };
236
42
  const EVENT_SLIDE = `slide${EVENT_KEY}`;
237
43
  const EVENT_SLID = `slid${EVENT_KEY}`;
238
44
  const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
239
45
  const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`;
240
46
  const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`;
241
- const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`;
242
- const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`;
243
- const EVENT_TOUCHEND = `touchend${EVENT_KEY}`;
244
- const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`;
245
- const EVENT_POINTERUP = `pointerup${EVENT_KEY}`;
246
47
  const EVENT_DRAG_START = `dragstart${EVENT_KEY}`;
247
48
  const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`;
248
49
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
@@ -253,41 +54,53 @@
253
54
  const CLASS_NAME_START = 'carousel-item-start';
254
55
  const CLASS_NAME_NEXT = 'carousel-item-next';
255
56
  const CLASS_NAME_PREV = 'carousel-item-prev';
256
- const CLASS_NAME_POINTER_EVENT = 'pointer-event';
257
57
  const SELECTOR_ACTIVE = '.active';
258
- const SELECTOR_ACTIVE_ITEM = '.active.carousel-item';
259
58
  const SELECTOR_ITEM = '.carousel-item';
59
+ const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM;
260
60
  const SELECTOR_ITEM_IMG = '.carousel-item img';
261
- const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';
262
61
  const SELECTOR_INDICATORS = '.carousel-indicators';
263
- const SELECTOR_INDICATOR = '[data-bs-target]';
264
62
  const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';
265
63
  const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]';
266
- const POINTER_TYPE_TOUCH = 'touch';
267
- const POINTER_TYPE_PEN = 'pen';
64
+ const KEY_TO_DIRECTION = {
65
+ [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
66
+ [ARROW_RIGHT_KEY]: DIRECTION_LEFT
67
+ };
68
+ const Default = {
69
+ interval: 5000,
70
+ keyboard: true,
71
+ pause: 'hover',
72
+ ride: false,
73
+ touch: true,
74
+ wrap: true
75
+ };
76
+ const DefaultType = {
77
+ interval: '(number|boolean)',
78
+ // TODO:v6 remove boolean support
79
+ keyboard: 'boolean',
80
+ pause: '(string|boolean)',
81
+ ride: '(boolean|string)',
82
+ touch: 'boolean',
83
+ wrap: 'boolean'
84
+ };
268
85
  /**
269
- * ------------------------------------------------------------------------
270
- * Class Definition
271
- * ------------------------------------------------------------------------
86
+ * Class definition
272
87
  */
273
88
 
274
89
  class Carousel extends BaseComponent__default.default {
275
90
  constructor(element, config) {
276
- super(element);
277
- this._items = null;
91
+ super(element, config);
278
92
  this._interval = null;
279
93
  this._activeElement = null;
280
- this._isPaused = false;
281
94
  this._isSliding = false;
282
95
  this.touchTimeout = null;
283
- this.touchStartX = 0;
284
- this.touchDeltaX = 0;
285
- this._config = this._getConfig(config);
96
+ this._swipeHelper = null;
286
97
  this._indicatorsElement = SelectorEngine__default.default.findOne(SELECTOR_INDICATORS, this._element);
287
- this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
288
- this._pointerEvent = Boolean(window.PointerEvent);
289
98
 
290
99
  this._addEventListeners();
100
+
101
+ if (this._config.ride === CLASS_NAME_CAROUSEL) {
102
+ this.cycle();
103
+ }
291
104
  } // Getters
292
105
 
293
106
 
@@ -295,6 +108,10 @@
295
108
  return Default;
296
109
  }
297
110
 
111
+ static get DefaultType() {
112
+ return DefaultType;
113
+ }
114
+
298
115
  static get NAME() {
299
116
  return NAME;
300
117
  } // Public
@@ -305,9 +122,10 @@
305
122
  }
306
123
 
307
124
  nextWhenVisible() {
125
+ // FIXME TODO use `document.visibilityState`
308
126
  // Don't call next when the page isn't visible
309
127
  // or the carousel or its parent isn't visible
310
- if (!document.hidden && isVisible(this._element)) {
128
+ if (!document.hidden && index.isVisible(this._element)) {
311
129
  this.next();
312
130
  }
313
131
  }
@@ -316,43 +134,39 @@
316
134
  this._slide(ORDER_PREV);
317
135
  }
318
136
 
319
- pause(event) {
320
- if (!event) {
321
- this._isPaused = true;
137
+ pause() {
138
+ if (this._isSliding) {
139
+ index.triggerTransitionEnd(this._element);
322
140
  }
323
141
 
324
- if (SelectorEngine__default.default.findOne(SELECTOR_NEXT_PREV, this._element)) {
325
- triggerTransitionEnd(this._element);
326
- this.cycle(true);
327
- }
142
+ this._clearInterval();
143
+ }
328
144
 
329
- clearInterval(this._interval);
330
- this._interval = null;
145
+ cycle() {
146
+ this._clearInterval();
147
+
148
+ this._updateInterval();
149
+
150
+ this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval);
331
151
  }
332
152
 
333
- cycle(event) {
334
- if (!event) {
335
- this._isPaused = false;
153
+ _maybeEnableCycle() {
154
+ if (!this._config.ride) {
155
+ return;
336
156
  }
337
157
 
338
- if (this._interval) {
339
- clearInterval(this._interval);
340
- this._interval = null;
158
+ if (this._isSliding) {
159
+ EventHandler__default.default.one(this._element, EVENT_SLID, () => this.cycle());
160
+ return;
341
161
  }
342
162
 
343
- if (this._config && this._config.interval && !this._isPaused) {
344
- this._updateInterval();
345
-
346
- this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
347
- }
163
+ this.cycle();
348
164
  }
349
165
 
350
166
  to(index) {
351
- this._activeElement = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
352
-
353
- const activeIndex = this._getItemIndex(this._activeElement);
167
+ const items = this._getItems();
354
168
 
355
- if (index > this._items.length - 1 || index < 0) {
169
+ if (index > items.length - 1 || index < 0) {
356
170
  return;
357
171
  }
358
172
 
@@ -361,42 +175,29 @@
361
175
  return;
362
176
  }
363
177
 
178
+ const activeIndex = this._getItemIndex(this._getActive());
179
+
364
180
  if (activeIndex === index) {
365
- this.pause();
366
- this.cycle();
367
181
  return;
368
182
  }
369
183
 
370
184
  const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;
371
185
 
372
- this._slide(order, this._items[index]);
373
- } // Private
374
-
375
-
376
- _getConfig(config) {
377
- config = { ...Default,
378
- ...Manipulator__default.default.getDataAttributes(this._element),
379
- ...(typeof config === 'object' ? config : {})
380
- };
381
- typeCheckConfig(NAME, config, DefaultType);
382
- return config;
186
+ this._slide(order, items[index]);
383
187
  }
384
188
 
385
- _handleSwipe() {
386
- const absDeltax = Math.abs(this.touchDeltaX);
387
-
388
- if (absDeltax <= SWIPE_THRESHOLD) {
389
- return;
189
+ dispose() {
190
+ if (this._swipeHelper) {
191
+ this._swipeHelper.dispose();
390
192
  }
391
193
 
392
- const direction = absDeltax / this.touchDeltaX;
393
- this.touchDeltaX = 0;
194
+ super.dispose();
195
+ } // Private
394
196
 
395
- if (!direction) {
396
- return;
397
- }
398
197
 
399
- this._slide(direction > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT);
198
+ _configAfterMerge(config) {
199
+ config.defaultInterval = config.interval;
200
+ return config;
400
201
  }
401
202
 
402
203
  _addEventListeners() {
@@ -405,72 +206,47 @@
405
206
  }
406
207
 
407
208
  if (this._config.pause === 'hover') {
408
- EventHandler__default.default.on(this._element, EVENT_MOUSEENTER, event => this.pause(event));
409
- EventHandler__default.default.on(this._element, EVENT_MOUSELEAVE, event => this.cycle(event));
209
+ EventHandler__default.default.on(this._element, EVENT_MOUSEENTER, () => this.pause());
210
+ EventHandler__default.default.on(this._element, EVENT_MOUSELEAVE, () => this._maybeEnableCycle());
410
211
  }
411
212
 
412
- if (this._config.touch && this._touchSupported) {
213
+ if (this._config.touch && Swipe__default.default.isSupported()) {
413
214
  this._addTouchEventListeners();
414
215
  }
415
216
  }
416
217
 
417
218
  _addTouchEventListeners() {
418
- const hasPointerPenTouch = event => {
419
- return this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH);
420
- };
421
-
422
- const start = event => {
423
- if (hasPointerPenTouch(event)) {
424
- this.touchStartX = event.clientX;
425
- } else if (!this._pointerEvent) {
426
- this.touchStartX = event.touches[0].clientX;
427
- }
428
- };
429
-
430
- const move = event => {
431
- // ensure swiping with one touch and not pinching
432
- this.touchDeltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this.touchStartX;
433
- };
434
-
435
- const end = event => {
436
- if (hasPointerPenTouch(event)) {
437
- this.touchDeltaX = event.clientX - this.touchStartX;
438
- }
219
+ for (const img of SelectorEngine__default.default.find(SELECTOR_ITEM_IMG, this._element)) {
220
+ EventHandler__default.default.on(img, EVENT_DRAG_START, event => event.preventDefault());
221
+ }
439
222
 
440
- this._handleSwipe();
223
+ const endCallBack = () => {
224
+ if (this._config.pause !== 'hover') {
225
+ return;
226
+ } // If it's a touch-enabled device, mouseenter/leave are fired as
227
+ // part of the mouse compatibility events on first tap - the carousel
228
+ // would stop cycling until user tapped out of it;
229
+ // here, we listen for touchend, explicitly pause the carousel
230
+ // (as if it's the second time we tap on it, mouseenter compat event
231
+ // is NOT fired) and after a timeout (to allow for mouse compatibility
232
+ // events to fire) we explicitly restart cycling
441
233
 
442
- if (this._config.pause === 'hover') {
443
- // If it's a touch-enabled device, mouseenter/leave are fired as
444
- // part of the mouse compatibility events on first tap - the carousel
445
- // would stop cycling until user tapped out of it;
446
- // here, we listen for touchend, explicitly pause the carousel
447
- // (as if it's the second time we tap on it, mouseenter compat event
448
- // is NOT fired) and after a timeout (to allow for mouse compatibility
449
- // events to fire) we explicitly restart cycling
450
- this.pause();
451
234
 
452
- if (this.touchTimeout) {
453
- clearTimeout(this.touchTimeout);
454
- }
235
+ this.pause();
455
236
 
456
- this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval);
237
+ if (this.touchTimeout) {
238
+ clearTimeout(this.touchTimeout);
457
239
  }
458
- };
459
-
460
- SelectorEngine__default.default.find(SELECTOR_ITEM_IMG, this._element).forEach(itemImg => {
461
- EventHandler__default.default.on(itemImg, EVENT_DRAG_START, event => event.preventDefault());
462
- });
463
240
 
464
- if (this._pointerEvent) {
465
- EventHandler__default.default.on(this._element, EVENT_POINTERDOWN, event => start(event));
466
- EventHandler__default.default.on(this._element, EVENT_POINTERUP, event => end(event));
241
+ this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval);
242
+ };
467
243
 
468
- this._element.classList.add(CLASS_NAME_POINTER_EVENT);
469
- } else {
470
- EventHandler__default.default.on(this._element, EVENT_TOUCHSTART, event => start(event));
471
- EventHandler__default.default.on(this._element, EVENT_TOUCHMOVE, event => move(event));
472
- EventHandler__default.default.on(this._element, EVENT_TOUCHEND, event => end(event));
473
- }
244
+ const swipeConfig = {
245
+ leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),
246
+ rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),
247
+ endCallback: endCallBack
248
+ };
249
+ this._swipeHelper = new Swipe__default.default(this._element, swipeConfig);
474
250
  }
475
251
 
476
252
  _keydown(event) {
@@ -483,95 +259,67 @@
483
259
  if (direction) {
484
260
  event.preventDefault();
485
261
 
486
- this._slide(direction);
262
+ this._slide(this._directionToOrder(direction));
487
263
  }
488
264
  }
489
265
 
490
266
  _getItemIndex(element) {
491
- this._items = element && element.parentNode ? SelectorEngine__default.default.find(SELECTOR_ITEM, element.parentNode) : [];
492
- return this._items.indexOf(element);
267
+ return this._getItems().indexOf(element);
493
268
  }
494
269
 
495
- _getItemByOrder(order, activeElement) {
496
- const isNext = order === ORDER_NEXT;
497
- return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);
498
- }
499
-
500
- _triggerSlideEvent(relatedTarget, eventDirectionName) {
501
- const targetIndex = this._getItemIndex(relatedTarget);
502
-
503
- const fromIndex = this._getItemIndex(SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element));
270
+ _setActiveIndicatorElement(index) {
271
+ if (!this._indicatorsElement) {
272
+ return;
273
+ }
504
274
 
505
- return EventHandler__default.default.trigger(this._element, EVENT_SLIDE, {
506
- relatedTarget,
507
- direction: eventDirectionName,
508
- from: fromIndex,
509
- to: targetIndex
510
- });
511
- }
275
+ const activeIndicator = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE, this._indicatorsElement);
276
+ activeIndicator.classList.remove(CLASS_NAME_ACTIVE);
277
+ activeIndicator.removeAttribute('aria-current');
278
+ const newActiveIndicator = SelectorEngine__default.default.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement);
512
279
 
513
- _setActiveIndicatorElement(element) {
514
- if (this._indicatorsElement) {
515
- const activeIndicator = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE, this._indicatorsElement);
516
- activeIndicator.classList.remove(CLASS_NAME_ACTIVE);
517
- activeIndicator.removeAttribute('aria-current');
518
- const indicators = SelectorEngine__default.default.find(SELECTOR_INDICATOR, this._indicatorsElement);
519
-
520
- for (let i = 0; i < indicators.length; i++) {
521
- if (Number.parseInt(indicators[i].getAttribute('data-bs-slide-to'), 10) === this._getItemIndex(element)) {
522
- indicators[i].classList.add(CLASS_NAME_ACTIVE);
523
- indicators[i].setAttribute('aria-current', 'true');
524
- break;
525
- }
526
- }
280
+ if (newActiveIndicator) {
281
+ newActiveIndicator.classList.add(CLASS_NAME_ACTIVE);
282
+ newActiveIndicator.setAttribute('aria-current', 'true');
527
283
  }
528
284
  }
529
285
 
530
286
  _updateInterval() {
531
- const element = this._activeElement || SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
287
+ const element = this._activeElement || this._getActive();
532
288
 
533
289
  if (!element) {
534
290
  return;
535
291
  }
536
292
 
537
293
  const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);
538
-
539
- if (elementInterval) {
540
- this._config.defaultInterval = this._config.defaultInterval || this._config.interval;
541
- this._config.interval = elementInterval;
542
- } else {
543
- this._config.interval = this._config.defaultInterval || this._config.interval;
544
- }
294
+ this._config.interval = elementInterval || this._config.defaultInterval;
545
295
  }
546
296
 
547
- _slide(directionOrOrder, element) {
548
- const order = this._directionToOrder(directionOrOrder);
549
-
550
- const activeElement = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
551
-
552
- const activeElementIndex = this._getItemIndex(activeElement);
553
-
554
- const nextElement = element || this._getItemByOrder(order, activeElement);
297
+ _slide(order, element = null) {
298
+ if (this._isSliding) {
299
+ return;
300
+ }
555
301
 
556
- const nextElementIndex = this._getItemIndex(nextElement);
302
+ const activeElement = this._getActive();
557
303
 
558
- const isCycling = Boolean(this._interval);
559
304
  const isNext = order === ORDER_NEXT;
560
- const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;
561
- const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;
562
-
563
- const eventDirectionName = this._orderToDirection(order);
305
+ const nextElement = element || index.getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap);
564
306
 
565
- if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE)) {
566
- this._isSliding = false;
307
+ if (nextElement === activeElement) {
567
308
  return;
568
309
  }
569
310
 
570
- if (this._isSliding) {
571
- return;
572
- }
311
+ const nextElementIndex = this._getItemIndex(nextElement);
312
+
313
+ const triggerEvent = eventName => {
314
+ return EventHandler__default.default.trigger(this._element, eventName, {
315
+ relatedTarget: nextElement,
316
+ direction: this._orderToDirection(order),
317
+ from: this._getItemIndex(activeElement),
318
+ to: nextElementIndex
319
+ });
320
+ };
573
321
 
574
- const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
322
+ const slideEvent = triggerEvent(EVENT_SLIDE);
575
323
 
576
324
  if (slideEvent.defaultPrevented) {
577
325
  return;
@@ -579,61 +327,60 @@
579
327
 
580
328
  if (!activeElement || !nextElement) {
581
329
  // Some weirdness is happening, so we bail
330
+ // todo: change tests that use empty divs to avoid this check
582
331
  return;
583
332
  }
584
333
 
334
+ const isCycling = Boolean(this._interval);
335
+ this.pause();
585
336
  this._isSliding = true;
586
337
 
587
- if (isCycling) {
588
- this.pause();
589
- }
590
-
591
- this._setActiveIndicatorElement(nextElement);
338
+ this._setActiveIndicatorElement(nextElementIndex);
592
339
 
593
340
  this._activeElement = nextElement;
341
+ const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;
342
+ const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;
343
+ nextElement.classList.add(orderClassName);
344
+ index.reflow(nextElement);
345
+ activeElement.classList.add(directionalClassName);
346
+ nextElement.classList.add(directionalClassName);
594
347
 
595
- const triggerSlidEvent = () => {
596
- EventHandler__default.default.trigger(this._element, EVENT_SLID, {
597
- relatedTarget: nextElement,
598
- direction: eventDirectionName,
599
- from: activeElementIndex,
600
- to: nextElementIndex
601
- });
602
- };
603
-
604
- if (this._element.classList.contains(CLASS_NAME_SLIDE)) {
605
- nextElement.classList.add(orderClassName);
606
- reflow(nextElement);
607
- activeElement.classList.add(directionalClassName);
608
- nextElement.classList.add(directionalClassName);
609
-
610
- const completeCallBack = () => {
611
- nextElement.classList.remove(directionalClassName, orderClassName);
612
- nextElement.classList.add(CLASS_NAME_ACTIVE);
613
- activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName);
614
- this._isSliding = false;
615
- setTimeout(triggerSlidEvent, 0);
616
- };
617
-
618
- this._queueCallback(completeCallBack, activeElement, true);
619
- } else {
620
- activeElement.classList.remove(CLASS_NAME_ACTIVE);
348
+ const completeCallBack = () => {
349
+ nextElement.classList.remove(directionalClassName, orderClassName);
621
350
  nextElement.classList.add(CLASS_NAME_ACTIVE);
351
+ activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName);
622
352
  this._isSliding = false;
623
- triggerSlidEvent();
624
- }
353
+ triggerEvent(EVENT_SLID);
354
+ };
355
+
356
+ this._queueCallback(completeCallBack, activeElement, this._isAnimated());
625
357
 
626
358
  if (isCycling) {
627
359
  this.cycle();
628
360
  }
629
361
  }
630
362
 
631
- _directionToOrder(direction) {
632
- if (![DIRECTION_RIGHT, DIRECTION_LEFT].includes(direction)) {
633
- return direction;
363
+ _isAnimated() {
364
+ return this._element.classList.contains(CLASS_NAME_SLIDE);
365
+ }
366
+
367
+ _getActive() {
368
+ return SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
369
+ }
370
+
371
+ _getItems() {
372
+ return SelectorEngine__default.default.find(SELECTOR_ITEM, this._element);
373
+ }
374
+
375
+ _clearInterval() {
376
+ if (this._interval) {
377
+ clearInterval(this._interval);
378
+ this._interval = null;
634
379
  }
380
+ }
635
381
 
636
- if (isRTL()) {
382
+ _directionToOrder(direction) {
383
+ if (index.isRTL()) {
637
384
  return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;
638
385
  }
639
386
 
@@ -641,11 +388,7 @@
641
388
  }
642
389
 
643
390
  _orderToDirection(order) {
644
- if (![ORDER_NEXT, ORDER_PREV].includes(order)) {
645
- return order;
646
- }
647
-
648
- if (isRTL()) {
391
+ if (index.isRTL()) {
649
392
  return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;
650
393
  }
651
394
 
@@ -653,89 +396,74 @@
653
396
  } // Static
654
397
 
655
398
 
656
- static carouselInterface(element, config) {
657
- const data = Carousel.getOrCreateInstance(element, config);
658
- let {
659
- _config
660
- } = data;
661
-
662
- if (typeof config === 'object') {
663
- _config = { ..._config,
664
- ...config
665
- };
666
- }
667
-
668
- const action = typeof config === 'string' ? config : _config.slide;
399
+ static jQueryInterface(config) {
400
+ return this.each(function () {
401
+ const data = Carousel.getOrCreateInstance(this, config);
669
402
 
670
- if (typeof config === 'number') {
671
- data.to(config);
672
- } else if (typeof action === 'string') {
673
- if (typeof data[action] === 'undefined') {
674
- throw new TypeError(`No method named "${action}"`);
403
+ if (typeof config === 'number') {
404
+ data.to(config);
405
+ return;
675
406
  }
676
407
 
677
- data[action]();
678
- } else if (_config.interval && _config.ride) {
679
- data.pause();
680
- data.cycle();
681
- }
682
- }
408
+ if (typeof config === 'string') {
409
+ if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
410
+ throw new TypeError(`No method named "${config}"`);
411
+ }
683
412
 
684
- static jQueryInterface(config) {
685
- return this.each(function () {
686
- Carousel.carouselInterface(this, config);
413
+ data[config]();
414
+ }
687
415
  });
688
416
  }
689
417
 
690
- static dataApiClickHandler(event) {
691
- const target = getElementFromSelector(this);
418
+ }
419
+ /**
420
+ * Data API implementation
421
+ */
422
+
692
423
 
693
- if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
694
- return;
695
- }
424
+ EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, function (event) {
425
+ const target = index.getElementFromSelector(this);
696
426
 
697
- const config = { ...Manipulator__default.default.getDataAttributes(target),
698
- ...Manipulator__default.default.getDataAttributes(this)
699
- };
700
- const slideIndex = this.getAttribute('data-bs-slide-to');
427
+ if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
428
+ return;
429
+ }
701
430
 
702
- if (slideIndex) {
703
- config.interval = false;
704
- }
431
+ event.preventDefault();
432
+ const carousel = Carousel.getOrCreateInstance(target);
433
+ const slideIndex = this.getAttribute('data-bs-slide-to');
705
434
 
706
- Carousel.carouselInterface(target, config);
435
+ if (slideIndex) {
436
+ carousel.to(slideIndex);
707
437
 
708
- if (slideIndex) {
709
- Carousel.getInstance(target).to(slideIndex);
710
- }
438
+ carousel._maybeEnableCycle();
711
439
 
712
- event.preventDefault();
440
+ return;
713
441
  }
714
442
 
715
- }
716
- /**
717
- * ------------------------------------------------------------------------
718
- * Data Api implementation
719
- * ------------------------------------------------------------------------
720
- */
443
+ if (Manipulator__default.default.getDataAttribute(this, 'slide') === 'next') {
444
+ carousel.next();
721
445
 
446
+ carousel._maybeEnableCycle();
722
447
 
723
- EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler);
448
+ return;
449
+ }
450
+
451
+ carousel.prev();
452
+
453
+ carousel._maybeEnableCycle();
454
+ });
724
455
  EventHandler__default.default.on(window, EVENT_LOAD_DATA_API, () => {
725
456
  const carousels = SelectorEngine__default.default.find(SELECTOR_DATA_RIDE);
726
457
 
727
- for (let i = 0, len = carousels.length; i < len; i++) {
728
- Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));
458
+ for (const carousel of carousels) {
459
+ Carousel.getOrCreateInstance(carousel);
729
460
  }
730
461
  });
731
462
  /**
732
- * ------------------------------------------------------------------------
733
463
  * jQuery
734
- * ------------------------------------------------------------------------
735
- * add .Carousel to jQuery only if jQuery is present
736
464
  */
737
465
 
738
- defineJQueryPlugin(Carousel);
466
+ index.defineJQueryPlugin(Carousel);
739
467
 
740
468
  return Carousel;
741
469