UNPKG

84.7 kBJavaScriptView Raw
1/**!
2* tippy.js v5.2.1
3* (c) 2017-2020 atomiks
4* MIT License
5*/
6var tippy = (function (Popper) {
7 'use strict';
8
9 Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;
10
11 var css = ".tippy-tooltip[data-animation=fade][data-state=hidden]{opacity:0}.tippy-iOS{cursor:pointer!important;-webkit-tap-highlight-color:transparent}.tippy-popper{pointer-events:none;max-width:calc(100vw - 10px);transition-timing-function:cubic-bezier(.165,.84,.44,1);transition-property:transform}.tippy-tooltip{position:relative;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;background-color:#333;transition-property:visibility,opacity,transform;outline:0}.tippy-tooltip[data-placement^=top]>.tippy-arrow{border-width:8px 8px 0;border-top-color:#333;margin:0 3px;transform-origin:50% 0;bottom:-7px}.tippy-tooltip[data-placement^=bottom]>.tippy-arrow{border-width:0 8px 8px;border-bottom-color:#333;margin:0 3px;transform-origin:50% 7px;top:-7px}.tippy-tooltip[data-placement^=left]>.tippy-arrow{border-width:8px 0 8px 8px;border-left-color:#333;margin:3px 0;transform-origin:0 50%;right:-7px}.tippy-tooltip[data-placement^=right]>.tippy-arrow{border-width:8px 8px 8px 0;border-right-color:#333;margin:3px 0;transform-origin:7px 50%;left:-7px}.tippy-tooltip[data-interactive][data-state=visible]{pointer-events:auto}.tippy-tooltip[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{position:absolute;border-color:transparent;border-style:solid}.tippy-content{padding:5px 9px}";
12
13 /**
14 * Injects a string of CSS styles to a style node in <head>
15 */
16 function injectCSS(css) {
17 var style = document.createElement('style');
18 style.textContent = css;
19 style.setAttribute('data-tippy-stylesheet', '');
20 var head = document.head;
21 var firstStyleOrLinkTag = document.querySelector('head>style,head>link');
22
23 if (firstStyleOrLinkTag) {
24 head.insertBefore(style, firstStyleOrLinkTag);
25 } else {
26 head.appendChild(style);
27 }
28 }
29
30 function _extends() {
31 _extends = Object.assign || function (target) {
32 for (var i = 1; i < arguments.length; i++) {
33 var source = arguments[i];
34
35 for (var key in source) {
36 if (Object.prototype.hasOwnProperty.call(source, key)) {
37 target[key] = source[key];
38 }
39 }
40 }
41
42 return target;
43 };
44
45 return _extends.apply(this, arguments);
46 }
47
48 var PASSIVE = {
49 passive: true
50 };
51 var ROUND_ARROW = '<svg viewBox="0 0 18 7" xmlns="http://www.w3.org/2000/svg"><path d="M0 7s2.021-.015 5.253-4.218C6.584 1.051 7.797.007 9 0c1.203-.007 2.416 1.035 3.761 2.782C16.012 7.005 18 7 18 7H0z"/></svg>';
52 var IOS_CLASS = "tippy-iOS";
53 var POPPER_CLASS = "tippy-popper";
54 var TOOLTIP_CLASS = "tippy-tooltip";
55 var CONTENT_CLASS = "tippy-content";
56 var BACKDROP_CLASS = "tippy-backdrop";
57 var ARROW_CLASS = "tippy-arrow";
58 var SVG_ARROW_CLASS = "tippy-svg-arrow";
59 var POPPER_SELECTOR = "." + POPPER_CLASS;
60 var TOOLTIP_SELECTOR = "." + TOOLTIP_CLASS;
61 var CONTENT_SELECTOR = "." + CONTENT_CLASS;
62 var ARROW_SELECTOR = "." + ARROW_CLASS;
63 var SVG_ARROW_SELECTOR = "." + SVG_ARROW_CLASS;
64
65 /**
66 * Triggers reflow
67 */
68 function reflow(element) {
69 void element.offsetHeight;
70 }
71 /**
72 * Sets the innerHTML of an element
73 */
74
75 function setInnerHTML(element, html) {
76 element[innerHTML()] = html;
77 }
78 /**
79 * Determines if the value is a reference element
80 */
81
82 function isReferenceElement(value) {
83 return !!(value && value._tippy && value._tippy.reference === value);
84 }
85 /**
86 * Safe .hasOwnProperty check, for prototype-less objects
87 */
88
89 function hasOwnProperty(obj, key) {
90 return {}.hasOwnProperty.call(obj, key);
91 }
92 /**
93 * Returns an array of elements based on the value
94 */
95
96 function getArrayOfElements(value) {
97 if (isElement(value)) {
98 return [value];
99 }
100
101 if (isNodeList(value)) {
102 return arrayFrom(value);
103 }
104
105 if (Array.isArray(value)) {
106 return value;
107 }
108
109 return arrayFrom(document.querySelectorAll(value));
110 }
111 /**
112 * Returns a value at a given index depending on if it's an array or number
113 */
114
115 function getValueAtIndexOrReturn(value, index, defaultValue) {
116 if (Array.isArray(value)) {
117 var v = value[index];
118 return v == null ? Array.isArray(defaultValue) ? defaultValue[index] : defaultValue : v;
119 }
120
121 return value;
122 }
123 /**
124 * Prevents errors from being thrown while accessing nested modifier objects
125 * in `popperOptions`
126 */
127
128 function getModifier(obj, key) {
129 return obj && obj.modifiers && obj.modifiers[key];
130 }
131 /**
132 * Determines if the value is of type
133 */
134
135 function isType(value, type) {
136 var str = {}.toString.call(value);
137 return str.indexOf('[object') === 0 && str.indexOf(type + "]") > -1;
138 }
139 /**
140 * Determines if the value is of type Element
141 */
142
143 function isElement(value) {
144 return isType(value, 'Element');
145 }
146 /**
147 * Determines if the value is of type NodeList
148 */
149
150 function isNodeList(value) {
151 return isType(value, 'NodeList');
152 }
153 /**
154 * Determines if the value is of type MouseEvent
155 */
156
157 function isMouseEvent(value) {
158 return isType(value, 'MouseEvent');
159 }
160 /**
161 * Firefox extensions don't allow setting .innerHTML directly, this will trick
162 * it
163 */
164
165 function innerHTML() {
166 return 'innerHTML';
167 }
168 /**
169 * Evaluates a function if one, or returns the value
170 */
171
172 function invokeWithArgsOrReturn(value, args) {
173 return typeof value === 'function' ? value.apply(void 0, args) : value;
174 }
175 /**
176 * Sets a popperInstance modifier's property to a value
177 */
178
179 function setModifierValue(modifiers, name, property, value) {
180 modifiers.filter(function (m) {
181 return m.name === name;
182 })[0][property] = value;
183 }
184 /**
185 * Returns a new `div` element
186 */
187
188 function div() {
189 return document.createElement('div');
190 }
191 /**
192 * Applies a transition duration to a list of elements
193 */
194
195 function setTransitionDuration(els, value) {
196 els.forEach(function (el) {
197 if (el) {
198 el.style.transitionDuration = value + "ms";
199 }
200 });
201 }
202 /**
203 * Sets the visibility state to elements so they can begin to transition
204 */
205
206 function setVisibilityState(els, state) {
207 els.forEach(function (el) {
208 if (el) {
209 el.setAttribute('data-state', state);
210 }
211 });
212 }
213 /**
214 * Debounce utility. To avoid bloating bundle size, we're only passing 1
215 * argument here, a more generic function would pass all arguments. Only
216 * `onMouseMove` uses this which takes the event object for now.
217 */
218
219 function debounce(fn, ms) {
220 // Avoid wrapping in `setTimeout` if ms is 0 anyway
221 if (ms === 0) {
222 return fn;
223 }
224
225 var timeout;
226 return function (arg) {
227 clearTimeout(timeout);
228 timeout = setTimeout(function () {
229 fn(arg);
230 }, ms);
231 };
232 }
233 /**
234 * Preserves the original function invocation when another function replaces it
235 */
236
237 function preserveInvocation(originalFn, currentFn, args) {
238 if (originalFn && originalFn !== currentFn) {
239 originalFn.apply(void 0, args);
240 }
241 }
242 /**
243 * Deletes properties from an object (pure)
244 */
245
246 function removeProperties(obj, keys) {
247 var clone = _extends({}, obj);
248
249 keys.forEach(function (key) {
250 delete clone[key];
251 });
252 return clone;
253 }
254 /**
255 * Ponyfill for Array.from - converts iterable values to an array
256 */
257
258 function arrayFrom(value) {
259 return [].slice.call(value);
260 }
261 /**
262 * Works like Element.prototype.closest, but uses a callback instead
263 */
264
265 function closestCallback(element, callback) {
266 while (element) {
267 if (callback(element)) {
268 return element;
269 }
270
271 element = element.parentElement;
272 }
273
274 return null;
275 }
276 /**
277 * Determines if an array or string includes a string
278 */
279
280 function includes(a, b) {
281 return a.indexOf(b) > -1;
282 }
283 /**
284 * Creates an array from string of values separated by whitespace
285 */
286
287 function splitBySpaces(value) {
288 return value.split(/\s+/).filter(Boolean);
289 }
290 /**
291 * Returns the `nextValue` if `nextValue` is not `undefined`, otherwise returns
292 * `currentValue`
293 */
294
295 function useIfDefined(nextValue, currentValue) {
296 return nextValue !== undefined ? nextValue : currentValue;
297 }
298 /**
299 * Converts a value that's an array or single value to an array
300 */
301
302 function normalizeToArray(value) {
303 return [].concat(value);
304 }
305 /**
306 * Returns the ownerDocument of the first available element, otherwise global
307 * document
308 */
309
310 function getOwnerDocument(elementOrElements) {
311 var _normalizeToArray = normalizeToArray(elementOrElements),
312 element = _normalizeToArray[0];
313
314 return element ? element.ownerDocument || document : document;
315 }
316 /**
317 * Adds item to array if array does not contain it
318 */
319
320 function pushIfUnique(arr, value) {
321 if (arr.indexOf(value) === -1) {
322 arr.push(value);
323 }
324 }
325 /**
326 * Adds `px` if value is a number, or returns it directly
327 */
328
329 function appendPxIfNumber(value) {
330 return typeof value === 'number' ? value + "px" : value;
331 }
332 /**
333 * Filters out duplicate elements in an array
334 */
335
336 function unique(arr) {
337 return arr.filter(function (item, index) {
338 return arr.indexOf(item) === index;
339 });
340 }
341 /**
342 * Returns number from number or CSS units string
343 */
344
345 function getNumber(value) {
346 return typeof value === 'number' ? value : parseFloat(value);
347 }
348 /**
349 * Gets number or CSS string units in pixels (e.g. `1rem` -> 16)
350 */
351
352 function getUnitsInPx(doc, value) {
353 var isRem = typeof value === 'string' && includes(value, 'rem');
354 var html = doc.documentElement;
355 var rootFontSize = 16;
356
357 if (html && isRem) {
358 return parseFloat(getComputedStyle(html).fontSize || String(rootFontSize)) * getNumber(value);
359 }
360
361 return getNumber(value);
362 }
363 /**
364 * Adds the `distancePx` value to the placement of a Popper.Padding object
365 */
366
367 function getComputedPadding(basePlacement, padding, distancePx) {
368 if (padding === void 0) {
369 padding = 5;
370 }
371
372 var freshPaddingObject = {
373 top: 0,
374 right: 0,
375 bottom: 0,
376 left: 0
377 };
378 var keys = Object.keys(freshPaddingObject);
379 return keys.reduce(function (obj, key) {
380 obj[key] = typeof padding === 'number' ? padding : padding[key];
381
382 if (basePlacement === key) {
383 obj[key] = typeof padding === 'number' ? padding + distancePx : padding[basePlacement] + distancePx;
384 }
385
386 return obj;
387 }, freshPaddingObject);
388 }
389
390 var currentInput = {
391 isTouch: false
392 };
393 var lastMouseMoveTime = 0;
394 /**
395 * When a `touchstart` event is fired, it's assumed the user is using touch
396 * input. We'll bind a `mousemove` event listener to listen for mouse input in
397 * the future. This way, the `isTouch` property is fully dynamic and will handle
398 * hybrid devices that use a mix of touch + mouse input.
399 */
400
401 function onDocumentTouchStart() {
402 if (currentInput.isTouch) {
403 return;
404 }
405
406 currentInput.isTouch = true;
407
408 if (window.performance) {
409 document.addEventListener('mousemove', onDocumentMouseMove);
410 }
411 }
412 /**
413 * When two `mousemove` event are fired consecutively within 20ms, it's assumed
414 * the user is using mouse input again. `mousemove` can fire on touch devices as
415 * well, but very rarely that quickly.
416 */
417
418 function onDocumentMouseMove() {
419 var now = performance.now();
420
421 if (now - lastMouseMoveTime < 20) {
422 currentInput.isTouch = false;
423 document.removeEventListener('mousemove', onDocumentMouseMove);
424 }
425
426 lastMouseMoveTime = now;
427 }
428 /**
429 * When an element is in focus and has a tippy, leaving the tab/window and
430 * returning causes it to show again. For mouse users this is unexpected, but
431 * for keyboard use it makes sense.
432 * TODO: find a better technique to solve this problem
433 */
434
435 function onWindowBlur() {
436 var activeElement = document.activeElement;
437
438 if (isReferenceElement(activeElement)) {
439 var instance = activeElement._tippy;
440
441 if (activeElement.blur && !instance.state.isVisible) {
442 activeElement.blur();
443 }
444 }
445 }
446 /**
447 * Adds the needed global event listeners
448 */
449
450 function bindGlobalEventListeners() {
451 document.addEventListener('touchstart', onDocumentTouchStart, _extends({}, PASSIVE, {
452 capture: true
453 }));
454 window.addEventListener('blur', onWindowBlur);
455 }
456
457 var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
458 var ua = isBrowser ? navigator.userAgent : '';
459 var isIE = /MSIE |Trident\//.test(ua);
460 var isIOS = isBrowser && /iPhone|iPad|iPod/.test(navigator.platform);
461 function updateIOSClass(isAdd) {
462 var shouldAdd = isAdd && isIOS && currentInput.isTouch;
463 document.body.classList[shouldAdd ? 'add' : 'remove'](IOS_CLASS);
464 }
465
466 var version = "5.2.1";
467
468 function createMemoryLeakWarning(method) {
469 var txt = method === 'destroy' ? 'n already-' : ' ';
470 return "\n " + method + "() was called on a" + txt + "destroyed instance. This is a no-op but\n indicates a potential memory leak.\n ";
471 }
472 function clean(value) {
473 var spacesAndTabs = /[ \t]{2,}/g;
474 var lineStartWithSpaces = /^[ \t]*/gm;
475 return value.replace(spacesAndTabs, ' ').replace(lineStartWithSpaces, '').trim();
476 }
477
478 function getDevMessage(message) {
479 return clean("\n %ctippy.js\n\n %c" + clean(message) + "\n\n %c\uD83D\uDC77\u200D This is a development-only message. It will be removed in production.\n ");
480 }
481
482 function getFormattedMessage(message) {
483 return [getDevMessage(message), // title
484 'color: #00C584; font-size: 1.3em; font-weight: bold;', // message
485 'line-height: 1.5', // footer
486 'color: #a6a095;'];
487 }
488 /**
489 * Helpful wrapper around `console.warn()`.
490 * TODO: Should we use a cache so it only warns a single time and not spam the
491 * console? (Need to consider hot reloading and invalidation though). Chrome
492 * already batches warnings as well.
493 */
494
495 function warnWhen(condition, message) {
496 if (condition) {
497 var _console;
498
499 (_console = console).warn.apply(_console, getFormattedMessage(message));
500 }
501 }
502 /**
503 * Helpful wrapper around `console.error()`
504 */
505
506 function errorWhen(condition, message) {
507 if (condition) {
508 var _console2;
509
510 (_console2 = console).error.apply(_console2, getFormattedMessage(message));
511 }
512 }
513 /**
514 * Validates the `targets` value passed to `tippy()`
515 */
516
517 function validateTargets(targets) {
518 var didPassFalsyValue = !targets;
519 var didPassPlainObject = Object.prototype.toString.call(targets) === '[object Object]' && !targets.addEventListener;
520 errorWhen(didPassFalsyValue, ['tippy() was passed', '`' + String(targets) + '`', 'as its targets (first) argument. Valid types are: String, Element, Element[],', 'or NodeList.'].join(' '));
521 errorWhen(didPassPlainObject, ['tippy() was passed a plain object which is no longer supported as an argument.', 'See: https://atomiks.github.io/tippyjs/misc/#custom-position'].join(' '));
522 }
523
524 var pluginProps = {
525 animateFill: false,
526 followCursor: false,
527 inlinePositioning: false,
528 sticky: false
529 };
530 var defaultProps = _extends({
531 allowHTML: true,
532 animation: 'fade',
533 appendTo: function appendTo() {
534 return document.body;
535 },
536 aria: 'describedby',
537 arrow: true,
538 boundary: 'scrollParent',
539 content: '',
540 delay: 0,
541 distance: 10,
542 duration: [300, 250],
543 flip: true,
544 flipBehavior: 'flip',
545 flipOnUpdate: false,
546 hideOnClick: true,
547 ignoreAttributes: false,
548 inertia: false,
549 interactive: false,
550 interactiveBorder: 2,
551 interactiveDebounce: 0,
552 lazy: true,
553 maxWidth: 350,
554 multiple: false,
555 offset: 0,
556 onAfterUpdate: function onAfterUpdate() {},
557 onBeforeUpdate: function onBeforeUpdate() {},
558 onCreate: function onCreate() {},
559 onDestroy: function onDestroy() {},
560 onHidden: function onHidden() {},
561 onHide: function onHide() {},
562 onMount: function onMount() {},
563 onShow: function onShow() {},
564 onShown: function onShown() {},
565 onTrigger: function onTrigger() {},
566 onUntrigger: function onUntrigger() {},
567 placement: 'top',
568 plugins: [],
569 popperOptions: {},
570 role: 'tooltip',
571 showOnCreate: false,
572 theme: '',
573 touch: true,
574 trigger: 'mouseenter focus',
575 triggerTarget: null,
576 updateDuration: 0,
577 zIndex: 9999
578 }, pluginProps);
579 var defaultKeys = Object.keys(defaultProps);
580 /**
581 * If the setProps() method encounters one of these, the popperInstance must be
582 * recreated
583 */
584
585 var POPPER_INSTANCE_DEPENDENCIES = ['arrow', 'boundary', 'distance', 'flip', 'flipBehavior', 'flipOnUpdate', 'offset', 'placement', 'popperOptions'];
586 /**
587 * Mutates the defaultProps object by setting the props specified
588 */
589
590 var setDefaultProps = function setDefaultProps(partialProps) {
591 {
592 validateProps(partialProps, []);
593 }
594
595 var keys = Object.keys(partialProps);
596 keys.forEach(function (key) {
597 defaultProps[key] = partialProps[key];
598 });
599 };
600 /**
601 * Returns an extended props object including plugin props
602 */
603
604 function getExtendedPassedProps(passedProps) {
605 var plugins = passedProps.plugins || [];
606 var pluginProps = plugins.reduce(function (acc, plugin) {
607 var name = plugin.name,
608 defaultValue = plugin.defaultValue;
609
610 if (name) {
611 acc[name] = passedProps[name] !== undefined ? passedProps[name] : defaultValue;
612 }
613
614 return acc;
615 }, {});
616 return _extends({}, passedProps, {}, pluginProps);
617 }
618 /**
619 * Returns an object of optional props from data-tippy-* attributes
620 */
621
622 function getDataAttributeProps(reference, plugins) {
623 var propKeys = plugins ? Object.keys(getExtendedPassedProps(_extends({}, defaultProps, {
624 plugins: plugins
625 }))) : defaultKeys;
626 var props = propKeys.reduce(function (acc, key) {
627 var valueAsString = (reference.getAttribute("data-tippy-" + key) || '').trim();
628
629 if (!valueAsString) {
630 return acc;
631 }
632
633 if (key === 'content') {
634 acc[key] = valueAsString;
635 } else {
636 try {
637 acc[key] = JSON.parse(valueAsString);
638 } catch (e) {
639 acc[key] = valueAsString;
640 }
641 }
642
643 return acc;
644 }, {});
645 return props;
646 }
647 /**
648 * Evaluates the props object by merging data attributes and disabling
649 * conflicting props where necessary
650 */
651
652 function evaluateProps(reference, props) {
653 var out = _extends({}, props, {
654 content: invokeWithArgsOrReturn(props.content, [reference])
655 }, props.ignoreAttributes ? {} : getDataAttributeProps(reference, props.plugins));
656
657 if (out.interactive) {
658 out.aria = null;
659 }
660
661 return out;
662 }
663 /**
664 * Validates props with the valid `defaultProps` object
665 */
666
667 function validateProps(partialProps, plugins) {
668 if (partialProps === void 0) {
669 partialProps = {};
670 }
671
672 if (plugins === void 0) {
673 plugins = [];
674 }
675
676 var keys = Object.keys(partialProps);
677 keys.forEach(function (prop) {
678 var value = partialProps[prop];
679 var didSpecifyPlacementInPopperOptions = prop === 'popperOptions' && value !== null && typeof value === 'object' && hasOwnProperty(value, 'placement');
680 var nonPluginProps = removeProperties(defaultProps, ['animateFill', 'followCursor', 'inlinePositioning', 'sticky']); // These props have custom warnings
681
682 var customWarningProps = ['a11y', 'arrowType', 'showOnInit', 'size', 'target', 'touchHold'];
683 var didPassUnknownProp = !hasOwnProperty(nonPluginProps, prop) && !includes(customWarningProps, prop); // Check if the prop exists in `plugins`
684
685 if (didPassUnknownProp) {
686 didPassUnknownProp = plugins.filter(function (plugin) {
687 return plugin.name === prop;
688 }).length === 0;
689 }
690
691 warnWhen(prop === 'target', ['The `target` prop was removed in v5 and replaced with the delegate() addon', 'in order to conserve bundle size.', 'See: https://atomiks.github.io/tippyjs/addons/#event-delegation'].join(' '));
692 warnWhen(prop === 'a11y', ['The `a11y` prop was removed in v5. Make sure the element you are giving a', 'tippy to is natively focusable, such as <button> or <input>, not <div>', 'or <span>.'].join(' '));
693 warnWhen(prop === 'showOnInit', 'The `showOnInit` prop was renamed to `showOnCreate` in v5.');
694 warnWhen(prop === 'arrowType', ['The `arrowType` prop was removed in v5 in favor of overloading the `arrow`', 'prop.', '\n\n', '"round" string was replaced with importing the string from the package.', '\n\n', "* import {roundArrow} from 'tippy.js'; (ESM version)\n", '* const {roundArrow} = tippy; (IIFE CDN version)', '\n\n', 'Before: {arrow: true, arrowType: "round"}\n', 'After: {arrow: roundArrow}`'].join(' '));
695 warnWhen(prop === 'touchHold', ['The `touchHold` prop was removed in v5 in favor of overloading the `touch`', 'prop.', '\n\n', 'Before: {touchHold: true}\n', 'After: {touch: "hold"}'].join(' '));
696 warnWhen(prop === 'size', ['The `size` prop was removed in v5. Instead, use a theme that specifies', 'CSS padding and font-size properties.'].join(' '));
697 warnWhen(prop === 'theme' && value === 'google', 'The included theme "google" was renamed to "material" in v5.');
698 warnWhen(didSpecifyPlacementInPopperOptions, ['Specifying placement in `popperOptions` is not supported. Use the base-level', '`placement` prop instead.', '\n\n', 'Before: {popperOptions: {placement: "bottom"}}\n', 'After: {placement: "bottom"}'].join(' '));
699 warnWhen(didPassUnknownProp, ["`" + prop + "`", "is not a valid prop. You may have spelled it incorrectly, or if it's a", 'plugin, forgot to pass it in an array as props.plugins.', '\n\n', 'In v5, the following props were turned into plugins:', '\n\n', '* animateFill\n', '* followCursor\n', '* sticky', '\n\n', 'All props: https://atomiks.github.io/tippyjs/all-props/\n', 'Plugins: https://atomiks.github.io/tippyjs/plugins/'].join(' '));
700 });
701 }
702
703 /**
704 * Returns the popper's placement, ignoring shifting (top-start, etc)
705 */
706
707 function getBasePlacement(placement) {
708 return placement.split('-')[0];
709 }
710 /**
711 * Adds `data-inertia` attribute
712 */
713
714 function addInertia(tooltip) {
715 tooltip.setAttribute('data-inertia', '');
716 }
717 /**
718 * Removes `data-inertia` attribute
719 */
720
721 function removeInertia(tooltip) {
722 tooltip.removeAttribute('data-inertia');
723 }
724 /**
725 * Adds interactive-related attributes
726 */
727
728 function addInteractive(tooltip) {
729 tooltip.setAttribute('data-interactive', '');
730 }
731 /**
732 * Removes interactive-related attributes
733 */
734
735 function removeInteractive(tooltip) {
736 tooltip.removeAttribute('data-interactive');
737 }
738 /**
739 * Sets the content of a tooltip
740 */
741
742 function setContent(contentEl, props) {
743 if (isElement(props.content)) {
744 setInnerHTML(contentEl, '');
745 contentEl.appendChild(props.content);
746 } else if (typeof props.content !== 'function') {
747 var key = props.allowHTML ? 'innerHTML' : 'textContent';
748 contentEl[key] = props.content;
749 }
750 }
751 /**
752 * Returns the child elements of a popper element
753 */
754
755 function getChildren(popper) {
756 return {
757 tooltip: popper.querySelector(TOOLTIP_SELECTOR),
758 content: popper.querySelector(CONTENT_SELECTOR),
759 arrow: popper.querySelector(ARROW_SELECTOR) || popper.querySelector(SVG_ARROW_SELECTOR)
760 };
761 }
762 /**
763 * Creates an arrow element and returns it
764 */
765
766 function createArrowElement(arrow) {
767 var arrowElement = div();
768
769 if (arrow === true) {
770 arrowElement.className = ARROW_CLASS;
771 } else {
772 arrowElement.className = SVG_ARROW_CLASS;
773
774 if (isElement(arrow)) {
775 arrowElement.appendChild(arrow);
776 } else {
777 setInnerHTML(arrowElement, arrow);
778 }
779 }
780
781 return arrowElement;
782 }
783 /**
784 * Constructs the popper element and returns it
785 */
786
787 function createPopperElement(id, props) {
788 var popper = div();
789 popper.className = POPPER_CLASS;
790 popper.style.position = 'absolute';
791 popper.style.top = '0';
792 popper.style.left = '0';
793 var tooltip = div();
794 tooltip.className = TOOLTIP_CLASS;
795 tooltip.id = "tippy-" + id;
796 tooltip.setAttribute('data-state', 'hidden');
797 tooltip.setAttribute('tabindex', '-1');
798 updateTheme(tooltip, 'add', props.theme);
799 var content = div();
800 content.className = CONTENT_CLASS;
801 content.setAttribute('data-state', 'hidden');
802
803 if (props.interactive) {
804 addInteractive(tooltip);
805 }
806
807 if (props.arrow) {
808 tooltip.setAttribute('data-arrow', '');
809 tooltip.appendChild(createArrowElement(props.arrow));
810 }
811
812 if (props.inertia) {
813 addInertia(tooltip);
814 }
815
816 setContent(content, props);
817 tooltip.appendChild(content);
818 popper.appendChild(tooltip);
819 updatePopperElement(popper, props, props);
820 return popper;
821 }
822 /**
823 * Updates the popper element based on the new props
824 */
825
826 function updatePopperElement(popper, prevProps, nextProps) {
827 var _getChildren = getChildren(popper),
828 tooltip = _getChildren.tooltip,
829 content = _getChildren.content,
830 arrow = _getChildren.arrow;
831
832 popper.style.zIndex = '' + nextProps.zIndex;
833 tooltip.setAttribute('data-animation', nextProps.animation);
834 tooltip.style.maxWidth = appendPxIfNumber(nextProps.maxWidth);
835
836 if (nextProps.role) {
837 tooltip.setAttribute('role', nextProps.role);
838 } else {
839 tooltip.removeAttribute('role');
840 }
841
842 if (prevProps.content !== nextProps.content) {
843 setContent(content, nextProps);
844 } // arrow
845
846
847 if (!prevProps.arrow && nextProps.arrow) {
848 // false to true
849 tooltip.appendChild(createArrowElement(nextProps.arrow));
850 tooltip.setAttribute('data-arrow', '');
851 } else if (prevProps.arrow && !nextProps.arrow) {
852 // true to false
853 tooltip.removeChild(arrow);
854 tooltip.removeAttribute('data-arrow');
855 } else if (prevProps.arrow !== nextProps.arrow) {
856 // true to 'round' or vice-versa
857 tooltip.removeChild(arrow);
858 tooltip.appendChild(createArrowElement(nextProps.arrow));
859 } // interactive
860
861
862 if (!prevProps.interactive && nextProps.interactive) {
863 addInteractive(tooltip);
864 } else if (prevProps.interactive && !nextProps.interactive) {
865 removeInteractive(tooltip);
866 } // inertia
867
868
869 if (!prevProps.inertia && nextProps.inertia) {
870 addInertia(tooltip);
871 } else if (prevProps.inertia && !nextProps.inertia) {
872 removeInertia(tooltip);
873 } // theme
874
875
876 if (prevProps.theme !== nextProps.theme) {
877 updateTheme(tooltip, 'remove', prevProps.theme);
878 updateTheme(tooltip, 'add', nextProps.theme);
879 }
880 }
881 /**
882 * Add/remove transitionend listener from tooltip
883 */
884
885 function updateTransitionEndListener(tooltip, action, listener) {
886 ['transitionend', 'webkitTransitionEnd'].forEach(function (event) {
887 tooltip[action + 'EventListener'](event, listener);
888 });
889 }
890 /**
891 * Adds/removes theme from tooltip's classList
892 */
893
894 function updateTheme(tooltip, action, theme) {
895 splitBySpaces(theme).forEach(function (name) {
896 tooltip.classList[action](name + "-theme");
897 });
898 }
899 /**
900 * Determines if the mouse cursor is outside of the popper's interactive border
901 * region
902 */
903
904 function isCursorOutsideInteractiveBorder(popperTreeData, event) {
905 var clientX = event.clientX,
906 clientY = event.clientY;
907 return popperTreeData.every(function (_ref) {
908 var popperRect = _ref.popperRect,
909 tooltipRect = _ref.tooltipRect,
910 interactiveBorder = _ref.interactiveBorder;
911 // Get min/max bounds of both the popper and tooltip rects due to
912 // `distance` offset
913 var mergedRect = {
914 top: Math.min(popperRect.top, tooltipRect.top),
915 right: Math.max(popperRect.right, tooltipRect.right),
916 bottom: Math.max(popperRect.bottom, tooltipRect.bottom),
917 left: Math.min(popperRect.left, tooltipRect.left)
918 };
919 var exceedsTop = mergedRect.top - clientY > interactiveBorder;
920 var exceedsBottom = clientY - mergedRect.bottom > interactiveBorder;
921 var exceedsLeft = mergedRect.left - clientX > interactiveBorder;
922 var exceedsRight = clientX - mergedRect.right > interactiveBorder;
923 return exceedsTop || exceedsBottom || exceedsLeft || exceedsRight;
924 });
925 }
926
927 var idCounter = 1;
928 var mouseMoveListeners = [];
929 /**
930 * Used by `hideAll()`
931 */
932
933 var mountedInstances = [];
934 /**
935 * Creates and returns a Tippy object. We're using a closure pattern instead of
936 * a class so that the exposed object API is clean without private members
937 * prefixed with `_`.
938 */
939
940 function createTippy(reference, passedProps) {
941 var props = evaluateProps(reference, _extends({}, defaultProps, {}, getExtendedPassedProps(passedProps))); // If the reference shouldn't have multiple tippys, return null early
942
943 if (!props.multiple && reference._tippy) {
944 return null;
945 }
946 /* ======================= 🔒 Private members 🔒 ======================= */
947
948
949 var showTimeout;
950 var hideTimeout;
951 var scheduleHideAnimationFrame;
952 var isBeingDestroyed = false;
953 var isVisibleFromClick = false;
954 var didHideDueToDocumentMouseDown = false;
955 var popperUpdates = 0;
956 var lastTriggerEvent;
957 var currentMountCallback;
958 var currentTransitionEndListener;
959 var listeners = [];
960 var debouncedOnMouseMove = debounce(onMouseMove, props.interactiveDebounce);
961 var currentTarget; // Support iframe contexts
962 // Static check that assumes any of the `triggerTarget` or `reference`
963 // nodes will never change documents, even when they are updated
964
965 var doc = getOwnerDocument(props.triggerTarget || reference);
966 /* ======================= 🔑 Public members 🔑 ======================= */
967
968 var id = idCounter++;
969 var popper = createPopperElement(id, props);
970 var popperChildren = getChildren(popper);
971 var popperInstance = null;
972 var plugins = unique(props.plugins); // These two elements are static
973
974 var tooltip = popperChildren.tooltip,
975 content = popperChildren.content;
976 var transitionableElements = [tooltip, content];
977 var state = {
978 // The current real placement (`data-placement` attribute)
979 currentPlacement: null,
980 // Is the instance currently enabled?
981 isEnabled: true,
982 // Is the tippy currently showing and not transitioning out?
983 isVisible: false,
984 // Has the instance been destroyed?
985 isDestroyed: false,
986 // Is the tippy currently mounted to the DOM?
987 isMounted: false,
988 // Has the tippy finished transitioning in?
989 isShown: false
990 };
991 var instance = {
992 // properties
993 id: id,
994 reference: reference,
995 popper: popper,
996 popperChildren: popperChildren,
997 popperInstance: popperInstance,
998 props: props,
999 state: state,
1000 plugins: plugins,
1001 // methods
1002 clearDelayTimeouts: clearDelayTimeouts,
1003 setProps: setProps,
1004 setContent: setContent,
1005 show: show,
1006 hide: hide,
1007 enable: enable,
1008 disable: disable,
1009 destroy: destroy
1010 };
1011 /* ==================== Initial instance mutations =================== */
1012
1013 reference._tippy = instance;
1014 popper._tippy = instance;
1015 var pluginsHooks = plugins.map(function (plugin) {
1016 return plugin.fn(instance);
1017 });
1018 var hadAriaExpandedAttributeOnCreate = reference.hasAttribute('aria-expanded');
1019 addListenersToTriggerTarget();
1020 handleAriaExpandedAttribute();
1021
1022 if (!props.lazy) {
1023 createPopperInstance();
1024 }
1025
1026 invokeHook('onCreate', [instance]);
1027
1028 if (props.showOnCreate) {
1029 scheduleShow();
1030 } // Prevent a tippy with a delay from hiding if the cursor left then returned
1031 // before it started hiding
1032
1033
1034 popper.addEventListener('mouseenter', function () {
1035 if (instance.props.interactive && instance.state.isVisible) {
1036 instance.clearDelayTimeouts();
1037 }
1038 });
1039 popper.addEventListener('mouseleave', function (event) {
1040 if (instance.props.interactive && includes(instance.props.trigger, 'mouseenter')) {
1041 debouncedOnMouseMove(event);
1042 doc.addEventListener('mousemove', debouncedOnMouseMove);
1043 }
1044 });
1045 return instance;
1046 /* ======================= 🔒 Private methods 🔒 ======================= */
1047
1048 function getNormalizedTouchSettings() {
1049 var touch = instance.props.touch;
1050 return Array.isArray(touch) ? touch : [touch, 0];
1051 }
1052
1053 function getIsCustomTouchBehavior() {
1054 return getNormalizedTouchSettings()[0] === 'hold';
1055 }
1056
1057 function getCurrentTarget() {
1058 return currentTarget || reference;
1059 }
1060
1061 function getDelay(isShow) {
1062 // For touch or keyboard input, force `0` delay for UX reasons
1063 // Also if the instance is mounted but not visible (transitioning out),
1064 // ignore delay
1065 if (instance.state.isMounted && !instance.state.isVisible || currentInput.isTouch || lastTriggerEvent && lastTriggerEvent.type === 'focus') {
1066 return 0;
1067 }
1068
1069 return getValueAtIndexOrReturn(instance.props.delay, isShow ? 0 : 1, defaultProps.delay);
1070 }
1071
1072 function invokeHook(hook, args, shouldInvokePropsHook) {
1073 if (shouldInvokePropsHook === void 0) {
1074 shouldInvokePropsHook = true;
1075 }
1076
1077 pluginsHooks.forEach(function (pluginHooks) {
1078 if (hasOwnProperty(pluginHooks, hook)) {
1079 // @ts-ignore
1080 pluginHooks[hook].apply(pluginHooks, args);
1081 }
1082 });
1083
1084 if (shouldInvokePropsHook) {
1085 var _instance$props;
1086
1087 // @ts-ignore
1088 (_instance$props = instance.props)[hook].apply(_instance$props, args);
1089 }
1090 }
1091
1092 function handleAriaDescribedByAttribute() {
1093 var aria = instance.props.aria;
1094
1095 if (!aria) {
1096 return;
1097 }
1098
1099 var attr = "aria-" + aria;
1100 var id = tooltip.id;
1101 var nodes = normalizeToArray(instance.props.triggerTarget || reference);
1102 nodes.forEach(function (node) {
1103 var currentValue = node.getAttribute(attr);
1104
1105 if (instance.state.isVisible) {
1106 node.setAttribute(attr, currentValue ? currentValue + " " + id : id);
1107 } else {
1108 var nextValue = currentValue && currentValue.replace(id, '').trim();
1109
1110 if (nextValue) {
1111 node.setAttribute(attr, nextValue);
1112 } else {
1113 node.removeAttribute(attr);
1114 }
1115 }
1116 });
1117 }
1118
1119 function handleAriaExpandedAttribute() {
1120 // If the user has specified `aria-expanded` on their reference when the
1121 // instance was created, we have to assume they're controlling it externally
1122 // themselves
1123 if (hadAriaExpandedAttributeOnCreate) {
1124 return;
1125 }
1126
1127 var nodes = normalizeToArray(instance.props.triggerTarget || reference);
1128 nodes.forEach(function (node) {
1129 if (instance.props.interactive) {
1130 node.setAttribute('aria-expanded', instance.state.isVisible && node === getCurrentTarget() ? 'true' : 'false');
1131 } else {
1132 node.removeAttribute('aria-expanded');
1133 }
1134 });
1135 }
1136
1137 function cleanupInteractiveMouseListeners() {
1138 doc.body.removeEventListener('mouseleave', scheduleHide);
1139 doc.removeEventListener('mousemove', debouncedOnMouseMove);
1140 mouseMoveListeners = mouseMoveListeners.filter(function (listener) {
1141 return listener !== debouncedOnMouseMove;
1142 });
1143 }
1144
1145 function onDocumentMouseDown(event) {
1146 // Clicked on interactive popper
1147 if (instance.props.interactive && popper.contains(event.target)) {
1148 return;
1149 } // Clicked on the event listeners target
1150
1151
1152 if (getCurrentTarget().contains(event.target)) {
1153 if (currentInput.isTouch) {
1154 return;
1155 }
1156
1157 if (instance.state.isVisible && includes(instance.props.trigger, 'click')) {
1158 return;
1159 }
1160 }
1161
1162 if (instance.props.hideOnClick === true) {
1163 isVisibleFromClick = false;
1164 instance.clearDelayTimeouts();
1165 instance.hide(); // `mousedown` event is fired right before `focus` if pressing the
1166 // currentTarget. This lets a tippy with `focus` trigger know that it
1167 // should not show
1168
1169 didHideDueToDocumentMouseDown = true;
1170 setTimeout(function () {
1171 didHideDueToDocumentMouseDown = false;
1172 }); // The listener gets added in `scheduleShow()`, but this may be hiding it
1173 // before it shows, and hide()'s early bail-out behavior can prevent it
1174 // from being cleaned up
1175
1176 if (!instance.state.isMounted) {
1177 removeDocumentMouseDownListener();
1178 }
1179 }
1180 }
1181
1182 function addDocumentMouseDownListener() {
1183 doc.addEventListener('mousedown', onDocumentMouseDown, true);
1184 }
1185
1186 function removeDocumentMouseDownListener() {
1187 doc.removeEventListener('mousedown', onDocumentMouseDown, true);
1188 }
1189
1190 function onTransitionedOut(duration, callback) {
1191 onTransitionEnd(duration, function () {
1192 if (!instance.state.isVisible && popper.parentNode && popper.parentNode.contains(popper)) {
1193 callback();
1194 }
1195 });
1196 }
1197
1198 function onTransitionedIn(duration, callback) {
1199 onTransitionEnd(duration, callback);
1200 }
1201
1202 function onTransitionEnd(duration, callback) {
1203 function listener(event) {
1204 if (event.target === tooltip) {
1205 updateTransitionEndListener(tooltip, 'remove', listener);
1206 callback();
1207 }
1208 } // Make callback synchronous if duration is 0
1209 // `transitionend` won't fire otherwise
1210
1211
1212 if (duration === 0) {
1213 return callback();
1214 }
1215
1216 updateTransitionEndListener(tooltip, 'remove', currentTransitionEndListener);
1217 updateTransitionEndListener(tooltip, 'add', listener);
1218 currentTransitionEndListener = listener;
1219 }
1220
1221 function on(eventType, handler, options) {
1222 if (options === void 0) {
1223 options = false;
1224 }
1225
1226 var nodes = normalizeToArray(instance.props.triggerTarget || reference);
1227 nodes.forEach(function (node) {
1228 node.addEventListener(eventType, handler, options);
1229 listeners.push({
1230 node: node,
1231 eventType: eventType,
1232 handler: handler,
1233 options: options
1234 });
1235 });
1236 }
1237
1238 function addListenersToTriggerTarget() {
1239 if (getIsCustomTouchBehavior()) {
1240 on('touchstart', onTrigger, PASSIVE);
1241 on('touchend', onMouseLeave, PASSIVE);
1242 }
1243
1244 splitBySpaces(instance.props.trigger).forEach(function (eventType) {
1245 if (eventType === 'manual') {
1246 return;
1247 }
1248
1249 on(eventType, onTrigger);
1250
1251 switch (eventType) {
1252 case 'mouseenter':
1253 on('mouseleave', onMouseLeave);
1254 break;
1255
1256 case 'focus':
1257 on(isIE ? 'focusout' : 'blur', onBlurOrFocusOut);
1258 break;
1259
1260 case 'focusin':
1261 on('focusout', onBlurOrFocusOut);
1262 break;
1263 }
1264 });
1265 }
1266
1267 function removeListenersFromTriggerTarget() {
1268 listeners.forEach(function (_ref) {
1269 var node = _ref.node,
1270 eventType = _ref.eventType,
1271 handler = _ref.handler,
1272 options = _ref.options;
1273 node.removeEventListener(eventType, handler, options);
1274 });
1275 listeners = [];
1276 }
1277
1278 function onTrigger(event) {
1279 var shouldScheduleClickHide = false;
1280
1281 if (!instance.state.isEnabled || isEventListenerStopped(event) || didHideDueToDocumentMouseDown) {
1282 return;
1283 }
1284
1285 lastTriggerEvent = event;
1286 currentTarget = event.currentTarget;
1287 handleAriaExpandedAttribute();
1288
1289 if (!instance.state.isVisible && isMouseEvent(event)) {
1290 // If scrolling, `mouseenter` events can be fired if the cursor lands
1291 // over a new target, but `mousemove` events don't get fired. This
1292 // causes interactive tooltips to get stuck open until the cursor is
1293 // moved
1294 mouseMoveListeners.forEach(function (listener) {
1295 return listener(event);
1296 });
1297 } // Toggle show/hide when clicking click-triggered tooltips
1298
1299
1300 if (event.type === 'click' && (!includes(instance.props.trigger, 'mouseenter') || isVisibleFromClick) && instance.props.hideOnClick !== false && instance.state.isVisible) {
1301 shouldScheduleClickHide = true;
1302 } else {
1303 var _getNormalizedTouchSe = getNormalizedTouchSettings(),
1304 value = _getNormalizedTouchSe[0],
1305 duration = _getNormalizedTouchSe[1];
1306
1307 if (currentInput.isTouch && value === 'hold' && duration) {
1308 // We can hijack the show timeout here, it will be cleared by
1309 // `scheduleHide()` when necessary
1310 showTimeout = setTimeout(function () {
1311 scheduleShow(event);
1312 }, duration);
1313 } else {
1314 scheduleShow(event);
1315 }
1316 }
1317
1318 if (event.type === 'click') {
1319 isVisibleFromClick = !shouldScheduleClickHide;
1320 }
1321
1322 if (shouldScheduleClickHide) {
1323 scheduleHide(event);
1324 }
1325 }
1326
1327 function onMouseMove(event) {
1328 var isCursorOverReferenceOrPopper = closestCallback(event.target, function (el) {
1329 return el === reference || el === popper;
1330 });
1331
1332 if (event.type === 'mousemove' && isCursorOverReferenceOrPopper) {
1333 return;
1334 }
1335
1336 var popperTreeData = arrayFrom(popper.querySelectorAll(POPPER_SELECTOR)).concat(popper).map(function (popper) {
1337 var instance = popper._tippy;
1338 var tooltip = instance.popperChildren.tooltip;
1339 var interactiveBorder = instance.props.interactiveBorder;
1340 return {
1341 popperRect: popper.getBoundingClientRect(),
1342 tooltipRect: tooltip.getBoundingClientRect(),
1343 interactiveBorder: interactiveBorder
1344 };
1345 });
1346
1347 if (isCursorOutsideInteractiveBorder(popperTreeData, event)) {
1348 cleanupInteractiveMouseListeners();
1349 scheduleHide(event);
1350 }
1351 }
1352
1353 function onMouseLeave(event) {
1354 if (isEventListenerStopped(event)) {
1355 return;
1356 }
1357
1358 if (includes(instance.props.trigger, 'click') && isVisibleFromClick) {
1359 return;
1360 }
1361
1362 if (instance.props.interactive) {
1363 doc.body.addEventListener('mouseleave', scheduleHide);
1364 doc.addEventListener('mousemove', debouncedOnMouseMove);
1365 pushIfUnique(mouseMoveListeners, debouncedOnMouseMove);
1366 debouncedOnMouseMove(event);
1367 return;
1368 }
1369
1370 scheduleHide(event);
1371 }
1372
1373 function onBlurOrFocusOut(event) {
1374 if (!includes(instance.props.trigger, 'focusin') && event.target !== getCurrentTarget()) {
1375 return;
1376 } // If focus was moved to within the popper
1377
1378
1379 if (instance.props.interactive && event.relatedTarget && popper.contains(event.relatedTarget)) {
1380 return;
1381 }
1382
1383 scheduleHide(event);
1384 }
1385
1386 function isEventListenerStopped(event) {
1387 var supportsTouch = 'ontouchstart' in window;
1388 var isTouchEvent = includes(event.type, 'touch');
1389 var isCustomTouch = getIsCustomTouchBehavior();
1390 return supportsTouch && currentInput.isTouch && isCustomTouch && !isTouchEvent || currentInput.isTouch && !isCustomTouch && isTouchEvent;
1391 }
1392
1393 function createPopperInstance() {
1394 var popperOptions = instance.props.popperOptions;
1395 var arrow = instance.popperChildren.arrow;
1396 var flipModifier = getModifier(popperOptions, 'flip');
1397 var preventOverflowModifier = getModifier(popperOptions, 'preventOverflow');
1398 var distancePx;
1399
1400 function applyMutations(data) {
1401 var prevPlacement = instance.state.currentPlacement;
1402 instance.state.currentPlacement = data.placement;
1403
1404 if (instance.props.flip && !instance.props.flipOnUpdate) {
1405 if (data.flipped) {
1406 instance.popperInstance.options.placement = data.placement;
1407 }
1408
1409 setModifierValue(instance.popperInstance.modifiers, 'flip', 'enabled', false);
1410 }
1411
1412 tooltip.setAttribute('data-placement', data.placement);
1413
1414 if (data.attributes['x-out-of-boundaries'] !== false) {
1415 tooltip.setAttribute('data-out-of-boundaries', '');
1416 } else {
1417 tooltip.removeAttribute('data-out-of-boundaries');
1418 }
1419
1420 var basePlacement = getBasePlacement(data.placement);
1421 var isVerticalPlacement = includes(['top', 'bottom'], basePlacement);
1422 var isSecondaryPlacement = includes(['bottom', 'right'], basePlacement); // Apply `distance` prop
1423
1424 tooltip.style.top = '0';
1425 tooltip.style.left = '0';
1426 tooltip.style[isVerticalPlacement ? 'top' : 'left'] = (isSecondaryPlacement ? 1 : -1) * distancePx + 'px'; // Careful not to cause an infinite loop here
1427 // Fixes https://github.com/FezVrasta/popper.js/issues/784
1428
1429 if (prevPlacement && prevPlacement !== data.placement) {
1430 instance.popperInstance.update();
1431 }
1432 }
1433
1434 var config = _extends({
1435 eventsEnabled: false,
1436 placement: instance.props.placement
1437 }, popperOptions, {
1438 modifiers: _extends({}, popperOptions && popperOptions.modifiers, {
1439 // We can't use `padding` on the popper el because of these bugs when
1440 // flipping from a vertical to horizontal placement or vice-versa,
1441 // there is severe flickering.
1442 // https://github.com/FezVrasta/popper.js/issues/720
1443 // This workaround increases bundle size by 250B minzip unfortunately,
1444 // due to need to custom compute the distance (since Popper rect does
1445 // not get affected by the inner tooltip's distance offset)
1446 tippyDistance: {
1447 enabled: true,
1448 order: 0,
1449 fn: function fn(data) {
1450 // `html` fontSize may change while `popperInstance` is alive
1451 // e.g. on resize in media queries
1452 distancePx = getUnitsInPx(doc, instance.props.distance);
1453 var basePlacement = getBasePlacement(data.placement);
1454 var computedPreventOverflowPadding = getComputedPadding(basePlacement, preventOverflowModifier && preventOverflowModifier.padding, distancePx);
1455 var computedFlipPadding = getComputedPadding(basePlacement, flipModifier && flipModifier.padding, distancePx);
1456 var instanceModifiers = instance.popperInstance.modifiers;
1457 setModifierValue(instanceModifiers, 'preventOverflow', 'padding', computedPreventOverflowPadding);
1458 setModifierValue(instanceModifiers, 'flip', 'padding', computedFlipPadding);
1459 return data;
1460 }
1461 },
1462 preventOverflow: _extends({
1463 boundariesElement: instance.props.boundary
1464 }, preventOverflowModifier),
1465 flip: _extends({
1466 enabled: instance.props.flip,
1467 behavior: instance.props.flipBehavior
1468 }, flipModifier),
1469 arrow: _extends({
1470 element: arrow,
1471 enabled: !!arrow
1472 }, getModifier(popperOptions, 'arrow')),
1473 offset: _extends({
1474 offset: instance.props.offset
1475 }, getModifier(popperOptions, 'offset'))
1476 }),
1477 onCreate: function onCreate(data) {
1478 applyMutations(data);
1479 preserveInvocation(popperOptions && popperOptions.onCreate, config.onCreate, [data]);
1480 runMountCallback();
1481 },
1482 onUpdate: function onUpdate(data) {
1483 applyMutations(data);
1484 preserveInvocation(popperOptions && popperOptions.onUpdate, config.onUpdate, [data]);
1485 runMountCallback();
1486 }
1487 });
1488
1489 instance.popperInstance = new Popper(reference, popper, config);
1490 }
1491
1492 function runMountCallback() {
1493 // Only invoke currentMountCallback after 2 updates
1494 // This fixes some bugs in Popper.js (TODO: aim for only 1 update)
1495 if (popperUpdates === 0) {
1496 popperUpdates++; // 1
1497
1498 instance.popperInstance.update();
1499 } else if (currentMountCallback && popperUpdates === 1) {
1500 popperUpdates++; // 2
1501
1502 reflow(popper);
1503 currentMountCallback();
1504 }
1505 }
1506
1507 function mount() {
1508 // The mounting callback (`currentMountCallback`) is only run due to a
1509 // popperInstance update/create
1510 popperUpdates = 0;
1511 var appendTo = instance.props.appendTo;
1512 var parentNode; // By default, we'll append the popper to the triggerTargets's parentNode so
1513 // it's directly after the reference element so the elements inside the
1514 // tippy can be tabbed to
1515 // If there are clipping issues, the user can specify a different appendTo
1516 // and ensure focus management is handled correctly manually
1517
1518 var node = getCurrentTarget();
1519
1520 if (instance.props.interactive && appendTo === defaultProps.appendTo || appendTo === 'parent') {
1521 parentNode = node.parentNode;
1522 } else {
1523 parentNode = invokeWithArgsOrReturn(appendTo, [node]);
1524 } // The popper element needs to exist on the DOM before its position can be
1525 // updated as Popper.js needs to read its dimensions
1526
1527
1528 if (!parentNode.contains(popper)) {
1529 parentNode.appendChild(popper);
1530 }
1531
1532 {
1533 // Accessibility check
1534 warnWhen(instance.props.interactive && appendTo === defaultProps.appendTo && node.nextElementSibling !== popper, ['Interactive tippy element may not be accessible via keyboard navigation', 'because it is not directly after the reference element in the DOM source', 'order.', '\n\n', 'Using a wrapper <div> or <span> tag around the reference element solves', 'this by creating a new parentNode context.', '\n\n', 'Specifying `appendTo: document.body` silences this warning, but it', 'assumes you are using a focus management solution to handle keyboard', 'navigation.', '\n\n', 'See: https://atomiks.github.io/tippyjs/accessibility/#interactivity'].join(' '));
1535 }
1536
1537 setModifierValue(instance.popperInstance.modifiers, 'flip', 'enabled', instance.props.flip);
1538 instance.popperInstance.enableEventListeners(); // Mounting callback invoked in `onUpdate`
1539
1540 instance.popperInstance.update();
1541 }
1542
1543 function scheduleShow(event) {
1544 instance.clearDelayTimeouts();
1545
1546 if (!instance.popperInstance) {
1547 createPopperInstance();
1548 }
1549
1550 if (event) {
1551 invokeHook('onTrigger', [instance, event]);
1552 }
1553
1554 addDocumentMouseDownListener();
1555 var delay = getDelay(true);
1556
1557 if (delay) {
1558 showTimeout = setTimeout(function () {
1559 instance.show();
1560 }, delay);
1561 } else {
1562 instance.show();
1563 }
1564 }
1565
1566 function scheduleHide(event) {
1567 instance.clearDelayTimeouts();
1568 invokeHook('onUntrigger', [instance, event]);
1569
1570 if (!instance.state.isVisible) {
1571 removeDocumentMouseDownListener();
1572 return;
1573 } // For interactive tippies, scheduleHide is added to a document.body handler
1574 // from onMouseLeave so must intercept scheduled hides from mousemove/leave
1575 // events when trigger contains mouseenter and click, and the tip is
1576 // currently shown as a result of a click.
1577
1578
1579 if (includes(instance.props.trigger, 'mouseenter') && includes(instance.props.trigger, 'click') && includes(['mouseleave', 'mousemove'], event.type) && isVisibleFromClick) {
1580 return;
1581 }
1582
1583 var delay = getDelay(false);
1584
1585 if (delay) {
1586 hideTimeout = setTimeout(function () {
1587 if (instance.state.isVisible) {
1588 instance.hide();
1589 }
1590 }, delay);
1591 } else {
1592 // Fixes a `transitionend` problem when it fires 1 frame too
1593 // late sometimes, we don't want hide() to be called.
1594 scheduleHideAnimationFrame = requestAnimationFrame(function () {
1595 instance.hide();
1596 });
1597 }
1598 }
1599 /* ======================= 🔑 Public methods 🔑 ======================= */
1600
1601
1602 function enable() {
1603 instance.state.isEnabled = true;
1604 }
1605
1606 function disable() {
1607 // Disabling the instance should also hide it
1608 // https://github.com/atomiks/tippy.js-react/issues/106
1609 instance.hide();
1610 instance.state.isEnabled = false;
1611 }
1612
1613 function clearDelayTimeouts() {
1614 clearTimeout(showTimeout);
1615 clearTimeout(hideTimeout);
1616 cancelAnimationFrame(scheduleHideAnimationFrame);
1617 }
1618
1619 function setProps(partialProps) {
1620 {
1621 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('setProps'));
1622 }
1623
1624 if (instance.state.isDestroyed) {
1625 return;
1626 }
1627
1628 {
1629 validateProps(partialProps, plugins);
1630 warnWhen(partialProps.plugins ? partialProps.plugins.length !== plugins.length || plugins.some(function (p, i) {
1631 if (partialProps.plugins && partialProps.plugins[i]) {
1632 return p !== partialProps.plugins[i];
1633 } else {
1634 return true;
1635 }
1636 }) : false, "Cannot update plugins");
1637 }
1638
1639 invokeHook('onBeforeUpdate', [instance, partialProps]);
1640 removeListenersFromTriggerTarget();
1641 var prevProps = instance.props;
1642 var nextProps = evaluateProps(reference, _extends({}, instance.props, {}, partialProps, {
1643 ignoreAttributes: true
1644 }));
1645 nextProps.ignoreAttributes = useIfDefined(partialProps.ignoreAttributes, prevProps.ignoreAttributes);
1646 instance.props = nextProps;
1647 addListenersToTriggerTarget();
1648
1649 if (prevProps.interactiveDebounce !== nextProps.interactiveDebounce) {
1650 cleanupInteractiveMouseListeners();
1651 debouncedOnMouseMove = debounce(onMouseMove, nextProps.interactiveDebounce);
1652 }
1653
1654 updatePopperElement(popper, prevProps, nextProps);
1655 instance.popperChildren = getChildren(popper); // Ensure stale aria-expanded attributes are removed
1656
1657 if (prevProps.triggerTarget && !nextProps.triggerTarget) {
1658 normalizeToArray(prevProps.triggerTarget).forEach(function (node) {
1659 node.removeAttribute('aria-expanded');
1660 });
1661 } else if (nextProps.triggerTarget) {
1662 reference.removeAttribute('aria-expanded');
1663 }
1664
1665 handleAriaExpandedAttribute();
1666
1667 if (instance.popperInstance) {
1668 if (POPPER_INSTANCE_DEPENDENCIES.some(function (prop) {
1669 return hasOwnProperty(partialProps, prop) && partialProps[prop] !== prevProps[prop];
1670 })) {
1671 var currentReference = instance.popperInstance.reference;
1672 instance.popperInstance.destroy();
1673 createPopperInstance();
1674 instance.popperInstance.reference = currentReference;
1675
1676 if (instance.state.isVisible) {
1677 instance.popperInstance.enableEventListeners();
1678 }
1679 } else {
1680 instance.popperInstance.update();
1681 }
1682 }
1683
1684 invokeHook('onAfterUpdate', [instance, partialProps]);
1685 }
1686
1687 function setContent(content) {
1688 instance.setProps({
1689 content: content
1690 });
1691 }
1692
1693 function show(duration) {
1694 if (duration === void 0) {
1695 duration = getValueAtIndexOrReturn(instance.props.duration, 0, defaultProps.duration);
1696 }
1697
1698 {
1699 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('show'));
1700 } // Early bail-out
1701
1702
1703 var isAlreadyVisible = instance.state.isVisible;
1704 var isDestroyed = instance.state.isDestroyed;
1705 var isDisabled = !instance.state.isEnabled;
1706 var isTouchAndTouchDisabled = currentInput.isTouch && !instance.props.touch;
1707
1708 if (isAlreadyVisible || isDestroyed || isDisabled || isTouchAndTouchDisabled) {
1709 return;
1710 } // Normalize `disabled` behavior across browsers.
1711 // Firefox allows events on disabled elements, but Chrome doesn't.
1712 // Using a wrapper element (i.e. <span>) is recommended.
1713
1714
1715 if (getCurrentTarget().hasAttribute('disabled')) {
1716 return;
1717 }
1718
1719 if (!instance.popperInstance) {
1720 createPopperInstance();
1721 }
1722
1723 invokeHook('onShow', [instance], false);
1724
1725 if (instance.props.onShow(instance) === false) {
1726 return;
1727 }
1728
1729 addDocumentMouseDownListener();
1730 popper.style.visibility = 'visible';
1731 instance.state.isVisible = true; // Prevent a transition of the popper from its previous position and of the
1732 // elements at a different placement
1733 // Check if the tippy was fully unmounted before `show()` was called, to
1734 // allow for smooth transition for `createSingleton()`
1735
1736 if (!instance.state.isMounted) {
1737 setTransitionDuration(transitionableElements.concat(popper), 0);
1738 }
1739
1740 currentMountCallback = function currentMountCallback() {
1741 if (!instance.state.isVisible) {
1742 return;
1743 }
1744
1745 setTransitionDuration([popper], instance.props.updateDuration);
1746 setTransitionDuration(transitionableElements, duration);
1747 setVisibilityState(transitionableElements, 'visible');
1748 handleAriaDescribedByAttribute();
1749 handleAriaExpandedAttribute();
1750 pushIfUnique(mountedInstances, instance);
1751 updateIOSClass(true);
1752 instance.state.isMounted = true;
1753 invokeHook('onMount', [instance]);
1754 onTransitionedIn(duration, function () {
1755 instance.state.isShown = true;
1756 invokeHook('onShown', [instance]);
1757 });
1758 };
1759
1760 mount();
1761 }
1762
1763 function hide(duration) {
1764 if (duration === void 0) {
1765 duration = getValueAtIndexOrReturn(instance.props.duration, 1, defaultProps.duration);
1766 }
1767
1768 {
1769 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('hide'));
1770 } // Early bail-out
1771
1772
1773 var isAlreadyHidden = !instance.state.isVisible && !isBeingDestroyed;
1774 var isDestroyed = instance.state.isDestroyed;
1775 var isDisabled = !instance.state.isEnabled && !isBeingDestroyed;
1776
1777 if (isAlreadyHidden || isDestroyed || isDisabled) {
1778 return;
1779 }
1780
1781 invokeHook('onHide', [instance], false);
1782
1783 if (instance.props.onHide(instance) === false && !isBeingDestroyed) {
1784 return;
1785 }
1786
1787 removeDocumentMouseDownListener();
1788 popper.style.visibility = 'hidden';
1789 instance.state.isVisible = false;
1790 instance.state.isShown = false;
1791 setTransitionDuration(transitionableElements, duration);
1792 setVisibilityState(transitionableElements, 'hidden');
1793 handleAriaDescribedByAttribute();
1794 handleAriaExpandedAttribute();
1795 onTransitionedOut(duration, function () {
1796 instance.popperInstance.disableEventListeners();
1797 instance.popperInstance.options.placement = instance.props.placement;
1798 popper.parentNode.removeChild(popper);
1799 mountedInstances = mountedInstances.filter(function (i) {
1800 return i !== instance;
1801 });
1802
1803 if (mountedInstances.length === 0) {
1804 updateIOSClass(false);
1805 }
1806
1807 instance.state.isMounted = false;
1808 invokeHook('onHidden', [instance]);
1809 });
1810 }
1811
1812 function destroy() {
1813 {
1814 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('destroy'));
1815 }
1816
1817 if (instance.state.isDestroyed) {
1818 return;
1819 }
1820
1821 isBeingDestroyed = true;
1822 instance.clearDelayTimeouts();
1823 instance.hide(0);
1824 removeListenersFromTriggerTarget();
1825 delete reference._tippy;
1826
1827 if (instance.popperInstance) {
1828 instance.popperInstance.destroy();
1829 }
1830
1831 isBeingDestroyed = false;
1832 instance.state.isDestroyed = true;
1833 invokeHook('onDestroy', [instance]);
1834 }
1835 }
1836
1837 function tippy(targets, optionalProps,
1838 /** @deprecated use Props.plugins */
1839 plugins) {
1840 if (optionalProps === void 0) {
1841 optionalProps = {};
1842 }
1843
1844 if (plugins === void 0) {
1845 plugins = [];
1846 }
1847
1848 plugins = defaultProps.plugins.concat(optionalProps.plugins || plugins);
1849
1850 {
1851 validateTargets(targets);
1852 validateProps(optionalProps, plugins);
1853 }
1854
1855 bindGlobalEventListeners();
1856
1857 var passedProps = _extends({}, optionalProps, {
1858 plugins: plugins
1859 });
1860
1861 var elements = getArrayOfElements(targets);
1862
1863 {
1864 var isSingleContentElement = isElement(passedProps.content);
1865 var isMoreThanOneReferenceElement = elements.length > 1;
1866 warnWhen(isSingleContentElement && isMoreThanOneReferenceElement, ['tippy() was passed an Element as the `content` prop, but more than one tippy', 'instance was created by this invocation. This means the content element will', 'only be appended to the last tippy instance.', '\n\n', 'Instead, pass the .innerHTML of the element, or use a function that returns a', 'cloned version of the element instead.', '\n\n', '1) content: element.innerHTML\n', '2) content: () => element.cloneNode(true)'].join(' '));
1867 }
1868
1869 var instances = elements.reduce(function (acc, reference) {
1870 var instance = reference && createTippy(reference, passedProps);
1871
1872 if (instance) {
1873 acc.push(instance);
1874 }
1875
1876 return acc;
1877 }, []);
1878 return isElement(targets) ? instances[0] : instances;
1879 }
1880
1881 tippy.version = version;
1882 tippy.defaultProps = defaultProps;
1883 tippy.setDefaultProps = setDefaultProps;
1884 tippy.currentInput = currentInput;
1885 /**
1886 * Hides all visible poppers on the document
1887 */
1888
1889 var hideAll = function hideAll(_temp) {
1890 var _ref = _temp === void 0 ? {} : _temp,
1891 excludedReferenceOrInstance = _ref.exclude,
1892 duration = _ref.duration;
1893
1894 mountedInstances.forEach(function (instance) {
1895 var isExcluded = false;
1896
1897 if (excludedReferenceOrInstance) {
1898 isExcluded = isReferenceElement(excludedReferenceOrInstance) ? instance.reference === excludedReferenceOrInstance : instance.popper === excludedReferenceOrInstance.popper;
1899 }
1900
1901 if (!isExcluded) {
1902 instance.hide(duration);
1903 }
1904 });
1905 };
1906
1907 /**
1908 * Re-uses a single tippy element for many different tippy instances.
1909 * Replaces v4's `tippy.group()`.
1910 */
1911
1912 var createSingleton = function createSingleton(tippyInstances, optionalProps,
1913 /** @deprecated use Props.plugins */
1914 plugins) {
1915 if (optionalProps === void 0) {
1916 optionalProps = {};
1917 }
1918
1919 if (plugins === void 0) {
1920 plugins = [];
1921 }
1922
1923 {
1924 errorWhen(!Array.isArray(tippyInstances), ['The first argument passed to createSingleton() must be an array of tippy', 'instances. The passed value was', String(tippyInstances)].join(' '));
1925 }
1926
1927 plugins = optionalProps.plugins || plugins;
1928 tippyInstances.forEach(function (instance) {
1929 instance.disable();
1930 });
1931
1932 var userAria = _extends({}, defaultProps, {}, optionalProps).aria;
1933
1934 var currentAria;
1935 var currentTarget;
1936 var shouldSkipUpdate = false;
1937 var references = tippyInstances.map(function (instance) {
1938 return instance.reference;
1939 });
1940 var singleton = {
1941 fn: function fn(instance) {
1942 function handleAriaDescribedByAttribute(isShow) {
1943 if (!currentAria) {
1944 return;
1945 }
1946
1947 var attr = "aria-" + currentAria;
1948
1949 if (isShow && !instance.props.interactive) {
1950 currentTarget.setAttribute(attr, instance.popperChildren.tooltip.id);
1951 } else {
1952 currentTarget.removeAttribute(attr);
1953 }
1954 }
1955
1956 return {
1957 onAfterUpdate: function onAfterUpdate(_, _ref) {
1958 var aria = _ref.aria;
1959
1960 // Ensure `aria` for the singleton instance stays `null`, while
1961 // changing the `userAria` value
1962 if (aria !== undefined && aria !== userAria) {
1963 if (!shouldSkipUpdate) {
1964 userAria = aria;
1965 } else {
1966 shouldSkipUpdate = true;
1967 instance.setProps({
1968 aria: null
1969 });
1970 shouldSkipUpdate = false;
1971 }
1972 }
1973 },
1974 onDestroy: function onDestroy() {
1975 tippyInstances.forEach(function (instance) {
1976 instance.enable();
1977 });
1978 },
1979 onMount: function onMount() {
1980 handleAriaDescribedByAttribute(true);
1981 },
1982 onUntrigger: function onUntrigger() {
1983 handleAriaDescribedByAttribute(false);
1984 },
1985 onTrigger: function onTrigger(_, event) {
1986 var target = event.currentTarget;
1987 var index = references.indexOf(target); // bail-out
1988
1989 if (target === currentTarget) {
1990 return;
1991 }
1992
1993 currentTarget = target;
1994 currentAria = userAria;
1995
1996 if (instance.state.isVisible) {
1997 handleAriaDescribedByAttribute(true);
1998 }
1999
2000 instance.popperInstance.reference = target;
2001 instance.setContent(tippyInstances[index].props.content);
2002 }
2003 };
2004 }
2005 };
2006 return tippy(div(), _extends({}, optionalProps, {
2007 plugins: [singleton].concat(plugins),
2008 aria: null,
2009 triggerTarget: references
2010 }));
2011 };
2012
2013 var BUBBLING_EVENTS_MAP = {
2014 mouseover: 'mouseenter',
2015 focusin: 'focus',
2016 click: 'click'
2017 };
2018 /**
2019 * Creates a delegate instance that controls the creation of tippy instances
2020 * for child elements (`target` CSS selector).
2021 */
2022
2023 function delegate(targets, props,
2024 /** @deprecated use Props.plugins */
2025 plugins) {
2026 if (plugins === void 0) {
2027 plugins = [];
2028 }
2029
2030 {
2031 errorWhen(!(props && props.target), ['You must specity a `target` prop indicating a CSS selector string matching', 'the target elements that should receive a tippy.'].join(' '));
2032 }
2033
2034 plugins = props.plugins || plugins;
2035 var listeners = [];
2036 var childTippyInstances = [];
2037 var target = props.target;
2038 var nativeProps = removeProperties(props, ['target']);
2039
2040 var parentProps = _extends({}, nativeProps, {
2041 plugins: plugins,
2042 trigger: 'manual'
2043 });
2044
2045 var childProps = _extends({}, nativeProps, {
2046 plugins: plugins,
2047 showOnCreate: true
2048 });
2049
2050 var returnValue = tippy(targets, parentProps);
2051 var normalizedReturnValue = normalizeToArray(returnValue);
2052
2053 function onTrigger(event) {
2054 if (!event.target) {
2055 return;
2056 }
2057
2058 var targetNode = event.target.closest(target);
2059
2060 if (!targetNode) {
2061 return;
2062 } // Get relevant trigger with fallbacks:
2063 // 1. Check `data-tippy-trigger` attribute on target node
2064 // 2. Fallback to `trigger` passed to `delegate()`
2065 // 3. Fallback to `defaultProps.trigger`
2066
2067
2068 var trigger = targetNode.getAttribute('data-tippy-trigger') || props.trigger || defaultProps.trigger; // Only create the instance if the bubbling event matches the trigger type
2069
2070 if (!includes(trigger, BUBBLING_EVENTS_MAP[event.type])) {
2071 return;
2072 }
2073
2074 var instance = tippy(targetNode, childProps);
2075
2076 if (instance) {
2077 childTippyInstances = childTippyInstances.concat(instance);
2078 }
2079 }
2080
2081 function on(node, eventType, handler, options) {
2082 if (options === void 0) {
2083 options = false;
2084 }
2085
2086 node.addEventListener(eventType, handler, options);
2087 listeners.push({
2088 node: node,
2089 eventType: eventType,
2090 handler: handler,
2091 options: options
2092 });
2093 }
2094
2095 function addEventListeners(instance) {
2096 var reference = instance.reference;
2097 on(reference, 'mouseover', onTrigger);
2098 on(reference, 'focusin', onTrigger);
2099 on(reference, 'click', onTrigger);
2100 }
2101
2102 function removeEventListeners() {
2103 listeners.forEach(function (_ref) {
2104 var node = _ref.node,
2105 eventType = _ref.eventType,
2106 handler = _ref.handler,
2107 options = _ref.options;
2108 node.removeEventListener(eventType, handler, options);
2109 });
2110 listeners = [];
2111 }
2112
2113 function applyMutations(instance) {
2114 var originalDestroy = instance.destroy;
2115
2116 instance.destroy = function (shouldDestroyChildInstances) {
2117 if (shouldDestroyChildInstances === void 0) {
2118 shouldDestroyChildInstances = true;
2119 }
2120
2121 if (shouldDestroyChildInstances) {
2122 childTippyInstances.forEach(function (instance) {
2123 instance.destroy();
2124 });
2125 }
2126
2127 childTippyInstances = [];
2128 removeEventListeners();
2129 originalDestroy();
2130 };
2131
2132 addEventListeners(instance);
2133 }
2134
2135 normalizedReturnValue.forEach(applyMutations);
2136 return returnValue;
2137 }
2138
2139 var animateFill = {
2140 name: 'animateFill',
2141 defaultValue: false,
2142 fn: function fn(instance) {
2143 var _instance$popperChild = instance.popperChildren,
2144 tooltip = _instance$popperChild.tooltip,
2145 content = _instance$popperChild.content;
2146 var backdrop = instance.props.animateFill ? createBackdropElement() : null;
2147
2148 function addBackdropToPopperChildren() {
2149 instance.popperChildren.backdrop = backdrop;
2150 }
2151
2152 return {
2153 onCreate: function onCreate() {
2154 if (backdrop) {
2155 addBackdropToPopperChildren();
2156 tooltip.insertBefore(backdrop, tooltip.firstElementChild);
2157 tooltip.setAttribute('data-animatefill', '');
2158 tooltip.style.overflow = 'hidden';
2159 instance.setProps({
2160 animation: 'shift-away',
2161 arrow: false
2162 });
2163 }
2164 },
2165 onMount: function onMount() {
2166 if (backdrop) {
2167 var transitionDuration = tooltip.style.transitionDuration;
2168 var duration = Number(transitionDuration.replace('ms', '')); // The content should fade in after the backdrop has mostly filled the
2169 // tooltip element. `clip-path` is the other alternative but is not
2170 // well-supported and is buggy on some devices.
2171
2172 content.style.transitionDelay = Math.round(duration / 10) + "ms";
2173 backdrop.style.transitionDuration = transitionDuration;
2174 setVisibilityState([backdrop], 'visible'); // Warn if the stylesheets are not loaded
2175
2176 {
2177 warnWhen(getComputedStyle(backdrop).position !== 'absolute', "The `tippy.js/dist/backdrop.css` stylesheet has not been\n imported!\n \n The `animateFill` plugin requires this stylesheet to work.");
2178 warnWhen(getComputedStyle(tooltip).transform === 'none', "The `tippy.js/animations/shift-away.css` stylesheet has not\n been imported!\n \n The `animateFill` plugin requires this stylesheet to work.");
2179 }
2180 }
2181 },
2182 onShow: function onShow() {
2183 if (backdrop) {
2184 backdrop.style.transitionDuration = '0ms';
2185 }
2186 },
2187 onHide: function onHide() {
2188 if (backdrop) {
2189 setVisibilityState([backdrop], 'hidden');
2190 }
2191 },
2192 onAfterUpdate: function onAfterUpdate() {
2193 // With this type of prop, it's highly unlikely it will be changed
2194 // dynamically. We'll leave out the diff/update logic it to save bytes.
2195 // `popperChildren` is assigned a new object onAfterUpdate
2196 addBackdropToPopperChildren();
2197 }
2198 };
2199 }
2200 };
2201
2202 function createBackdropElement() {
2203 var backdrop = div();
2204 backdrop.className = BACKDROP_CLASS;
2205 setVisibilityState([backdrop], 'hidden');
2206 return backdrop;
2207 }
2208
2209 var followCursor = {
2210 name: 'followCursor',
2211 defaultValue: false,
2212 fn: function fn(instance) {
2213 var reference = instance.reference,
2214 popper = instance.popper;
2215 var originalReference = null; // Support iframe contexts
2216 // Static check that assumes any of the `triggerTarget` or `reference`
2217 // nodes will never change documents, even when they are updated
2218
2219 var doc = getOwnerDocument(instance.props.triggerTarget || reference); // Internal state
2220
2221 var lastMouseMoveEvent;
2222 var mouseCoords = null;
2223 var isInternallySettingControlledProp = false; // These are controlled by this plugin, so we need to store the user's
2224 // original prop value
2225
2226 var userProps = instance.props;
2227
2228 function setUserProps(props) {
2229 var keys = Object.keys(props);
2230 keys.forEach(function (prop) {
2231 userProps[prop] = useIfDefined(props[prop], userProps[prop]);
2232 });
2233 }
2234
2235 function getIsManual() {
2236 return instance.props.trigger.trim() === 'manual';
2237 }
2238
2239 function getIsEnabled() {
2240 // #597
2241 var isValidMouseEvent = getIsManual() ? true : // Check if a keyboard "click"
2242 mouseCoords !== null && !(mouseCoords.clientX === 0 && mouseCoords.clientY === 0);
2243 return instance.props.followCursor && isValidMouseEvent;
2244 }
2245
2246 function getIsInitialBehavior() {
2247 return currentInput.isTouch || instance.props.followCursor === 'initial' && instance.state.isVisible;
2248 }
2249
2250 function resetReference() {
2251 if (instance.popperInstance && originalReference) {
2252 instance.popperInstance.reference = originalReference;
2253 }
2254 }
2255
2256 function handlePlacement() {
2257 // Due to `getVirtualOffsets()`, we need to reverse the placement if it's
2258 // shifted (start -> end, and vice-versa)
2259 // Early bail-out
2260 if (!getIsEnabled() && instance.props.placement === userProps.placement) {
2261 return;
2262 }
2263
2264 var placement = userProps.placement;
2265 var shift = placement.split('-')[1];
2266 isInternallySettingControlledProp = true;
2267 instance.setProps({
2268 placement: getIsEnabled() && shift ? placement.replace(shift, shift === 'start' ? 'end' : 'start') : placement
2269 });
2270 isInternallySettingControlledProp = false;
2271 }
2272
2273 function handlePopperListeners() {
2274 if (!instance.popperInstance) {
2275 return;
2276 } // Popper's scroll listeners make sense for `true` only. TODO: work out
2277 // how to only listen horizontal scroll for "horizontal" and vertical
2278 // scroll for "vertical"
2279
2280
2281 if (getIsEnabled() && getIsInitialBehavior()) {
2282 instance.popperInstance.disableEventListeners();
2283 }
2284 }
2285
2286 function handleMouseMoveListener() {
2287 if (getIsEnabled()) {
2288 addListener();
2289 } else {
2290 resetReference();
2291 }
2292 }
2293
2294 function triggerLastMouseMove() {
2295 if (getIsEnabled()) {
2296 onMouseMove(lastMouseMoveEvent);
2297 }
2298 }
2299
2300 function addListener() {
2301 doc.addEventListener('mousemove', onMouseMove);
2302 }
2303
2304 function removeListener() {
2305 doc.removeEventListener('mousemove', onMouseMove);
2306 }
2307
2308 function onMouseMove(event) {
2309 var _lastMouseMoveEvent = lastMouseMoveEvent = event,
2310 clientX = _lastMouseMoveEvent.clientX,
2311 clientY = _lastMouseMoveEvent.clientY;
2312
2313 if (!instance.popperInstance || !instance.state.currentPlacement) {
2314 return;
2315 } // If the instance is interactive, avoid updating the position unless it's
2316 // over the reference element
2317
2318
2319 var isCursorOverReference = closestCallback(event.target, function (el) {
2320 return el === reference;
2321 });
2322 var followCursor = instance.props.followCursor;
2323 var isHorizontal = followCursor === 'horizontal';
2324 var isVertical = followCursor === 'vertical';
2325 var isVerticalPlacement = includes(['top', 'bottom'], getBasePlacement(instance.state.currentPlacement)); // The virtual reference needs some size to prevent itself from overflowing
2326
2327 var _getVirtualOffsets = getVirtualOffsets(popper, isVerticalPlacement),
2328 size = _getVirtualOffsets.size,
2329 x = _getVirtualOffsets.x,
2330 y = _getVirtualOffsets.y;
2331
2332 if (isCursorOverReference || !instance.props.interactive) {
2333 // Preserve custom position ReferenceObjects, which may not be the
2334 // original targets reference passed as an argument
2335 if (originalReference === null) {
2336 originalReference = instance.popperInstance.reference;
2337 }
2338
2339 instance.popperInstance.reference = {
2340 referenceNode: reference,
2341 // These `client` values don't get used by Popper.js if they are 0
2342 clientWidth: 0,
2343 clientHeight: 0,
2344 getBoundingClientRect: function getBoundingClientRect() {
2345 var rect = reference.getBoundingClientRect();
2346 return {
2347 width: isVerticalPlacement ? size : 0,
2348 height: isVerticalPlacement ? 0 : size,
2349 top: (isHorizontal ? rect.top : clientY) - y,
2350 bottom: (isHorizontal ? rect.bottom : clientY) + y,
2351 left: (isVertical ? rect.left : clientX) - x,
2352 right: (isVertical ? rect.right : clientX) + x
2353 };
2354 }
2355 };
2356 instance.popperInstance.update();
2357 }
2358
2359 if (getIsInitialBehavior()) {
2360 removeListener();
2361 }
2362 }
2363
2364 return {
2365 onAfterUpdate: function onAfterUpdate(_, partialProps) {
2366 if (!isInternallySettingControlledProp) {
2367 setUserProps(partialProps);
2368
2369 if (partialProps.placement) {
2370 handlePlacement();
2371 }
2372 } // A new placement causes the popperInstance to be recreated
2373
2374
2375 if (partialProps.placement) {
2376 handlePopperListeners();
2377 } // Wait for `.update()` to set `instance.state.currentPlacement` to
2378 // the new placement
2379
2380
2381 requestAnimationFrame(triggerLastMouseMove);
2382 },
2383 onMount: function onMount() {
2384 triggerLastMouseMove();
2385 handlePopperListeners();
2386 },
2387 onShow: function onShow() {
2388 if (getIsManual()) {
2389 // Since there's no trigger event to use, we have to use these as
2390 // baseline coords
2391 mouseCoords = {
2392 clientX: 0,
2393 clientY: 0
2394 }; // Ensure `lastMouseMoveEvent` doesn't access any other properties
2395 // of a MouseEvent here
2396
2397 lastMouseMoveEvent = mouseCoords;
2398 handlePlacement();
2399 handleMouseMoveListener();
2400 }
2401 },
2402 onTrigger: function onTrigger(_, event) {
2403 // Tapping on touch devices can trigger `mouseenter` then `focus`
2404 if (mouseCoords) {
2405 return;
2406 }
2407
2408 if (isMouseEvent(event)) {
2409 mouseCoords = {
2410 clientX: event.clientX,
2411 clientY: event.clientY
2412 };
2413 lastMouseMoveEvent = event;
2414 }
2415
2416 handlePlacement();
2417 handleMouseMoveListener();
2418 },
2419 onUntrigger: function onUntrigger() {
2420 // If untriggered before showing (`onHidden` will never be invoked)
2421 if (!instance.state.isVisible) {
2422 removeListener();
2423 mouseCoords = null;
2424 }
2425 },
2426 onHidden: function onHidden() {
2427 removeListener();
2428 resetReference();
2429 mouseCoords = null;
2430 }
2431 };
2432 }
2433 };
2434 function getVirtualOffsets(popper, isVerticalPlacement) {
2435 var size = isVerticalPlacement ? popper.offsetWidth : popper.offsetHeight;
2436 return {
2437 size: size,
2438 x: isVerticalPlacement ? size : 0,
2439 y: isVerticalPlacement ? 0 : size
2440 };
2441 }
2442
2443 // position. This will require the `followCursor` plugin's fixes for overflow
2444 // due to using event.clientX/Y values. (normalizedPlacement, getVirtualOffsets)
2445
2446 var inlinePositioning = {
2447 name: 'inlinePositioning',
2448 defaultValue: false,
2449 fn: function fn(instance) {
2450 var reference = instance.reference;
2451
2452 function getIsEnabled() {
2453 return !!instance.props.inlinePositioning;
2454 }
2455
2456 return {
2457 onHidden: function onHidden() {
2458 if (getIsEnabled()) {
2459 instance.popperInstance.reference = reference;
2460 }
2461 },
2462 onShow: function onShow() {
2463 if (!getIsEnabled()) {
2464 return;
2465 }
2466
2467 instance.popperInstance.reference = {
2468 referenceNode: reference,
2469 // These `client` values don't get used by Popper.js if they are 0
2470 clientWidth: 0,
2471 clientHeight: 0,
2472 getBoundingClientRect: function getBoundingClientRect() {
2473 return getInlineBoundingClientRect(instance.state.currentPlacement && getBasePlacement(instance.state.currentPlacement), reference.getBoundingClientRect(), arrayFrom(reference.getClientRects()));
2474 }
2475 };
2476 }
2477 };
2478 }
2479 };
2480 function getInlineBoundingClientRect(currentBasePlacement, boundingRect, clientRects) {
2481 // Not an inline element, or placement is not yet known
2482 if (clientRects.length < 2 || currentBasePlacement === null) {
2483 return boundingRect;
2484 }
2485
2486 switch (currentBasePlacement) {
2487 case 'top':
2488 case 'bottom':
2489 {
2490 var firstRect = clientRects[0];
2491 var lastRect = clientRects[clientRects.length - 1];
2492 var isTop = currentBasePlacement === 'top';
2493 var top = firstRect.top;
2494 var bottom = lastRect.bottom;
2495 var left = isTop ? firstRect.left : lastRect.left;
2496 var right = isTop ? firstRect.right : lastRect.right;
2497 var width = right - left;
2498 var height = bottom - top;
2499 return {
2500 top: top,
2501 bottom: bottom,
2502 left: left,
2503 right: right,
2504 width: width,
2505 height: height
2506 };
2507 }
2508
2509 case 'left':
2510 case 'right':
2511 {
2512 var minLeft = Math.min.apply(Math, clientRects.map(function (rects) {
2513 return rects.left;
2514 }));
2515 var maxRight = Math.max.apply(Math, clientRects.map(function (rects) {
2516 return rects.right;
2517 }));
2518 var measureRects = clientRects.filter(function (rect) {
2519 return currentBasePlacement === 'left' ? rect.left === minLeft : rect.right === maxRight;
2520 });
2521 var _top = measureRects[0].top;
2522 var _bottom = measureRects[measureRects.length - 1].bottom;
2523 var _left = minLeft;
2524 var _right = maxRight;
2525
2526 var _width = _right - _left;
2527
2528 var _height = _bottom - _top;
2529
2530 return {
2531 top: _top,
2532 bottom: _bottom,
2533 left: _left,
2534 right: _right,
2535 width: _width,
2536 height: _height
2537 };
2538 }
2539
2540 default:
2541 {
2542 return boundingRect;
2543 }
2544 }
2545 }
2546
2547 var sticky = {
2548 name: 'sticky',
2549 defaultValue: false,
2550 fn: function fn(instance) {
2551 var reference = instance.reference,
2552 popper = instance.popper;
2553
2554 function getReference() {
2555 return instance.popperInstance ? instance.popperInstance.reference : reference;
2556 }
2557
2558 function shouldCheck(value) {
2559 return instance.props.sticky === true || instance.props.sticky === value;
2560 }
2561
2562 var prevRefRect = null;
2563 var prevPopRect = null;
2564
2565 function updatePosition() {
2566 var currentRefRect = shouldCheck('reference') ? getReference().getBoundingClientRect() : null;
2567 var currentPopRect = shouldCheck('popper') ? popper.getBoundingClientRect() : null;
2568
2569 if (currentRefRect && areRectsDifferent(prevRefRect, currentRefRect) || currentPopRect && areRectsDifferent(prevPopRect, currentPopRect)) {
2570 instance.popperInstance.update();
2571 }
2572
2573 prevRefRect = currentRefRect;
2574 prevPopRect = currentPopRect;
2575
2576 if (instance.state.isMounted) {
2577 requestAnimationFrame(updatePosition);
2578 }
2579 }
2580
2581 return {
2582 onMount: function onMount() {
2583 if (instance.props.sticky) {
2584 updatePosition();
2585 }
2586 }
2587 };
2588 }
2589 };
2590
2591 function areRectsDifferent(rectA, rectB) {
2592 if (rectA && rectB) {
2593 return rectA.top !== rectB.top || rectA.right !== rectB.right || rectA.bottom !== rectB.bottom || rectA.left !== rectB.left;
2594 }
2595
2596 return true;
2597 }
2598
2599 if (isBrowser) {
2600 injectCSS(css);
2601 }
2602
2603 tippy.setDefaultProps({
2604 plugins: [animateFill, followCursor, inlinePositioning, sticky]
2605 });
2606 tippy.createSingleton = createSingleton;
2607 tippy.delegate = delegate;
2608 tippy.hideAll = hideAll;
2609 tippy.roundArrow = ROUND_ARROW;
2610
2611 return tippy;
2612
2613}(Popper));
2614//# sourceMappingURL=tippy-bundle.iife.js.map