PageSourceSearch

https://th-deg.de/cache-buster-1756303285/static/js/node_modules/popper.js/dist/popper.js

js th-deg.de collected 2026-10-02 03:35:47 UTC 84,440 bytes, 2,450 lines download raw bytes

vendor: 4,271 bytes, lines 1-147
1/**!
2 * @fileOverview Kickass library to create and place poppers near their reference elements.
3 * @version 1.15.0
4 * @license
5 * Copyright (c) 2016 Federico Zivolo and contributors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
26
27const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
28let timeoutDuration = 0;
29for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) {
30  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
31    timeoutDuration = 1;
32    break;
33  }
34}
35
36function microtaskDebounce(fn) {
37  let called = false;
38  return () => {
39    if (called) {
40      return;
41    }
42    called = true;
43    window.Promise.resolve().then(() => {
44      called = false;
45      fn();
46    });
47  };
48}
49
50function taskDebounce(fn) {
51  let scheduled = false;
52  return () => {
53    if (!scheduled) {
54      scheduled = true;
55      setTimeout(() => {
56        scheduled = false;
57        fn();
58      }, timeoutDuration);
59    }
60  };
61}
62
63const supportsMicroTasks = isBrowser && window.Promise;
64
65/**
66* Create a debounced version of a method, that's asynchronously deferred
67* but called in the minimum time possible.
68*
69* @method
70* @memberof Popper.Utils
71* @argument {Function} fn
72* @returns {Function}
73*/
74var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
75
76/**
77 * Check if the given variable is a function
78 * @method
79 * @memberof Popper.Utils
80 * @argument {Any} functionToCheck - variable to check
81 * @returns {Boolean} answer to: is a function?
82 */
83function isFunction(functionToCheck) {
84  const getType = {};
85  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
86}
87
88/**
89 * Get CSS computed property of the given element
90 * @method
91 * @memberof Popper.Utils
92 * @argument {Eement} element
93 * @argument {String} property
94 */
95function getStyleComputedProperty(element, property) {
96  if (element.nodeType !== 1) {
97    return [];
98  }
99  // NOTE: 1 DOM access here
100  const window = element.ownerDocument.defaultView;
101  const css = window.getComputedStyle(element, null);
102  return property ? css[property] : css;
103}
104
105/**
106 * Returns the parentNode or the host of the element
107 * @method
108 * @memberof Popper.Utils
109 * @argument {Element} element
110 * @returns {Element} parent
111 */
112function getParentNode(element) {
113  if (element.nodeName === 'HTML') {
114    return element;
115  }
116  return element.parentNode || element.host;
117}
118
119/**
120 * Returns the scrolling parent of the given element
121 * @method
122 * @memberof Popper.Utils
123 * @argument {Element} element
124 * @returns {Element} scroll parent
125 */
126function getScrollParent(element) {
127  // Return body, `getScroll` will take care to get the correct `scrollTop` from it
128  if (!element) {
129    return document.body;
130  }
131
132  switch (element.nodeName) {
133    case 'HTML':
134    case 'BODY':
135      return element.ownerDocument.body;
136    case '#document':
137      return element.body;
138  }
139
140  // Firefox want us to check `-x` and `-y` variations as well
141  const { overflow, overflowX, overflowY } = getStyleComputedProperty(element);
142  if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
143    return element;
144  }
145
146  return getScrollParent(getParentNode(element));
147}
vendor: 5,535 bytes, lines 147-326
147
148
149const isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
150const isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
151
152/**
153 * Determines if the browser is Internet Explorer
154 * @method
155 * @memberof Popper.Utils
156 * @param {Number} version to check
157 * @returns {Boolean} isIE
158 */
159function isIE(version) {
160  if (version === 11) {
161    return isIE11;
162  }
163  if (version === 10) {
164    return isIE10;
165  }
166  return isIE11 || isIE10;
167}
168
169/**
170 * Returns the offset parent of the given element
171 * @method
172 * @memberof Popper.Utils
173 * @argument {Element} element
174 * @returns {Element} offset parent
175 */
176function getOffsetParent(element) {
177  if (!element) {
178    return document.documentElement;
179  }
180
181  const noOffsetParent = isIE(10) ? document.body : null;
182
183  // NOTE: 1 DOM access here
184  let offsetParent = element.offsetParent || null;
185  // Skip hidden elements which don't have an offsetParent
186  while (offsetParent === noOffsetParent && element.nextElementSibling) {
187    offsetParent = (element = element.nextElementSibling).offsetParent;
188  }
189
190  const nodeName = offsetParent && offsetParent.nodeName;
191
192  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
193    return element ? element.ownerDocument.documentElement : document.documentElement;
194  }
195
196  // .offsetParent will return the closest TH, TD or TABLE in case
197  // no offsetParent is present, I hate this job...
198  if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
199    return getOffsetParent(offsetParent);
200  }
201
202  return offsetParent;
203}
204
205function isOffsetContainer(element) {
206  const { nodeName } = element;
207  if (nodeName === 'BODY') {
208    return false;
209  }
210  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
211}
212
213/**
214 * Finds the root node (document, shadowDOM root) of the given element
215 * @method
216 * @memberof Popper.Utils
217 * @argument {Element} node
218 * @returns {Element} root node
219 */
220function getRoot(node) {
221  if (node.parentNode !== null) {
222    return getRoot(node.parentNode);
223  }
224
225  return node;
226}
227
228/**
229 * Finds the offset parent common to the two provided nodes
230 * @method
231 * @memberof Popper.Utils
232 * @argument {Element} element1
233 * @argument {Element} element2
234 * @returns {Element} common offset parent
235 */
236function findCommonOffsetParent(element1, element2) {
237  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
238  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
239    return document.documentElement;
240  }
241
242  // Here we make sure to give as "start" the element that comes first in the DOM
243  const order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
244  const start = order ? element1 : element2;
245  const end = order ? element2 : element1;
246
247  // Get common ancestor container
248  const range = document.createRange();
249  range.setStart(start, 0);
250  range.setEnd(end, 0);
251  const { commonAncestorContainer } = range;
252
253  // Both nodes are inside #document
254  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
255    if (isOffsetContainer(commonAncestorContainer)) {
256      return commonAncestorContainer;
257    }
258
259    return getOffsetParent(commonAncestorContainer);
260  }
261
262  // one of the nodes is inside shadowDOM, find which one
263  const element1root = getRoot(element1);
264  if (element1root.host) {
265    return findCommonOffsetParent(element1root.host, element2);
266  } else {
267    return findCommonOffsetParent(element1, getRoot(element2).host);
268  }
269}
270
271/**
272 * Gets the scroll value of the given element in the given side (top and left)
273 * @method
274 * @memberof Popper.Utils
275 * @argument {Element} element
276 * @argument {String} side `top` or `left`
277 * @returns {number} amount of scrolled pixels
278 */
279function getScroll(element, side = 'top') {
280  const upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
281  const nodeName = element.nodeName;
282
283  if (nodeName === 'BODY' || nodeName === 'HTML') {
284    const html = element.ownerDocument.documentElement;
285    const scrollingElement = element.ownerDocument.scrollingElement || html;
286    return scrollingElement[upperSide];
287  }
288
289  return element[upperSide];
290}
291
292/*
293 * Sum or subtract the element scroll values (left and top) from a given rect object
294 * @method
295 * @memberof Popper.Utils
296 * @param {Object} rect - Rect object you want to change
297 * @param {HTMLElement} element - The element from the function reads the scroll values
298 * @param {Boolean} subtract - set to true if you want to subtract the scroll values
299 * @return {Object} rect - The modifier rect object
300 */
301function includeScroll(rect, element, subtract = false) {
302  const scrollTop = getScroll(element, 'top');
303  const scrollLeft = getScroll(element, 'left');
304  const modifier = subtract ? -1 : 1;
305  rect.top += scrollTop * modifier;
306  rect.bottom += scrollTop * modifier;
307  rect.left += scrollLeft * modifier;
308  rect.right += scrollLeft * modifier;
309  return rect;
310}
311
312/*
313 * Helper to detect borders of a given element
314 * @method
315 * @memberof Popper.Utils
316 * @param {CSSStyleDeclaration} styles
317 * Result of `getStyleComputedProperty` on the given element
318 * @param {String} axis - `x` or `y`
319 * @return {number} borders - The borders size of the given axis
320 */
321
322function getBordersSize(styles, axis) {
323  const sideA = axis === 'x' ? 'Left' : 'Top';
324  const sideB = sideA === 'Left' ? 'Right' : 'Bottom';
325
326  return parseFloat(styles[`border${sideA}Width`]
vendor: 10,574 bytes, lines 326-639
326, 10) + parseFloat(styles[`border${sideB}Width`], 10);
327}
328
329function getSize(axis, body, html, computedStyle) {
330  return Math.max(body[`offset${axis}`], body[`scroll${axis}`], html[`client${axis}`], html[`offset${axis}`], html[`scroll${axis}`], isIE(10) ? parseInt(html[`offset${axis}`]) + parseInt(computedStyle[`margin${axis === 'Height' ? 'Top' : 'Left'}`]) + parseInt(computedStyle[`margin${axis === 'Height' ? 'Bottom' : 'Right'}`]) : 0);
331}
332
333function getWindowSizes(document) {
334  const body = document.body;
335  const html = document.documentElement;
336  const computedStyle = isIE(10) && getComputedStyle(html);
337
338  return {
339    height: getSize('Height', body, html, computedStyle),
340    width: getSize('Width', body, html, computedStyle)
341  };
342}
343
344var _extends = Object.assign || function (target) {
345  for (var i = 1; i < arguments.length; i++) {
346    var source = arguments[i];
347
348    for (var key in source) {
349      if (Object.prototype.hasOwnProperty.call(source, key)) {
350        target[key] = source[key];
351      }
352    }
353  }
354
355  return target;
356};
357
358/**
359 * Given element offsets, generate an output similar to getBoundingClientRect
360 * @method
361 * @memberof Popper.Utils
362 * @argument {Object} offsets
363 * @returns {Object} ClientRect like output
364 */
365function getClientRect(offsets) {
366  return _extends({}, offsets, {
367    right: offsets.left + offsets.width,
368    bottom: offsets.top + offsets.height
369  });
370}
371
372/**
373 * Get bounding client rect of given element
374 * @method
375 * @memberof Popper.Utils
376 * @param {HTMLElement} element
377 * @return {Object} client rect
378 */
379function getBoundingClientRect(element) {
380  let rect = {};
381
382  // IE10 10 FIX: Please, don't ask, the element isn't
383  // considered in DOM in some circumstances...
384  // This isn't reproducible in IE10 compatibility mode of IE11
385  try {
386    if (isIE(10)) {
387      rect = element.getBoundingClientRect();
388      const scrollTop = getScroll(element, 'top');
389      const scrollLeft = getScroll(element, 'left');
390      rect.top += scrollTop;
391      rect.left += scrollLeft;
392      rect.bottom += scrollTop;
393      rect.right += scrollLeft;
394    } else {
395      rect = element.getBoundingClientRect();
396    }
397  } catch (e) {}
398
399  const result = {
400    left: rect.left,
401    top: rect.top,
402    width: rect.right - rect.left,
403    height: rect.bottom - rect.top
404  };
405
406  // subtract scrollbar size from sizes
407  const sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
408  const width = sizes.width || element.clientWidth || result.right - result.left;
409  const height = sizes.height || element.clientHeight || result.bottom - result.top;
410
411  let horizScrollbar = element.offsetWidth - width;
412  let vertScrollbar = element.offsetHeight - height;
413
414  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
415  // we make this check conditional for performance reasons
416  if (horizScrollbar || vertScrollbar) {
417    const styles = getStyleComputedProperty(element);
418    horizScrollbar -= getBordersSize(styles, 'x');
419    vertScrollbar -= getBordersSize(styles, 'y');
420
421    result.width -= horizScrollbar;
422    result.height -= vertScrollbar;
423  }
424
425  return getClientRect(result);
426}
427
428function getOffsetRectRelativeToArbitraryNode(children, parent, fixedPosition = false) {
429  const isIE10 = isIE(10);
430  const isHTML = parent.nodeName === 'HTML';
431  const childrenRect = getBoundingClientRect(children);
432  const parentRect = getBoundingClientRect(parent);
433  const scrollParent = getScrollParent(children);
434
435  const styles = getStyleComputedProperty(parent);
436  const borderTopWidth = parseFloat(styles.borderTopWidth, 10);
437  const borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
438
439  // In cases where the parent is fixed, we must ignore negative scroll in offset calc
440  if (fixedPosition && isHTML) {
441    parentRect.top = Math.max(parentRect.top, 0);
442    parentRect.left = Math.max(parentRect.left, 0);
443  }
444  let offsets = getClientRect({
445    top: childrenRect.top - parentRect.top - borderTopWidth,
446    left: childrenRect.left - parentRect.left - borderLeftWidth,
447    width: childrenRect.width,
448    height: childrenRect.height
449  });
450  offsets.marginTop = 0;
451  offsets.marginLeft = 0;
452
453  // Subtract margins of documentElement in case it's being used as parent
454  // we do this only on HTML because it's the only element that behaves
455  // differently when margins are applied to it. The margins are included in
456  // the box of the documentElement, in the other cases not.
457  if (!isIE10 && isHTML) {
458    const marginTop = parseFloat(styles.marginTop, 10);
459    const marginLeft = parseFloat(styles.marginLeft, 10);
460
461    offsets.top -= borderTopWidth - marginTop;
462    offsets.bottom -= borderTopWidth - marginTop;
463    offsets.left -= borderLeftWidth - marginLeft;
464    offsets.right -= borderLeftWidth - marginLeft;
465
466    // Attach marginTop and marginLeft because in some circumstances we may need them
467    offsets.marginTop = marginTop;
468    offsets.marginLeft = marginLeft;
469  }
470
471  if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
472    offsets = includeScroll(offsets, parent);
473  }
474
475  return offsets;
476}
477
478function getViewportOffsetRectRelativeToArtbitraryNode(element, excludeScroll = false) {
479  const html = element.ownerDocument.documentElement;
480  const relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
481  const width = Math.max(html.clientWidth, window.innerWidth || 0);
482  const height = Math.max(html.clientHeight, window.innerHeight || 0);
483
484  const scrollTop = !excludeScroll ? getScroll(html) : 0;
485  const scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
486
487  const offset = {
488    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
489    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
490    width,
491    height
492  };
493
494  return getClientRect(offset);
495}
496
497/**
498 * Check if the given element is fixed or is inside a fixed parent
499 * @method
500 * @memberof Popper.Utils
501 * @argument {Element} element
502 * @argument {Element} customContainer
503 * @returns {Boolean} answer to "isFixed?"
504 */
505function isFixed(element) {
506  const nodeName = element.nodeName;
507  if (nodeName === 'BODY' || nodeName === 'HTML') {
508    return false;
509  }
510  if (getStyleComputedProperty(element, 'position') === 'fixed') {
511    return true;
512  }
513  const parentNode = getParentNode(element);
514  if (!parentNode) {
515    return false;
516  }
517  return isFixed(parentNode);
518}
519
520/**
521 * Finds the first parent of an element that has a transformed property defined
522 * @method
523 * @memberof Popper.Utils
524 * @argument {Element} element
525 * @returns {Element} first transformed parent or documentElement
526 */
527
528function getFixedPositionOffsetParent(element) {
529  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
530  if (!element || !element.parentElement || isIE()) {
531    return document.documentElement;
532  }
533  let el = element.parentElement;
534  while (el && getStyleComputedProperty(el, 'transform') === 'none') {
535    el = el.parentElement;
536  }
537  return el || document.documentElement;
538}
539
540/**
541 * Computed the boundaries limits and return them
542 * @method
543 * @memberof Popper.Utils
544 * @param {HTMLElement} popper
545 * @param {HTMLElement} reference
546 * @param {number} padding
547 * @param {HTMLElement} boundariesElement - Element used to define the boundaries
548 * @param {Boolean} fixedPosition - Is in fixed position mode
549 * @returns {Object} Coordinates of the boundaries
550 */
551function getBoundaries(popper, reference, padding, boundariesElement, fixedPosition = false) {
552  // NOTE: 1 DOM access here
553
554  let boundaries = { top: 0, left: 0 };
555  const offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
556
557  // Handle viewport case
558  if (boundariesElement === 'viewport') {
559    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
560  } else {
561    // Handle other cases based on DOM element used as boundaries
562    let boundariesNode;
563    if (boundariesElement === 'scrollParent') {
564      boundariesNode = getScrollParent(getParentNode(reference));
565      if (boundariesNode.nodeName === 'BODY') {
566        boundariesNode = popper.ownerDocument.documentElement;
567      }
568    } else if (boundariesElement === 'window') {
569      boundariesNode = popper.ownerDocument.documentElement;
570    } else {
571      boundariesNode = boundariesElement;
572    }
573
574    const offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
575
576    // In case of HTML, we need a different computation
577    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
578      const { height, width } = getWindowSizes(popper.ownerDocument);
579      boundaries.top += offsets.top - offsets.marginTop;
580      boundaries.bottom = height + offsets.top;
581      boundaries.left += offsets.left - offsets.marginLeft;
582      boundaries.right = width + offsets.left;
583    } else {
584      // for all the other DOM elements, this one is good
585      boundaries = offsets;
586    }
587  }
588
589  // Add paddings
590  padding = padding || 0;
591  const isPaddingNumber = typeof padding === 'number';
592  boundaries.left += isPaddingNumber ? padding : padding.left || 0;
593  boundaries.top += isPaddingNumber ? padding : padding.top || 0;
594  boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
595  boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
596
597  return boundaries;
598}
599
600function getArea({ width, height }) {
601  return width * height;
602}
603
604/**
605 * Utility used to transform the `auto` placement to the placement with more
606 * available space.
607 * @method
608 * @memberof Popper.Utils
609 * @argument {Object} data - The data object generated by update method
610 * @argument {Object} options - Modifiers configuration and options
611 * @returns {Object} The data object, properly modified
612 */
613function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement, padding = 0) {
614  if (placement.indexOf('auto') === -1) {
615    return placement;
616  }
617
618  const boundaries = getBoundaries(popper, reference, padding, boundariesElement);
619
620  const rects = {
621    top: {
622      width: boundaries.width,
623      height: refRect.top - boundaries.top
624    },
625    right: {
626      width: boundaries.right - refRect.right,
627      height: boundaries.height
628    },
629    bottom: {
630      width: boundaries.width,
631      height: boundaries.bottom - refRect.bottom
632    },
633    left: {
634      width: refRect.left - boundaries.left,
635      height: boundaries.height
636    }
637  };
638
639  const sortedAreas = Object.keys(rects).map(key => _extends({
vendor: 1,045 bytes, lines 640-665
640    key
641  }, rects[key], {
642    area: getArea(rects[key])
643  })).sort((a, b) => b.area - a.area);
644
645  const filteredAreas = sortedAreas.filter(({ width, height }) => width >= popper.clientWidth && height >= popper.clientHeight);
646
647  const computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
648
649  const variation = placement.split('-')[1];
650
651  return computedPlacement + (variation ? `-${variation}` : '');
652}
653
654/**
655 * Get offsets to the reference element
656 * @method
657 * @memberof Popper.Utils
658 * @param {Object} state
659 * @param {Element} popper - the popper element
660 * @param {Element} reference - the reference element (the popper will be relative to this)
661 * @param {Element} fixedPosition - is in fixed position mode
662 * @returns {Object} An object containing the offsets which will be applied to the popper
663 */
664function getReferenceOffsets(state, popper, reference, fixedPosition = null) {
665  const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference
vendor: 23,450 bytes, lines 665-1347
665);
666  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
667}
668
669/**
670 * Get the outer sizes of the given element (offset size + margins)
671 * @method
672 * @memberof Popper.Utils
673 * @argument {Element} element
674 * @returns {Object} object containing width and height properties
675 */
676function getOuterSizes(element) {
677  const window = element.ownerDocument.defaultView;
678  const styles = window.getComputedStyle(element);
679  const x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
680  const y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
681  const result = {
682    width: element.offsetWidth + y,
683    height: element.offsetHeight + x
684  };
685  return result;
686}
687
688/**
689 * Get the opposite placement of the given one
690 * @method
691 * @memberof Popper.Utils
692 * @argument {String} placement
693 * @returns {String} flipped placement
694 */
695function getOppositePlacement(placement) {
696  const hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
697  return placement.replace(/left|right|bottom|top/g, matched => hash[matched]);
698}
699
700/**
701 * Get offsets to the popper
702 * @method
703 * @memberof Popper.Utils
704 * @param {Object} position - CSS position the Popper will get applied
705 * @param {HTMLElement} popper - the popper element
706 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
707 * @param {String} placement - one of the valid placement options
708 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
709 */
710function getPopperOffsets(popper, referenceOffsets, placement) {
711  placement = placement.split('-')[0];
712
713  // Get popper node sizes
714  const popperRect = getOuterSizes(popper);
715
716  // Add position, width and height to our offsets object
717  const popperOffsets = {
718    width: popperRect.width,
719    height: popperRect.height
720  };
721
722  // depending by the popper placement we have to compute its offsets slightly differently
723  const isHoriz = ['right', 'left'].indexOf(placement) !== -1;
724  const mainSide = isHoriz ? 'top' : 'left';
725  const secondarySide = isHoriz ? 'left' : 'top';
726  const measurement = isHoriz ? 'height' : 'width';
727  const secondaryMeasurement = !isHoriz ? 'height' : 'width';
728
729  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
730  if (placement === secondarySide) {
731    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
732  } else {
733    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
734  }
735
736  return popperOffsets;
737}
738
739/**
740 * Mimics the `find` method of Array
741 * @method
742 * @memberof Popper.Utils
743 * @argument {Array} arr
744 * @argument prop
745 * @argument value
746 * @returns index or -1
747 */
748function find(arr, check) {
749  // use native find if supported
750  if (Array.prototype.find) {
751    return arr.find(check);
752  }
753
754  // use `filter` to obtain the same behavior of `find`
755  return arr.filter(check)[0];
756}
757
758/**
759 * Return the index of the matching object
760 * @method
761 * @memberof Popper.Utils
762 * @argument {Array} arr
763 * @argument prop
764 * @argument value
765 * @returns index or -1
766 */
767function findIndex(arr, prop, value) {
768  // use native findIndex if supported
769  if (Array.prototype.findIndex) {
770    return arr.findIndex(cur => cur[prop] === value);
771  }
772
773  // use `find` + `indexOf` if `findIndex` isn't supported
774  const match = find(arr, obj => obj[prop] === value);
775  return arr.indexOf(match);
776}
777
778/**
779 * Loop trough the list of modifiers and run them in order,
780 * each of them will then edit the data object.
781 * @method
782 * @memberof Popper.Utils
783 * @param {dataObject} data
784 * @param {Array} modifiers
785 * @param {String} ends - Optional modifier name used as stopper
786 * @returns {dataObject}
787 */
788function runModifiers(modifiers, data, ends) {
789  const modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
790
791  modifiersToRun.forEach(modifier => {
792    if (modifier['function']) {
793      // eslint-disable-line dot-notation
794      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
795    }
796    const fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
797    if (modifier.enabled && isFunction(fn)) {
798      // Add properties to offsets to make them a complete clientRect object
799      // we do this before each modifier to make sure the previous one doesn't
800      // mess with these values
801      data.offsets.popper = getClientRect(data.offsets.popper);
802      data.offsets.reference = getClientRect(data.offsets.reference);
803
804      data = fn(data, modifier);
805    }
806  });
807
808  return data;
809}
810
811/**
812 * Updates the position of the popper, computing the new offsets and applying
813 * the new style.<br />
814 * Prefer `scheduleUpdate` over `update` because of performance reasons.
815 * @method
816 * @memberof Popper
817 */
818function update() {
819  // if popper is destroyed, don't perform any further update
820  if (this.state.isDestroyed) {
821    return;
822  }
823
824  let data = {
825    instance: this,
826    styles: {},
827    arrowStyles: {},
828    attributes: {},
829    flipped: false,
830    offsets: {}
831  };
832
833  // compute reference element offsets
834  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
835
836  // compute auto placement, store placement inside the data object,
837  // modifiers will be able to edit `placement` if needed
838  // and refer to originalPlacement to know the original value
839  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
840
841  // store the computed placement inside `originalPlacement`
842  data.originalPlacement = data.placement;
843
844  data.positionFixed = this.options.positionFixed;
845
846  // compute the popper offsets
847  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
848
849  data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
850
851  // run the modifiers
852  data = runModifiers(this.modifiers, data);
853
854  // the first `update` will call `onCreate` callback
855  // the other ones will call `onUpdate` callback
856  if (!this.state.isCreated) {
857    this.state.isCreated = true;
858    this.options.onCreate(data);
859  } else {
860    this.options.onUpdate(data);
861  }
862}
863
864/**
865 * Helper used to know if the given modifier is enabled.
866 * @method
867 * @memberof Popper.Utils
868 * @returns {Boolean}
869 */
870function isModifierEnabled(modifiers, modifierName) {
871  return modifiers.some(({ name, enabled }) => enabled && name === modifierName);
872}
873
874/**
875 * Get the prefixed supported property name
876 * @method
877 * @memberof Popper.Utils
878 * @argument {String} property (camelCase)
879 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
880 */
881function getSupportedPropertyName(property) {
882  const prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
883  const upperProp = property.charAt(0).toUpperCase() + property.slice(1);
884
885  for (let i = 0; i < prefixes.length; i++) {
886    const prefix = prefixes[i];
887    const toCheck = prefix ? `${prefix}${upperProp}` : property;
888    if (typeof document.body.style[toCheck] !== 'undefined') {
889      return toCheck;
890    }
891  }
892  return null;
893}
894
895/**
896 * Destroys the popper.
897 * @method
898 * @memberof Popper
899 */
900function destroy() {
901  this.state.isDestroyed = true;
902
903  // touch DOM only if `applyStyle` modifier is enabled
904  if (isModifierEnabled(this.modifiers, 'applyStyle')) {
905    this.popper.removeAttribute('x-placement');
906    this.popper.style.position = '';
907    this.popper.style.top = '';
908    this.popper.style.left = '';
909    this.popper.style.right = '';
910    this.popper.style.bottom = '';
911    this.popper.style.willChange = '';
912    this.popper.style[getSupportedPropertyName('transform')] = '';
913  }
914
915  this.disableEventListeners();
916
917  // remove the popper if user explicity asked for the deletion on destroy
918  // do not use `remove` because IE11 doesn't support it
919  if (this.options.removeOnDestroy) {
920    this.popper.parentNode.removeChild(this.popper);
921  }
922  return this;
923}
924
925/**
926 * Get the window associated with the element
927 * @argument {Element} element
928 * @returns {Window}
929 */
930function getWindow(element) {
931  const ownerDocument = element.ownerDocument;
932  return ownerDocument ? ownerDocument.defaultView : window;
933}
934
935function attachToScrollParents(scrollParent, event, callback, scrollParents) {
936  const isBody = scrollParent.nodeName === 'BODY';
937  const target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
938  target.addEventListener(event, callback, { passive: true });
939
940  if (!isBody) {
941    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
942  }
943  scrollParents.push(target);
944}
945
946/**
947 * Setup needed event listeners used to update the popper position
948 * @method
949 * @memberof Popper.Utils
950 * @private
951 */
952function setupEventListeners(reference, options, state, updateBound) {
953  // Resize event listener on window
954  state.updateBound = updateBound;
955  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
956
957  // Scroll event listener on scroll parents
958  const scrollElement = getScrollParent(reference);
959  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
960  state.scrollElement = scrollElement;
961  state.eventsEnabled = true;
962
963  return state;
964}
965
966/**
967 * It will add resize/scroll events and start recalculating
968 * position of the popper element when they are triggered.
969 * @method
970 * @memberof Popper
971 */
972function enableEventListeners() {
973  if (!this.state.eventsEnabled) {
974    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
975  }
976}
977
978/**
979 * Remove event listeners used to update the popper position
980 * @method
981 * @memberof Popper.Utils
982 * @private
983 */
984function removeEventListeners(reference, state) {
985  // Remove resize event listener on window
986  getWindow(reference).removeEventListener('resize', state.updateBound);
987
988  // Remove scroll event listener on scroll parents
989  state.scrollParents.forEach(target => {
990    target.removeEventListener('scroll', state.updateBound);
991  });
992
993  // Reset state
994  state.updateBound = null;
995  state.scrollParents = [];
996  state.scrollElement = null;
997  state.eventsEnabled = false;
998  return state;
999}
1000
1001/**
1002 * It will remove resize/scroll events and won't recalculate popper position
1003 * when they are triggered. It also won't trigger `onUpdate` callback anymore,
1004 * unless you call `update` method manually.
1005 * @method
1006 * @memberof Popper
1007 */
1008function disableEventListeners() {
1009  if (this.state.eventsEnabled) {
1010    cancelAnimationFrame(this.scheduleUpdate);
1011    this.state = removeEventListeners(this.reference, this.state);
1012  }
1013}
1014
1015/**
1016 * Tells if a given input is a number
1017 * @method
1018 * @memberof Popper.Utils
1019 * @param {*} input to check
1020 * @return {Boolean}
1021 */
1022function isNumeric(n) {
1023  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
1024}
1025
1026/**
1027 * Set the style to the given popper
1028 * @method
1029 * @memberof Popper.Utils
1030 * @argument {Element} element - Element to apply the style to
1031 * @argument {Object} styles
1032 * Object with a list of properties and values which will be applied to the element
1033 */
1034function setStyles(element, styles) {
1035  Object.keys(styles).forEach(prop => {
1036    let unit = '';
1037    // add unit if the value is numeric and is one of the following
1038    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
1039      unit = 'px';
1040    }
1041    element.style[prop] = styles[prop] + unit;
1042  });
1043}
1044
1045/**
1046 * Set the attributes to the given popper
1047 * @method
1048 * @memberof Popper.Utils
1049 * @argument {Element} element - Element to apply the attributes to
1050 * @argument {Object} styles
1051 * Object with a list of properties and values which will be applied to the element
1052 */
1053function setAttributes(element, attributes) {
1054  Object.keys(attributes).forEach(function (prop) {
1055    const value = attributes[prop];
1056    if (value !== false) {
1057      element.setAttribute(prop, attributes[prop]);
1058    } else {
1059      element.removeAttribute(prop);
1060    }
1061  });
1062}
1063
1064/**
1065 * @function
1066 * @memberof Modifiers
1067 * @argument {Object} data - The data object generated by `update` method
1068 * @argument {Object} data.styles - List of style properties - values to apply to popper element
1069 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
1070 * @argument {Object} options - Modifiers configuration and options
1071 * @returns {Object} The same data object
1072 */
1073function applyStyle(data) {
1074  // any property present in `data.styles` will be applied to the popper,
1075  // in this way we can make the 3rd party modifiers add custom styles to it
1076  // Be aware, modifiers could override the properties defined in the previous
1077  // lines of this modifier!
1078  setStyles(data.instance.popper, data.styles);
1079
1080  // any property present in `data.attributes` will be applied to the popper,
1081  // they will be set as HTML attributes of the element
1082  setAttributes(data.instance.popper, data.attributes);
1083
1084  // if arrowElement is defined and arrowStyles has some properties
1085  if (data.arrowElement && Object.keys(data.arrowStyles).length) {
1086    setStyles(data.arrowElement, data.arrowStyles);
1087  }
1088
1089  return data;
1090}
1091
1092/**
1093 * Set the x-placement attribute before everything else because it could be used
1094 * to add margins to the popper margins needs to be calculated to get the
1095 * correct popper offsets.
1096 * @method
1097 * @memberof Popper.modifiers
1098 * @param {HTMLElement} reference - The reference element used to position the popper
1099 * @param {HTMLElement} popper - The HTML element used as popper
1100 * @param {Object} options - Popper.js options
1101 */
1102function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
1103  // compute reference element offsets
1104  const referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
1105
1106  // compute auto placement, store placement inside the data object,
1107  // modifiers will be able to edit `placement` if needed
1108  // and refer to originalPlacement to know the original value
1109  const placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
1110
1111  popper.setAttribute('x-placement', placement);
1112
1113  // Apply `position` to popper before anything else because
1114  // without the position applied we can't guarantee correct computations
1115  setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
1116
1117  return options;
1118}
1119
1120/**
1121 * @function
1122 * @memberof Popper.Utils
1123 * @argument {Object} data - The data object generated by `update` method
1124 * @argument {Boolean} shouldRound - If the offsets should be rounded at all
1125 * @returns {Object} The popper's position offsets rounded
1126 *
1127 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
1128 * good as it can be within reason.
1129 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
1130 *
1131 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
1132 * as well on High DPI screens).
1133 *
1134 * Firefox prefers no rounding for positioning and does not have blurriness on
1135 * high DPI screens.
1136 *
1137 * Only horizontal placement and left/right values need to be considered.
1138 */
1139function getRoundedOffsets(data, shouldRound) {
1140  const { popper, reference } = data.offsets;
1141  const { round, floor } = Math;
1142  const noRound = v => v;
1143
1144  const referenceWidth = round(reference.width);
1145  const popperWidth = round(popper.width);
1146
1147  const isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
1148  const isVariation = data.placement.indexOf('-') !== -1;
1149  const sameWidthParity = referenceWidth % 2 === popperWidth % 2;
1150  const bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
1151
1152  const horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
1153  const verticalToInteger = !shouldRound ? noRound : round;
1154
1155  return {
1156    left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
1157    top: verticalToInteger(popper.top),
1158    bottom: verticalToInteger(popper.bottom),
1159    right: horizontalToInteger(popper.right)
1160  };
1161}
1162
1163const isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
1164
1165/**
1166 * @function
1167 * @memberof Modifiers
1168 * @argument {Object} data - The data object generated by `update` method
1169 * @argument {Object} options - Modifiers configuration and options
1170 * @returns {Object} The data object, properly modified
1171 */
1172function computeStyle(data, options) {
1173  const { x, y } = options;
1174  const { popper } = data.offsets;
1175
1176  // Remove this legacy support in Popper.js v2
1177  const legacyGpuAccelerationOption = find(data.instance.modifiers, modifier => modifier.name === 'applyStyle').gpuAcceleration;
1178  if (legacyGpuAccelerationOption !== undefined) {
1179    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
1180  }
1181  const gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
1182
1183  const offsetParent = getOffsetParent(data.instance.popper);
1184  const offsetParentRect = getBoundingClientRect(offsetParent);
1185
1186  // Styles
1187  const styles = {
1188    position: popper.position
1189  };
1190
1191  const offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
1192
1193  const sideA = x === 'bottom' ? 'top' : 'bottom';
1194  const sideB = y === 'right' ? 'left' : 'right';
1195
1196  // if gpuAcceleration is set to `true` and transform is supported,
1197  //  we use `translate3d` to apply the position to the popper we
1198  // automatically use the supported prefixed version if needed
1199  const prefixedProperty = getSupportedPropertyName('transform');
1200
1201  // now, let's make a step back and look at this code closely (wtf?)
1202  // If the content of the popper grows once it's been positioned, it
1203  // may happen that the popper gets misplaced because of the new content
1204  // overflowing its reference element
1205  // To avoid this problem, we provide two options (x and y), which allow
1206  // the consumer to define the offset origin.
1207  // If we position a popper on top of a reference element, we can set
1208  // `x` to `top` to make the popper grow towards its top instead of
1209  // its bottom.
1210  let left, top;
1211  if (sideA === 'bottom') {
1212    // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
1213    // and not the bottom of the html element
1214    if (offsetParent.nodeName === 'HTML') {
1215      top = -offsetParent.clientHeight + offsets.bottom;
1216    } else {
1217      top = -offsetParentRect.height + offsets.bottom;
1218    }
1219  } else {
1220    top = offsets.top;
1221  }
1222  if (sideB === 'right') {
1223    if (offsetParent.nodeName === 'HTML') {
1224      left = -offsetParent.clientWidth + offsets.right;
1225    } else {
1226      left = -offsetParentRect.width + offsets.right;
1227    }
1228  } else {
1229    left = offsets.left;
1230  }
1231  if (gpuAcceleration && prefixedProperty) {
1232    styles[prefixedProperty] = `translate3d(${left}px, ${top}px, 0)`;
1233    styles[sideA] = 0;
1234    styles[sideB] = 0;
1235    styles.willChange = 'transform';
1236  } else {
1237    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
1238    const invertTop = sideA === 'bottom' ? -1 : 1;
1239    const invertLeft = sideB === 'right' ? -1 : 1;
1240    styles[sideA] = top * invertTop;
1241    styles[sideB] = left * invertLeft;
1242    styles.willChange = `${sideA}, ${sideB}`;
1243  }
1244
1245  // Attributes
1246  const attributes = {
1247    'x-placement': data.placement
1248  };
1249
1250  // Update `data` attributes, styles and arrowStyles
1251  data.attributes = _extends({}, attributes, data.attributes);
1252  data.styles = _extends({}, styles, data.styles);
1253  data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
1254
1255  return data;
1256}
1257
1258/**
1259 * Helper used to know if the given modifier depends from another one.<br />
1260 * It checks if the needed modifier is listed and enabled.
1261 * @method
1262 * @memberof Popper.Utils
1263 * @param {Array} modifiers - list of modifiers
1264 * @param {String} requestingName - name of requesting modifier
1265 * @param {String} requestedName - name of requested modifier
1266 * @returns {Boolean}
1267 */
1268function isModifierRequired(modifiers, requestingName, requestedName) {
1269  const requesting = find(modifiers, ({ name }) => name === requestingName);
1270
1271  const isRequired = !!requesting && modifiers.some(modifier => {
1272    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
1273  });
1274
1275  if (!isRequired) {
1276    const requesting = `\`${requestingName}\``;
1277    const requested = `\`${requestedName}\``;
1278    console.warn(`${requested} modifier is required by ${requesting} modifier in order to work, be sure to include it before ${requesting}!`);
1279  }
1280  return isRequired;
1281}
1282
1283/**
1284 * @function
1285 * @memberof Modifiers
1286 * @argument {Object} data - The data object generated by update method
1287 * @argument {Object} options - Modifiers configuration and options
1288 * @returns {Object} The data object, properly modified
1289 */
1290function arrow(data, options) {
1291  // arrow depends on keepTogether in order to work
1292  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
1293    return data;
1294  }
1295
1296  let arrowElement = options.element;
1297
1298  // if arrowElement is a string, suppose it's a CSS selector
1299  if (typeof arrowElement === 'string') {
1300    arrowElement = data.instance.popper.querySelector(arrowElement);
1301
1302    // if arrowElement is not found, don't run the modifier
1303    if (!arrowElement) {
1304      return data;
1305    }
1306  } else {
1307    // if the arrowElement isn't a query selector we must check that the
1308    // provided DOM node is child of its popper node
1309    if (!data.instance.popper.contains(arrowElement)) {
1310      console.warn('WARNING: `arrow.element` must be child of its popper element!');
1311      return data;
1312    }
1313  }
1314
1315  const placement = data.placement.split('-')[0];
1316  const { popper, reference } = data.offsets;
1317  const isVertical = ['left', 'right'].indexOf(placement) !== -1;
1318
1319  const len = isVertical ? 'height' : 'width';
1320  const sideCapitalized = isVertical ? 'Top' : 'Left';
1321  const side = sideCapitalized.toLowerCase();
1322  const altSide = isVertical ? 'left' : 'top';
1323  const opSide = isVertical ? 'bottom' : 'right';
1324  const arrowElementSize = getOuterSizes(arrowElement)[len];
1325
1326  //
1327  // extends keepTogether behavior making sure the popper and its
1328  // reference have enough pixels in conjunction
1329  //
1330
1331  // top/left side
1332  if (reference[opSide] - arrowElementSize < popper[side]) {
1333    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
1334  }
1335  // bottom/right side
1336  if (reference[side] + arrowElementSize > popper[opSide]) {
1337    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
1338  }
1339  data.offsets.popper = getClientRect(data.offsets.popper);
1340
1341  // compute center of the popper
1342  const center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
1343
1344  // Compute the sideValue using the updated popper offsets
1345  // take popper margin in account because we don't have this info available
1346  const css = getStyleComputedProperty(data.instance.popper);
1347  const popperMarginSide = parseFloat(css[`margin${sideCapitalized}`]
1347, 10);
1348  const popperBorderSide = parseFloat(css[`border${sideCapitalized}Width`], 10
vendor: 20,969 bytes, lines 1348-1936
1348);
1349  let sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
1350
1351  // prevent arrowElement from being placed not contiguously to its popper
1352  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
1353
1354  data.arrowElement = arrowElement;
1355  data.offsets.arrow = {
1356    [side]: Math.round(sideValue),
1357    [altSide]: '' // make sure to unset any eventual altSide value from the DOM node
1358  };
1359
1360  return data;
1361}
1362
1363/**
1364 * Get the opposite placement variation of the given one
1365 * @method
1366 * @memberof Popper.Utils
1367 * @argument {String} placement variation
1368 * @returns {String} flipped placement variation
1369 */
1370function getOppositeVariation(variation) {
1371  if (variation === 'end') {
1372    return 'start';
1373  } else if (variation === 'start') {
1374    return 'end';
1375  }
1376  return variation;
1377}
1378
1379/**
1380 * List of accepted placements to use as values of the `placement` option.<br />
1381 * Valid placements are:
1382 * - `auto`
1383 * - `top`
1384 * - `right`
1385 * - `bottom`
1386 * - `left`
1387 *
1388 * Each placement can have a variation from this list:
1389 * - `-start`
1390 * - `-end`
1391 *
1392 * Variations are interpreted easily if you think of them as the left to right
1393 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
1394 * is right.<br />
1395 * Vertically (`left` and `right`), `start` is top and `end` is bottom.
1396 *
1397 * Some valid examples are:
1398 * - `top-end` (on top of reference, right aligned)
1399 * - `right-start` (on right of reference, top aligned)
1400 * - `bottom` (on bottom, centered)
1401 * - `auto-end` (on the side with more space available, alignment depends by placement)
1402 *
1403 * @static
1404 * @type {Array}
1405 * @enum {String}
1406 * @readonly
1407 * @method placements
1408 * @memberof Popper
1409 */
1410var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
1411
1412// Get rid of `auto` `auto-start` and `auto-end`
1413const validPlacements = placements.slice(3);
1414
1415/**
1416 * Given an initial placement, returns all the subsequent placements
1417 * clockwise (or counter-clockwise).
1418 *
1419 * @method
1420 * @memberof Popper.Utils
1421 * @argument {String} placement - A valid placement (it accepts variations)
1422 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
1423 * @returns {Array} placements including their variations
1424 */
1425function clockwise(placement, counter = false) {
1426  const index = validPlacements.indexOf(placement);
1427  const arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
1428  return counter ? arr.reverse() : arr;
1429}
1430
1431const BEHAVIORS = {
1432  FLIP: 'flip',
1433  CLOCKWISE: 'clockwise',
1434  COUNTERCLOCKWISE: 'counterclockwise'
1435};
1436
1437/**
1438 * @function
1439 * @memberof Modifiers
1440 * @argument {Object} data - The data object generated by update method
1441 * @argument {Object} options - Modifiers configuration and options
1442 * @returns {Object} The data object, properly modified
1443 */
1444function flip(data, options) {
1445  // if `inner` modifier is enabled, we can't use the `flip` modifier
1446  if (isModifierEnabled(data.instance.modifiers, 'inner')) {
1447    return data;
1448  }
1449
1450  if (data.flipped && data.placement === data.originalPlacement) {
1451    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
1452    return data;
1453  }
1454
1455  const boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
1456
1457  let placement = data.placement.split('-')[0];
1458  let placementOpposite = getOppositePlacement(placement);
1459  let variation = data.placement.split('-')[1] || '';
1460
1461  let flipOrder = [];
1462
1463  switch (options.behavior) {
1464    case BEHAVIORS.FLIP:
1465      flipOrder = [placement, placementOpposite];
1466      break;
1467    case BEHAVIORS.CLOCKWISE:
1468      flipOrder = clockwise(placement);
1469      break;
1470    case BEHAVIORS.COUNTERCLOCKWISE:
1471      flipOrder = clockwise(placement, true);
1472      break;
1473    default:
1474      flipOrder = options.behavior;
1475  }
1476
1477  flipOrder.forEach((step, index) => {
1478    if (placement !== step || flipOrder.length === index + 1) {
1479      return data;
1480    }
1481
1482    placement = data.placement.split('-')[0];
1483    placementOpposite = getOppositePlacement(placement);
1484
1485    const popperOffsets = data.offsets.popper;
1486    const refOffsets = data.offsets.reference;
1487
1488    // using floor because the reference offsets may contain decimals we are not going to consider here
1489    const floor = Math.floor;
1490    const overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
1491
1492    const overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
1493    const overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
1494    const overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
1495    const overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
1496
1497    const overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
1498
1499    // flip the variation if required
1500    const isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1501
1502    // flips variation if reference element overflows boundaries
1503    const flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
1504
1505    // flips variation if popper content overflows boundaries
1506    const flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
1507
1508    const flippedVariation = flippedVariationByRef || flippedVariationByContent;
1509
1510    if (overlapsRef || overflowsBoundaries || flippedVariation) {
1511      // this boolean to detect any flip loop
1512      data.flipped = true;
1513
1514      if (overlapsRef || overflowsBoundaries) {
1515        placement = flipOrder[index + 1];
1516      }
1517
1518      if (flippedVariation) {
1519        variation = getOppositeVariation(variation);
1520      }
1521
1522      data.placement = placement + (variation ? '-' + variation : '');
1523
1524      // this object contains `position`, we want to preserve it along with
1525      // any additional property we may add in the future
1526      data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
1527
1528      data = runModifiers(data.instance.modifiers, data, 'flip');
1529    }
1530  });
1531  return data;
1532}
1533
1534/**
1535 * @function
1536 * @memberof Modifiers
1537 * @argument {Object} data - The data object generated by update method
1538 * @argument {Object} options - Modifiers configuration and options
1539 * @returns {Object} The data object, properly modified
1540 */
1541function keepTogether(data) {
1542  const { popper, reference } = data.offsets;
1543  const placement = data.placement.split('-')[0];
1544  const floor = Math.floor;
1545  const isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
1546  const side = isVertical ? 'right' : 'bottom';
1547  const opSide = isVertical ? 'left' : 'top';
1548  const measurement = isVertical ? 'width' : 'height';
1549
1550  if (popper[side] < floor(reference[opSide])) {
1551    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
1552  }
1553  if (popper[opSide] > floor(reference[side])) {
1554    data.offsets.popper[opSide] = floor(reference[side]);
1555  }
1556
1557  return data;
1558}
1559
1560/**
1561 * Converts a string containing value + unit into a px value number
1562 * @function
1563 * @memberof {modifiers~offset}
1564 * @private
1565 * @argument {String} str - Value + unit string
1566 * @argument {String} measurement - `height` or `width`
1567 * @argument {Object} popperOffsets
1568 * @argument {Object} referenceOffsets
1569 * @returns {Number|String}
1570 * Value in pixels, or original string if no values were extracted
1571 */
1572function toValue(str, measurement, popperOffsets, referenceOffsets) {
1573  // separate value from unit
1574  const split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
1575  const value = +split[1];
1576  const unit = split[2];
1577
1578  // If it's not a number it's an operator, I guess
1579  if (!value) {
1580    return str;
1581  }
1582
1583  if (unit.indexOf('%') === 0) {
1584    let element;
1585    switch (unit) {
1586      case '%p':
1587        element = popperOffsets;
1588        break;
1589      case '%':
1590      case '%r':
1591      default:
1592        element = referenceOffsets;
1593    }
1594
1595    const rect = getClientRect(element);
1596    return rect[measurement] / 100 * value;
1597  } else if (unit === 'vh' || unit === 'vw') {
1598    // if is a vh or vw, we calculate the size based on the viewport
1599    let size;
1600    if (unit === 'vh') {
1601      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
1602    } else {
1603      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
1604    }
1605    return size / 100 * value;
1606  } else {
1607    // if is an explicit pixel unit, we get rid of the unit and keep the value
1608    // if is an implicit unit, it's px, and we return just the value
1609    return value;
1610  }
1611}
1612
1613/**
1614 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
1615 * @function
1616 * @memberof {modifiers~offset}
1617 * @private
1618 * @argument {String} offset
1619 * @argument {Object} popperOffsets
1620 * @argument {Object} referenceOffsets
1621 * @argument {String} basePlacement
1622 * @returns {Array} a two cells array with x and y offsets in numbers
1623 */
1624function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
1625  const offsets = [0, 0];
1626
1627  // Use height if placement is left or right and index is 0 otherwise use width
1628  // in this way the first offset will use an axis and the second one
1629  // will use the other one
1630  const useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
1631
1632  // Split the offset string to obtain a list of values and operands
1633  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
1634  const fragments = offset.split(/(\+|\-)/).map(frag => frag.trim());
1635
1636  // Detect if the offset string contains a pair of values or a single one
1637  // they could be separated by comma or space
1638  const divider = fragments.indexOf(find(fragments, frag => frag.search(/,|\s/) !== -1));
1639
1640  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
1641    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
1642  }
1643
1644  // If divider is found, we divide the list of values and operands to divide
1645  // them by ofset X and Y.
1646  const splitRegex = /\s*,\s*|\s+/;
1647  let ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
1648
1649  // Convert the values with units to absolute pixels to allow our computations
1650  ops = ops.map((op, index) => {
1651    // Most of the units rely on the orientation of the popper
1652    const measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
1653    let mergeWithPrevious = false;
1654    return op
1655    // This aggregates any `+` or `-` sign that aren't considered operators
1656    // e.g.: 10 + +5 => [10, +, +5]
1657    .reduce((a, b) => {
1658      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
1659        a[a.length - 1] = b;
1660        mergeWithPrevious = true;
1661        return a;
1662      } else if (mergeWithPrevious) {
1663        a[a.length - 1] += b;
1664        mergeWithPrevious = false;
1665        return a;
1666      } else {
1667        return a.concat(b);
1668      }
1669    }, [])
1670    // Here we convert the string values into number values (in px)
1671    .map(str => toValue(str, measurement, popperOffsets, referenceOffsets));
1672  });
1673
1674  // Loop trough the offsets arrays and execute the operations
1675  ops.forEach((op, index) => {
1676    op.forEach((frag, index2) => {
1677      if (isNumeric(frag)) {
1678        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
1679      }
1680    });
1681  });
1682  return offsets;
1683}
1684
1685/**
1686 * @function
1687 * @memberof Modifiers
1688 * @argument {Object} data - The data object generated by update method
1689 * @argument {Object} options - Modifiers configuration and options
1690 * @argument {Number|String} options.offset=0
1691 * The offset value as described in the modifier description
1692 * @returns {Object} The data object, properly modified
1693 */
1694function offset(data, { offset }) {
1695  const { placement, offsets: { popper, reference } } = data;
1696  const basePlacement = placement.split('-')[0];
1697
1698  let offsets;
1699  if (isNumeric(+offset)) {
1700    offsets = [+offset, 0];
1701  } else {
1702    offsets = parseOffset(offset, popper, reference, basePlacement);
1703  }
1704
1705  if (basePlacement === 'left') {
1706    popper.top += offsets[0];
1707    popper.left -= offsets[1];
1708  } else if (basePlacement === 'right') {
1709    popper.top += offsets[0];
1710    popper.left += offsets[1];
1711  } else if (basePlacement === 'top') {
1712    popper.left += offsets[0];
1713    popper.top -= offsets[1];
1714  } else if (basePlacement === 'bottom') {
1715    popper.left += offsets[0];
1716    popper.top += offsets[1];
1717  }
1718
1719  data.popper = popper;
1720  return data;
1721}
1722
1723/**
1724 * @function
1725 * @memberof Modifiers
1726 * @argument {Object} data - The data object generated by `update` method
1727 * @argument {Object} options - Modifiers configuration and options
1728 * @returns {Object} The data object, properly modified
1729 */
1730function preventOverflow(data, options) {
1731  let boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
1732
1733  // If offsetParent is the reference element, we really want to
1734  // go one step up and use the next offsetParent as reference to
1735  // avoid to make this modifier completely useless and look like broken
1736  if (data.instance.reference === boundariesElement) {
1737    boundariesElement = getOffsetParent(boundariesElement);
1738  }
1739
1740  // NOTE: DOM access here
1741  // resets the popper's position so that the document size can be calculated excluding
1742  // the size of the popper element itself
1743  const transformProp = getSupportedPropertyName('transform');
1744  const popperStyles = data.instance.popper.style; // assignment to help minification
1745  const { top, left, [transformProp]: transform } = popperStyles;
1746  popperStyles.top = '';
1747  popperStyles.left = '';
1748  popperStyles[transformProp] = '';
1749
1750  const boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
1751
1752  // NOTE: DOM access here
1753  // restores the original style properties after the offsets have been computed
1754  popperStyles.top = top;
1755  popperStyles.left = left;
1756  popperStyles[transformProp] = transform;
1757
1758  options.boundaries = boundaries;
1759
1760  const order = options.priority;
1761  let popper = data.offsets.popper;
1762
1763  const check = {
1764    primary(placement) {
1765      let value = popper[placement];
1766      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
1767        value = Math.max(popper[placement], boundaries[placement]);
1768      }
1769      return { [placement]: value };
1770    },
1771    secondary(placement) {
1772      const mainSide = placement === 'right' ? 'left' : 'top';
1773      let value = popper[mainSide];
1774      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
1775        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
1776      }
1777      return { [mainSide]: value };
1778    }
1779  };
1780
1781  order.forEach(placement => {
1782    const side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
1783    popper = _extends({}, popper, check[side](placement));
1784  });
1785
1786  data.offsets.popper = popper;
1787
1788  return data;
1789}
1790
1791/**
1792 * @function
1793 * @memberof Modifiers
1794 * @argument {Object} data - The data object generated by `update` method
1795 * @argument {Object} options - Modifiers configuration and options
1796 * @returns {Object} The data object, properly modified
1797 */
1798function shift(data) {
1799  const placement = data.placement;
1800  const basePlacement = placement.split('-')[0];
1801  const shiftvariation = placement.split('-')[1];
1802
1803  // if shift shiftvariation is specified, run the modifier
1804  if (shiftvariation) {
1805    const { reference, popper } = data.offsets;
1806    const isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
1807    const side = isVertical ? 'left' : 'top';
1808    const measurement = isVertical ? 'width' : 'height';
1809
1810    const shiftOffsets = {
1811      start: { [side]: reference[side] },
1812      end: {
1813        [side]: reference[side] + reference[measurement] - popper[measurement]
1814      }
1815    };
1816
1817    data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
1818  }
1819
1820  return data;
1821}
1822
1823/**
1824 * @function
1825 * @memberof Modifiers
1826 * @argument {Object} data - The data object generated by update method
1827 * @argument {Object} options - Modifiers configuration and options
1828 * @returns {Object} The data object, properly modified
1829 */
1830function hide(data) {
1831  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
1832    return data;
1833  }
1834
1835  const refRect = data.offsets.reference;
1836  const bound = find(data.instance.modifiers, modifier => modifier.name === 'preventOverflow').boundaries;
1837
1838  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
1839    // Avoid unnecessary DOM access if visibility hasn't changed
1840    if (data.hide === true) {
1841      return data;
1842    }
1843
1844    data.hide = true;
1845    data.attributes['x-out-of-boundaries'] = '';
1846  } else {
1847    // Avoid unnecessary DOM access if visibility hasn't changed
1848    if (data.hide === false) {
1849      return data;
1850    }
1851
1852    data.hide = false;
1853    data.attributes['x-out-of-boundaries'] = false;
1854  }
1855
1856  return data;
1857}
1858
1859/**
1860 * @function
1861 * @memberof Modifiers
1862 * @argument {Object} data - The data object generated by `update` method
1863 * @argument {Object} options - Modifiers configuration and options
1864 * @returns {Object} The data object, properly modified
1865 */
1866function inner(data) {
1867  const placement = data.placement;
1868  const basePlacement = placement.split('-')[0];
1869  const { popper, reference } = data.offsets;
1870  const isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
1871
1872  const subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
1873
1874  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
1875
1876  data.placement = getOppositePlacement(placement);
1877  data.offsets.popper = getClientRect(popper);
1878
1879  return data;
1880}
1881
1882/**
1883 * Modifier function, each modifier can have a function of this type assigned
1884 * to its `fn` property.<br />
1885 * These functions will be called on each update, this means that you must
1886 * make sure they are performant enough to avoid performance bottlenecks.
1887 *
1888 * @function ModifierFn
1889 * @argument {dataObject} data - The data object generated by `update` method
1890 * @argument {Object} options - Modifiers configuration and options
1891 * @returns {dataObject} The data object, properly modified
1892 */
1893
1894/**
1895 * Modifiers are plugins used to alter the behavior of your poppers.<br />
1896 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
1897 * needed by the library.
1898 *
1899 * Usually you don't want to override the `order`, `fn` and `onLoad` props.
1900 * All the other properties are configurations that could be tweaked.
1901 * @namespace modifiers
1902 */
1903var modifiers = {
1904  /**
1905   * Modifier used to shift the popper on the start or end of its reference
1906   * element.<br />
1907   * It will read the variation of the `placement` property.<br />
1908   * It can be one either `-end` or `-start`.
1909   * @memberof modifiers
1910   * @inner
1911   */
1912  shift: {
1913    /** @prop {number} order=100 - Index used to define the order of execution */
1914    order: 100,
1915    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
1916    enabled: true,
1917    /** @prop {ModifierFn} */
1918    fn: shift
1919  },
1920
1921  /**
1922   * The `offset` modifier can shift your popper on both its axis.
1923   *
1924   * It accepts the following units:
1925   * - `px` or unit-less, interpreted as pixels
1926   * - `%` or `%r`, percentage relative to the length of the reference element
1927   * - `%p`, percentage relative to the length of the popper element
1928   * - `vw`, CSS viewport width unit
1929   * - `vh`, CSS viewport height unit
1930   *
1931   * For length is intended the main axis relative to the placement of the popper.<br />
1932   * This means that if the placement is `top` or `bottom`, the length will be the
1933   * `width`. In case of `left` or `right`, it will be the `height`.
1934   *
1935   * You can provide a single value (as `Number` or `String`), or a pair of values
1936   * as `String` divided by a comma or one (or more) white space
vendor: 9,957 bytes, lines 1936-2208
1936s.<br />
1937   * The latter is a deprecated method because it leads to confusion and will be
1938   * removed in v2.<br />
1939   * Additionally, it accepts additions and subtractions between different units.
1940   * Note that multiplications and divisions aren't supported.
1941   *
1942   * Valid examples are:
1943   * ```
1944   * 10
1945   * '10%'
1946   * '10, 10'
1947   * '10%, 10'
1948   * '10 + 10%'
1949   * '10 - 5vh + 3%'
1950   * '-10px + 5vh, 5px - 6%'
1951   * ```
1952   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
1953   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
1954   * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
1955   *
1956   * @memberof modifiers
1957   * @inner
1958   */
1959  offset: {
1960    /** @prop {number} order=200 - Index used to define the order of execution */
1961    order: 200,
1962    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
1963    enabled: true,
1964    /** @prop {ModifierFn} */
1965    fn: offset,
1966    /** @prop {Number|String} offset=0
1967     * The offset value as described in the modifier description
1968     */
1969    offset: 0
1970  },
1971
1972  /**
1973   * Modifier used to prevent the popper from being positioned outside the boundary.
1974   *
1975   * A scenario exists where the reference itself is not within the boundaries.<br />
1976   * We can say it has "escaped the boundaries" — or just "escaped".<br />
1977   * In this case we need to decide whether the popper should either:
1978   *
1979   * - detach from the reference and remain "trapped" in the boundaries, or
1980   * - if it should ignore the boundary and "escape with its reference"
1981   *
1982   * When `escapeWithReference` is set to`true` and reference is completely
1983   * outside its boundaries, the popper will overflow (or completely leave)
1984   * the boundaries in order to remain attached to the edge of the reference.
1985   *
1986   * @memberof modifiers
1987   * @inner
1988   */
1989  preventOverflow: {
1990    /** @prop {number} order=300 - Index used to define the order of execution */
1991    order: 300,
1992    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
1993    enabled: true,
1994    /** @prop {ModifierFn} */
1995    fn: preventOverflow,
1996    /**
1997     * @prop {Array} [priority=['left','right','top','bottom']]
1998     * Popper will try to prevent overflow following these priorities by default,
1999     * then, it could overflow on the left and on top of the `boundariesElement`
2000     */
2001    priority: ['left', 'right', 'top', 'bottom'],
2002    /**
2003     * @prop {number} padding=5
2004     * Amount of pixel used to define a minimum distance between the boundaries
2005     * and the popper. This makes sure the popper always has a little padding
2006     * between the edges of its container
2007     */
2008    padding: 5,
2009    /**
2010     * @prop {String|HTMLElement} boundariesElement='scrollParent'
2011     * Boundaries used by the modifier. Can be `scrollParent`, `window`,
2012     * `viewport` or any DOM element.
2013     */
2014    boundariesElement: 'scrollParent'
2015  },
2016
2017  /**
2018   * Modifier used to make sure the reference and its popper stay near each other
2019   * without leaving any gap between the two. Especially useful when the arrow is
2020   * enabled and you want to ensure that it points to its reference element.
2021   * It cares only about the first axis. You can still have poppers with margin
2022   * between the popper and its reference element.
2023   * @memberof modifiers
2024   * @inner
2025   */
2026  keepTogether: {
2027    /** @prop {number} order=400 - Index used to define the order of execution */
2028    order: 400,
2029    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2030    enabled: true,
2031    /** @prop {ModifierFn} */
2032    fn: keepTogether
2033  },
2034
2035  /**
2036   * This modifier is used to move the `arrowElement` of the popper to make
2037   * sure it is positioned between the reference element and its popper element.
2038   * It will read the outer size of the `arrowElement` node to detect how many
2039   * pixels of conjunction are needed.
2040   *
2041   * It has no effect if no `arrowElement` is provided.
2042   * @memberof modifiers
2043   * @inner
2044   */
2045  arrow: {
2046    /** @prop {number} order=500 - Index used to define the order of execution */
2047    order: 500,
2048    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2049    enabled: true,
2050    /** @prop {ModifierFn} */
2051    fn: arrow,
2052    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
2053    element: '[x-arrow]'
2054  },
2055
2056  /**
2057   * Modifier used to flip the popper's placement when it starts to overlap its
2058   * reference element.
2059   *
2060   * Requires the `preventOverflow` modifier before it in order to work.
2061   *
2062   * **NOTE:** this modifier will interrupt the current update cycle and will
2063   * restart it if it detects the need to flip the placement.
2064   * @memberof modifiers
2065   * @inner
2066   */
2067  flip: {
2068    /** @prop {number} order=600 - Index used to define the order of execution */
2069    order: 600,
2070    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2071    enabled: true,
2072    /** @prop {ModifierFn} */
2073    fn: flip,
2074    /**
2075     * @prop {String|Array} behavior='flip'
2076     * The behavior used to change the popper's placement. It can be one of
2077     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
2078     * placements (with optional variations)
2079     */
2080    behavior: 'flip',
2081    /**
2082     * @prop {number} padding=5
2083     * The popper will flip if it hits the edges of the `boundariesElement`
2084     */
2085    padding: 5,
2086    /**
2087     * @prop {String|HTMLElement} boundariesElement='viewport'
2088     * The element which will define the boundaries of the popper position.
2089     * The popper will never be placed outside of the defined boundaries
2090     * (except if `keepTogether` is enabled)
2091     */
2092    boundariesElement: 'viewport',
2093    /**
2094     * @prop {Boolean} flipVariations=false
2095     * The popper will switch placement variation between `-start` and `-end` when
2096     * the reference element overlaps its boundaries.
2097     *
2098     * The original placement should have a set variation.
2099     */
2100    flipVariations: false,
2101    /**
2102     * @prop {Boolean} flipVariationsByContent=false
2103     * The popper will switch placement variation between `-start` and `-end` when
2104     * the popper element overlaps its reference boundaries.
2105     *
2106     * The original placement should have a set variation.
2107     */
2108    flipVariationsByContent: false
2109  },
2110
2111  /**
2112   * Modifier used to make the popper flow toward the inner of the reference element.
2113   * By default, when this modifier is disabled, the popper will be placed outside
2114   * the reference element.
2115   * @memberof modifiers
2116   * @inner
2117   */
2118  inner: {
2119    /** @prop {number} order=700 - Index used to define the order of execution */
2120    order: 700,
2121    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
2122    enabled: false,
2123    /** @prop {ModifierFn} */
2124    fn: inner
2125  },
2126
2127  /**
2128   * Modifier used to hide the popper when its reference element is outside of the
2129   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
2130   * be used to hide with a CSS selector the popper when its reference is
2131   * out of boundaries.
2132   *
2133   * Requires the `preventOverflow` modifier before it in order to work.
2134   * @memberof modifiers
2135   * @inner
2136   */
2137  hide: {
2138    /** @prop {number} order=800 - Index used to define the order of execution */
2139    order: 800,
2140    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2141    enabled: true,
2142    /** @prop {ModifierFn} */
2143    fn: hide
2144  },
2145
2146  /**
2147   * Computes the style that will be applied to the popper element to gets
2148   * properly positioned.
2149   *
2150   * Note that this modifier will not touch the DOM, it just prepares the styles
2151   * so that `applyStyle` modifier can apply it. This separation is useful
2152   * in case you need to replace `applyStyle` with a custom implementation.
2153   *
2154   * This modifier has `850` as `order` value to maintain backward compatibility
2155   * with previous versions of Popper.js. Expect the modifiers ordering method
2156   * to change in future major versions of the library.
2157   *
2158   * @memberof modifiers
2159   * @inner
2160   */
2161  computeStyle: {
2162    /** @prop {number} order=850 - Index used to define the order of execution */
2163    order: 850,
2164    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2165    enabled: true,
2166    /** @prop {ModifierFn} */
2167    fn: computeStyle,
2168    /**
2169     * @prop {Boolean} gpuAcceleration=true
2170     * If true, it uses the CSS 3D transformation to position the popper.
2171     * Otherwise, it will use the `top` and `left` properties
2172     */
2173    gpuAcceleration: true,
2174    /**
2175     * @prop {string} [x='bottom']
2176     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
2177     * Change this if your popper should grow in a direction different from `bottom`
2178     */
2179    x: 'bottom',
2180    /**
2181     * @prop {string} [x='left']
2182     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
2183     * Change this if your popper should grow in a direction different from `right`
2184     */
2185    y: 'right'
2186  },
2187
2188  /**
2189   * Applies the computed styles to the popper element.
2190   *
2191   * All the DOM manipulations are limited to this modifier. This is useful in case
2192   * you want to integrate Popper.js inside a framework or view library and you
2193   * want to delegate all the DOM manipulations to it.
2194   *
2195   * Note that if you disable this modifier, you must make sure the popper element
2196   * has its position set to `absolute` before Popper.js can do its work!
2197   *
2198   * Just disable this modifier and define your own to achieve the desired effect.
2199   *
2200   * @memberof modifiers
2201   * @inner
2202   */
2203  applyStyle: {
2204    /** @prop {number} order=900 - Index used to define the order of execution */
2205    order: 900,
2206    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
2207    enabled: true,
2208    /** @prop {ModifierFn} */
vendor: 8,554 bytes, lines 2209-2450
2209    fn: applyStyle,
2210    /** @prop {Function} */
2211    onLoad: applyStyleOnLoad,
2212    /**
2213     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
2214     * @prop {Boolean} gpuAcceleration=true
2215     * If true, it uses the CSS 3D transformation to position the popper.
2216     * Otherwise, it will use the `top` and `left` properties
2217     */
2218    gpuAcceleration: undefined
2219  }
2220};
2221
2222/**
2223 * The `dataObject` is an object containing all the information used by Popper.js.
2224 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
2225 * @name dataObject
2226 * @property {Object} data.instance The Popper.js instance
2227 * @property {String} data.placement Placement applied to popper
2228 * @property {String} data.originalPlacement Placement originally defined on init
2229 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
2230 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
2231 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
2232 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
2233 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
2234 * @property {Object} data.boundaries Offsets of the popper boundaries
2235 * @property {Object} data.offsets The measurements of popper, reference and arrow elements
2236 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
2237 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
2238 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
2239 */
2240
2241/**
2242 * Default options provided to Popper.js constructor.<br />
2243 * These can be overridden using the `options` argument of Popper.js.<br />
2244 * To override an option, simply pass an object with the same
2245 * structure of the `options` object, as the 3rd argument. For example:
2246 * ```
2247 * new Popper(ref, pop, {
2248 *   modifiers: {
2249 *     preventOverflow: { enabled: false }
2250 *   }
2251 * })
2252 * ```
2253 * @type {Object}
2254 * @static
2255 * @memberof Popper
2256 */
2257var Defaults = {
2258  /**
2259   * Popper's placement.
2260   * @prop {Popper.placements} placement='bottom'
2261   */
2262  placement: 'bottom',
2263
2264  /**
2265   * Set this to true if you want popper to position it self in 'fixed' mode
2266   * @prop {Boolean} positionFixed=false
2267   */
2268  positionFixed: false,
2269
2270  /**
2271   * Whether events (resize, scroll) are initially enabled.
2272   * @prop {Boolean} eventsEnabled=true
2273   */
2274  eventsEnabled: true,
2275
2276  /**
2277   * Set to true if you want to automatically remove the popper when
2278   * you call the `destroy` method.
2279   * @prop {Boolean} removeOnDestroy=false
2280   */
2281  removeOnDestroy: false,
2282
2283  /**
2284   * Callback called when the popper is created.<br />
2285   * By default, it is set to no-op.<br />
2286   * Access Popper.js instance with `data.instance`.
2287   * @prop {onCreate}
2288   */
2289  onCreate: () => {},
2290
2291  /**
2292   * Callback called when the popper is updated. This callback is not called
2293   * on the initialization/creation of the popper, but only on subsequent
2294   * updates.<br />
2295   * By default, it is set to no-op.<br />
2296   * Access Popper.js instance with `data.instance`.
2297   * @prop {onUpdate}
2298   */
2299  onUpdate: () => {},
2300
2301  /**
2302   * List of modifiers used to modify the offsets before they are applied to the popper.
2303   * They provide most of the functionalities of Popper.js.
2304   * @prop {modifiers}
2305   */
2306  modifiers
2307};
2308
2309/**
2310 * @callback onCreate
2311 * @param {dataObject} data
2312 */
2313
2314/**
2315 * @callback onUpdate
2316 * @param {dataObject} data
2317 */
2318
2319// Utils
2320// Methods
2321class Popper {
2322  /**
2323   * Creates a new Popper.js instance.
2324   * @class Popper
2325   * @param {Element|referenceObject} reference - The reference element used to position the popper
2326   * @param {Element} popper - The HTML / XML element used as the popper
2327   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
2328   * @return {Object} instance - The generated Popper.js instance
2329   */
2330  constructor(reference, popper, options = {}) {
2331    this.scheduleUpdate = () => requestAnimationFrame(this.update);
2332
2333    // make update() debounced, so that it only runs at most once-per-tick
2334    this.update = debounce(this.update.bind(this));
2335
2336    // with {} we create a new object with the options inside it
2337    this.options = _extends({}, Popper.Defaults, options);
2338
2339    // init state
2340    this.state = {
2341      isDestroyed: false,
2342      isCreated: false,
2343      scrollParents: []
2344    };
2345
2346    // get reference and popper elements (allow jQuery wrappers)
2347    this.reference = reference && reference.jquery ? reference[0] : reference;
2348    this.popper = popper && popper.jquery ? popper[0] : popper;
2349
2350    // Deep merge modifiers options
2351    this.options.modifiers = {};
2352    Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(name => {
2353      this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
2354    });
2355
2356    // Refactoring modifiers' list (Object => Array)
2357    this.modifiers = Object.keys(this.options.modifiers).map(name => _extends({
2358      name
2359    }, this.options.modifiers[name]))
2360    // sort the modifiers by order
2361    .sort((a, b) => a.order - b.order);
2362
2363    // modifiers have the ability to execute arbitrary code when Popper.js get inited
2364    // such code is executed in the same order of its modifier
2365    // they could add new properties to their options configuration
2366    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
2367    this.modifiers.forEach(modifierOptions => {
2368      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
2369        modifierOptions.onLoad(this.reference, this.popper, this.options, modifierOptions, this.state);
2370      }
2371    });
2372
2373    // fire the first update to position the popper in the right place
2374    this.update();
2375
2376    const eventsEnabled = this.options.eventsEnabled;
2377    if (eventsEnabled) {
2378      // setup event listeners, they will take care of update the position in specific situations
2379      this.enableEventListeners();
2380    }
2381
2382    this.state.eventsEnabled = eventsEnabled;
2383  }
2384
2385  // We can't use class properties because they don't get listed in the
2386  // class prototype and break stuff like Sinon stubs
2387  update() {
2388    return update.call(this);
2389  }
2390  destroy() {
2391    return destroy.call(this);
2392  }
2393  enableEventListeners() {
2394    return enableEventListeners.call(this);
2395  }
2396  disableEventListeners() {
2397    return disableEventListeners.call(this);
2398  }
2399
2400  /**
2401   * Schedules an update. It will run on the next UI update available.
2402   * @method scheduleUpdate
2403   * @memberof Popper
2404   */
2405
2406
2407  /**
2408   * Collection of utilities useful when writing custom modifiers.
2409   * Starting from version 1.7, this method is available only if you
2410   * include `popper-utils.js` before `popper.js`.
2411   *
2412   * **DEPRECATION**: This way to access PopperUtils is deprecated
2413   * and will be removed in v2! Use the PopperUtils module directly instead.
2414   * Due to the high instability of the methods contained in Utils, we can't
2415   * guarantee them to follow semver. Use them at your own risk!
2416   * @static
2417   * @private
2418   * @type {Object}
2419   * @deprecated since version 1.8
2420   * @member Utils
2421   * @memberof Popper
2422   */
2423}
2424
2425/**
2426 * The `referenceObject` is an object that provides an interface compatible with Popper.js
2427 * and lets you use it as replacement of a real DOM node.<br />
2428 * You can use this method to position a popper relatively to a set of coordinates
2429 * in case you don't have a DOM node to use as reference.
2430 *
2431 * ```
2432 * new Popper(referenceObject, popperNode);
2433 * ```
2434 *
2435 * NB: This feature isn't supported in Internet Explorer 10.
2436 * @name referenceObject
2437 * @property {Function} data.getBoundingClientRect
2438 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
2439 * @property {number} data.clientWidth
2440 * An ES6 getter that will return the width of the virtual reference element.
2441 * @property {number} data.clientHeight
2442 * An ES6 getter that will return the height of the virtual reference element.
2443 */
2444
2445Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
2446Popper.placements = placements;
2447Popper.Defaults = Defaults;
2448
2449export default Popper;
2450//# sourceMappingURL=popper.js.map

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.