@openeuropa/bcl-bootstrap 0.24.1 → 0.26.0

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 (142) hide show
  1. package/bootstrap-icons.svg +1 -1
  2. package/icons/apple.svg +2 -2
  3. package/icons/boombox-fill.svg +2 -2
  4. package/icons/cup-fill.svg +1 -1
  5. package/icons/cup.svg +1 -1
  6. package/js/dist/alert.js +3 -12
  7. package/js/dist/alert.js.map +1 -1
  8. package/js/dist/base-component.js +32 -18
  9. package/js/dist/base-component.js.map +1 -1
  10. package/js/dist/button.js +3 -12
  11. package/js/dist/button.js.map +1 -1
  12. package/js/dist/carousel.js +207 -307
  13. package/js/dist/carousel.js.map +1 -1
  14. package/js/dist/collapse.js +57 -88
  15. package/js/dist/collapse.js.map +1 -1
  16. package/js/dist/dom/data.js +1 -3
  17. package/js/dist/dom/data.js.map +1 -1
  18. package/js/dist/dom/event-handler.js +87 -106
  19. package/js/dist/dom/event-handler.js.map +1 -1
  20. package/js/dist/dom/manipulator.js +21 -25
  21. package/js/dist/dom/manipulator.js.map +1 -1
  22. package/js/dist/dom/selector-engine.js +11 -10
  23. package/js/dist/dom/selector-engine.js.map +1 -1
  24. package/js/dist/dropdown.js +83 -115
  25. package/js/dist/dropdown.js.map +1 -1
  26. package/js/dist/modal.js +95 -152
  27. package/js/dist/modal.js.map +1 -1
  28. package/js/dist/offcanvas.js +75 -58
  29. package/js/dist/offcanvas.js.map +1 -1
  30. package/js/dist/popover.js +29 -56
  31. package/js/dist/popover.js.map +1 -1
  32. package/js/dist/scrollspy.js +176 -125
  33. package/js/dist/scrollspy.js.map +1 -1
  34. package/js/dist/tab.js +207 -92
  35. package/js/dist/tab.js.map +1 -1
  36. package/js/dist/toast.js +23 -37
  37. package/js/dist/toast.js.map +1 -1
  38. package/js/dist/tooltip.js +259 -348
  39. package/js/dist/tooltip.js.map +1 -1
  40. package/js/dist/util/backdrop.js +62 -39
  41. package/js/dist/util/backdrop.js.map +1 -1
  42. package/js/dist/util/component-functions.js +1 -1
  43. package/js/dist/util/component-functions.js.map +1 -1
  44. package/js/dist/util/config.js +75 -0
  45. package/js/dist/util/config.js.map +1 -0
  46. package/js/dist/util/focustrap.js +41 -34
  47. package/js/dist/util/focustrap.js.map +1 -1
  48. package/js/dist/util/index.js +56 -52
  49. package/js/dist/util/index.js.map +1 -1
  50. package/js/dist/util/sanitizer.js +12 -19
  51. package/js/dist/util/sanitizer.js.map +1 -1
  52. package/js/dist/util/scrollbar.js +49 -34
  53. package/js/dist/util/scrollbar.js.map +1 -1
  54. package/js/dist/util/swipe.js +151 -0
  55. package/js/dist/util/swipe.js.map +1 -0
  56. package/js/dist/util/template-factory.js +173 -0
  57. package/js/dist/util/template-factory.js.map +1 -0
  58. package/js/src/alert.js +3 -15
  59. package/js/src/base-component.js +28 -18
  60. package/js/src/button.js +3 -17
  61. package/js/src/carousel.js +203 -319
  62. package/js/src/collapse.js +61 -94
  63. package/js/src/dom/data.js +1 -3
  64. package/js/src/dom/event-handler.js +80 -108
  65. package/js/src/dom/manipulator.js +22 -31
  66. package/js/src/dom/selector-engine.js +10 -19
  67. package/js/src/dropdown.js +84 -138
  68. package/js/src/modal.js +94 -158
  69. package/js/src/offcanvas.js +72 -61
  70. package/js/src/popover.js +31 -62
  71. package/js/src/scrollspy.js +166 -171
  72. package/js/src/tab.js +193 -110
  73. package/js/src/toast.js +19 -41
  74. package/js/src/tooltip.js +259 -371
  75. package/js/src/util/backdrop.js +55 -36
  76. package/js/src/util/component-functions.js +1 -1
  77. package/js/src/util/config.js +66 -0
  78. package/js/src/util/focustrap.js +38 -28
  79. package/js/src/util/index.js +67 -64
  80. package/js/src/util/sanitizer.js +11 -19
  81. package/js/src/util/scrollbar.js +47 -30
  82. package/js/src/util/swipe.js +146 -0
  83. package/js/src/util/template-factory.js +160 -0
  84. package/package.json +4 -4
  85. package/scss/_accordion.scss +52 -24
  86. package/scss/_alert.scss +18 -4
  87. package/scss/_badge.scss +14 -5
  88. package/scss/_breadcrumb.scss +22 -10
  89. package/scss/_button-group.scss +3 -0
  90. package/scss/_buttons.scss +97 -22
  91. package/scss/_card.scss +55 -37
  92. package/scss/_close.scss +1 -1
  93. package/scss/_containers.scss +1 -1
  94. package/scss/_dropdown.scss +83 -75
  95. package/scss/_functions.scss +7 -7
  96. package/scss/_grid.scss +3 -3
  97. package/scss/_helpers.scss +1 -0
  98. package/scss/_list-group.scss +44 -27
  99. package/scss/_maps.scss +54 -0
  100. package/scss/_modal.scss +71 -43
  101. package/scss/_nav.scss +53 -20
  102. package/scss/_navbar.scss +91 -150
  103. package/scss/_offcanvas.scss +119 -59
  104. package/scss/_pagination.scss +66 -21
  105. package/scss/_placeholders.scss +1 -1
  106. package/scss/_popover.scss +90 -52
  107. package/scss/_progress.scss +20 -9
  108. package/scss/_reboot.scss +25 -40
  109. package/scss/_root.scss +40 -21
  110. package/scss/_spinners.scss +38 -22
  111. package/scss/_tables.scss +32 -23
  112. package/scss/_toasts.scss +35 -16
  113. package/scss/_tooltip.scss +61 -56
  114. package/scss/_type.scss +2 -0
  115. package/scss/_utilities.scss +43 -26
  116. package/scss/_variables.scss +113 -121
  117. package/scss/bootstrap-grid.scss +3 -6
  118. package/scss/bootstrap-reboot.scss +3 -7
  119. package/scss/bootstrap-utilities.scss +3 -6
  120. package/scss/bootstrap.scss +4 -6
  121. package/scss/forms/_floating-labels.scss +14 -3
  122. package/scss/forms/_form-check.scss +28 -5
  123. package/scss/forms/_form-control.scss +12 -37
  124. package/scss/forms/_form-select.scss +0 -1
  125. package/scss/forms/_input-group.scss +15 -7
  126. package/scss/helpers/_color-bg.scss +10 -0
  127. package/scss/helpers/_colored-links.scss +2 -2
  128. package/scss/helpers/_position.scss +7 -1
  129. package/scss/helpers/_ratio.scss +2 -2
  130. package/scss/helpers/_vr.scss +1 -1
  131. package/scss/mixins/_alert.scss +7 -3
  132. package/scss/mixins/_banner.scss +9 -0
  133. package/scss/mixins/_breakpoints.scss +8 -8
  134. package/scss/mixins/_buttons.scss +32 -95
  135. package/scss/mixins/_container.scss +4 -2
  136. package/scss/mixins/_forms.scss +8 -0
  137. package/scss/mixins/_gradients.scss +1 -1
  138. package/scss/mixins/_grid.scss +12 -12
  139. package/scss/mixins/_pagination.scss +4 -25
  140. package/scss/mixins/_reset-text.scss +1 -1
  141. package/scss/mixins/_table-variants.scss +12 -9
  142. package/scss/mixins/_utilities.scss +12 -4
@@ -1,26 +1,25 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./util/index'), require('./dom/event-handler'), require('./dom/manipulator'), require('./dom/selector-engine'), require('./base-component')) :
3
- typeof define === 'function' && define.amd ? define(['./util/index', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Carousel = factory(global.Index, global.EventHandler, global.Manipulator, global.SelectorEngine, global.BaseComponent));
5
- })(this, (function (index, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
2
+ 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')) :
3
+ typeof define === 'function' && define.amd ? define(['./util/index', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './util/swipe', './base-component'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Carousel = factory(global.Index, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Swipe, global.BaseComponent));
5
+ })(this, (function (index, EventHandler, Manipulator, SelectorEngine, Swipe, BaseComponent) { 'use strict';
6
6
 
7
7
  const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
8
8
 
9
9
  const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
10
10
  const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
11
11
  const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
12
+ const Swipe__default = /*#__PURE__*/_interopDefaultLegacy(Swipe);
12
13
  const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
13
14
 
14
15
  /**
15
16
  * --------------------------------------------------------------------------
16
- * Bootstrap (v5.1.3): carousel.js
17
+ * Bootstrap (v5.2.0): carousel.js
17
18
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
18
19
  * --------------------------------------------------------------------------
19
20
  */
20
21
  /**
21
- * ------------------------------------------------------------------------
22
22
  * Constants
23
- * ------------------------------------------------------------------------
24
23
  */
25
24
 
26
25
  const NAME = 'carousel';
@@ -31,41 +30,15 @@
31
30
  const ARROW_RIGHT_KEY = 'ArrowRight';
32
31
  const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
33
32
 
34
- const SWIPE_THRESHOLD = 40;
35
- const Default = {
36
- interval: 5000,
37
- keyboard: true,
38
- slide: false,
39
- pause: 'hover',
40
- wrap: true,
41
- touch: true
42
- };
43
- const DefaultType = {
44
- interval: '(number|boolean)',
45
- keyboard: 'boolean',
46
- slide: '(boolean|string)',
47
- pause: '(string|boolean)',
48
- wrap: 'boolean',
49
- touch: 'boolean'
50
- };
51
33
  const ORDER_NEXT = 'next';
52
34
  const ORDER_PREV = 'prev';
53
35
  const DIRECTION_LEFT = 'left';
54
36
  const DIRECTION_RIGHT = 'right';
55
- const KEY_TO_DIRECTION = {
56
- [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
57
- [ARROW_RIGHT_KEY]: DIRECTION_LEFT
58
- };
59
37
  const EVENT_SLIDE = `slide${EVENT_KEY}`;
60
38
  const EVENT_SLID = `slid${EVENT_KEY}`;
61
39
  const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
62
40
  const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`;
63
41
  const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`;
64
- const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`;
65
- const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`;
66
- const EVENT_TOUCHEND = `touchend${EVENT_KEY}`;
67
- const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`;
68
- const EVENT_POINTERUP = `pointerup${EVENT_KEY}`;
69
42
  const EVENT_DRAG_START = `dragstart${EVENT_KEY}`;
70
43
  const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`;
71
44
  const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
@@ -76,41 +49,53 @@
76
49
  const CLASS_NAME_START = 'carousel-item-start';
77
50
  const CLASS_NAME_NEXT = 'carousel-item-next';
78
51
  const CLASS_NAME_PREV = 'carousel-item-prev';
79
- const CLASS_NAME_POINTER_EVENT = 'pointer-event';
80
52
  const SELECTOR_ACTIVE = '.active';
81
- const SELECTOR_ACTIVE_ITEM = '.active.carousel-item';
82
53
  const SELECTOR_ITEM = '.carousel-item';
54
+ const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM;
83
55
  const SELECTOR_ITEM_IMG = '.carousel-item img';
84
- const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';
85
56
  const SELECTOR_INDICATORS = '.carousel-indicators';
86
- const SELECTOR_INDICATOR = '[data-bs-target]';
87
57
  const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';
88
58
  const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]';
89
- const POINTER_TYPE_TOUCH = 'touch';
90
- const POINTER_TYPE_PEN = 'pen';
59
+ const KEY_TO_DIRECTION = {
60
+ [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
61
+ [ARROW_RIGHT_KEY]: DIRECTION_LEFT
62
+ };
63
+ const Default = {
64
+ interval: 5000,
65
+ keyboard: true,
66
+ pause: 'hover',
67
+ ride: false,
68
+ touch: true,
69
+ wrap: true
70
+ };
71
+ const DefaultType = {
72
+ interval: '(number|boolean)',
73
+ // TODO:v6 remove boolean support
74
+ keyboard: 'boolean',
75
+ pause: '(string|boolean)',
76
+ ride: '(boolean|string)',
77
+ touch: 'boolean',
78
+ wrap: 'boolean'
79
+ };
91
80
  /**
92
- * ------------------------------------------------------------------------
93
- * Class Definition
94
- * ------------------------------------------------------------------------
81
+ * Class definition
95
82
  */
96
83
 
97
84
  class Carousel extends BaseComponent__default.default {
98
85
  constructor(element, config) {
99
- super(element);
100
- this._items = null;
86
+ super(element, config);
101
87
  this._interval = null;
102
88
  this._activeElement = null;
103
- this._isPaused = false;
104
89
  this._isSliding = false;
105
90
  this.touchTimeout = null;
106
- this.touchStartX = 0;
107
- this.touchDeltaX = 0;
108
- this._config = this._getConfig(config);
91
+ this._swipeHelper = null;
109
92
  this._indicatorsElement = SelectorEngine__default.default.findOne(SELECTOR_INDICATORS, this._element);
110
- this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
111
- this._pointerEvent = Boolean(window.PointerEvent);
112
93
 
113
94
  this._addEventListeners();
95
+
96
+ if (this._config.ride === CLASS_NAME_CAROUSEL) {
97
+ this.cycle();
98
+ }
114
99
  } // Getters
115
100
 
116
101
 
@@ -118,6 +103,10 @@
118
103
  return Default;
119
104
  }
120
105
 
106
+ static get DefaultType() {
107
+ return DefaultType;
108
+ }
109
+
121
110
  static get NAME() {
122
111
  return NAME;
123
112
  } // Public
@@ -128,6 +117,7 @@
128
117
  }
129
118
 
130
119
  nextWhenVisible() {
120
+ // FIXME TODO use `document.visibilityState`
131
121
  // Don't call next when the page isn't visible
132
122
  // or the carousel or its parent isn't visible
133
123
  if (!document.hidden && index.isVisible(this._element)) {
@@ -139,43 +129,39 @@
139
129
  this._slide(ORDER_PREV);
140
130
  }
141
131
 
142
- pause(event) {
143
- if (!event) {
144
- this._isPaused = true;
145
- }
146
-
147
- if (SelectorEngine__default.default.findOne(SELECTOR_NEXT_PREV, this._element)) {
132
+ pause() {
133
+ if (this._isSliding) {
148
134
  index.triggerTransitionEnd(this._element);
149
- this.cycle(true);
150
135
  }
151
136
 
152
- clearInterval(this._interval);
153
- this._interval = null;
137
+ this._clearInterval();
154
138
  }
155
139
 
156
- cycle(event) {
157
- if (!event) {
158
- this._isPaused = false;
159
- }
140
+ cycle() {
141
+ this._clearInterval();
160
142
 
161
- if (this._interval) {
162
- clearInterval(this._interval);
163
- this._interval = null;
164
- }
143
+ this._updateInterval();
144
+
145
+ this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval);
146
+ }
165
147
 
166
- if (this._config && this._config.interval && !this._isPaused) {
167
- this._updateInterval();
148
+ _maybeEnableCycle() {
149
+ if (!this._config.ride) {
150
+ return;
151
+ }
168
152
 
169
- this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
153
+ if (this._isSliding) {
154
+ EventHandler__default.default.one(this._element, EVENT_SLID, () => this.cycle());
155
+ return;
170
156
  }
157
+
158
+ this.cycle();
171
159
  }
172
160
 
173
161
  to(index) {
174
- this._activeElement = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
162
+ const items = this._getItems();
175
163
 
176
- const activeIndex = this._getItemIndex(this._activeElement);
177
-
178
- if (index > this._items.length - 1 || index < 0) {
164
+ if (index > items.length - 1 || index < 0) {
179
165
  return;
180
166
  }
181
167
 
@@ -184,42 +170,29 @@
184
170
  return;
185
171
  }
186
172
 
173
+ const activeIndex = this._getItemIndex(this._getActive());
174
+
187
175
  if (activeIndex === index) {
188
- this.pause();
189
- this.cycle();
190
176
  return;
191
177
  }
192
178
 
193
179
  const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;
194
180
 
195
- this._slide(order, this._items[index]);
196
- } // Private
197
-
198
-
199
- _getConfig(config) {
200
- config = { ...Default,
201
- ...Manipulator__default.default.getDataAttributes(this._element),
202
- ...(typeof config === 'object' ? config : {})
203
- };
204
- index.typeCheckConfig(NAME, config, DefaultType);
205
- return config;
181
+ this._slide(order, items[index]);
206
182
  }
207
183
 
208
- _handleSwipe() {
209
- const absDeltax = Math.abs(this.touchDeltaX);
210
-
211
- if (absDeltax <= SWIPE_THRESHOLD) {
212
- return;
184
+ dispose() {
185
+ if (this._swipeHelper) {
186
+ this._swipeHelper.dispose();
213
187
  }
214
188
 
215
- const direction = absDeltax / this.touchDeltaX;
216
- this.touchDeltaX = 0;
189
+ super.dispose();
190
+ } // Private
217
191
 
218
- if (!direction) {
219
- return;
220
- }
221
192
 
222
- this._slide(direction > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT);
193
+ _configAfterMerge(config) {
194
+ config.defaultInterval = config.interval;
195
+ return config;
223
196
  }
224
197
 
225
198
  _addEventListeners() {
@@ -228,72 +201,47 @@
228
201
  }
229
202
 
230
203
  if (this._config.pause === 'hover') {
231
- EventHandler__default.default.on(this._element, EVENT_MOUSEENTER, event => this.pause(event));
232
- EventHandler__default.default.on(this._element, EVENT_MOUSELEAVE, event => this.cycle(event));
204
+ EventHandler__default.default.on(this._element, EVENT_MOUSEENTER, () => this.pause());
205
+ EventHandler__default.default.on(this._element, EVENT_MOUSELEAVE, () => this._maybeEnableCycle());
233
206
  }
234
207
 
235
- if (this._config.touch && this._touchSupported) {
208
+ if (this._config.touch && Swipe__default.default.isSupported()) {
236
209
  this._addTouchEventListeners();
237
210
  }
238
211
  }
239
212
 
240
213
  _addTouchEventListeners() {
241
- const hasPointerPenTouch = event => {
242
- return this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH);
243
- };
244
-
245
- const start = event => {
246
- if (hasPointerPenTouch(event)) {
247
- this.touchStartX = event.clientX;
248
- } else if (!this._pointerEvent) {
249
- this.touchStartX = event.touches[0].clientX;
250
- }
251
- };
252
-
253
- const move = event => {
254
- // ensure swiping with one touch and not pinching
255
- this.touchDeltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this.touchStartX;
256
- };
257
-
258
- const end = event => {
259
- if (hasPointerPenTouch(event)) {
260
- this.touchDeltaX = event.clientX - this.touchStartX;
261
- }
214
+ for (const img of SelectorEngine__default.default.find(SELECTOR_ITEM_IMG, this._element)) {
215
+ EventHandler__default.default.on(img, EVENT_DRAG_START, event => event.preventDefault());
216
+ }
262
217
 
263
- this._handleSwipe();
218
+ const endCallBack = () => {
219
+ if (this._config.pause !== 'hover') {
220
+ return;
221
+ } // If it's a touch-enabled device, mouseenter/leave are fired as
222
+ // part of the mouse compatibility events on first tap - the carousel
223
+ // would stop cycling until user tapped out of it;
224
+ // here, we listen for touchend, explicitly pause the carousel
225
+ // (as if it's the second time we tap on it, mouseenter compat event
226
+ // is NOT fired) and after a timeout (to allow for mouse compatibility
227
+ // events to fire) we explicitly restart cycling
264
228
 
265
- if (this._config.pause === 'hover') {
266
- // If it's a touch-enabled device, mouseenter/leave are fired as
267
- // part of the mouse compatibility events on first tap - the carousel
268
- // would stop cycling until user tapped out of it;
269
- // here, we listen for touchend, explicitly pause the carousel
270
- // (as if it's the second time we tap on it, mouseenter compat event
271
- // is NOT fired) and after a timeout (to allow for mouse compatibility
272
- // events to fire) we explicitly restart cycling
273
- this.pause();
274
229
 
275
- if (this.touchTimeout) {
276
- clearTimeout(this.touchTimeout);
277
- }
230
+ this.pause();
278
231
 
279
- this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval);
232
+ if (this.touchTimeout) {
233
+ clearTimeout(this.touchTimeout);
280
234
  }
281
- };
282
235
 
283
- SelectorEngine__default.default.find(SELECTOR_ITEM_IMG, this._element).forEach(itemImg => {
284
- EventHandler__default.default.on(itemImg, EVENT_DRAG_START, event => event.preventDefault());
285
- });
286
-
287
- if (this._pointerEvent) {
288
- EventHandler__default.default.on(this._element, EVENT_POINTERDOWN, event => start(event));
289
- EventHandler__default.default.on(this._element, EVENT_POINTERUP, event => end(event));
236
+ this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval);
237
+ };
290
238
 
291
- this._element.classList.add(CLASS_NAME_POINTER_EVENT);
292
- } else {
293
- EventHandler__default.default.on(this._element, EVENT_TOUCHSTART, event => start(event));
294
- EventHandler__default.default.on(this._element, EVENT_TOUCHMOVE, event => move(event));
295
- EventHandler__default.default.on(this._element, EVENT_TOUCHEND, event => end(event));
296
- }
239
+ const swipeConfig = {
240
+ leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),
241
+ rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),
242
+ endCallback: endCallBack
243
+ };
244
+ this._swipeHelper = new Swipe__default.default(this._element, swipeConfig);
297
245
  }
298
246
 
299
247
  _keydown(event) {
@@ -306,95 +254,67 @@
306
254
  if (direction) {
307
255
  event.preventDefault();
308
256
 
309
- this._slide(direction);
257
+ this._slide(this._directionToOrder(direction));
310
258
  }
311
259
  }
312
260
 
313
261
  _getItemIndex(element) {
314
- this._items = element && element.parentNode ? SelectorEngine__default.default.find(SELECTOR_ITEM, element.parentNode) : [];
315
- return this._items.indexOf(element);
262
+ return this._getItems().indexOf(element);
316
263
  }
317
264
 
318
- _getItemByOrder(order, activeElement) {
319
- const isNext = order === ORDER_NEXT;
320
- return index.getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);
321
- }
322
-
323
- _triggerSlideEvent(relatedTarget, eventDirectionName) {
324
- const targetIndex = this._getItemIndex(relatedTarget);
325
-
326
- const fromIndex = this._getItemIndex(SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element));
265
+ _setActiveIndicatorElement(index) {
266
+ if (!this._indicatorsElement) {
267
+ return;
268
+ }
327
269
 
328
- return EventHandler__default.default.trigger(this._element, EVENT_SLIDE, {
329
- relatedTarget,
330
- direction: eventDirectionName,
331
- from: fromIndex,
332
- to: targetIndex
333
- });
334
- }
270
+ const activeIndicator = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE, this._indicatorsElement);
271
+ activeIndicator.classList.remove(CLASS_NAME_ACTIVE);
272
+ activeIndicator.removeAttribute('aria-current');
273
+ const newActiveIndicator = SelectorEngine__default.default.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement);
335
274
 
336
- _setActiveIndicatorElement(element) {
337
- if (this._indicatorsElement) {
338
- const activeIndicator = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE, this._indicatorsElement);
339
- activeIndicator.classList.remove(CLASS_NAME_ACTIVE);
340
- activeIndicator.removeAttribute('aria-current');
341
- const indicators = SelectorEngine__default.default.find(SELECTOR_INDICATOR, this._indicatorsElement);
342
-
343
- for (let i = 0; i < indicators.length; i++) {
344
- if (Number.parseInt(indicators[i].getAttribute('data-bs-slide-to'), 10) === this._getItemIndex(element)) {
345
- indicators[i].classList.add(CLASS_NAME_ACTIVE);
346
- indicators[i].setAttribute('aria-current', 'true');
347
- break;
348
- }
349
- }
275
+ if (newActiveIndicator) {
276
+ newActiveIndicator.classList.add(CLASS_NAME_ACTIVE);
277
+ newActiveIndicator.setAttribute('aria-current', 'true');
350
278
  }
351
279
  }
352
280
 
353
281
  _updateInterval() {
354
- const element = this._activeElement || SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
282
+ const element = this._activeElement || this._getActive();
355
283
 
356
284
  if (!element) {
357
285
  return;
358
286
  }
359
287
 
360
288
  const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);
361
-
362
- if (elementInterval) {
363
- this._config.defaultInterval = this._config.defaultInterval || this._config.interval;
364
- this._config.interval = elementInterval;
365
- } else {
366
- this._config.interval = this._config.defaultInterval || this._config.interval;
367
- }
289
+ this._config.interval = elementInterval || this._config.defaultInterval;
368
290
  }
369
291
 
370
- _slide(directionOrOrder, element) {
371
- const order = this._directionToOrder(directionOrOrder);
372
-
373
- const activeElement = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
374
-
375
- const activeElementIndex = this._getItemIndex(activeElement);
376
-
377
- const nextElement = element || this._getItemByOrder(order, activeElement);
292
+ _slide(order, element = null) {
293
+ if (this._isSliding) {
294
+ return;
295
+ }
378
296
 
379
- const nextElementIndex = this._getItemIndex(nextElement);
297
+ const activeElement = this._getActive();
380
298
 
381
- const isCycling = Boolean(this._interval);
382
299
  const isNext = order === ORDER_NEXT;
383
- const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;
384
- const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;
300
+ const nextElement = element || index.getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap);
385
301
 
386
- const eventDirectionName = this._orderToDirection(order);
387
-
388
- if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE)) {
389
- this._isSliding = false;
302
+ if (nextElement === activeElement) {
390
303
  return;
391
304
  }
392
305
 
393
- if (this._isSliding) {
394
- return;
395
- }
306
+ const nextElementIndex = this._getItemIndex(nextElement);
307
+
308
+ const triggerEvent = eventName => {
309
+ return EventHandler__default.default.trigger(this._element, eventName, {
310
+ relatedTarget: nextElement,
311
+ direction: this._orderToDirection(order),
312
+ from: this._getItemIndex(activeElement),
313
+ to: nextElementIndex
314
+ });
315
+ };
396
316
 
397
- const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
317
+ const slideEvent = triggerEvent(EVENT_SLIDE);
398
318
 
399
319
  if (slideEvent.defaultPrevented) {
400
320
  return;
@@ -402,60 +322,59 @@
402
322
 
403
323
  if (!activeElement || !nextElement) {
404
324
  // Some weirdness is happening, so we bail
325
+ // todo: change tests that use empty divs to avoid this check
405
326
  return;
406
327
  }
407
328
 
329
+ const isCycling = Boolean(this._interval);
330
+ this.pause();
408
331
  this._isSliding = true;
409
332
 
410
- if (isCycling) {
411
- this.pause();
412
- }
413
-
414
- this._setActiveIndicatorElement(nextElement);
333
+ this._setActiveIndicatorElement(nextElementIndex);
415
334
 
416
335
  this._activeElement = nextElement;
336
+ const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;
337
+ const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;
338
+ nextElement.classList.add(orderClassName);
339
+ index.reflow(nextElement);
340
+ activeElement.classList.add(directionalClassName);
341
+ nextElement.classList.add(directionalClassName);
417
342
 
418
- const triggerSlidEvent = () => {
419
- EventHandler__default.default.trigger(this._element, EVENT_SLID, {
420
- relatedTarget: nextElement,
421
- direction: eventDirectionName,
422
- from: activeElementIndex,
423
- to: nextElementIndex
424
- });
425
- };
426
-
427
- if (this._element.classList.contains(CLASS_NAME_SLIDE)) {
428
- nextElement.classList.add(orderClassName);
429
- index.reflow(nextElement);
430
- activeElement.classList.add(directionalClassName);
431
- nextElement.classList.add(directionalClassName);
432
-
433
- const completeCallBack = () => {
434
- nextElement.classList.remove(directionalClassName, orderClassName);
435
- nextElement.classList.add(CLASS_NAME_ACTIVE);
436
- activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName);
437
- this._isSliding = false;
438
- setTimeout(triggerSlidEvent, 0);
439
- };
440
-
441
- this._queueCallback(completeCallBack, activeElement, true);
442
- } else {
443
- activeElement.classList.remove(CLASS_NAME_ACTIVE);
343
+ const completeCallBack = () => {
344
+ nextElement.classList.remove(directionalClassName, orderClassName);
444
345
  nextElement.classList.add(CLASS_NAME_ACTIVE);
346
+ activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName);
445
347
  this._isSliding = false;
446
- triggerSlidEvent();
447
- }
348
+ triggerEvent(EVENT_SLID);
349
+ };
350
+
351
+ this._queueCallback(completeCallBack, activeElement, this._isAnimated());
448
352
 
449
353
  if (isCycling) {
450
354
  this.cycle();
451
355
  }
452
356
  }
453
357
 
454
- _directionToOrder(direction) {
455
- if (![DIRECTION_RIGHT, DIRECTION_LEFT].includes(direction)) {
456
- return direction;
358
+ _isAnimated() {
359
+ return this._element.classList.contains(CLASS_NAME_SLIDE);
360
+ }
361
+
362
+ _getActive() {
363
+ return SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
364
+ }
365
+
366
+ _getItems() {
367
+ return SelectorEngine__default.default.find(SELECTOR_ITEM, this._element);
368
+ }
369
+
370
+ _clearInterval() {
371
+ if (this._interval) {
372
+ clearInterval(this._interval);
373
+ this._interval = null;
457
374
  }
375
+ }
458
376
 
377
+ _directionToOrder(direction) {
459
378
  if (index.isRTL()) {
460
379
  return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;
461
380
  }
@@ -464,10 +383,6 @@
464
383
  }
465
384
 
466
385
  _orderToDirection(order) {
467
- if (![ORDER_NEXT, ORDER_PREV].includes(order)) {
468
- return order;
469
- }
470
-
471
386
  if (index.isRTL()) {
472
387
  return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;
473
388
  }
@@ -476,86 +391,71 @@
476
391
  } // Static
477
392
 
478
393
 
479
- static carouselInterface(element, config) {
480
- const data = Carousel.getOrCreateInstance(element, config);
481
- let {
482
- _config
483
- } = data;
484
-
485
- if (typeof config === 'object') {
486
- _config = { ..._config,
487
- ...config
488
- };
489
- }
490
-
491
- const action = typeof config === 'string' ? config : _config.slide;
394
+ static jQueryInterface(config) {
395
+ return this.each(function () {
396
+ const data = Carousel.getOrCreateInstance(this, config);
492
397
 
493
- if (typeof config === 'number') {
494
- data.to(config);
495
- } else if (typeof action === 'string') {
496
- if (typeof data[action] === 'undefined') {
497
- throw new TypeError(`No method named "${action}"`);
398
+ if (typeof config === 'number') {
399
+ data.to(config);
400
+ return;
498
401
  }
499
402
 
500
- data[action]();
501
- } else if (_config.interval && _config.ride) {
502
- data.pause();
503
- data.cycle();
504
- }
505
- }
403
+ if (typeof config === 'string') {
404
+ if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
405
+ throw new TypeError(`No method named "${config}"`);
406
+ }
506
407
 
507
- static jQueryInterface(config) {
508
- return this.each(function () {
509
- Carousel.carouselInterface(this, config);
408
+ data[config]();
409
+ }
510
410
  });
511
411
  }
512
412
 
513
- static dataApiClickHandler(event) {
514
- const target = index.getElementFromSelector(this);
413
+ }
414
+ /**
415
+ * Data API implementation
416
+ */
515
417
 
516
- if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
517
- return;
518
- }
519
418
 
520
- const config = { ...Manipulator__default.default.getDataAttributes(target),
521
- ...Manipulator__default.default.getDataAttributes(this)
522
- };
523
- const slideIndex = this.getAttribute('data-bs-slide-to');
419
+ EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, function (event) {
420
+ const target = index.getElementFromSelector(this);
524
421
 
525
- if (slideIndex) {
526
- config.interval = false;
527
- }
422
+ if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
423
+ return;
424
+ }
528
425
 
529
- Carousel.carouselInterface(target, config);
426
+ event.preventDefault();
427
+ const carousel = Carousel.getOrCreateInstance(target);
428
+ const slideIndex = this.getAttribute('data-bs-slide-to');
530
429
 
531
- if (slideIndex) {
532
- Carousel.getInstance(target).to(slideIndex);
533
- }
430
+ if (slideIndex) {
431
+ carousel.to(slideIndex);
432
+
433
+ carousel._maybeEnableCycle();
534
434
 
535
- event.preventDefault();
435
+ return;
536
436
  }
537
437
 
538
- }
539
- /**
540
- * ------------------------------------------------------------------------
541
- * Data Api implementation
542
- * ------------------------------------------------------------------------
543
- */
438
+ if (Manipulator__default.default.getDataAttribute(this, 'slide') === 'next') {
439
+ carousel.next();
440
+
441
+ carousel._maybeEnableCycle();
544
442
 
443
+ return;
444
+ }
545
445
 
546
- EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler);
446
+ carousel.prev();
447
+
448
+ carousel._maybeEnableCycle();
449
+ });
547
450
  EventHandler__default.default.on(window, EVENT_LOAD_DATA_API, () => {
548
451
  const carousels = SelectorEngine__default.default.find(SELECTOR_DATA_RIDE);
549
452
 
550
- for (let i = 0, len = carousels.length; i < len; i++) {
551
- Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));
453
+ for (const carousel of carousels) {
454
+ Carousel.getOrCreateInstance(carousel);
552
455
  }
553
456
  });
554
457
  /**
555
- * ------------------------------------------------------------------------
556
458
  * jQuery
557
- * ------------------------------------------------------------------------
558
- * add .Carousel to jQuery only if jQuery is present
559
459
  */
560
460
 
561
461
  index.defineJQueryPlugin(Carousel);