UNPKG

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