@coreui/coreui 4.1.6 → 4.2.2

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