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,319 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * Bootstrap (v5.0.0-beta3): scrollspy.js
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import {
9
+ defineJQueryPlugin,
10
+ getSelectorFromElement,
11
+ getUID,
12
+ isElement,
13
+ typeCheckConfig
14
+ } from './util/index'
15
+ import Data from './dom/data'
16
+ import EventHandler from './dom/event-handler'
17
+ import Manipulator from './dom/manipulator'
18
+ import SelectorEngine from './dom/selector-engine'
19
+ import BaseComponent from './base-component'
20
+
21
+ /**
22
+ * ------------------------------------------------------------------------
23
+ * Constants
24
+ * ------------------------------------------------------------------------
25
+ */
26
+
27
+ const NAME = 'scrollspy'
28
+ const DATA_KEY = 'bs.scrollspy'
29
+ const EVENT_KEY = `.${DATA_KEY}`
30
+ const DATA_API_KEY = '.data-api'
31
+
32
+ const Default = {
33
+ offset: 10,
34
+ method: 'auto',
35
+ target: ''
36
+ }
37
+
38
+ const DefaultType = {
39
+ offset: 'number',
40
+ method: 'string',
41
+ target: '(string|element)'
42
+ }
43
+
44
+ const EVENT_ACTIVATE = `activate${EVENT_KEY}`
45
+ const EVENT_SCROLL = `scroll${EVENT_KEY}`
46
+ const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
47
+
48
+ const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'
49
+ const CLASS_NAME_ACTIVE = 'active'
50
+
51
+ const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]'
52
+ const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'
53
+ const SELECTOR_NAV_LINKS = '.nav-link'
54
+ const SELECTOR_NAV_ITEMS = '.nav-item'
55
+ const SELECTOR_LIST_ITEMS = '.list-group-item'
56
+ const SELECTOR_DROPDOWN = '.dropdown'
57
+ const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'
58
+
59
+ const METHOD_OFFSET = 'offset'
60
+ const METHOD_POSITION = 'position'
61
+
62
+ /**
63
+ * ------------------------------------------------------------------------
64
+ * Class Definition
65
+ * ------------------------------------------------------------------------
66
+ */
67
+
68
+ class ScrollSpy extends BaseComponent {
69
+ constructor(element, config) {
70
+ super(element)
71
+ this._scrollElement = this._element.tagName === 'BODY' ? window : this._element
72
+ this._config = this._getConfig(config)
73
+ this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`
74
+ this._offsets = []
75
+ this._targets = []
76
+ this._activeTarget = null
77
+ this._scrollHeight = 0
78
+
79
+ EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process())
80
+
81
+ this.refresh()
82
+ this._process()
83
+ }
84
+
85
+ // Getters
86
+
87
+ static get Default() {
88
+ return Default
89
+ }
90
+
91
+ static get DATA_KEY() {
92
+ return DATA_KEY
93
+ }
94
+
95
+ // Public
96
+
97
+ refresh() {
98
+ const autoMethod = this._scrollElement === this._scrollElement.window ?
99
+ METHOD_OFFSET :
100
+ METHOD_POSITION
101
+
102
+ const offsetMethod = this._config.method === 'auto' ?
103
+ autoMethod :
104
+ this._config.method
105
+
106
+ const offsetBase = offsetMethod === METHOD_POSITION ?
107
+ this._getScrollTop() :
108
+ 0
109
+
110
+ this._offsets = []
111
+ this._targets = []
112
+ this._scrollHeight = this._getScrollHeight()
113
+
114
+ const targets = SelectorEngine.find(this._selector)
115
+
116
+ targets.map(element => {
117
+ const targetSelector = getSelectorFromElement(element)
118
+ const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null
119
+
120
+ if (target) {
121
+ const targetBCR = target.getBoundingClientRect()
122
+ if (targetBCR.width || targetBCR.height) {
123
+ return [
124
+ Manipulator[offsetMethod](target).top + offsetBase,
125
+ targetSelector
126
+ ]
127
+ }
128
+ }
129
+
130
+ return null
131
+ })
132
+ .filter(item => item)
133
+ .sort((a, b) => a[0] - b[0])
134
+ .forEach(item => {
135
+ this._offsets.push(item[0])
136
+ this._targets.push(item[1])
137
+ })
138
+ }
139
+
140
+ dispose() {
141
+ super.dispose()
142
+ EventHandler.off(this._scrollElement, EVENT_KEY)
143
+
144
+ this._scrollElement = null
145
+ this._config = null
146
+ this._selector = null
147
+ this._offsets = null
148
+ this._targets = null
149
+ this._activeTarget = null
150
+ this._scrollHeight = null
151
+ }
152
+
153
+ // Private
154
+
155
+ _getConfig(config) {
156
+ config = {
157
+ ...Default,
158
+ ...(typeof config === 'object' && config ? config : {})
159
+ }
160
+
161
+ if (typeof config.target !== 'string' && isElement(config.target)) {
162
+ let { id } = config.target
163
+ if (!id) {
164
+ id = getUID(NAME)
165
+ config.target.id = id
166
+ }
167
+
168
+ config.target = `#${id}`
169
+ }
170
+
171
+ typeCheckConfig(NAME, config, DefaultType)
172
+
173
+ return config
174
+ }
175
+
176
+ _getScrollTop() {
177
+ return this._scrollElement === window ?
178
+ this._scrollElement.pageYOffset :
179
+ this._scrollElement.scrollTop
180
+ }
181
+
182
+ _getScrollHeight() {
183
+ return this._scrollElement.scrollHeight || Math.max(
184
+ document.body.scrollHeight,
185
+ document.documentElement.scrollHeight
186
+ )
187
+ }
188
+
189
+ _getOffsetHeight() {
190
+ return this._scrollElement === window ?
191
+ window.innerHeight :
192
+ this._scrollElement.getBoundingClientRect().height
193
+ }
194
+
195
+ _process() {
196
+ const scrollTop = this._getScrollTop() + this._config.offset
197
+ const scrollHeight = this._getScrollHeight()
198
+ const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight()
199
+
200
+ if (this._scrollHeight !== scrollHeight) {
201
+ this.refresh()
202
+ }
203
+
204
+ if (scrollTop >= maxScroll) {
205
+ const target = this._targets[this._targets.length - 1]
206
+
207
+ if (this._activeTarget !== target) {
208
+ this._activate(target)
209
+ }
210
+
211
+ return
212
+ }
213
+
214
+ if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
215
+ this._activeTarget = null
216
+ this._clear()
217
+ return
218
+ }
219
+
220
+ for (let i = this._offsets.length; i--;) {
221
+ const isActiveTarget = this._activeTarget !== this._targets[i] &&
222
+ scrollTop >= this._offsets[i] &&
223
+ (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1])
224
+
225
+ if (isActiveTarget) {
226
+ this._activate(this._targets[i])
227
+ }
228
+ }
229
+ }
230
+
231
+ _activate(target) {
232
+ this._activeTarget = target
233
+
234
+ this._clear()
235
+
236
+ const queries = this._selector.split(',')
237
+ .map(selector => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`)
238
+
239
+ const link = SelectorEngine.findOne(queries.join(','))
240
+
241
+ if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
242
+ SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, link.closest(SELECTOR_DROPDOWN))
243
+ .classList.add(CLASS_NAME_ACTIVE)
244
+
245
+ link.classList.add(CLASS_NAME_ACTIVE)
246
+ } else {
247
+ // Set triggered link as active
248
+ link.classList.add(CLASS_NAME_ACTIVE)
249
+
250
+ SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP)
251
+ .forEach(listGroup => {
252
+ // Set triggered links parents as active
253
+ // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
254
+ SelectorEngine.prev(listGroup, `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`)
255
+ .forEach(item => item.classList.add(CLASS_NAME_ACTIVE))
256
+
257
+ // Handle special case when .nav-link is inside .nav-item
258
+ SelectorEngine.prev(listGroup, SELECTOR_NAV_ITEMS)
259
+ .forEach(navItem => {
260
+ SelectorEngine.children(navItem, SELECTOR_NAV_LINKS)
261
+ .forEach(item => item.classList.add(CLASS_NAME_ACTIVE))
262
+ })
263
+ })
264
+ }
265
+
266
+ EventHandler.trigger(this._scrollElement, EVENT_ACTIVATE, {
267
+ relatedTarget: target
268
+ })
269
+ }
270
+
271
+ _clear() {
272
+ SelectorEngine.find(this._selector)
273
+ .filter(node => node.classList.contains(CLASS_NAME_ACTIVE))
274
+ .forEach(node => node.classList.remove(CLASS_NAME_ACTIVE))
275
+ }
276
+
277
+ // Static
278
+
279
+ static jQueryInterface(config) {
280
+ return this.each(function () {
281
+ let data = Data.get(this, DATA_KEY)
282
+ const _config = typeof config === 'object' && config
283
+
284
+ if (!data) {
285
+ data = new ScrollSpy(this, _config)
286
+ }
287
+
288
+ if (typeof config === 'string') {
289
+ if (typeof data[config] === 'undefined') {
290
+ throw new TypeError(`No method named "${config}"`)
291
+ }
292
+
293
+ data[config]()
294
+ }
295
+ })
296
+ }
297
+ }
298
+
299
+ /**
300
+ * ------------------------------------------------------------------------
301
+ * Data Api implementation
302
+ * ------------------------------------------------------------------------
303
+ */
304
+
305
+ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
306
+ SelectorEngine.find(SELECTOR_DATA_SPY)
307
+ .forEach(spy => new ScrollSpy(spy, Manipulator.getDataAttributes(spy)))
308
+ })
309
+
310
+ /**
311
+ * ------------------------------------------------------------------------
312
+ * jQuery
313
+ * ------------------------------------------------------------------------
314
+ * add .ScrollSpy to jQuery only if jQuery is present
315
+ */
316
+
317
+ defineJQueryPlugin(NAME, ScrollSpy)
318
+
319
+ export default ScrollSpy
@@ -0,0 +1,220 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * Bootstrap (v5.0.0-beta3): tab.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
+ isDisabled,
14
+ reflow
15
+ } from './util/index'
16
+ import Data from './dom/data'
17
+ import EventHandler from './dom/event-handler'
18
+ import SelectorEngine from './dom/selector-engine'
19
+ import BaseComponent from './base-component'
20
+
21
+ /**
22
+ * ------------------------------------------------------------------------
23
+ * Constants
24
+ * ------------------------------------------------------------------------
25
+ */
26
+
27
+ const NAME = 'tab'
28
+ const DATA_KEY = 'bs.tab'
29
+ const EVENT_KEY = `.${DATA_KEY}`
30
+ const DATA_API_KEY = '.data-api'
31
+
32
+ const EVENT_HIDE = `hide${EVENT_KEY}`
33
+ const EVENT_HIDDEN = `hidden${EVENT_KEY}`
34
+ const EVENT_SHOW = `show${EVENT_KEY}`
35
+ const EVENT_SHOWN = `shown${EVENT_KEY}`
36
+ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
37
+
38
+ const CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu'
39
+ const CLASS_NAME_ACTIVE = 'active'
40
+ const CLASS_NAME_FADE = 'fade'
41
+ const CLASS_NAME_SHOW = 'show'
42
+
43
+ const SELECTOR_DROPDOWN = '.dropdown'
44
+ const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'
45
+ const SELECTOR_ACTIVE = '.active'
46
+ const SELECTOR_ACTIVE_UL = ':scope > li > .active'
47
+ const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]'
48
+ const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'
49
+ const SELECTOR_DROPDOWN_ACTIVE_CHILD = ':scope > .dropdown-menu .active'
50
+
51
+ /**
52
+ * ------------------------------------------------------------------------
53
+ * Class Definition
54
+ * ------------------------------------------------------------------------
55
+ */
56
+
57
+ class Tab extends BaseComponent {
58
+ // Getters
59
+
60
+ static get DATA_KEY() {
61
+ return DATA_KEY
62
+ }
63
+
64
+ // Public
65
+
66
+ show() {
67
+ if ((this._element.parentNode &&
68
+ this._element.parentNode.nodeType === Node.ELEMENT_NODE &&
69
+ this._element.classList.contains(CLASS_NAME_ACTIVE)) ||
70
+ isDisabled(this._element)) {
71
+ return
72
+ }
73
+
74
+ let previous
75
+ const target = getElementFromSelector(this._element)
76
+ const listElement = this._element.closest(SELECTOR_NAV_LIST_GROUP)
77
+
78
+ if (listElement) {
79
+ const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE
80
+ previous = SelectorEngine.find(itemSelector, listElement)
81
+ previous = previous[previous.length - 1]
82
+ }
83
+
84
+ const hideEvent = previous ?
85
+ EventHandler.trigger(previous, EVENT_HIDE, {
86
+ relatedTarget: this._element
87
+ }) :
88
+ null
89
+
90
+ const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, {
91
+ relatedTarget: previous
92
+ })
93
+
94
+ if (showEvent.defaultPrevented || (hideEvent !== null && hideEvent.defaultPrevented)) {
95
+ return
96
+ }
97
+
98
+ this._activate(this._element, listElement)
99
+
100
+ const complete = () => {
101
+ EventHandler.trigger(previous, EVENT_HIDDEN, {
102
+ relatedTarget: this._element
103
+ })
104
+ EventHandler.trigger(this._element, EVENT_SHOWN, {
105
+ relatedTarget: previous
106
+ })
107
+ }
108
+
109
+ if (target) {
110
+ this._activate(target, target.parentNode, complete)
111
+ } else {
112
+ complete()
113
+ }
114
+ }
115
+
116
+ // Private
117
+
118
+ _activate(element, container, callback) {
119
+ const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ?
120
+ SelectorEngine.find(SELECTOR_ACTIVE_UL, container) :
121
+ SelectorEngine.children(container, SELECTOR_ACTIVE)
122
+
123
+ const active = activeElements[0]
124
+ const isTransitioning = callback && (active && active.classList.contains(CLASS_NAME_FADE))
125
+
126
+ const complete = () => this._transitionComplete(element, active, callback)
127
+
128
+ if (active && isTransitioning) {
129
+ const transitionDuration = getTransitionDurationFromElement(active)
130
+ active.classList.remove(CLASS_NAME_SHOW)
131
+
132
+ EventHandler.one(active, 'transitionend', complete)
133
+ emulateTransitionEnd(active, transitionDuration)
134
+ } else {
135
+ complete()
136
+ }
137
+ }
138
+
139
+ _transitionComplete(element, active, callback) {
140
+ if (active) {
141
+ active.classList.remove(CLASS_NAME_ACTIVE)
142
+
143
+ const dropdownChild = SelectorEngine.findOne(SELECTOR_DROPDOWN_ACTIVE_CHILD, active.parentNode)
144
+
145
+ if (dropdownChild) {
146
+ dropdownChild.classList.remove(CLASS_NAME_ACTIVE)
147
+ }
148
+
149
+ if (active.getAttribute('role') === 'tab') {
150
+ active.setAttribute('aria-selected', false)
151
+ }
152
+ }
153
+
154
+ element.classList.add(CLASS_NAME_ACTIVE)
155
+ if (element.getAttribute('role') === 'tab') {
156
+ element.setAttribute('aria-selected', true)
157
+ }
158
+
159
+ reflow(element)
160
+
161
+ if (element.classList.contains(CLASS_NAME_FADE)) {
162
+ element.classList.add(CLASS_NAME_SHOW)
163
+ }
164
+
165
+ if (element.parentNode && element.parentNode.classList.contains(CLASS_NAME_DROPDOWN_MENU)) {
166
+ const dropdownElement = element.closest(SELECTOR_DROPDOWN)
167
+
168
+ if (dropdownElement) {
169
+ SelectorEngine.find(SELECTOR_DROPDOWN_TOGGLE)
170
+ .forEach(dropdown => dropdown.classList.add(CLASS_NAME_ACTIVE))
171
+ }
172
+
173
+ element.setAttribute('aria-expanded', true)
174
+ }
175
+
176
+ if (callback) {
177
+ callback()
178
+ }
179
+ }
180
+
181
+ // Static
182
+
183
+ static jQueryInterface(config) {
184
+ return this.each(function () {
185
+ const data = Data.get(this, DATA_KEY) || new Tab(this)
186
+
187
+ if (typeof config === 'string') {
188
+ if (typeof data[config] === 'undefined') {
189
+ throw new TypeError(`No method named "${config}"`)
190
+ }
191
+
192
+ data[config]()
193
+ }
194
+ })
195
+ }
196
+ }
197
+
198
+ /**
199
+ * ------------------------------------------------------------------------
200
+ * Data Api implementation
201
+ * ------------------------------------------------------------------------
202
+ */
203
+
204
+ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
205
+ event.preventDefault()
206
+
207
+ const data = Data.get(this, DATA_KEY) || new Tab(this)
208
+ data.show()
209
+ })
210
+
211
+ /**
212
+ * ------------------------------------------------------------------------
213
+ * jQuery
214
+ * ------------------------------------------------------------------------
215
+ * add .Tab to jQuery only if jQuery is present
216
+ */
217
+
218
+ defineJQueryPlugin(NAME, Tab)
219
+
220
+ export default Tab