@openeuropa/bcl-bootstrap 0.25.1 → 0.26.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 (142) hide show
  1. package/bootstrap-icons.svg +1 -1
  2. package/icons/apple.svg +2 -2
  3. package/icons/boombox-fill.svg +2 -2
  4. package/icons/cup-fill.svg +1 -1
  5. package/icons/cup.svg +1 -1
  6. package/js/dist/alert.js +3 -12
  7. package/js/dist/alert.js.map +1 -1
  8. package/js/dist/base-component.js +32 -18
  9. package/js/dist/base-component.js.map +1 -1
  10. package/js/dist/button.js +3 -12
  11. package/js/dist/button.js.map +1 -1
  12. package/js/dist/carousel.js +207 -307
  13. package/js/dist/carousel.js.map +1 -1
  14. package/js/dist/collapse.js +57 -88
  15. package/js/dist/collapse.js.map +1 -1
  16. package/js/dist/dom/data.js +1 -3
  17. package/js/dist/dom/data.js.map +1 -1
  18. package/js/dist/dom/event-handler.js +87 -106
  19. package/js/dist/dom/event-handler.js.map +1 -1
  20. package/js/dist/dom/manipulator.js +21 -25
  21. package/js/dist/dom/manipulator.js.map +1 -1
  22. package/js/dist/dom/selector-engine.js +11 -10
  23. package/js/dist/dom/selector-engine.js.map +1 -1
  24. package/js/dist/dropdown.js +83 -115
  25. package/js/dist/dropdown.js.map +1 -1
  26. package/js/dist/modal.js +95 -152
  27. package/js/dist/modal.js.map +1 -1
  28. package/js/dist/offcanvas.js +75 -58
  29. package/js/dist/offcanvas.js.map +1 -1
  30. package/js/dist/popover.js +29 -56
  31. package/js/dist/popover.js.map +1 -1
  32. package/js/dist/scrollspy.js +176 -125
  33. package/js/dist/scrollspy.js.map +1 -1
  34. package/js/dist/tab.js +207 -92
  35. package/js/dist/tab.js.map +1 -1
  36. package/js/dist/toast.js +23 -37
  37. package/js/dist/toast.js.map +1 -1
  38. package/js/dist/tooltip.js +259 -348
  39. package/js/dist/tooltip.js.map +1 -1
  40. package/js/dist/util/backdrop.js +62 -39
  41. package/js/dist/util/backdrop.js.map +1 -1
  42. package/js/dist/util/component-functions.js +1 -1
  43. package/js/dist/util/component-functions.js.map +1 -1
  44. package/js/dist/util/config.js +75 -0
  45. package/js/dist/util/config.js.map +1 -0
  46. package/js/dist/util/focustrap.js +41 -34
  47. package/js/dist/util/focustrap.js.map +1 -1
  48. package/js/dist/util/index.js +56 -52
  49. package/js/dist/util/index.js.map +1 -1
  50. package/js/dist/util/sanitizer.js +12 -19
  51. package/js/dist/util/sanitizer.js.map +1 -1
  52. package/js/dist/util/scrollbar.js +49 -34
  53. package/js/dist/util/scrollbar.js.map +1 -1
  54. package/js/dist/util/swipe.js +151 -0
  55. package/js/dist/util/swipe.js.map +1 -0
  56. package/js/dist/util/template-factory.js +173 -0
  57. package/js/dist/util/template-factory.js.map +1 -0
  58. package/js/src/alert.js +3 -15
  59. package/js/src/base-component.js +28 -18
  60. package/js/src/button.js +3 -17
  61. package/js/src/carousel.js +203 -319
  62. package/js/src/collapse.js +61 -94
  63. package/js/src/dom/data.js +1 -3
  64. package/js/src/dom/event-handler.js +80 -108
  65. package/js/src/dom/manipulator.js +22 -31
  66. package/js/src/dom/selector-engine.js +10 -19
  67. package/js/src/dropdown.js +84 -138
  68. package/js/src/modal.js +94 -158
  69. package/js/src/offcanvas.js +72 -61
  70. package/js/src/popover.js +31 -62
  71. package/js/src/scrollspy.js +166 -171
  72. package/js/src/tab.js +193 -110
  73. package/js/src/toast.js +19 -41
  74. package/js/src/tooltip.js +259 -371
  75. package/js/src/util/backdrop.js +55 -36
  76. package/js/src/util/component-functions.js +1 -1
  77. package/js/src/util/config.js +66 -0
  78. package/js/src/util/focustrap.js +38 -28
  79. package/js/src/util/index.js +67 -64
  80. package/js/src/util/sanitizer.js +11 -19
  81. package/js/src/util/scrollbar.js +47 -30
  82. package/js/src/util/swipe.js +146 -0
  83. package/js/src/util/template-factory.js +160 -0
  84. package/package.json +4 -4
  85. package/scss/_accordion.scss +52 -24
  86. package/scss/_alert.scss +18 -4
  87. package/scss/_badge.scss +14 -5
  88. package/scss/_breadcrumb.scss +22 -10
  89. package/scss/_button-group.scss +3 -0
  90. package/scss/_buttons.scss +97 -22
  91. package/scss/_card.scss +55 -37
  92. package/scss/_close.scss +1 -1
  93. package/scss/_containers.scss +1 -1
  94. package/scss/_dropdown.scss +83 -75
  95. package/scss/_functions.scss +7 -7
  96. package/scss/_grid.scss +3 -3
  97. package/scss/_helpers.scss +1 -0
  98. package/scss/_list-group.scss +44 -27
  99. package/scss/_maps.scss +54 -0
  100. package/scss/_modal.scss +71 -43
  101. package/scss/_nav.scss +53 -20
  102. package/scss/_navbar.scss +91 -150
  103. package/scss/_offcanvas.scss +119 -59
  104. package/scss/_pagination.scss +66 -21
  105. package/scss/_placeholders.scss +1 -1
  106. package/scss/_popover.scss +90 -52
  107. package/scss/_progress.scss +20 -9
  108. package/scss/_reboot.scss +25 -40
  109. package/scss/_root.scss +40 -21
  110. package/scss/_spinners.scss +38 -22
  111. package/scss/_tables.scss +32 -23
  112. package/scss/_toasts.scss +35 -16
  113. package/scss/_tooltip.scss +61 -56
  114. package/scss/_type.scss +2 -0
  115. package/scss/_utilities.scss +43 -26
  116. package/scss/_variables.scss +113 -121
  117. package/scss/bootstrap-grid.scss +3 -6
  118. package/scss/bootstrap-reboot.scss +3 -7
  119. package/scss/bootstrap-utilities.scss +3 -6
  120. package/scss/bootstrap.scss +4 -6
  121. package/scss/forms/_floating-labels.scss +14 -3
  122. package/scss/forms/_form-check.scss +28 -5
  123. package/scss/forms/_form-control.scss +12 -37
  124. package/scss/forms/_form-select.scss +0 -1
  125. package/scss/forms/_input-group.scss +15 -7
  126. package/scss/helpers/_color-bg.scss +10 -0
  127. package/scss/helpers/_colored-links.scss +2 -2
  128. package/scss/helpers/_position.scss +7 -1
  129. package/scss/helpers/_ratio.scss +2 -2
  130. package/scss/helpers/_vr.scss +1 -1
  131. package/scss/mixins/_alert.scss +7 -3
  132. package/scss/mixins/_banner.scss +9 -0
  133. package/scss/mixins/_breakpoints.scss +8 -8
  134. package/scss/mixins/_buttons.scss +32 -95
  135. package/scss/mixins/_container.scss +4 -2
  136. package/scss/mixins/_forms.scss +8 -0
  137. package/scss/mixins/_gradients.scss +1 -1
  138. package/scss/mixins/_grid.scss +12 -12
  139. package/scss/mixins/_pagination.scss +4 -25
  140. package/scss/mixins/_reset-text.scss +1 -1
  141. package/scss/mixins/_table-variants.scss +12 -9
  142. package/scss/mixins/_utilities.scss +12 -4
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./util/index'), require('./util/sanitizer'), require('./dom/data'), require('./dom/event-handler'), require('./dom/manipulator'), require('./dom/selector-engine'), require('./base-component')) :
3
- typeof define === 'function' && define.amd ? define(['@popperjs/core', './util/index', './util/sanitizer', './dom/data', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global["@popperjs/core"], global.Index, global.Sanitizer, global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine, global.BaseComponent));
5
- })(this, (function (Popper, index, sanitizer, Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./util/index'), require('./util/sanitizer'), require('./dom/event-handler'), require('./dom/manipulator'), require('./base-component'), require('./util/template-factory')) :
3
+ typeof define === 'function' && define.amd ? define(['@popperjs/core', './util/index', './util/sanitizer', './dom/event-handler', './dom/manipulator', './base-component', './util/template-factory'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global["@popperjs/core"], global.Index, global.Sanitizer, global.EventHandler, global.Manipulator, global.BaseComponent, global.TemplateFactory));
5
+ })(this, (function (Popper, index, sanitizer, EventHandler, Manipulator, BaseComponent, TemplateFactory) { 'use strict';
6
6
 
7
7
  const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
8
8
 
@@ -25,48 +25,43 @@
25
25
  }
26
26
 
27
27
  const Popper__namespace = /*#__PURE__*/_interopNamespace(Popper);
28
- const Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
29
28
  const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
30
29
  const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
31
- const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
32
30
  const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
31
+ const TemplateFactory__default = /*#__PURE__*/_interopDefaultLegacy(TemplateFactory);
33
32
 
34
33
  /**
35
34
  * --------------------------------------------------------------------------
36
- * Bootstrap (v5.1.3): tooltip.js
35
+ * Bootstrap (v5.2.0): tooltip.js
37
36
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
38
37
  * --------------------------------------------------------------------------
39
38
  */
40
39
  /**
41
- * ------------------------------------------------------------------------
42
40
  * Constants
43
- * ------------------------------------------------------------------------
44
41
  */
45
42
 
46
43
  const NAME = 'tooltip';
47
- const DATA_KEY = 'bs.tooltip';
48
- const EVENT_KEY = `.${DATA_KEY}`;
49
- const CLASS_PREFIX = 'bs-tooltip';
50
44
  const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
51
- const DefaultType = {
52
- animation: 'boolean',
53
- template: 'string',
54
- title: '(string|element|function)',
55
- trigger: 'string',
56
- delay: '(number|object)',
57
- html: 'boolean',
58
- selector: '(string|boolean)',
59
- placement: '(string|function)',
60
- offset: '(array|string|function)',
61
- container: '(string|element|boolean)',
62
- fallbackPlacements: 'array',
63
- boundary: '(string|element)',
64
- customClass: '(string|function)',
65
- sanitize: 'boolean',
66
- sanitizeFn: '(null|function)',
67
- allowList: 'object',
68
- popperConfig: '(null|object|function)'
69
- };
45
+ const CLASS_NAME_FADE = 'fade';
46
+ const CLASS_NAME_MODAL = 'modal';
47
+ const CLASS_NAME_SHOW = 'show';
48
+ const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
49
+ const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
50
+ const EVENT_MODAL_HIDE = 'hide.bs.modal';
51
+ const TRIGGER_HOVER = 'hover';
52
+ const TRIGGER_FOCUS = 'focus';
53
+ const TRIGGER_CLICK = 'click';
54
+ const TRIGGER_MANUAL = 'manual';
55
+ const EVENT_HIDE = 'hide';
56
+ const EVENT_HIDDEN = 'hidden';
57
+ const EVENT_SHOW = 'show';
58
+ const EVENT_SHOWN = 'shown';
59
+ const EVENT_INSERTED = 'inserted';
60
+ const EVENT_CLICK = 'click';
61
+ const EVENT_FOCUSIN = 'focusin';
62
+ const EVENT_FOCUSOUT = 'focusout';
63
+ const EVENT_MOUSEENTER = 'mouseenter';
64
+ const EVENT_MOUSELEAVE = 'mouseleave';
70
65
  const AttachmentMap = {
71
66
  AUTO: 'auto',
72
67
  TOP: 'top',
@@ -75,52 +70,45 @@
75
70
  LEFT: index.isRTL() ? 'right' : 'left'
76
71
  };
77
72
  const Default = {
73
+ allowList: sanitizer.DefaultAllowlist,
78
74
  animation: true,
79
- template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
80
- trigger: 'hover focus',
81
- title: '',
75
+ boundary: 'clippingParents',
76
+ container: false,
77
+ customClass: '',
82
78
  delay: 0,
79
+ fallbackPlacements: ['top', 'right', 'bottom', 'left'],
83
80
  html: false,
84
- selector: false,
85
- placement: 'top',
86
81
  offset: [0, 0],
87
- container: false,
88
- fallbackPlacements: ['top', 'right', 'bottom', 'left'],
89
- boundary: 'clippingParents',
90
- customClass: '',
82
+ placement: 'top',
83
+ popperConfig: null,
91
84
  sanitize: true,
92
85
  sanitizeFn: null,
93
- allowList: sanitizer.DefaultAllowlist,
94
- popperConfig: null
86
+ selector: false,
87
+ template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
88
+ title: '',
89
+ trigger: 'hover focus'
95
90
  };
96
- const Event = {
97
- HIDE: `hide${EVENT_KEY}`,
98
- HIDDEN: `hidden${EVENT_KEY}`,
99
- SHOW: `show${EVENT_KEY}`,
100
- SHOWN: `shown${EVENT_KEY}`,
101
- INSERTED: `inserted${EVENT_KEY}`,
102
- CLICK: `click${EVENT_KEY}`,
103
- FOCUSIN: `focusin${EVENT_KEY}`,
104
- FOCUSOUT: `focusout${EVENT_KEY}`,
105
- MOUSEENTER: `mouseenter${EVENT_KEY}`,
106
- MOUSELEAVE: `mouseleave${EVENT_KEY}`
91
+ const DefaultType = {
92
+ allowList: 'object',
93
+ animation: 'boolean',
94
+ boundary: '(string|element)',
95
+ container: '(string|element|boolean)',
96
+ customClass: '(string|function)',
97
+ delay: '(number|object)',
98
+ fallbackPlacements: 'array',
99
+ html: 'boolean',
100
+ offset: '(array|string|function)',
101
+ placement: '(string|function)',
102
+ popperConfig: '(null|object|function)',
103
+ sanitize: 'boolean',
104
+ sanitizeFn: '(null|function)',
105
+ selector: '(string|boolean)',
106
+ template: 'string',
107
+ title: '(string|element|function)',
108
+ trigger: 'string'
107
109
  };
108
- const CLASS_NAME_FADE = 'fade';
109
- const CLASS_NAME_MODAL = 'modal';
110
- const CLASS_NAME_SHOW = 'show';
111
- const HOVER_STATE_SHOW = 'show';
112
- const HOVER_STATE_OUT = 'out';
113
- const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
114
- const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
115
- const EVENT_MODAL_HIDE = 'hide.bs.modal';
116
- const TRIGGER_HOVER = 'hover';
117
- const TRIGGER_FOCUS = 'focus';
118
- const TRIGGER_CLICK = 'click';
119
- const TRIGGER_MANUAL = 'manual';
120
110
  /**
121
- * ------------------------------------------------------------------------
122
- * Class Definition
123
- * ------------------------------------------------------------------------
111
+ * Class definition
124
112
  */
125
113
 
126
114
  class Tooltip extends BaseComponent__default.default {
@@ -129,15 +117,16 @@
129
117
  throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
130
118
  }
131
119
 
132
- super(element); // private
120
+ super(element, config); // Private
133
121
 
134
122
  this._isEnabled = true;
135
123
  this._timeout = 0;
136
- this._hoverState = '';
124
+ this._isHovered = false;
137
125
  this._activeTrigger = {};
138
- this._popper = null; // Protected
126
+ this._popper = null;
127
+ this._templateFactory = null;
128
+ this._newContent = null; // Protected
139
129
 
140
- this._config = this._getConfig(config);
141
130
  this.tip = null;
142
131
 
143
132
  this._setListeners();
@@ -148,16 +137,12 @@
148
137
  return Default;
149
138
  }
150
139
 
151
- static get NAME() {
152
- return NAME;
153
- }
154
-
155
- static get Event() {
156
- return Event;
157
- }
158
-
159
140
  static get DefaultType() {
160
141
  return DefaultType;
142
+ }
143
+
144
+ static get NAME() {
145
+ return NAME;
161
146
  } // Public
162
147
 
163
148
 
@@ -184,19 +169,21 @@
184
169
  context._activeTrigger.click = !context._activeTrigger.click;
185
170
 
186
171
  if (context._isWithActiveTrigger()) {
187
- context._enter(null, context);
172
+ context._enter();
188
173
  } else {
189
- context._leave(null, context);
174
+ context._leave();
190
175
  }
191
- } else {
192
- if (this.getTipElement().classList.contains(CLASS_NAME_SHOW)) {
193
- this._leave(null, this);
194
176
 
195
- return;
196
- }
177
+ return;
178
+ }
197
179
 
198
- this._enter(null, this);
180
+ if (this._isShown()) {
181
+ this._leave();
182
+
183
+ return;
199
184
  }
185
+
186
+ this._enter();
200
187
  }
201
188
 
202
189
  dispose() {
@@ -217,233 +204,206 @@
217
204
  throw new Error('Please use show on visible elements');
218
205
  }
219
206
 
220
- if (!(this.isWithContent() && this._isEnabled)) {
207
+ if (!(this._isWithContent() && this._isEnabled)) {
221
208
  return;
222
209
  }
223
210
 
224
- const showEvent = EventHandler__default.default.trigger(this._element, this.constructor.Event.SHOW);
211
+ const showEvent = EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_SHOW));
225
212
  const shadowRoot = index.findShadowRoot(this._element);
226
- const isInTheDom = shadowRoot === null ? this._element.ownerDocument.documentElement.contains(this._element) : shadowRoot.contains(this._element);
213
+
214
+ const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);
227
215
 
228
216
  if (showEvent.defaultPrevented || !isInTheDom) {
229
217
  return;
230
- } // A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title`
231
- // This will be removed later in favor of a `setContent` method
232
-
218
+ } // todo v6 remove this OR make it optional
233
219
 
234
- if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) {
235
- this._disposePopper();
236
220
 
221
+ if (this.tip) {
237
222
  this.tip.remove();
238
223
  this.tip = null;
239
224
  }
240
225
 
241
- const tip = this.getTipElement();
242
- const tipId = index.getUID(this.constructor.NAME);
243
- tip.setAttribute('id', tipId);
244
-
245
- this._element.setAttribute('aria-describedby', tipId);
226
+ const tip = this._getTipElement();
246
227
 
247
- if (this._config.animation) {
248
- tip.classList.add(CLASS_NAME_FADE);
249
- }
250
-
251
- const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;
252
-
253
- const attachment = this._getAttachment(placement);
254
-
255
- this._addAttachmentClass(attachment);
228
+ this._element.setAttribute('aria-describedby', tip.getAttribute('id'));
256
229
 
257
230
  const {
258
231
  container
259
232
  } = this._config;
260
- Data__default.default.set(tip, this.constructor.DATA_KEY, this);
261
233
 
262
234
  if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
263
235
  container.append(tip);
264
- EventHandler__default.default.trigger(this._element, this.constructor.Event.INSERTED);
236
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));
265
237
  }
266
238
 
267
239
  if (this._popper) {
268
240
  this._popper.update();
269
241
  } else {
270
- this._popper = Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
242
+ this._popper = this._createPopper(tip);
271
243
  }
272
244
 
273
- tip.classList.add(CLASS_NAME_SHOW);
274
-
275
- const customClass = this._resolvePossibleFunction(this._config.customClass);
276
-
277
- if (customClass) {
278
- tip.classList.add(...customClass.split(' '));
279
- } // If this is a touch-enabled device we add extra
245
+ tip.classList.add(CLASS_NAME_SHOW); // If this is a touch-enabled device we add extra
280
246
  // empty mouseover listeners to the body's immediate children;
281
247
  // only needed because of broken event delegation on iOS
282
248
  // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
283
249
 
284
-
285
250
  if ('ontouchstart' in document.documentElement) {
286
- [].concat(...document.body.children).forEach(element => {
251
+ for (const element of [].concat(...document.body.children)) {
287
252
  EventHandler__default.default.on(element, 'mouseover', index.noop);
288
- });
253
+ }
289
254
  }
290
255
 
291
256
  const complete = () => {
292
- const prevHoverState = this._hoverState;
293
- this._hoverState = null;
294
- EventHandler__default.default.trigger(this._element, this.constructor.Event.SHOWN);
257
+ const previousHoverState = this._isHovered;
258
+ this._isHovered = false;
259
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_SHOWN));
295
260
 
296
- if (prevHoverState === HOVER_STATE_OUT) {
297
- this._leave(null, this);
261
+ if (previousHoverState) {
262
+ this._leave();
298
263
  }
299
264
  };
300
265
 
301
- const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
302
-
303
- this._queueCallback(complete, this.tip, isAnimated);
266
+ this._queueCallback(complete, this.tip, this._isAnimated());
304
267
  }
305
268
 
306
269
  hide() {
307
- if (!this._popper) {
270
+ if (!this._isShown()) {
308
271
  return;
309
272
  }
310
273
 
311
- const tip = this.getTipElement();
312
-
313
- const complete = () => {
314
- if (this._isWithActiveTrigger()) {
315
- return;
316
- }
317
-
318
- if (this._hoverState !== HOVER_STATE_SHOW) {
319
- tip.remove();
320
- }
321
-
322
- this._cleanTipClass();
323
-
324
- this._element.removeAttribute('aria-describedby');
325
-
326
- EventHandler__default.default.trigger(this._element, this.constructor.Event.HIDDEN);
327
-
328
- this._disposePopper();
329
- };
330
-
331
- const hideEvent = EventHandler__default.default.trigger(this._element, this.constructor.Event.HIDE);
274
+ const hideEvent = EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_HIDE));
332
275
 
333
276
  if (hideEvent.defaultPrevented) {
334
277
  return;
335
278
  }
336
279
 
280
+ const tip = this._getTipElement();
281
+
337
282
  tip.classList.remove(CLASS_NAME_SHOW); // If this is a touch-enabled device we remove the extra
338
283
  // empty mouseover listeners we added for iOS support
339
284
 
340
285
  if ('ontouchstart' in document.documentElement) {
341
- [].concat(...document.body.children).forEach(element => EventHandler__default.default.off(element, 'mouseover', index.noop));
286
+ for (const element of [].concat(...document.body.children)) {
287
+ EventHandler__default.default.off(element, 'mouseover', index.noop);
288
+ }
342
289
  }
343
290
 
344
291
  this._activeTrigger[TRIGGER_CLICK] = false;
345
292
  this._activeTrigger[TRIGGER_FOCUS] = false;
346
293
  this._activeTrigger[TRIGGER_HOVER] = false;
347
- const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
294
+ this._isHovered = false;
295
+
296
+ const complete = () => {
297
+ if (this._isWithActiveTrigger()) {
298
+ return;
299
+ }
300
+
301
+ if (!this._isHovered) {
302
+ tip.remove();
303
+ }
348
304
 
349
- this._queueCallback(complete, this.tip, isAnimated);
305
+ this._element.removeAttribute('aria-describedby');
306
+
307
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN));
350
308
 
351
- this._hoverState = '';
309
+ this._disposePopper();
310
+ };
311
+
312
+ this._queueCallback(complete, this.tip, this._isAnimated());
352
313
  }
353
314
 
354
315
  update() {
355
- if (this._popper !== null) {
316
+ if (this._popper) {
356
317
  this._popper.update();
357
318
  }
358
319
  } // Protected
359
320
 
360
321
 
361
- isWithContent() {
362
- return Boolean(this.getTitle());
322
+ _isWithContent() {
323
+ return Boolean(this._getTitle());
363
324
  }
364
325
 
365
- getTipElement() {
366
- if (this.tip) {
367
- return this.tip;
326
+ _getTipElement() {
327
+ if (!this.tip) {
328
+ this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());
368
329
  }
369
330
 
370
- const element = document.createElement('div');
371
- element.innerHTML = this._config.template;
372
- const tip = element.children[0];
373
- this.setContent(tip);
374
- tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
375
- this.tip = tip;
376
331
  return this.tip;
377
332
  }
378
333
 
379
- setContent(tip) {
380
- this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER);
381
- }
334
+ _createTipElement(content) {
335
+ const tip = this._getTemplateFactory(content).toHtml(); // todo: remove this check on v6
382
336
 
383
- _sanitizeAndSetContent(template, content, selector) {
384
- const templateElement = SelectorEngine__default.default.findOne(selector, template);
385
337
 
386
- if (!content && templateElement) {
387
- templateElement.remove();
388
- return;
389
- } // we use append for html objects to maintain js events
338
+ if (!tip) {
339
+ return null;
340
+ }
390
341
 
342
+ tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW); // todo: on v6 the following can be achieved with CSS only
391
343
 
392
- this.setElementContent(templateElement, content);
393
- }
344
+ tip.classList.add(`bs-${this.constructor.NAME}-auto`);
345
+ const tipId = index.getUID(this.constructor.NAME).toString();
346
+ tip.setAttribute('id', tipId);
394
347
 
395
- setElementContent(element, content) {
396
- if (element === null) {
397
- return;
348
+ if (this._isAnimated()) {
349
+ tip.classList.add(CLASS_NAME_FADE);
398
350
  }
399
351
 
400
- if (index.isElement(content)) {
401
- content = index.getElement(content); // content is a DOM node or a jQuery
352
+ return tip;
353
+ }
402
354
 
403
- if (this._config.html) {
404
- if (content.parentNode !== element) {
405
- element.innerHTML = '';
406
- element.append(content);
407
- }
408
- } else {
409
- element.textContent = content.textContent;
410
- }
355
+ setContent(content) {
356
+ this._newContent = content;
411
357
 
412
- return;
413
- }
358
+ if (this._isShown()) {
359
+ this._disposePopper();
414
360
 
415
- if (this._config.html) {
416
- if (this._config.sanitize) {
417
- content = sanitizer.sanitizeHtml(content, this._config.allowList, this._config.sanitizeFn);
418
- }
361
+ this.show();
362
+ }
363
+ }
419
364
 
420
- element.innerHTML = content;
365
+ _getTemplateFactory(content) {
366
+ if (this._templateFactory) {
367
+ this._templateFactory.changeContent(content);
421
368
  } else {
422
- element.textContent = content;
369
+ this._templateFactory = new TemplateFactory__default.default({ ...this._config,
370
+ // the `content` var has to be after `this._config`
371
+ // to override config.content in case of popover
372
+ content,
373
+ extraClass: this._resolvePossibleFunction(this._config.customClass)
374
+ });
423
375
  }
424
- }
425
376
 
426
- getTitle() {
427
- const title = this._element.getAttribute('data-bs-original-title') || this._config.title;
377
+ return this._templateFactory;
378
+ }
428
379
 
429
- return this._resolvePossibleFunction(title);
380
+ _getContentForTemplate() {
381
+ return {
382
+ [SELECTOR_TOOLTIP_INNER]: this._getTitle()
383
+ };
430
384
  }
431
385
 
432
- updateAttachment(attachment) {
433
- if (attachment === 'right') {
434
- return 'end';
435
- }
386
+ _getTitle() {
387
+ return this._resolvePossibleFunction(this._config.title) || this._config.originalTitle;
388
+ } // Private
436
389
 
437
- if (attachment === 'left') {
438
- return 'start';
439
- }
440
390
 
441
- return attachment;
442
- } // Private
391
+ _initializeOnDelegatedTarget(event) {
392
+ return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
393
+ }
394
+
395
+ _isAnimated() {
396
+ return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE);
397
+ }
443
398
 
399
+ _isShown() {
400
+ return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW);
401
+ }
444
402
 
445
- _initializeOnDelegatedTarget(event, context) {
446
- return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
403
+ _createPopper(tip) {
404
+ const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;
405
+ const attachment = AttachmentMap[placement.toUpperCase()];
406
+ return Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
447
407
  }
448
408
 
449
409
  _getOffset() {
@@ -452,7 +412,7 @@
452
412
  } = this._config;
453
413
 
454
414
  if (typeof offset === 'string') {
455
- return offset.split(',').map(val => Number.parseInt(val, 10));
415
+ return offset.split(',').map(value => Number.parseInt(value, 10));
456
416
  }
457
417
 
458
418
  if (typeof offset === 'function') {
@@ -462,8 +422,8 @@
462
422
  return offset;
463
423
  }
464
424
 
465
- _resolvePossibleFunction(content) {
466
- return typeof content === 'function' ? content.call(this._element) : content;
425
+ _resolvePossibleFunction(arg) {
426
+ return typeof arg === 'function' ? arg.call(this._element) : arg;
467
427
  }
468
428
 
469
429
  _getPopperConfig(attachment) {
@@ -490,43 +450,46 @@
490
450
  element: `.${this.constructor.NAME}-arrow`
491
451
  }
492
452
  }, {
493
- name: 'onChange',
453
+ name: 'preSetPlacement',
494
454
  enabled: true,
495
- phase: 'afterWrite',
496
- fn: data => this._handlePopperPlacementChange(data)
497
- }],
498
- onFirstUpdate: data => {
499
- if (data.options.placement !== data.placement) {
500
- this._handlePopperPlacementChange(data);
455
+ phase: 'beforeMain',
456
+ fn: data => {
457
+ // Pre-set Popper's placement attribute in order to read the arrow sizes properly.
458
+ // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
459
+ this._getTipElement().setAttribute('data-popper-placement', data.state.placement);
501
460
  }
502
- }
461
+ }]
503
462
  };
504
463
  return { ...defaultBsPopperConfig,
505
464
  ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
506
465
  };
507
466
  }
508
467
 
509
- _addAttachmentClass(attachment) {
510
- this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`);
511
- }
512
-
513
- _getAttachment(placement) {
514
- return AttachmentMap[placement.toUpperCase()];
515
- }
516
-
517
468
  _setListeners() {
518
469
  const triggers = this._config.trigger.split(' ');
519
470
 
520
- triggers.forEach(trigger => {
471
+ for (const trigger of triggers) {
521
472
  if (trigger === 'click') {
522
- EventHandler__default.default.on(this._element, this.constructor.Event.CLICK, this._config.selector, event => this.toggle(event));
473
+ EventHandler__default.default.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => this.toggle(event));
523
474
  } else if (trigger !== TRIGGER_MANUAL) {
524
- const eventIn = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSEENTER : this.constructor.Event.FOCUSIN;
525
- const eventOut = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSELEAVE : this.constructor.Event.FOCUSOUT;
526
- EventHandler__default.default.on(this._element, eventIn, this._config.selector, event => this._enter(event));
527
- EventHandler__default.default.on(this._element, eventOut, this._config.selector, event => this._leave(event));
475
+ const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN);
476
+ const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT);
477
+ EventHandler__default.default.on(this._element, eventIn, this._config.selector, event => {
478
+ const context = this._initializeOnDelegatedTarget(event);
479
+
480
+ context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
481
+
482
+ context._enter();
483
+ });
484
+ EventHandler__default.default.on(this._element, eventOut, this._config.selector, event => {
485
+ const context = this._initializeOnDelegatedTarget(event);
486
+
487
+ context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
488
+
489
+ context._leave();
490
+ });
528
491
  }
529
- });
492
+ }
530
493
 
531
494
  this._hideModalHandler = () => {
532
495
  if (this._element) {
@@ -547,95 +510,78 @@
547
510
  }
548
511
 
549
512
  _fixTitle() {
550
- const title = this._element.getAttribute('title');
551
-
552
- const originalTitleType = typeof this._element.getAttribute('data-bs-original-title');
553
-
554
- if (title || originalTitleType !== 'string') {
555
- this._element.setAttribute('data-bs-original-title', title || '');
556
-
557
- if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) {
558
- this._element.setAttribute('aria-label', title);
559
- }
560
-
561
- this._element.setAttribute('title', '');
562
- }
563
- }
513
+ const title = this._config.originalTitle;
564
514
 
565
- _enter(event, context) {
566
- context = this._initializeOnDelegatedTarget(event, context);
567
-
568
- if (event) {
569
- context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
515
+ if (!title) {
516
+ return;
570
517
  }
571
518
 
572
- if (context.getTipElement().classList.contains(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {
573
- context._hoverState = HOVER_STATE_SHOW;
574
- return;
519
+ if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {
520
+ this._element.setAttribute('aria-label', title);
575
521
  }
576
522
 
577
- clearTimeout(context._timeout);
578
- context._hoverState = HOVER_STATE_SHOW;
523
+ this._element.removeAttribute('title');
524
+ }
579
525
 
580
- if (!context._config.delay || !context._config.delay.show) {
581
- context.show();
526
+ _enter() {
527
+ if (this._isShown() || this._isHovered) {
528
+ this._isHovered = true;
582
529
  return;
583
530
  }
584
531
 
585
- context._timeout = setTimeout(() => {
586
- if (context._hoverState === HOVER_STATE_SHOW) {
587
- context.show();
532
+ this._isHovered = true;
533
+
534
+ this._setTimeout(() => {
535
+ if (this._isHovered) {
536
+ this.show();
588
537
  }
589
- }, context._config.delay.show);
538
+ }, this._config.delay.show);
590
539
  }
591
540
 
592
- _leave(event, context) {
593
- context = this._initializeOnDelegatedTarget(event, context);
594
-
595
- if (event) {
596
- context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
597
- }
598
-
599
- if (context._isWithActiveTrigger()) {
541
+ _leave() {
542
+ if (this._isWithActiveTrigger()) {
600
543
  return;
601
544
  }
602
545
 
603
- clearTimeout(context._timeout);
604
- context._hoverState = HOVER_STATE_OUT;
605
-
606
- if (!context._config.delay || !context._config.delay.hide) {
607
- context.hide();
608
- return;
609
- }
546
+ this._isHovered = false;
610
547
 
611
- context._timeout = setTimeout(() => {
612
- if (context._hoverState === HOVER_STATE_OUT) {
613
- context.hide();
548
+ this._setTimeout(() => {
549
+ if (!this._isHovered) {
550
+ this.hide();
614
551
  }
615
- }, context._config.delay.hide);
552
+ }, this._config.delay.hide);
616
553
  }
617
554
 
618
- _isWithActiveTrigger() {
619
- for (const trigger in this._activeTrigger) {
620
- if (this._activeTrigger[trigger]) {
621
- return true;
622
- }
623
- }
555
+ _setTimeout(handler, timeout) {
556
+ clearTimeout(this._timeout);
557
+ this._timeout = setTimeout(handler, timeout);
558
+ }
624
559
 
625
- return false;
560
+ _isWithActiveTrigger() {
561
+ return Object.values(this._activeTrigger).includes(true);
626
562
  }
627
563
 
628
564
  _getConfig(config) {
629
565
  const dataAttributes = Manipulator__default.default.getDataAttributes(this._element);
630
- Object.keys(dataAttributes).forEach(dataAttr => {
631
- if (DISALLOWED_ATTRIBUTES.has(dataAttr)) {
632
- delete dataAttributes[dataAttr];
566
+
567
+ for (const dataAttribute of Object.keys(dataAttributes)) {
568
+ if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
569
+ delete dataAttributes[dataAttribute];
633
570
  }
634
- });
635
- config = { ...this.constructor.Default,
636
- ...dataAttributes,
571
+ }
572
+
573
+ config = { ...dataAttributes,
637
574
  ...(typeof config === 'object' && config ? config : {})
638
575
  };
576
+ config = this._mergeConfigObj(config);
577
+ config = this._configAfterMerge(config);
578
+
579
+ this._typeCheckConfig(config);
580
+
581
+ return config;
582
+ }
583
+
584
+ _configAfterMerge(config) {
639
585
  config.container = config.container === false ? document.body : index.getElement(config.container);
640
586
 
641
587
  if (typeof config.delay === 'number') {
@@ -645,6 +591,8 @@
645
591
  };
646
592
  }
647
593
 
594
+ config.originalTitle = this._element.getAttribute('title') || '';
595
+
648
596
  if (typeof config.title === 'number') {
649
597
  config.title = config.title.toString();
650
598
  }
@@ -653,12 +601,6 @@
653
601
  config.content = config.content.toString();
654
602
  }
655
603
 
656
- index.typeCheckConfig(NAME, config, this.constructor.DefaultType);
657
-
658
- if (config.sanitize) {
659
- config.template = sanitizer.sanitizeHtml(config.template, config.allowList, config.sanitizeFn);
660
- }
661
-
662
604
  return config;
663
605
  }
664
606
 
@@ -677,36 +619,6 @@
677
619
  return config;
678
620
  }
679
621
 
680
- _cleanTipClass() {
681
- const tip = this.getTipElement();
682
- const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g');
683
- const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex);
684
-
685
- if (tabClass !== null && tabClass.length > 0) {
686
- tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass));
687
- }
688
- }
689
-
690
- _getBasicClassPrefix() {
691
- return CLASS_PREFIX;
692
- }
693
-
694
- _handlePopperPlacementChange(popperData) {
695
- const {
696
- state
697
- } = popperData;
698
-
699
- if (!state) {
700
- return;
701
- }
702
-
703
- this.tip = state.elements.popper;
704
-
705
- this._cleanTipClass();
706
-
707
- this._addAttachmentClass(this._getAttachment(state.placement));
708
- }
709
-
710
622
  _disposePopper() {
711
623
  if (this._popper) {
712
624
  this._popper.destroy();
@@ -720,22 +632,21 @@
720
632
  return this.each(function () {
721
633
  const data = Tooltip.getOrCreateInstance(this, config);
722
634
 
723
- if (typeof config === 'string') {
724
- if (typeof data[config] === 'undefined') {
725
- throw new TypeError(`No method named "${config}"`);
726
- }
635
+ if (typeof config !== 'string') {
636
+ return;
637
+ }
727
638
 
728
- data[config]();
639
+ if (typeof data[config] === 'undefined') {
640
+ throw new TypeError(`No method named "${config}"`);
729
641
  }
642
+
643
+ data[config]();
730
644
  });
731
645
  }
732
646
 
733
647
  }
734
648
  /**
735
- * ------------------------------------------------------------------------
736
649
  * jQuery
737
- * ------------------------------------------------------------------------
738
- * add .Tooltip to jQuery only if jQuery is present
739
650
  */
740
651
 
741
652