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