bootstrap 4.3.1 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,373 +1,273 @@
1
1
  /*!
2
- * Bootstrap scrollspy.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 scrollspy.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.ScrollSpy = 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.Scrollspy = 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
- }
24
-
25
- function _createClass(Constructor, protoProps, staticProps) {
26
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
27
- if (staticProps) _defineProperties(Constructor, staticProps);
28
- return Constructor;
29
- }
30
-
31
- function _defineProperty(obj, key, value) {
32
- if (key in obj) {
33
- Object.defineProperty(obj, key, {
34
- value: value,
35
- enumerable: true,
36
- configurable: true,
37
- writable: true
38
- });
39
- } else {
40
- obj[key] = value;
41
- }
42
-
43
- return obj;
44
- }
45
-
46
- function _objectSpread(target) {
47
- for (var i = 1; i < arguments.length; i++) {
48
- var source = arguments[i] != null ? arguments[i] : {};
49
- var ownKeys = Object.keys(source);
50
-
51
- if (typeof Object.getOwnPropertySymbols === 'function') {
52
- ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
53
- return Object.getOwnPropertyDescriptor(source, sym).enumerable;
54
- }));
55
- }
56
-
57
- ownKeys.forEach(function (key) {
58
- _defineProperty(target, key, source[key]);
59
- });
60
- }
12
+ /**
13
+ * --------------------------------------------------------------------------
14
+ * Bootstrap scrollspy.js
15
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
16
+ * --------------------------------------------------------------------------
17
+ */
61
18
 
62
- return target;
63
- }
64
19
 
65
20
  /**
66
- * ------------------------------------------------------------------------
67
21
  * Constants
68
- * ------------------------------------------------------------------------
69
22
  */
70
23
 
71
- var NAME = 'scrollspy';
72
- var VERSION = '4.3.1';
73
- var DATA_KEY = 'bs.scrollspy';
74
- var EVENT_KEY = "." + DATA_KEY;
75
- var DATA_API_KEY = '.data-api';
76
- var JQUERY_NO_CONFLICT = $.fn[NAME];
77
- var Default = {
78
- offset: 10,
79
- method: 'auto',
80
- target: ''
24
+ const NAME = 'scrollspy';
25
+ const DATA_KEY = 'bs.scrollspy';
26
+ const EVENT_KEY = `.${DATA_KEY}`;
27
+ const DATA_API_KEY = '.data-api';
28
+ const EVENT_ACTIVATE = `activate${EVENT_KEY}`;
29
+ const EVENT_CLICK = `click${EVENT_KEY}`;
30
+ const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`;
31
+ const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
32
+ const CLASS_NAME_ACTIVE = 'active';
33
+ const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]';
34
+ const SELECTOR_TARGET_LINKS = '[href]';
35
+ const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
36
+ const SELECTOR_NAV_LINKS = '.nav-link';
37
+ const SELECTOR_NAV_ITEMS = '.nav-item';
38
+ const SELECTOR_LIST_ITEMS = '.list-group-item';
39
+ const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`;
40
+ const SELECTOR_DROPDOWN = '.dropdown';
41
+ const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
42
+ const Default = {
43
+ offset: null,
44
+ // TODO: v6 @deprecated, keep it for backwards compatibility reasons
45
+ rootMargin: '0px 0px -25%',
46
+ smoothScroll: false,
47
+ target: null,
48
+ threshold: [0.1, 0.5, 1]
81
49
  };
82
- var DefaultType = {
83
- offset: 'number',
84
- method: 'string',
85
- target: '(string|element)'
50
+ const DefaultType = {
51
+ offset: '(number|null)',
52
+ // TODO v6 @deprecated, keep it for backwards compatibility reasons
53
+ rootMargin: 'string',
54
+ smoothScroll: 'boolean',
55
+ target: 'element',
56
+ threshold: 'array'
86
57
  };
87
- var Event = {
88
- ACTIVATE: "activate" + EVENT_KEY,
89
- SCROLL: "scroll" + EVENT_KEY,
90
- LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY
91
- };
92
- var ClassName = {
93
- DROPDOWN_ITEM: 'dropdown-item',
94
- DROPDOWN_MENU: 'dropdown-menu',
95
- ACTIVE: 'active'
96
- };
97
- var Selector = {
98
- DATA_SPY: '[data-spy="scroll"]',
99
- ACTIVE: '.active',
100
- NAV_LIST_GROUP: '.nav, .list-group',
101
- NAV_LINKS: '.nav-link',
102
- NAV_ITEMS: '.nav-item',
103
- LIST_ITEMS: '.list-group-item',
104
- DROPDOWN: '.dropdown',
105
- DROPDOWN_ITEMS: '.dropdown-item',
106
- DROPDOWN_TOGGLE: '.dropdown-toggle'
107
- };
108
- var OffsetMethod = {
109
- OFFSET: 'offset',
110
- POSITION: 'position'
111
- /**
112
- * ------------------------------------------------------------------------
113
- * Class Definition
114
- * ------------------------------------------------------------------------
115
- */
116
58
 
117
- };
59
+ /**
60
+ * Class definition
61
+ */
118
62
 
119
- var ScrollSpy =
120
- /*#__PURE__*/
121
- function () {
122
- function ScrollSpy(element, config) {
123
- var _this = this;
63
+ class ScrollSpy extends BaseComponent {
64
+ constructor(element, config) {
65
+ super(element, config);
124
66
 
125
- this._element = element;
126
- this._scrollElement = element.tagName === 'BODY' ? window : element;
127
- this._config = this._getConfig(config);
128
- this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS);
129
- this._offsets = [];
130
- this._targets = [];
67
+ // this._element is the observablesContainer and config.target the menu links wrapper
68
+ this._targetLinks = new Map();
69
+ this._observableSections = new Map();
70
+ this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element;
131
71
  this._activeTarget = null;
132
- this._scrollHeight = 0;
133
- $(this._scrollElement).on(Event.SCROLL, function (event) {
134
- return _this._process(event);
135
- });
136
- this.refresh();
137
-
138
- this._process();
139
- } // Getters
140
-
72
+ this._observer = null;
73
+ this._previousScrollData = {
74
+ visibleEntryTop: 0,
75
+ parentScrollTop: 0
76
+ };
77
+ this.refresh(); // initialize
78
+ }
141
79
 
142
- var _proto = ScrollSpy.prototype;
80
+ // Getters
81
+ static get Default() {
82
+ return Default;
83
+ }
84
+ static get DefaultType() {
85
+ return DefaultType;
86
+ }
87
+ static get NAME() {
88
+ return NAME;
89
+ }
143
90
 
144
91
  // Public
145
- _proto.refresh = function refresh() {
146
- var _this2 = this;
92
+ refresh() {
93
+ this._initializeTargetsAndObservables();
94
+ this._maybeEnableSmoothScroll();
95
+ if (this._observer) {
96
+ this._observer.disconnect();
97
+ } else {
98
+ this._observer = this._getNewObserver();
99
+ }
100
+ for (const section of this._observableSections.values()) {
101
+ this._observer.observe(section);
102
+ }
103
+ }
104
+ dispose() {
105
+ this._observer.disconnect();
106
+ super.dispose();
107
+ }
147
108
 
148
- var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION;
149
- var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
150
- var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
151
- this._offsets = [];
152
- this._targets = [];
153
- this._scrollHeight = this._getScrollHeight();
154
- var targets = [].slice.call(document.querySelectorAll(this._selector));
155
- targets.map(function (element) {
156
- var target;
157
- var targetSelector = Util.getSelectorFromElement(element);
109
+ // Private
110
+ _configAfterMerge(config) {
111
+ // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case
112
+ config.target = index_js.getElement(config.target) || document.body;
158
113
 
159
- if (targetSelector) {
160
- target = document.querySelector(targetSelector);
161
- }
162
-
163
- if (target) {
164
- var targetBCR = target.getBoundingClientRect();
114
+ // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only
115
+ config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin;
116
+ if (typeof config.threshold === 'string') {
117
+ config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value));
118
+ }
119
+ return config;
120
+ }
121
+ _maybeEnableSmoothScroll() {
122
+ if (!this._config.smoothScroll) {
123
+ return;
124
+ }
165
125
 
166
- if (targetBCR.width || targetBCR.height) {
167
- // TODO (fat): remove sketch reliance on jQuery position/offset
168
- return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
126
+ // unregister any previous listeners
127
+ EventHandler.off(this._config.target, EVENT_CLICK);
128
+ EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {
129
+ const observableSection = this._observableSections.get(event.target.hash);
130
+ if (observableSection) {
131
+ event.preventDefault();
132
+ const root = this._rootElement || window;
133
+ const height = observableSection.offsetTop - this._element.offsetTop;
134
+ if (root.scrollTo) {
135
+ root.scrollTo({
136
+ top: height,
137
+ behavior: 'smooth'
138
+ });
139
+ return;
169
140
  }
170
- }
171
141
 
172
- return null;
173
- }).filter(function (item) {
174
- return item;
175
- }).sort(function (a, b) {
176
- return a[0] - b[0];
177
- }).forEach(function (item) {
178
- _this2._offsets.push(item[0]);
179
-
180
- _this2._targets.push(item[1]);
142
+ // Chrome 60 doesn't support `scrollTo`
143
+ root.scrollTop = height;
144
+ }
181
145
  });
182
- };
183
-
184
- _proto.dispose = function dispose() {
185
- $.removeData(this._element, DATA_KEY);
186
- $(this._scrollElement).off(EVENT_KEY);
187
- this._element = null;
188
- this._scrollElement = null;
189
- this._config = null;
190
- this._selector = null;
191
- this._offsets = null;
192
- this._targets = null;
193
- this._activeTarget = null;
194
- this._scrollHeight = null;
195
- } // Private
196
- ;
197
-
198
- _proto._getConfig = function _getConfig(config) {
199
- config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {});
200
-
201
- if (typeof config.target !== 'string') {
202
- var id = $(config.target).attr('id');
146
+ }
147
+ _getNewObserver() {
148
+ const options = {
149
+ root: this._rootElement,
150
+ threshold: this._config.threshold,
151
+ rootMargin: this._config.rootMargin
152
+ };
153
+ return new IntersectionObserver(entries => this._observerCallback(entries), options);
154
+ }
203
155
 
204
- if (!id) {
205
- id = Util.getUID(NAME);
206
- $(config.target).attr('id', id);
156
+ // The logic of selection
157
+ _observerCallback(entries) {
158
+ const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`);
159
+ const activate = entry => {
160
+ this._previousScrollData.visibleEntryTop = entry.target.offsetTop;
161
+ this._process(targetElement(entry));
162
+ };
163
+ const parentScrollTop = (this._rootElement || document.documentElement).scrollTop;
164
+ const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop;
165
+ this._previousScrollData.parentScrollTop = parentScrollTop;
166
+ for (const entry of entries) {
167
+ if (!entry.isIntersecting) {
168
+ this._activeTarget = null;
169
+ this._clearActiveClass(targetElement(entry));
170
+ continue;
171
+ }
172
+ const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop;
173
+ // if we are scrolling down, pick the bigger offsetTop
174
+ if (userScrollsDown && entryIsLowerThanPrevious) {
175
+ activate(entry);
176
+ // if parent isn't scrolled, let's keep the first visible item, breaking the iteration
177
+ if (!parentScrollTop) {
178
+ return;
179
+ }
180
+ continue;
207
181
  }
208
182
 
209
- config.target = "#" + id;
210
- }
211
-
212
- Util.typeCheckConfig(NAME, config, DefaultType);
213
- return config;
214
- };
215
-
216
- _proto._getScrollTop = function _getScrollTop() {
217
- return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
218
- };
219
-
220
- _proto._getScrollHeight = function _getScrollHeight() {
221
- return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
222
- };
223
-
224
- _proto._getOffsetHeight = function _getOffsetHeight() {
225
- return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
226
- };
227
-
228
- _proto._process = function _process() {
229
- var scrollTop = this._getScrollTop() + this._config.offset;
230
-
231
- var scrollHeight = this._getScrollHeight();
232
-
233
- var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
234
-
235
- if (this._scrollHeight !== scrollHeight) {
236
- this.refresh();
183
+ // if we are scrolling up, pick the smallest offsetTop
184
+ if (!userScrollsDown && !entryIsLowerThanPrevious) {
185
+ activate(entry);
186
+ }
237
187
  }
238
-
239
- if (scrollTop >= maxScroll) {
240
- var target = this._targets[this._targets.length - 1];
241
-
242
- if (this._activeTarget !== target) {
243
- this._activate(target);
188
+ }
189
+ _initializeTargetsAndObservables() {
190
+ this._targetLinks = new Map();
191
+ this._observableSections = new Map();
192
+ const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target);
193
+ for (const anchor of targetLinks) {
194
+ // ensure that the anchor has an id and is not disabled
195
+ if (!anchor.hash || index_js.isDisabled(anchor)) {
196
+ continue;
244
197
  }
198
+ const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element);
245
199
 
246
- return;
200
+ // ensure that the observableSection exists & is visible
201
+ if (index_js.isVisible(observableSection)) {
202
+ this._targetLinks.set(decodeURI(anchor.hash), anchor);
203
+ this._observableSections.set(anchor.hash, observableSection);
204
+ }
247
205
  }
248
-
249
- if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
250
- this._activeTarget = null;
251
-
252
- this._clear();
253
-
206
+ }
207
+ _process(target) {
208
+ if (this._activeTarget === target) {
254
209
  return;
255
210
  }
256
-
257
- var offsetLength = this._offsets.length;
258
-
259
- for (var i = offsetLength; i--;) {
260
- var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
261
-
262
- if (isActiveTarget) {
263
- this._activate(this._targets[i]);
264
- }
265
- }
266
- };
267
-
268
- _proto._activate = function _activate(target) {
211
+ this._clearActiveClass(this._config.target);
269
212
  this._activeTarget = target;
270
-
271
- this._clear();
272
-
273
- var queries = this._selector.split(',').map(function (selector) {
274
- return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]";
213
+ target.classList.add(CLASS_NAME_ACTIVE);
214
+ this._activateParents(target);
215
+ EventHandler.trigger(this._element, EVENT_ACTIVATE, {
216
+ relatedTarget: target
275
217
  });
276
-
277
- var $link = $([].slice.call(document.querySelectorAll(queries.join(','))));
278
-
279
- if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
280
- $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
281
- $link.addClass(ClassName.ACTIVE);
282
- } else {
283
- // Set triggered link as active
284
- $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active
218
+ }
219
+ _activateParents(target) {
220
+ // Activate dropdown parents
221
+ if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
222
+ SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE);
223
+ return;
224
+ }
225
+ for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) {
226
+ // Set triggered links parents as active
285
227
  // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
286
-
287
- $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + ", " + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item
288
-
289
- $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
228
+ for (const item of SelectorEngine.prev(listGroup, SELECTOR_LINK_ITEMS)) {
229
+ item.classList.add(CLASS_NAME_ACTIVE);
230
+ }
290
231
  }
232
+ }
233
+ _clearActiveClass(parent) {
234
+ parent.classList.remove(CLASS_NAME_ACTIVE);
235
+ const activeNodes = SelectorEngine.find(`${SELECTOR_TARGET_LINKS}.${CLASS_NAME_ACTIVE}`, parent);
236
+ for (const node of activeNodes) {
237
+ node.classList.remove(CLASS_NAME_ACTIVE);
238
+ }
239
+ }
291
240
 
292
- $(this._scrollElement).trigger(Event.ACTIVATE, {
293
- relatedTarget: target
294
- });
295
- };
296
-
297
- _proto._clear = function _clear() {
298
- [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {
299
- return node.classList.contains(ClassName.ACTIVE);
300
- }).forEach(function (node) {
301
- return node.classList.remove(ClassName.ACTIVE);
302
- });
303
- } // Static
304
- ;
305
-
306
- ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
241
+ // Static
242
+ static jQueryInterface(config) {
307
243
  return this.each(function () {
308
- var data = $(this).data(DATA_KEY);
309
-
310
- var _config = typeof config === 'object' && config;
311
-
312
- if (!data) {
313
- data = new ScrollSpy(this, _config);
314
- $(this).data(DATA_KEY, data);
244
+ const data = ScrollSpy.getOrCreateInstance(this, config);
245
+ if (typeof config !== 'string') {
246
+ return;
315
247
  }
316
-
317
- if (typeof config === 'string') {
318
- if (typeof data[config] === 'undefined') {
319
- throw new TypeError("No method named \"" + config + "\"");
320
- }
321
-
322
- data[config]();
248
+ if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
249
+ throw new TypeError(`No method named "${config}"`);
323
250
  }
251
+ data[config]();
324
252
  });
325
- };
326
-
327
- _createClass(ScrollSpy, null, [{
328
- key: "VERSION",
329
- get: function get() {
330
- return VERSION;
331
- }
332
- }, {
333
- key: "Default",
334
- get: function get() {
335
- return Default;
336
- }
337
- }]);
253
+ }
254
+ }
338
255
 
339
- return ScrollSpy;
340
- }();
341
256
  /**
342
- * ------------------------------------------------------------------------
343
- * Data Api implementation
344
- * ------------------------------------------------------------------------
257
+ * Data API implementation
345
258
  */
346
259
 
347
-
348
- $(window).on(Event.LOAD_DATA_API, function () {
349
- var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY));
350
- var scrollSpysLength = scrollSpys.length;
351
-
352
- for (var i = scrollSpysLength; i--;) {
353
- var $spy = $(scrollSpys[i]);
354
-
355
- ScrollSpy._jQueryInterface.call($spy, $spy.data());
260
+ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
261
+ for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) {
262
+ ScrollSpy.getOrCreateInstance(spy);
356
263
  }
357
264
  });
265
+
358
266
  /**
359
- * ------------------------------------------------------------------------
360
267
  * jQuery
361
- * ------------------------------------------------------------------------
362
268
  */
363
269
 
364
- $.fn[NAME] = ScrollSpy._jQueryInterface;
365
- $.fn[NAME].Constructor = ScrollSpy;
366
-
367
- $.fn[NAME].noConflict = function () {
368
- $.fn[NAME] = JQUERY_NO_CONFLICT;
369
- return ScrollSpy._jQueryInterface;
370
- };
270
+ index_js.defineJQueryPlugin(ScrollSpy);
371
271
 
372
272
  return ScrollSpy;
373
273