administrate-bootstrap-theme 0.1.0 → 0.1.9

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