UNPKG

59.4 kBJavaScriptView Raw
1/**!
2* tippy.js v5.2.1
3* (c) 2017-2020 atomiks
4* MIT License
5*/
6'use strict';
7
8function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
9
10var Popper = _interopDefault(require('popper.js'));
11
12function _extends() {
13 _extends = Object.assign || function (target) {
14 for (var i = 1; i < arguments.length; i++) {
15 var source = arguments[i];
16
17 for (var key in source) {
18 if (Object.prototype.hasOwnProperty.call(source, key)) {
19 target[key] = source[key];
20 }
21 }
22 }
23
24 return target;
25 };
26
27 return _extends.apply(this, arguments);
28}
29
30var version = "5.2.1";
31
32/**
33 * Triggers reflow
34 */
35function reflow(element) {
36 void element.offsetHeight;
37}
38/**
39 * Sets the innerHTML of an element
40 */
41
42function setInnerHTML(element, html) {
43 element[innerHTML()] = html;
44}
45/**
46 * Determines if the value is a reference element
47 */
48
49function isReferenceElement(value) {
50 return !!(value && value._tippy && value._tippy.reference === value);
51}
52/**
53 * Safe .hasOwnProperty check, for prototype-less objects
54 */
55
56function hasOwnProperty(obj, key) {
57 return {}.hasOwnProperty.call(obj, key);
58}
59/**
60 * Returns an array of elements based on the value
61 */
62
63function getArrayOfElements(value) {
64 if (isElement(value)) {
65 return [value];
66 }
67
68 if (isNodeList(value)) {
69 return arrayFrom(value);
70 }
71
72 if (Array.isArray(value)) {
73 return value;
74 }
75
76 return arrayFrom(document.querySelectorAll(value));
77}
78/**
79 * Returns a value at a given index depending on if it's an array or number
80 */
81
82function getValueAtIndexOrReturn(value, index, defaultValue) {
83 if (Array.isArray(value)) {
84 var v = value[index];
85 return v == null ? Array.isArray(defaultValue) ? defaultValue[index] : defaultValue : v;
86 }
87
88 return value;
89}
90/**
91 * Prevents errors from being thrown while accessing nested modifier objects
92 * in `popperOptions`
93 */
94
95function getModifier(obj, key) {
96 return obj && obj.modifiers && obj.modifiers[key];
97}
98/**
99 * Determines if the value is of type
100 */
101
102function isType(value, type) {
103 var str = {}.toString.call(value);
104 return str.indexOf('[object') === 0 && str.indexOf(type + "]") > -1;
105}
106/**
107 * Determines if the value is of type Element
108 */
109
110function isElement(value) {
111 return isType(value, 'Element');
112}
113/**
114 * Determines if the value is of type NodeList
115 */
116
117function isNodeList(value) {
118 return isType(value, 'NodeList');
119}
120/**
121 * Determines if the value is of type MouseEvent
122 */
123
124function isMouseEvent(value) {
125 return isType(value, 'MouseEvent');
126}
127/**
128 * Firefox extensions don't allow setting .innerHTML directly, this will trick
129 * it
130 */
131
132function innerHTML() {
133 return 'innerHTML';
134}
135/**
136 * Evaluates a function if one, or returns the value
137 */
138
139function invokeWithArgsOrReturn(value, args) {
140 return typeof value === 'function' ? value.apply(void 0, args) : value;
141}
142/**
143 * Sets a popperInstance modifier's property to a value
144 */
145
146function setModifierValue(modifiers, name, property, value) {
147 modifiers.filter(function (m) {
148 return m.name === name;
149 })[0][property] = value;
150}
151/**
152 * Returns a new `div` element
153 */
154
155function div() {
156 return document.createElement('div');
157}
158/**
159 * Applies a transition duration to a list of elements
160 */
161
162function setTransitionDuration(els, value) {
163 els.forEach(function (el) {
164 if (el) {
165 el.style.transitionDuration = value + "ms";
166 }
167 });
168}
169/**
170 * Sets the visibility state to elements so they can begin to transition
171 */
172
173function setVisibilityState(els, state) {
174 els.forEach(function (el) {
175 if (el) {
176 el.setAttribute('data-state', state);
177 }
178 });
179}
180/**
181 * Debounce utility. To avoid bloating bundle size, we're only passing 1
182 * argument here, a more generic function would pass all arguments. Only
183 * `onMouseMove` uses this which takes the event object for now.
184 */
185
186function debounce(fn, ms) {
187 // Avoid wrapping in `setTimeout` if ms is 0 anyway
188 if (ms === 0) {
189 return fn;
190 }
191
192 var timeout;
193 return function (arg) {
194 clearTimeout(timeout);
195 timeout = setTimeout(function () {
196 fn(arg);
197 }, ms);
198 };
199}
200/**
201 * Preserves the original function invocation when another function replaces it
202 */
203
204function preserveInvocation(originalFn, currentFn, args) {
205 if (originalFn && originalFn !== currentFn) {
206 originalFn.apply(void 0, args);
207 }
208}
209/**
210 * Deletes properties from an object (pure)
211 */
212
213function removeProperties(obj, keys) {
214 var clone = _extends({}, obj);
215
216 keys.forEach(function (key) {
217 delete clone[key];
218 });
219 return clone;
220}
221/**
222 * Ponyfill for Array.from - converts iterable values to an array
223 */
224
225function arrayFrom(value) {
226 return [].slice.call(value);
227}
228/**
229 * Works like Element.prototype.closest, but uses a callback instead
230 */
231
232function closestCallback(element, callback) {
233 while (element) {
234 if (callback(element)) {
235 return element;
236 }
237
238 element = element.parentElement;
239 }
240
241 return null;
242}
243/**
244 * Determines if an array or string includes a string
245 */
246
247function includes(a, b) {
248 return a.indexOf(b) > -1;
249}
250/**
251 * Creates an array from string of values separated by whitespace
252 */
253
254function splitBySpaces(value) {
255 return value.split(/\s+/).filter(Boolean);
256}
257/**
258 * Returns the `nextValue` if `nextValue` is not `undefined`, otherwise returns
259 * `currentValue`
260 */
261
262function useIfDefined(nextValue, currentValue) {
263 return nextValue !== undefined ? nextValue : currentValue;
264}
265/**
266 * Converts a value that's an array or single value to an array
267 */
268
269function normalizeToArray(value) {
270 return [].concat(value);
271}
272/**
273 * Returns the ownerDocument of the first available element, otherwise global
274 * document
275 */
276
277function getOwnerDocument(elementOrElements) {
278 var _normalizeToArray = normalizeToArray(elementOrElements),
279 element = _normalizeToArray[0];
280
281 return element ? element.ownerDocument || document : document;
282}
283/**
284 * Adds item to array if array does not contain it
285 */
286
287function pushIfUnique(arr, value) {
288 if (arr.indexOf(value) === -1) {
289 arr.push(value);
290 }
291}
292/**
293 * Adds `px` if value is a number, or returns it directly
294 */
295
296function appendPxIfNumber(value) {
297 return typeof value === 'number' ? value + "px" : value;
298}
299/**
300 * Filters out duplicate elements in an array
301 */
302
303function unique(arr) {
304 return arr.filter(function (item, index) {
305 return arr.indexOf(item) === index;
306 });
307}
308/**
309 * Returns number from number or CSS units string
310 */
311
312function getNumber(value) {
313 return typeof value === 'number' ? value : parseFloat(value);
314}
315/**
316 * Gets number or CSS string units in pixels (e.g. `1rem` -> 16)
317 */
318
319function getUnitsInPx(doc, value) {
320 var isRem = typeof value === 'string' && includes(value, 'rem');
321 var html = doc.documentElement;
322 var rootFontSize = 16;
323
324 if (html && isRem) {
325 return parseFloat(getComputedStyle(html).fontSize || String(rootFontSize)) * getNumber(value);
326 }
327
328 return getNumber(value);
329}
330/**
331 * Adds the `distancePx` value to the placement of a Popper.Padding object
332 */
333
334function getComputedPadding(basePlacement, padding, distancePx) {
335 if (padding === void 0) {
336 padding = 5;
337 }
338
339 var freshPaddingObject = {
340 top: 0,
341 right: 0,
342 bottom: 0,
343 left: 0
344 };
345 var keys = Object.keys(freshPaddingObject);
346 return keys.reduce(function (obj, key) {
347 obj[key] = typeof padding === 'number' ? padding : padding[key];
348
349 if (basePlacement === key) {
350 obj[key] = typeof padding === 'number' ? padding + distancePx : padding[basePlacement] + distancePx;
351 }
352
353 return obj;
354 }, freshPaddingObject);
355}
356
357function createMemoryLeakWarning(method) {
358 var txt = method === 'destroy' ? 'n already-' : ' ';
359 return "\n " + method + "() was called on a" + txt + "destroyed instance. This is a no-op but\n indicates a potential memory leak.\n ";
360}
361function clean(value) {
362 var spacesAndTabs = /[ \t]{2,}/g;
363 var lineStartWithSpaces = /^[ \t]*/gm;
364 return value.replace(spacesAndTabs, ' ').replace(lineStartWithSpaces, '').trim();
365}
366
367function getDevMessage(message) {
368 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 ");
369}
370
371function getFormattedMessage(message) {
372 return [getDevMessage(message), // title
373 'color: #00C584; font-size: 1.3em; font-weight: bold;', // message
374 'line-height: 1.5', // footer
375 'color: #a6a095;'];
376}
377/**
378 * Helpful wrapper around `console.warn()`.
379 * TODO: Should we use a cache so it only warns a single time and not spam the
380 * console? (Need to consider hot reloading and invalidation though). Chrome
381 * already batches warnings as well.
382 */
383
384function warnWhen(condition, message) {
385 if (condition) {
386 var _console;
387
388 (_console = console).warn.apply(_console, getFormattedMessage(message));
389 }
390}
391/**
392 * Helpful wrapper around `console.error()`
393 */
394
395function errorWhen(condition, message) {
396 if (condition) {
397 var _console2;
398
399 (_console2 = console).error.apply(_console2, getFormattedMessage(message));
400 }
401}
402/**
403 * Validates the `targets` value passed to `tippy()`
404 */
405
406function validateTargets(targets) {
407 var didPassFalsyValue = !targets;
408 var didPassPlainObject = Object.prototype.toString.call(targets) === '[object Object]' && !targets.addEventListener;
409 errorWhen(didPassFalsyValue, ['tippy() was passed', '`' + String(targets) + '`', 'as its targets (first) argument. Valid types are: String, Element, Element[],', 'or NodeList.'].join(' '));
410 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(' '));
411}
412
413var pluginProps = {
414 animateFill: false,
415 followCursor: false,
416 inlinePositioning: false,
417 sticky: false
418};
419var defaultProps = _extends({
420 allowHTML: true,
421 animation: 'fade',
422 appendTo: function appendTo() {
423 return document.body;
424 },
425 aria: 'describedby',
426 arrow: true,
427 boundary: 'scrollParent',
428 content: '',
429 delay: 0,
430 distance: 10,
431 duration: [300, 250],
432 flip: true,
433 flipBehavior: 'flip',
434 flipOnUpdate: false,
435 hideOnClick: true,
436 ignoreAttributes: false,
437 inertia: false,
438 interactive: false,
439 interactiveBorder: 2,
440 interactiveDebounce: 0,
441 lazy: true,
442 maxWidth: 350,
443 multiple: false,
444 offset: 0,
445 onAfterUpdate: function onAfterUpdate() {},
446 onBeforeUpdate: function onBeforeUpdate() {},
447 onCreate: function onCreate() {},
448 onDestroy: function onDestroy() {},
449 onHidden: function onHidden() {},
450 onHide: function onHide() {},
451 onMount: function onMount() {},
452 onShow: function onShow() {},
453 onShown: function onShown() {},
454 onTrigger: function onTrigger() {},
455 onUntrigger: function onUntrigger() {},
456 placement: 'top',
457 plugins: [],
458 popperOptions: {},
459 role: 'tooltip',
460 showOnCreate: false,
461 theme: '',
462 touch: true,
463 trigger: 'mouseenter focus',
464 triggerTarget: null,
465 updateDuration: 0,
466 zIndex: 9999
467}, pluginProps);
468var defaultKeys = Object.keys(defaultProps);
469/**
470 * If the setProps() method encounters one of these, the popperInstance must be
471 * recreated
472 */
473
474var POPPER_INSTANCE_DEPENDENCIES = ['arrow', 'boundary', 'distance', 'flip', 'flipBehavior', 'flipOnUpdate', 'offset', 'placement', 'popperOptions'];
475/**
476 * Mutates the defaultProps object by setting the props specified
477 */
478
479var setDefaultProps = function setDefaultProps(partialProps) {
480 if (process.env.NODE_ENV !== "production") {
481 validateProps(partialProps, []);
482 }
483
484 var keys = Object.keys(partialProps);
485 keys.forEach(function (key) {
486 defaultProps[key] = partialProps[key];
487 });
488};
489/**
490 * Returns an extended props object including plugin props
491 */
492
493function getExtendedPassedProps(passedProps) {
494 var plugins = passedProps.plugins || [];
495 var pluginProps = plugins.reduce(function (acc, plugin) {
496 var name = plugin.name,
497 defaultValue = plugin.defaultValue;
498
499 if (name) {
500 acc[name] = passedProps[name] !== undefined ? passedProps[name] : defaultValue;
501 }
502
503 return acc;
504 }, {});
505 return _extends({}, passedProps, {}, pluginProps);
506}
507/**
508 * Returns an object of optional props from data-tippy-* attributes
509 */
510
511function getDataAttributeProps(reference, plugins) {
512 var propKeys = plugins ? Object.keys(getExtendedPassedProps(_extends({}, defaultProps, {
513 plugins: plugins
514 }))) : defaultKeys;
515 var props = propKeys.reduce(function (acc, key) {
516 var valueAsString = (reference.getAttribute("data-tippy-" + key) || '').trim();
517
518 if (!valueAsString) {
519 return acc;
520 }
521
522 if (key === 'content') {
523 acc[key] = valueAsString;
524 } else {
525 try {
526 acc[key] = JSON.parse(valueAsString);
527 } catch (e) {
528 acc[key] = valueAsString;
529 }
530 }
531
532 return acc;
533 }, {});
534 return props;
535}
536/**
537 * Evaluates the props object by merging data attributes and disabling
538 * conflicting props where necessary
539 */
540
541function evaluateProps(reference, props) {
542 var out = _extends({}, props, {
543 content: invokeWithArgsOrReturn(props.content, [reference])
544 }, props.ignoreAttributes ? {} : getDataAttributeProps(reference, props.plugins));
545
546 if (out.interactive) {
547 out.aria = null;
548 }
549
550 return out;
551}
552/**
553 * Validates props with the valid `defaultProps` object
554 */
555
556function validateProps(partialProps, plugins) {
557 if (partialProps === void 0) {
558 partialProps = {};
559 }
560
561 if (plugins === void 0) {
562 plugins = [];
563 }
564
565 var keys = Object.keys(partialProps);
566 keys.forEach(function (prop) {
567 var value = partialProps[prop];
568 var didSpecifyPlacementInPopperOptions = prop === 'popperOptions' && value !== null && typeof value === 'object' && hasOwnProperty(value, 'placement');
569 var nonPluginProps = removeProperties(defaultProps, ['animateFill', 'followCursor', 'inlinePositioning', 'sticky']); // These props have custom warnings
570
571 var customWarningProps = ['a11y', 'arrowType', 'showOnInit', 'size', 'target', 'touchHold'];
572 var didPassUnknownProp = !hasOwnProperty(nonPluginProps, prop) && !includes(customWarningProps, prop); // Check if the prop exists in `plugins`
573
574 if (didPassUnknownProp) {
575 didPassUnknownProp = plugins.filter(function (plugin) {
576 return plugin.name === prop;
577 }).length === 0;
578 }
579
580 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(' '));
581 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(' '));
582 warnWhen(prop === 'showOnInit', 'The `showOnInit` prop was renamed to `showOnCreate` in v5.');
583 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(' '));
584 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(' '));
585 warnWhen(prop === 'size', ['The `size` prop was removed in v5. Instead, use a theme that specifies', 'CSS padding and font-size properties.'].join(' '));
586 warnWhen(prop === 'theme' && value === 'google', 'The included theme "google" was renamed to "material" in v5.');
587 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(' '));
588 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(' '));
589 });
590}
591
592var PASSIVE = {
593 passive: true
594};
595var 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>';
596var IOS_CLASS = "tippy-iOS";
597var POPPER_CLASS = "tippy-popper";
598var TOOLTIP_CLASS = "tippy-tooltip";
599var CONTENT_CLASS = "tippy-content";
600var BACKDROP_CLASS = "tippy-backdrop";
601var ARROW_CLASS = "tippy-arrow";
602var SVG_ARROW_CLASS = "tippy-svg-arrow";
603var POPPER_SELECTOR = "." + POPPER_CLASS;
604var TOOLTIP_SELECTOR = "." + TOOLTIP_CLASS;
605var CONTENT_SELECTOR = "." + CONTENT_CLASS;
606var ARROW_SELECTOR = "." + ARROW_CLASS;
607var SVG_ARROW_SELECTOR = "." + SVG_ARROW_CLASS;
608
609var currentInput = {
610 isTouch: false
611};
612var lastMouseMoveTime = 0;
613/**
614 * When a `touchstart` event is fired, it's assumed the user is using touch
615 * input. We'll bind a `mousemove` event listener to listen for mouse input in
616 * the future. This way, the `isTouch` property is fully dynamic and will handle
617 * hybrid devices that use a mix of touch + mouse input.
618 */
619
620function onDocumentTouchStart() {
621 if (currentInput.isTouch) {
622 return;
623 }
624
625 currentInput.isTouch = true;
626
627 if (window.performance) {
628 document.addEventListener('mousemove', onDocumentMouseMove);
629 }
630}
631/**
632 * When two `mousemove` event are fired consecutively within 20ms, it's assumed
633 * the user is using mouse input again. `mousemove` can fire on touch devices as
634 * well, but very rarely that quickly.
635 */
636
637function onDocumentMouseMove() {
638 var now = performance.now();
639
640 if (now - lastMouseMoveTime < 20) {
641 currentInput.isTouch = false;
642 document.removeEventListener('mousemove', onDocumentMouseMove);
643 }
644
645 lastMouseMoveTime = now;
646}
647/**
648 * When an element is in focus and has a tippy, leaving the tab/window and
649 * returning causes it to show again. For mouse users this is unexpected, but
650 * for keyboard use it makes sense.
651 * TODO: find a better technique to solve this problem
652 */
653
654function onWindowBlur() {
655 var activeElement = document.activeElement;
656
657 if (isReferenceElement(activeElement)) {
658 var instance = activeElement._tippy;
659
660 if (activeElement.blur && !instance.state.isVisible) {
661 activeElement.blur();
662 }
663 }
664}
665/**
666 * Adds the needed global event listeners
667 */
668
669function bindGlobalEventListeners() {
670 document.addEventListener('touchstart', onDocumentTouchStart, _extends({}, PASSIVE, {
671 capture: true
672 }));
673 window.addEventListener('blur', onWindowBlur);
674}
675
676var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
677var ua = isBrowser ? navigator.userAgent : '';
678var isIE = /MSIE |Trident\//.test(ua);
679var isIOS = isBrowser && /iPhone|iPad|iPod/.test(navigator.platform);
680function updateIOSClass(isAdd) {
681 var shouldAdd = isAdd && isIOS && currentInput.isTouch;
682 document.body.classList[shouldAdd ? 'add' : 'remove'](IOS_CLASS);
683}
684
685/**
686 * Returns the popper's placement, ignoring shifting (top-start, etc)
687 */
688
689function getBasePlacement(placement) {
690 return placement.split('-')[0];
691}
692/**
693 * Adds `data-inertia` attribute
694 */
695
696function addInertia(tooltip) {
697 tooltip.setAttribute('data-inertia', '');
698}
699/**
700 * Removes `data-inertia` attribute
701 */
702
703function removeInertia(tooltip) {
704 tooltip.removeAttribute('data-inertia');
705}
706/**
707 * Adds interactive-related attributes
708 */
709
710function addInteractive(tooltip) {
711 tooltip.setAttribute('data-interactive', '');
712}
713/**
714 * Removes interactive-related attributes
715 */
716
717function removeInteractive(tooltip) {
718 tooltip.removeAttribute('data-interactive');
719}
720/**
721 * Sets the content of a tooltip
722 */
723
724function setContent(contentEl, props) {
725 if (isElement(props.content)) {
726 setInnerHTML(contentEl, '');
727 contentEl.appendChild(props.content);
728 } else if (typeof props.content !== 'function') {
729 var key = props.allowHTML ? 'innerHTML' : 'textContent';
730 contentEl[key] = props.content;
731 }
732}
733/**
734 * Returns the child elements of a popper element
735 */
736
737function getChildren(popper) {
738 return {
739 tooltip: popper.querySelector(TOOLTIP_SELECTOR),
740 content: popper.querySelector(CONTENT_SELECTOR),
741 arrow: popper.querySelector(ARROW_SELECTOR) || popper.querySelector(SVG_ARROW_SELECTOR)
742 };
743}
744/**
745 * Creates an arrow element and returns it
746 */
747
748function createArrowElement(arrow) {
749 var arrowElement = div();
750
751 if (arrow === true) {
752 arrowElement.className = ARROW_CLASS;
753 } else {
754 arrowElement.className = SVG_ARROW_CLASS;
755
756 if (isElement(arrow)) {
757 arrowElement.appendChild(arrow);
758 } else {
759 setInnerHTML(arrowElement, arrow);
760 }
761 }
762
763 return arrowElement;
764}
765/**
766 * Constructs the popper element and returns it
767 */
768
769function createPopperElement(id, props) {
770 var popper = div();
771 popper.className = POPPER_CLASS;
772 popper.style.position = 'absolute';
773 popper.style.top = '0';
774 popper.style.left = '0';
775 var tooltip = div();
776 tooltip.className = TOOLTIP_CLASS;
777 tooltip.id = "tippy-" + id;
778 tooltip.setAttribute('data-state', 'hidden');
779 tooltip.setAttribute('tabindex', '-1');
780 updateTheme(tooltip, 'add', props.theme);
781 var content = div();
782 content.className = CONTENT_CLASS;
783 content.setAttribute('data-state', 'hidden');
784
785 if (props.interactive) {
786 addInteractive(tooltip);
787 }
788
789 if (props.arrow) {
790 tooltip.setAttribute('data-arrow', '');
791 tooltip.appendChild(createArrowElement(props.arrow));
792 }
793
794 if (props.inertia) {
795 addInertia(tooltip);
796 }
797
798 setContent(content, props);
799 tooltip.appendChild(content);
800 popper.appendChild(tooltip);
801 updatePopperElement(popper, props, props);
802 return popper;
803}
804/**
805 * Updates the popper element based on the new props
806 */
807
808function updatePopperElement(popper, prevProps, nextProps) {
809 var _getChildren = getChildren(popper),
810 tooltip = _getChildren.tooltip,
811 content = _getChildren.content,
812 arrow = _getChildren.arrow;
813
814 popper.style.zIndex = '' + nextProps.zIndex;
815 tooltip.setAttribute('data-animation', nextProps.animation);
816 tooltip.style.maxWidth = appendPxIfNumber(nextProps.maxWidth);
817
818 if (nextProps.role) {
819 tooltip.setAttribute('role', nextProps.role);
820 } else {
821 tooltip.removeAttribute('role');
822 }
823
824 if (prevProps.content !== nextProps.content) {
825 setContent(content, nextProps);
826 } // arrow
827
828
829 if (!prevProps.arrow && nextProps.arrow) {
830 // false to true
831 tooltip.appendChild(createArrowElement(nextProps.arrow));
832 tooltip.setAttribute('data-arrow', '');
833 } else if (prevProps.arrow && !nextProps.arrow) {
834 // true to false
835 tooltip.removeChild(arrow);
836 tooltip.removeAttribute('data-arrow');
837 } else if (prevProps.arrow !== nextProps.arrow) {
838 // true to 'round' or vice-versa
839 tooltip.removeChild(arrow);
840 tooltip.appendChild(createArrowElement(nextProps.arrow));
841 } // interactive
842
843
844 if (!prevProps.interactive && nextProps.interactive) {
845 addInteractive(tooltip);
846 } else if (prevProps.interactive && !nextProps.interactive) {
847 removeInteractive(tooltip);
848 } // inertia
849
850
851 if (!prevProps.inertia && nextProps.inertia) {
852 addInertia(tooltip);
853 } else if (prevProps.inertia && !nextProps.inertia) {
854 removeInertia(tooltip);
855 } // theme
856
857
858 if (prevProps.theme !== nextProps.theme) {
859 updateTheme(tooltip, 'remove', prevProps.theme);
860 updateTheme(tooltip, 'add', nextProps.theme);
861 }
862}
863/**
864 * Add/remove transitionend listener from tooltip
865 */
866
867function updateTransitionEndListener(tooltip, action, listener) {
868 ['transitionend', 'webkitTransitionEnd'].forEach(function (event) {
869 tooltip[action + 'EventListener'](event, listener);
870 });
871}
872/**
873 * Adds/removes theme from tooltip's classList
874 */
875
876function updateTheme(tooltip, action, theme) {
877 splitBySpaces(theme).forEach(function (name) {
878 tooltip.classList[action](name + "-theme");
879 });
880}
881/**
882 * Determines if the mouse cursor is outside of the popper's interactive border
883 * region
884 */
885
886function isCursorOutsideInteractiveBorder(popperTreeData, event) {
887 var clientX = event.clientX,
888 clientY = event.clientY;
889 return popperTreeData.every(function (_ref) {
890 var popperRect = _ref.popperRect,
891 tooltipRect = _ref.tooltipRect,
892 interactiveBorder = _ref.interactiveBorder;
893 // Get min/max bounds of both the popper and tooltip rects due to
894 // `distance` offset
895 var mergedRect = {
896 top: Math.min(popperRect.top, tooltipRect.top),
897 right: Math.max(popperRect.right, tooltipRect.right),
898 bottom: Math.max(popperRect.bottom, tooltipRect.bottom),
899 left: Math.min(popperRect.left, tooltipRect.left)
900 };
901 var exceedsTop = mergedRect.top - clientY > interactiveBorder;
902 var exceedsBottom = clientY - mergedRect.bottom > interactiveBorder;
903 var exceedsLeft = mergedRect.left - clientX > interactiveBorder;
904 var exceedsRight = clientX - mergedRect.right > interactiveBorder;
905 return exceedsTop || exceedsBottom || exceedsLeft || exceedsRight;
906 });
907}
908
909var idCounter = 1;
910var mouseMoveListeners = [];
911/**
912 * Used by `hideAll()`
913 */
914
915var mountedInstances = [];
916/**
917 * Creates and returns a Tippy object. We're using a closure pattern instead of
918 * a class so that the exposed object API is clean without private members
919 * prefixed with `_`.
920 */
921
922function createTippy(reference, passedProps) {
923 var props = evaluateProps(reference, _extends({}, defaultProps, {}, getExtendedPassedProps(passedProps))); // If the reference shouldn't have multiple tippys, return null early
924
925 if (!props.multiple && reference._tippy) {
926 return null;
927 }
928 /* ======================= 🔒 Private members 🔒 ======================= */
929
930
931 var showTimeout;
932 var hideTimeout;
933 var scheduleHideAnimationFrame;
934 var isBeingDestroyed = false;
935 var isVisibleFromClick = false;
936 var didHideDueToDocumentMouseDown = false;
937 var popperUpdates = 0;
938 var lastTriggerEvent;
939 var currentMountCallback;
940 var currentTransitionEndListener;
941 var listeners = [];
942 var debouncedOnMouseMove = debounce(onMouseMove, props.interactiveDebounce);
943 var currentTarget; // Support iframe contexts
944 // Static check that assumes any of the `triggerTarget` or `reference`
945 // nodes will never change documents, even when they are updated
946
947 var doc = getOwnerDocument(props.triggerTarget || reference);
948 /* ======================= 🔑 Public members 🔑 ======================= */
949
950 var id = idCounter++;
951 var popper = createPopperElement(id, props);
952 var popperChildren = getChildren(popper);
953 var popperInstance = null;
954 var plugins = unique(props.plugins); // These two elements are static
955
956 var tooltip = popperChildren.tooltip,
957 content = popperChildren.content;
958 var transitionableElements = [tooltip, content];
959 var state = {
960 // The current real placement (`data-placement` attribute)
961 currentPlacement: null,
962 // Is the instance currently enabled?
963 isEnabled: true,
964 // Is the tippy currently showing and not transitioning out?
965 isVisible: false,
966 // Has the instance been destroyed?
967 isDestroyed: false,
968 // Is the tippy currently mounted to the DOM?
969 isMounted: false,
970 // Has the tippy finished transitioning in?
971 isShown: false
972 };
973 var instance = {
974 // properties
975 id: id,
976 reference: reference,
977 popper: popper,
978 popperChildren: popperChildren,
979 popperInstance: popperInstance,
980 props: props,
981 state: state,
982 plugins: plugins,
983 // methods
984 clearDelayTimeouts: clearDelayTimeouts,
985 setProps: setProps,
986 setContent: setContent,
987 show: show,
988 hide: hide,
989 enable: enable,
990 disable: disable,
991 destroy: destroy
992 };
993 /* ==================== Initial instance mutations =================== */
994
995 reference._tippy = instance;
996 popper._tippy = instance;
997 var pluginsHooks = plugins.map(function (plugin) {
998 return plugin.fn(instance);
999 });
1000 var hadAriaExpandedAttributeOnCreate = reference.hasAttribute('aria-expanded');
1001 addListenersToTriggerTarget();
1002 handleAriaExpandedAttribute();
1003
1004 if (!props.lazy) {
1005 createPopperInstance();
1006 }
1007
1008 invokeHook('onCreate', [instance]);
1009
1010 if (props.showOnCreate) {
1011 scheduleShow();
1012 } // Prevent a tippy with a delay from hiding if the cursor left then returned
1013 // before it started hiding
1014
1015
1016 popper.addEventListener('mouseenter', function () {
1017 if (instance.props.interactive && instance.state.isVisible) {
1018 instance.clearDelayTimeouts();
1019 }
1020 });
1021 popper.addEventListener('mouseleave', function (event) {
1022 if (instance.props.interactive && includes(instance.props.trigger, 'mouseenter')) {
1023 debouncedOnMouseMove(event);
1024 doc.addEventListener('mousemove', debouncedOnMouseMove);
1025 }
1026 });
1027 return instance;
1028 /* ======================= 🔒 Private methods 🔒 ======================= */
1029
1030 function getNormalizedTouchSettings() {
1031 var touch = instance.props.touch;
1032 return Array.isArray(touch) ? touch : [touch, 0];
1033 }
1034
1035 function getIsCustomTouchBehavior() {
1036 return getNormalizedTouchSettings()[0] === 'hold';
1037 }
1038
1039 function getCurrentTarget() {
1040 return currentTarget || reference;
1041 }
1042
1043 function getDelay(isShow) {
1044 // For touch or keyboard input, force `0` delay for UX reasons
1045 // Also if the instance is mounted but not visible (transitioning out),
1046 // ignore delay
1047 if (instance.state.isMounted && !instance.state.isVisible || currentInput.isTouch || lastTriggerEvent && lastTriggerEvent.type === 'focus') {
1048 return 0;
1049 }
1050
1051 return getValueAtIndexOrReturn(instance.props.delay, isShow ? 0 : 1, defaultProps.delay);
1052 }
1053
1054 function invokeHook(hook, args, shouldInvokePropsHook) {
1055 if (shouldInvokePropsHook === void 0) {
1056 shouldInvokePropsHook = true;
1057 }
1058
1059 pluginsHooks.forEach(function (pluginHooks) {
1060 if (hasOwnProperty(pluginHooks, hook)) {
1061 // @ts-ignore
1062 pluginHooks[hook].apply(pluginHooks, args);
1063 }
1064 });
1065
1066 if (shouldInvokePropsHook) {
1067 var _instance$props;
1068
1069 // @ts-ignore
1070 (_instance$props = instance.props)[hook].apply(_instance$props, args);
1071 }
1072 }
1073
1074 function handleAriaDescribedByAttribute() {
1075 var aria = instance.props.aria;
1076
1077 if (!aria) {
1078 return;
1079 }
1080
1081 var attr = "aria-" + aria;
1082 var id = tooltip.id;
1083 var nodes = normalizeToArray(instance.props.triggerTarget || reference);
1084 nodes.forEach(function (node) {
1085 var currentValue = node.getAttribute(attr);
1086
1087 if (instance.state.isVisible) {
1088 node.setAttribute(attr, currentValue ? currentValue + " " + id : id);
1089 } else {
1090 var nextValue = currentValue && currentValue.replace(id, '').trim();
1091
1092 if (nextValue) {
1093 node.setAttribute(attr, nextValue);
1094 } else {
1095 node.removeAttribute(attr);
1096 }
1097 }
1098 });
1099 }
1100
1101 function handleAriaExpandedAttribute() {
1102 // If the user has specified `aria-expanded` on their reference when the
1103 // instance was created, we have to assume they're controlling it externally
1104 // themselves
1105 if (hadAriaExpandedAttributeOnCreate) {
1106 return;
1107 }
1108
1109 var nodes = normalizeToArray(instance.props.triggerTarget || reference);
1110 nodes.forEach(function (node) {
1111 if (instance.props.interactive) {
1112 node.setAttribute('aria-expanded', instance.state.isVisible && node === getCurrentTarget() ? 'true' : 'false');
1113 } else {
1114 node.removeAttribute('aria-expanded');
1115 }
1116 });
1117 }
1118
1119 function cleanupInteractiveMouseListeners() {
1120 doc.body.removeEventListener('mouseleave', scheduleHide);
1121 doc.removeEventListener('mousemove', debouncedOnMouseMove);
1122 mouseMoveListeners = mouseMoveListeners.filter(function (listener) {
1123 return listener !== debouncedOnMouseMove;
1124 });
1125 }
1126
1127 function onDocumentMouseDown(event) {
1128 // Clicked on interactive popper
1129 if (instance.props.interactive && popper.contains(event.target)) {
1130 return;
1131 } // Clicked on the event listeners target
1132
1133
1134 if (getCurrentTarget().contains(event.target)) {
1135 if (currentInput.isTouch) {
1136 return;
1137 }
1138
1139 if (instance.state.isVisible && includes(instance.props.trigger, 'click')) {
1140 return;
1141 }
1142 }
1143
1144 if (instance.props.hideOnClick === true) {
1145 isVisibleFromClick = false;
1146 instance.clearDelayTimeouts();
1147 instance.hide(); // `mousedown` event is fired right before `focus` if pressing the
1148 // currentTarget. This lets a tippy with `focus` trigger know that it
1149 // should not show
1150
1151 didHideDueToDocumentMouseDown = true;
1152 setTimeout(function () {
1153 didHideDueToDocumentMouseDown = false;
1154 }); // The listener gets added in `scheduleShow()`, but this may be hiding it
1155 // before it shows, and hide()'s early bail-out behavior can prevent it
1156 // from being cleaned up
1157
1158 if (!instance.state.isMounted) {
1159 removeDocumentMouseDownListener();
1160 }
1161 }
1162 }
1163
1164 function addDocumentMouseDownListener() {
1165 doc.addEventListener('mousedown', onDocumentMouseDown, true);
1166 }
1167
1168 function removeDocumentMouseDownListener() {
1169 doc.removeEventListener('mousedown', onDocumentMouseDown, true);
1170 }
1171
1172 function onTransitionedOut(duration, callback) {
1173 onTransitionEnd(duration, function () {
1174 if (!instance.state.isVisible && popper.parentNode && popper.parentNode.contains(popper)) {
1175 callback();
1176 }
1177 });
1178 }
1179
1180 function onTransitionedIn(duration, callback) {
1181 onTransitionEnd(duration, callback);
1182 }
1183
1184 function onTransitionEnd(duration, callback) {
1185 function listener(event) {
1186 if (event.target === tooltip) {
1187 updateTransitionEndListener(tooltip, 'remove', listener);
1188 callback();
1189 }
1190 } // Make callback synchronous if duration is 0
1191 // `transitionend` won't fire otherwise
1192
1193
1194 if (duration === 0) {
1195 return callback();
1196 }
1197
1198 updateTransitionEndListener(tooltip, 'remove', currentTransitionEndListener);
1199 updateTransitionEndListener(tooltip, 'add', listener);
1200 currentTransitionEndListener = listener;
1201 }
1202
1203 function on(eventType, handler, options) {
1204 if (options === void 0) {
1205 options = false;
1206 }
1207
1208 var nodes = normalizeToArray(instance.props.triggerTarget || reference);
1209 nodes.forEach(function (node) {
1210 node.addEventListener(eventType, handler, options);
1211 listeners.push({
1212 node: node,
1213 eventType: eventType,
1214 handler: handler,
1215 options: options
1216 });
1217 });
1218 }
1219
1220 function addListenersToTriggerTarget() {
1221 if (getIsCustomTouchBehavior()) {
1222 on('touchstart', onTrigger, PASSIVE);
1223 on('touchend', onMouseLeave, PASSIVE);
1224 }
1225
1226 splitBySpaces(instance.props.trigger).forEach(function (eventType) {
1227 if (eventType === 'manual') {
1228 return;
1229 }
1230
1231 on(eventType, onTrigger);
1232
1233 switch (eventType) {
1234 case 'mouseenter':
1235 on('mouseleave', onMouseLeave);
1236 break;
1237
1238 case 'focus':
1239 on(isIE ? 'focusout' : 'blur', onBlurOrFocusOut);
1240 break;
1241
1242 case 'focusin':
1243 on('focusout', onBlurOrFocusOut);
1244 break;
1245 }
1246 });
1247 }
1248
1249 function removeListenersFromTriggerTarget() {
1250 listeners.forEach(function (_ref) {
1251 var node = _ref.node,
1252 eventType = _ref.eventType,
1253 handler = _ref.handler,
1254 options = _ref.options;
1255 node.removeEventListener(eventType, handler, options);
1256 });
1257 listeners = [];
1258 }
1259
1260 function onTrigger(event) {
1261 var shouldScheduleClickHide = false;
1262
1263 if (!instance.state.isEnabled || isEventListenerStopped(event) || didHideDueToDocumentMouseDown) {
1264 return;
1265 }
1266
1267 lastTriggerEvent = event;
1268 currentTarget = event.currentTarget;
1269 handleAriaExpandedAttribute();
1270
1271 if (!instance.state.isVisible && isMouseEvent(event)) {
1272 // If scrolling, `mouseenter` events can be fired if the cursor lands
1273 // over a new target, but `mousemove` events don't get fired. This
1274 // causes interactive tooltips to get stuck open until the cursor is
1275 // moved
1276 mouseMoveListeners.forEach(function (listener) {
1277 return listener(event);
1278 });
1279 } // Toggle show/hide when clicking click-triggered tooltips
1280
1281
1282 if (event.type === 'click' && (!includes(instance.props.trigger, 'mouseenter') || isVisibleFromClick) && instance.props.hideOnClick !== false && instance.state.isVisible) {
1283 shouldScheduleClickHide = true;
1284 } else {
1285 var _getNormalizedTouchSe = getNormalizedTouchSettings(),
1286 value = _getNormalizedTouchSe[0],
1287 duration = _getNormalizedTouchSe[1];
1288
1289 if (currentInput.isTouch && value === 'hold' && duration) {
1290 // We can hijack the show timeout here, it will be cleared by
1291 // `scheduleHide()` when necessary
1292 showTimeout = setTimeout(function () {
1293 scheduleShow(event);
1294 }, duration);
1295 } else {
1296 scheduleShow(event);
1297 }
1298 }
1299
1300 if (event.type === 'click') {
1301 isVisibleFromClick = !shouldScheduleClickHide;
1302 }
1303
1304 if (shouldScheduleClickHide) {
1305 scheduleHide(event);
1306 }
1307 }
1308
1309 function onMouseMove(event) {
1310 var isCursorOverReferenceOrPopper = closestCallback(event.target, function (el) {
1311 return el === reference || el === popper;
1312 });
1313
1314 if (event.type === 'mousemove' && isCursorOverReferenceOrPopper) {
1315 return;
1316 }
1317
1318 var popperTreeData = arrayFrom(popper.querySelectorAll(POPPER_SELECTOR)).concat(popper).map(function (popper) {
1319 var instance = popper._tippy;
1320 var tooltip = instance.popperChildren.tooltip;
1321 var interactiveBorder = instance.props.interactiveBorder;
1322 return {
1323 popperRect: popper.getBoundingClientRect(),
1324 tooltipRect: tooltip.getBoundingClientRect(),
1325 interactiveBorder: interactiveBorder
1326 };
1327 });
1328
1329 if (isCursorOutsideInteractiveBorder(popperTreeData, event)) {
1330 cleanupInteractiveMouseListeners();
1331 scheduleHide(event);
1332 }
1333 }
1334
1335 function onMouseLeave(event) {
1336 if (isEventListenerStopped(event)) {
1337 return;
1338 }
1339
1340 if (includes(instance.props.trigger, 'click') && isVisibleFromClick) {
1341 return;
1342 }
1343
1344 if (instance.props.interactive) {
1345 doc.body.addEventListener('mouseleave', scheduleHide);
1346 doc.addEventListener('mousemove', debouncedOnMouseMove);
1347 pushIfUnique(mouseMoveListeners, debouncedOnMouseMove);
1348 debouncedOnMouseMove(event);
1349 return;
1350 }
1351
1352 scheduleHide(event);
1353 }
1354
1355 function onBlurOrFocusOut(event) {
1356 if (!includes(instance.props.trigger, 'focusin') && event.target !== getCurrentTarget()) {
1357 return;
1358 } // If focus was moved to within the popper
1359
1360
1361 if (instance.props.interactive && event.relatedTarget && popper.contains(event.relatedTarget)) {
1362 return;
1363 }
1364
1365 scheduleHide(event);
1366 }
1367
1368 function isEventListenerStopped(event) {
1369 var supportsTouch = 'ontouchstart' in window;
1370 var isTouchEvent = includes(event.type, 'touch');
1371 var isCustomTouch = getIsCustomTouchBehavior();
1372 return supportsTouch && currentInput.isTouch && isCustomTouch && !isTouchEvent || currentInput.isTouch && !isCustomTouch && isTouchEvent;
1373 }
1374
1375 function createPopperInstance() {
1376 var popperOptions = instance.props.popperOptions;
1377 var arrow = instance.popperChildren.arrow;
1378 var flipModifier = getModifier(popperOptions, 'flip');
1379 var preventOverflowModifier = getModifier(popperOptions, 'preventOverflow');
1380 var distancePx;
1381
1382 function applyMutations(data) {
1383 var prevPlacement = instance.state.currentPlacement;
1384 instance.state.currentPlacement = data.placement;
1385
1386 if (instance.props.flip && !instance.props.flipOnUpdate) {
1387 if (data.flipped) {
1388 instance.popperInstance.options.placement = data.placement;
1389 }
1390
1391 setModifierValue(instance.popperInstance.modifiers, 'flip', 'enabled', false);
1392 }
1393
1394 tooltip.setAttribute('data-placement', data.placement);
1395
1396 if (data.attributes['x-out-of-boundaries'] !== false) {
1397 tooltip.setAttribute('data-out-of-boundaries', '');
1398 } else {
1399 tooltip.removeAttribute('data-out-of-boundaries');
1400 }
1401
1402 var basePlacement = getBasePlacement(data.placement);
1403 var isVerticalPlacement = includes(['top', 'bottom'], basePlacement);
1404 var isSecondaryPlacement = includes(['bottom', 'right'], basePlacement); // Apply `distance` prop
1405
1406 tooltip.style.top = '0';
1407 tooltip.style.left = '0';
1408 tooltip.style[isVerticalPlacement ? 'top' : 'left'] = (isSecondaryPlacement ? 1 : -1) * distancePx + 'px'; // Careful not to cause an infinite loop here
1409 // Fixes https://github.com/FezVrasta/popper.js/issues/784
1410
1411 if (prevPlacement && prevPlacement !== data.placement) {
1412 instance.popperInstance.update();
1413 }
1414 }
1415
1416 var config = _extends({
1417 eventsEnabled: false,
1418 placement: instance.props.placement
1419 }, popperOptions, {
1420 modifiers: _extends({}, popperOptions && popperOptions.modifiers, {
1421 // We can't use `padding` on the popper el because of these bugs when
1422 // flipping from a vertical to horizontal placement or vice-versa,
1423 // there is severe flickering.
1424 // https://github.com/FezVrasta/popper.js/issues/720
1425 // This workaround increases bundle size by 250B minzip unfortunately,
1426 // due to need to custom compute the distance (since Popper rect does
1427 // not get affected by the inner tooltip's distance offset)
1428 tippyDistance: {
1429 enabled: true,
1430 order: 0,
1431 fn: function fn(data) {
1432 // `html` fontSize may change while `popperInstance` is alive
1433 // e.g. on resize in media queries
1434 distancePx = getUnitsInPx(doc, instance.props.distance);
1435 var basePlacement = getBasePlacement(data.placement);
1436 var computedPreventOverflowPadding = getComputedPadding(basePlacement, preventOverflowModifier && preventOverflowModifier.padding, distancePx);
1437 var computedFlipPadding = getComputedPadding(basePlacement, flipModifier && flipModifier.padding, distancePx);
1438 var instanceModifiers = instance.popperInstance.modifiers;
1439 setModifierValue(instanceModifiers, 'preventOverflow', 'padding', computedPreventOverflowPadding);
1440 setModifierValue(instanceModifiers, 'flip', 'padding', computedFlipPadding);
1441 return data;
1442 }
1443 },
1444 preventOverflow: _extends({
1445 boundariesElement: instance.props.boundary
1446 }, preventOverflowModifier),
1447 flip: _extends({
1448 enabled: instance.props.flip,
1449 behavior: instance.props.flipBehavior
1450 }, flipModifier),
1451 arrow: _extends({
1452 element: arrow,
1453 enabled: !!arrow
1454 }, getModifier(popperOptions, 'arrow')),
1455 offset: _extends({
1456 offset: instance.props.offset
1457 }, getModifier(popperOptions, 'offset'))
1458 }),
1459 onCreate: function onCreate(data) {
1460 applyMutations(data);
1461 preserveInvocation(popperOptions && popperOptions.onCreate, config.onCreate, [data]);
1462 runMountCallback();
1463 },
1464 onUpdate: function onUpdate(data) {
1465 applyMutations(data);
1466 preserveInvocation(popperOptions && popperOptions.onUpdate, config.onUpdate, [data]);
1467 runMountCallback();
1468 }
1469 });
1470
1471 instance.popperInstance = new Popper(reference, popper, config);
1472 }
1473
1474 function runMountCallback() {
1475 // Only invoke currentMountCallback after 2 updates
1476 // This fixes some bugs in Popper.js (TODO: aim for only 1 update)
1477 if (popperUpdates === 0) {
1478 popperUpdates++; // 1
1479
1480 instance.popperInstance.update();
1481 } else if (currentMountCallback && popperUpdates === 1) {
1482 popperUpdates++; // 2
1483
1484 reflow(popper);
1485 currentMountCallback();
1486 }
1487 }
1488
1489 function mount() {
1490 // The mounting callback (`currentMountCallback`) is only run due to a
1491 // popperInstance update/create
1492 popperUpdates = 0;
1493 var appendTo = instance.props.appendTo;
1494 var parentNode; // By default, we'll append the popper to the triggerTargets's parentNode so
1495 // it's directly after the reference element so the elements inside the
1496 // tippy can be tabbed to
1497 // If there are clipping issues, the user can specify a different appendTo
1498 // and ensure focus management is handled correctly manually
1499
1500 var node = getCurrentTarget();
1501
1502 if (instance.props.interactive && appendTo === defaultProps.appendTo || appendTo === 'parent') {
1503 parentNode = node.parentNode;
1504 } else {
1505 parentNode = invokeWithArgsOrReturn(appendTo, [node]);
1506 } // The popper element needs to exist on the DOM before its position can be
1507 // updated as Popper.js needs to read its dimensions
1508
1509
1510 if (!parentNode.contains(popper)) {
1511 parentNode.appendChild(popper);
1512 }
1513
1514 if (process.env.NODE_ENV !== "production") {
1515 // Accessibility check
1516 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(' '));
1517 }
1518
1519 setModifierValue(instance.popperInstance.modifiers, 'flip', 'enabled', instance.props.flip);
1520 instance.popperInstance.enableEventListeners(); // Mounting callback invoked in `onUpdate`
1521
1522 instance.popperInstance.update();
1523 }
1524
1525 function scheduleShow(event) {
1526 instance.clearDelayTimeouts();
1527
1528 if (!instance.popperInstance) {
1529 createPopperInstance();
1530 }
1531
1532 if (event) {
1533 invokeHook('onTrigger', [instance, event]);
1534 }
1535
1536 addDocumentMouseDownListener();
1537 var delay = getDelay(true);
1538
1539 if (delay) {
1540 showTimeout = setTimeout(function () {
1541 instance.show();
1542 }, delay);
1543 } else {
1544 instance.show();
1545 }
1546 }
1547
1548 function scheduleHide(event) {
1549 instance.clearDelayTimeouts();
1550 invokeHook('onUntrigger', [instance, event]);
1551
1552 if (!instance.state.isVisible) {
1553 removeDocumentMouseDownListener();
1554 return;
1555 } // For interactive tippies, scheduleHide is added to a document.body handler
1556 // from onMouseLeave so must intercept scheduled hides from mousemove/leave
1557 // events when trigger contains mouseenter and click, and the tip is
1558 // currently shown as a result of a click.
1559
1560
1561 if (includes(instance.props.trigger, 'mouseenter') && includes(instance.props.trigger, 'click') && includes(['mouseleave', 'mousemove'], event.type) && isVisibleFromClick) {
1562 return;
1563 }
1564
1565 var delay = getDelay(false);
1566
1567 if (delay) {
1568 hideTimeout = setTimeout(function () {
1569 if (instance.state.isVisible) {
1570 instance.hide();
1571 }
1572 }, delay);
1573 } else {
1574 // Fixes a `transitionend` problem when it fires 1 frame too
1575 // late sometimes, we don't want hide() to be called.
1576 scheduleHideAnimationFrame = requestAnimationFrame(function () {
1577 instance.hide();
1578 });
1579 }
1580 }
1581 /* ======================= 🔑 Public methods 🔑 ======================= */
1582
1583
1584 function enable() {
1585 instance.state.isEnabled = true;
1586 }
1587
1588 function disable() {
1589 // Disabling the instance should also hide it
1590 // https://github.com/atomiks/tippy.js-react/issues/106
1591 instance.hide();
1592 instance.state.isEnabled = false;
1593 }
1594
1595 function clearDelayTimeouts() {
1596 clearTimeout(showTimeout);
1597 clearTimeout(hideTimeout);
1598 cancelAnimationFrame(scheduleHideAnimationFrame);
1599 }
1600
1601 function setProps(partialProps) {
1602 if (process.env.NODE_ENV !== "production") {
1603 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('setProps'));
1604 }
1605
1606 if (instance.state.isDestroyed) {
1607 return;
1608 }
1609
1610 if (process.env.NODE_ENV !== "production") {
1611 validateProps(partialProps, plugins);
1612 warnWhen(partialProps.plugins ? partialProps.plugins.length !== plugins.length || plugins.some(function (p, i) {
1613 if (partialProps.plugins && partialProps.plugins[i]) {
1614 return p !== partialProps.plugins[i];
1615 } else {
1616 return true;
1617 }
1618 }) : false, "Cannot update plugins");
1619 }
1620
1621 invokeHook('onBeforeUpdate', [instance, partialProps]);
1622 removeListenersFromTriggerTarget();
1623 var prevProps = instance.props;
1624 var nextProps = evaluateProps(reference, _extends({}, instance.props, {}, partialProps, {
1625 ignoreAttributes: true
1626 }));
1627 nextProps.ignoreAttributes = useIfDefined(partialProps.ignoreAttributes, prevProps.ignoreAttributes);
1628 instance.props = nextProps;
1629 addListenersToTriggerTarget();
1630
1631 if (prevProps.interactiveDebounce !== nextProps.interactiveDebounce) {
1632 cleanupInteractiveMouseListeners();
1633 debouncedOnMouseMove = debounce(onMouseMove, nextProps.interactiveDebounce);
1634 }
1635
1636 updatePopperElement(popper, prevProps, nextProps);
1637 instance.popperChildren = getChildren(popper); // Ensure stale aria-expanded attributes are removed
1638
1639 if (prevProps.triggerTarget && !nextProps.triggerTarget) {
1640 normalizeToArray(prevProps.triggerTarget).forEach(function (node) {
1641 node.removeAttribute('aria-expanded');
1642 });
1643 } else if (nextProps.triggerTarget) {
1644 reference.removeAttribute('aria-expanded');
1645 }
1646
1647 handleAriaExpandedAttribute();
1648
1649 if (instance.popperInstance) {
1650 if (POPPER_INSTANCE_DEPENDENCIES.some(function (prop) {
1651 return hasOwnProperty(partialProps, prop) && partialProps[prop] !== prevProps[prop];
1652 })) {
1653 var currentReference = instance.popperInstance.reference;
1654 instance.popperInstance.destroy();
1655 createPopperInstance();
1656 instance.popperInstance.reference = currentReference;
1657
1658 if (instance.state.isVisible) {
1659 instance.popperInstance.enableEventListeners();
1660 }
1661 } else {
1662 instance.popperInstance.update();
1663 }
1664 }
1665
1666 invokeHook('onAfterUpdate', [instance, partialProps]);
1667 }
1668
1669 function setContent(content) {
1670 instance.setProps({
1671 content: content
1672 });
1673 }
1674
1675 function show(duration) {
1676 if (duration === void 0) {
1677 duration = getValueAtIndexOrReturn(instance.props.duration, 0, defaultProps.duration);
1678 }
1679
1680 if (process.env.NODE_ENV !== "production") {
1681 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('show'));
1682 } // Early bail-out
1683
1684
1685 var isAlreadyVisible = instance.state.isVisible;
1686 var isDestroyed = instance.state.isDestroyed;
1687 var isDisabled = !instance.state.isEnabled;
1688 var isTouchAndTouchDisabled = currentInput.isTouch && !instance.props.touch;
1689
1690 if (isAlreadyVisible || isDestroyed || isDisabled || isTouchAndTouchDisabled) {
1691 return;
1692 } // Normalize `disabled` behavior across browsers.
1693 // Firefox allows events on disabled elements, but Chrome doesn't.
1694 // Using a wrapper element (i.e. <span>) is recommended.
1695
1696
1697 if (getCurrentTarget().hasAttribute('disabled')) {
1698 return;
1699 }
1700
1701 if (!instance.popperInstance) {
1702 createPopperInstance();
1703 }
1704
1705 invokeHook('onShow', [instance], false);
1706
1707 if (instance.props.onShow(instance) === false) {
1708 return;
1709 }
1710
1711 addDocumentMouseDownListener();
1712 popper.style.visibility = 'visible';
1713 instance.state.isVisible = true; // Prevent a transition of the popper from its previous position and of the
1714 // elements at a different placement
1715 // Check if the tippy was fully unmounted before `show()` was called, to
1716 // allow for smooth transition for `createSingleton()`
1717
1718 if (!instance.state.isMounted) {
1719 setTransitionDuration(transitionableElements.concat(popper), 0);
1720 }
1721
1722 currentMountCallback = function currentMountCallback() {
1723 if (!instance.state.isVisible) {
1724 return;
1725 }
1726
1727 setTransitionDuration([popper], instance.props.updateDuration);
1728 setTransitionDuration(transitionableElements, duration);
1729 setVisibilityState(transitionableElements, 'visible');
1730 handleAriaDescribedByAttribute();
1731 handleAriaExpandedAttribute();
1732 pushIfUnique(mountedInstances, instance);
1733 updateIOSClass(true);
1734 instance.state.isMounted = true;
1735 invokeHook('onMount', [instance]);
1736 onTransitionedIn(duration, function () {
1737 instance.state.isShown = true;
1738 invokeHook('onShown', [instance]);
1739 });
1740 };
1741
1742 mount();
1743 }
1744
1745 function hide(duration) {
1746 if (duration === void 0) {
1747 duration = getValueAtIndexOrReturn(instance.props.duration, 1, defaultProps.duration);
1748 }
1749
1750 if (process.env.NODE_ENV !== "production") {
1751 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('hide'));
1752 } // Early bail-out
1753
1754
1755 var isAlreadyHidden = !instance.state.isVisible && !isBeingDestroyed;
1756 var isDestroyed = instance.state.isDestroyed;
1757 var isDisabled = !instance.state.isEnabled && !isBeingDestroyed;
1758
1759 if (isAlreadyHidden || isDestroyed || isDisabled) {
1760 return;
1761 }
1762
1763 invokeHook('onHide', [instance], false);
1764
1765 if (instance.props.onHide(instance) === false && !isBeingDestroyed) {
1766 return;
1767 }
1768
1769 removeDocumentMouseDownListener();
1770 popper.style.visibility = 'hidden';
1771 instance.state.isVisible = false;
1772 instance.state.isShown = false;
1773 setTransitionDuration(transitionableElements, duration);
1774 setVisibilityState(transitionableElements, 'hidden');
1775 handleAriaDescribedByAttribute();
1776 handleAriaExpandedAttribute();
1777 onTransitionedOut(duration, function () {
1778 instance.popperInstance.disableEventListeners();
1779 instance.popperInstance.options.placement = instance.props.placement;
1780 popper.parentNode.removeChild(popper);
1781 mountedInstances = mountedInstances.filter(function (i) {
1782 return i !== instance;
1783 });
1784
1785 if (mountedInstances.length === 0) {
1786 updateIOSClass(false);
1787 }
1788
1789 instance.state.isMounted = false;
1790 invokeHook('onHidden', [instance]);
1791 });
1792 }
1793
1794 function destroy() {
1795 if (process.env.NODE_ENV !== "production") {
1796 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('destroy'));
1797 }
1798
1799 if (instance.state.isDestroyed) {
1800 return;
1801 }
1802
1803 isBeingDestroyed = true;
1804 instance.clearDelayTimeouts();
1805 instance.hide(0);
1806 removeListenersFromTriggerTarget();
1807 delete reference._tippy;
1808
1809 if (instance.popperInstance) {
1810 instance.popperInstance.destroy();
1811 }
1812
1813 isBeingDestroyed = false;
1814 instance.state.isDestroyed = true;
1815 invokeHook('onDestroy', [instance]);
1816 }
1817}
1818
1819function tippy(targets, optionalProps,
1820/** @deprecated use Props.plugins */
1821plugins) {
1822 if (optionalProps === void 0) {
1823 optionalProps = {};
1824 }
1825
1826 if (plugins === void 0) {
1827 plugins = [];
1828 }
1829
1830 plugins = defaultProps.plugins.concat(optionalProps.plugins || plugins);
1831
1832 if (process.env.NODE_ENV !== "production") {
1833 validateTargets(targets);
1834 validateProps(optionalProps, plugins);
1835 }
1836
1837 bindGlobalEventListeners();
1838
1839 var passedProps = _extends({}, optionalProps, {
1840 plugins: plugins
1841 });
1842
1843 var elements = getArrayOfElements(targets);
1844
1845 if (process.env.NODE_ENV !== "production") {
1846 var isSingleContentElement = isElement(passedProps.content);
1847 var isMoreThanOneReferenceElement = elements.length > 1;
1848 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(' '));
1849 }
1850
1851 var instances = elements.reduce(function (acc, reference) {
1852 var instance = reference && createTippy(reference, passedProps);
1853
1854 if (instance) {
1855 acc.push(instance);
1856 }
1857
1858 return acc;
1859 }, []);
1860 return isElement(targets) ? instances[0] : instances;
1861}
1862
1863tippy.version = version;
1864tippy.defaultProps = defaultProps;
1865tippy.setDefaultProps = setDefaultProps;
1866tippy.currentInput = currentInput;
1867/**
1868 * Hides all visible poppers on the document
1869 */
1870
1871var hideAll = function hideAll(_temp) {
1872 var _ref = _temp === void 0 ? {} : _temp,
1873 excludedReferenceOrInstance = _ref.exclude,
1874 duration = _ref.duration;
1875
1876 mountedInstances.forEach(function (instance) {
1877 var isExcluded = false;
1878
1879 if (excludedReferenceOrInstance) {
1880 isExcluded = isReferenceElement(excludedReferenceOrInstance) ? instance.reference === excludedReferenceOrInstance : instance.popper === excludedReferenceOrInstance.popper;
1881 }
1882
1883 if (!isExcluded) {
1884 instance.hide(duration);
1885 }
1886 });
1887};
1888/**
1889 * Returns a proxy wrapper function that passes the plugins
1890 * @deprecated use tippy.setDefaultProps({plugins: [...]});
1891 */
1892
1893function createTippyWithPlugins(outerPlugins) {
1894 if (process.env.NODE_ENV !== "production") {
1895 warnWhen(true, ['createTippyWithPlugins([...]) has been deprecated.', '\n\n', 'Use tippy.setDefaultProps({plugins: [...]}) instead.'].join(' '));
1896 }
1897
1898 var tippyPluginsWrapper = function tippyPluginsWrapper(targets, optionalProps, innerPlugins) {
1899 if (optionalProps === void 0) {
1900 optionalProps = {};
1901 }
1902
1903 if (innerPlugins === void 0) {
1904 innerPlugins = [];
1905 }
1906
1907 innerPlugins = optionalProps.plugins || innerPlugins;
1908 return tippy(targets, _extends({}, optionalProps, {
1909 plugins: [].concat(outerPlugins, innerPlugins)
1910 }));
1911 };
1912
1913 tippyPluginsWrapper.version = version;
1914 tippyPluginsWrapper.defaultProps = defaultProps;
1915 tippyPluginsWrapper.setDefaultProps = setDefaultProps;
1916 tippyPluginsWrapper.currentInput = currentInput; // @ts-ignore
1917
1918 return tippyPluginsWrapper;
1919}
1920
1921exports.BACKDROP_CLASS = BACKDROP_CLASS;
1922exports.ROUND_ARROW = ROUND_ARROW;
1923exports._extends = _extends;
1924exports.arrayFrom = arrayFrom;
1925exports.closestCallback = closestCallback;
1926exports.createTippyWithPlugins = createTippyWithPlugins;
1927exports.currentInput = currentInput;
1928exports.defaultProps = defaultProps;
1929exports.div = div;
1930exports.errorWhen = errorWhen;
1931exports.getBasePlacement = getBasePlacement;
1932exports.getOwnerDocument = getOwnerDocument;
1933exports.hideAll = hideAll;
1934exports.includes = includes;
1935exports.isBrowser = isBrowser;
1936exports.isMouseEvent = isMouseEvent;
1937exports.normalizeToArray = normalizeToArray;
1938exports.removeProperties = removeProperties;
1939exports.setVisibilityState = setVisibilityState;
1940exports.tippy = tippy;
1941exports.useIfDefined = useIfDefined;
1942exports.warnWhen = warnWhen;
1943//# sourceMappingURL=tippy.chunk.cjs.js.map