bootstrap 5.1.1 → 5.2.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/assets/javascripts/bootstrap/alert.js +18 -153
  4. data/assets/javascripts/bootstrap/base-component.js +44 -127
  5. data/assets/javascripts/bootstrap/button.js +16 -80
  6. data/assets/javascripts/bootstrap/carousel.js +225 -497
  7. data/assets/javascripts/bootstrap/collapse.js +79 -262
  8. data/assets/javascripts/bootstrap/dom/data.js +6 -8
  9. data/assets/javascripts/bootstrap/dom/event-handler.js +95 -133
  10. data/assets/javascripts/bootstrap/dom/manipulator.js +25 -29
  11. data/assets/javascripts/bootstrap/dom/selector-engine.js +17 -59
  12. data/assets/javascripts/bootstrap/dropdown.js +124 -342
  13. data/assets/javascripts/bootstrap/modal.js +122 -767
  14. data/assets/javascripts/bootstrap/offcanvas.js +102 -671
  15. data/assets/javascripts/bootstrap/popover.js +42 -124
  16. data/assets/javascripts/bootstrap/scrollspy.js +186 -269
  17. data/assets/javascripts/bootstrap/tab.js +222 -221
  18. data/assets/javascripts/bootstrap/toast.js +41 -227
  19. data/assets/javascripts/bootstrap/tooltip.js +283 -629
  20. data/assets/javascripts/bootstrap/util/backdrop.js +165 -0
  21. data/assets/javascripts/bootstrap/util/component-functions.js +46 -0
  22. data/assets/javascripts/bootstrap/util/config.js +79 -0
  23. data/assets/javascripts/bootstrap/util/focustrap.js +129 -0
  24. data/assets/javascripts/bootstrap/util/index.js +350 -0
  25. data/assets/javascripts/bootstrap/util/sanitizer.js +122 -0
  26. data/assets/javascripts/bootstrap/util/scrollbar.js +138 -0
  27. data/assets/javascripts/bootstrap/util/swipe.js +155 -0
  28. data/assets/javascripts/bootstrap/util/template-factory.js +177 -0
  29. data/assets/javascripts/bootstrap-global-this-define.js +1 -1
  30. data/assets/javascripts/bootstrap-sprockets.js +16 -7
  31. data/assets/javascripts/bootstrap.js +2094 -1891
  32. data/assets/javascripts/bootstrap.min.js +3 -3
  33. data/assets/stylesheets/_bootstrap-grid.scss +3 -6
  34. data/assets/stylesheets/_bootstrap-reboot.scss +3 -7
  35. data/assets/stylesheets/_bootstrap.scss +4 -6
  36. data/assets/stylesheets/bootstrap/_accordion.scss +52 -24
  37. data/assets/stylesheets/bootstrap/_alert.scss +18 -4
  38. data/assets/stylesheets/bootstrap/_badge.scss +14 -5
  39. data/assets/stylesheets/bootstrap/_breadcrumb.scss +22 -10
  40. data/assets/stylesheets/bootstrap/_button-group.scss +3 -0
  41. data/assets/stylesheets/bootstrap/_buttons.scss +97 -22
  42. data/assets/stylesheets/bootstrap/_card.scss +55 -37
  43. data/assets/stylesheets/bootstrap/_close.scss +1 -1
  44. data/assets/stylesheets/bootstrap/_containers.scss +1 -1
  45. data/assets/stylesheets/bootstrap/_dropdown.scss +83 -75
  46. data/assets/stylesheets/bootstrap/_functions.scss +7 -7
  47. data/assets/stylesheets/bootstrap/_grid.scss +3 -3
  48. data/assets/stylesheets/bootstrap/_helpers.scss +1 -0
  49. data/assets/stylesheets/bootstrap/_list-group.scss +44 -27
  50. data/assets/stylesheets/bootstrap/_maps.scss +54 -0
  51. data/assets/stylesheets/bootstrap/_modal.scss +71 -43
  52. data/assets/stylesheets/bootstrap/_nav.scss +53 -20
  53. data/assets/stylesheets/bootstrap/_navbar.scss +91 -150
  54. data/assets/stylesheets/bootstrap/_offcanvas.scss +119 -59
  55. data/assets/stylesheets/bootstrap/_pagination.scss +66 -21
  56. data/assets/stylesheets/bootstrap/_placeholders.scss +1 -1
  57. data/assets/stylesheets/bootstrap/_popover.scss +90 -52
  58. data/assets/stylesheets/bootstrap/_progress.scss +20 -9
  59. data/assets/stylesheets/bootstrap/_reboot.scss +25 -40
  60. data/assets/stylesheets/bootstrap/_root.scss +40 -21
  61. data/assets/stylesheets/bootstrap/_spinners.scss +38 -22
  62. data/assets/stylesheets/bootstrap/_tables.scss +38 -25
  63. data/assets/stylesheets/bootstrap/_toasts.scss +35 -16
  64. data/assets/stylesheets/bootstrap/_tooltip.scss +61 -56
  65. data/assets/stylesheets/bootstrap/_type.scss +2 -0
  66. data/assets/stylesheets/bootstrap/_utilities.scss +43 -26
  67. data/assets/stylesheets/bootstrap/_variables.scss +118 -124
  68. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +3 -6
  69. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +14 -3
  70. data/assets/stylesheets/bootstrap/forms/_form-check.scss +28 -5
  71. data/assets/stylesheets/bootstrap/forms/_form-control.scss +12 -37
  72. data/assets/stylesheets/bootstrap/forms/_form-select.scss +2 -1
  73. data/assets/stylesheets/bootstrap/forms/_input-group.scss +15 -7
  74. data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +10 -0
  75. data/assets/stylesheets/bootstrap/helpers/_colored-links.scss +2 -2
  76. data/assets/stylesheets/bootstrap/helpers/_position.scss +7 -1
  77. data/assets/stylesheets/bootstrap/helpers/_ratio.scss +2 -2
  78. data/assets/stylesheets/bootstrap/helpers/_vr.scss +1 -1
  79. data/assets/stylesheets/bootstrap/mixins/_alert.scss +7 -3
  80. data/assets/stylesheets/bootstrap/mixins/_banner.scss +9 -0
  81. data/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +8 -8
  82. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +32 -95
  83. data/assets/stylesheets/bootstrap/mixins/_container.scss +4 -2
  84. data/assets/stylesheets/bootstrap/mixins/_forms.scss +8 -0
  85. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +1 -1
  86. data/assets/stylesheets/bootstrap/mixins/_grid.scss +13 -12
  87. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +4 -25
  88. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +1 -1
  89. data/assets/stylesheets/bootstrap/mixins/_table-variants.scss +12 -9
  90. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +12 -4
  91. data/assets/stylesheets/bootstrap/mixins/_visually-hidden.scss +1 -1
  92. data/bootstrap.gemspec +1 -1
  93. data/lib/bootstrap/version.rb +2 -2
  94. data/tasks/updater/js.rb +9 -4
  95. metadata +16 -4
@@ -1,405 +1,137 @@
1
1
  /*!
2
- * Bootstrap tooltip.js v5.1.1 (https://getbootstrap.com/)
3
- * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap tooltip.js v5.2.0 (https://getbootstrap.com/)
3
+ * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
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('@popperjs/core'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) :
8
- typeof define === 'function' && define.amd ? define(['@popperjs/core', './dom/data', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global.Popper, global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base));
10
- }(this, (function (Popper, Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
7
+ 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')) :
8
+ typeof define === 'function' && define.amd ? define(['@popperjs/core', './util/index', './util/sanitizer', './dom/event-handler', './dom/manipulator', './base-component', './util/template-factory'], factory) :
9
+ (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));
10
+ })(this, (function (Popper, index, sanitizer, EventHandler, Manipulator, BaseComponent, TemplateFactory) { 'use strict';
11
11
 
12
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
+ const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
13
 
14
14
  function _interopNamespace(e) {
15
15
  if (e && e.__esModule) return e;
16
- var n = Object.create(null);
16
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
17
17
  if (e) {
18
- Object.keys(e).forEach(function (k) {
18
+ for (const k in e) {
19
19
  if (k !== 'default') {
20
- var d = Object.getOwnPropertyDescriptor(e, k);
20
+ const d = Object.getOwnPropertyDescriptor(e, k);
21
21
  Object.defineProperty(n, k, d.get ? d : {
22
22
  enumerable: true,
23
- get: function () {
24
- return e[k];
25
- }
23
+ get: () => e[k]
26
24
  });
27
25
  }
28
- });
26
+ }
29
27
  }
30
- n['default'] = e;
28
+ n.default = e;
31
29
  return Object.freeze(n);
32
30
  }
33
31
 
34
- var Popper__namespace = /*#__PURE__*/_interopNamespace(Popper);
35
- var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
36
- var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
37
- var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
38
- var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
39
- var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
40
-
41
- /**
42
- * --------------------------------------------------------------------------
43
- * Bootstrap (v5.1.1): util/index.js
44
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
45
- * --------------------------------------------------------------------------
46
- */
47
- const MAX_UID = 1000000;
48
-
49
- const toType = obj => {
50
- if (obj === null || obj === undefined) {
51
- return `${obj}`;
52
- }
53
-
54
- return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
55
- };
56
- /**
57
- * --------------------------------------------------------------------------
58
- * Public Util Api
59
- * --------------------------------------------------------------------------
60
- */
61
-
62
-
63
- const getUID = prefix => {
64
- do {
65
- prefix += Math.floor(Math.random() * MAX_UID);
66
- } while (document.getElementById(prefix));
67
-
68
- return prefix;
69
- };
70
-
71
- const isElement = obj => {
72
- if (!obj || typeof obj !== 'object') {
73
- return false;
74
- }
75
-
76
- if (typeof obj.jquery !== 'undefined') {
77
- obj = obj[0];
78
- }
79
-
80
- return typeof obj.nodeType !== 'undefined';
81
- };
82
-
83
- const getElement = obj => {
84
- if (isElement(obj)) {
85
- // it's a jQuery object or a node element
86
- return obj.jquery ? obj[0] : obj;
87
- }
88
-
89
- if (typeof obj === 'string' && obj.length > 0) {
90
- return document.querySelector(obj);
91
- }
92
-
93
- return null;
94
- };
95
-
96
- const typeCheckConfig = (componentName, config, configTypes) => {
97
- Object.keys(configTypes).forEach(property => {
98
- const expectedTypes = configTypes[property];
99
- const value = config[property];
100
- const valueType = value && isElement(value) ? 'element' : toType(value);
101
-
102
- if (!new RegExp(expectedTypes).test(valueType)) {
103
- throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
104
- }
105
- });
106
- };
107
-
108
- const findShadowRoot = element => {
109
- if (!document.documentElement.attachShadow) {
110
- return null;
111
- } // Can find the shadow root otherwise it'll return the document
112
-
113
-
114
- if (typeof element.getRootNode === 'function') {
115
- const root = element.getRootNode();
116
- return root instanceof ShadowRoot ? root : null;
117
- }
118
-
119
- if (element instanceof ShadowRoot) {
120
- return element;
121
- } // when we don't find a shadow root
122
-
123
-
124
- if (!element.parentNode) {
125
- return null;
126
- }
127
-
128
- return findShadowRoot(element.parentNode);
129
- };
130
-
131
- const noop = () => {};
132
-
133
- const getjQuery = () => {
134
- const {
135
- jQuery
136
- } = window;
137
-
138
- if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
139
- return jQuery;
140
- }
141
-
142
- return null;
143
- };
144
-
145
- const DOMContentLoadedCallbacks = [];
146
-
147
- const onDOMContentLoaded = callback => {
148
- if (document.readyState === 'loading') {
149
- // add listener on the first call when the document is in loading state
150
- if (!DOMContentLoadedCallbacks.length) {
151
- document.addEventListener('DOMContentLoaded', () => {
152
- DOMContentLoadedCallbacks.forEach(callback => callback());
153
- });
154
- }
155
-
156
- DOMContentLoadedCallbacks.push(callback);
157
- } else {
158
- callback();
159
- }
160
- };
161
-
162
- const isRTL = () => document.documentElement.dir === 'rtl';
163
-
164
- const defineJQueryPlugin = plugin => {
165
- onDOMContentLoaded(() => {
166
- const $ = getjQuery();
167
- /* istanbul ignore if */
168
-
169
- if ($) {
170
- const name = plugin.NAME;
171
- const JQUERY_NO_CONFLICT = $.fn[name];
172
- $.fn[name] = plugin.jQueryInterface;
173
- $.fn[name].Constructor = plugin;
174
-
175
- $.fn[name].noConflict = () => {
176
- $.fn[name] = JQUERY_NO_CONFLICT;
177
- return plugin.jQueryInterface;
178
- };
179
- }
180
- });
181
- };
182
-
183
- /**
184
- * --------------------------------------------------------------------------
185
- * Bootstrap (v5.1.1): util/sanitizer.js
186
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
187
- * --------------------------------------------------------------------------
188
- */
189
- const uriAttrs = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']);
190
- const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
191
- /**
192
- * A pattern that recognizes a commonly useful subset of URLs that are safe.
193
- *
194
- * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
195
- */
196
-
197
- const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i;
198
- /**
199
- * A pattern that matches safe data URLs. Only matches image, video and audio types.
200
- *
201
- * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
202
- */
203
-
204
- const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;
205
-
206
- const allowedAttribute = (attr, allowedAttributeList) => {
207
- const attrName = attr.nodeName.toLowerCase();
208
-
209
- if (allowedAttributeList.includes(attrName)) {
210
- if (uriAttrs.has(attrName)) {
211
- return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue));
212
- }
213
-
214
- return true;
215
- }
216
-
217
- const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp); // Check if a regular expression validates the attribute.
218
-
219
- for (let i = 0, len = regExp.length; i < len; i++) {
220
- if (regExp[i].test(attrName)) {
221
- return true;
222
- }
223
- }
224
-
225
- return false;
226
- };
227
-
228
- const DefaultAllowlist = {
229
- // Global attributes allowed on any supplied element below.
230
- '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
231
- a: ['target', 'href', 'title', 'rel'],
232
- area: [],
233
- b: [],
234
- br: [],
235
- col: [],
236
- code: [],
237
- div: [],
238
- em: [],
239
- hr: [],
240
- h1: [],
241
- h2: [],
242
- h3: [],
243
- h4: [],
244
- h5: [],
245
- h6: [],
246
- i: [],
247
- img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
248
- li: [],
249
- ol: [],
250
- p: [],
251
- pre: [],
252
- s: [],
253
- small: [],
254
- span: [],
255
- sub: [],
256
- sup: [],
257
- strong: [],
258
- u: [],
259
- ul: []
260
- };
261
- function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
262
- if (!unsafeHtml.length) {
263
- return unsafeHtml;
264
- }
265
-
266
- if (sanitizeFn && typeof sanitizeFn === 'function') {
267
- return sanitizeFn(unsafeHtml);
268
- }
269
-
270
- const domParser = new window.DOMParser();
271
- const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
272
- const allowlistKeys = Object.keys(allowList);
273
- const elements = [].concat(...createdDocument.body.querySelectorAll('*'));
274
-
275
- for (let i = 0, len = elements.length; i < len; i++) {
276
- const el = elements[i];
277
- const elName = el.nodeName.toLowerCase();
278
-
279
- if (!allowlistKeys.includes(elName)) {
280
- el.remove();
281
- continue;
282
- }
283
-
284
- const attributeList = [].concat(...el.attributes);
285
- const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []);
286
- attributeList.forEach(attr => {
287
- if (!allowedAttribute(attr, allowedAttributes)) {
288
- el.removeAttribute(attr.nodeName);
289
- }
290
- });
291
- }
292
-
293
- return createdDocument.body.innerHTML;
294
- }
32
+ const Popper__namespace = /*#__PURE__*/_interopNamespace(Popper);
33
+ const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
34
+ const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
35
+ const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
36
+ const TemplateFactory__default = /*#__PURE__*/_interopDefaultLegacy(TemplateFactory);
295
37
 
296
38
  /**
297
39
  * --------------------------------------------------------------------------
298
- * Bootstrap (v5.1.1): tooltip.js
40
+ * Bootstrap (v5.2.0): tooltip.js
299
41
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
300
42
  * --------------------------------------------------------------------------
301
43
  */
302
44
  /**
303
- * ------------------------------------------------------------------------
304
45
  * Constants
305
- * ------------------------------------------------------------------------
306
46
  */
307
47
 
308
48
  const NAME = 'tooltip';
309
- const DATA_KEY = 'bs.tooltip';
310
- const EVENT_KEY = `.${DATA_KEY}`;
311
- const CLASS_PREFIX = 'bs-tooltip';
312
49
  const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
313
- const DefaultType = {
314
- animation: 'boolean',
315
- template: 'string',
316
- title: '(string|element|function)',
317
- trigger: 'string',
318
- delay: '(number|object)',
319
- html: 'boolean',
320
- selector: '(string|boolean)',
321
- placement: '(string|function)',
322
- offset: '(array|string|function)',
323
- container: '(string|element|boolean)',
324
- fallbackPlacements: 'array',
325
- boundary: '(string|element)',
326
- customClass: '(string|function)',
327
- sanitize: 'boolean',
328
- sanitizeFn: '(null|function)',
329
- allowList: 'object',
330
- popperConfig: '(null|object|function)'
331
- };
50
+ const CLASS_NAME_FADE = 'fade';
51
+ const CLASS_NAME_MODAL = 'modal';
52
+ const CLASS_NAME_SHOW = 'show';
53
+ const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
54
+ const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
55
+ const EVENT_MODAL_HIDE = 'hide.bs.modal';
56
+ const TRIGGER_HOVER = 'hover';
57
+ const TRIGGER_FOCUS = 'focus';
58
+ const TRIGGER_CLICK = 'click';
59
+ const TRIGGER_MANUAL = 'manual';
60
+ const EVENT_HIDE = 'hide';
61
+ const EVENT_HIDDEN = 'hidden';
62
+ const EVENT_SHOW = 'show';
63
+ const EVENT_SHOWN = 'shown';
64
+ const EVENT_INSERTED = 'inserted';
65
+ const EVENT_CLICK = 'click';
66
+ const EVENT_FOCUSIN = 'focusin';
67
+ const EVENT_FOCUSOUT = 'focusout';
68
+ const EVENT_MOUSEENTER = 'mouseenter';
69
+ const EVENT_MOUSELEAVE = 'mouseleave';
332
70
  const AttachmentMap = {
333
71
  AUTO: 'auto',
334
72
  TOP: 'top',
335
- RIGHT: isRTL() ? 'left' : 'right',
73
+ RIGHT: index.isRTL() ? 'left' : 'right',
336
74
  BOTTOM: 'bottom',
337
- LEFT: isRTL() ? 'right' : 'left'
75
+ LEFT: index.isRTL() ? 'right' : 'left'
338
76
  };
339
77
  const Default = {
78
+ allowList: sanitizer.DefaultAllowlist,
340
79
  animation: true,
341
- template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
342
- trigger: 'hover focus',
343
- title: '',
80
+ boundary: 'clippingParents',
81
+ container: false,
82
+ customClass: '',
344
83
  delay: 0,
84
+ fallbackPlacements: ['top', 'right', 'bottom', 'left'],
345
85
  html: false,
346
- selector: false,
347
- placement: 'top',
348
86
  offset: [0, 0],
349
- container: false,
350
- fallbackPlacements: ['top', 'right', 'bottom', 'left'],
351
- boundary: 'clippingParents',
352
- customClass: '',
87
+ placement: 'top',
88
+ popperConfig: null,
353
89
  sanitize: true,
354
90
  sanitizeFn: null,
355
- allowList: DefaultAllowlist,
356
- popperConfig: null
91
+ selector: false,
92
+ template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
93
+ title: '',
94
+ trigger: 'hover focus'
357
95
  };
358
- const Event = {
359
- HIDE: `hide${EVENT_KEY}`,
360
- HIDDEN: `hidden${EVENT_KEY}`,
361
- SHOW: `show${EVENT_KEY}`,
362
- SHOWN: `shown${EVENT_KEY}`,
363
- INSERTED: `inserted${EVENT_KEY}`,
364
- CLICK: `click${EVENT_KEY}`,
365
- FOCUSIN: `focusin${EVENT_KEY}`,
366
- FOCUSOUT: `focusout${EVENT_KEY}`,
367
- MOUSEENTER: `mouseenter${EVENT_KEY}`,
368
- MOUSELEAVE: `mouseleave${EVENT_KEY}`
96
+ const DefaultType = {
97
+ allowList: 'object',
98
+ animation: 'boolean',
99
+ boundary: '(string|element)',
100
+ container: '(string|element|boolean)',
101
+ customClass: '(string|function)',
102
+ delay: '(number|object)',
103
+ fallbackPlacements: 'array',
104
+ html: 'boolean',
105
+ offset: '(array|string|function)',
106
+ placement: '(string|function)',
107
+ popperConfig: '(null|object|function)',
108
+ sanitize: 'boolean',
109
+ sanitizeFn: '(null|function)',
110
+ selector: '(string|boolean)',
111
+ template: 'string',
112
+ title: '(string|element|function)',
113
+ trigger: 'string'
369
114
  };
370
- const CLASS_NAME_FADE = 'fade';
371
- const CLASS_NAME_MODAL = 'modal';
372
- const CLASS_NAME_SHOW = 'show';
373
- const HOVER_STATE_SHOW = 'show';
374
- const HOVER_STATE_OUT = 'out';
375
- const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
376
- const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
377
- const EVENT_MODAL_HIDE = 'hide.bs.modal';
378
- const TRIGGER_HOVER = 'hover';
379
- const TRIGGER_FOCUS = 'focus';
380
- const TRIGGER_CLICK = 'click';
381
- const TRIGGER_MANUAL = 'manual';
382
115
  /**
383
- * ------------------------------------------------------------------------
384
- * Class Definition
385
- * ------------------------------------------------------------------------
116
+ * Class definition
386
117
  */
387
118
 
388
- class Tooltip extends BaseComponent__default['default'] {
119
+ class Tooltip extends BaseComponent__default.default {
389
120
  constructor(element, config) {
390
121
  if (typeof Popper__namespace === 'undefined') {
391
122
  throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
392
123
  }
393
124
 
394
- super(element); // private
125
+ super(element, config); // Private
395
126
 
396
127
  this._isEnabled = true;
397
128
  this._timeout = 0;
398
- this._hoverState = '';
129
+ this._isHovered = false;
399
130
  this._activeTrigger = {};
400
- this._popper = null; // Protected
131
+ this._popper = null;
132
+ this._templateFactory = null;
133
+ this._newContent = null; // Protected
401
134
 
402
- this._config = this._getConfig(config);
403
135
  this.tip = null;
404
136
 
405
137
  this._setListeners();
@@ -410,16 +142,12 @@
410
142
  return Default;
411
143
  }
412
144
 
413
- static get NAME() {
414
- return NAME;
415
- }
416
-
417
- static get Event() {
418
- return Event;
419
- }
420
-
421
145
  static get DefaultType() {
422
146
  return DefaultType;
147
+ }
148
+
149
+ static get NAME() {
150
+ return NAME;
423
151
  } // Public
424
152
 
425
153
 
@@ -446,24 +174,26 @@
446
174
  context._activeTrigger.click = !context._activeTrigger.click;
447
175
 
448
176
  if (context._isWithActiveTrigger()) {
449
- context._enter(null, context);
177
+ context._enter();
450
178
  } else {
451
- context._leave(null, context);
179
+ context._leave();
452
180
  }
453
- } else {
454
- if (this.getTipElement().classList.contains(CLASS_NAME_SHOW)) {
455
- this._leave(null, this);
456
181
 
457
- return;
458
- }
182
+ return;
183
+ }
184
+
185
+ if (this._isShown()) {
186
+ this._leave();
459
187
 
460
- this._enter(null, this);
188
+ return;
461
189
  }
190
+
191
+ this._enter();
462
192
  }
463
193
 
464
194
  dispose() {
465
195
  clearTimeout(this._timeout);
466
- EventHandler__default['default'].off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
196
+ EventHandler__default.default.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
467
197
 
468
198
  if (this.tip) {
469
199
  this.tip.remove();
@@ -479,233 +209,206 @@
479
209
  throw new Error('Please use show on visible elements');
480
210
  }
481
211
 
482
- if (!(this.isWithContent() && this._isEnabled)) {
212
+ if (!(this._isWithContent() && this._isEnabled)) {
483
213
  return;
484
214
  }
485
215
 
486
- const showEvent = EventHandler__default['default'].trigger(this._element, this.constructor.Event.SHOW);
487
- const shadowRoot = findShadowRoot(this._element);
488
- const isInTheDom = shadowRoot === null ? this._element.ownerDocument.documentElement.contains(this._element) : shadowRoot.contains(this._element);
216
+ const showEvent = EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_SHOW));
217
+ const shadowRoot = index.findShadowRoot(this._element);
218
+
219
+ const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);
489
220
 
490
221
  if (showEvent.defaultPrevented || !isInTheDom) {
491
222
  return;
492
- } // A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title`
493
- // This will be removed later in favor of a `setContent` method
223
+ } // todo v6 remove this OR make it optional
494
224
 
495
225
 
496
- if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) {
497
- this._disposePopper();
498
-
226
+ if (this.tip) {
499
227
  this.tip.remove();
500
228
  this.tip = null;
501
229
  }
502
230
 
503
- const tip = this.getTipElement();
504
- const tipId = getUID(this.constructor.NAME);
505
- tip.setAttribute('id', tipId);
506
-
507
- this._element.setAttribute('aria-describedby', tipId);
231
+ const tip = this._getTipElement();
508
232
 
509
- if (this._config.animation) {
510
- tip.classList.add(CLASS_NAME_FADE);
511
- }
512
-
513
- const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;
514
-
515
- const attachment = this._getAttachment(placement);
516
-
517
- this._addAttachmentClass(attachment);
233
+ this._element.setAttribute('aria-describedby', tip.getAttribute('id'));
518
234
 
519
235
  const {
520
236
  container
521
237
  } = this._config;
522
- Data__default['default'].set(tip, this.constructor.DATA_KEY, this);
523
238
 
524
239
  if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
525
240
  container.append(tip);
526
- EventHandler__default['default'].trigger(this._element, this.constructor.Event.INSERTED);
241
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));
527
242
  }
528
243
 
529
244
  if (this._popper) {
530
245
  this._popper.update();
531
246
  } else {
532
- this._popper = Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
247
+ this._popper = this._createPopper(tip);
533
248
  }
534
249
 
535
- tip.classList.add(CLASS_NAME_SHOW);
536
-
537
- const customClass = this._resolvePossibleFunction(this._config.customClass);
538
-
539
- if (customClass) {
540
- tip.classList.add(...customClass.split(' '));
541
- } // If this is a touch-enabled device we add extra
250
+ tip.classList.add(CLASS_NAME_SHOW); // If this is a touch-enabled device we add extra
542
251
  // empty mouseover listeners to the body's immediate children;
543
252
  // only needed because of broken event delegation on iOS
544
253
  // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
545
254
 
546
-
547
255
  if ('ontouchstart' in document.documentElement) {
548
- [].concat(...document.body.children).forEach(element => {
549
- EventHandler__default['default'].on(element, 'mouseover', noop);
550
- });
256
+ for (const element of [].concat(...document.body.children)) {
257
+ EventHandler__default.default.on(element, 'mouseover', index.noop);
258
+ }
551
259
  }
552
260
 
553
261
  const complete = () => {
554
- const prevHoverState = this._hoverState;
555
- this._hoverState = null;
556
- EventHandler__default['default'].trigger(this._element, this.constructor.Event.SHOWN);
262
+ const previousHoverState = this._isHovered;
263
+ this._isHovered = false;
264
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_SHOWN));
557
265
 
558
- if (prevHoverState === HOVER_STATE_OUT) {
559
- this._leave(null, this);
266
+ if (previousHoverState) {
267
+ this._leave();
560
268
  }
561
269
  };
562
270
 
563
- const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
564
-
565
- this._queueCallback(complete, this.tip, isAnimated);
271
+ this._queueCallback(complete, this.tip, this._isAnimated());
566
272
  }
567
273
 
568
274
  hide() {
569
- if (!this._popper) {
275
+ if (!this._isShown()) {
570
276
  return;
571
277
  }
572
278
 
573
- const tip = this.getTipElement();
574
-
575
- const complete = () => {
576
- if (this._isWithActiveTrigger()) {
577
- return;
578
- }
579
-
580
- if (this._hoverState !== HOVER_STATE_SHOW) {
581
- tip.remove();
582
- }
583
-
584
- this._cleanTipClass();
585
-
586
- this._element.removeAttribute('aria-describedby');
587
-
588
- EventHandler__default['default'].trigger(this._element, this.constructor.Event.HIDDEN);
589
-
590
- this._disposePopper();
591
- };
592
-
593
- const hideEvent = EventHandler__default['default'].trigger(this._element, this.constructor.Event.HIDE);
279
+ const hideEvent = EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_HIDE));
594
280
 
595
281
  if (hideEvent.defaultPrevented) {
596
282
  return;
597
283
  }
598
284
 
285
+ const tip = this._getTipElement();
286
+
599
287
  tip.classList.remove(CLASS_NAME_SHOW); // If this is a touch-enabled device we remove the extra
600
288
  // empty mouseover listeners we added for iOS support
601
289
 
602
290
  if ('ontouchstart' in document.documentElement) {
603
- [].concat(...document.body.children).forEach(element => EventHandler__default['default'].off(element, 'mouseover', noop));
291
+ for (const element of [].concat(...document.body.children)) {
292
+ EventHandler__default.default.off(element, 'mouseover', index.noop);
293
+ }
604
294
  }
605
295
 
606
296
  this._activeTrigger[TRIGGER_CLICK] = false;
607
297
  this._activeTrigger[TRIGGER_FOCUS] = false;
608
298
  this._activeTrigger[TRIGGER_HOVER] = false;
609
- const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
299
+ this._isHovered = false;
300
+
301
+ const complete = () => {
302
+ if (this._isWithActiveTrigger()) {
303
+ return;
304
+ }
305
+
306
+ if (!this._isHovered) {
307
+ tip.remove();
308
+ }
309
+
310
+ this._element.removeAttribute('aria-describedby');
610
311
 
611
- this._queueCallback(complete, this.tip, isAnimated);
312
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN));
612
313
 
613
- this._hoverState = '';
314
+ this._disposePopper();
315
+ };
316
+
317
+ this._queueCallback(complete, this.tip, this._isAnimated());
614
318
  }
615
319
 
616
320
  update() {
617
- if (this._popper !== null) {
321
+ if (this._popper) {
618
322
  this._popper.update();
619
323
  }
620
324
  } // Protected
621
325
 
622
326
 
623
- isWithContent() {
624
- return Boolean(this.getTitle());
327
+ _isWithContent() {
328
+ return Boolean(this._getTitle());
625
329
  }
626
330
 
627
- getTipElement() {
628
- if (this.tip) {
629
- return this.tip;
331
+ _getTipElement() {
332
+ if (!this.tip) {
333
+ this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());
630
334
  }
631
335
 
632
- const element = document.createElement('div');
633
- element.innerHTML = this._config.template;
634
- const tip = element.children[0];
635
- this.setContent(tip);
636
- tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
637
- this.tip = tip;
638
336
  return this.tip;
639
337
  }
640
338
 
641
- setContent(tip) {
642
- this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER);
643
- }
339
+ _createTipElement(content) {
340
+ const tip = this._getTemplateFactory(content).toHtml(); // todo: remove this check on v6
644
341
 
645
- _sanitizeAndSetContent(template, content, selector) {
646
- const templateElement = SelectorEngine__default['default'].findOne(selector, template);
647
342
 
648
- if (!content && templateElement) {
649
- templateElement.remove();
650
- return;
651
- } // we use append for html objects to maintain js events
343
+ if (!tip) {
344
+ return null;
345
+ }
652
346
 
347
+ tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW); // todo: on v6 the following can be achieved with CSS only
653
348
 
654
- this.setElementContent(templateElement, content);
655
- }
349
+ tip.classList.add(`bs-${this.constructor.NAME}-auto`);
350
+ const tipId = index.getUID(this.constructor.NAME).toString();
351
+ tip.setAttribute('id', tipId);
656
352
 
657
- setElementContent(element, content) {
658
- if (element === null) {
659
- return;
353
+ if (this._isAnimated()) {
354
+ tip.classList.add(CLASS_NAME_FADE);
660
355
  }
661
356
 
662
- if (isElement(content)) {
663
- content = getElement(content); // content is a DOM node or a jQuery
357
+ return tip;
358
+ }
664
359
 
665
- if (this._config.html) {
666
- if (content.parentNode !== element) {
667
- element.innerHTML = '';
668
- element.append(content);
669
- }
670
- } else {
671
- element.textContent = content.textContent;
672
- }
360
+ setContent(content) {
361
+ this._newContent = content;
673
362
 
674
- return;
675
- }
363
+ if (this._isShown()) {
364
+ this._disposePopper();
676
365
 
677
- if (this._config.html) {
678
- if (this._config.sanitize) {
679
- content = sanitizeHtml(content, this._config.allowList, this._config.sanitizeFn);
680
- }
366
+ this.show();
367
+ }
368
+ }
681
369
 
682
- element.innerHTML = content;
370
+ _getTemplateFactory(content) {
371
+ if (this._templateFactory) {
372
+ this._templateFactory.changeContent(content);
683
373
  } else {
684
- element.textContent = content;
374
+ this._templateFactory = new TemplateFactory__default.default({ ...this._config,
375
+ // the `content` var has to be after `this._config`
376
+ // to override config.content in case of popover
377
+ content,
378
+ extraClass: this._resolvePossibleFunction(this._config.customClass)
379
+ });
685
380
  }
686
- }
687
381
 
688
- getTitle() {
689
- const title = this._element.getAttribute('data-bs-original-title') || this._config.title;
382
+ return this._templateFactory;
383
+ }
690
384
 
691
- return this._resolvePossibleFunction(title);
385
+ _getContentForTemplate() {
386
+ return {
387
+ [SELECTOR_TOOLTIP_INNER]: this._getTitle()
388
+ };
692
389
  }
693
390
 
694
- updateAttachment(attachment) {
695
- if (attachment === 'right') {
696
- return 'end';
697
- }
391
+ _getTitle() {
392
+ return this._resolvePossibleFunction(this._config.title) || this._config.originalTitle;
393
+ } // Private
698
394
 
699
- if (attachment === 'left') {
700
- return 'start';
701
- }
702
395
 
703
- return attachment;
704
- } // Private
396
+ _initializeOnDelegatedTarget(event) {
397
+ return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
398
+ }
399
+
400
+ _isAnimated() {
401
+ return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE);
402
+ }
705
403
 
404
+ _isShown() {
405
+ return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW);
406
+ }
706
407
 
707
- _initializeOnDelegatedTarget(event, context) {
708
- return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
408
+ _createPopper(tip) {
409
+ const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;
410
+ const attachment = AttachmentMap[placement.toUpperCase()];
411
+ return Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
709
412
  }
710
413
 
711
414
  _getOffset() {
@@ -714,7 +417,7 @@
714
417
  } = this._config;
715
418
 
716
419
  if (typeof offset === 'string') {
717
- return offset.split(',').map(val => Number.parseInt(val, 10));
420
+ return offset.split(',').map(value => Number.parseInt(value, 10));
718
421
  }
719
422
 
720
423
  if (typeof offset === 'function') {
@@ -724,8 +427,8 @@
724
427
  return offset;
725
428
  }
726
429
 
727
- _resolvePossibleFunction(content) {
728
- return typeof content === 'function' ? content.call(this._element) : content;
430
+ _resolvePossibleFunction(arg) {
431
+ return typeof arg === 'function' ? arg.call(this._element) : arg;
729
432
  }
730
433
 
731
434
  _getPopperConfig(attachment) {
@@ -752,43 +455,46 @@
752
455
  element: `.${this.constructor.NAME}-arrow`
753
456
  }
754
457
  }, {
755
- name: 'onChange',
458
+ name: 'preSetPlacement',
756
459
  enabled: true,
757
- phase: 'afterWrite',
758
- fn: data => this._handlePopperPlacementChange(data)
759
- }],
760
- onFirstUpdate: data => {
761
- if (data.options.placement !== data.placement) {
762
- this._handlePopperPlacementChange(data);
460
+ phase: 'beforeMain',
461
+ fn: data => {
462
+ // Pre-set Popper's placement attribute in order to read the arrow sizes properly.
463
+ // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
464
+ this._getTipElement().setAttribute('data-popper-placement', data.state.placement);
763
465
  }
764
- }
466
+ }]
765
467
  };
766
468
  return { ...defaultBsPopperConfig,
767
469
  ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
768
470
  };
769
471
  }
770
472
 
771
- _addAttachmentClass(attachment) {
772
- this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`);
773
- }
774
-
775
- _getAttachment(placement) {
776
- return AttachmentMap[placement.toUpperCase()];
777
- }
778
-
779
473
  _setListeners() {
780
474
  const triggers = this._config.trigger.split(' ');
781
475
 
782
- triggers.forEach(trigger => {
476
+ for (const trigger of triggers) {
783
477
  if (trigger === 'click') {
784
- EventHandler__default['default'].on(this._element, this.constructor.Event.CLICK, this._config.selector, event => this.toggle(event));
478
+ EventHandler__default.default.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => this.toggle(event));
785
479
  } else if (trigger !== TRIGGER_MANUAL) {
786
- const eventIn = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSEENTER : this.constructor.Event.FOCUSIN;
787
- const eventOut = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSELEAVE : this.constructor.Event.FOCUSOUT;
788
- EventHandler__default['default'].on(this._element, eventIn, this._config.selector, event => this._enter(event));
789
- EventHandler__default['default'].on(this._element, eventOut, this._config.selector, event => this._leave(event));
480
+ const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN);
481
+ const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT);
482
+ EventHandler__default.default.on(this._element, eventIn, this._config.selector, event => {
483
+ const context = this._initializeOnDelegatedTarget(event);
484
+
485
+ context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
486
+
487
+ context._enter();
488
+ });
489
+ EventHandler__default.default.on(this._element, eventOut, this._config.selector, event => {
490
+ const context = this._initializeOnDelegatedTarget(event);
491
+
492
+ context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
493
+
494
+ context._leave();
495
+ });
790
496
  }
791
- });
497
+ }
792
498
 
793
499
  this._hideModalHandler = () => {
794
500
  if (this._element) {
@@ -796,7 +502,7 @@
796
502
  }
797
503
  };
798
504
 
799
- EventHandler__default['default'].on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
505
+ EventHandler__default.default.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
800
506
 
801
507
  if (this._config.selector) {
802
508
  this._config = { ...this._config,
@@ -809,96 +515,79 @@
809
515
  }
810
516
 
811
517
  _fixTitle() {
812
- const title = this._element.getAttribute('title');
813
-
814
- const originalTitleType = typeof this._element.getAttribute('data-bs-original-title');
518
+ const title = this._config.originalTitle;
815
519
 
816
- if (title || originalTitleType !== 'string') {
817
- this._element.setAttribute('data-bs-original-title', title || '');
818
-
819
- if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) {
820
- this._element.setAttribute('aria-label', title);
821
- }
822
-
823
- this._element.setAttribute('title', '');
824
- }
825
- }
826
-
827
- _enter(event, context) {
828
- context = this._initializeOnDelegatedTarget(event, context);
829
-
830
- if (event) {
831
- context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
520
+ if (!title) {
521
+ return;
832
522
  }
833
523
 
834
- if (context.getTipElement().classList.contains(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {
835
- context._hoverState = HOVER_STATE_SHOW;
836
- return;
524
+ if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {
525
+ this._element.setAttribute('aria-label', title);
837
526
  }
838
527
 
839
- clearTimeout(context._timeout);
840
- context._hoverState = HOVER_STATE_SHOW;
528
+ this._element.removeAttribute('title');
529
+ }
841
530
 
842
- if (!context._config.delay || !context._config.delay.show) {
843
- context.show();
531
+ _enter() {
532
+ if (this._isShown() || this._isHovered) {
533
+ this._isHovered = true;
844
534
  return;
845
535
  }
846
536
 
847
- context._timeout = setTimeout(() => {
848
- if (context._hoverState === HOVER_STATE_SHOW) {
849
- context.show();
537
+ this._isHovered = true;
538
+
539
+ this._setTimeout(() => {
540
+ if (this._isHovered) {
541
+ this.show();
850
542
  }
851
- }, context._config.delay.show);
543
+ }, this._config.delay.show);
852
544
  }
853
545
 
854
- _leave(event, context) {
855
- context = this._initializeOnDelegatedTarget(event, context);
856
-
857
- if (event) {
858
- context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
859
- }
860
-
861
- if (context._isWithActiveTrigger()) {
546
+ _leave() {
547
+ if (this._isWithActiveTrigger()) {
862
548
  return;
863
549
  }
864
550
 
865
- clearTimeout(context._timeout);
866
- context._hoverState = HOVER_STATE_OUT;
867
-
868
- if (!context._config.delay || !context._config.delay.hide) {
869
- context.hide();
870
- return;
871
- }
551
+ this._isHovered = false;
872
552
 
873
- context._timeout = setTimeout(() => {
874
- if (context._hoverState === HOVER_STATE_OUT) {
875
- context.hide();
553
+ this._setTimeout(() => {
554
+ if (!this._isHovered) {
555
+ this.hide();
876
556
  }
877
- }, context._config.delay.hide);
557
+ }, this._config.delay.hide);
878
558
  }
879
559
 
880
- _isWithActiveTrigger() {
881
- for (const trigger in this._activeTrigger) {
882
- if (this._activeTrigger[trigger]) {
883
- return true;
884
- }
885
- }
560
+ _setTimeout(handler, timeout) {
561
+ clearTimeout(this._timeout);
562
+ this._timeout = setTimeout(handler, timeout);
563
+ }
886
564
 
887
- return false;
565
+ _isWithActiveTrigger() {
566
+ return Object.values(this._activeTrigger).includes(true);
888
567
  }
889
568
 
890
569
  _getConfig(config) {
891
- const dataAttributes = Manipulator__default['default'].getDataAttributes(this._element);
892
- Object.keys(dataAttributes).forEach(dataAttr => {
893
- if (DISALLOWED_ATTRIBUTES.has(dataAttr)) {
894
- delete dataAttributes[dataAttr];
570
+ const dataAttributes = Manipulator__default.default.getDataAttributes(this._element);
571
+
572
+ for (const dataAttribute of Object.keys(dataAttributes)) {
573
+ if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
574
+ delete dataAttributes[dataAttribute];
895
575
  }
896
- });
897
- config = { ...this.constructor.Default,
898
- ...dataAttributes,
576
+ }
577
+
578
+ config = { ...dataAttributes,
899
579
  ...(typeof config === 'object' && config ? config : {})
900
580
  };
901
- config.container = config.container === false ? document.body : getElement(config.container);
581
+ config = this._mergeConfigObj(config);
582
+ config = this._configAfterMerge(config);
583
+
584
+ this._typeCheckConfig(config);
585
+
586
+ return config;
587
+ }
588
+
589
+ _configAfterMerge(config) {
590
+ config.container = config.container === false ? document.body : index.getElement(config.container);
902
591
 
903
592
  if (typeof config.delay === 'number') {
904
593
  config.delay = {
@@ -907,6 +596,8 @@
907
596
  };
908
597
  }
909
598
 
599
+ config.originalTitle = this._element.getAttribute('title') || '';
600
+
910
601
  if (typeof config.title === 'number') {
911
602
  config.title = config.title.toString();
912
603
  }
@@ -915,12 +606,6 @@
915
606
  config.content = config.content.toString();
916
607
  }
917
608
 
918
- typeCheckConfig(NAME, config, this.constructor.DefaultType);
919
-
920
- if (config.sanitize) {
921
- config.template = sanitizeHtml(config.template, config.allowList, config.sanitizeFn);
922
- }
923
-
924
609
  return config;
925
610
  }
926
611
 
@@ -939,36 +624,6 @@
939
624
  return config;
940
625
  }
941
626
 
942
- _cleanTipClass() {
943
- const tip = this.getTipElement();
944
- const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g');
945
- const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex);
946
-
947
- if (tabClass !== null && tabClass.length > 0) {
948
- tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass));
949
- }
950
- }
951
-
952
- _getBasicClassPrefix() {
953
- return CLASS_PREFIX;
954
- }
955
-
956
- _handlePopperPlacementChange(popperData) {
957
- const {
958
- state
959
- } = popperData;
960
-
961
- if (!state) {
962
- return;
963
- }
964
-
965
- this.tip = state.elements.popper;
966
-
967
- this._cleanTipClass();
968
-
969
- this._addAttachmentClass(this._getAttachment(state.placement));
970
- }
971
-
972
627
  _disposePopper() {
973
628
  if (this._popper) {
974
629
  this._popper.destroy();
@@ -982,27 +637,26 @@
982
637
  return this.each(function () {
983
638
  const data = Tooltip.getOrCreateInstance(this, config);
984
639
 
985
- if (typeof config === 'string') {
986
- if (typeof data[config] === 'undefined') {
987
- throw new TypeError(`No method named "${config}"`);
988
- }
640
+ if (typeof config !== 'string') {
641
+ return;
642
+ }
989
643
 
990
- data[config]();
644
+ if (typeof data[config] === 'undefined') {
645
+ throw new TypeError(`No method named "${config}"`);
991
646
  }
647
+
648
+ data[config]();
992
649
  });
993
650
  }
994
651
 
995
652
  }
996
653
  /**
997
- * ------------------------------------------------------------------------
998
654
  * jQuery
999
- * ------------------------------------------------------------------------
1000
- * add .Tooltip to jQuery only if jQuery is present
1001
655
  */
1002
656
 
1003
657
 
1004
- defineJQueryPlugin(Tooltip);
658
+ index.defineJQueryPlugin(Tooltip);
1005
659
 
1006
660
  return Tooltip;
1007
661
 
1008
- })));
662
+ }));