bootstrap 5.1.3 → 5.2.2

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