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 || 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
1604 // Do not hide when using browser autofill 1605 if ( event.target === document.body ) { 1606 1607 return; 1608 } 1609 1610 instance.clearDelayTimeouts(); 1611 invokeHook('onUntrigger', [instance, event]); 1612 1613 if (!instance.state.isVisible) { 1614 removeDocumentMouseDownListener(); 1615 return; 1616 } // For interactive tippies, scheduleHide is added to a document.body handler 1617 // from onMouseLeave so must intercept scheduled hides from mousemove/leave 1618 // events when trigger contains mouseenter and click, and the tip is 1619 // currently shown as a result of a click. 1620 1621 1622 if (includes(instance.props.trigger, 'mouseenter') && includes(instance.props.trigger, 'click') && includes(['mouseleave', 'mousemove'], event.type) && isVisibleFromClick) { 1623 return; 1624 } 1625 1626 var delay = getDelay(false); 1627 1628 if (delay) { 1629 hideTimeout = setTimeout(function () { 1630 if (instance.state.isVisible) { 1631 instance.hide(); 1632 } 1633 }, delay); 1634 } else { 1635 // Fixes a `transitionend` problem when it fires 1 frame too 1636 // late sometimes, we don't want hide() to be called. 1637 scheduleHideAnimationFrame = requestAnimationFrame(function () { 1638 instance.hide(); 1639 }); 1640 } 1641 } 1642 /* ======================= 🔑 Public methods 🔑 ======================= */ 1643 1644 1645 function enable() { 1646 instance.state.isEnabled = true; 1647 } 1648 1649 function disable() { 1650 // Disabling the instance should also hide it 1651 // https://github.com/atomiks/tippy.js-react/issues/106 1652 instance.hide(); 1653 instance.state.isEnabled = false; 1654 } 1655 1656 function clearDelayTimeouts() { 1657 clearTimeout(showTimeout); 1658 clearTimeout(hideTimeout); 1659 cancelAnimationFrame(scheduleHideAnimationFrame); 1660 } 1661 1662 function setProps(partialProps) { 1663 { 1664 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('setProps')); 1665 } 1666 1667 if (instance.state.isDestroyed) { 1668 return; 1669 } 1670 1671 { 1672 validateProps(partialProps, plugins); 1673 warnWhen(partialProps.plugins ? partialProps.plugins.length !== plugins.length || plugins.some(function (p, i) { 1674 if (partialProps.plugins && partialProps.plugins[i]) { 1675 return p !== partialProps.plugins[i]; 1676 } else { 1677 return true; 1678 } 1679 }) : false, "Cannot update plugins"); 1680 } 1681 1682 invokeHook('onBeforeUpdate', [instance, partialProps]); 1683 removeListenersFromTriggerTarget(); 1684 var prevProps = instance.props; 1685 var nextProps = evaluateProps(reference, _extends({}, instance.props, {}, partialProps, { 1686 ignoreAttributes: true 1687 })); 1688 nextProps.ignoreAttributes = useIfDefined(partialProps.ignoreAttributes, prevProps.ignoreAttributes); 1689 instance.props = nextProps; 1690 addListenersToTriggerTarget(); 1691 1692 if (prevProps.interactiveDebounce !== nextProps.interactiveDebounce) { 1693 cleanupInteractiveMouseListeners(); 1694 debouncedOnMouseMove = debounce(onMouseMove, nextProps.interactiveDebounce); 1695 } 1696 1697 updatePopperElement(popper, prevProps, nextProps); 1698 instance.popperChildren = getChildren(popper); // Ensure stale aria-expanded attributes are removed 1699 1700 if (prevProps.triggerTarget && !nextProps.triggerTarget) { 1701 normalizeToArray(prevProps.triggerTarget).forEach(function (node) { 1702 node.removeAttribute('aria-expanded'); 1703 }); 1704 } else if (nextProps.triggerTarget) { 1705 reference.removeAttribute('aria-expanded'); 1706 } 1707 1708 handleAriaExpandedAttribute(); 1709 1710 if (instance.popperInstance) { 1711 if (POPPER_INSTANCE_DEPENDENCIES.some(function (prop) { 1712 return hasOwnProperty(partialProps, prop) && partialProps[prop] !== prevProps[prop]; 1713 })) { 1714 var currentReference = instance.popperInstance.reference; 1715 instance.popperInstance.destroy(); 1716 createPopperInstance(); 1717 instance.popperInstance.reference = currentReference; 1718 1719 if (instance.state.isVisible) { 1720 instance.popperInstance.enableEventListeners(); 1721 } 1722 } else {
1723 instance.popperInstance.update(); 1724 } 1725 } 1726 1727 invokeHook('onAfterUpdate', [instance, partialProps]); 1728 } 1729 1730 function setContent(content) { 1731 instance.setProps({ 1732 content: content 1733 }); 1734 } 1735 1736 function show(duration) { 1737 if (duration === void 0) { 1738 duration = getValueAtIndexOrReturn(instance.props.duration, 0, defaultProps.duration); 1739 } 1740 1741 { 1742 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('show')); 1743 } // Early bail-out 1744 1745 1746 var isAlreadyVisible = instance.state.isVisible; 1747 var isDestroyed = instance.state.isDestroyed; 1748 var isDisabled = !instance.state.isEnabled; 1749 var isTouchAndTouchDisabled = currentInput.isTouch && !instance.props.touch; 1750 1751 if (isAlreadyVisible || isDestroyed || isDisabled || isTouchAndTouchDisabled) { 1752 return; 1753 } // Normalize `disabled` behavior across browsers. 1754 // Firefox allows events on disabled elements, but Chrome doesn't. 1755 // Using a wrapper element (i.e. <span>) is recommended. 1756 1757 1758 if (getCurrentTarget().hasAttribute('disabled')) { 1759 return; 1760 } 1761 1762 if (!instance.popperInstance) { 1763 createPopperInstance(); 1764 } 1765 1766 invokeHook('onShow', [instance], false); 1767 1768 if (instance.props.onShow(instance) === false) { 1769 return; 1770 } 1771 1772 addDocumentMouseDownListener(); 1773 popper.style.visibility = 'visible'; 1774 instance.state.isVisible = true; // Prevent a transition of the popper from its previous position and of the 1775 // elements at a different placement 1776 // Check if the tippy was fully unmounted before `show()` was called, to 1777 // allow for smooth transition for `createSingleton()` 1778 1779 if (!instance.state.isMounted) { 1780 setTransitionDuration(transitionableElements.concat(popper), 0); 1781 } 1782 1783 currentMountCallback = function currentMountCallback() { 1784 if (!instance.state.isVisible) { 1785 return; 1786 } 1787 1788 setTransitionDuration([popper], instance.props.updateDuration); 1789 setTransitionDuration(transitionableElements, duration); 1790 setVisibilityState(transitionableElements, 'visible'); 1791 handleAriaDescribedByAttribute(); 1792 handleAriaExpandedAttribute(); 1793 pushIfUnique(mountedInstances, instance); 1794 updateIOSClass(true); 1795 instance.state.isMounted = true; 1796 invokeHook('onMount', [instance]); 1797 onTransitionedIn(duration, function () { 1798 instance.state.isShown = true; 1799 invokeHook('onShown', [instance]); 1800 }); 1801 }; 1802 1803 mount(); 1804 } 1805 1806 function hide(duration) { 1807 if (duration === void 0) { 1808 duration = getValueAtIndexOrReturn(instance.props.duration, 1, defaultProps.duration); 1809 } 1810 1811 { 1812 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('hide')); 1813 } // Early bail-out 1814 1815 1816 var isAlreadyHidden = !instance.state.isVisible && !isBeingDestroyed; 1817 var isDestroyed = instance.state.isDestroyed; 1818 var isDisabled = !instance.state.isEnabled && !isBeingDestroyed; 1819 1820 if (isAlreadyHidden || isDestroyed || isDisabled) { 1821 return; 1822 } 1823 1824 invokeHook('onHide', [instance], false); 1825 1826 if (instance.props.onHide(instance) === false && !isBeingDestroyed) { 1827 return; 1828 } 1829 1830 removeDocumentMouseDownListener(); 1831 popper.style.visibility = 'hidden'; 1832 instance.state.isVisible = false; 1833 instance.state.isShown = false; 1834 setTransitionDuration(transitionableElements, duration); 1835 setVisibilityState(transitionableElements, 'hidden'); 1836 handleAriaDescribedByAttribute(); 1837 handleAriaExpandedAttribute(); 1838 onTransitionedOut(duration, function () { 1839 instance.popperInstance.disableEventListeners(); 1840 instance.popperInstance.options.placement = instance.props.placement; 1841 popper.parentNode.removeChild(popper); 1842 mountedInstances = mountedInstances.filter(function (i) { 1843 return i !== instance; 1844 }); 1845 1846 if (mountedInstances.length === 0) { 1847 updateIOSClass(false); 1848 } 1849 1850 instance.state.isMounted = false;
1851 invokeHook('onHidden', [instance]); 1852 }); 1853 } 1854 1855 function destroy() { 1856 { 1857 warnWhen(instance.state.isDestroyed, createMemoryLeakWarning('destroy')); 1858 } 1859 1860 if (instance.state.isDestroyed) { 1861 return; 1862 } 1863 1864 isBeingDestroyed = true; 1865 instance.clearDelayTimeouts(); 1866 instance.hide(0); 1867 removeListenersFromTriggerTarget(); 1868 delete reference._tippy; 1869 1870 if (instance.popperInstance) { 1871 instance.popperInstance.destroy(); 1872 } 1873 1874 isBeingDestroyed = false; 1875 instance.state.isDestroyed = true; 1876 invokeHook('onDestroy', [instance]); 1877 } 1878 } 1879 1880 function tippy(targets, optionalProps, 1881 /** @deprecated use Props.plugins */ 1882 plugins) { 1883 if (optionalProps === void 0) { 1884 optionalProps = {}; 1885 } 1886 1887 if (plugins === void 0) { 1888 plugins = []; 1889 } 1890 1891 plugins = defaultProps.plugins.concat(optionalProps.plugins || plugins); 1892 1893 { 1894 validateTargets(targets); 1895 validateProps(optionalProps, plugins); 1896 } 1897 1898 bindGlobalEventListeners(); 1899 1900 var passedProps = _extends({}, optionalProps, { 1901 plugins: plugins 1902 }); 1903 1904 var elements = getArrayOfElements(targets); 1905 1906 { 1907 var isSingleContentElement = isElement(passedProps.content); 1908 var isMoreThanOneReferenceElement = elements.length > 1; 1909 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(' ')); 1910 } 1911 1912 var instances = elements.reduce(function (acc, reference) { 1913 var instance = reference && createTippy(reference, passedProps); 1914 1915 if (instance) { 1916 acc.push(instance); 1917 } 1918 1919 return acc; 1920 }, []); 1921 return isElement(targets) ? instances[0] : instances; 1922 } 1923 1924 tippy.version = version; 1925 tippy.defaultProps = defaultProps; 1926 tippy.setDefaultProps = setDefaultProps; 1927 tippy.currentInput = currentInput; 1928 /** 1929 * Hides all visible poppers on the document 1930 */ 1931 1932 var hideAll = function hideAll(_temp) { 1933 var _ref = _temp === void 0 ? {} : _temp, 1934 excludedReferenceOrInstance = _ref.exclude, 1935 duration = _ref.duration; 1936 1937 mountedInstances.forEach(function (instance) { 1938 var isExcluded = false; 1939 1940 if (excludedReferenceOrInstance) { 1941 isExcluded = isReferenceElement(excludedReferenceOrInstance) ? instance.reference === excludedReferenceOrInstance : instance.popper === excludedReferenceOrInstance.popper; 1942 } 1943 1944 if (!isExcluded) { 1945 instance.hide(duration); 1946 } 1947 }); 1948 }; 1949 1950 /** 1951 * Re-uses a single tippy element for many different tippy instances. 1952 * Replaces v4's `tippy.group()`. 1953 */ 1954 1955 var createSingleton = function createSingleton(tippyInstances, optionalProps, 1956 /** @deprecated use Props.plugins */ 1957 plugins) { 1958 if (optionalProps === void 0) { 1959 optionalProps = {}; 1960 } 1961 1962 if (plugins === void 0) { 1963 plugins = []; 1964 } 1965 1966 { 1967 errorWhen(!Array.isArray(tippyInstances), ['The first argument passed to createSingleton() must be an array of tippy', 'instances. The passed value was', String(tippyInstances)].join(' ')); 1968 } 1969 1970 plugins = optionalProps.plugins || plugins; 1971 tippyInstances.forEach(function (instance) { 1972 instance.disable(); 1973 }); 1974 1975 var userAria = _extends({}, defaultProps, {}, optionalProps).aria; 1976 1977 var currentAria; 1978 var currentTarget; 1979 var shouldSkipUpdate = false; 1980 var references = tippyInstances.map(function (instance) { 1981 return instance.reference; 1982 }); 1983 var singleton = { 1984 fn: function fn(instance) { 1985 function handleAriaDescribedByAttribute(isShow) { 1986 if (!currentAria) { 1987 return; 1988 } 1989 1990 var attr = "aria-" + currentAria; 1991 1992 if (isShow && !instance.props.interactive) { 1993 currentTarget.setAttribute(attr, instance.popperChildren.tooltip.id); 1994 } else { 1995 currentTarget.removeAttribute(attr); 1996 } 1997 } 1998 1999 return { 2000 onAfterUpdate: function onAfterUpdate(_, _ref) { 2001 var aria = _ref.aria; 2002 2003 // Ensure `aria` for the singleton instance stays `null`, while
2004 // changing the `userAria` value 2005 if (aria !== undefined && aria !== userAria) { 2006 if (!shouldSkipUpdate) { 2007 userAria = aria; 2008 } else { 2009 shouldSkipUpdate = true; 2010 instance.setProps({ 2011 aria: null 2012 }); 2013 shouldSkipUpdate = false; 2014 } 2015 } 2016 }, 2017 onDestroy: function onDestroy() { 2018 tippyInstances.forEach(function (instance) { 2019 instance.enable(); 2020 }); 2021 }, 2022 onMount: function onMount() { 2023 handleAriaDescribedByAttribute(true); 2024 }, 2025 onUntrigger: function onUntrigger() { 2026 handleAriaDescribedByAttribute(false); 2027 }, 2028 onTrigger: function onTrigger(_, event) { 2029 var target = event.currentTarget; 2030 var index = references.indexOf(target); // bail-out 2031 2032 if (target === currentTarget) { 2033 return; 2034 } 2035 2036 currentTarget = target; 2037 currentAria = userAria; 2038 2039 if (instance.state.isVisible) { 2040 handleAriaDescribedByAttribute(true); 2041 } 2042 2043 instance.popperInstance.reference = target; 2044 instance.setContent(tippyInstances[index].props.content); 2045 } 2046 }; 2047 } 2048 }; 2049 return tippy(div(), _extends({}, optionalProps, { 2050 plugins: [singleton].concat(plugins), 2051 aria: null, 2052 triggerTarget: references 2053 })); 2054 }; 2055 2056 var BUBBLING_EVENTS_MAP = { 2057 mouseover: 'mouseenter', 2058 focusin: 'focus', 2059 click: 'click' 2060 }; 2061 /** 2062 * Creates a delegate instance that controls the creation of tippy instances 2063 * for child elements (`target` CSS selector). 2064 */ 2065 2066 function delegate(targets, props, 2067 /** @deprecated use Props.plugins */ 2068 plugins) { 2069 if (plugins === void 0) { 2070 plugins = []; 2071 } 2072 2073 { 2074 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(' ')); 2075 } 2076 2077 plugins = props.plugins || plugins; 2078 var listeners = []; 2079 var childTippyInstances = []; 2080 var target = props.target; 2081 var nativeProps = removeProperties(props, ['target']); 2082 2083 var parentProps = _extends({}, nativeProps, { 2084 plugins: plugins, 2085 trigger: 'manual' 2086 }); 2087 2088 var childProps = _extends({}, nativeProps, { 2089 plugins: plugins, 2090 showOnCreate: true 2091 }); 2092 2093 var returnValue = tippy(targets, parentProps); 2094 var normalizedReturnValue = normalizeToArray(returnValue); 2095 2096 function onTrigger(event) { 2097 if (!event.target) { 2098 return; 2099 } 2100 2101 var targetNode = event.target.closest(target); 2102 2103 if (!targetNode) { 2104 return; 2105 } // Get relevant trigger with fallbacks: 2106 // 1. Check `data-tippy-trigger` attribute on target node 2107 // 2. Fallback to `trigger` passed to `delegate()` 2108 // 3. Fallback to `defaultProps.trigger` 2109 2110 2111 var trigger = targetNode.getAttribute('data-tippy-trigger') || props.trigger || defaultProps.trigger; // Only create the instance if the bubbling event matches the trigger type 2112 2113 if (!includes(trigger, BUBBLING_EVENTS_MAP[event.type])) { 2114 return; 2115 } 2116 2117 var instance = tippy(targetNode, childProps); 2118 2119 if (instance) { 2120 childTippyInstances = childTippyInstances.concat(instance); 2121 } 2122 } 2123 2124 function on(node, eventType, handler, options) { 2125 if (options === void 0) { 2126 options = false; 2127 } 2128 2129 node.addEventListener(eventType, handler, options); 2130 listeners.push({ 2131 node: node, 2132 eventType: eventType, 2133 handler: handler, 2134 options: options 2135 }); 2136 } 2137 2138 function addEventListeners(instance) { 2139 var reference = instance.reference; 2140 on(reference, 'mouseover', onTrigger); 2141 on(reference, 'focusin', onTrigger); 2142 on(reference, 'click', onTrigger); 2143 } 2144 2145 function removeEventListeners() { 2146 listeners.forEach(function (_ref) { 2147 var node = _ref.node, 2148 eventType = _ref.eventType, 2149 handler = _ref.handler, 2150 options = _ref.options; 2151 node.removeEventListener(eventType, handler, options); 2152 }); 2153 listeners = []; 2154 } 2155 2156 function applyMutations(instance) { 2157 var originalDestroy = instance.destroy; 2158 2159 instance.destroy = function (shouldDestroyChildInstances) { 2160 if (shouldDestroyChildInstances === void 0) { 2161 shouldDestroyChildInstances = true; 2162 } 2163 2164 if (shouldDestroyChildInstances) {
2165 childTippyInstances.forEach(function (instance) { 2166 instance.destroy(); 2167 }); 2168 } 2169 2170 childTippyInstances = []; 2171 removeEventListeners(); 2172 originalDestroy(); 2173 }; 2174 2175 addEventListeners(instance); 2176 } 2177 2178 normalizedReturnValue.forEach(applyMutations); 2179 return returnValue; 2180 } 2181 2182 var animateFill = { 2183 name: 'animateFill', 2184 defaultValue: false, 2185 fn: function fn(instance) { 2186 var _instance$popperChild = instance.popperChildren, 2187 tooltip = _instance$popperChild.tooltip, 2188 content = _instance$popperChild.content; 2189 var backdrop = instance.props.animateFill ? createBackdropElement() : null; 2190 2191 function addBackdropToPopperChildren() { 2192 instance.popperChildren.backdrop = backdrop; 2193 } 2194 2195 return { 2196 onCreate: function onCreate() { 2197 if (backdrop) { 2198 addBackdropToPopperChildren(); 2199 tooltip.insertBefore(backdrop, tooltip.firstElementChild); 2200 tooltip.setAttribute('data-animatefill', ''); 2201 tooltip.style.overflow = 'hidden'; 2202 instance.setProps({ 2203 animation: 'shift-away', 2204 arrow: false 2205 }); 2206 } 2207 }, 2208 onMount: function onMount() { 2209 if (backdrop) { 2210 var transitionDuration = tooltip.style.transitionDuration; 2211 var duration = Number(transitionDuration.replace('ms', '')); // The content should fade in after the backdrop has mostly filled the 2212 // tooltip element. `clip-path` is the other alternative but is not
2213 // well-supported and is buggy on some devices. 2214 2215 content.style.transitionDelay = Math.round(duration / 10) + "ms"; 2216 backdrop.style.transitionDuration = transitionDuration; 2217 setVisibilityState([backdrop], 'visible'); // Warn if the stylesheets are not loaded 2218 2219 { 2220 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."); 2221 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."); 2222 } 2223 } 2224 }, 2225 onShow: function onShow() { 2226 if (backdrop) { 2227 backdrop.style.transitionDuration = '0ms'; 2228 } 2229 }, 2230 onHide: function onHide() { 2231 if (backdrop) { 2232 setVisibilityState([backdrop], 'hidden'); 2233 } 2234 }, 2235 onAfterUpdate: function onAfterUpdate() {
2236 // With this type of prop, it's highly unlikely it will be changed 2237 // dynamically. We'll leave out the diff/update logic it to save bytes. 2238 // `popperChildren` is assigned a new object onAfterUpdate 2239 addBackdropToPopperChildren(); 2240 } 2241 }; 2242 } 2243 }; 2244 2245 function createBackdropElement() { 2246 var backdrop = div(); 2247 backdrop.className = BACKDROP_CLASS; 2248 setVisibilityState([backdrop], 'hidden'); 2249 return backdrop; 2250 } 2251 2252 var followCursor = { 2253 name: 'followCursor', 2254 defaultValue: false, 2255 fn: function fn(instance) { 2256 var reference = instance.reference, 2257 popper = instance.popper; 2258 var originalReference = null; // Support iframe contexts 2259 // Static check that assumes any of the `triggerTarget` or `reference` 2260 // nodes will never change documents, even when they are updated 2261 2262 var doc = getOwnerDocument(instance.props.triggerTarget || reference); // Internal state 2263 2264 var lastMouseMoveEvent; 2265 var mouseCoords = null; 2266 var isInternallySettingControlledProp = false; // These are controlled by this plugin, so we need to store the user's 2267 // original prop value 2268 2269 var userProps = instance.props; 2270 2271 function setUserProps(props) { 2272 var keys = Object.keys(props); 2273 keys.forEach(function (prop) { 2274 userProps[prop] = useIfDefined(props[prop], userProps[prop]); 2275 }); 2276 } 2277 2278 function getIsManual() { 2279 return instance.props.trigger.trim() === 'manual'; 2280 } 2281 2282 function getIsEnabled() { 2283 // #597 2284 var isValidMouseEvent = getIsManual() ? true : // Check if a keyboard "click" 2285 mouseCoords !== null && !(mouseCoords.clientX === 0 && mouseCoords.clientY === 0); 2286 return instance.props.followCursor && isValidMouseEvent; 2287 } 2288 2289 function getIsInitialBehavior() { 2290 return currentInput.isTouch || instance.props.followCursor === 'initial' && instance.state.isVisible; 2291 } 2292 2293 function resetReference() { 2294 if (instance.popperInstance && originalReference) { 2295 instance.popperInstance.reference = originalReference; 2296 } 2297 } 2298 2299 function handlePlacement() { 2300 // Due to `getVirtualOffsets()`, we need to reverse the placement if it's 2301 // shifted (start -> end, and vice-versa) 2302 // Early bail-out 2303 if (!getIsEnabled() && instance.props.placement === userProps.placement) { 2304 return; 2305 } 2306 2307 var placement = userProps.placement; 2308 var shift = placement.split('-')[1]; 2309 isInternallySettingControlledProp = true; 2310 instance.setProps({ 2311 placement: getIsEnabled() && shift ? placement.replace(shift, shift === 'start' ? 'end' : 'start') : placement 2312 }); 2313 isInternallySettingControlledProp = false; 2314 } 2315 2316 function handlePopperListeners() { 2317 if (!instance.popperInstance) { 2318 return; 2319 } // Popper's scroll listeners make sense for `true` only. TODO: work out 2320 // how to only listen horizontal scroll for "horizontal" and vertical 2321 // scroll for "vertical" 2322 2323 2324 if (getIsEnabled() && getIsInitialBehavior()) { 2325 instance.popperInstance.disableEventListeners(); 2326 } 2327 } 2328 2329 function handleMouseMoveListener() { 2330 if (getIsEnabled()) { 2331 addListener(); 2332 } else { 2333 resetReference(); 2334 } 2335 } 2336 2337 function triggerLastMouseMove() { 2338 if (getIsEnabled()) { 2339 onMouseMove(lastMouseMoveEvent); 2340 } 2341 } 2342 2343 function addListener() { 2344 doc.addEventListener('mousemove', onMouseMove); 2345 } 2346 2347 function removeListener() { 2348 doc.removeEventListener('mousemove', onMouseMove); 2349 } 2350 2351 function onMouseMove(event) { 2352 var _lastMouseMoveEvent = lastMouseMoveEvent = event, 2353 clientX = _lastMouseMoveEvent.clientX, 2354 clientY = _lastMouseMoveEvent.clientY; 2355 2356 if (!instance.popperInstance || !instance.state.currentPlacement) { 2357 return; 2358 } // If the instance is interactive, avoid updating the position unless it's 2359 // over the reference element 2360 2361 2362 var isCursorOverReference = closestCallback(event.target, function (el) { 2363 return el === reference; 2364 }); 2365 var followCursor = instance.props.followCursor; 2366 var isHorizontal = followCursor === 'horizontal'; 2367 var isVertical = followCursor === 'vertical'; 2368 var isVerticalPlacement = includes(['top', 'bottom'], getBasePlacement(instance.state.currentPlacement)); // The virtual reference needs some size to prevent itself from overflowing 2369 2370 var _getVirtualOffsets = getVirtualOffsets(popper, isVerticalPlacement), 2371 size = _getVirtualOffsets.size, 2372 x = _getVirtualOffsets.x, 2373 y = _getVirtualOffsets.y; 2374 2375 if (isCursorOverReference || !instance.props.interactive) { 2376 // Preserve custom position ReferenceObjects, which may not be the 2377 // original targets reference passed as an argument 2378 if (originalReference === null) { 2379 originalReference = instance.popperInstance.reference; 2380 } 2381 2382 instance.popperInstance.reference = { 2383 referenceNode: reference, 2384 // These `client` values don't get used by Popper.js if they are 0 2385 clientWidth: 0, 2386 clientHeight: 0, 2387 getBoundingClientRect: function getBoundingClientRect() { 2388 var rect = reference.getBoundingClientRect(); 2389 return { 2390 width: isVerticalPlacement ? size : 0, 2391 height: isVerticalPlacement ? 0 : size, 2392 top: (isHorizontal ? rect.top : clientY) - y, 2393 bottom: (isHorizontal ? rect.bottom : clientY) + y, 2394 left: (isVertical ? rect.left : clientX) - x, 2395 right: (isVertical ? rect.right : clientX) + x 2396 }; 2397 } 2398 };
2399 instance.popperInstance.update(); 2400 } 2401 2402 if (getIsInitialBehavior()) { 2403 removeListener(); 2404 } 2405 } 2406 2407 return { 2408 onAfterUpdate: function onAfterUpdate(_, partialProps) { 2409 if (!isInternallySettingControlledProp) { 2410 setUserProps(partialProps); 2411 2412 if (partialProps.placement) { 2413 handlePlacement(); 2414 } 2415 } // A new placement causes the popperInstance to be recreated 2416 2417 2418 if (partialProps.placement) { 2419 handlePopperListeners(); 2420 } // Wait for `.update()` to set `instance.state.currentPlacement` to 2421 // the new placement 2422 2423 2424 requestAnimationFrame(triggerLastMouseMove); 2425 }, 2426 onMount: function onMount() { 2427 triggerLastMouseMove(); 2428 handlePopperListeners(); 2429 }, 2430 onShow: function onShow() { 2431 if (getIsManual()) { 2432 // Since there's no trigger event to use, we have to use these as 2433 // baseline coords 2434 mouseCoords = { 2435 clientX: 0, 2436 clientY: 0 2437 }; // Ensure `lastMouseMoveEvent` doesn't access any other properties 2438 // of a MouseEvent here 2439 2440 lastMouseMoveEvent = mouseCoords; 2441 handlePlacement(); 2442 handleMouseMoveListener(); 2443 } 2444 }, 2445 onTrigger: function onTrigger(_, event) { 2446 // Tapping on touch devices can trigger `mouseenter` then `focus` 2447 if (mouseCoords) { 2448 return; 2449 } 2450 2451 if (isMouseEvent(event)) { 2452 mouseCoords = { 2453 clientX: event.clientX, 2454 clientY: event.clientY 2455 }; 2456 lastMouseMoveEvent = event; 2457 } 2458 2459 handlePlacement(); 2460 handleMouseMoveListener(); 2461 }, 2462 onUntrigger: function onUntrigger() { 2463 // If untriggered before showing (`onHidden` will never be invoked) 2464 if (!instance.state.isVisible) { 2465 removeListener(); 2466 mouseCoords = null; 2467 } 2468 }, 2469 onHidden: function onHidden() { 2470 removeListener(); 2471 resetReference(); 2472 mouseCoords = null; 2473 } 2474 }; 2475 } 2476 }; 2477 function getVirtualOffsets(popper, isVerticalPlacement) { 2478 var size = isVerticalPlacement ? popper.offsetWidth : popper.offsetHeight; 2479 return { 2480 size: size, 2481 x: isVerticalPlacement ? size : 0, 2482 y: isVerticalPlacement ? 0 : size 2483 }; 2484 } 2485 2486 // position. This will require the `followCursor` plugin's fixes for overflow 2487 // due to using event.clientX/Y values. (normalizedPlacement, getVirtualOffsets) 2488 2489 var inlinePositioning = { 2490 name: 'inlinePositioning', 2491 defaultValue: false, 2492 fn: function fn(instance) { 2493 var reference = instance.reference; 2494 2495 function getIsEnabled() { 2496 return !!instance.props.inlinePositioning; 2497 } 2498 2499 return { 2500 onHidden: function onHidden() { 2501 if (getIsEnabled()) { 2502 instance.popperInstance.reference = reference; 2503 } 2504 }, 2505 onShow: function onShow() { 2506 if (!getIsEnabled()) { 2507 return; 2508 } 2509 2510 instance.popperInstance.reference = { 2511 referenceNode: reference, 2512 // These `client` values don't get used by Popper.js if they are 0 2513 clientWidth: 0, 2514 clientHeight: 0, 2515 getBoundingClientRect: function getBoundingClientRect() { 2516 return getInlineBoundingClientRect(instance.state.currentPlacement && getBasePlacement(instance.state.currentPlacement), reference.getBoundingClientRect(), arrayFrom(reference.getClientRects())); 2517 } 2518 }; 2519 } 2520 }; 2521 } 2522 }; 2523 function getInlineBoundingClientRect(currentBasePlacement, boundingRect, clientRects) { 2524 // Not an inline element, or placement is not yet known 2525 if (clientRects.length < 2 || currentBasePlacement === null) { 2526 return boundingRect; 2527 } 2528 2529 switch (currentBasePlacement) { 2530 case 'top': 2531 case 'bottom': 2532 { 2533 var firstRect = clientRects[0]; 2534 var lastRect = clientRects[clientRects.length - 1]; 2535 var isTop = currentBasePlacement === 'top'; 2536 var top = firstRect.top; 2537 var bottom = lastRect.bottom; 2538 var left = isTop ? firstRect.left : lastRect.left; 2539 var right = isTop ? firstRect.right : lastRect.right; 2540 var width = right - left; 2541 var height = bottom - top; 2542 return { 2543 top: top, 2544 bottom: bottom, 2545 left: left, 2546 right: right, 2547 width: width, 2548 height: height 2549 }; 2550 } 2551 2552 case 'left': 2553 case 'right': 2554 { 2555 var minLeft = Math.min.apply(Math, clientRects.map(function (rects) { 2556 return rects.left; 2557 })); 2558 var maxRight = Math.max.apply(Math, clientRects.map(function (rects) { 2559 return rects.right; 2560 })); 2561 var measureRects = clientRects.filter(function (rect) { 2562 return currentBasePlacement === 'left' ? rect.left === minLeft : rect.right === maxRight; 2563 }); 2564 var _top = measureRects[0].top; 2565 var _bottom = measureRects[measureRects.length - 1].bottom; 2566 var _left = minLeft; 2567 var _right = maxRight; 2568 2569 var _width = _right - _left; 2570 2571 var _height = _bottom - _top; 2572 2573 return { 2574 top: _top, 2575 bottom: _bottom, 2576 left: _left, 2577 right: _right, 2578 width: _width, 2579 height: _height 2580 }; 2581 } 2582 2583 default: 2584 { 2585 return boundingRect; 2586 } 2587 } 2588 } 2589 2590 var sticky = { 2591 name: 'sticky', 2592 defaultValue: false, 2593 fn: function fn(instance) { 2594 var reference = instance.reference, 2595 popper = instance.popper; 2596 2597 function getReference() { 2598 return instance.popperInstance ? instance.popperInstance.reference : reference; 2599 } 2600 2601 function shouldCheck(value) { 2602 return instance.props.sticky === true || instance.props.sticky === value; 2603 } 2604 2605 var prevRefRect = null; 2606 var prevPopRect = null; 2607 2608 function updatePosition() { 2609 var currentRefRect = shouldCheck('reference') ? getReference().getBoundingClientRect() : null; 2610 var currentPopRect = shouldCheck('popper') ? popper.getBoundingClientRect() : null; 2611 2612 if (currentRefRect && areRectsDifferent(prevRefRect, currentRefRect) || currentPopRect && areRectsDifferent(prevPopRect, currentPopRect)) {
2613 instance.popperInstance.update(); 2614 } 2615 2616 prevRefRect = currentRefRect; 2617 prevPopRect = currentPopRect; 2618 2619 if (instance.state.isMounted) { 2620 requestAnimationFrame(updatePosition); 2621 } 2622 } 2623 2624 return { 2625 onMount: function onMount() { 2626 if (instance.props.sticky) { 2627 updatePosition(); 2628 } 2629 } 2630 }; 2631 } 2632 }; 2633 2634 function areRectsDifferent(rectA, rectB) { 2635 if (rectA && rectB) { 2636 return rectA.top !== rectB.top || rectA.right !== rectB.right || rectA.bottom !== rectB.bottom || rectA.left !== rectB.left; 2637 } 2638 2639 return true; 2640 } 2641 2642 if (isBrowser) { 2643 injectCSS(css); 2644 } 2645 2646 tippy.setDefaultProps({ 2647 plugins: [animateFill, followCursor, inlinePositioning, sticky] 2648 }); 2649 tippy.createSingleton = createSingleton; 2650 tippy.delegate = delegate; 2651 tippy.hideAll = hideAll; 2652 tippy.roundArrow = ROUND_ARROW; 2653 2654 return tippy; 2655 2656}(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.