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