bootstrap 4.3.1 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +55 -0
  3. data/CHANGELOG.md +2 -14
  4. data/README.md +28 -5
  5. data/assets/javascripts/bootstrap/alert.js +54 -163
  6. data/assets/javascripts/bootstrap/base-component.js +83 -0
  7. data/assets/javascripts/bootstrap/button.js +44 -152
  8. data/assets/javascripts/bootstrap/carousel.js +289 -569
  9. data/assets/javascripts/bootstrap/collapse.js +170 -349
  10. data/assets/javascripts/bootstrap/dom/data.js +62 -0
  11. data/assets/javascripts/bootstrap/dom/event-handler.js +236 -0
  12. data/assets/javascripts/bootstrap/dom/manipulator.js +71 -0
  13. data/assets/javascripts/bootstrap/dom/selector-engine.js +103 -0
  14. data/assets/javascripts/bootstrap/dropdown.js +303 -496
  15. data/assets/javascripts/bootstrap/modal.js +229 -559
  16. data/assets/javascripts/bootstrap/offcanvas.js +245 -0
  17. data/assets/javascripts/bootstrap/popover.js +61 -226
  18. data/assets/javascripts/bootstrap/scrollspy.js +217 -317
  19. data/assets/javascripts/bootstrap/tab.js +220 -212
  20. data/assets/javascripts/bootstrap/toast.js +145 -229
  21. data/assets/javascripts/bootstrap/tooltip.js +421 -782
  22. data/assets/javascripts/bootstrap/util/backdrop.js +139 -0
  23. data/assets/javascripts/bootstrap/util/component-functions.js +41 -0
  24. data/assets/javascripts/bootstrap/util/config.js +67 -0
  25. data/assets/javascripts/bootstrap/util/focustrap.js +113 -0
  26. data/assets/javascripts/bootstrap/util/index.js +281 -0
  27. data/assets/javascripts/bootstrap/util/sanitizer.js +110 -0
  28. data/assets/javascripts/bootstrap/util/scrollbar.js +112 -0
  29. data/assets/javascripts/bootstrap/util/swipe.js +134 -0
  30. data/assets/javascripts/bootstrap/util/template-factory.js +150 -0
  31. data/assets/javascripts/bootstrap-global-this-define.js +6 -0
  32. data/assets/javascripts/bootstrap-global-this-undefine.js +2 -0
  33. data/assets/javascripts/bootstrap-sprockets.js +23 -7
  34. data/assets/javascripts/bootstrap.js +3690 -3639
  35. data/assets/javascripts/bootstrap.min.js +4 -4
  36. data/assets/stylesheets/_bootstrap-grid.scss +53 -20
  37. data/assets/stylesheets/_bootstrap-reboot.scss +5 -7
  38. data/assets/stylesheets/_bootstrap.scss +21 -13
  39. data/assets/stylesheets/bootstrap/_accordion.scss +158 -0
  40. data/assets/stylesheets/bootstrap/_alert.scss +32 -15
  41. data/assets/stylesheets/bootstrap/_badge.scss +15 -31
  42. data/assets/stylesheets/bootstrap/_breadcrumb.scss +23 -24
  43. data/assets/stylesheets/bootstrap/_button-group.scss +27 -48
  44. data/assets/stylesheets/bootstrap/_buttons.scss +139 -69
  45. data/assets/stylesheets/bootstrap/_card.scss +91 -141
  46. data/assets/stylesheets/bootstrap/_carousel.scss +86 -39
  47. data/assets/stylesheets/bootstrap/_close.scss +51 -29
  48. data/assets/stylesheets/bootstrap/_containers.scss +41 -0
  49. data/assets/stylesheets/bootstrap/_dropdown.scss +131 -72
  50. data/assets/stylesheets/bootstrap/_forms.scss +9 -330
  51. data/assets/stylesheets/bootstrap/_functions.scss +244 -28
  52. data/assets/stylesheets/bootstrap/_grid.scss +18 -31
  53. data/assets/stylesheets/bootstrap/_helpers.scss +12 -0
  54. data/assets/stylesheets/bootstrap/_images.scss +3 -3
  55. data/assets/stylesheets/bootstrap/_list-group.scss +101 -53
  56. data/assets/stylesheets/bootstrap/_maps.scss +174 -0
  57. data/assets/stylesheets/bootstrap/_mixins.scss +13 -18
  58. data/assets/stylesheets/bootstrap/_modal.scss +120 -112
  59. data/assets/stylesheets/bootstrap/_nav.scss +113 -24
  60. data/assets/stylesheets/bootstrap/_navbar.scss +145 -150
  61. data/assets/stylesheets/bootstrap/_offcanvas.scss +146 -0
  62. data/assets/stylesheets/bootstrap/_pagination.scss +74 -38
  63. data/assets/stylesheets/bootstrap/_placeholders.scss +51 -0
  64. data/assets/stylesheets/bootstrap/_popover.scss +99 -74
  65. data/assets/stylesheets/bootstrap/_progress.scss +40 -15
  66. data/assets/stylesheets/bootstrap/_reboot.scss +342 -215
  67. data/assets/stylesheets/bootstrap/_root.scss +174 -9
  68. data/assets/stylesheets/bootstrap/_spinners.scss +52 -22
  69. data/assets/stylesheets/bootstrap/_tables.scss +101 -115
  70. data/assets/stylesheets/bootstrap/_toasts.scss +54 -25
  71. data/assets/stylesheets/bootstrap/_tooltip.scss +67 -63
  72. data/assets/stylesheets/bootstrap/_transitions.scss +8 -1
  73. data/assets/stylesheets/bootstrap/_type.scss +42 -61
  74. data/assets/stylesheets/bootstrap/_utilities.scss +806 -17
  75. data/assets/stylesheets/bootstrap/_variables-dark.scss +85 -0
  76. data/assets/stylesheets/bootstrap/_variables.scss +1235 -615
  77. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +19 -0
  78. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +94 -0
  79. data/assets/stylesheets/bootstrap/forms/_form-check.scss +188 -0
  80. data/assets/stylesheets/bootstrap/forms/_form-control.scss +214 -0
  81. data/assets/stylesheets/bootstrap/forms/_form-range.scss +91 -0
  82. data/assets/stylesheets/bootstrap/forms/_form-select.scss +80 -0
  83. data/assets/stylesheets/bootstrap/forms/_form-text.scss +11 -0
  84. data/assets/stylesheets/bootstrap/forms/_input-group.scss +132 -0
  85. data/assets/stylesheets/bootstrap/forms/_labels.scss +36 -0
  86. data/assets/stylesheets/bootstrap/forms/_validation.scss +12 -0
  87. data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +8 -0
  88. data/assets/stylesheets/bootstrap/helpers/_colored-links.scss +30 -0
  89. data/assets/stylesheets/bootstrap/helpers/_focus-ring.scss +5 -0
  90. data/assets/stylesheets/bootstrap/helpers/_icon-link.scss +25 -0
  91. data/assets/stylesheets/bootstrap/helpers/_position.scss +36 -0
  92. data/assets/stylesheets/bootstrap/helpers/_ratio.scss +26 -0
  93. data/assets/stylesheets/bootstrap/helpers/_stacks.scss +15 -0
  94. data/assets/stylesheets/bootstrap/helpers/_stretched-link.scss +15 -0
  95. data/assets/stylesheets/bootstrap/helpers/_text-truncation.scss +7 -0
  96. data/assets/stylesheets/bootstrap/helpers/_visually-hidden.scss +8 -0
  97. data/assets/stylesheets/bootstrap/helpers/_vr.scss +8 -0
  98. data/assets/stylesheets/bootstrap/mixins/_alert.scss +11 -6
  99. data/assets/stylesheets/bootstrap/mixins/_backdrop.scss +14 -0
  100. data/assets/stylesheets/bootstrap/mixins/_banner.scss +7 -0
  101. data/assets/stylesheets/bootstrap/mixins/_border-radius.scss +37 -22
  102. data/assets/stylesheets/bootstrap/mixins/_box-shadow.scss +7 -9
  103. data/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +20 -16
  104. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +60 -97
  105. data/assets/stylesheets/bootstrap/mixins/_caret.scss +34 -27
  106. data/assets/stylesheets/bootstrap/mixins/_clearfix.scss +2 -0
  107. data/assets/stylesheets/bootstrap/mixins/_color-mode.scss +21 -0
  108. data/assets/stylesheets/bootstrap/mixins/_color-scheme.scss +7 -0
  109. data/assets/stylesheets/bootstrap/mixins/_container.scss +11 -0
  110. data/assets/stylesheets/bootstrap/mixins/_forms.scss +77 -116
  111. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +13 -11
  112. data/assets/stylesheets/bootstrap/mixins/_grid.scss +133 -33
  113. data/assets/stylesheets/bootstrap/mixins/_image.scss +0 -20
  114. data/assets/stylesheets/bootstrap/mixins/_list-group.scss +7 -2
  115. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +7 -19
  116. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +2 -2
  117. data/assets/stylesheets/bootstrap/mixins/_table-variants.scss +24 -0
  118. data/assets/stylesheets/bootstrap/mixins/_transition.scss +18 -8
  119. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +97 -0
  120. data/assets/stylesheets/bootstrap/mixins/_visually-hidden.scss +33 -0
  121. data/assets/stylesheets/bootstrap/utilities/_api.scss +47 -0
  122. data/assets/stylesheets/bootstrap/vendor/_rfs.scss +276 -132
  123. data/bootstrap.gemspec +4 -6
  124. data/lib/bootstrap/version.rb +2 -2
  125. data/tasks/updater/js.rb +31 -7
  126. data/tasks/updater/network.rb +10 -4
  127. data/tasks/updater/scss.rb +1 -1
  128. data/tasks/updater.rb +2 -2
  129. data/test/dummy_rails/app/assets/config/manifest.js +3 -0
  130. data/test/dummy_rails/app/assets/javascripts/application.js +4 -3
  131. data/test/dummy_rails/app/assets/stylesheets/.browserslistrc +1 -0
  132. data/test/dummy_rails/app/views/layouts/application.html.erb +3 -1
  133. data/test/dummy_rails/app/views/pages/root.html +89 -0
  134. data/test/dummy_rails/config/application.rb +0 -3
  135. data/test/gemfiles/rails_5_2.gemfile +8 -0
  136. data/test/gemfiles/rails_6_0.gemfile +7 -0
  137. data/test/gemfiles/rails_6_1.gemfile +7 -0
  138. data/test/gemfiles/rails_7_0.gemfile +7 -0
  139. data/test/support/dummy_rails_integration.rb +3 -1
  140. data/test/test_helper.rb +18 -12
  141. metadata +86 -84
  142. data/.travis.yml +0 -17
  143. data/assets/javascripts/bootstrap/util.js +0 -171
  144. data/assets/stylesheets/bootstrap/_code.scss +0 -48
  145. data/assets/stylesheets/bootstrap/_custom-forms.scss +0 -507
  146. data/assets/stylesheets/bootstrap/_input-group.scss +0 -193
  147. data/assets/stylesheets/bootstrap/_jumbotron.scss +0 -17
  148. data/assets/stylesheets/bootstrap/_media.scss +0 -8
  149. data/assets/stylesheets/bootstrap/_print.scss +0 -141
  150. data/assets/stylesheets/bootstrap/mixins/_background-variant.scss +0 -21
  151. data/assets/stylesheets/bootstrap/mixins/_badge.scss +0 -17
  152. data/assets/stylesheets/bootstrap/mixins/_float.scss +0 -14
  153. data/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +0 -66
  154. data/assets/stylesheets/bootstrap/mixins/_hover.scss +0 -37
  155. data/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +0 -10
  156. data/assets/stylesheets/bootstrap/mixins/_screen-reader.scss +0 -33
  157. data/assets/stylesheets/bootstrap/mixins/_size.scss +0 -7
  158. data/assets/stylesheets/bootstrap/mixins/_table-row.scss +0 -39
  159. data/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +0 -16
  160. data/assets/stylesheets/bootstrap/mixins/_text-hide.scss +0 -11
  161. data/assets/stylesheets/bootstrap/mixins/_visibility.scss +0 -8
  162. data/assets/stylesheets/bootstrap/utilities/_align.scss +0 -8
  163. data/assets/stylesheets/bootstrap/utilities/_background.scss +0 -19
  164. data/assets/stylesheets/bootstrap/utilities/_borders.scss +0 -75
  165. data/assets/stylesheets/bootstrap/utilities/_display.scss +0 -26
  166. data/assets/stylesheets/bootstrap/utilities/_embed.scss +0 -39
  167. data/assets/stylesheets/bootstrap/utilities/_flex.scss +0 -51
  168. data/assets/stylesheets/bootstrap/utilities/_float.scss +0 -11
  169. data/assets/stylesheets/bootstrap/utilities/_overflow.scss +0 -5
  170. data/assets/stylesheets/bootstrap/utilities/_position.scss +0 -32
  171. data/assets/stylesheets/bootstrap/utilities/_screenreaders.scss +0 -11
  172. data/assets/stylesheets/bootstrap/utilities/_shadows.scss +0 -6
  173. data/assets/stylesheets/bootstrap/utilities/_sizing.scss +0 -20
  174. data/assets/stylesheets/bootstrap/utilities/_spacing.scss +0 -73
  175. data/assets/stylesheets/bootstrap/utilities/_stretched-link.scss +0 -19
  176. data/assets/stylesheets/bootstrap/utilities/_text.scss +0 -72
  177. data/assets/stylesheets/bootstrap/utilities/_visibility.scss +0 -13
  178. data/test/dummy_rails/app/views/pages/root.html.slim +0 -58
  179. /data/assets/stylesheets/bootstrap/{utilities → helpers}/_clearfix.scss +0 -0
@@ -1,267 +1,275 @@
1
1
  /*!
2
- * Bootstrap tab.js v4.3.1 (https://getbootstrap.com/)
3
- * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2
+ * Bootstrap tab.js v5.3.0 (https://getbootstrap.com/)
3
+ * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  */
6
6
  (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
8
- typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
9
- (global = global || self, global.Tab = factory(global.jQuery, global.Util));
10
- }(this, function ($, Util) { 'use strict';
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./dom/selector-engine.js'), require('./util/index.js')) :
8
+ typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './dom/selector-engine', './util/index'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tab = factory(global.BaseComponent, global.EventHandler, global.SelectorEngine, global.Index));
10
+ })(this, (function (BaseComponent, EventHandler, SelectorEngine, index_js) { 'use strict';
11
11
 
12
- $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
13
- Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;
14
-
15
- function _defineProperties(target, props) {
16
- for (var i = 0; i < props.length; i++) {
17
- var descriptor = props[i];
18
- descriptor.enumerable = descriptor.enumerable || false;
19
- descriptor.configurable = true;
20
- if ("value" in descriptor) descriptor.writable = true;
21
- Object.defineProperty(target, descriptor.key, descriptor);
22
- }
23
- }
12
+ /**
13
+ * --------------------------------------------------------------------------
14
+ * Bootstrap tab.js
15
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
16
+ * --------------------------------------------------------------------------
17
+ */
24
18
 
25
- function _createClass(Constructor, protoProps, staticProps) {
26
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
27
- if (staticProps) _defineProperties(Constructor, staticProps);
28
- return Constructor;
29
- }
30
19
 
31
20
  /**
32
- * ------------------------------------------------------------------------
33
21
  * Constants
34
- * ------------------------------------------------------------------------
35
22
  */
36
23
 
37
- var NAME = 'tab';
38
- var VERSION = '4.3.1';
39
- var DATA_KEY = 'bs.tab';
40
- var EVENT_KEY = "." + DATA_KEY;
41
- var DATA_API_KEY = '.data-api';
42
- var JQUERY_NO_CONFLICT = $.fn[NAME];
43
- var Event = {
44
- HIDE: "hide" + EVENT_KEY,
45
- HIDDEN: "hidden" + EVENT_KEY,
46
- SHOW: "show" + EVENT_KEY,
47
- SHOWN: "shown" + EVENT_KEY,
48
- CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
49
- };
50
- var ClassName = {
51
- DROPDOWN_MENU: 'dropdown-menu',
52
- ACTIVE: 'active',
53
- DISABLED: 'disabled',
54
- FADE: 'fade',
55
- SHOW: 'show'
56
- };
57
- var Selector = {
58
- DROPDOWN: '.dropdown',
59
- NAV_LIST_GROUP: '.nav, .list-group',
60
- ACTIVE: '.active',
61
- ACTIVE_UL: '> li > .active',
62
- DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
63
- DROPDOWN_TOGGLE: '.dropdown-toggle',
64
- DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
65
- /**
66
- * ------------------------------------------------------------------------
67
- * Class Definition
68
- * ------------------------------------------------------------------------
69
- */
24
+ const NAME = 'tab';
25
+ const DATA_KEY = 'bs.tab';
26
+ const EVENT_KEY = `.${DATA_KEY}`;
27
+ const EVENT_HIDE = `hide${EVENT_KEY}`;
28
+ const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
29
+ const EVENT_SHOW = `show${EVENT_KEY}`;
30
+ const EVENT_SHOWN = `shown${EVENT_KEY}`;
31
+ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}`;
32
+ const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
33
+ const EVENT_LOAD_DATA_API = `load${EVENT_KEY}`;
34
+ const ARROW_LEFT_KEY = 'ArrowLeft';
35
+ const ARROW_RIGHT_KEY = 'ArrowRight';
36
+ const ARROW_UP_KEY = 'ArrowUp';
37
+ const ARROW_DOWN_KEY = 'ArrowDown';
38
+ const CLASS_NAME_ACTIVE = 'active';
39
+ const CLASS_NAME_FADE = 'fade';
40
+ const CLASS_NAME_SHOW = 'show';
41
+ const CLASS_DROPDOWN = 'dropdown';
42
+ const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
43
+ const SELECTOR_DROPDOWN_MENU = '.dropdown-menu';
44
+ const NOT_SELECTOR_DROPDOWN_TOGGLE = ':not(.dropdown-toggle)';
45
+ const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]';
46
+ const SELECTOR_OUTER = '.nav-item, .list-group-item';
47
+ const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`;
48
+ const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]'; // TODO: could only be `tab` in v6
49
+ const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`;
50
+ const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="pill"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="list"]`;
70
51
 
71
- };
52
+ /**
53
+ * Class definition
54
+ */
72
55
 
73
- var Tab =
74
- /*#__PURE__*/
75
- function () {
76
- function Tab(element) {
77
- this._element = element;
78
- } // Getters
56
+ class Tab extends BaseComponent {
57
+ constructor(element) {
58
+ super(element);
59
+ this._parent = this._element.closest(SELECTOR_TAB_PANEL);
60
+ if (!this._parent) {
61
+ return;
62
+ // TODO: should throw exception in v6
63
+ // throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`)
64
+ }
79
65
 
66
+ // Set up initial aria attributes
67
+ this._setInitialAttributes(this._parent, this._getChildren());
68
+ EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event));
69
+ }
80
70
 
81
- var _proto = Tab.prototype;
71
+ // Getters
72
+ static get NAME() {
73
+ return NAME;
74
+ }
82
75
 
83
76
  // Public
84
- _proto.show = function show() {
85
- var _this = this;
86
-
87
- if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE) || $(this._element).hasClass(ClassName.DISABLED)) {
77
+ show() {
78
+ // Shows this elem and deactivate the active sibling if exists
79
+ const innerElem = this._element;
80
+ if (this._elemIsActive(innerElem)) {
88
81
  return;
89
82
  }
90
83
 
91
- var target;
92
- var previous;
93
- var listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0];
94
- var selector = Util.getSelectorFromElement(this._element);
95
-
96
- if (listElement) {
97
- var itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE;
98
- previous = $.makeArray($(listElement).find(itemSelector));
99
- previous = previous[previous.length - 1];
100
- }
101
-
102
- var hideEvent = $.Event(Event.HIDE, {
103
- relatedTarget: this._element
104
- });
105
- var showEvent = $.Event(Event.SHOW, {
106
- relatedTarget: previous
84
+ // Search for active tab on same parent to deactivate it
85
+ const active = this._getActiveElem();
86
+ const hideEvent = active ? EventHandler.trigger(active, EVENT_HIDE, {
87
+ relatedTarget: innerElem
88
+ }) : null;
89
+ const showEvent = EventHandler.trigger(innerElem, EVENT_SHOW, {
90
+ relatedTarget: active
107
91
  });
108
-
109
- if (previous) {
110
- $(previous).trigger(hideEvent);
111
- }
112
-
113
- $(this._element).trigger(showEvent);
114
-
115
- if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
92
+ if (showEvent.defaultPrevented || hideEvent && hideEvent.defaultPrevented) {
116
93
  return;
117
94
  }
95
+ this._deactivate(active, innerElem);
96
+ this._activate(innerElem, active);
97
+ }
118
98
 
119
- if (selector) {
120
- target = document.querySelector(selector);
99
+ // Private
100
+ _activate(element, relatedElem) {
101
+ if (!element) {
102
+ return;
121
103
  }
104
+ element.classList.add(CLASS_NAME_ACTIVE);
105
+ this._activate(SelectorEngine.getElementFromSelector(element)); // Search and activate/show the proper section
122
106
 
123
- this._activate(this._element, listElement);
124
-
125
- var complete = function complete() {
126
- var hiddenEvent = $.Event(Event.HIDDEN, {
127
- relatedTarget: _this._element
128
- });
129
- var shownEvent = $.Event(Event.SHOWN, {
130
- relatedTarget: previous
107
+ const complete = () => {
108
+ if (element.getAttribute('role') !== 'tab') {
109
+ element.classList.add(CLASS_NAME_SHOW);
110
+ return;
111
+ }
112
+ element.removeAttribute('tabindex');
113
+ element.setAttribute('aria-selected', true);
114
+ this._toggleDropDown(element, true);
115
+ EventHandler.trigger(element, EVENT_SHOWN, {
116
+ relatedTarget: relatedElem
131
117
  });
132
- $(previous).trigger(hiddenEvent);
133
- $(_this._element).trigger(shownEvent);
134
118
  };
135
-
136
- if (target) {
137
- this._activate(target, target.parentNode, complete);
138
- } else {
139
- complete();
119
+ this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE));
120
+ }
121
+ _deactivate(element, relatedElem) {
122
+ if (!element) {
123
+ return;
140
124
  }
141
- };
142
-
143
- _proto.dispose = function dispose() {
144
- $.removeData(this._element, DATA_KEY);
145
- this._element = null;
146
- } // Private
147
- ;
148
-
149
- _proto._activate = function _activate(element, container, callback) {
150
- var _this2 = this;
151
-
152
- var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $(container).find(Selector.ACTIVE_UL) : $(container).children(Selector.ACTIVE);
153
- var active = activeElements[0];
154
- var isTransitioning = callback && active && $(active).hasClass(ClassName.FADE);
155
-
156
- var complete = function complete() {
157
- return _this2._transitionComplete(element, active, callback);
125
+ element.classList.remove(CLASS_NAME_ACTIVE);
126
+ element.blur();
127
+ this._deactivate(SelectorEngine.getElementFromSelector(element)); // Search and deactivate the shown section too
128
+
129
+ const complete = () => {
130
+ if (element.getAttribute('role') !== 'tab') {
131
+ element.classList.remove(CLASS_NAME_SHOW);
132
+ return;
133
+ }
134
+ element.setAttribute('aria-selected', false);
135
+ element.setAttribute('tabindex', '-1');
136
+ this._toggleDropDown(element, false);
137
+ EventHandler.trigger(element, EVENT_HIDDEN, {
138
+ relatedTarget: relatedElem
139
+ });
158
140
  };
159
-
160
- if (active && isTransitioning) {
161
- var transitionDuration = Util.getTransitionDurationFromElement(active);
162
- $(active).removeClass(ClassName.SHOW).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
163
- } else {
164
- complete();
141
+ this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE));
142
+ }
143
+ _keydown(event) {
144
+ if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) {
145
+ return;
165
146
  }
166
- };
167
-
168
- _proto._transitionComplete = function _transitionComplete(element, active, callback) {
169
- if (active) {
170
- $(active).removeClass(ClassName.ACTIVE);
171
- var dropdownChild = $(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
172
-
173
- if (dropdownChild) {
174
- $(dropdownChild).removeClass(ClassName.ACTIVE);
175
- }
176
-
177
- if (active.getAttribute('role') === 'tab') {
178
- active.setAttribute('aria-selected', false);
179
- }
147
+ event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page
148
+ event.preventDefault();
149
+ const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key);
150
+ const nextActiveElement = index_js.getNextActiveElement(this._getChildren().filter(element => !index_js.isDisabled(element)), event.target, isNext, true);
151
+ if (nextActiveElement) {
152
+ nextActiveElement.focus({
153
+ preventScroll: true
154
+ });
155
+ Tab.getOrCreateInstance(nextActiveElement).show();
180
156
  }
181
-
182
- $(element).addClass(ClassName.ACTIVE);
183
-
184
- if (element.getAttribute('role') === 'tab') {
185
- element.setAttribute('aria-selected', true);
157
+ }
158
+ _getChildren() {
159
+ // collection of inner elements
160
+ return SelectorEngine.find(SELECTOR_INNER_ELEM, this._parent);
161
+ }
162
+ _getActiveElem() {
163
+ return this._getChildren().find(child => this._elemIsActive(child)) || null;
164
+ }
165
+ _setInitialAttributes(parent, children) {
166
+ this._setAttributeIfNotExists(parent, 'role', 'tablist');
167
+ for (const child of children) {
168
+ this._setInitialAttributesOnChild(child);
186
169
  }
187
-
188
- Util.reflow(element);
189
-
190
- if (element.classList.contains(ClassName.FADE)) {
191
- element.classList.add(ClassName.SHOW);
170
+ }
171
+ _setInitialAttributesOnChild(child) {
172
+ child = this._getInnerElement(child);
173
+ const isActive = this._elemIsActive(child);
174
+ const outerElem = this._getOuterElement(child);
175
+ child.setAttribute('aria-selected', isActive);
176
+ if (outerElem !== child) {
177
+ this._setAttributeIfNotExists(outerElem, 'role', 'presentation');
192
178
  }
179
+ if (!isActive) {
180
+ child.setAttribute('tabindex', '-1');
181
+ }
182
+ this._setAttributeIfNotExists(child, 'role', 'tab');
193
183
 
194
- if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
195
- var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];
196
-
197
- if (dropdownElement) {
198
- var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE));
199
- $(dropdownToggleList).addClass(ClassName.ACTIVE);
184
+ // set attributes to the related panel too
185
+ this._setInitialAttributesOnTargetPanel(child);
186
+ }
187
+ _setInitialAttributesOnTargetPanel(child) {
188
+ const target = SelectorEngine.getElementFromSelector(child);
189
+ if (!target) {
190
+ return;
191
+ }
192
+ this._setAttributeIfNotExists(target, 'role', 'tabpanel');
193
+ if (child.id) {
194
+ this._setAttributeIfNotExists(target, 'aria-labelledby', `${child.id}`);
195
+ }
196
+ }
197
+ _toggleDropDown(element, open) {
198
+ const outerElem = this._getOuterElement(element);
199
+ if (!outerElem.classList.contains(CLASS_DROPDOWN)) {
200
+ return;
201
+ }
202
+ const toggle = (selector, className) => {
203
+ const element = SelectorEngine.findOne(selector, outerElem);
204
+ if (element) {
205
+ element.classList.toggle(className, open);
200
206
  }
201
-
202
- element.setAttribute('aria-expanded', true);
207
+ };
208
+ toggle(SELECTOR_DROPDOWN_TOGGLE, CLASS_NAME_ACTIVE);
209
+ toggle(SELECTOR_DROPDOWN_MENU, CLASS_NAME_SHOW);
210
+ outerElem.setAttribute('aria-expanded', open);
211
+ }
212
+ _setAttributeIfNotExists(element, attribute, value) {
213
+ if (!element.hasAttribute(attribute)) {
214
+ element.setAttribute(attribute, value);
203
215
  }
216
+ }
217
+ _elemIsActive(elem) {
218
+ return elem.classList.contains(CLASS_NAME_ACTIVE);
219
+ }
204
220
 
205
- if (callback) {
206
- callback();
207
- }
208
- } // Static
209
- ;
221
+ // Try to get the inner element (usually the .nav-link)
222
+ _getInnerElement(elem) {
223
+ return elem.matches(SELECTOR_INNER_ELEM) ? elem : SelectorEngine.findOne(SELECTOR_INNER_ELEM, elem);
224
+ }
210
225
 
211
- Tab._jQueryInterface = function _jQueryInterface(config) {
212
- return this.each(function () {
213
- var $this = $(this);
214
- var data = $this.data(DATA_KEY);
226
+ // Try to get the outer element (usually the .nav-item)
227
+ _getOuterElement(elem) {
228
+ return elem.closest(SELECTOR_OUTER) || elem;
229
+ }
215
230
 
216
- if (!data) {
217
- data = new Tab(this);
218
- $this.data(DATA_KEY, data);
231
+ // Static
232
+ static jQueryInterface(config) {
233
+ return this.each(function () {
234
+ const data = Tab.getOrCreateInstance(this);
235
+ if (typeof config !== 'string') {
236
+ return;
219
237
  }
220
-
221
- if (typeof config === 'string') {
222
- if (typeof data[config] === 'undefined') {
223
- throw new TypeError("No method named \"" + config + "\"");
224
- }
225
-
226
- data[config]();
238
+ if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
239
+ throw new TypeError(`No method named "${config}"`);
227
240
  }
241
+ data[config]();
228
242
  });
229
- };
230
-
231
- _createClass(Tab, null, [{
232
- key: "VERSION",
233
- get: function get() {
234
- return VERSION;
235
- }
236
- }]);
243
+ }
244
+ }
237
245
 
238
- return Tab;
239
- }();
240
246
  /**
241
- * ------------------------------------------------------------------------
242
- * Data Api implementation
243
- * ------------------------------------------------------------------------
247
+ * Data API implementation
244
248
  */
245
249
 
250
+ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
251
+ if (['A', 'AREA'].includes(this.tagName)) {
252
+ event.preventDefault();
253
+ }
254
+ if (index_js.isDisabled(this)) {
255
+ return;
256
+ }
257
+ Tab.getOrCreateInstance(this).show();
258
+ });
246
259
 
247
- $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
248
- event.preventDefault();
249
-
250
- Tab._jQueryInterface.call($(this), 'show');
260
+ /**
261
+ * Initialize on focus
262
+ */
263
+ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
264
+ for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE_ACTIVE)) {
265
+ Tab.getOrCreateInstance(element);
266
+ }
251
267
  });
252
268
  /**
253
- * ------------------------------------------------------------------------
254
269
  * jQuery
255
- * ------------------------------------------------------------------------
256
270
  */
257
271
 
258
- $.fn[NAME] = Tab._jQueryInterface;
259
- $.fn[NAME].Constructor = Tab;
260
-
261
- $.fn[NAME].noConflict = function () {
262
- $.fn[NAME] = JQUERY_NO_CONFLICT;
263
- return Tab._jQueryInterface;
264
- };
272
+ index_js.defineJQueryPlugin(Tab);
265
273
 
266
274
  return Tab;
267
275