bootstrap 5.1.3 → 5.2.1

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -4
  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 +103 -317
  13. data/assets/javascripts/bootstrap/modal.js +107 -749
  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 +183 -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 +272 -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 +2077 -1859
  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 +56 -25
  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 +4 -1
  41. data/assets/stylesheets/bootstrap/_buttons.scss +120 -30
  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 +85 -76
  46. data/assets/stylesheets/bootstrap/_functions.scss +8 -8
  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 +48 -30
  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 +93 -150
  54. data/assets/stylesheets/bootstrap/_offcanvas.scss +120 -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 +36 -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 +128 -135
  68. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +3 -6
  69. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +15 -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 +19 -8
  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 +18 -10
  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 +13 -5
  91. data/bootstrap.gemspec +1 -1
  92. data/lib/bootstrap/version.rb +2 -2
  93. data/tasks/updater/js.rb +10 -5
  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.1 (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.1): 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